home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_PAS / XLIB_TP5.ZIP / UNITS / X_PICS.PAS < prev    next >
Pascal/Delphi Source File  |  1994-01-19  |  25KB  |  740 lines

  1. unit X_Pics;
  2.  
  3. (* X_Pics  load SCR-Files      (converted with the utily Gif2SCR)
  4.            load/save RLE-Files
  5.  
  6.    RLE-procedures    by Themie Gouthas
  7.    SCR-procedure     by CHristian Harms
  8.  
  9.     ****** XLIB - Mode X graphics library                ****************
  10.     ******                                               ****************
  11.     ****** Written By Themie Gouthas ( C-Version )       ****************
  12.     ****** Converted By Christian Harms in TP            ****************
  13.  
  14.  
  15.    X_Pics is the a old part of X_Bitmaps, who was very big and the Bitmaps
  16.    are more smaller then big backgrounds.
  17.  
  18. - Screenfiles (scr) are simple Screen-Dumps.
  19.  
  20.   Byte 0+Byte 1 :  Width in Bytes (width*4=Pixel)
  21.   Byte 2+Byte 3 :  Height in Pixel
  22.   Byte 4       :  Boolean, if True, then follow Byte 4..Byte 4+768 Palette
  23.   Byte n       :  Plane 0 - 3
  24.  
  25.   used by Gif2SCR and the procedure x_load_scr
  26.  
  27.  
  28. *)
  29.  
  30.  
  31. interface
  32.  
  33. (******************************* SCR ***************************************)
  34. (* Load SCR_File on activ Page and set var.Pal if New_Pal in File ,        *)
  35. (* otherwise fill it with 0.   True,if successed.                          *)
  36. function x_Load_Scr(Name:String;var Pal):Boolean;
  37.  
  38. (******************************* RLE ***************************************)
  39. (* see comment in implementation part *)
  40. function x_buff_RLEncode(Var src,dest;count:Word):Word;
  41. function x_buff_RLE_size(Var src;count:Word):Word;
  42. function x_buff_RLDecode(Var src,dest):Word;
  43. function x_file_RLEncode(Var FileVar:File;Var src;Count:Word):Word;
  44. function x_file_RLDecode(Var FileVar:File;Var dest):Word;
  45.  
  46.  
  47. implementation
  48.  
  49. uses X_Const,X_Main,X_FileIO;
  50.  
  51. (***************************************************************************)
  52. (*                                                                         *)
  53. (* Screen-File  Load                                                       *)
  54. (*                                                                         *)
  55. (***************************************************************************)
  56. function X_Load_Scr(Name:String;var Pal):Boolean;    (* able with MasterFile *)
  57. type Big=Array[0..$FFF0] of Byte;
  58. var F         : File;
  59.     j1,j2     : LongInt;
  60.     width,height,h:Word;
  61.     i         : Byte;
  62.     isNew_Pal : Boolean;
  63.     New_Pal   : Palette;
  64.     inter     : Integer;
  65.     Bitmap    : ^Big;
  66. begin;
  67.   x_Load_Scr:=False;
  68.   Name:=Only_one_Ext(Name,'SCR');
  69.   if not F_Open_Read(F,Name) then exit;
  70.   BlockRead(f,width, 2);
  71.   BlockRead(f,Height,2);
  72.   BlockRead(f,isNew_Pal,1);
  73.   j2:=(5+ord(isNew_pal)*sizeof(New_Pal)+4*LongInt(width*height));
  74.   if F_size(Name)<>j2 then begin;F_Close(f);exit;end;
  75.  
  76.   if isNew_pal then BlockRead(f,New_Pal,sizeof(New_Pal))   (* Read new palette      *)
  77.            else Fillchar(New_Pal,sizeof(New_Pal),0);   (* fill palette with 0's *)
  78.  
  79.   h:=width*height;
  80.   if MaxAvail<h then begin;F_Close(f);exit;end;
  81.   GetMEM(Bitmap,h);      (* no direct Read in [SCREEN_SEG:ScreenOfs],because*)
  82.                   (* SmartDrv change the value in VGA-Card (Bitplane-sets). *)
  83.   for i:=0 to 3 do
  84.   begin;
  85.     BlockRead(f,Bitmap^[0],h,inter);
  86.     x_select_default_plane(i);
  87.     asm
  88.       push ds                       (* copy plane to video-ram            *)
  89.       mov  ax,Screen_Seg
  90.       mov  es,ax
  91.       mov  di,ScreenOfs
  92.       mov  cx,h
  93.       lds  si,dword ptr [Bitmap]
  94.       rep  movsb
  95.       pop  ds
  96.     end;
  97.   end;
  98.   F_Close(F);
  99.   move(New_Pal,Pal,sizeof(New_Pal));
  100.   FreeMEM(Bitmap,h);
  101.   X_Load_Scr:=True;
  102. end;
  103.  
  104.  
  105. (*
  106. ;-----------------------------------------------------------------------
  107. ; MODULE XRLETOOL
  108. ;
  109. ; Hardware detection module
  110. ;
  111. ; Compile with Tasm.
  112. ;
  113. ; ****** XLIB - Mode X graphics library                ****************
  114. ; ******                                               ****************
  115. ; ****** Written By Themie Gouthas                     ****************
  116. ;
  117. ; egg@dstos3.dsto.gov.au
  118. ; teg@bart.dsto.gov.au
  119. ;-----------------------------------------------------------------------
  120.  
  121. COMMENT $
  122.  
  123. Firstly, please note that this module has been built from the ground up
  124. in a rush so although I'm confident all the functions work, I have'nt
  125. extensively checked them. If any should surface please let me know.
  126.  
  127.  
  128. This module implements a number of functions comprising an RLE encoding
  129. decoding system.
  130.  
  131. RLE stands for RUN LENGTH ENCODING. It is a quick simple data compression
  132. scheme which is commonly used for image data compression or compression
  133. of any data. Although not the most efficient system, it is fast, which is
  134. why it is used in image storage systems like PCX. This implementation is
  135. more efficient than the one used in PCX files because it uses 1 bit to
  136. identify a Run Length byte as opposed to two in PCX files, but more on this
  137. later.
  138.  
  139. This set of functions can be used to implement your own compressed image
  140. file format or for example compress game mapse for various levels etc.
  141. The uses are limited by your imagination.
  142.  
  143. I opted for trading off PCX RLE compatibility for the improved compression
  144. efficiency.
  145.  
  146. Here is how the data is un-compressed to give an idea of its structure.
  147.  
  148.  
  149. STEP 1 read a byte from the RLE compressed source buffer.
  150.  
  151. STEP 2 if has its high bit then the lower 7 bits represent the number of
  152.        times the next byte is to be repeated in the destination buffer.
  153.        if the count (lower 7 bits) is zero then
  154.       we have finished decoding goto STEP 5
  155.        else goto STEP 4
  156.  
  157. STEP 3 Read a data from the source buffer and copy it directly to the
  158.        destination buffer.
  159.        goto STEP 1
  160.  
  161. STEP 4 Read a data from the source buffer and copy it to the destination
  162.        buffer the number of times specified by step 2.
  163.        goto STEP 1
  164.  
  165. STEP 5 Stop, decoding done.
  166.  
  167. If the byte does not have the high bit set then the byte itself is transfered
  168.  to the destination buffer.
  169.  
  170. Data bytes that have the high bit already set and are unique in the input
  171.  stream are represented as a Run Length of 1 (ie 81 which includes high bit)
  172.  followed by the data byte.
  173.  
  174. If your original uncompressed data contains few consecutive bytes and most
  175. have high bit set (ie have values > 127) then your so called
  176. compressed data would require up to 2x the space of the uncompressed data,
  177. so be aware that the compression ratio is extremely variable depending on the
  178. type of data being compressed.
  179.  
  180. Apologies for this poor attempt at a description, but you can look up
  181. RLE in any good text. Alternatively, any text that describes the PCX file
  182. structure in any depth should have a section on RLE compression.
  183.  
  184.  
  185.  
  186. $
  187.  
  188. LOCALS
  189. .286
  190.  
  191. include model.inc
  192. include xrletool.inc
  193.  
  194.     .data
  195.         *)
  196.  
  197. var RLE_last_buff_offs : Word;
  198.     RLEbuff            : Byte;
  199.  
  200.  
  201. (*****************************************************************
  202. (**
  203. (** NAME: x_buff_RLEncode
  204. (**
  205. (**
  206. (** RLE Compresses a source buffer to a destination buffer and returns
  207. (** the size of the resultant compressed data.
  208. (**
  209. (** C PROTOTYPE:
  210. (**
  211. (**  extern unsigned int x_buff_RLEncode(char far * source_buff,
  212. (**           char far * dest_buff,unsigned int count);
  213. (**
  214. (** source_buff   - The buffer to compress
  215. (** dest_buff     - The destination buffer
  216. (** count         - The size of the source data in bytes
  217. (**
  218. (** WARNING: buffers must be pre allocated.
  219. *)
  220.  
  221. function x_buff_RLEncode(Var src,dest;count:Word):Word; assembler;
  222. asm
  223.     push si
  224.     push di
  225.  
  226.     lds  si,[src]
  227.     les  di,[dest]
  228.     mov  dx,[count]
  229.  
  230.     push di
  231.  
  232.     lodsb              (* Load first byte into BL                       *)
  233.     mov  bl,al
  234.     xor  cx,cx         (* Set number characters packed to zero          *)
  235.     cld                (* All moves are forward                         *)
  236.  
  237. @@RepeatByte:
  238.     lodsb           (* Get byte into AL                              *)
  239.     inc  cx            (* Increment compressed byte count               *)
  240.     sub  dx,1          (* Decrement bytes left                          *)
  241.     je   @@LastByte    (* Finished when dx = 1                          *)
  242.     cmp  cx,7fh        (* Filled block yet                              *)
  243.     jne  @@NotFilled   (* Nope!                                         *)
  244.  
  245.     or   cl,80h        (* Set bit to indicate value is repeat count     *)
  246.     mov  es:[di],cl    (* store it                                      *)
  247.     inc  di
  248.     xor  cx,cx         (* clear compressed byte count                   *)
  249.     mov  es:[di],bl    (* store byte to be repeated                     *)
  250.     inc  di
  251.  
  252. @@NotFilled:
  253.     cmp  al,bl         (* hase there been a byte transition ?           *)
  254.     je   @@RepeatByte  (* No!                                           *)
  255.  
  256.     cmp  cl,1          (* do we have a unique byte ?                    *)
  257.     jne  @@NotUnique   (* No                                            *)
  258.  
  259.     test bl,80h        (* Can this byte be mistaken for repeat count    *)
  260.     jz   @@Unambiguous (* No ! Dont bother with repeat count            *)
  261.  
  262. @@NotUnique:
  263.     or   cl,80h        (* Set bit to indicate value is repeat count     *)
  264.     mov  es:[di],cl    (* store it                                      *)
  265.     inc  di
  266. @@Unambiguous:
  267.     xor  cx,cx         (* clear compressed byte count                   *)
  268.     mov  es:[di],bl    (* store byte to be repeated                     *)
  269.     inc  di
  270.     mov  bl,al         (* move latest byte into bl                      *)
  271.     jmp  @@RepeatByte
  272.  
  273. @@LastByte:
  274.     cmp  cl,1          (* Is this a unique byte                         *)
  275.     jne  @@FinalCount  (* No                                            *)
  276.  
  277.     test bl,80h        (* Can this byte be mistaken for repeat count    *)
  278.     jz   @@FinalByte   (* No, so dont bother with the repeat count      *)
  279.  
  280. @@FinalCount:              (* Output the repeat count                       *)
  281.     or   cl,80h
  282.     mov  al,cl
  283.     stosb
  284.  
  285. @@FinalByte:
  286.     mov  al,bl
  287.     stosb
  288.  
  289.     mov  al,80h       (* store terminating null length                  *)
  290.     stosb
  291.  
  292.         (* Calculate encoded length of buffer                               *)
  293.  
  294.     mov  ax,di
  295.     pop  di
  296.     sub  ax,di
  297.  
  298.     pop  di
  299.     pop  si
  300.     pop  ds
  301. end;
  302.  
  303.  
  304.  
  305. (*****************************************************************
  306. (**
  307. (** NAME: x_buff_RLE_size
  308. (**
  309. (**
  310. (** Returns the size the input data would compress to.
  311. (**
  312. (** C PROTOTYPE:
  313. (**
  314. (**  extern unsigned int x_buff_RLE_size(char far * source_buff,
  315. (**           unsigned int count);
  316. (**
  317. (** source_buff   - The uncompressed data buffer
  318. (** count         - The size of the source data in bytes
  319. (**
  320. *)
  321.  
  322. function x_buff_RLE_size(Var src;count:Word):Word; assembler;
  323. asm
  324.     push ds
  325.     push si
  326.     push di
  327.  
  328.     lds  si,[src]
  329.     mov  dx,[count]
  330.  
  331.     xor  di,di
  332.  
  333.     lodsb              (* Load first byte into BL                       *)
  334.     mov  bl,al
  335.     xor  cx,cx         (* Set number characters packed to zero          *)
  336.     cld                (* All moves are forward                         *)
  337.  
  338. @@RepeatByte:
  339.     lodsb           (* Get byte into AL                              *)
  340.     inc  cx            (* Increment compressed byte count               *)
  341.     sub  dx,1          (* Decrement bytes left                          *)
  342.     je   @@LastByte    (* Finished when dx = 1                          *)
  343.     cmp  cx,7fh        (* Filled block yet                              *)
  344.     jne  @@NotFilled   (* Nope!                                         *)
  345.  
  346.     add  di,2          (* RL/BYTE pair stub                             *)
  347.  
  348. @@NotFilled:
  349.     cmp  al,bl         (* hase there been a byte transition ?           *)
  350.     je   @@RepeatByte  (* No!                                           *)
  351.  
  352.     cmp  cl,1          (* do we have a unique byte ?                    *)
  353.     jne  @@NotUnique   (* No                                            *)
  354.  
  355.     test bl,80h        (* Can this byte be mistaken for repeat count    *)
  356.     jz   @@Unambiguous (* No ! Dont bother with repeat count            *)
  357.  
  358. @@NotUnique:
  359.     inc  di            (* RL stub                                       *)
  360.  
  361. @@Unambiguous:
  362.     xor  cx,cx         (* clear compressed byte count                   *)
  363.     inc  di            (* BYTE stub                                     *)
  364.     mov  bl,al         (* move latest byte into bl                      *)
  365.     jmp  @@RepeatByte
  366.  
  367. @@LastByte:
  368.     cmp  cl,1          (* Is this a unique byte                         *)
  369.     jne  @@FinalCount  (* No                                            *)
  370.  
  371.     test bl,80h        (* Can this byte be mistaken for repeat count    *)
  372.     jz   @@FinalByte   (* No, so dont bother with the repeat count      *)
  373.  
  374. @@FinalCount:              (* Output the repeat count                       *)
  375.     inc  di            (* RL stub                                       *)
  376.  
  377. @@FinalByte:
  378.     inc  di            (* BYTE stub                                     *)
  379.     inc  di            (* RL stub - Account for termiating null         *)
  380.     mov  ax,di
  381.  
  382.     pop  di
  383.     pop  si
  384.     pop  ds
  385. end;
  386.  
  387. (*****************************************************************
  388. (**
  389. (** NAME: x_buff_RLDecode
  390. (**
  391. (**
  392. (** Expands an RLE compressed source buffer to a destination buffer.
  393. (** returns the size of the resultant uncompressed data.
  394. (**
  395. (** C PROTOTYPE:
  396. (**
  397. (**  extern unsigned int x_buff_RLDecode(char far * source_buff,
  398. (**           char far * dest_buff)(*
  399. (**
  400. (** source_buff   - The buffer to compress
  401. (** dest_buff     - The destination buffer
  402. (**
  403. (** WARNING: buffers must be pre allocated.
  404. *)
  405. function x_buff_RLDecode(Var src,dest):Word; assembler;
  406. var si_ini:Word;
  407. asm
  408.     push ds
  409.     push si
  410.     push di
  411.  
  412.     mov  dx,-1        (* zero output data buffer size - 1 (compensate for *)
  413.               (* terminating null RL)                           *)
  414.     xor  cx,cx        (* clear CX                                       *)
  415.     cld               (* Move forward                                   *)
  416.  
  417.     lds  si,[src]     (* point ds:si -> RLE source                      *)
  418.     les  di,[dest]    (* point es:di -> uncompressed buffer             *)
  419.         mov  [si_ini],si
  420.  
  421. @@UnpackLoop:
  422.     lodsb             (* load a byte into AL                            *)
  423.     cmp  al,80h       (* is it terminating null RL code                 *)
  424.     je   @@done       (* if so jump                                     *)
  425.  
  426.     test al,80h       (* is AL a RL code (is high bit set ?)            *)
  427.     jz   @@NoRepeats  (* if not the no RL encoding for this byte, jump  *)
  428.  
  429.     mov  cl,al        (* set CL to RL (run length) taking care          *)
  430.     xor  cl,80h       (* to remove the bit identifying it as a RL       *)
  431.         add  dx,cx        (* increment buffer size                          *)
  432.  
  433.     lodsb             (* get the next byte which should be a data byte  *)
  434.  
  435.     shr  cx,1         (* divide RL by 2 to use word stos                *)
  436.     jcxz @@NoRepeats  (* result is zero, jump                           *)
  437.  
  438.     mov  ah,al        (* copy data byte to AH since going to use stosw  *)
  439.     rep  stosw        (* copy AX to outbut buffer RL times              *)
  440.     jnb  @@UnpackLoop (* when we shifted the RL if we had a carry =>    *)
  441.               (* we had an odd number of repeats so store the   *)
  442.               (* last BYTE if carry was set otherwise jump      *)
  443.         stosb             (* store AL in destination buffer                 *)
  444.         jmp  @@UnpackLoop
  445.  
  446. @@NoRepeats:
  447.     inc  dx           (* increment buffer size                          *)
  448.     stosb             (* store AL in destination buffer                 *)
  449.         jmp  @@UnpackLoop
  450.  
  451. @@done:
  452.  
  453.         mov  bx,si
  454.         sub  bx,[si_ini]
  455.     mov  ax,dx
  456.     pop  di
  457.     pop  si
  458.     pop  ds
  459.         mov  [RLE_last_buff_offs],bx
  460. end;
  461.  
  462. (*==========================================================================
  463. (*==========================================================================
  464. (* RLEncode to file / RLDecode from file
  465. (* WARNING the following functions are *MUCH* slower than the above
  466. (* Its best to use the above functions with intermediate buffers where
  467. (* disk i/o is concearned... See demo 4
  468. (*==========================================================================
  469. (*==========================================================================*)
  470.  
  471. var handle:Word;
  472.  
  473. (*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  474. (*
  475. (* put_cx
  476. (*
  477. (*   Local utility proc for x_file_RLEncode - write cx to file
  478. (*
  479. (* Entry:
  480. (*       es:dx -> output buffer
  481. (*       cx = word to write
  482. (*
  483. *)
  484. procedure put_cx; assembler;
  485. asm
  486.     push ds             (* preserve critical registers                  *)
  487.     push ax
  488.     push bx
  489.     mov  ax,ds          (* set up DS to output buffers segment          *)
  490.     mov  ds,ax
  491.     mov  word ptr [RLEbuff],cx (* copy CX to output buffer              *)
  492.     mov  ah,40h         (* select "write to file or device" DOS service *)
  493.     mov  bx,[handle]    (* select handle of file to write               *)
  494.     mov  cx,2           (* sending 2 bytes                              *)
  495.     int  21h        (* call DOS service                             *)
  496.     pop  bx             (* recover registers                            *)
  497.     pop  ax
  498.     pop  ds
  499. end;
  500.  
  501. (*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  502. (*
  503. (* put_cx
  504. (*
  505. (*   Local utility proc for x_file_RLEncode - write cx to file
  506. (*
  507. (* Entry:
  508. (*       es:dx -> output buffer
  509. (*       cx = word to write
  510. (*
  511. *)
  512. procedure put_cl; assembler;
  513. asm
  514.     push ds             (* preserve critical registers                  *)
  515.     push ax
  516.     push bx
  517.     mov  ax,ds          (* set up DS to output buffers segment          *)
  518.     mov  ds,ax
  519.     mov  byte ptr [RLEbuff],cl
  520.     mov  ah,40h         (* select "write to file or device" DOS service *)
  521.     mov  bx,[handle]    (* select handle of file to write               *)
  522.     mov  cx,1           (* sending 1 byte                               *)
  523.     int  21h        (* call DOS service                             *)
  524.     pop  bx             (* recover registers                            *)
  525.     pop  ax
  526.     pop  ds
  527. end;
  528.  
  529.  
  530. (****************************************************************
  531. ;*
  532. ;* NAME: x_file_RLEncode
  533. ;*
  534. ;*
  535. ;* RLE Compresses a source buffer to an output file returning
  536. ;* the size of the resultant compressed data or 0 if it fails.
  537. ;*
  538. ;* C PROTOTYPE:
  539. ;*
  540. ;*  extern unsigned int x_file_RLEncode(int handle,
  541. ;*           char far * source_buff,unsigned int count);
  542. (**
  543. (** source_buff   - The buffer to compress
  544. (** handle        - The file handler
  545. (** count         - The size of the source data in bytes
  546. (**
  547. *)
  548. function x_file_RLEncode(Var FileVar:File;Var src;Count:Word):Word; assembler;
  549. var filesize:Word;
  550. asm
  551.     push ds
  552.     push si
  553.     push di
  554.  
  555.         les  si,dword ptr [FileVar]
  556.         mov  ax,es:[si]
  557.         mov  handle,ax
  558.  
  559.     mov  [filesize],0
  560.     mov  dx,offset [RLEbuff]
  561.     mov  ax,ds
  562.     mov  es,ax
  563.     lds  si,[src]
  564.     mov  di,[count]
  565.  
  566.     lodsb              (* Load first byte into BL                       *)
  567.     mov  bl,al
  568.     xor  cx,cx         (* Set number characters packed to zero          *)
  569.     cld                (* All moves are forward                         *)
  570.  
  571. @@RepeatByte:
  572.     lodsb           (* Get byte into AL                              *)
  573.     inc  cx            (* Increment compressed byte count               *)
  574.     sub  di,1          (* Decrement bytes left                          *)
  575.     je   @@LastByte    (* Finished when di = 1                          *)
  576.     cmp  cx,7fh        (* Filled block yet                              *)
  577.     jne  @@NotFilled   (* Nope!                                         *)
  578.  
  579.     or   cl,80h        (* Set bit to indicate value is repeat count     *)
  580.     mov  ch,bl
  581.     add  [filesize],2
  582.     call put_cx
  583.     jb   @@FileError   (* if carry set then file I/O error              *)
  584.     xor  cx,cx         (* clear compressed byte count                   *)
  585.  
  586. @@NotFilled:
  587.     cmp  al,bl         (* hase there been a byte transition ?           *)
  588.     je   @@RepeatByte  (* No!                                           *)
  589.  
  590.     cmp  cl,1          (* do we have a unique byte ?                    *)
  591.     jne  @@NotUnique   (* No                                            *)
  592.  
  593.     test bl,80h        (* Can this byte be mistaken for repeat count    *)
  594.     jz   @@Unambiguous (* No ! Dont bother with repeat count            *)
  595.  
  596. @@NotUnique:
  597.     or   cl,80h        (* Set bit to indicate value is repeat count     *)
  598.     inc  [filesize]
  599.     call put_cl        (* store it                                      *)
  600.         jb   @@FileError   (* if carry set then file I/O error              *)
  601. @@Unambiguous:
  602.  
  603.     mov  cl,bl         (* store byte to be repeated                     *)
  604.         inc  [filesize]
  605.     call put_cl
  606.         jb   @@FileError   (* if carry set then file I/O error              *)
  607.     mov  bl,al         (* move latest byte into bl                      *)
  608.         xor  cx,cx         (* clear compressed byte count                   *)
  609.     jmp  @@RepeatByte
  610.  
  611. @@FileError:
  612.     mov  ax,0
  613.     jmp  @@exit
  614.  
  615. @@LastByte:
  616.     cmp  cl,1          (* Is this a unique byte                         *)
  617.     jne  @@FinalCount  (* No                                            *)
  618.  
  619.     test bl,80h        (* Can this byte be mistaken for repeat count    *)
  620.     jz   @@FinalByte   (* No, so dont bother with the repeat count      *)
  621.  
  622. @@FinalCount:              (* Output the repeat count                       *)
  623.     or   cl,80h
  624.         inc  [filesize]
  625.     call put_cl
  626.     jb   @@FileError   (* if carry set then file I/O error              *)
  627.  
  628. @@FinalByte:
  629.     mov  cl,bl
  630.     mov  ch,80h
  631.     add  [filesize],2
  632.     call put_cx        (* store terminating null length                 *)
  633.     jb   @@FileError   (* if carry set then file I/O error              *)
  634.  
  635.     mov  ax,[filesize]
  636.     jmp  @@exit
  637.  
  638. @@exit:
  639.     pop  di
  640.     pop  si
  641.     pop  ds
  642. end;
  643.  
  644.  
  645.  
  646.  
  647. (*****************************************************************
  648. (**
  649. (** NAME: x_file_RLDecode
  650. (**
  651. (**
  652. (** Expands an RLE compresses file to a destination RAM buffer.
  653. (** returns the size of the resultant uncompressed data.
  654. (**
  655. (** C PROTOTYPE:
  656. (**
  657. (**  extern unsigned int x_buff_RLDecode(int handle,
  658. (**           char far * dest_buff);
  659. (**
  660. (** handle        - Input file handle
  661. (** dest_buff     - The destination buffer
  662. (**
  663. *)
  664. function x_file_RLDecode(Var FileVar:File;Var dest):Word; assembler;
  665. asm
  666.     push si
  667.     push di
  668.  
  669.  
  670.     mov  bx,-1        (* zero output data buffer size - 1 (compensate for*)
  671.               (* terminating null RL)                           *)
  672.     mov  dx,offset [RLEbuff] (* setup DS:DX -> RLEBuffer                *)
  673.         xor  cx,cx        (* clear CX                                       *)
  674.     cld               (* Move forward                                   *)
  675.  
  676.     les  di,[dest]    (* point es:di -> uncompressed buffer             *)
  677.  
  678. @@UnpackLoop:
  679.  
  680.                  (* Load a byte from file into AL                  *)
  681.     push bx
  682.     mov  ah,3fh         (* select "read from file or device" DOS service*)
  683.     mov  bx,[handle]    (* Select handle of file to close               *)
  684.     mov  cx,1           (* Want to read 1 byte                          *)
  685.     int  21h            (* call DOS service                             *)
  686.     pop  bx
  687.     jb   @@FileError    (* failed if carry flag set                     *)
  688.     mov  al,[RLEbuff]
  689.  
  690.     cmp  al,80h       (* is it terminating null RL code                 *)
  691.     je   @@done       (* if so jump                                     *)
  692.  
  693.     test al,80h       (* is AL a RL code (is high bit set ?)            *)
  694.     jz   @@NoRepeats  (* if not the no RL encoding for this byte, jump  *)
  695.  
  696.     mov  cl,al        (* set CL to RL (run length) taking care          *)
  697.     xor  cl,80h       (* to remove the bit identifying it as a RL       *)
  698.     add  bx,cx        (* increment buffer size                          *)
  699.     mov  si,cx        (* save the CX value                              *)
  700.  
  701.                    (* Load a byte from file into AL                  *)
  702.     push bx
  703.     mov  ah,3fh         (* select "read from file or device" DOS service*)
  704.     mov  bx,[handle]    (* Select handle of file to close               *)
  705.     mov  cx,1           (* Want to read 1 byte                          *)
  706.     int  21h            (* call DOS service                             *)
  707.     pop  bx
  708.     jb   @@FileError    (* failed if carry flag set                     *)
  709.     mov  al,[RLEbuff]
  710.  
  711.     mov  cx,si        (* restore CX value                               *)
  712.         shr  cx,1         (* divide RL by 2 to use word stos                *)
  713.     jcxz @@NoRepeats  (* result is zero, jump                           *)
  714.  
  715.     mov  ah,al        (* copy data byte to AH since going to use stosw  *)
  716.     rep  stosw        (* copy AX to outbut buffer RL times              *)
  717.     jnb  @@UnpackLoop (* when we shifted the RL if we had a carry =>    *)
  718.               (* we had an odd number of repeats so store the   *)
  719.               (* last BYTE if carry was set otherwise jump      *)
  720.         stosb             (* store AL in destination buffer                 *)
  721.         jmp  @@UnpackLoop
  722.  
  723. @@NoRepeats:
  724.     inc  bx
  725.     stosb             (* store AL in destination buffer                 *)
  726.         jmp  @@UnpackLoop
  727.  
  728. @@FileError:
  729.     mov  ax,0
  730.     jmp  @@exit
  731.  
  732. @@done:
  733.     mov  ax,bx
  734. @@exit:
  735.     pop  di
  736.     pop  si
  737. end;
  738.  
  739.  
  740. end.