home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / pascal / rehack / demosrc / pcxtool.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1991-04-12  |  16.0 KB  |  462 lines

  1. {**************************************************************************
  2.  **************************************************************************
  3.                             PCXTOOL UNIT
  4.  **************************************************************************
  5.   By: Mark Betz, 76605, 2346
  6.  Developed on: 1-4-91
  7.  Last update:  4-8-91
  8.  **************************************************************************
  9.  **************************************************************************}
  10.  
  11. Unit PCXTOOL;
  12.  
  13. interface
  14.  
  15. Uses
  16.     DOS, CRT;
  17. const
  18.     size_of_pcx : word = 64500;          {size of the unpacked PCX}
  19.  
  20. type
  21.     palette_rec   = record               {palette entry storage structure}
  22.                          red : byte;
  23.                          green : byte;
  24.                          blue : byte;
  25.                     end;
  26.  
  27.     Header_struc = record                              {PCX header structure}
  28.                      mfg : byte;                       {manufacturer}
  29.                      ver : byte;                       {version}
  30.                      enc : byte;                       {encoding}
  31.                      bpp : byte;                       {bits per pixel}
  32.                      xmin, ymin : integer;             {picture origin}
  33.                      xmax, ymax : integer;             {picture dimensions}
  34.                      hres : integer;                   {horizontal resolution}
  35.                      vres : integer;                   {vertical resolution}
  36.                      palette : array[0..47] of byte;   {palette area for 16 clr}
  37.                      res : byte;                       {reserved}
  38.                      clr_plns : byte;                  {color planes}
  39.                      bpl : integer;                    {bytes per line}
  40.                      pal_type : integer;               {palette type}
  41.                      filler : array[0..57] of byte;    {filler}
  42.                    end;
  43.  
  44. var
  45.     current_pal : array[0..255] of palette_rec;
  46.     saved_pal   : array[0..255] of palette_rec;
  47.     test_pal    : array[0..255] of palette_rec;
  48.     Cpal_ptr    : pointer;
  49.     Spal_ptr    : pointer;
  50.     PCXHead     : Header_struc;               {PCX header structure}
  51.     PicFile     : file;                       {current picture file}
  52.     read_ahed   : array[0..9999] of byte;
  53.     ra_buf_pos  : integer;
  54.  
  55. {----------------------------------Interface Procedure definitions------------}
  56.  
  57. Procedure InitGraphics;                       {set up mode 19}
  58. Procedure Restoretext;                        {restore to text mode}
  59. Function  LoadPcx(pcxfile : pathstr):pointer; {load a PCX file into buffer}
  60. Procedure FadeInPcx(buf_ptr : pointer);       {fade in a pcx file}
  61. Procedure FadeOutPcx;                         {remove from screen}
  62. Procedure FreePcxMem(buf_ptr : pointer);      {deallocate memory}
  63.  
  64. implementation
  65. var
  66.     file_size : longint;       {holds the size of the pcx}
  67.  
  68. {*****************************************************************************
  69.     Procedure InitGraphics-
  70.     task: set graphics card to VGA mode 19, 320 x 200 x 256
  71.  *****************************************************************************}
  72.  
  73. Procedure InitGraphics;
  74. var
  75.     regs : registers;
  76. begin
  77.     regs.ax := $0013;          {load ah = 00, al = video mode $13}
  78.     Intr($10,regs);            {call BIOS to set video mode}
  79. end;
  80.  
  81. {*****************************************************************************
  82.     Procedure RestoreText-
  83.     task: restore graphics card to mode 3, 80 x 25 16 color text
  84.  *****************************************************************************}
  85.  
  86. Procedure RestoreText;
  87. var
  88.     regs : registers;
  89. begin
  90.     regs.ax := $0003;          {load ah = 00, al = video mode $3}
  91.     Intr($10,regs);
  92. end;
  93.  
  94. {*****************************************************************************
  95.     Function Check_exist-
  96.     task: called with a path and filename it will return true and set the
  97.           value of file_size if the requested filename exists. Returns false
  98.           if file not found
  99.  *****************************************************************************}
  100.  
  101. Function Check_exist(check_file : pathstr) : boolean;
  102. var
  103.     file_attrib : word;
  104.     file_rec    : searchrec;
  105. begin
  106.     file_attrib := $3F;
  107.     findfirst(check_file,file_attrib,file_rec);
  108.     case doserror of
  109.         0  : begin
  110.                  Check_exist := true;
  111.                  file_size := file_rec.size;
  112.              end;
  113.         else
  114.              Check_exist := false;
  115.     end;
  116. end;
  117.  
  118. {*****************************************************************************
  119.     Procedure ShiftPalette;
  120.     task: shifts the contents of the passed palette structure right by 2 bits
  121.  *****************************************************************************}
  122.  
  123. Procedure ShiftPalette(SPal : pointer);
  124. var
  125.     cntr        : integer;
  126. begin
  127.     cntr := 0;
  128.     while cntr<768 do begin
  129.         mem[seg(Spal^):ofs(Spal^)+cntr] := mem[seg(Spal^):ofs(Spal^)+cntr] SHR 2;
  130.         inc(cntr,1);
  131.     end;
  132. end;
  133.  
  134. {*****************************************************************************
  135.     Procedure LoadPalette-
  136.     task: loads the passed palette into the VGA Dac registers
  137.  *****************************************************************************}
  138.  
  139. Procedure LoadPalette(LPal : pointer);
  140. var
  141.     regs : registers;
  142. begin
  143.     regs.ax := $1012;                      {interrupt 10h, function 12h}
  144.     regs.bx := $0;                         {start with first palette reg}
  145.     regs.cx := $100;                       {load all 256 registers}
  146.     regs.es := seg(LPal^);
  147.     regs.dx := ofs(LPal^);
  148.     intr($10,regs);
  149. end;
  150.  
  151. {*****************************************************************************
  152.     Procedure ReadPalette-
  153.     task: reads the VGA DAC registers into the test_pal palette structure
  154.  *****************************************************************************}
  155.  
  156. Procedure ReadPalette;
  157. var
  158.     regs : registers;
  159.     cntr : byte;
  160.  
  161. begin
  162.     regs.ax := $1017;
  163.     regs.bx := $0;
  164.     regs.cx := $100;
  165.     regs.es := seg(test_pal);
  166.     regs.dx := ofs(test_pal);
  167.     intr($10,regs);
  168. end;
  169.  
  170. {*****************************************************************************
  171.     Procedure ClearPalette-
  172.     task: clear all rgb values in the passed palette to 0
  173.  *****************************************************************************}
  174.  
  175. Procedure ClearPalette(Palette : pointer);
  176. var
  177.     cntr        : integer;
  178.     segmnt      : word;
  179.     offs        : word;
  180. begin
  181.     cntr := 0;
  182.     segmnt := seg(palette^);
  183.     offs   := ofs(palette^);
  184.     while cntr<768 do begin
  185.         mem[segmnt:offs+cntr] := 0;
  186.         inc(cntr,1);
  187.     end;
  188. end;
  189.  
  190. {*****************************************************************************
  191.     Procedure SelectRefresh-
  192.     task: enable disable screen refresh. on = 1, off = 0.
  193.  *****************************************************************************}
  194.  
  195. Procedure SelectRefresh(on_off : byte);
  196. var
  197.     regs : registers;
  198. begin
  199.     regs.ah := $12;
  200.     regs.bl := $32;
  201.     regs.al := on_off;
  202.     intr($10,regs);
  203. end;
  204.  
  205. {*****************************************************************************
  206.     Procedure InitReadAheadBuffer-
  207.     task: load the first 10000 bytes of PicFile into the read-ahead buffer,
  208.           and initialize the position counter to 0
  209.  *****************************************************************************}
  210.  
  211. Procedure InitReadAheadBuffer;
  212. begin
  213.     blockread(PicFile,read_ahed,10000);
  214.     ra_buf_pos := 0;
  215. end;
  216.  
  217. {*****************************************************************************
  218.     Function GetNextByte-
  219.     task: manage the read-ahead buffer and return the next physical byte to
  220.           the unpacking routine in LoadPcx.
  221.  *****************************************************************************}
  222.  
  223. Function GetNextByte : byte;
  224. begin
  225.     if ra_buf_pos <= SizeOf(read_ahed) then begin
  226.         GetNextByte := read_ahed[ra_buf_pos];
  227.         inc(ra_buf_pos,1);
  228.     end else begin
  229.         if (File_size - FilePos(PicFile)) > 10000 then begin
  230.             blockread(PicFile,read_ahed,10000);
  231.         end else begin
  232.             blockread(PicFile,read_ahed,(File_size-FilePos(PicFile)));
  233.         end;
  234.         ra_buf_pos := 0;
  235.         GetNextByte := read_ahed[ra_buf_pos];
  236.         inc(ra_buf_pos,1);
  237.     end;
  238. end;
  239.  
  240. {*****************************************************************************
  241.     Function LoadPcx -
  242.     task: called with a path and filename it attempts to decode the pcx file
  243.           into a heap variable, and returns a pointer to the buffer if succ-
  244.           essful. No error recovery is implemented. If the load fails the
  245.           program halts.
  246.  *****************************************************************************}
  247.  
  248. {$I-}
  249. Function LoadPcx;
  250.  
  251. var
  252.     width       : word;          {pic dimension width in bytes}
  253.     depth       : word;          {depth in lines}
  254.     bytes       : word;          {bytes per line}
  255.     pal_check   : byte;          {palette tag check var}
  256.     num_read    : word;          {number of palette entries read}
  257.     ln_cntr     : word;          {line counter for unpacking}
  258.     file_val    : byte;          {used in line unpack block}
  259.     run_length  : byte;          {length of compressed string}
  260.     byte_cntr   : word;          {counts bytes in line processed}
  261.     p           : pointer;       {temp pointer for mem allocation}
  262.  
  263. begin
  264.     if check_exist(PcxFile) = true then begin      {check that file exists}
  265.         assign(PicFile,PcxFile);                   {assign it}
  266.         reset(PicFile,1);                          {open it}
  267.         if IOResult <> 0 then begin                {check for I/O error}
  268.             writeln('IO error ',IOResult);
  269.             halt(0);
  270.         end;
  271.     end else begin
  272.         writeln('file not found ', PcxFile);
  273.         halt(0);
  274.     end;
  275.     GetMem(p, size_of_pcx);                        {allocate buffer}
  276.     LoadPcx := p;                                  {return the pointer}
  277.     seek(PicFile,file_size-769);                   {seek start of palette}
  278.     BlockRead(PicFile,pal_check,1);                {check for palette tag}
  279.     if pal_check <> $0C then begin
  280.         writeln('error seeking to palette');       {error if tag not $0C}
  281.         halt(0);
  282.     end;
  283.     BlockRead(PicFile,Current_pal,SizeOf(Current_pal),num_read);  {get palette}
  284.     if num_read <> SizeOf(Current_Pal) then begin                 {check size}
  285.         writeln('error in palette size. size = ',num_read);
  286.         halt(0);
  287.     end;
  288.     move(Current_pal,saved_pal,SizeOf(Current_pal));      {copy to saved palette}
  289.     Cpal_ptr := ptr(seg(current_pal),ofs(current_pal));   {setup palette ptrs}
  290.     Spal_ptr := ptr(seg(saved_pal),ofs(saved_pal));
  291.     Seek(PicFile,0);                                          {start of file}
  292.     BlockRead(PicFile,PCXHead,Sizeof(PCXHead));               {read header}
  293.     if (PCXhead.mfg <> $0A) or (PCXHead.ver <> 5) then begin  {check mfg and ver}
  294.         writeln('not a 256 color PCX file');
  295.         halt(0);
  296.     end;
  297.     depth := 200;                          {set dimensions in bytes}
  298.     width := 320;
  299.     bytes := 320;                          {bytes = bytes per line}
  300.     ln_cntr := 0;
  301.     InitReadAheadBuffer;
  302.     while ln_cntr<=depth do begin
  303.         byte_cntr := 0;                                {set byte counter to 0}
  304.         while byte_cntr<bytes do begin
  305.             File_val := GetNextByte;                   {get the first byte}
  306.             if (File_Val AND $C0) = $C0 then begin     {are high bits set?}
  307.                 run_length := (File_Val AND $3F);      {and off the high bits}
  308.                 File_val := GetNextByte;               {get the run byte}
  309.                 while run_length <> 0 do begin         {run the byte}
  310.  
  311.                     mem[seg(p^):(ln_cntr*320)+byte_cntr] := File_val;
  312.                     inc(byte_cntr,1);
  313.                     dec(run_length,1);
  314.                 end;
  315.             end else begin                             {simply store}
  316.  
  317.                 mem[seg(p^):(ln_cntr*320)+byte_cntr] := File_Val;
  318.                 inc(byte_cntr,1);
  319.             end;
  320.         end;
  321.         inc(ln_cntr,1);
  322.     end;
  323.     close(PicFile);
  324. end;
  325.  
  326. {$I+}
  327.  
  328. {*****************************************************************************
  329.     Procedure FadeInPcx-
  330.     task: sets all VGA dac palette entries to 0, loads the decoded PCX into
  331.           video memory, and then cycles through the palette, increasing the
  332.           value of each entry until it matches the picture defaults. Current_
  333.           pal holds the display palette, while Saved_pal holds the picture
  334.           default palette.
  335.  *****************************************************************************}
  336.  
  337. Procedure FadeInPcx;
  338. const
  339.     total_slots : integer = 256;           {total number of palette entries}
  340.     fade_percent : byte = 15;              {brightness gradiant in percent}
  341. var
  342.     resolved : integer;                    {number of palette entries resolved}
  343.     cntr : integer;                        {points to entry being manipulated}
  344.  
  345. begin
  346.     ClearPalette(Cpal_ptr);                {zero the display palette}
  347.     LoadPalette(CPal_ptr);                 {load it}
  348.     ShiftPalette(Spal_ptr);                {shift the saved palette}
  349.     ReadPalette;                           {TESTING LINE - REMOVE}
  350.     resolved := 0;
  351.     cntr := 0;
  352.  
  353.     {move the pcx data into memory}
  354.     move(buf_ptr^,ptr($a000,0)^,size_of_pcx);
  355.     {while some bytes unresolved}
  356.     while resolved < total_slots do begin
  357.  
  358.         {each pass through this loop processes one DAC triplet of 3 bytes}
  359.         {while cntr less than total number of palette bytes}
  360.         while cntr <= total_slots do begin
  361.             {with display palette structure}
  362.             with Current_pal[cntr] do begin
  363.                 {if this red byte unresolved (<> default value)}
  364.                 if red <> saved_pal[cntr].red then begin
  365.                    {add to it a percentage of the saved red value}
  366.                    red := round(red+((fade_percent/100)*Saved_pal[cntr].red));
  367.                    {if it now equals or is greater than the saved red value}
  368.                    if red >= saved_pal[cntr].red then begin
  369.                        {set it to the saved red value}
  370.                        red := saved_pal[cntr].red;
  371.                        {one more byte resolved (=default value)}
  372.                        inc(resolved,1);
  373.                    end;
  374.                 end;
  375.  
  376.                 {process blue and green as in red, above}
  377.                 if blue <> saved_pal[cntr].blue then begin
  378.                    blue := round(blue+((fade_percent/100)*saved_pal[cntr].blue));
  379.                    if blue >= saved_pal[cntr].blue then begin
  380.                        blue := saved_pal[cntr].blue;
  381.                        inc(resolved,1);
  382.                    end;
  383.                 end;
  384.                 if green <> saved_pal[cntr].green then begin
  385.                    green := round(green+((fade_percent/100)*saved_pal[cntr].green));
  386.                    if green >= saved_pal[cntr].green then begin
  387.                        green := saved_pal[cntr].green;
  388.                        inc(resolved,1);
  389.                    end;
  390.                 end;
  391.             end;
  392.             inc(cntr,1);
  393.         end;
  394.         LoadPalette(CPal_ptr);          {load the display palette}
  395.         cntr := 0;
  396.     end;
  397. end;
  398.  
  399. {*****************************************************************************
  400.     Procedure FadeOutPcx-
  401.     task: cycles through the DAC palette reducing all values by fade_percent
  402.           until the entire palette is zeroed. Does not affect video memory
  403.     note: functionally equivalent to above procedure
  404.  
  405.  ***************************************************************************}
  406.  
  407. Procedure FadeOutPcx;
  408. const
  409.     total_slots : integer = 256;           {total number of palette entries}
  410.     fade_percent : byte = 15;              {brightness gradiant in percent}
  411. var
  412.     regs : registers;
  413.     resolved : integer;                    {number of palette entries resolved}
  414.     cntr : integer;                  {points to entry being manipulated}
  415. begin
  416.     resolved := 0;
  417.     cntr := 0;
  418.     while resolved < total_slots do begin
  419.         while cntr <= total_slots do begin
  420.             with Current_pal[cntr] do begin
  421.                 if red <> 0 then begin
  422.                    red := round(red-((fade_percent/100)*saved_pal[cntr].red));
  423.                    if red <= 0 then begin
  424.                        red := 0;
  425.                        inc(resolved,1);
  426.                    end;
  427.                 end;
  428.                 if blue <> 0 then begin
  429.                    blue := round(blue-((fade_percent/100)*saved_pal[cntr].blue));
  430.                    if blue <= 0 then begin
  431.                        blue := 0;
  432.                        inc(resolved,1);
  433.                    end;
  434.                 end;
  435.                 if green <> 0 then begin
  436.                    green := round(green-((fade_percent/100)*saved_pal[cntr].green));
  437.                    if green <= 0 then begin
  438.                        green := 0;
  439.                        inc(resolved,1);
  440.                    end;
  441.                 end;
  442.             end;
  443.             inc(cntr,1);
  444.         end;
  445.         LoadPalette(Cpal_ptr);
  446.         cntr := 0;
  447.     end;
  448. end;
  449.  
  450. {*****************************************************************************
  451.     Procedure FreePcxMem-
  452.     task: deallocates the memeory assigned to the passed pointer. No checking
  453.           is performed so a valid pointer must be passed. Zeros both palette
  454.           structures.
  455.  *****************************************************************************}
  456.  
  457. Procedure FreePcxMem;
  458. begin
  459.     FreeMem(buf_ptr,SizeOf(buf_ptr^));
  460. end;
  461.  
  462. end.