home *** CD-ROM | disk | FTP | other *** search
/ PC Gamer 9 / 1995-08_Disc_9.iso / vesa / samples / vesapcx.pas < prev   
Pascal/Delphi Source File  |  1990-10-05  |  24KB  |  864 lines

  1. {-----------------------------------------------------------------------}
  2. {VESAPCX                        GL:01/15/90    }
  3. {-----------------------------------------------------------------------}
  4. {Program for decoding a 4-plane or 8-bit PCX file using the facilities    }
  5. {defined by the VESA Super VGA BIOS Extensions to provide for using    }
  6. {the extended resolutions of a Super VGA card in a hardware independent    }
  7. {manner.  Zsoft's PCX file format was chosen because of its relative    }
  8. {simplicity, so that this demonstration program would not become overly    }
  9. {cluttered with image decoding information.  PCX is the native file    }
  10. {format of Zsoft Paintbrush Plus and other paint programs.        }
  11. {-----------------------------------------------------------------------}
  12. {The following program is written to loosely conform to the VESA     }
  13. {Super VGA BIOS Extension document VS891001.  The program is intended    }
  14. {as a demonstration and is not intended to be an example of a         }
  15. {high-performance implementations of the VESA standard.            }
  16. {                        Gary Lorensen        }
  17. {                        Everex Systems, Inc.    }
  18. {                        48571 Milmont Dr. B3    }
  19. {                        Fremont, CA   94538    }
  20. {-----------------------------------------------------------------------}
  21.  
  22. uses
  23.     dos;
  24.  
  25. {-----------------------------------------------------------------------}
  26.  
  27. const
  28.     rSequAddr = $3C4;
  29.  
  30. {-----------------------------------------------------------------------}
  31.  
  32. type
  33.     ColorType = record
  34.         r,g,b : byte;
  35.     end;
  36.  
  37.     PCXHeaderType = record
  38.         manu : byte;    {10d=0Ah= ZSoft PCX}
  39.     vers : byte;    {0=v2.5,2=v2.8 w/pal,3=v2.8 wo/pal,5=v3.0}
  40.     code : byte;    {1=PCX run length}
  41.     bpp  : byte;    {bits/pixel/plane}
  42.     xmin : word;    {image dimensions}
  43.     ymin : word;
  44.     xmax : word;
  45.     ymax : word;
  46.     hres : word;    {Source device horz res}
  47.     vres : word;    {Source device vert res}
  48.     pal  : array [$00..$0F] of ColorType;
  49.     res0 : byte;    {reserved}
  50.     npln : byte;    {Number of color planes}
  51.     bpl  : word;    {Bytes/scan/plane (usually even)}
  52.     pinf : word;    {Palette info (1=color/BW, 2=gray, 9=????)}
  53.     dpi  : word;    {Scanner dpi or VRes}
  54.     res1 : array [$00..$37] of byte;    {reserved}
  55.     end;
  56.  
  57.     ByteBufferPtrType = ^ByteBufferType;
  58.     ByteBufferType = array [$00..$00] of byte;
  59.  
  60. {-----------------------------------------------------------------------}
  61.  
  62.     s80 = string[80];
  63.     s8  = string[8];
  64.  
  65.     DacType = array [$00..$FF] of ColorType;
  66.  
  67. {-----------------------------------------------------------------------}
  68.  
  69.     CharString = array [$00..$03] of char;
  70.  
  71.     ModeListType = array [$00..$00] of word;
  72.  
  73.     PageFuncPtrType = pointer;
  74.  
  75.     VgaInfoBlockType = record
  76.         VESASignature    : CharString;
  77.     VESAVersion     : word;
  78.     OEMStringPtr    : ^CharString;
  79.     Capabilities    : array [$00..$03] of byte;
  80.     VideoModePtr    : ^ModeListType;
  81.     reserved    : array [$00..$ED] of byte;    {Pad to 256}
  82.     end;
  83.  
  84.     ModeInfoBlockType = record
  85.                      {mandatory information}
  86.     ModeAttributes    : word;
  87.     WinAAttributes    : byte;
  88.     WinBAttributes    : byte;
  89.     WinGranularity    : word;
  90.     WinSize        : word;
  91.     WinASegment    : word;
  92.     WinBSegment    : word;
  93.     WinFuncPtr    : PageFuncPtrType;
  94.     BytesPerScanLine : word;
  95.  
  96.                     {optional information}
  97.     XResolution    : word;
  98.     YResolution    : word;
  99.     XCharSize    : byte;
  100.     YCharSize    : byte;
  101.     NumberOfPlanes    : byte;
  102.     BitsPerPixel    : byte;
  103.     NumberOfBanks    : byte;
  104.     MemoryModel    : byte;
  105.     BankSize    : byte;
  106.     reserved    : array [$00..$E2] of byte;    {Pad to 256}
  107.     end;
  108.  
  109. {-----------------------------------------------------------------------}
  110. {-----------------------------------------------------------------------}
  111.  
  112. var
  113.     reg : Registers;
  114.     VesaVgaInfo : VgaInfoBlockType;
  115.     VesaModeInfo : ModeInfoBlockType;
  116.     prevVesaMode : word;
  117.     VesaMode : word;
  118.     PcxHeader    : PCXHeaderType;
  119.     pcxfile : file;
  120.     pcxfname : s80;
  121.     i,j : word;
  122.     ch : char;
  123.  
  124. {-----------------------------------------------------------------------}
  125. {-----------------------------------------------------------------------}
  126.  
  127. function decval(ch : char) : byte;
  128.  
  129. begin
  130.     decval := 0;
  131.     if ((ch>='0') and (ch<='9')) then
  132.         decval := ord(ch)-ord('0');
  133.     if ((ch>='A') and (ch<='F')) then
  134.         decval := ord(ch)-ord('A')+$0A;
  135.     if ((ch>='a') and (ch<='f')) then
  136.         decval := ord(ch)-ord('a')+$0A;
  137. end;
  138.  
  139. function hex2dec(s : s80) : word;
  140.  
  141. var
  142.     i     : byte;
  143.     tmp   : word;
  144.     place : word;
  145.  
  146. begin
  147.     i := ord(s[0]);
  148.     place := 1;
  149.     tmp := 0;
  150.     while (i>0) do begin
  151.         tmp := tmp+place*decval(s[i]);
  152.     i:=i-1;
  153.     place := place*$10;
  154.     end;
  155.     hex2dec := tmp;
  156. {    writeln('hex2dec(',s,') = ',tmp);}
  157. end;
  158.  
  159. {-----------------------------------------------------------------------}
  160.  
  161. function hexval(x : byte) : char;
  162.  
  163. begin
  164.     hexval := '0';
  165.     if ((x>=0) and (x<=9)) then
  166.         hexval := chr(x+ord('0'));
  167.     if ((x>=10) and (x<=15)) then
  168.         hexval := chr(x-10+ord('A'));
  169. end;
  170.  
  171. function dec2hex(x : word) : s8;
  172.  
  173. var
  174.     tmp   : s8;
  175.     place : word;
  176.  
  177. begin
  178. {    tmp   := '0';}
  179.     tmp := ' ';
  180.     if (x>=$100) then
  181.         place := $1000
  182.     else
  183.         place := $10;
  184.  
  185.     repeat
  186.         tmp := tmp+hexval(x div place);
  187.     x := x mod place;
  188.     place := place div $10;
  189.     until (place=$0000);
  190.  
  191.     dec2hex := tmp+'h';
  192. end;
  193.  
  194.  
  195. function hex(x : word) : s8;
  196.  
  197. var
  198.     tmp   : s8;
  199.     place : word;
  200.  
  201. begin
  202.     tmp := '0';
  203.     if (x>=$100) then
  204.         place := $1000
  205.     else
  206.         place := $10;
  207.  
  208.     repeat
  209.         tmp := tmp+hexval(x div place);
  210.     x := x mod place;
  211.     place := place div $10;
  212.     until (place=$0000);
  213.  
  214.     hex := tmp+'h';
  215. end;
  216.  
  217. function addrhex(x : word) : s8;
  218.  
  219. var
  220.     tmp   : s8;
  221.     place : word;
  222.  
  223. begin
  224.     tmp := '';
  225.     place := $1000;
  226.  
  227.     repeat
  228.         tmp := tmp+hexval(x div place);
  229.     x := x mod place;
  230.     place := place div $10;
  231.     until (place=$0000);
  232.  
  233.     addrhex := tmp;
  234. end;
  235.  
  236. {-----------------------------------------------------------------------}
  237.  
  238. function Min(m,n : longint) : longint;
  239.  
  240. begin
  241.     if (m<n) then
  242.         Min := m
  243.     else
  244.         Min := n;
  245. end;
  246.  
  247. function Max(m,n : longint) : longint;
  248.  
  249. begin
  250.     if (m>n) then
  251.         Max := m
  252.     else
  253.         Max := n;
  254. end;
  255.  
  256. {-----------------------------------------------------------------------}
  257.  
  258. procedure SetVesaBank(win  : byte;
  259.                       bank : byte);
  260.  
  261. var
  262.     reg : Registers;
  263.  
  264. begin
  265.     reg.AX := $4F05;
  266.     reg.BH := $00;
  267.     reg.BL := win;
  268.     reg.DX := bank;
  269.     intr($10,reg);
  270. end;
  271.  
  272. {-----------------------------------------------------------------------}
  273.  
  274. procedure GetVesaBank(win  : byte;
  275.                       var bank : byte);
  276.  
  277. var
  278.     reg : Registers;
  279.  
  280. begin
  281.     reg.AX := $4F05;
  282.     reg.BH := $01;
  283.     reg.BL := win;
  284.     intr($10,reg);
  285.     bank := reg.DX;
  286. end;
  287.  
  288. {-----------------------------------------------------------------------}
  289.  
  290. procedure FindVesaMode(xsize,ysize : word;
  291.                       memmodel : byte;
  292.               bitpixel : byte;
  293.               var bestVesaMode : word;
  294.               var bestVesaModeInfo : ModeInfoBlockType);
  295. var
  296.     tmpVesaModeInfo : ModeInfoBlockType;
  297.     i : byte;
  298.     error : boolean;
  299.  
  300. begin
  301.     i := $00;
  302.     bestVesaMode := $FFFF;
  303.     error := false;
  304.     while ((VesaVgaInfo.VideoModePtr^[i]<>$FFFF) and not(error)) do begin
  305.  
  306.         reg.AX := $4F01;
  307.     reg.CX := VesaVgaInfo.VideoModePtr^[i];
  308.         reg.ES := Seg(tmpVesaModeInfo);
  309.         reg.DI := Ofs(tmpVesaModeInfo);
  310.         intr($10,reg);
  311.  
  312.     error := (reg.AX<>$004F);
  313.  
  314.     if (tmpVesaModeInfo.ModeAttributes and $02=$00) then begin
  315.         case VesaVgaInfo.VideoModePtr^[i] of
  316.             $0100,$0101,$0103,$0105,$0107 : begin
  317.             tmpVesaModeInfo.XCharSize   := 0;
  318.             tmpVesaModeInfo.YCharSize   := 0;
  319.             tmpVesaModeInfo.NumberOfPlanes:= 1;
  320.             tmpVesaModeInfo.BitsPerPixel:= 8;
  321.             tmpVesaModeInfo.NumberOfBanks:= 1;
  322.             tmpVesaModeInfo.MemoryModel := $04;
  323.             tmpVesaModeInfo.BankSize    := 0;
  324.         end;
  325.             $0102,$0104,$0106 : begin
  326.             tmpVesaModeInfo.XCharSize   := 0;
  327.             tmpVesaModeInfo.YCharSize   := 0;
  328.             tmpVesaModeInfo.NumberOfPlanes:= 4;
  329.             tmpVesaModeInfo.BitsPerPixel:= 4;
  330.             tmpVesaModeInfo.NumberOfBanks:= 1;
  331.             tmpVesaModeInfo.MemoryModel := $03;
  332.             tmpVesaModeInfo.BankSize    := 0;
  333.         end;
  334.         else
  335.         tmpVesaModeInfo.XCharSize   := 0;
  336.         tmpVesaModeInfo.YCharSize   := 0;
  337.         tmpVesaModeInfo.NumberOfPlanes:= 0;
  338.         tmpVesaModeInfo.BitsPerPixel:= 0;
  339.         tmpVesaModeInfo.NumberOfBanks:= 0;
  340.         tmpVesaModeInfo.MemoryModel := $FF;
  341.         tmpVesaModeInfo.BankSize    := 0;
  342.         end;
  343.  
  344.         case VesaVgaInfo.VideoModePtr^[i] of
  345.         $0100 : begin
  346.             tmpVesaModeInfo.XResolution := 640;
  347.             tmpVesaModeInfo.YResolution := 400;
  348.         end;
  349.         $0101 : begin
  350.             tmpVesaModeInfo.XResolution := 640;
  351.             tmpVesaModeInfo.YResolution := 480;
  352.         end;
  353.         $0102,$0103 : begin
  354.             tmpVesaModeInfo.XResolution := 800;
  355.             tmpVesaModeInfo.YResolution := 600;
  356.         end;
  357.         $0104,$0105 : begin
  358.             tmpVesaModeInfo.XResolution := 1024;
  359.             tmpVesaModeInfo.YResolution := 768;
  360.         end;
  361.         $0106,$0107 : begin
  362.             tmpVesaModeInfo.XResolution := 1280;
  363.             tmpVesaModeInfo.YResolution := 1024;
  364.         end;
  365.         else
  366.         tmpVesaModeInfo.XResolution := 0;
  367.         tmpVesaModeInfo.YResolution := 0;
  368.         end;
  369.     end;
  370.  
  371.     if ((tmpVesaModeInfo.XResolution>=xsize)
  372.         and (tmpVesaModeInfo.YResolution>=ysize)
  373.         and (tmpVesaModeInfo.MemoryModel=memmodel)
  374.         and (tmpVesaModeInfo.BitsPerPixel=bitpixel)
  375.         and (tmpVesaModeInfo.ModeAttributes and $01=$01)
  376.         ) then begin
  377.  
  378.         if (bestVesaMode=$FFFF) then begin
  379.             bestVesaMode := VesaVgaInfo.VideoModePtr^[i];
  380.             bestVesaModeInfo := tmpVesaModeInfo;
  381.         end else if ((tmpVesaModeInfo.XResolution>=xsize) 
  382.         and (tmpVesaModeInfo.XResolution<=bestVesaModeInfo.XResolution))
  383.         and ((tmpVesaModeInfo.YResolution>=ysize) 
  384.         and (tmpVesaModeInfo.YResolution<=bestVesaModeInfo.YResolution))
  385.         then begin
  386.  
  387.         bestVesaModeInfo := tmpVesaModeInfo;
  388.         bestVesaMode := VesaVgaInfo.VideoModePtr^[i];
  389.  
  390.         end;
  391.     end;
  392.  
  393.     i:=i+1;
  394.     end;
  395. end;
  396.  
  397. {-----------------------------------------------------------------------}
  398.  
  399. procedure SetVesaMode(VesaMode : word);
  400.  
  401. var
  402.     reg : Registers;
  403.  
  404. begin
  405.     reg.AX := $4F02;
  406.     reg.BX := VesaMode;
  407.     intr($10,reg);
  408. end;
  409.  
  410. {-----------------------------------------------------------------------}
  411.  
  412. procedure GetVesaMode(var VesaMode : word);
  413.  
  414. var
  415.     reg : Registers;
  416.  
  417. begin
  418.     reg.AX := $4F03;
  419.     intr($10,reg);
  420.     VesaMode := reg.BX;
  421. end;
  422.  
  423. {-----------------------------------------------------------------------}
  424.  
  425. procedure DecodeVesaPcx4(var pcxfile : file;
  426.                          pcxheader : PCXHeaderType;
  427.              VesaModeInfo : ModeInfoBlockType);
  428. var
  429.     pcxbuffptr : ByteBufferPtrType;
  430.     decodebuffptr : ByteBufferPtrType;
  431.     pcxfileind : longint;
  432.     pcxind : word;
  433.     decodeind : word;
  434.     scan : word;
  435.     i,tmp : byte;
  436.     mapmask : byte;
  437.     scrnptr : ByteBufferPtrType;
  438.     writebank : byte;
  439.     readbank : byte;
  440.     scrnofs : word;
  441.     vesabank : word;
  442.     scanrun : word;
  443.     dac : DacType;
  444.     pal : array [$00..$10] of byte;
  445.  
  446. begin
  447.     GetMem(pcxbuffptr,pcxheader.bpl*2*4);
  448.     GetMem(decodebuffptr,pcxheader.bpl*4);
  449.  
  450.     for i := $00 to $0F do
  451.         pal[i] := i;
  452.     pal[$10] := $00;
  453.  
  454.     reg.AX := $1002;
  455.     reg.ES := Seg(pal);
  456.     reg.DX := Ofs(pal);
  457.     intr($10,reg);
  458.  
  459.     Seek(pcxfile,FileSize(pcxfile)-(3*256)-1);
  460.     i := 0;
  461.     BlockRead(pcxfile,i,1);
  462.     if (i=$0C) then begin
  463.         BlockRead(pcxfile,dac,3*256);
  464.     for i := $00 to $FF do begin
  465.         dac[i].r := (dac[i].r {+ $03}) shr 2;
  466.         dac[i].g := (dac[i].g {+ $03}) shr 2;
  467.         dac[i].b := (dac[i].b {+ $03}) shr 2;
  468.     end;
  469.     reg.CX := $0100;
  470.     end else begin
  471.         for i := $00 to $0F do begin
  472.         dac[i].r := (pcxheader.pal[i].r{+3}) shr 2;
  473.         dac[i].g := (pcxheader.pal[i].g{+3}) shr 2;
  474.         dac[i].b := (pcxheader.pal[i].b{+3}) shr 2;
  475.         end;
  476.     reg.CX := $0010;
  477.     end;
  478.     reg.AX := $1012;
  479.     reg.BX := $0000;
  480.     reg.ES := Seg(dac);
  481.     reg.DX := Ofs(dac);
  482.     intr($10,reg);
  483.  
  484.     if (VesaModeInfo.WinAAttributes and $05 = $05) then begin
  485.         writebank := $00;
  486.         scrnptr := Ptr(VesaModeInfo.WinASegment,$0000);
  487.     end else if (VesaModeInfo.WinBAttributes and $05 = $05) then begin
  488.         writebank := $01;
  489.         scrnptr := Ptr(VesaModeInfo.WinBSegment,$0000);
  490.     end else begin
  491.         writebank := $00;
  492.         scrnptr := Ptr($A000,$0000);
  493.     end;
  494.  
  495.     if (VesaModeInfo.WinAAttributes and $03 = $03) then begin
  496.         readbank := $00;
  497.     end else if (VesaModeInfo.WinBAttributes and $03 = $03) then begin
  498.         readbank := $01;
  499.     end else begin
  500.         readbank := $00;
  501.     end;
  502.  
  503.     Seek(pcxfile,SizeOf(pcxheader));
  504.     pcxfileind := FilePos(pcxfile);
  505.  
  506.     for scan := $0000 to (pcxheader.ymax-pcxheader.ymin) do begin
  507.  
  508.         pcxind := 0;
  509.         decodeind := 0;
  510.  
  511.     BlockRead(pcxfile,pcxbuffptr^,Min(pcxheader.bpl*2*4,
  512.         FileSize(pcxfile)-pcxfileind));
  513.  
  514.     while (decodeind<pcxheader.bpl*4) do begin
  515.         if (pcxbuffptr^[pcxind] and $C0 = $C0) then begin
  516.             for i := $00 to (pcxbuffptr^[pcxind] and $3F)-1 do
  517.             decodebuffptr^[decodeind+i] :=  pcxbuffptr^[pcxind+1];
  518.         decodeind := decodeind + (pcxbuffptr^[pcxind] and $3F);
  519.         pcxind := pcxind+2;
  520.         end else begin
  521.         decodebuffptr^[decodeind] :=  pcxbuffptr^[pcxind];
  522.         decodeind := decodeind+1;
  523.         pcxind := pcxind+1;
  524.         end;
  525.     end;
  526.  
  527.         pcxfileind := pcxfileind+pcxind;
  528.     Seek(pcxfile,pcxfileind);
  529.  
  530.     for mapmask := $00 to $03 do begin
  531.  
  532.         Port[rSequAddr  ] := $02;
  533.         Port[rSequAddr+1] := ($01 shl mapmask);
  534.  
  535.         vesabank := longint(longint(scan)*longint(VesaModeInfo.BytesPerScanLine))
  536.             div longint(longint(VesaModeInfo.WinSize)*longint(1024));
  537.         SetVesaBank(writebank,vesabank);
  538.         SetVesaBank(readbank,vesabank);
  539.         scrnofs := longint(longint(scan)*longint(VesaModeInfo.BytesPerScanLine))
  540.             mod longint(longint(VesaModeInfo.WinSize)*longint(1024));
  541.  
  542.         scanrun := Min((pcxheader.xmax-pcxheader.xmin+1) div 8,VesaModeInfo.XResolution div 8);
  543.  
  544.         if (longint(longint(scrnofs)+longint(scanrun))
  545.             >longint(longint(VesaModeInfo.WinSize)*longint(1024))) then begin
  546.  
  547.             for i := $00 to (longint(longint(VesaModeInfo.WinSize)*longint(1024))-longint(scrnofs))-1 do begin
  548.             tmp := scrnptr^[scrnofs + i];
  549.                 scrnptr^[scrnofs + i] := decodebuffptr^[mapmask*pcxheader.bpl+i];
  550.         end;
  551.             j := i+1;
  552.             vesabank := vesabank+1;
  553.             SetVesaBank(writebank,vesabank);
  554.             SetVesaBank(readbank,vesabank);
  555.             scanrun := (longint(longint(scrnofs)+longint(scanrun)-1)-longint(longint(VesaModeInfo.WinSize)*longint(1024)));
  556.             scrnofs := $0000;
  557.             for i := $00 to scanrun do begin
  558.             tmp := scrnptr^[scrnofs + i];
  559.                 scrnptr^[scrnofs + i] := decodebuffptr^[mapmask*pcxheader.bpl+j+i];
  560.         end;
  561.         end else begin
  562.             for i := $00 to scanrun-1 do begin
  563.             tmp := scrnptr^[scrnofs + i];
  564.                 scrnptr^[scrnofs + i] := decodebuffptr^[mapmask*pcxheader.bpl+i];
  565.         end;
  566.         end;
  567.  
  568.     end;
  569.  
  570.     end;
  571.     
  572. end;
  573.  
  574. {-----------------------------------------------------------------------}
  575.  
  576. procedure DecodeVesaPcx8(var pcxfile : file;
  577.                          pcxheader : PCXHeaderType;
  578.              VesaModeInfo : ModeInfoBlockType);
  579. var
  580.     pcxbuffptr : ByteBufferPtrType;
  581.     decodebuffptr : ByteBufferPtrType;
  582.     pcxfileind : longint;
  583.     pcxind : word;
  584.     decodeind : word;
  585.     scan : word;
  586.     scanrun : word;
  587.     i,j : word;
  588.     vesabank : word;
  589.     scrnptr : ByteBufferPtrType;
  590.     writebank : byte;
  591.     readbank : byte;
  592.     scrnofs : word;
  593.     dac : DacType;
  594.     reg : Registers;
  595.  
  596. begin
  597.     GetMem(pcxbuffptr,pcxheader.bpl*2);
  598.     GetMem(decodebuffptr,pcxheader.bpl);
  599.  
  600.     Seek(pcxfile,FileSize(pcxfile)-(3*256)-1);
  601.     i := 0;
  602.     BlockRead(pcxfile,i,1);
  603.     if (i=$0C) then begin
  604.         BlockRead(pcxfile,dac,3*256);
  605.     for i := $00 to $FF do begin
  606.         dac[i].r := (dac[i].r {+ $03}) shr 2;
  607.         dac[i].g := (dac[i].g {+ $03}) shr 2;
  608.         dac[i].b := (dac[i].b {+ $03}) shr 2;
  609.     end;
  610.     reg.CX := $0100;
  611.     end else begin
  612.         for i := $00 to $0F do begin
  613.         dac[i].r := (pcxheader.pal[i].r{+3}) shr 2;
  614.         dac[i].g := (pcxheader.pal[i].g{+3}) shr 2;
  615.         dac[i].b := (pcxheader.pal[i].b{+3}) shr 2;
  616.         end;
  617.     reg.CX := $0010;
  618.     end;
  619.     reg.AX := $1012;
  620.     reg.BX := $0000;
  621.     reg.ES := Seg(dac);
  622.     reg.DX := Ofs(dac);
  623.     intr($10,reg);
  624.  
  625.     if (VesaModeInfo.WinAAttributes and $05 = $05) then begin
  626.         writebank := $00;
  627.         scrnptr := Ptr(VesaModeInfo.WinASegment,$0000);
  628.     end else if (VesaModeInfo.WinBAttributes and $05 = $05) then begin
  629.         writebank := $01;
  630.         scrnptr := Ptr(VesaModeInfo.WinBSegment,$0000);
  631.     end else begin
  632.         writebank := $00;
  633.         scrnptr := Ptr($A000,$0000);
  634.     end;
  635.  
  636.     if (VesaModeInfo.WinAAttributes and $03 = $03) then begin
  637.         readbank := $00;
  638.     end else if (VesaModeInfo.WinBAttributes and $03 = $03) then begin
  639.         readbank := $01;
  640.     end else begin
  641.         readbank := $00;
  642.     end;
  643.  
  644.     Seek(pcxfile,SizeOf(pcxheader));
  645.     pcxfileind := FilePos(pcxfile);
  646.  
  647.     for scan := $0000 to (pcxheader.ymax-pcxheader.ymin) do begin
  648.  
  649.         pcxind := 0;
  650.         decodeind := 0;
  651.  
  652.     BlockRead(pcxfile,pcxbuffptr^,Min(pcxheader.bpl*2,FileSize(pcxfile)-pcxfileind));
  653.  
  654.     while (decodeind<pcxheader.bpl) do begin
  655.         if (pcxbuffptr^[pcxind] and $C0 = $C0) then begin
  656.             for i := $00 to (pcxbuffptr^[pcxind] and $3F)-1 do
  657.             decodebuffptr^[decodeind+i] :=  pcxbuffptr^[pcxind+1];
  658.         decodeind := decodeind + (pcxbuffptr^[pcxind] and $3F);
  659.         pcxind := pcxind+2;
  660.         end else begin
  661.         decodebuffptr^[decodeind] :=  pcxbuffptr^[pcxind];
  662.         decodeind := decodeind+1;
  663.         pcxind := pcxind+1;
  664.         end;
  665.     end;
  666.  
  667.         pcxfileind := pcxfileind+pcxind;
  668.     Seek(pcxfile,pcxfileind);
  669.  
  670.     if (VesaModeInfo.MemoryModel=$04) then begin
  671.  
  672.         vesabank := longint(longint(scan)*longint(VesaModeInfo.BytesPerScanLine))
  673.             div longint(longint(VesaModeInfo.WinSize)*longint(1024));
  674.         SetVesaBank(writebank,vesabank);
  675.         SetVesaBank(readbank,vesabank);
  676.         scrnofs := longint(longint(scan)*longint(VesaModeInfo.BytesPerScanLine))
  677.             mod longint(longint(VesaModeInfo.WinSize)*longint(1024));
  678.  
  679.         scanrun := Min(pcxheader.xmax-pcxheader.xmin,VesaModeInfo.XResolution);
  680.  
  681.         if (longint(longint(scrnofs)+longint(scanrun))
  682.             >longint(longint(VesaModeInfo.WinSize)*longint(1024))) then begin
  683.             for i := $00 to (longint(longint(VesaModeInfo.WinSize)*longint(1024))-longint(scrnofs))-1 do
  684.                 scrnptr^[scrnofs + i] := decodebuffptr^[i];
  685.             j := i+1;
  686.             vesabank := vesabank+1;
  687.             SetVesaBank(writebank,vesabank);
  688.             SetVesaBank(readbank,vesabank);
  689.             scanrun := (longint(longint(scrnofs)+longint(scanrun)-1)
  690.             -longint(longint(VesaModeInfo.WinSize)*longint(1024)));
  691.             scrnofs := $0000;
  692.             for i := $00 to scanrun do
  693.                 scrnptr^[scrnofs + i] := decodebuffptr^[j+i];
  694.         end else begin
  695.             for i := $00 to scanrun-1 do
  696.                 scrnptr^[scrnofs + i] := decodebuffptr^[i];
  697.         end;
  698.  
  699.         end else begin            {Sequential 256-color mode}
  700.  
  701.         scrnofs := longint(longint(scan)*longint(VesaModeInfo.BytesPerScanLine));
  702.         scanrun := Min(pcxheader.xmax-pcxheader.xmin,VesaModeInfo.XResolution);
  703.  
  704.         for i := $00 to scanrun-1 do begin
  705.             Port[rSequAddr  ] := $02;
  706.         Port[rSequAddr+1] := ($01 shl (i mod 4));
  707.  
  708.         j := scrnptr^[scrnofs + (i div 4)];
  709.             scrnptr^[scrnofs + (i div 4)] := decodebuffptr^[i];
  710.         end;
  711.  
  712.     end;
  713.  
  714.     end;
  715.     
  716. end;
  717.  
  718. {-----------------------------------------------------------------------}
  719. {-----------------------------------------------------------------------}
  720.  
  721. begin
  722.     writeln;
  723.     writeln('VESA PCX file decoder');
  724.     writeln('A demonstration of hardware independent VESA programming.');
  725.     writeln('1990 Everex Systems, Inc.');
  726.     writeln;
  727.  
  728.     reg.AX := $4F00;
  729.     reg.ES := Seg(VesaVgaInfo);
  730.     reg.DI := Ofs(VesaVgaInfo);
  731.     intr($10,reg);
  732.  
  733.     if (reg.AL<>$4F) then begin
  734.         writeln('ERROR: VESA Function 00h: Return Super VGA Information not supported.');
  735.     halt(1);
  736.     end;
  737.  
  738.     if (reg.AH<>$00) then begin
  739.         writeln('ERROR: VESA Function 00h: Return Super VGA Information failed.');
  740.     halt(2);
  741.     end;
  742.  
  743.     if (ParamCount=0) then begin
  744.         write('Input name of PCX file to display >> ');
  745.     readln(pcxfname);
  746.     end else
  747.         pcxfname := ParamStr(1);
  748.  
  749.     writeln('---------------------------------------');
  750.     writeln;
  751.  
  752.     writeln('VESA VGA Information:');
  753.  
  754.     write('    VESA Signature: ');
  755.     for i := $00 to $03 do
  756.         write(VesaVgaInfo.VesaSignature[i]);
  757.     writeln;
  758.  
  759.     write('    VESA Version  : v');
  760.     write(VesaVgaInfo.VesaVersion div $100);
  761.     write('.');
  762.     write(VesaVgaInfo.VesaVersion mod $100);
  763.     writeln;
  764.  
  765.     write('    OEM String    : ');
  766.     i := $00;
  767.     while (VesaVgaInfo.OEMStringPtr^[i]<>#00) do begin
  768.         write(VesaVgaInfo.OEMStringPtr^[i]);
  769.     i:=i+1;
  770.     end;
  771.     writeln;
  772.  
  773.     write('    Capabilities  : ');
  774.     for j := $00 to $03 do
  775.         for i := $00 to $07 do
  776.         if ((VesaVgaInfo.Capabilities[j] and ($80 shr i))=$00) then
  777.             write('0')
  778.         else
  779.             write('1');
  780.     writeln;
  781.  
  782.     write  ('    Modes         : ');
  783.     i := $00;
  784.     while (VesaVgaInfo.VideoModePtr^[i]<>$FFFF) do begin
  785.         if ((i mod 8)=0) then begin
  786.         writeln;
  787.         write('        ');
  788.     end;
  789.         write(addrhex(VesaVgaInfo.VideoModePtr^[i]),'h ');
  790.     i:=i+1;
  791.     end;
  792.     writeln;
  793.  
  794.     assign(pcxfile,pcxfname);
  795.     reset(pcxfile,1);
  796.  
  797.     if (FileSize(pcxfile)<SizeOf(PcxHeader)) then begin
  798.         writeln('ERROR: Invalid PCX image file specified.');
  799.     halt(1);
  800.     end;
  801.  
  802.     BlockRead(pcxfile,PcxHeader,sizeof(PcxHeader));
  803.  
  804.     if (PcxHeader.manu<>$0A) then begin    {Check if PCX file}
  805.     writeln('ERROR: Invalid PCX file format.');
  806.     halt(2);
  807.     end;
  808.  
  809.     if ((PcxHeader.vers<>5)        {Check for right version}
  810.     or (PcxHeader.code<>1))        {Check for encoding technique}
  811.     then begin
  812.     writeln('ERROR: Unsupported PCX file format.');
  813.     halt(2);
  814.     end;
  815.  
  816.     writeln;
  817.     with PcxHeader do begin
  818.         writeln('PCX image size: ',(xmax-xmin+1),'x',(ymax-ymin+1),'x',bpp*npln);
  819.  
  820.         if ((PcxHeader.bpp=1) and (PcxHeader.npln=4)) then begin
  821.             FindVesaMode((xmax-xmin+1),(ymax-ymin+1),$03,4,VesaMode,VesaModeInfo);
  822.         if (VesaMode=$FFFF) then begin
  823.             writeln('ERROR: Can not find an adequate VESA 4-bit mode.');
  824.             halt(2);
  825.         end else begin
  826.             write('VESA mode res : ',VesaModeInfo.XResolution,'x');
  827.         writeln(VesaModeInfo.YResolution,'x',VesaModeInfo.BitsPerPixel);
  828.         readln;
  829.             GetVesaMode(prevVesaMode);
  830.             SetVesaMode(VesaMode);
  831.         DecodeVesaPcx4(pcxfile,pcxheader,VesaModeInfo);
  832.         readln;
  833.             SetVesaMode(prevVesaMode);
  834.         end;
  835.         end else if ((PcxHeader.bpp=8) and (PcxHeader.npln=1)) then begin
  836.             FindVesaMode((xmax-xmin+1),(ymax-ymin+1),$04,8,VesaMode,VesaModeInfo);
  837.         if (VesaMode=$FFFF) then
  838.                 FindVesaMode((xmax-xmin+1),(ymax-ymin+1),$05,8,VesaMode,VesaModeInfo);
  839.         if (VesaMode=$FFFF) then begin
  840.             writeln('ERROR: Can not find an adequate VESA 8-bit mode.');
  841.             halt(2);
  842.         end else begin
  843.             write('VESA mode res : ',VesaModeInfo.XResolution,'x');
  844.         writeln(VesaModeInfo.YResolution,'x',VesaModeInfo.BitsPerPixel);
  845.         readln;
  846.             GetVesaMode(prevVesaMode);
  847.             SetVesaMode(VesaMode);
  848.         DecodeVesaPcx8(pcxfile,pcxheader,VesaModeInfo);
  849.         readln;
  850.             SetVesaMode(prevVesaMode);
  851.         end;
  852.         end else begin
  853.             writeln('ERROR: VESA PCX file decoder only supports VGA 4 and 8 bit formats.');
  854.         halt(1);
  855.         end;
  856.     end;
  857.  
  858.  
  859. end.
  860.  
  861. {-----------------------------------------------------------------------}
  862. {-----------------------------------------------------------------------}
  863.  
  864.