home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_PAS / XLIB_TP5.ZIP / UNITS / X_BITMAP.PAS < prev    next >
Pascal/Delphi Source File  |  1994-01-23  |  118KB  |  3,249 lines

  1. {$G+}
  2. Unit X_Bitmap;
  3.  
  4. (*
  5.     Bitmap procedures. (load,save,put,convert)
  6.  
  7.     ****** XLIB - Mode X graphics library                ****************
  8.     ******                                               ****************
  9.     ****** Written By Themie Gouthas ( C-Version )       ****************
  10.     ****** Converted By Christian Harms in TP            ****************
  11.  
  12.     Gouthas : egg@dstos3.dsto.gov.au or teg@bart.dsto.gov.au
  13.     Harms   : harms@minnie.informatik.uni-stuttgart.de
  14.  
  15.  
  16. - Planar Bitmap (pbm) functions - System Ram <-> Video Ram
  17.  
  18.   This module implements a set of functions to operate on planar bitmaps.
  19.   Planar bitmaps as used by these functions have the following structure:
  20.  
  21.   BYTE 0                 The bitmap width in bytes (4 pixel groups) range 1..255
  22.   BYTE 1                 The bitmap height in rows range 1..255
  23.   BYTE 2..n1             The plane 0 pixels width*height bytes
  24.   BYTE n1..n2            The plane 1 pixels width*height bytes
  25.   BYTE n2..n3            The plane 2 pixels width*height bytes
  26.   BYTE n3..n4            The plane 3 pixels width*height bytes
  27.  
  28.   or in Pascal :
  29.  
  30.   record pbm of
  31.     X_Byte,Y_Pixel              : Byte;
  32.     Plane0,Plane1,Plane2,Plane3 : Array[1..Y_Pixel,1..X_Byte] of Byte;
  33.   end;
  34.  
  35.   But these Stucture are not interessting, because all pbm's are used
  36.   from pure asm-Procedures.
  37.  
  38.   These functions provide the fastest possible bitmap blts from system ram
  39.   to video and further, the single bitmap is applicable to all pixel
  40.   allignments. The masked functions do not need separate masks since all
  41.   non zero pixels are considered to be masking pixels, hence if a pixel
  42.   is 0 the corresponding screen destination pixel is left unchanged.
  43.  
  44.  
  45. - Linear Bitmap (lbm) can only converted from/in pbm, but the are easy to
  46.   change with Turbo Pascal.
  47.  
  48.   record lbm of
  49.     X,Y   : Byte;
  50.     Pixel : Array[1..Y,1..X] of Byte;
  51.   end;
  52.  
  53. - Compiled Bitmap (cbm) is the fastes Bitmap format in XLib_TP, but the
  54.   size can be x3 of pbm (Speed x6).
  55.   cbm are fixed to one ScreenWidth after converting in cbm (!)and you can
  56.   only cbm as masked bitmaps.
  57.  
  58. - Interpreted Bitmap (ibm) is a format to save space. ibm can be to 50%
  59.   of the pbm, the speed is 50% - 100 % faster then pbm.
  60.  
  61.  
  62.   format : byte 0 :      The bitmap width
  63.            byte 1        The bitmap height
  64.  
  65.            next bytes will be interpreted
  66.  
  67.              if zero , add ScreenPointer with next byte
  68.                   else copy the next n bytes to screen
  69.              if x=MaxX then add ScrennPointer do next BitmapbeginLine
  70.              next Loop
  71.  
  72.            pack - example :
  73.  
  74.               black line  (0,0,0,0,0,0,0,0,0,0) as (0,10);
  75.               color line  (2,3,2,3,2,3,2,3,2,3) as (10,2,3,2,3,2,3,2,3,2,3);
  76.               normal line (0,0,0,0,0,9,8,7,6,5) as (0,5, 5,9,8,7,6,5);
  77.  
  78.  
  79.   Smaller than pbm, if some pixels with color 0 in bitmap
  80.   Faster  than pbm, because no every pixel-compares
  81.  
  82.  
  83.  
  84. - The VBM format implements yet another type of bitmap to complement
  85.   planar and compiled bitmaps, VRAM based bitmaps. If a 4 cylinder car is
  86.   analagous to planar bitmaps, that is thrifty on memory consumption but low
  87.   performance and and a V8 is analagous to Compiled bitmaps, memory guzzlers
  88.   that really fly, then VRAM based bitmaps are the 6 cylinder modest performers
  89.   with acceptable memory consumption.
  90.  
  91.   To summarise their selling points, VBM's are moderately fast with fair memory
  92.   consumption, and unlike compiled bitmaps, can be clipped. The disadvantages
  93.   are that they are limited by the amount of free video ram and have a complex
  94.   structure.
  95.  
  96.   The VRAM bitmap format is rather complex consisting of components stored in
  97.   video ram and components in system ram working together. This complexity
  98.   necessitates the existence of a creation function "x_lbm_to_vbm" which takes
  99.   an input linear bitmap and generates the equivalent VBM (VRAM Bit Map).
  100.  
  101.   VBM structure:
  102.  
  103.       WORD  0   Size          Total size of this VBM structure in bytes
  104.       WORD  1   ImageWidth    Width in bytes of the image (for all alignments)
  105.       WORD  2   ImageHeight   Height in scan lines of the image
  106.  
  107.       WORD  3 Alignment 0  ImagePtr   Offset in VidRAM of this aligned image
  108.    +--WORD  4              MaskPtr    Offset (within this structure's DS) of
  109.    |   .                   alignment masks
  110.    |   .
  111.    |   .
  112.    |  WORD  9 Alignment 3  ImagePtr   Offset in VidRAM of this aligned image
  113.   +|--WORD 10              MaskPtr    Offset (within this structure's DS) of
  114.   ||                              alignment masks
  115.   ||
  116.   |+->BYTE 21 (WORD 11)                -------+-- Image masks for alignment 0
  117.   |   .                                       |
  118.   |   .                                       |
  119.   |   BYTE  21 + ImageWidth*ImageHeight  -----+
  120.   |
  121.   |   .
  122.   |   . (similaly for alignments 1 - 2 )
  123.   |   .
  124.   |
  125.   +-->BYTE  21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3
  126.       .                                       |
  127.       .                                       |
  128.       BYTE  21 + 4*(ImageWidth*ImageHeight) --+
  129.  
  130.       .
  131.       .
  132.       << Similarly for alignments 2 and 3 >>
  133.       .
  134.       .
  135.       BYTE 21 + 4*(ImageWidth*ImageHeight)
  136.   -------------
  137.  
  138.   (And dont forget the corresponding data in video ram)
  139.  
  140. *)
  141.  
  142. interface
  143.  
  144. const EXT_pbm = 'PBM';
  145.       EXT_lbm = 'BM';
  146.       EXT_ibm = 'IBM';
  147.  
  148. (* var Bitmap could be an Array of Byte  or a pointer (MUST allocated !)   *)
  149. (* Some of the procedure work with Heap-memory. No Size checking included !*)
  150.  
  151. (******************************* PBM ***************************************)
  152. (* Put Planar Bitmap from System RAM to Pos.(X,Y).                         *)
  153. procedure x_put_pbm(X,Y:Word;var Bitmap);
  154. (* Put Planar Bitmap from System RAM to Pos.(X,Y) by skipping all 0-Pixel. *)
  155. procedure x_put_masked_pbm(X,Y:Word;var Bitmap);
  156. (* All put procedures with clipping.                                       *)
  157. procedure x_put_pbm_clipy(X,Y:Word;Var Bitmap);
  158. procedure x_put_pbm_clipx(X,Y:Word;Var Bitmap);
  159. procedure x_put_pbm_clipxy(X,Y:Word;Var Bitmap);
  160. procedure x_put_masked_pbm_clipy(X,Y:Word;Var Bitmap);
  161. procedure x_put_masked_pbm_clipx(X,Y:Word;Var Bitmap);
  162. procedure x_put_masked_pbm_clipxy(X,Y:Word;Var Bitmap);
  163.  
  164. (* Copy Planar Bitmap from Pos.(X1,Y1,X2,Y2) to System Ram.                *)
  165. procedure x_get_pbm(X1,Y1,X2,Y2:Word;var Bitmap);
  166.  
  167. (* Return the Memory for the Bitmap to store in System Ram.                *)
  168. function  x_pbm_size(x1,y1,x2,y2:Word):Word;
  169. function  x_sizeof_pbm(var BitMap):Word;
  170. procedure x_get_pbm_sizeXY(var x,y:Word;var Bitmap);
  171.  
  172. (* Save Planar Bitmap to File with Name.   Name with .pbm automatical      *)
  173. procedure x_save_pbm(var Name:String;var Bitmap);
  174. (* Load Planar Bitmap from File with Name.                                   *)
  175. procedure x_load_pbm(var Name:String;var Bitmap);
  176.  
  177. procedure x_load_put_pbm(X,Y:Word;Name:String);
  178. procedure x_get_save_pbm(X1,Y1,X2,Y2:Word;Name:String);
  179.  
  180. (* Converted Linear Bitmap to Planar Bitmap. True,if succesful.            *)
  181. function  x_lbm_to_pbm(var src_bm,dest_pbm):Boolean;
  182. (* Converted Planar Bitmap to Linear Bitmap. True,if succesful.            *)
  183. function  x_pbm_to_lbm(var src_pbm,dest_lbm):Boolean;
  184.  
  185. (******************************* LBM ***************************************)
  186. procedure x_save_lbm(var Name:String;var Bitmap);
  187. procedure x_load_lbm(var Name:String;var Bitmap);
  188. function  x_lbm_size(x1,y1,x2,y2:Word):Word;
  189. function  x_sizeof_lbm(var BitMap):Word;
  190.  
  191. (**************************** PCX -> LBM ***********************************
  192.  * PCXVIEW - by Lee Hamel (Patch), hamell@cx.pdx.edu, *Avalanche* coder    *
  193.  * July 14th, 1993                                                         *
  194.  ***************************************************************************
  195.  * converted to TP/asm by Christian Harms , harms@129.69.212.10  (or .13)  *
  196.  ***************************************************************************
  197.  
  198.    Limitations : max_PCX-filesize : 65 kB
  199.                  Bitmapsize       : 255x255 pixel                          *)
  200.  
  201.  
  202. (* If the size=0, then it isn't a 256-Color PCX-pictures or the image size
  203.    is to big for later converting in pbm.                                  *)
  204. function x_get_PCX_Size(Name:String):Word;
  205.  
  206. (* Load the pcx-image and encode into Bitmap as lbm.                       *)
  207. (* True, if encoding ok.                                                   *)
  208. function x_Load_PCX_as_LBM(Name:String;Var Bitmap):Boolean;
  209.  
  210.  
  211. (******************************* CBM ***************************************)
  212. (* Converted Planar Bitmap into Compiled Bitmap                            *)
  213. procedure x_pbm_to_cbm(logical_width:Word;Var pbm,cbm);
  214. (* Return the used size of the cbm from the source pbm.                    *)
  215. function  x_sizeof_cpbm (logical_width:Word;Var pbm):Word;
  216. (* Put Compiled Bitmap from System RAM to Pos (X,Y)  only as masked version*)
  217. procedure x_put_cbm(XPos,YPos:Word;Var Sprite);
  218.  
  219.  
  220. (******************************* IBM ***************************************)
  221. (* Converted Planar Bitmap into Interpreted Bitmap                            *)
  222. procedure x_pbm_to_ibm(Var pbm,ibm);
  223. (* Return the used size of the ibm from the source pbm.                    *)
  224. function  x_sizeof_ipbm (Var pbm):Word;
  225. (* Put Interpreted Bitmap from System RAM to Pos (X,Y) .                      *)
  226. procedure x_put_ibm(x,y:WOrd;Var ibm);
  227. (* Put Interpreted Bitmap from System RAM to Pos (X,Y) .                      *)
  228. procedure x_put_masked_ibm(X,Y:Word;Var ibm);
  229. (* Load Interpreted Bitmap from File with Name.                                   *)
  230. procedure x_load_ibm(var Name:String;var Bitmap);
  231.  
  232.  
  233. (******************************* VBM ***************************************)
  234. (* Converted Linear Bitmap into Video Bitmap                               *)
  235. function  x_lbm_to_vbm(Var lbm;Var VramStart:Word):Pointer;
  236. procedure x_put_masked_vbm(X,Y:Word;var SrcVBM);
  237. procedure x_put_masked_vbm_clipx(X,Y:Word;Var SrcVBM);
  238. procedure x_put_masked_vbm_clipy(X,Y:Word;Var SrcVBM);
  239. procedure x_put_masked_vbm_clipxy(X,Y:Word;Var SrcVBM);
  240.  
  241. implementation
  242.  
  243. uses X_Const,X_Main,X_FileIO,crt;
  244.  
  245. const ColumnMask :Array[0..3] of Byte = ($11,$22,$44,$88);
  246.  
  247. (* ----------------------------------------------------------------------   *)
  248. (* x_put_masked_pbm - mask write a planar bitmap from system ram to video ram  *)
  249. (* all zero source bitmap bytes indicate destination byte to be left unchanged *)
  250. (*                                                                          *)
  251. (* Source Bitmap structure:                                                 *)
  252. (*                                                                          *)
  253. (*  Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., *)
  254. (*  Bitmap data (plane 2)..,Bitmap data (plane 3)..                         *)
  255. (*                                                                          *)
  256. (*  note width is in bytes ie lots of 4 pixels                              *)
  257. (*                                                                          *)
  258. (*  x_put_masked_pbm(X,Y,Bitmap)                                            *)
  259. (*                                                                          *)
  260. (*                                                                          *)
  261. (* LIMITATIONS: No clipping is supported                                    *)
  262. (*              Only supports bitmaps with widths which are a multiple of   *)
  263. (*              4 pixels                                                    *)
  264. (*                                                                          *)
  265. (* Written by Themie Gouthas                                                *)
  266. (*----------------------------------------------------------------------    *)
  267. procedure x_put_masked_pbm(X,Y:Word;var Bitmap); assembler;
  268. var Plane,BMHeight:Byte;
  269.     LineInc:Word;
  270. asm;
  271.     push  ds
  272.     cld
  273.     mov   ax,SCREEN_SEG
  274.     mov   es,ax
  275.     mov   ax,Y                        (* Calculate dest screen row           *)
  276.     mov   bx,ScrnLogicalByteWidth     (*  by mult. dest Y coord by Screen    *)
  277.     mul   bx                          (*  width then adding screen offset    *)
  278.     mov   di,ScreenOfs                (*  store result in DI                 *)
  279.     add   di,ax
  280.     mov   cx,X                        (* Load X coord into CX and make a     *)
  281.     mov   dx,cx                       (*  copy in DX                         *)
  282.     shr   dx,2                        (* Find starting byte in dest row      *)
  283.     add   di,dx                       (*  add to DI giving screen offset of  *)
  284.                       (*  first pixel's byte                 *)
  285.     lds   si,dword ptr[Bitmap]        (* DS:SI -> Bitmap data                *)
  286.     lodsw                             (* Al = B.M. width (bytes) AH = B.M.   *)
  287.                       (*  height                             *)
  288.     mov   BMHeight,ah                 (* Save source bitmap dimensions       *)
  289.     xor   ah,ah                       (* LineInc = bytes to the begin.       *)
  290.     sub   bx,ax                       (*  of bitmaps next row on screen      *)
  291.     mov   LineInc,bx
  292.     mov   bh,al                       (* Use bh as column loop count         *)
  293.     and   cx,0003h                    (* mask X coord giving plane of 1st    *)
  294.                       (* bitmap pixel(zero CH coincidentally)*)
  295.     mov   ah,11h                      (* Init. mask for VGA plane selection  *)
  296.     shl   ah,cl                       (* Shift for starting pixel plane      *)
  297.     mov   dx,SC_INDEX                 (* Prepare VGA for cpu to video writes *)
  298.     mov   al,MAP_MASK
  299.     out   dx,al
  300.     inc   dx
  301.     mov   Plane,4                     (* Set plane counter to 4              *)
  302. @@PlaneLoop:
  303.     push  di                          (* Save bitmap's start dest. offset    *)
  304.     mov   bl,BMHeight                 (* Reset row counter (BL)              *)
  305.     mov   al,ah
  306.     out   dx,al                       (* set vga write plane                 *)
  307. @@RowLoop:
  308.     mov   cl,bh                       (* Reset Column counter cl             *)
  309. @@ColLoop:
  310.     lodsb                             (* Get next source bitmap byte         *)
  311.     or    al,al                       (* If not zero then write to dest.     *)
  312.     jz    @@NoPixel                   (* otherwise skip to next byte         *)
  313.     mov   es:[di],al
  314. @@NoPixel:
  315.     inc   di
  316.     loop  @@ColLoop                   (* loop if more columns left           *)
  317.     add   di,LineInc                  (* Move to next row                    *)
  318.     dec   bl                          (* decrement row counter               *)
  319.     jnz   @@RowLoop                   (* Jump if more rows left              *)
  320.     pop   di                          (* Restore bitmaps start dest byte     *)
  321.     rol   ah,1                        (* Shift mask for next plane           *)
  322.     adc   di,0                        (* If wrapped increment dest address   *)
  323.     dec   Plane                       (* Decrement plane counter             *)
  324.     jnz   @@PlaneLoop                 (* Jump if more planes left            *)
  325.  
  326.     pop   ds                          (* restore data segment                *)
  327. end;
  328.  
  329.  
  330. (* ----------------------------------------------------------------------   *)
  331. (* x_put_pbm - Write a planar bitmap from system ram to video ram           *)
  332. (*                                                                          *)
  333. (* Source Bitmap structure:                                                 *)
  334. (*                                                                          *)
  335. (*  Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).,*)
  336. (*  Bitmap data (plane 2)..,Bitmap data (plane 3)..                         *)
  337. (*                                                                          *)
  338. (*  note width is in bytes ie lots of 4 pixels                              *)
  339. (*                                                                          *)
  340. (*  x_put_pbm(X,Y,Bitmap)                                                   *)
  341. (*                                                                          *)
  342. (*                                                                          *)
  343. (* LIMITATIONS: No clipping is supported                                    *)
  344. (*              Only supports bitmaps with widths which are a multiple of   *)
  345. (*              4 pixels                                                    *)
  346. (* FEATURES   : Automatically selects REP MOVSB or REP MOVSW  depending on  *)
  347. (*              source bitmap width, by modifying opcode (*-).              *)
  348. (*                                                                          *)
  349. (* Written by Themie Gouthas                                                *)
  350. (* ----------------------------------------------------------------------   *)
  351. procedure x_put_pbm(X,Y:Word;var Bitmap);  assembler;
  352. var Plane,BMHeight:Byte;
  353.     LineInc       :Word;
  354. asm;
  355.     push  ds
  356.     cld
  357.     mov   ax,SCREEN_SEG
  358.     mov   es,ax
  359.     mov   ax,Y                        (* Calculate dest screen row           *)
  360.     mov   bx,ScrnLogicalByteWidth     (*  by mult. dest Y coord by Screen    *)
  361.     mul   bx                          (*  width then adding screen offset    *)
  362.     mov   di,ScreenOfs                (*  store result in DI                 *)
  363.     add   di,ax
  364.     mov   cx,X                        (* Load X coord into CX and make a     *)
  365.     mov   dx,cx                       (*  copy in DX                         *)
  366.     shr   dx,1;shr dx,1               (* Find starting byte in dest row      *)
  367.     add   di,dx                       (*  add to DI giving screen offset of  *)
  368.                       (*  first pixel's byte                 *)
  369.     lds   si,dword ptr[Bitmap]                   (* DS:SI -> Bitmap data                *)
  370.     lodsw                             (* Al = B.M. width (bytes) AH = B.M.   *)
  371.                       (*  height                             *)
  372.     mov   BMHeight,ah                 (* Save source bitmap dimensions       *)
  373.     xor   ah,ah                       (* LineInc = bytes to the begin.       *)
  374.     sub   bx,ax                       (*  of bitmaps next row on screen      *)
  375.     mov   LineInc,bx
  376.     mov   bh,al
  377.                       (* Self Modifying, Shame, shame shame..*)
  378.     and   cx,0003h                    (* mask X coord giving plane of 1st    *)
  379.                       (* bitmap pixel(zero CH coincidentally)*)
  380.     mov   ah,11h                      (* Init. mask for VGA plane selection  *)
  381.     shl   ah,cl                       (* Shift for starting pixel plane      *)
  382.     mov   dx,SC_INDEX                 (* Prepare VGA for cpu to video writes *)
  383.     mov   al,MAP_MASK
  384.     out   dx,al
  385.     inc   dx
  386.     mov   Plane,4                     (* Set plane counter to 4              *)
  387. @@PlaneLoop:
  388.     push  di
  389.     mov   bl,BMHeight
  390.     mov   al,ah
  391.     out   dx,al
  392. @@RowLoop:
  393.     mov   cl,bh
  394.     shr   cl,1
  395.     rep   movsw                       (* Copy a complete row for curr plane  *)
  396.     adc   cl,0
  397.     rep   movsb
  398.     add   di,LineInc                  (* Move to next row                    *)
  399.     dec   bl                          (* decrement row counter               *)
  400.     jnz   @@RowLoop                   (* Jump if more rows left              *)
  401.     pop   di                          (* Restore bitmaps start dest byte     *)
  402.     rol   ah,1                        (* Shift mask for next plane           *)
  403.     adc   di,0                        (* If wrapped increment dest address   *)
  404.     dec   Plane                       (* Decrement plane counter             *)
  405.     jnz   @@PlaneLoop                 (* Jump if more planes left            *)
  406.  
  407.     pop   ds                          (* restore data segment                *)
  408. end;
  409.  
  410. (* ----------------------------------------------------------------------   *)
  411. (* x_get_pbm - Read a planar bitmap to system ram from video ram            *)
  412. (*                                                                          *)
  413. (* Source Bitmap structure:                                                 *)
  414. (*                                                                          *)
  415. (*  Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).,*)
  416. (*  Bitmap data (plane 2)..,Bitmap data (plane 3)..                         *)
  417. (*                                                                          *)
  418. (*  note width is in bytes ie lots of 4 pixels                              *)
  419. (*                                                                          *)
  420. (*  x_get_pbm(X1,Y1,X2,Y2,Bitmap)                                           *)
  421. (*                                                                          *)
  422. (*                                                                          *)
  423. (* LIMITATIONS: No clipping is supported                                    *)
  424. (*              Only supports bitmaps with widths which are a multiple of   *)
  425. (*              4 pixels                                                    *)
  426. (*              X2-X1<256, Y2-Y1<256                                        *)
  427. (* FEATURES   : Automatically selects REP MOVSB or REP MOVSW  depending on  *)
  428. (*              source bitmap width, by modifying opcode (*-).              *)
  429. (*                                                                          *)
  430. (* Written by Themie Gouthas                                                *)
  431. (* ----------------------------------------------------------------------   *)
  432. procedure x_get_pbm(X1,Y1,X2,Y2:Word;var Bitmap); assembler;
  433. var Plane,SrcWidth,SrcHeight:Byte;
  434.     LineInc:Word;
  435. asm;
  436.     mov   ax,X2                       (* Store X2 in SrcWidth . *)
  437.     sub   ax,X1
  438.     add   ax,3
  439.     shr   ax,1;shr ax,1
  440.     mov   SrcWidth,al
  441.     mov   ax,Y2                       (* Store Y2 in SrcHeight . *)
  442.     sub   ax,Y1
  443.     mov   SrcHeight,al
  444.  
  445.     push  ds
  446.     cld
  447.  
  448.     mov   ax,Y1                       (* Calculate screen row                *)
  449.     mov   bx,ScrnLogicalByteWidth     (*  by mult. Y coord by Screen         *)
  450.     mul   bx                          (*  width then adding screen offset    *)
  451.     mov   si,ScreenOfs                (*  store result in SI                 *)
  452.     add   si,ax
  453.     mov   cx,X1                       (* Load X coord into CX and make a     *)
  454.     mov   dx,cx                       (*  copy in DX                         *)
  455.     shr   dx,1;shr dx,1               (* Find starting byte in screen row    *)
  456.     add   si,dx                       (*  add to SI giving screen offset of  *)
  457.                       (*  first pixel's byte                 *)
  458.     mov   ax,SCREEN_SEG
  459.     mov   ds,ax
  460.     les   di,dword ptr [Bitmap]                   (* ES:DI -> Bitmap data                *)
  461.     mov   al,SrcWidth
  462.     mov   ah,SrcHeight
  463.     stosw                             (* Al = B.M. width (bytes) AH = B.M.   *)
  464.                       (*  height                             *)
  465.     xor   ah,ah                       (* LineInc = bytes to the begin.       *)
  466.     sub   bx,ax                       (*  of bitmaps next row on screen      *)
  467.     mov   LineInc,bx
  468.     mov   bh,al
  469.                       (* Self Modifying, Shame, shame shame..*)
  470.     and   cx,0003h                    (* mask X coord giving plane of 1st    *)
  471.                       (* bitmap pixel(zero CH coincidentally)*)
  472.     mov   ah,11h                      (* Init. mask for VGA plane selection  *)
  473.     shl   ah,cl                       (* Shift for starting pixel plane      *)
  474.     mov   dx,GC_INDEX                 (* Prepare VGA for cpu to video reads  *)
  475.     mov   al,READ_MAP
  476.     out   dx,al
  477.     inc   dx
  478.     mov   Plane,4                     (* Set plane counter (BH) to 4         *)
  479.     mov   al,cl
  480. @@PlaneLoop:
  481.     push  si
  482.     mov   bl,SrcHeight
  483.     out   dx,al
  484. @@RowLoop:
  485.     mov   cl,bh
  486.     shr   cl,1
  487.     rep   movsw                       (* Copy a complete row for curr plane  *)
  488.     adc   cl,0
  489.     rep   movsb
  490.     add   si,LineInc                  (* Move to next row                    *)
  491.     dec   bl                          (* decrement row counter               *)
  492.     jnz   @@RowLoop                   (* Jump if more rows left              *)
  493.     pop   si                          (* Restore bitmaps start dest byte     *)
  494.  
  495.     inc   al                          (* Select next plane to read from      *)
  496.     and   al,3                        (*                                     *)
  497.  
  498.     rol   ah,1                        (* Shift mask for next plane           *)
  499.     adc   si,0                        (* If wrapped increment dest address   *)
  500.     dec   Plane                       (* Decrement plane counter             *)
  501.     jnz   @@PlaneLoop                 (* Jump if more planes left            *)
  502.  
  503.     pop   ds                          (* restore data segment                *)
  504. end;
  505.  
  506.  
  507. (* global clipping variables *)
  508. var TopBound,BottomBound,LeftBound,RightBound:Word;
  509.  
  510. (*
  511.   These functions provide the fastest possible bitmap blts from system ram to
  512.   to video and further, the single bitmap is applicable to all pixel
  513.   allignments. The masked functions do not need separate masks since all non
  514.   zero pixels are considered to be masking pixels, hence if a pixel is 0 the
  515.   corresponding screen destination pixel is left unchanged.
  516. *)
  517.  
  518. (*----------------------------------------------------------------------    *)
  519. (* x_put_masked_pbm_clipx - mask write a planar bitmap from system ram to video *)
  520. (*            ram all zero source bitmap bytes indicate destination *)
  521. (*            byte to be left unchanged.                          *)
  522. (*                       Performs clipping in x directions. similar to      *)
  523. (*                "x_put_masked_pbm".                                 *)
  524. (*                                                                          *)
  525. (* See Also:  x_put_masked_pbm, x_put_masked_pbm_clipxy                     *)
  526. (*                                                                          *)
  527. (* Clipping region variables: LeftClip,RightClip                            *)
  528. (*                                                                          *)
  529. (* Written by Themie Gouthas                                                *)
  530. (*                                                                          *)
  531. (* This code is a SLOW hack, any better ideas are welcome                   *)
  532. (*----------------------------------------------------------------------    *)
  533. procedure x_put_masked_pbm_clipx(X,Y:Word;Var Bitmap);   assembler;
  534. Var   Plane:Byte;
  535.       CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:Word;
  536. asm
  537.         push  si
  538.         push  di
  539.         push  ds
  540.     cld
  541.  
  542.     les   si,[Bitmap]                 (* Point ES:SI to start of bitmap *)
  543.  
  544.     xor   ax,ax                       (* Clear AX                       *)
  545.     mov   [CType],ax                  (* Clear Clip type descision var  *)
  546.     mov   al,byte ptr es:[si]         (* AX=width(byte coverted to word)*)
  547.  
  548.  
  549.     mov   di,[X]                      (* DI = X coordinate of dest      *)
  550.     mov   cx,di                       (* copy to CX                     *)
  551.     sar   di,2                        (* convert to offset in row       *)
  552.  
  553.  
  554.     (**** CLIP PROCESSING FOR LEFT CLIP BORDER ******************)
  555.  
  556.     mov   dx,[LeftClip]               (* Is X Coord to the right of     *)
  557.     sub   dx,di                       (* LeftClip ?                     *)
  558.     jle   @@NotLeftClip               (* Yes! => no left clipping       *)
  559.     cmp   dx,ax                       (* Is dist of X Coord from        *)
  560.     jnl   @@NotVisible                (* ClipLeft > Width ? yes => the  *)
  561.                       (* bitmap is not visible          *)
  562.     add   di,dx
  563.     mov   [LeftSkip],dx
  564.     mov   [DataInc],dx
  565.     sub   ax,dx
  566.     mov   [CType],1
  567.     jmp   @@HorizClipDone
  568.  
  569.     (*** EXIT FOR COMPLETELY OBSCURED P.B.M's *********************)
  570.  
  571. @@NotVisible:
  572.     mov   ax,1
  573.     pop   ds                          (* restore data segment           *)
  574.     pop   di                          (* restore registers              *)
  575.     pop   si
  576.         jmp   @Ok
  577.  
  578.     (**** CLIP PROCESSING FOR RIGHT CLIP BORDER ******************)
  579.  
  580. @@NotLeftClip:
  581.     mov   dx,[RightClip]
  582.     sub   dx,di
  583.     js    @@NotVisible
  584.     mov   [LeftSkip],0
  585.     mov   [DataInc],0
  586.     cmp   dx,ax
  587.     jge   @@HorizClipDone             (* was jg *)
  588.     inc   dx
  589.     sub   ax,dx
  590.     mov   [DataInc],ax
  591.     mov   ax,dx
  592.     mov   [CType],-1
  593.  
  594. @@HorizClipDone:
  595.  
  596.     xor   bh,bh
  597.     mov   bl,byte ptr es:[si+1]       (* BX = height                    *)
  598.  
  599.     mov   [Width],ax                  (* Save width and height of clipped *)
  600.     mov   [Height],bx                 (*  image                         *)
  601.  
  602.  
  603.     add   si,2                        (* Skip dimension bytes in source *)
  604.     add   si,[LeftSkip]               (* Skip pixels in front of row that *)
  605.                       (*  are clipped                   *)
  606.  
  607.  
  608.     mov   bx,[ScrnLogicalByteWidth]   (* Set BX to Logical Screen Width *)
  609.     mov   dx,bx                       (* BX - Width of image = No. bytes*)
  610.     sub   dx,ax                       (*  to first byte of next screen  *)
  611.     mov   [LineInc],dx                (*  row.                          *)
  612.  
  613.     mov   ax,[Y]                      (* Calculate screen start row     *)
  614.     mul   bx                          (*  then adding screen offset     *)
  615.     add   di,ax
  616.     add   di,[ScreenOfs]
  617.     mov   ax,es                       (* copy ES to DS                  *)
  618.     mov   ds,ax
  619.     mov   ax,SCREEN_SEG               (* Point ES to VGA segment        *)
  620.     mov   es,ax
  621.  
  622.     and   cx,3
  623.     mov   ah,11h                      (* Set up initial plane mask      *)
  624.     shl   ah,cl
  625.  
  626.     mov   dx,SC_INDEX                 (* Prepare VGA for cpu to video writes *)
  627.     mov   al,MAP_MASK
  628.     out   dx,al
  629.     inc   dx
  630.     mov   [Plane],4                   (* Set plane counter to 4         *)
  631.     mov   bh,byte ptr [Width]         (* set bh to width for fast looping *)
  632. @@PlaneLoop:
  633.     push  di               (* Save bitmap's start dest. offset *)
  634.     mov   bl,byte ptr [Height]        (* Reset row counter (BL)         *)
  635.     mov   al,ah
  636.     out   dx,al                       (* set vga write plane            *)
  637. @@RowLoop:
  638.     mov   cl,bh                       (* Reset Column counter cl        *)
  639.     jcxz  @@NoWidth
  640. @@ColLoop:
  641.     lodsb                          (* Get next source bitmap byte    *)
  642.     or    al,al                       (* If not zero then write to dest.*)
  643.     jz    @@NoPixel                   (* otherwise skip to next byte    *)
  644.     mov   es:[di],al
  645. @@NoPixel:
  646.     inc   di
  647.     loop @@ColLoop
  648. @@NoWidth:
  649.     add   si,[DataInc]                (* Move to next source row        *)
  650.     add   di,[LineInc]                (* Move to next screen row        *)
  651.     dec   bl                          (* decrement row counter          *)
  652.     jnz   @@RowLoop                   (* Jump if more rows left         *)
  653.     pop   di                          (* Restore bitmaps start dest byte*)
  654.     rol   ah,1                  (* Shift mask for next plane      *)
  655.  
  656.     (* Plane Transition (A HACK but it works!)                          *)
  657.  
  658.     jnb   @@Nocarry                   (* Jump if not plane transition   *)
  659.     mov   bl,ah                       (* Save Plane Mask                *)
  660.     mov   ax,[CType]                  (* set AX to clip type inc variable *)
  661.     add   bh,al                       (* Update advancing variables     *)
  662.     sub   [DataInc],ax                (*                                *)
  663.     sub   [LineInc],ax                (*                                *)
  664.     cmp   al,0                        (* What type of clip do we have   *)
  665.     mov   ah,bl                       (*   restore Plane mask           *)
  666.     jg    @@RightAdvance              (* jump on a right clip!          *)
  667.     inc   di                          (* otherwise increment DI         *)
  668.     jmp   @@Nocarry
  669. @@RightAdvance:
  670.     dec si
  671. @@Nocarry:
  672.     dec   [Plane]                     (* Decrement plane counter        *)
  673.     jnz   @@PlaneLoop                 (* Jump if more planes left       *)
  674.  
  675.     xor   ax,ax
  676.     pop   ds                          (* restore data segment           *)
  677.     pop   di                          (* restore registers              *)
  678.     pop   si
  679. @Ok:
  680. end;
  681.  
  682.  
  683. (*----------------------------------------------------------------------    *)
  684. (* x_put_masked_pbm_clipy - mask write a planar bitmap from system ram to video *)
  685. (*            ram all zero source bitmap bytes indicate destination   *)
  686. (*            byte to be left unchanged.                          *)
  687. (*                       Performs clipping in y direction. similar to       *)
  688. (*                "x_put_masked_pbm".                                 *)
  689. (*
  690. (* See Also:  x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipy *)
  691. (*                                                                          *)
  692. (* Clipping region variables: TopClip,BottomClip                            *)
  693. (*                                                                          *)
  694. (* Written by Themie Gouthas                                                *)
  695. (*----------------------------------------------------------------------    *)
  696. procedure x_put_masked_pbm_clipy(X,Y:Word;Var Bitmap);   assembler;
  697. var Width,Height,TopRow,LineInc,PlaneInc:Word;
  698. asm
  699.     push  si
  700.     push  di
  701.     push  ds
  702.     cld
  703.  
  704.     les   si,[Bitmap]
  705.  
  706.     xor   bh,bh
  707.     mov   bl,byte ptr es:[si+1]       (* BX = height                    *)
  708.  
  709.     xor   ah,ah
  710.     mov   al,byte ptr es:[si]         (* AX = width                     *)
  711.  
  712.     mov   cx,ax                       (* Save AX                        *)
  713.     mul   bx                          (* AX = AX*BX = bytes/plane       *)
  714.     mov   [PlaneInc],ax               (*  save as PlaneInc              *)
  715.     mov   ax,cx                       (* Restore AX                     *)
  716.  
  717.     mov   di,[X]
  718.     mov   cx,di
  719.     shr   di,2
  720.  
  721.     (**** CLIP PROCESSING FOR TOP CLIP BORDER *********************)
  722.  
  723.     mov   dx,[TopClip]            (* Compare u.l. Y coord with Top      *)
  724.     sub   dx,[Y]                  (* clipping border                    *)
  725.     jle   @@NotTopClip            (* jump if VBM not clipped from above *)
  726.     cmp   dx,bx
  727.     jnl   @@NotVisible            (* jump if VBM is completely obscured *)
  728.     mov   [TopRow],dx
  729.     sub   bx,dx
  730.     add   [Y],dx
  731.     jmp   @@VertClipDone
  732.  
  733.     (*** EXIT FOR COMPLETELY OBSCURED P.B.M's *********************)
  734.  
  735. @@NotVisible:
  736.     mov   ax,1
  737.     pop   ds                          (* restore data segment           *)
  738.     pop   di                          (* restore registers              *)
  739.     pop   si
  740.         jmp   @Ok
  741.  
  742.     (**** CLIP PROCESSING FOR BOTTOM CLIP BORDER ******************)
  743.  
  744. @@NotTopClip:
  745.     mov   dx,[BottomClip]
  746.     sub   dx,[Y]
  747.     js    @@NotVisible
  748.     mov   [TopRow],0
  749.     cmp   dx,bx
  750.     jg    @@VertClipDone
  751.     inc   dx
  752.     mov   bx,dx
  753.  
  754. @@VertClipDone:
  755.  
  756.     mov   [Width],ax
  757.     mov   [Height],bx                 (* Calculate relative offset in data *)
  758.     mul   [TopRow]                    (*  of first visible scanline     *)
  759.     add   ax,2                        (* Skip dimension bytes in source *)
  760.     add   si,ax                       (* Skip top rows that arent visible *)
  761.  
  762.  
  763.     mov   ax,[Y]                      (* Calculate screen row           *)
  764.     mov   bx,[ScrnLogicalByteWidth]   (*  by mult. Y coord by Screen    *)
  765.     mul   bx                          (*  width then adding screen offset *)
  766.     add   di,ax
  767.     add   di,[ScreenOfs]
  768.     sub   bx,[Width]                  (* calculate difference from end of *)
  769.     mov   [LineInc],bx                (* b.m. in curr line to beginning of *)
  770.                       (* b.m. on next scan line         *)
  771.     mov   ax,es                       (* copy ES to DS                  *)
  772.     mov   ds,ax
  773.     mov   ax,SCREEN_SEG               (* Point ES to VGA segment        *)
  774.     mov   es,ax
  775.  
  776.     mov   ah,11h                      (* Set up initial plane mask      *)
  777.     and   cx,3
  778.     shl   ah,cl
  779.  
  780.     mov   dx,SC_INDEX                 (* Prepare VGA for cpu to video writes *)
  781.     mov   al,MAP_MASK
  782.     out   dx,al
  783.     inc   dx
  784.     mov   bh,4                        (* Set plane counter to 4         *)
  785. @@PlaneLoop:
  786.     push  di               (* Save bitmap's start dest. offset *)
  787.     push  si                          (* Save Bitmaps data offset       *)
  788.     mov   bl,byte ptr [Height]        (* Reset row counter (BL)         *)
  789.     mov   al,ah
  790.     out   dx,al                       (* set vga write plane            *)
  791. @@RowLoop:
  792.     mov   cl,byte ptr [Width]         (* Reset Column counter cl        *)
  793. @@ColLoop:
  794.     lodsb                             (* Get next source bitmap byte    *)
  795.     or    al,al                       (* If not zero then write to dest.*)
  796.     jz    @@NoPixel                   (* otherwise skip to next byte    *)
  797.     mov   es:[di],al
  798. @@NoPixel:
  799.     inc   di
  800.     loop  @@ColLoop                   (* loop if more columns left      *)
  801.     add   di,[LineInc]                (* Move to next row               *)
  802.     dec   bl                          (* decrement row counter          *)
  803.     jnz   @@RowLoop                   (* Jump if more rows left         *)
  804.     pop   si                          (* Restore SI and set to offset of*)
  805.     add   si,[PlaneInc]               (* first vis pixel in next plane data *)
  806.     pop   di                          (* Restore bitmaps start dest byte*)
  807.     rol   ah,1                        (* Shift mask for next plane      *)
  808.     adc   di,0                        (* if carry increment screen offset *)
  809.     dec   bh                          (* Decrement plane counter        *)
  810.     jnz   @@PlaneLoop                 (* Jump if more planes left       *)
  811.  
  812.     xor   ax,ax
  813.     pop   ds                          (* restore data segment           *)
  814.     pop   di                          (* restore registers              *)
  815.     pop   si
  816. @Ok:
  817. end;
  818.  
  819. (*----------------------------------------------------------------------    *)
  820. (* x_put_masked_pbm_clipxy - Write a planar bitmap from system ram to video *)
  821. (*                    RAM with clipping in x and y directions. similar to   *)
  822. (*             "x_put_masked_pbm".                                    *)
  823. (*                                                                          *)
  824. (* See Also: x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipxy *)
  825. (*                                                                          *)
  826. (* Clipping region variables: LeftClip,RightClip,TopClip,BottomClip         *)
  827. (*                                                                          *)
  828. (*                                                                          *)
  829. (* Written by Themie Gouthas                                                *)
  830. (*----------------------------------------------------------------------    *)
  831. procedure x_put_masked_pbm_clipxy(X,Y:Word;Var Bitmap);   assembler;
  832. Var Plane:Byte;
  833.     CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:Word;
  834. asm
  835.     push  si
  836.     push  di
  837.     push  ds
  838.     cld
  839.  
  840.     les   si,[Bitmap]
  841.  
  842.     xor   ax,ax
  843.     mov   [CType],ax
  844.     mov   al,byte ptr es:[si]         (* AX = width                     *)
  845.     xor   bh,bh
  846.     mov   bl,byte ptr es:[si+1]       (* BX = height                    *)
  847.  
  848.     mov   cx,ax                       (* Save AX                        *)
  849.     mul   bx                          (* AX = AX*BX = bytes/plane       *)
  850.     mov   [PlaneInc],ax               (*  save as PlaneInc              *)
  851.     mov   ax,cx                       (* Restore AX                     *)
  852.  
  853.  
  854.     mov   di,[X]                      (* DI = X coordinate of dest.     *)
  855.     mov   cx,di                       (* save in CX                     *)
  856.     sar   di,2                        (* convert to address byte        *)
  857.  
  858.  
  859.     (**** CLIP PROCESSING FOR TOP CLIP BORDER ********************)
  860.  
  861.     mov   dx,[TopClip]            (* Compare u.l. Y coord with Top      *)
  862.     sub   dx,[Y]                  (* clipping border                    *)
  863.     jle   @@NotTopClip            (* jump if VBM not clipped from above *)
  864.     cmp   dx,bx
  865.     jnl   @@NotVisible            (* jump if VBM is completely obscured *)
  866.     mov   [TopRow],dx
  867.     sub   bx,dx
  868.     add   [Y],dx
  869.     jmp   @@VertClipDone
  870.  
  871.     (*** EXIT FOR COMPLETELY OBSCURED P.B.M's *********************)
  872.  
  873. @@NotVisible:
  874.     mov   ax,1
  875.     pop   ds                          (* restore data segment           *)
  876.     pop   di                          (* restore registers              *)
  877.     pop   si
  878.         jmp   @OK
  879.  
  880.     (**** CLIP PROCESSING FOR BOTTOM CLIP BORDER ******************)
  881.  
  882. @@NotTopClip:
  883.     mov   dx,[BottomClip]
  884.     sub   dx,[Y]
  885.     js    @@NotVisible
  886.     mov   [TopRow],0
  887.     cmp   dx,bx
  888.     jg    @@VertClipDone
  889.     inc   dx
  890.     mov   bx,dx
  891.  
  892. @@VertClipDone:
  893.  
  894.     (**** CLIP PROCESSING FOR LEFT CLIP BORDER ********************)
  895.  
  896.     mov   dx,[LeftClip]
  897.     sub   dx,di
  898.     jle   @@NotLeftClip
  899.     cmp   dx,ax
  900.     jnl   @@NotVisible
  901.  
  902.     add   di,dx
  903.     mov   [LeftSkip],dx
  904.     mov   [DataInc],dx
  905.     sub   ax,dx
  906.     mov   [CType],1
  907.     jmp   @@HorizClipDone
  908.  
  909.     (**** CLIP PROCESSING FOR RIGHT CLIP BORDER *******************)
  910.  
  911. @@NotLeftClip:
  912.     mov   dx,[RightClip]
  913.     sub   dx,di
  914.     js    @@NotVisible
  915.     mov   [LeftSkip],0
  916.     mov   [DataInc],0
  917.     cmp   dx,ax
  918.         jge   @@HorizClipDone       (* was jg                         *)
  919.     inc   dx
  920.     sub   ax,dx
  921.     mov   [DataInc],ax
  922.     mov   ax,dx
  923.  
  924.  
  925.     mov   [CType],-1
  926.  
  927. @@HorizClipDone:
  928.  
  929.     mov   [Width],ax                  (* Save width and height of clipped *)
  930.     mov   [Height],bx                 (*  image                         *)
  931.  
  932.     add   ax,[DataInc]                (* AX = original width of image   *)
  933.     mul   [TopRow]                    (* Calculate bytes in clipped top *)
  934.     add   si,ax                  (*  rows                          *)
  935.     add   si,2                        (* Skip dimension bytes in source *)
  936.     add   si,[LeftSkip]               (* Skip pixels in front of row that *)
  937.                       (*  are clipped                   *)
  938.  
  939.     mov   bx,[ScrnLogicalByteWidth]   (* Set BX to Logical Screen Width *)
  940.     mov   dx,bx                       (* BX - Width of image = No. bytes*)
  941.     sub   dx,[Width]                  (*  to first byte of next screen  *)
  942.     mov   [LineInc],dx                (*  row.                          *)
  943.  
  944.     mov   ax,[Y]                      (* Calculate screen start row     *)
  945.     mul   bx                          (*  then adding screen offset     *)
  946.     add   di,ax
  947.     add   di,[ScreenOfs]
  948.     mov   ax,es                       (* copy ES to DS                  *)
  949.     mov   ds,ax
  950.     mov   ax,SCREEN_SEG               (* Point ES to VGA segment        *)
  951.     mov   es,ax
  952.  
  953.  
  954.  
  955.     and   cx,3
  956.     mov   ah,11h                      (* Set up initial plane mask      *)
  957.     shl   ah,cl
  958.  
  959.     mov   dx,SC_INDEX                 (* Prepare VGA for cpu to video writes *)
  960.     mov   al,MAP_MASK
  961.     out   dx,al
  962.     inc   dx
  963.     mov   [Plane],4                   (* Set plane counter to 4         *)
  964.     mov   bh,byte ptr [Width]         (* set bh to width for fast looping *)
  965. @@PlaneLoop:
  966.     push  di               (* Save bitmap's start dest. offset *)
  967.     push  si
  968.     mov   bl,byte ptr [Height]        (* Reset row counter (BL)         *)
  969.     mov   al,ah
  970.     out   dx,al                       (* set vga write plane            *)
  971. @@RowLoop:
  972.     mov   cl,bh                       (* Reset Column counter cl        *)
  973.     jcxz   @@NoWidth
  974. @@ColLoop:
  975.     lodsb                          (* Get next source bitmap byte    *)
  976.     or    al,al                       (* If not zero then write to dest.*)
  977.     jz    @@NoPixel                   (* otherwise skip to next byte    *)
  978.     mov   es:[di],al
  979. @@NoPixel:
  980.     inc   di
  981.     loop @@ColLoop
  982. @@NoWidth:
  983.     add   si,[DataInc]                (* Move to next source row        *)
  984.     add   di,[LineInc]                (* Move to next screen row        *)
  985.     dec   bl                          (* decrement row counter          *)
  986.     jnz   @@RowLoop                   (* Jump if more rows left         *)
  987.     pop   si                          (* Restore SI and set to offset of*)
  988.     add   si,[PlaneInc]               (* first vis pixel in next plane data *)
  989.     pop   di                          (* Restore bitmaps start dest byte*)
  990.     rol   ah,1                  (* Shift mask for next plane      *)
  991.  
  992.     (* Plane Transition (A HACK but it works!)                          *)
  993.  
  994.     jnb   @@Nocarry                   (* Jump if not plane transition   *)
  995.     mov   bl,ah                       (* Save Plane Mask                *)
  996.     mov   ax,[CType]                  (* set AX to clip type inc variable *)
  997.     add   bh,al                       (* Update advancing variables     *)
  998.     sub   [DataInc],ax                (*                                *)
  999.     sub   [LineInc],ax                (*                                *)
  1000.     cmp   al,0                        (* What type of clip do we have   *)
  1001.     mov   ah,bl                       (*   restore Plane mask           *)
  1002.     jg    @@RightAdvance              (* jump on a right clip!          *)
  1003.     inc   di                          (* otherwise increment DI         *)
  1004.     jmp   @@Nocarry
  1005. @@RightAdvance:
  1006.     dec   si
  1007. @@Nocarry:
  1008.     dec   [Plane]                     (* Decrement plane counter        *)
  1009.     jnz   @@PlaneLoop                 (* Jump if more planes left       *)
  1010.  
  1011.     xor   ax,ax
  1012.     pop   ds                          (* restore data segment           *)
  1013.     pop   di                          (* restore registers              *)
  1014.     pop   si
  1015. @OK:
  1016. end;
  1017.  
  1018.  
  1019.  
  1020.  
  1021. (*----------------------------------------------------------------------    *)
  1022. (* x_put_pbm_clipx - Write a planar bitmap from system ram to video ram     *)
  1023. (*                    with clipping in x and y directions. similar to       *)
  1024. (*             "x_put_pbm".                                           *)
  1025. (*                                                                          *)
  1026. (* See Also:  x_put_pbm_clip                                                *)
  1027. (*                                                                          *)
  1028. (*                                                                          *)
  1029. (* See Also:  x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipxy                    *)
  1030. (*                                                                          *)
  1031. (* Clipping region variables: LeftClip,RightClip                            *)
  1032. (*                                                                          *)
  1033. (* Written by Themie Gouthas                                                *)
  1034. (*                                                                          *)
  1035. (* This code is a SLOW hack, any better ideas are welcome                   *)
  1036. (*----------------------------------------------------------------------    *)
  1037. procedure x_put_pbm_clipx(X,Y:Word;Var Bitmap);   assembler;
  1038. var Plane:Byte;
  1039.     CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:Word;
  1040. asm
  1041.     push  si
  1042.     push  di
  1043.     push  ds
  1044.     cld
  1045.  
  1046.     les   si,[Bitmap]
  1047.  
  1048.     xor   ax,ax
  1049.     mov   [CType],ax
  1050.     mov   al,byte ptr es:[si]         (* AX = width                     *)
  1051.  
  1052.  
  1053.     mov   di,[X]                      (* DI = X coordinate of dest.     *)
  1054.     mov   cx,di                       (* save in CX                     *)
  1055.     sar   di,2                        (* convert to address byte        *)
  1056.  
  1057.  
  1058.  
  1059.     (**** CLIP PROCESSING FOR LEFT CLIP BORDER *******************)
  1060.  
  1061.     mov   dx,[LeftClip]
  1062.     sub   dx,di
  1063.     jle   @@NotLeftClip
  1064.     cmp   dx,ax
  1065.     jnl   @@NotVisible
  1066.  
  1067.     add   di,dx
  1068.     mov   [LeftSkip],dx
  1069.     mov   [DataInc],dx
  1070.     sub   ax,dx
  1071.     mov   [CType],1
  1072.     jmp   @@HorizClipDone
  1073.  
  1074.     (*** EXIT FOR COMPLETELY OBSCURED P.B.M's *********************)
  1075.  
  1076. @@NotVisible:
  1077.     mov   ax,1
  1078.     pop   ds                          (* restore data segment           *)
  1079.     pop   di                          (* restore registers              *)
  1080.     pop   si
  1081.         jmp   @Ok
  1082.  
  1083.     (**** CLIP PROCESSING FOR RIGHT CLIP BORDER *******************)
  1084.  
  1085. @@NotLeftClip:
  1086.     mov   dx,[RightClip]
  1087.     sub   dx,di
  1088.     js    @@NotVisible
  1089.     mov   [LeftSkip],0
  1090.     mov   [DataInc],0
  1091.     cmp   dx,ax
  1092.         jge   @@HorizClipDone       (* was jg                     *)
  1093.     inc   dx
  1094.     sub   ax,dx
  1095.     mov   [DataInc],ax
  1096.     mov   ax,dx
  1097.     mov   [CType],-1
  1098.  
  1099. @@HorizClipDone:
  1100.  
  1101.     xor   bh,bh
  1102.     mov   bl,byte ptr es:[si+1]       (* BX = height                    *)
  1103.  
  1104.     mov   [Width],ax                  (* Save width and height of clipped *)
  1105.     mov   [Height],bx                 (*  image                         *)
  1106.  
  1107.  
  1108.     add   si,2                        (* Skip dimension bytes in source *)
  1109.     add   si,[LeftSkip]               (* Skip pixels in front of row that *)
  1110.                       (*  are clipped                   *)
  1111.  
  1112.  
  1113.     mov   bx,[ScrnLogicalByteWidth]   (* Set BX to Logical Screen Width *)
  1114.     mov   dx,bx                       (* BX - Width of image = No. bytes*)
  1115.     sub   dx,ax                       (*  to first byte of next screen  *)
  1116.     mov   [LineInc],dx                (*  row.                          *)
  1117.  
  1118.     mov   ax,[Y]                      (* Calculate screen start row     *)
  1119.     mul   bx                          (*  then adding screen offset     *)
  1120.     add   di,ax
  1121.     add   di,[ScreenOfs]
  1122.     mov   ax,es                       (* copy ES to DS                  *)
  1123.     mov   ds,ax
  1124.     mov   ax,SCREEN_SEG               (* Point ES to VGA segment        *)
  1125.     mov   es,ax
  1126.  
  1127.     and   cx,3
  1128.     mov   ah,11h                      (* Set up initial plane mask      *)
  1129.     shl   ah,cl
  1130.  
  1131.     mov   dx,SC_INDEX                 (* Prepare VGA for cpu to video writes *)
  1132.     mov   al,MAP_MASK
  1133.     out   dx,al
  1134.     inc   dx
  1135.     mov   [Plane],4                   (* Set plane counter to 4         *)
  1136.     mov   bh,byte ptr [Width]         (* set bh to width for fast looping *)
  1137. @@PlaneLoop:
  1138.     push  di               (* Save bitmap's start dest. offset *)
  1139.     mov   bl,byte ptr [Height]        (* Reset row counter (BL)         *)
  1140.     mov   al,ah
  1141.     out   dx,al                       (* set vga write plane            *)
  1142. @@RowLoop:
  1143.     mov   cl,bh                       (* Reset Column counter cl        *)
  1144.     shr   cl,1
  1145.     rep   movsw                       (* Copy a complete row            *)
  1146.     adc   cl,0
  1147.     rep   movsb
  1148.     add   si,[DataInc]                (* Move to next source row        *)
  1149.     add   di,[LineInc]                (* Move to next screen row        *)
  1150.     dec   bl                          (* decrement row counter          *)
  1151.     jnz   @@RowLoop                   (* Jump if more rows left         *)
  1152.     pop   di                          (* Restore bitmaps start dest byte*)
  1153.     rol   ah,1                  (* Shift mask for next plane      *)
  1154.  
  1155.     (* Plane Transition (A HACK but it works!)                          *)
  1156.  
  1157.     jnb   @@Nocarry                   (* Jump if not plane transition   *)
  1158.     mov   bl,ah                       (* Save Plane Mask                *)
  1159.     mov   ax,[CType]                  (* set AX to clip type inc variable *)
  1160.     add   bh,al                       (* Update advancing variables     *)
  1161.     sub   [DataInc],ax                (*                                *)
  1162.     sub   [LineInc],ax                (*                                *)
  1163.     cmp   al,0                        (* What type of clip do we have   *)
  1164.     mov   ah,bl                       (*   restore Plane mask           *)
  1165.     jg    @@RightAdvance              (* jump on a right clip!          *)
  1166.     inc   di                          (* otherwise increment DI         *)
  1167.     jmp   @@Nocarry
  1168. @@RightAdvance:
  1169.     dec si
  1170. @@Nocarry:
  1171.     dec   [Plane]                     (* Decrement plane counter        *)
  1172.     jnz   @@PlaneLoop                 (* Jump if more planes left       *)
  1173.  
  1174.     xor   ax,ax
  1175.     pop   ds                          (* restore data segment           *)
  1176.     pop   di                          (* restore registers              *)
  1177.     pop   si
  1178. @OK:
  1179. end;
  1180.  
  1181.  
  1182.  
  1183. (*----------------------------------------------------------------------    *)
  1184. (* x_put_pbm_clipy - Write a planar bitmap from system ram to video ram     *)
  1185. (*                    with clipping in y direction only. similar to         *)
  1186. (*             "x_put_pbm".                                           *)
  1187. (*                                                                          *)
  1188. (* See Also:  x_put_pbm,x_put_pbm_clipx,x_put_pbm_clipxy                    *)
  1189. (*                                                                          *)
  1190. (* Clipping region variables: TopClip,BottomClip                            *)
  1191. (*                                                                          *)
  1192. (* Written by Themie Gouthas                                                *)
  1193. (*----------------------------------------------------------------------    *)
  1194. procedure x_put_pbm_clipy(X,Y:Word;Var Bitmap);   assembler;
  1195. var Width,Height,TopRow,LineInc,PlaneInc:Word;
  1196. asm
  1197.     push  si
  1198.     push  di
  1199.     push  ds
  1200.     cld
  1201.  
  1202.     les   si,[Bitmap]
  1203.  
  1204.     xor   bh,bh
  1205.     mov   bl,byte ptr es:[si+1]   (* BX = height *)
  1206.     mov   [Height],bx
  1207.  
  1208.     xor   ah,ah
  1209.     mov   al,byte ptr es:[si]     (* AX = width  *)
  1210.     mov   [Width],ax
  1211.  
  1212.     mov   cx,ax                       (* Save AX                        *)
  1213.     mul   bx                          (* AX = AX*BX = bytes/plane       *)
  1214.     mov   [PlaneInc],ax               (*  save as PlaneInc              *)
  1215.     mov   ax,cx                       (* Restore AX                     *)
  1216.  
  1217.     mov   di,[X]
  1218.     mov   cx,di
  1219.     and   cx,3
  1220.     shr   di,2
  1221.  
  1222.     (**** CLIP PROCESSING FOR TOP CLIP BORDER *********************)
  1223.  
  1224.     mov   dx,[TopClip]            (* Compare u.l. Y coord with Top      *)
  1225.     sub   dx,[Y]                  (* clipping border                    *)
  1226.     jle   @@NotTopClip            (* jump if VBM not clipped from above *)
  1227.     cmp   dx,bx
  1228.     jnl   @@NotVisible            (* jump if VBM is completely obscured *)
  1229.     mov   [TopRow],dx
  1230.     sub   bx,dx
  1231.     add   [Y],dx
  1232.     jmp   @@VertClipDone
  1233.  
  1234.     (*** EXIT FOR COMPLETELY OBSCURED P.B.M's *********************)
  1235.  
  1236. @@NotVisible:
  1237.     mov   ax,1
  1238.     pop   ds                          (* restore data segment           *)
  1239.     pop   di                          (* restore registers              *)
  1240.     pop   si
  1241.         jmp   @OK
  1242.  
  1243.     (**** CLIP PROCESSING FOR BOTTOM CLIP BORDER ******************)
  1244.  
  1245. @@NotTopClip:
  1246.     mov   dx,[BottomClip]
  1247.     sub   dx,[Y]
  1248.     js    @@NotVisible
  1249.     mov   [TopRow],0
  1250.     cmp   dx,bx
  1251.     jg    @@VertClipDone
  1252.     inc   dx
  1253.     mov   bx,dx
  1254.  
  1255. @@VertClipDone:
  1256.  
  1257.     mov   [Height],bx                 (* Calculate relative offset in data *)
  1258.     mul   [TopRow]                    (*  of first visible scanline     *)
  1259.     add   ax,2                        (* Skip dimension bytes in source *)
  1260.     add   si,ax                       (* Skip top rows that arent visible *)
  1261.  
  1262.  
  1263.     mov   ax,[Y]                      (* Calculate screen row           *)
  1264.     mov   bx,[ScrnLogicalByteWidth]  (*  by mult. Y coord by Screen     *)
  1265.     mul   bx                          (*  width then adding screen offset *)
  1266.     add   di,ax
  1267.     add   di,[ScreenOfs]
  1268.     sub   bx,[Width]                  (* calculate difference from end of *)
  1269.     mov   [LineInc],bx                (* b.m. in curr line to beginning of*)
  1270.                       (* b.m. on next scan line         *)
  1271.     mov   ax,es                       (* copy ES to DS                  *)
  1272.     mov   ds,ax
  1273.     mov   ax,SCREEN_SEG               (* Point ES to VGA segment        *)
  1274.     mov   es,ax
  1275.  
  1276.     mov   ah,11h                      (* Set up initial plane mask      *)
  1277.     shl   ah,cl
  1278.  
  1279.     mov   dx,SC_INDEX                 (* Prepare VGA for cpu to video writes *)
  1280.     mov   al,MAP_MASK
  1281.     out   dx,al
  1282.     inc   dx
  1283.     mov   bh,4                        (* Set plane counter to 4         *)
  1284. @@PlaneLoop:
  1285.     push  di               (* Save bitmap's start dest. offset *)
  1286.     push  si                          (* Save Bitmaps data offset       *)
  1287.     mov   bl,byte ptr [Height]        (* Reset row counter (BL)         *)
  1288.     mov   al,ah
  1289.     out   dx,al                       (* set vga write plane            *)
  1290. @@RowLoop:
  1291.     mov   cl,byte ptr [Width]         (* Reset Column counter cl        *)
  1292.     shr   cl,1
  1293.     rep   movsw                       (* Copy a complete row            *)
  1294.     adc   cl,0
  1295.     rep   movsb
  1296.  
  1297.     add   di,[LineInc]                (* Move to next row               *)
  1298.     dec   bl                          (* decrement row counter          *)
  1299.     jnz   @@RowLoop                   (* Jump if more rows left         *)
  1300.     pop   si                          (* Restore SI and set to offset of*)
  1301.     add   si,[PlaneInc]               (* first vis pixel in next plane data *)
  1302.     pop   di                          (* Restore bitmaps start dest byte*)
  1303.     rol   ah,1                        (* Shift mask for next plane      *)
  1304.     adc   di,0                        (* if carry increment screen offset *)
  1305.     dec   bh                          (* Decrement plane counter        *)
  1306.     jnz   @@PlaneLoop                 (* Jump if more planes left       *)
  1307.  
  1308.     xor   ax,ax
  1309.     pop   ds                          (* restore data segment           *)
  1310.     pop   di                          (* restore registers              *)
  1311.     pop   si
  1312. @OK:
  1313. end;
  1314.  
  1315.  
  1316. (*----------------------------------------------------------------------    *)
  1317. (* x_put_pbm_clipxy - Write a planar bitmap from system ram to video ram    *)
  1318. (*                    with clipping in x and y directions. similar to       *)
  1319. (*             "x_put_pbm".                                           *)
  1320. (*                                                                          *)
  1321. (* See Also:  x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipx                     *)
  1322. (*                                                                          *)
  1323. (* Clipping region variables: LeftClip,RightClip,TopClip,BottomClip         *)
  1324. (*                                                                          *)
  1325. (* Written by Themie Gouthas                                                *)
  1326. (*----------------------------------------------------------------------    *)
  1327. procedure x_put_pbm_clipxy(X,Y:Word;Var Bitmap);   assembler;
  1328. var Plane:Byte;
  1329.     CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:Word;
  1330. asm
  1331.     push  si
  1332.     push  di
  1333.     push  ds
  1334.     cld
  1335.  
  1336.     les   si,[Bitmap]
  1337.  
  1338.     xor   ax,ax
  1339.     mov   [CType],ax
  1340.     mov   al,byte ptr es:[si]         (* AX = width                     *)
  1341.     xor   bh,bh
  1342.     mov   bl,byte ptr es:[si+1]       (* BX = height                    *)
  1343.  
  1344.     mov   cx,ax                       (* Save AX                        *)
  1345.     mul   bx                          (* AX = AX*BX = bytes/plane       *)
  1346.     mov   [PlaneInc],ax               (*  save as PlaneInc              *)
  1347.     mov   ax,cx                       (* Restore AX                     *)
  1348.  
  1349.  
  1350.     mov   di,[X]                      (* DI = X coordinate of dest.     *)
  1351.     mov   cx,di                       (* save in CX                     *)
  1352.     sar   di,2                        (* convert to address byte        *)
  1353.  
  1354.  
  1355.     (**** CLIP PROCESSING FOR TOP CLIP BORDER ********************)
  1356.  
  1357.     mov   dx,[TopClip]            (* Compare u.l. Y coord with Top      *)
  1358.     sub   dx,[Y]                  (* clipping border                    *)
  1359.     jle   @@NotTopClip            (* jump if VBM not clipped from above *)
  1360.     cmp   dx,bx
  1361.     jnl   @@NotVisible            (* jump if VBM is completely obscured *)
  1362.     mov   [TopRow],dx
  1363.     sub   bx,dx
  1364.     add   [Y],dx
  1365.     jmp   @@VertClipDone
  1366.  
  1367.     (*** EXIT FOR COMPLETELY OBSCURED P.B.M's *********************)
  1368.  
  1369. @@NotVisible:
  1370.     mov   ax,1
  1371.     pop   ds                          (* restore data segment           *)
  1372.     pop   di                          (* restore registers              *)
  1373.     pop   si
  1374.         jmp   @OK
  1375.  
  1376.     (**** CLIP PROCESSING FOR BOTTOM CLIP BORDER *******************)
  1377.  
  1378. @@NotTopClip:
  1379.     mov   dx,[BottomClip]
  1380.     sub   dx,[Y]
  1381.     js    @@NotVisible
  1382.     mov   [TopRow],0
  1383.     cmp   dx,bx
  1384.     jg    @@VertClipDone
  1385.     inc   dx
  1386.     mov   bx,dx
  1387.  
  1388. @@VertClipDone:
  1389.  
  1390.     (**** CLIP PROCESSING FOR LEFT CLIP BORDER ********************)
  1391.  
  1392.     mov   dx,[LeftClip]
  1393.     sub   dx,di
  1394.     jle   @@NotLeftClip
  1395.     cmp   dx,ax
  1396.     jnl   @@NotVisible
  1397.  
  1398.     add   di,dx
  1399.     mov   [LeftSkip],dx
  1400.     mov   [DataInc],dx
  1401.     sub   ax,dx
  1402.     mov   [CType],1
  1403.     jmp   @@HorizClipDone
  1404.  
  1405.     (**** CLIP PROCESSING FOR RIGHT CLIP BORDER *******************)
  1406.  
  1407. @@NotLeftClip:
  1408.     mov   dx,[RightClip]
  1409.     sub   dx,di
  1410.     js    @@NotVisible
  1411.     mov   [LeftSkip],0
  1412.     mov   [DataInc],0
  1413.     cmp   dx,ax
  1414.         jge   @@HorizClipDone       (* was jg     *)
  1415.     inc   dx
  1416.     sub   ax,dx
  1417.     mov   [DataInc],ax
  1418.     mov   ax,dx
  1419.     mov   [CType],-1
  1420.  
  1421. @@HorizClipDone:
  1422.  
  1423.  
  1424.  
  1425.     mov   [Width],ax                  (* Save width and height of clipped *)
  1426.     mov   [Height],bx                 (*  image                         *)
  1427.  
  1428.     add   ax,[DataInc]                (* AX = original width of image   *)
  1429.     mul   [TopRow]                    (* Calculate bytes in clipped top *)
  1430.     add   si,ax                  (*  rows                          *)
  1431.     add   si,2                        (* Skip dimension bytes in source *)
  1432.     add   si,[LeftSkip]               (* Skip pixels in front of row that *)
  1433.                       (*  are clipped                   *)
  1434.  
  1435.     mov   bx,[ScrnLogicalByteWidth]   (* Set BX to Logical Screen Width *)
  1436.     mov   dx,bx                       (* BX - Width of image = No. bytes*)
  1437.     sub   dx,[Width]                  (*  to first byte of next screen  *)
  1438.     mov   [LineInc],dx                (*  row.                          *)
  1439.  
  1440.     mov   ax,[Y]                      (* Calculate screen start row     *)
  1441.     mul   bx                          (*  then adding screen offset     *)
  1442.     add   di,ax
  1443.     add   di,[ScreenOfs]
  1444.     mov   ax,es                       (* copy ES to DS                  *)
  1445.     mov   ds,ax
  1446.     mov   ax,SCREEN_SEG               (* Point ES to VGA segment        *)
  1447.     mov   es,ax
  1448.  
  1449.  
  1450.  
  1451.     and   cx,3
  1452.     mov   ah,11h                      (* Set up initial plane mask      *)
  1453.     shl   ah,cl
  1454.  
  1455.     mov   dx,SC_INDEX                 (* Prepare VGA for cpu to video writes *)
  1456.     mov   al,MAP_MASK
  1457.     out   dx,al
  1458.     inc   dx
  1459.     mov   [Plane],4                   (* Set plane counter to 4         *)
  1460.     mov   bh,byte ptr [Width]         (* set bh to width for fast looping *)
  1461. @@PlaneLoop:
  1462.     push  di               (* Save bitmap's start dest. offset *)
  1463.     push  si
  1464.     mov   bl,byte ptr [Height]        (* Reset row counter (BL)         *)
  1465.     mov   al,ah
  1466.     out   dx,al                       (* set vga write plane            *)
  1467. @@RowLoop:
  1468.     mov   cl,bh                       (* Reset Column counter cl        *)
  1469.     shr   cl,1
  1470.     rep   movsw                       (* Copy a complete row            *)
  1471.     adc   cl,0
  1472.     rep   movsb
  1473.     add   si,[DataInc]                (* Move to next source row        *)
  1474.     add   di,[LineInc]                (* Move to next screen row        *)
  1475.     dec   bl                          (* decrement row counter          *)
  1476.     jnz   @@RowLoop                   (* Jump if more rows left         *)
  1477.     pop   si                          (* Restore SI and set to offset of*)
  1478.     add   si,[PlaneInc]               (* first vis pixel in next plane data *)
  1479.     pop   di                          (* Restore bitmaps start dest byte*)
  1480.     rol   ah,1                  (* Shift mask for next plane      *)
  1481.  
  1482.     (* Plane Transition (A HACK but it works!)                          *)
  1483.  
  1484.     jnb   @@Nocarry                   (* Jump if not plane transition   *)
  1485.     mov   bl,ah                       (* Save Plane Mask                *)
  1486.     mov   ax,[CType]                  (* set AX to clip type inc variable *)
  1487.     add   bh,al                       (* Update advancing variables     *)
  1488.     sub   [DataInc],ax                (*                                *)
  1489.     sub   [LineInc],ax                (*                                *)
  1490.     cmp   al,0                        (* What type of clip do we have   *)
  1491.     mov   ah,bl                       (*   restore Plane mask           *)
  1492.     jg    @@RightAdvance              (* jump on a right clip!          *)
  1493.     inc   di                          (* otherwise increment DI         *)
  1494.     jmp   @@Nocarry
  1495. @@RightAdvance:
  1496.     dec si
  1497. @@Nocarry:
  1498.     dec   [Plane]                     (* Decrement plane counter        *)
  1499.     jnz   @@PlaneLoop                 (* Jump if more planes left       *)
  1500.  
  1501.     xor   ax,ax
  1502.     pop   ds                          (* restore data segment           *)
  1503.     pop   di                          (* restore registers              *)
  1504.     pop   si
  1505. @OK:
  1506. end;
  1507.  
  1508.  
  1509.  
  1510. (*-----------------------------------------------------------------------   *)
  1511. (* x_pbm_to_bm                                                              *)
  1512. (*                                                                          *)
  1513. (* This function converts a bitmap in the planar format to the linear format*)
  1514. (* as used by x_compile_bitmap.                                             *)
  1515. (*                                                                          *)
  1516. (* WARNING: the source and destination bitmaps must be pre - allocated      *)
  1517. (*                                                                          *)
  1518. (* NOTE: This function can only convert planar bitmaps that are suitable.   *)
  1519. (*       If the source planar bitmap's width (per plane) is >= 256/4        *)
  1520. (*       it cannot be converted. In this situation an error code            *)
  1521. (*       BM_WIDTH_ERROR. On successful conversion True is returned.         *)
  1522. (*                                                                          *)
  1523. (* C callable as:                                                           *)
  1524. (*    int x_pbm_to_bm(char far * source_pbm, char far * dest_bm)(*          *)
  1525. (*                                                                          *)
  1526. (* Written By Themie Gouthas                                                *)
  1527.  
  1528. function x_pbm_to_lbm(var src_pbm,dest_lbm):Boolean;  assembler;
  1529. asm
  1530.     push ds
  1531.  
  1532.     les  di,dest_lbm       (* es:di -> destination bitmap                *)
  1533.     lds  si,src_pbm       (* ds:si -> source planar bitmap              *)
  1534.     lodsb                 (* load AL with source pbm pixel width per plane *)
  1535.     mov  bl,al            (* save in CL                                 *)
  1536.     xor  ah,ah            (* convert to word                            *)
  1537.     shl  ax,2             (* mult by 4 giving source image width        *)
  1538.     cmp  ax,255           (* if the result > 255 then we have exceeded  *)
  1539.     ja   @@WidthError     (* the max width of linear bm.                *)
  1540.  
  1541.     stosb                 (* write do dest_bm                           *)
  1542.  
  1543.     lodsb                 (* tranfer source pbm height in pixels to     *)
  1544.     stosb                 (*  dest_bm                                   *)
  1545.  
  1546.     xor  ah,ah            (* convert to word                            *)
  1547.     mul  bl               (* AX = AX * BL ie. total no. pixels per plane*)
  1548.     mov  dx,di            (* save DI, the pointer to the destination bm *)
  1549.     mov  bl,3             (* set plane loop counter (BL)                *)
  1550.  
  1551. @@PlaneLoop:
  1552.     mov  cx,ax            (* set CX to total number of pixels per plane *)
  1553.  
  1554. @@PixelLoop:
  1555.     movsb                 (* transfer pixel                             *)
  1556.     add  di,3             (* increment destination to compensate for plane *)
  1557.     loop @@PixelLoop
  1558.  
  1559.     inc  dx               (* increment original di for next pixel plane  *)
  1560.     mov  di,dx            (* and restore di from incremented original    *)
  1561.     dec  bl               (* decrement plane counter                     *)
  1562.     jns  @@PlaneLoop      (* loop if more planes left                    *)
  1563.     mov  ax,Word(True)
  1564.     jmp  @@Done
  1565. @@WidthError:
  1566.     mov  ax,Word(false)
  1567. @@Done:
  1568.     pop  ds
  1569. end;
  1570.  
  1571.  
  1572. (* -----------------------------------------------------------------------  *)
  1573. (* x_bm_to_pbm                                                              *)
  1574. (*                                                                          *)
  1575. (* This function converts a bitmap in the linear format as used by          *)
  1576. (* x_compile_bitmap to the planar formap.                                   *)
  1577. (*                                                                          *)
  1578. (* WARNING: the source and destination bitmaps must be pre - allocated      *)
  1579. (*                                                                          *)
  1580. (* NOTE: This function can only convert linear bitmaps that are suitable.   *)
  1581. (*       If the source linear bitmap's width is not a multiple of 4         *)
  1582. (*       it cannot be converted. In this situation an error code            *)
  1583. (*       BM_WIDTH_ERROR. On successful conversion True is returned.         *)
  1584. (*                                                                          *)
  1585. (*    int x_bm_to_pbm(source_pbm,dest_bm);                                  *)
  1586. (*                                                                          *)
  1587. (* Written By Themie Gouthas                                                *)
  1588.  
  1589. function x_lbm_to_pbm(var src_bm,dest_pbm):Boolean;    assembler;
  1590. asm
  1591.     push ds
  1592.  
  1593.     les  di,dest_pbm         (* es:di -> destination planar bitmap      *)
  1594.     lds  si,src_bm           (* ds:si -> source bitmap                  *)
  1595.     lodsb                    (* load AX with source bitmap width        *)
  1596.     test al,03h              (* Check that width is a multiple of 4     *)
  1597.     jnz  @@WidthIncompatible
  1598.     shr  al,1;shr al,1       (* divide by 4 giving width of plane       *)
  1599.     stosb                    (* store destination planar bitmap width   *)
  1600.     mov  bl,al               (*  and copy to bl                         *)
  1601.     lodsb
  1602.     stosb            (* Transfer source bitmap height to dest pbm       *)
  1603.     xor  ah,ah               (* Conver height to word                   *)
  1604.     mul  bl                  (* calculate the total no. of pixels / plane *)
  1605.     mov  dx,si               (* save source offset                      *)
  1606.     mov  bl,3
  1607.  
  1608. @@PlaneLoop:
  1609.     mov  cx,ax            (* set CX to total number of pixels per plane *)
  1610.  
  1611. @@PixelLoop:
  1612.     movsb                 (* transfer pixel                             *)
  1613.     add  si,3             (* increment src offset to compensate for plane *)
  1614.     loop @@PixelLoop
  1615.  
  1616.     inc  dx               (* increment original si for next pixel plane *)
  1617.     mov  si,dx            (* and restore si from incremented original   *)
  1618.     dec  bl               (* decrement plane counter                    *)
  1619.     jns  @@PlaneLoop      (* loop if more planes left                   *)
  1620.     mov  ax,Word(True)
  1621.     jmp  @@Done
  1622. @@WidthIncompatible:
  1623.     mov  ax,Word(False)
  1624.  
  1625. @@Done:
  1626.     pop  ds
  1627. end;
  1628.  
  1629. function x_pbm_size(x1,y1,x2,y2:Word):Word; assembler;
  1630. asm
  1631.     mov   ax,x2
  1632.     sub   ax,x1
  1633.     inc   ax
  1634.     mov   bx,y2
  1635.     sub   bx,y1
  1636.     inc   bx
  1637.     mul   bx
  1638.     inc   ax
  1639.     inc   ax                  (* x_pbm_size:=2+(x2-x1+1)*(y2-y1+1);         *)
  1640. end;
  1641.  
  1642. function  x_sizeof_pbm(var BitMap):Word;    assembler;
  1643. asm
  1644.     les   di,dword ptr [Bitmap]
  1645.     mov   al,es:[di]
  1646.     xor   ah,ah
  1647.     shl   al,1
  1648.     shl   al,1
  1649.     mov   bl,es:[di+1]
  1650.     mul   bl
  1651.     inc   ax
  1652.     inc   ax
  1653. end;
  1654.  
  1655. procedure x_get_pbm_sizeXY(var x,y:Word;var Bitmap); assembler;
  1656. asm
  1657.     les   di,dword ptr [Bitmap]
  1658.     mov   ax,es:[di]
  1659.     xor   bx,bx
  1660.     mov   bl,ah
  1661.     les   di,dword ptr[y]
  1662.     mov   es:[di],bx
  1663.     shl   al,2
  1664.     xor   ah,ah
  1665.     les   di,dword ptr[x]
  1666.     mov   es:[di],ax
  1667.  
  1668. end;
  1669.  
  1670. function x_lbm_size(x1,y1,x2,y2:Word):Word;
  1671. begin;
  1672.   x_lbm_size:=x_pbm_size(x1,y1,x2,y2);
  1673. end;
  1674.  
  1675. function x_sizeof_lbm(var BitMap):Word;    assembler;
  1676. asm
  1677.     les   di,dword ptr [Bitmap]
  1678.     mov   al,es:[di]
  1679.     xor   ah,ah
  1680.     mov   bl,es:[di+1]
  1681.     inc   bl
  1682.     mul   bl
  1683.     inc   ax
  1684.     inc   ax
  1685. end;
  1686.  
  1687. type PCX_Header = record
  1688.         Manufacturer,version,encoding,bits_per_pixel : Byte;
  1689.         xmin,ymin,xmax,ymax,Hres,Vres                : Word;
  1690.         pal                                          : Array[0..47] of Byte;
  1691.         reserved,color_planes                        : Byte;
  1692.         bytes_per_line,palette_type                  : Word;
  1693.         filler                                       : Array[0..57] of Byte;
  1694.      end;
  1695.  
  1696. function x_get_pcx_size(Name:String):Word;
  1697. var F:File;
  1698.     Header:PCX_Header;
  1699.     Code:Integer;
  1700.     C:Byte;
  1701.     x,y:Word;
  1702. begin;
  1703.   x_get_pcx_size:=0;
  1704.   if F_Size(Name)-sizeof(Header)-3*256>$FFFF then exit;
  1705.  
  1706.   if not F_Open_Read(F,Name) then exit;
  1707.  
  1708.   BlockRead(F,Header,sizeof(Header),code);
  1709.  
  1710.   if code<>sizeof(Header) then exit;
  1711.  
  1712.   if (Header.manufacturer<>$0A)and(header.version<>5) then begin;F_Close(F);exit;end;
  1713.   F_Close(f);
  1714.  
  1715.   x:=(Header.xmax-header.xmin+4)and not 3;
  1716.   y:=Header.ymax-Header.ymin+1;
  1717.  
  1718.   if (x>253)or(y>255) then exit;
  1719.  
  1720.   x_get_pcx_size:=x*y+2;
  1721. end;
  1722.  
  1723. function x_Load_PCX_as_LBM;
  1724. var code,width,depth : Word;
  1725.     bytes,Add_X      : Byte;
  1726.     F                : File;
  1727.     Header           : ^PCX_Header;
  1728.     Buffer           : Pointer;
  1729.     Size             : LongInt;
  1730. begin;
  1731.   x_Load_PCX_as_LBM:=False;
  1732.  
  1733.   if x_get_pcx_size(Name)=0 then exit;
  1734.  
  1735.   if not F_Open_Read(F,Name) then exit;
  1736.  
  1737.   New(Header);
  1738.   BlockRead(F,Header^,sizeof(PCX_Header),code);
  1739.  
  1740.   width:=(Header^.xmax-header^.xmin+4) and not 3;
  1741.   depth:=Header^.ymax-Header^.ymin+1;
  1742.   bytes:=Header^.bytes_per_line-1;
  1743.   Add_X:=width-(Header^.xmax-header^.xmin+1);
  1744.   Dispose(Header);
  1745.  
  1746.   Size:=F_Size(Name)-sizeof(PCX_Header)-3*255;
  1747.  
  1748.   GetMEM(Buffer,size);
  1749.   BlockRead(F,Buffer^,size);
  1750.   F_Close(F);
  1751.  
  1752.   (*  es:di   Bitmap
  1753.       ds:si   Buffer
  1754.       dl      n       is the bytepointer each line
  1755.       dh      i       is the linepointer
  1756.       bl      bytes   bytecount of line in pcx-pictures
  1757.       bh      add_X   the (mod 4) rows in the lbm
  1758.       ah      depth-1 count of lines in pcx-pictures
  1759.                                                                             *)
  1760.   asm
  1761.     les   di,dword ptr [Bitmap]   (* Set x,y in LBM *)
  1762.     mov   ax,width
  1763.     stosb
  1764.     mov   ax,depth
  1765.     stosb
  1766.  
  1767.     mov   dh,0                    (* i:=0                                   *)
  1768.     mov   bl,bytes
  1769.     mov   ax,depth
  1770.     shl   ax,8
  1771.     dec   ah
  1772.     mov   bh,add_X
  1773.  
  1774.     push  ds
  1775.     lds   si,dword ptr [Buffer]
  1776.  
  1777. @Next_Line:
  1778.     jmp   @Get_Line
  1779. @Next_MEM:
  1780.  
  1781.     push  bx
  1782.     shr   bx,8
  1783.     add   di,bx
  1784.     pop   bx
  1785.  
  1786.     inc   dh
  1787.     cmp   dh,ah
  1788.     je    @Pic_Ready
  1789.     jmp   @Next_Line
  1790.  
  1791. @Get_Line:
  1792.     mov   dl,0                       (*  n:=0;                              *)
  1793.  
  1794. @Loop:
  1795.     cmp   dl,bl                      (*  while (n<bytes) do                 *)
  1796.     ja    @next_mem
  1797.  
  1798. @nothing:                            (*  begin;                             *)
  1799.     lodsb                            (*    BlockRead(f,c,1);                *)
  1800.  
  1801.     mov   cl,al             (* save the value c *)
  1802.     and   al,$c0
  1803.     cmp   al,$c0                     (*    if (c and $c0)=$c0 then          *)
  1804.     jne   @Part2
  1805.                                      (*    begin;                           *)
  1806.     and   cl,$3f                     (*      run:=c and $3f;                *)
  1807.     add   dl,cl                      (*      Inc(n,run);                    *)
  1808.     xor   ch,ch
  1809.     lodsb                            (*      BlockRead(f,c,1);              *)
  1810.     rep   stosb             (* write to Bitmap *)
  1811.     jmp   @Loop                      (*    end                              *)
  1812.  
  1813. @Part2:                            (* else begin;                           *)
  1814.     mov   al,cl
  1815.     stosb                   (* write to Bitmap *)
  1816.     inc   dl                         (*      Inc(n);                        *)
  1817.     jmp   @Loop                      (*    end;                             *)
  1818.  
  1819.  
  1820. @Pic_Ready:
  1821.     pop   ds
  1822.   end;
  1823.  
  1824.  
  1825.   (* for i:=0 to 255 do for j:=0 to 2 do pal[i,j]:=pal[i,j] shr 2;*)
  1826.  
  1827.   FreeMEM(Buffer,size);
  1828.   X_Load_PCX_as_LBM:=True;
  1829. end;
  1830.  
  1831.  
  1832.  
  1833. (* Intern use by x_load_pbm , x_load_lbm , x_load_ibm                       *)
  1834. procedure x_load_bitmap(var Name:String;Ext:String;var Bitmap);
  1835. var F:File;
  1836. begin;
  1837.   Name:=Only_one_Ext(Name,ext);
  1838.   if F_Open_Read(F,Name) then
  1839.                begin;
  1840.                  BlockRead(f,Bitmap,F_Size(Name));
  1841.                  F_Close(F);
  1842.                end
  1843.              else fillchar(Bitmap,2,0);
  1844. end;
  1845.  
  1846. procedure x_save_pbm(var Name:String;var Bitmap);
  1847. var F    : File;
  1848. begin;
  1849.   Name:=Only_one_Ext(Name,EXT_pbm);
  1850.   F_Open_Write(F,Name);
  1851.   BlockWrite(f,BitMap,x_sizeof_pbm(BitMap));
  1852.   F_Close(f);
  1853. end;
  1854.  
  1855.  
  1856. procedure x_load_pbm(var Name:String;var Bitmap);   (* able with MasterFile *)
  1857. begin;
  1858.   x_load_bitmap(Name,EXT_pbm,Bitmap);
  1859. end;
  1860.  
  1861. procedure x_save_lbm(var Name:String;var Bitmap);
  1862. var F    : File;
  1863. begin;
  1864.   Name:=Only_one_Ext(Name,EXT_lbm);
  1865.   F_Open_Write(F,Name);
  1866.   BlockWrite(f,BitMap,x_sizeof_lbm(Bitmap));
  1867.   F_Close(f);
  1868. end;
  1869.  
  1870. procedure x_load_lbm(var Name:String;var Bitmap);   (* able with MasterFile *)
  1871. var F    : File;
  1872. begin;
  1873.   x_load_bitmap(Name,EXT_lbm,Bitmap);
  1874. end;
  1875.  
  1876. procedure x_get_save_pbm(X1,Y1,X2,Y2:Word;Name:String);
  1877. var F    : File;
  1878.     B    : Pointer;
  1879.     Size : Word;
  1880. begin;
  1881.   Size:=x_pbm_size(X1,Y1,X2,Y2);
  1882.   GetMEM(B,Size);
  1883.   x_get_pbm(X1,Y1,X2,Y2,B^);
  1884.   x_save_pbm(Name,B^);
  1885.   FreeMEM(B,Size);
  1886. end;
  1887.  
  1888. procedure x_load_put_pbm(X,Y:Word;Name:String);
  1889. var F    : File;
  1890.     B    : Pointer;
  1891.     Size : Word;
  1892. begin;
  1893.   Size:=F_Size(Name);
  1894.   GetMEM(B,Size);
  1895.   x_load_pbm(Name,B^);
  1896.   x_put_pbm(X,Y,B^);
  1897.   FreeMEM(B,Size);
  1898. end;
  1899.  
  1900. const ROL_AL          = $c0d0;              (* rol al                  *)
  1901.       SHORT_STORE_8   = $44c6;              (* mov [si]+disp8,  imm8   *)
  1902.       STORE_8         = $84c6;              (* mov [si]+disp16, imm8   *)
  1903.       SHORT_STORE_16  = $44c7;              (* mov [si]+disp8,  imm16  *)
  1904.       STORE_16        = $84c7;              (* mov [si]+disp16, imm16  *)
  1905.       ADC_SI_IMMED    = $d683;              (* adc si,imm8             *)
  1906.       OUT_AL          = $ee;                (* out dx,al               *)
  1907.       RETURN          = $cb;                (* ret                     *)
  1908.  
  1909.  
  1910.  
  1911. procedure x_pbm_to_cbm(logical_width:Word;Var pbm,cbm); assembler;
  1912. var bwidth,scanx,scany,cbmx,cbmy,column,set_column,input_size:Word;
  1913. asm
  1914.     push si
  1915.     push di
  1916.     push ds
  1917.  
  1918.     mov word ptr [scanx],0
  1919.     mov word ptr [scany],0
  1920.     mov word ptr [cbmx],0
  1921.     mov word ptr [cbmy],0
  1922.     mov word ptr [column],0
  1923.     mov word ptr [set_column],0
  1924.  
  1925.     lds si,[pbm]        (* 32-bit pointer to source pbm                *)
  1926.  
  1927.     les di,[cbm]        (* 32-bit pointer to destination stream        *)
  1928.  
  1929.     lodsb               (* load width byte                             *)
  1930.     xor ah, ah          (* convert to word                             *)
  1931.     mov [bwidth], ax    (* save for future reference                   *)
  1932.     mov bl, al          (* copy width byte to bl                       *)
  1933.     lodsb               (* load height byte -- already a word since ah=0 *)
  1934.     mul bl              (* mult height word by width byte              *)
  1935.     mov [input_size], ax(*  to get pixel total                         *)
  1936.  
  1937. @@MainLoop:
  1938.     mov bx, [scanx]     (* position in original pbm                    *)
  1939.     add bx, [scany]
  1940.  
  1941.     mov al, [si+bx]     (* get pixel                                   *)
  1942.     or  al, al          (* skip empty pixels                           *)
  1943.     jnz @@NoAdvance
  1944.     jmp @@Advance
  1945. @@NoAdvance:
  1946.  
  1947.     mov dx, [set_column]
  1948.     cmp dx, [column]
  1949.     je @@SameColumn
  1950. @@ColumnLoop:
  1951.     mov word ptr es:[di],ROL_AL (* emit code to move to new column     *)
  1952.     add di,2
  1953.     mov word ptr es:[di],ADC_SI_IMMED
  1954.     add di,2
  1955.     mov byte ptr es:[di],0
  1956.     inc di
  1957.  
  1958.     inc dx
  1959.     cmp dx, [column]
  1960.     jl @@ColumnLoop
  1961.  
  1962.     mov byte ptr es:[di],OUT_AL (* emit code to set VGA mask for new column    *)
  1963.     inc di
  1964.     mov [set_column], dx
  1965. @@SameColumn:
  1966.     mov dx, [cbmy]      (* calculate cbm position                      *)
  1967.     add dx, [cbmx]
  1968.     sub dx, 128
  1969.  
  1970.     inc word ptr [scanx]
  1971.     mov cx, [scanx]     (* within four pixels of right edge?           *)
  1972.     cmp cx, [bwidth]
  1973.     jge @@OnePixel
  1974.  
  1975.     inc word ptr [cbmx]
  1976.     mov ah, [si+bx+1]   (* get second pixel                            *)
  1977.     or ah, ah
  1978.     jnz @@TwoPixels
  1979. @@OnePixel:
  1980.     cmp dx, 127         (* can we use shorter form?                    *)
  1981.     jg @@OnePixLarge
  1982.     cmp dx, -128
  1983.     jl @@OnePixLarge
  1984.     mov word ptr es:[di],SHORT_STORE_8
  1985.     add di,2
  1986.     mov byte ptr es:[di],dl (* 8-bit position in cbm                   *)
  1987.     inc di
  1988.     jmp @@EmitOnePixel
  1989. @@OnePixLarge:
  1990.     mov word ptr es:[di],STORE_8
  1991.     add di,2
  1992.     mov word ptr es:[di],dx (* position in cbm                             *)
  1993.     add di,2
  1994. @@EmitOnePixel:
  1995.     mov byte ptr es:[di],al
  1996.     inc di
  1997.     jmp @@Advance
  1998. @@TwoPixels:
  1999.     cmp dx, 127
  2000.     jg @@TwoPixLarge
  2001.     cmp dx, -128
  2002.     jl @@TwoPixLarge
  2003.     mov word ptr es:[di],SHORT_STORE_16
  2004.     add di,2
  2005.     mov byte ptr es:[di],dl (* 8-bit position in cbm                   *)
  2006.     inc di
  2007.     jmp @@EmitTwoPixels
  2008. @@TwoPixLarge:
  2009.     mov word ptr es:[di],STORE_16
  2010.     add di,2
  2011.     mov word ptr es:[di],dx (* position in cbm                             *)
  2012.     add di,2
  2013. @@EmitTwoPixels:
  2014.     mov word ptr es:[di],ax
  2015.     add di,2
  2016.  
  2017. @@Advance:
  2018.     inc word ptr [cbmx]
  2019.     mov ax, [scanx]
  2020.     inc ax
  2021.     cmp ax, [bwidth]
  2022.     jl @@AdvanceDone
  2023.     mov dx, [cbmy]
  2024.     add dx, [logical_width]
  2025.     mov cx, [scany]
  2026.     add cx, [bwidth]
  2027.     cmp cx, [input_size]
  2028.     jl @@NoNewColumn
  2029.     inc word ptr [column]
  2030.     mov cx, [column]
  2031.     cmp cx, 4
  2032.     je @@Exit           (* Column 4: there is no column 4.             *)
  2033.     xor cx, cx          (* scany and cbmy are 0 again for              *)
  2034.     mov dx, cx          (* the new column                              *)
  2035.     add si, [input_size]
  2036. @@NoNewColumn:
  2037.     mov [cbmy], dx
  2038.     mov [scany], cx
  2039.     xor ax, ax
  2040.     mov word ptr [cbmx], 0
  2041. @@AdvanceDone:
  2042.     mov [scanx], ax
  2043.     jmp @@MainLoop
  2044.  
  2045. @@Exit:
  2046.     mov byte ptr es:[di],RETURN
  2047.     inc di
  2048.     mov byte ptr es:[di],RETURN
  2049.     inc di
  2050.     mov ax,di
  2051.     sub ax,word ptr [cbm] (* size of generated code                    *)
  2052.  
  2053.     pop ds
  2054.     pop di
  2055.     pop si
  2056.  
  2057. end;
  2058.  
  2059.  
  2060. (*                                                                         *)
  2061. (* x_sizeof_cpbm  Returns wanted size for the converted pbm                *)
  2062. (*                                                                         *)
  2063.  
  2064.  
  2065. function x_sizeof_cpbm (logical_width:Word;Var pbm):Word; assembler;
  2066. var bwidth,scanx,scany,cbmx,cbmy,column,set_column,input_size:Word;
  2067. asm
  2068.     push si
  2069.     push di
  2070.     push ds
  2071.  
  2072.     mov word ptr [scanx], 0
  2073.     mov word ptr [scany], 0
  2074.     mov word ptr [cbmx], 0
  2075.     mov word ptr [cbmy], 0
  2076.     mov word ptr [column], 0
  2077.     mov word ptr [set_column], 0
  2078.  
  2079.     lds si,[pbm]        (* 32-bit pointer to source pbm                *)
  2080.  
  2081.     mov di, 1           (* initial size is just the size of the far RET*)
  2082.  
  2083.     lodsb               (* load width byte                             *)
  2084.     xor ah, ah          (* convert to word                             *)
  2085.     mov [bwidth], ax    (* save for future reference                   *)
  2086.     mov bl, al          (* copy width byte to bl                       *)
  2087.     lodsb               (* load height byte -- already a word since ah=0 *)
  2088.     mul bl              (* mult height word by width byte              *)
  2089.     mov [input_size], ax(*  to get pixel total                         *)
  2090.  
  2091. @@MainLoop:
  2092.     mov bx, [scanx]     (* position in original pbm                    *)
  2093.     add bx, [scany]
  2094.  
  2095.     mov al, [si+bx]     (* get pixel                                   *)
  2096.     or  al, al          (* skip empty pixels                           *)
  2097.     jnz @@NoAdvance
  2098.     jmp @@Advance
  2099. @@NoAdvance:
  2100.  
  2101.     mov dx, [set_column]
  2102.     cmp dx, [column]
  2103.     je @@SameColumn
  2104. @@ColumnLoop:
  2105.     add di, 5           (* size of code to move to new column          *)
  2106.     inc dx
  2107.     cmp dx,[column]
  2108.     jl @@ColumnLoop
  2109.  
  2110.     inc di              (* size of code to set VGA mask                *)
  2111.     mov [set_column], dx
  2112. @@SameColumn:
  2113.     mov dx, [cbmy]      (* calculate cbm position                      *)
  2114.     add dx, [cbmx]
  2115.     sub dx, 128
  2116.  
  2117.     inc word ptr [scanx]
  2118.     mov cx, [scanx]     (* within four pixels of right edge?           *)
  2119.     cmp cx, [bwidth]
  2120.     jge @@OnePixel
  2121.  
  2122.     inc word ptr [cbmx]
  2123.     mov ah,[si+bx+1]    (* get second pixel                            *)
  2124.     or ah, ah
  2125.     jnz @@TwoPixels
  2126. @@OnePixel:
  2127.     cmp dx, 127         (* can we use shorter form?                    *)
  2128.     jg @@OnePixLarge
  2129.     cmp dx, -128
  2130.     jl @@OnePixLarge
  2131.     add di, 4           (* size of 8-bit position in cbm plus one pixel*)
  2132.     jmp @@EmitOnePixel
  2133. @@OnePixLarge:
  2134.     add di, 5           (* size of position in cbm plus one pixels     *)
  2135. @@EmitOnePixel:
  2136.     jmp @@Advance
  2137. @@TwoPixels:
  2138.     cmp dx, 127
  2139.     jg @@TwoPixLarge
  2140.     cmp dx, -128
  2141.     jl @@TwoPixLarge
  2142.     add di, 5           (* size of 8-bit position in cbm plus two pixels *)
  2143.     jmp @@EmitTwoPixels
  2144. @@TwoPixLarge:
  2145.     add di, 6           (* size of 16-bit position in cbm plus two pixels*)
  2146. @@EmitTwoPixels:
  2147.  
  2148. @@Advance:
  2149.     inc word ptr [cbmx]
  2150.     mov ax, [scanx]
  2151.     inc ax
  2152.     cmp ax, [bwidth]
  2153.     jl @@AdvanceDone
  2154.     mov dx, [cbmy]
  2155.     add dx, [logical_width]
  2156.     mov cx, [scany]
  2157.     add cx, [bwidth]
  2158.     cmp cx, [input_size]
  2159.     jl @@NoNewColumn
  2160.     inc word ptr [column]
  2161.     mov cx, [column]
  2162.     cmp cx, 4
  2163.     je @@Exit           (* Column 4: there is no column 4.             *)
  2164.     xor cx,cx           (* scany and cbmy are 0 again for              *)
  2165.     mov dx,cx           (* the new column                              *)
  2166.     add si, [input_size]
  2167. @@NoNewColumn:
  2168.     mov [cbmy], dx
  2169.     mov [scany], cx
  2170.     xor ax, ax
  2171.     mov word ptr [cbmx], ax
  2172. @@AdvanceDone:
  2173.     mov [scanx], ax
  2174.     jmp @@MainLoop
  2175.  
  2176. @@Exit:
  2177.     mov ax, di          (* size of generated code                      *)
  2178.  
  2179.     pop ds
  2180.     pop di
  2181.     pop si
  2182. end;
  2183.  
  2184. (*                                                                         *)
  2185. (* x_put_cbm                                                               *)
  2186. (*                                                                         *)
  2187. (* Displays a compiled bitmap generated by x_pbm_to_cbm at given           *)
  2188. (* coordinates, on a given screen page.                                    *)
  2189. (*                                                                         *)
  2190. (* ax, bx, cx, and dx are squashed like insignificant insects.             *)
  2191.  
  2192. procedure x_put_cbm(XPos,YPos:Word;Var Sprite); assembler;
  2193. asm
  2194.     push si
  2195.     push ds
  2196.  
  2197.     mov ax, [ScrnLogicalByteWidth] (* global Xlib variable             *)
  2198.     mul word ptr [YPos] (* height in bytes                             *)
  2199.     mov si, [XPos]
  2200.     mov bx, si
  2201.     sar si, 1
  2202.     sar si, 1           (* width in bytes                              *)
  2203.     add si, ax
  2204.     add si, [ScreenOfs](* (YPos * screen width) +                      *)
  2205.     add si, 128         (*   (Xpos / 4) + page base + 128 ==> starting pos *)
  2206.  
  2207.     and bx, 3
  2208.     mov ah, [offset ColumnMask+bx]
  2209.  
  2210.     mov dx, SC_INDEX
  2211.     mov al, MAP_MASK
  2212.     out dx, ax
  2213.     inc dx              (* ready to send out other masks as bytes      *)
  2214.     mov al, ah
  2215.  
  2216.     mov bx, SCREEN_SEG
  2217.     mov ds, bx          (* We do this so the compiled shape won't need *)
  2218.                         (*  segment overrides.     *)
  2219.  
  2220.     call dword ptr [Sprite] (* the business end of the routine         *)
  2221.  
  2222.     pop ds
  2223.     pop si
  2224.  
  2225. end;
  2226.  
  2227. (***************************************************************************)
  2228. (****************************** IBM ****************************************)
  2229. (***************************************************************************)
  2230.  
  2231. (* internal use of pbm_to_ibm *)
  2232. procedure IncP(Var P); assembler;
  2233. asm
  2234.   les di,Dword ptr [P]
  2235.   mov ax,es:[di]
  2236.   inc ax
  2237.   mov es:[di],ax
  2238. end;
  2239.  
  2240.  
  2241. procedure x_pbm_to_ibm(Var pbm,ibm);
  2242. type byte_A=Array[0..$ff]of Byte;
  2243. var pbmP : ^byte_A;
  2244.     ibmP : ^Byte;
  2245.     x,y,p,i,j,l,lastX:Word;
  2246.  
  2247. procedure Store(B:Byte);begin;ibmP^:=B;IncP(ibmP);end;
  2248. begin;
  2249.   x_get_pbm_sizeXY(x,y,pbm);
  2250.   x:=x shr 2;
  2251.   pbmP:=addr(pbm);
  2252.   ibmP:=addr(ibm);
  2253.   Store(x shl 2);  IncP(pbmP);
  2254.   Store(y);        IncP(pbmP);
  2255.  
  2256.   for j:=1 to y*4 do
  2257.   begin;
  2258.     lastx:=0;
  2259.     for i:=0 to x do
  2260.     begin;
  2261.       if ((pbmP^[i]=0)<>(pbmP^[LastX]=0))or
  2262.          (i=x)                            then
  2263.       begin;
  2264.         if (pbmP^[LastX]=0) then
  2265.         begin;
  2266.           Store(0);
  2267.           Store(i-LastX);
  2268.           LastX:=i;
  2269.         end                else
  2270.         begin;
  2271.           Store(i-LastX);
  2272.           for l:=LastX to i-1 do Store(pbmP^[l]);
  2273.           LastX:=i;
  2274.         end;
  2275.       end;
  2276.     end;
  2277.     for l:=1 to x do IncP(pbmP);
  2278.   end;
  2279. end;
  2280.  
  2281. function x_sizeof_ipbm (Var pbm):Word;
  2282. type byte_A=Array[0..$ff]of Byte;
  2283. var pbmP : ^byte_A;
  2284.     x,y,p,i,j,l,lastX,Size:Word;
  2285. begin;
  2286.   x_get_pbm_sizeXY(x,y,pbm);
  2287.   x:=x shr 2;
  2288.   pbmP:=addr(pbm);
  2289.   IncP(pbmP);
  2290.   IncP(pbmP);
  2291.   Size:=2;
  2292.  
  2293.   for j:=1 to y*4 do
  2294.   begin;
  2295.     lastx:=0;
  2296.     for i:=0 to x do
  2297.     begin;
  2298.       if ((pbmP^[i]=0)<>(pbmP^[LastX]=0))or
  2299.          (i=x)                           then
  2300.       begin;
  2301.         if (pbmP^[LastX]=0) then
  2302.         begin;
  2303.           Inc(Size,2);
  2304.           LastX:=i;
  2305.         end                else
  2306.         begin;
  2307.           Inc(Size,i-LastX+1);
  2308.           LastX:=i;
  2309.         end;
  2310.       end;
  2311.     end;
  2312.     for l:=0 to x-1 do IncP(pbmP);
  2313.   end;
  2314.   x_sizeof_ipbm:=Size;
  2315. end;
  2316.  
  2317.  
  2318. procedure x_put_ibm(x,y:WOrd;Var ibm);        assembler;
  2319. var Next_Line,x1,y1,maxX,maxY   : Word;
  2320.     Plane : Byte;
  2321. asm
  2322.     push  ds
  2323.  
  2324.     mov   ax,SCREEN_SEG         (* es:di points in Screen *)
  2325.     mov   es,ax
  2326.     mov   ax,Y                        (* Calculate dest screen row           *)
  2327.     mov   bx,ScrnLogicalByteWidth     (*  by mult. dest Y coord by Screen    *)
  2328.     mul   bx                          (*  width then adding screen offset    *)
  2329.     mov   di,ScreenOfs                (*  store result in DI                 *)
  2330.     add   di,ax
  2331.     push  di
  2332.  
  2333.     mov   dx,ScrnLogicalByteWidth
  2334.     lds   si,dword ptr [ibm]    (* ds:si points in ibm *)
  2335.     xor   ax,ax
  2336.     mov   al,ds:[si]
  2337.     shr   al,2
  2338.     mov   maxX,ax
  2339.     sub   dx,ax
  2340.     mov   Next_Line,dx
  2341.     inc   si
  2342.     mov   al,ds:[si]
  2343.     mov   maxY,ax
  2344.     inc   si
  2345.  
  2346.     mov   Plane,0
  2347.  
  2348. @Plane_Loop:
  2349.     mov   y1,0
  2350.  
  2351.         mov  cx,x
  2352.         add  cl,Plane
  2353.  
  2354.     (* SELECT WRITE PLANE *)
  2355.     and  cl,011b              (* CL = plane                           *)
  2356.     mov  ax,0100h + MAP_MASK  (* AL = index in SC of Map Mask reg     *)
  2357.     shl  ah,cl                (* set only the bit for the required    *)
  2358.                   (*  plane to 1                          *)
  2359.     mov  dx,SC_INDEX          (* set the Map Mask to enable only the  *)
  2360.     out  dx,ax                (*  pixel's plane                       *)
  2361.  
  2362.     pop   di
  2363.     push  di
  2364.  
  2365.     mov   ax,x
  2366.     add   al,Plane
  2367.     adc   ah,0
  2368.     shr   ax,2
  2369.     add   di,ax
  2370.  
  2371.     xor   dx,dx
  2372.  
  2373. @Lines:
  2374.     xor   ah,ah
  2375.     lodsb
  2376.     or    al,al
  2377.     jz    @black
  2378.  
  2379. @color:    xor   cx,cx       (* count for next n color pixel found *)
  2380.            mov   cl,al
  2381.            add   dx,cx
  2382.            and   al,1
  2383.            jz   @word_Move
  2384. @byte_Move:movsb
  2385. @word_move:shr   cx,1
  2386.            rep   movsw
  2387.            jmp   @Ok
  2388.  
  2389. @black:    lodsb             (* 0 found, fill with pixel 0 *)
  2390.            xor   ch,ch
  2391.            mov   cl,al
  2392.            add   dx,cx
  2393.            and   al,1
  2394.            jz    @Word_Mov
  2395. @byte_Mov: xor   al,al
  2396.            stosb
  2397. @word_mov: shr   cx,1
  2398.            rep   stosw
  2399.  
  2400.  
  2401. @Ok:
  2402.     cmp   dx,maxX
  2403.     jne   @Lines
  2404.  
  2405.     xor   dx,dx
  2406.  
  2407.     add   di,Next_Line
  2408.     inc   y1
  2409.     mov   ax,maxY
  2410.     cmp   y1,ax
  2411.     jne   @Lines
  2412.  
  2413.     Inc   Plane
  2414.     cmp   Plane,4
  2415.     jne   @Plane_Loop
  2416.  
  2417.     pop   di
  2418.     pop   ds
  2419. end;
  2420. procedure x_put_masked_ibm(x,y:WOrd;Var ibm);        assembler;
  2421. var Next_Line,x1,y1,maxX,maxY   : Word;
  2422.     Plane : Byte;
  2423. asm
  2424.     push  ds
  2425.  
  2426.     mov   ax,SCREEN_SEG         (* es:di points in Screen *)
  2427.     mov   es,ax
  2428.     mov   ax,Y                        (* Calculate dest screen row           *)
  2429.     mov   bx,ScrnLogicalByteWidth     (*  by mult. dest Y coord by Screen    *)
  2430.     mul   bx                          (*  width then adding screen offset    *)
  2431.     mov   di,ScreenOfs                (*  store result in DI                 *)
  2432.     add   di,ax
  2433.     push  di
  2434.  
  2435.     mov   dx,ScrnLogicalByteWidth
  2436.     lds   si,dword ptr [ibm]    (* ds:si points in ibm *)
  2437.     xor   ax,ax
  2438.     mov   al,ds:[si]
  2439.     shr   al,2
  2440.     mov   maxX,ax
  2441.     sub   dx,ax
  2442.     mov   Next_Line,dx
  2443.     inc   si
  2444.     mov   al,ds:[si]
  2445.     mov   maxY,ax
  2446.     inc   si
  2447.  
  2448.     mov   Plane,0
  2449.  
  2450. @Plane_Loop:
  2451.     mov   y1,0
  2452.  
  2453.         mov  cx,x
  2454.         add  cl,Plane
  2455.  
  2456.     (* SELECT WRITE PLANE *)
  2457.     and  cl,011b              (* CL = plane                           *)
  2458.     mov  ax,0100h + MAP_MASK  (* AL = index in SC of Map Mask reg     *)
  2459.     shl  ah,cl                (* set only the bit for the required    *)
  2460.                   (*  plane to 1                          *)
  2461.     mov  dx,SC_INDEX          (* set the Map Mask to enable only the  *)
  2462.     out  dx,ax                (*  pixel's plane                       *)
  2463.  
  2464.     pop   di
  2465.     push  di
  2466.  
  2467.     mov   ax,x
  2468.     add   al,Plane
  2469.     adc   ah,0
  2470.     shr   ax,2
  2471.     add   di,ax
  2472.  
  2473.     xor   dx,dx
  2474.  
  2475. @Lines:
  2476.     xor   ah,ah
  2477.     lodsb
  2478.     or    al,al
  2479.     jz    @black
  2480.  
  2481. @color:    xor   cx,cx       (* count for next n color pixel found *)
  2482.            mov   cl,al
  2483.            add   dx,cx
  2484.            and   al,1
  2485.            jz   @word_Move
  2486. @byte_Move:movsb
  2487. @word_move:shr   cx,1
  2488.            rep   movsw
  2489.            jmp   @Ok
  2490.  
  2491. @black:    lodsb             (* 0 found, add n screenpointer for trans. *)
  2492.            add   dx,ax       (* pixels                                  *)
  2493.            add   di,ax
  2494.  
  2495. @Ok:
  2496.     cmp   dx,maxX
  2497.     jne   @Lines
  2498.  
  2499.     xor   dx,dx
  2500.  
  2501.     add   di,Next_Line
  2502.     inc   y1
  2503.     mov   ax,maxY
  2504.     cmp   y1,ax
  2505.     jne   @Lines
  2506.  
  2507.     Inc   Plane
  2508.     cmp   Plane,4
  2509.     jne   @Plane_Loop
  2510.  
  2511.     pop   di
  2512.     pop   ds
  2513. end;
  2514.  
  2515. procedure x_load_ibm(var Name:String;var Bitmap);   (* able with MasterFile *)
  2516. begin;
  2517.   x_load_bitmap(Name,EXT_ibm,Bitmap);
  2518. end;
  2519.  
  2520.  
  2521.  
  2522. (***************************************************************************)
  2523. (****************************** VBM ****************************************)
  2524. (***************************************************************************)
  2525.  
  2526. type VBM_info_struc = record
  2527.        Size          : Word;
  2528.        ImageWidth    : Word;
  2529.        ImageHeight   : Word;
  2530.      { AlignData      : Word;}
  2531.      end;
  2532.  
  2533.      VBM_alignment_struc = record
  2534.        ImagePtr      : Word;
  2535.        MaskPtr       : Word;
  2536.      end;
  2537.  
  2538. const AlignData = 6;
  2539.  
  2540.  
  2541. (*----------------------------------------------------------------------   *)
  2542. (* x_store_vbm_image                                                       *)
  2543. (*                                                                         *)
  2544. (*  Store the linear bitmap in video RAM using the specified alignment and *)
  2545. (*  start address. Returns number video ram bytes used.                    *)
  2546. (*                                                                         *)
  2547. (*  THIS FUNCTION IS FOR USE BY x_make_masked_vbm                          *)
  2548. (*                                                                         *)
  2549. (*  Returns the VideoOffs                                                  *)
  2550. (*                                                                         *)
  2551. (*  function x_store_vbm_image(VramOffs,Align:Word;Var Lbm):Word;               *)
  2552. (*                                                                         *)
  2553. (* Written by Themie Gouthas                                               *)
  2554. (*----------------------------------------------------------------------   *)
  2555. function x_store_vbm_image(VramOffs,Align:Word;Var Lbm):Word; Assembler;
  2556. var BMWidth:Byte;
  2557. asm
  2558.         push  si
  2559.         push  di
  2560.     push  ds
  2561.     cld
  2562.  
  2563.     mov   ax,SCREEN_SEG               (* Point ES to screen segment    *)
  2564.     mov   es,ax
  2565.     mov   di,[VramOffs]               (* Point ES:DI to VRAM dest start*)
  2566.     mov   bx,[Align]                  (* Set BL to first pixel plane align *)
  2567.         and   bl,03h
  2568.  
  2569.     lds   si,[Lbm]                (* DS:SI -> source linear Bitmap     *)
  2570.         lodsw                             (* Al = B.M. width (bytes) AH = B.M. *)
  2571.     mov   bh,ah                       (* Save source bitmap dimensions *)
  2572.     mov   [BMWidth],al                (*                               *)
  2573.  
  2574.     mov   dx,SC_INDEX                 (* Initialize Map Mask for plane *)
  2575.     mov   al,MAP_MASK                 (* selection                     *)
  2576.         out   dx,al
  2577.     inc   dx
  2578.     xor   ch,ch                       (* clear CH                      *)
  2579. @@RowLoop:
  2580.     mov   cl,bl                       (* Set initial plane for current *)
  2581.     mov   ah,11h                      (* allignment                    *)
  2582.     shl   ah,cl
  2583.  
  2584.     mov   cl,[BMWidth]                (* Initialize column counter     *)
  2585. @@ColLoop:
  2586.     mov   al,ah
  2587.         out   dx,al                       (* set vga write plane           *)
  2588.     lodsb                             (* load next LBM pixel           *)
  2589.     mov   es:[di],al                  (* store it in Video Ram         *)
  2590.     shl   ah,1                        (* rotate plane mask             *)
  2591.     jnb   @@NoAddrIncr                (* Time to increment dest address ? *)
  2592.     inc   di                          (* Yes: increment addr and reset *)
  2593.     mov   ah,11h                      (*  plane mask to plane 0        *)
  2594. @@NoAddrIncr:
  2595.     loop  @@ColLoop                   (* Loop to next pixel column     *)
  2596.     cmp   ah,11h
  2597.     je    @@skip
  2598.     inc   di                (* Increment dest addr           *)
  2599. @@skip:
  2600.     dec   bh                          (* Decrement row counter         *)
  2601.     jnz   @@RowLoop                   (* Jump if more rows to go       *)
  2602.     mov   ax,di                       (* calculate video RAM consumed a*)
  2603.     sub   ax,[VramOffs]               (*   return value                *)
  2604.  
  2605.         pop   ds                          (* restore data segment          *)
  2606.     pop   di                          (* restore registers             *)
  2607.         pop   si
  2608. end;
  2609.  
  2610. (* Alignment structures, 4 of which make up the header section of the   *)
  2611. (* video bitmap                                                         *)
  2612.  
  2613. type alignment = record
  2614.         ImagePtr    : Word;
  2615.         MaskPtr     : Word;
  2616.      end;
  2617.      alignment_header = record
  2618.         Size        : Word;
  2619.         ImageWidth  : Word;
  2620.         Imageheight : Word;
  2621.         alignments  : Array[0..3] of alignment;
  2622.      end;
  2623.  
  2624. (* Structure to extract width/height frol LBM (linear bit map)           *)
  2625.  
  2626.      lbm_header = record
  2627.         width,height: Byte;
  2628.      end;
  2629.  
  2630.  
  2631. (*************************************************************************)
  2632. (*                                                                       *)
  2633. (* Generates all four possible mode X image/mask alignments, stores      *)
  2634. (* image alignments in display memory, allocates memory for and generates*)
  2635. (* mask alignments, and fills out a VBM aligned masked image structure.  *)
  2636. (* Each non-zero byte in source bitmap corresponds to image pixel to be  *)
  2637. (* drawn.                                                                *)
  2638. (* On success returns a far pointer to the new VBM structure otherwise   *)
  2639. (* it returns NULL                                                       *)
  2640. (*                                                                       *)
  2641. (* Source Language: C                                                    *)
  2642. (*                                                                       *)
  2643. (* Parameters:                                                           *)
  2644. (*    lbm        pointer to linear bitmap                                *)
  2645. (*    vramStart  contains the next available video offset which is       *)
  2646. (*               also updated after calling this function                *)
  2647. (*                                                                       *)
  2648. (*************************************************************************)
  2649.  
  2650.  
  2651. function x_lbm_to_vbm(Var lbm;Var VramStart:Word):Pointer;
  2652. type PByte = ^Byte;
  2653. procedure IncP(Var P:PByte); assembler;
  2654. asm
  2655.   les di,Dword ptr [P]
  2656.   mov ax,es:[di]
  2657.   inc ax
  2658.   mov es:[di],ax
  2659. end;
  2660.  
  2661. var lbm_headr : ^lbm_header;
  2662.     vbm_headr : ^alignment_header;
  2663.     vbm_mask_ptr,p,lbm_pixel_ptr : PByte;
  2664.     align,BitNum,TempImageWidth  : Integer;
  2665.     TempWidth,TempHeight,TempSize,MaskSize,VramOffs,MaskSpace : Word;
  2666.     scanline  : Integer;
  2667.     MaskTemp,i  : Byte;
  2668. begin;
  2669.   MaskSpace := 0;
  2670.   VramOffs  := VramStart;
  2671.   lbm_headr := addr(lbm);
  2672.  
  2673.   TempWidth := (lbm_headr^.width+3)div 4+1;
  2674.   TempHeight:= lbm_headr^.height;
  2675.   TempSize  := TempWidth*TempHeight;
  2676.  
  2677.   if MemAvail<22+TempSize*4 then begin;x_lbm_to_vbm:=NIL;exit;end;
  2678.   GetMEM(vbm_headr,22+TempSize*4);
  2679.  
  2680.   MaskSpace:=22;
  2681.  
  2682.   vbm_headr^.ImageWidth  := TempWidth;
  2683.   vbm_headr^.ImageHeight := TempHeight;
  2684.   vbm_headr^.size        := 22+TempSize*4;
  2685.   for align:=0 to 3 do
  2686.   begin;
  2687.     vbm_headr^.alignments[align].ImagePtr := VramOffs;
  2688.     VramOffs:=x_store_vbm_image(VramOffs,align,lbm);
  2689.     Inc(MaskSpace,TempSize);
  2690.     Inc(VramOffs,TempSize);
  2691.   end;
  2692.  
  2693.   vbm_mask_ptr := ptr(seg(vbm_headr^),ofs(vbm_headr^)+22);
  2694.  
  2695.   for align:=0 to 3 do
  2696.   begin;
  2697.     lbm_pixel_ptr := ptr(seg(lbm),ofs(lbm)+2);
  2698.     vbm_headr^.alignments[align].MaskPtr := ofs(vbm_mask_ptr^);
  2699.     for scanline:=0 to TempHeight-1 do
  2700.     begin;
  2701.       BitNum  :=align;
  2702.       MaskTemp:=0;
  2703.       for TempImageWidth:=lbm_headr^.width downto 1 do
  2704.       begin;
  2705.         MaskTemp := MaskTemp or (Byte(lbm_pixel_ptr^<>0) shl BitNum);
  2706.         IncP(lbm_pixel_ptr);
  2707.  
  2708.         Inc(BitNum);
  2709.         if (BitNum > 3) then
  2710.         begin;
  2711.           vbm_mask_ptr^:=MaskTemp;
  2712.           IncP(vbm_mask_ptr);
  2713.           MaskTemp:=0;
  2714.           BitNum:=0;
  2715.         end;
  2716. {        Dec(TempImageWidth);}
  2717.       end;
  2718.       if BitNum<>0 then vbm_mask_ptr^:=MaskTemp
  2719.                    else vbm_mask_ptr^:=0;
  2720.       IncP(vbm_mask_ptr);
  2721.     end;
  2722.  
  2723.   end;
  2724.  
  2725.   VramStart:=VramOffs;
  2726.   x_lbm_to_vbm:=vbm_headr;
  2727. end;
  2728.  
  2729.  
  2730. procedure x_put_masked_vbm(X,Y:Word;var SrcVBM);  assembler;
  2731. var VBMWidth,VBMHeight,NextLineIncr:Word;
  2732. asm
  2733.         push  si
  2734.         push  di
  2735.     push  ds
  2736.     cld
  2737.  
  2738.         mov   ax,[x]
  2739.         and   ax,not 3
  2740.         or    ax,3
  2741.         mov   [x],ax
  2742.  
  2743.     mov   ax,SCREEN_SEG               (* Point es to VGA segment       *)
  2744.         mov   es,ax
  2745.         mov   ax,[Y]                      (* Calculate dest screen row     *)
  2746.     mov   cx,[ScrnLogicalByteWidth]  (*  by mult. dest Y coord by Screen *)
  2747.     mul   cx                          (*  width then adding screen offset *)
  2748.  
  2749.     mov   di,[ScreenOfs]               (*  store result in DI          *)
  2750.         add   di,ax
  2751.     mov   si,[X]                      (* Load X coord into CX and make a *)
  2752.     mov   bx,si                       (*  copy in DX                   *)
  2753.     shr   bx,1                        (* Find starting byte in dest row*)
  2754.     shr   bx,1
  2755.     add   di,bx                       (*  add to DI giving screen offset *)
  2756.                                           (*  of first pixel's byte        *)
  2757.  
  2758.     and   si,3                        (* get pixel alignment in si     *)
  2759.  
  2760.     lds   bx,[SrcVBM]                 (* DS:BX -> VBM data structure   *)
  2761.     shl   si,1                        (* si = offset of data  for curr *)
  2762.     shl   si,1              (* alignment                     *)
  2763.  
  2764. {    mov ax,word ptr [bx+ImageHeight] }(* Get image height              *)
  2765.         mov   ax,word ptr [bx+4]
  2766.     mov   [VBMHeight],ax
  2767. {    mov ax,word ptr [bx+ImageWidth]  }(* Get image width               *)
  2768.         mov   ax,word ptr [bx+2]
  2769.     mov   [VBMWidth],ax
  2770.  
  2771.     sub   cx,ax                       (* NextLineIncr = bytes to the begin. *)
  2772.     mov   [NextLineIncr],cx           (*  of bitmaps next row on screen*)
  2773. {    mov   dx,[bx+MaskPtr+AlignData+si]} (* DS:SI -> mask data          *)
  2774.         mov   dx,[bx+2+AlignData+si]
  2775. {    mov   bx,[bx+ImagePtr+AlignData+si]}(* ES:BX -> source video bitmap*)
  2776.         mov   bx,[bx+0+AlignData+si]
  2777.     mov   si,dx
  2778.  
  2779.     mov   dx,GC_INDEX                 (* Set bit mask for all bits from*)
  2780.     mov   ax,BIT_MASK                 (* VGA latches and none from CPU *)
  2781.     out   dx,ax
  2782.  
  2783.     mov   dx,SC_INDEX                 (* Point SC register to map mask *)
  2784.     mov   al,MAP_MASK                 (* in preperation for masking data *)
  2785.     out   dx,al
  2786.     inc   dx                          (* Point dx to SC data register  *)
  2787.     mov   ah,byte ptr [VBMHeight]     (* AH = Scanline loop counter    *)
  2788.  
  2789. @@RowLoop:
  2790.     mov   cx,[VBMWidth]               (* Width in bytes across         *)
  2791.  
  2792. @@ColumnLoop:
  2793.     lodsb
  2794.     out   dx,al
  2795.     mov   al,es:[bx]                  (* load latches from source bitmap*)
  2796.     stosb                             (* store latches to dest. bitmap *)
  2797.     inc   bx
  2798.     loop  @@ColumnLoop
  2799.  
  2800.     add   di,[NextLineIncr]           (* point to start of next dest row*)
  2801.     dec   ah                          (* decrement scan line counter   *)
  2802.     jnz   @@RowLoop                   (* jump if more scanlines left   *)
  2803.  
  2804.     mov   dx,GC_INDEX+1               (* Restore bitmask to the default - *)
  2805.     mov   al,0ffh                     (*  all data from cpu            *)
  2806.     out   dx,al
  2807.  
  2808.         pop   ds                          (* restore data segment          *)
  2809.         pop   di                          (* restore registers             *)
  2810.         pop   si
  2811. end;
  2812.  
  2813.  
  2814. procedure x_put_masked_vbm_clipx(X,Y:Word;Var SrcVBM); assembler;
  2815. var DataInc,LeftSkip,VBMWidth,VBMHeight,NextLineIncr:Word;
  2816. asm
  2817.         push  si
  2818.         push  di
  2819.     push  ds
  2820.     cld
  2821.  
  2822.         mov   ax,[x]
  2823.         and   ax,not 3
  2824.         or    ax,3
  2825.         mov   [x],ax
  2826.  
  2827.     mov   di,[X]                  (* load X coord int DI and make a    *)
  2828.     mov   si,di                   (*  copy in SI                       *)
  2829.     sar   di,1                    (* Find Byte offset of X coord       *)
  2830.     sar   di,1
  2831.  
  2832.     and   si,3                    (* Calculate pixels plane alignment  *)
  2833.     shl   si,1                    (* Prepare to lookup mask & data     *)
  2834.     shl   si,1
  2835.     les   bx,[SrcVBM]             (* ES:BX -> begining of VBM data     *)
  2836.  
  2837. {    mov   cx,es:[bx+ImageWidth]}  (* Get image width and save in CX    *)
  2838.     mov   cx,es:[bx+2]
  2839.  
  2840.  
  2841.     (**** CLIP PROCESSING FOR LEFT CLIP BORDER *******************)
  2842.  
  2843.     mov   dx,[LeftClip]
  2844.     sub   dx,di
  2845.     jle   @@NotLeftClip
  2846.     cmp   dx,cx
  2847.     jnl   @@NotVisible
  2848.     add   di,dx
  2849.     mov   [LeftSkip],dx
  2850.     mov   [DataInc],dx
  2851.     sub   cx,dx
  2852.     jmp   @@HorizClipDone
  2853.  
  2854.         (*** EXIT FOR COMPLETELY OBSCURED V.B.M's *********************)
  2855.  
  2856. @@NotVisible:
  2857.     mov   ax,1
  2858.     pop   ds                          (* restore data segment          *)
  2859.     pop   di                          (* restore registers             *)
  2860.     pop   si
  2861.     jmp   @Ok
  2862.  
  2863.     (**** CLIP PROCESSING FOR RIGHT CLIP BORDER *******************)
  2864.  
  2865. @@NotLeftClip:
  2866.     mov   dx,[RightClip]
  2867.     sub   dx,di
  2868.     js    @@NotVisible
  2869.     mov   [LeftSkip],0
  2870.     mov   [DataInc],0
  2871.     cmp   dx,cx
  2872.     jge   @@HorizClipDone
  2873.     inc   dx
  2874.     sub   cx,dx
  2875.     mov   [DataInc],cx
  2876.     mov   cx,dx
  2877.  
  2878. @@HorizClipDone:
  2879.  
  2880.  
  2881.     add   di,[ScreenOfs]           (* Add the current page offset      *)
  2882.     mov   [VBMWidth],cx
  2883. {       mov   ax,es:[bx+ImageHeight]}  (* Get image height and save in AX   *)
  2884.     mov   ax,es:[bx+4]
  2885.     mov   [VBMHeight],ax
  2886.  
  2887.  
  2888.     (*************************************************************)
  2889.  
  2890.     mov   ax,[Y]                      (* Calculate dest screen row     *)
  2891.     mov   cx,[ScrnLogicalByteWidth]   (*  by mult. dest Y coord by Screen *)
  2892.     mul   cx                          (*  width then adding screen offset *)
  2893.     add   di,ax                       (* Add Dest Screen Row to di     *)
  2894.     sub   cx,[VBMWidth]
  2895.     mov   [NextLineIncr],cx
  2896.  
  2897.     mov   ax,es                       (* copy ES to DS                 *)
  2898.     mov   ds,ax
  2899.     mov   ax,SCREEN_SEG               (* Point es to VGA segment       *)
  2900.     mov   es,ax
  2901.  
  2902. {    mov   ax,[bx+MaskPtr+AlignData+si]} (* DS:SI -> mask data          *)
  2903.     mov   ax,[bx+2+AlignData+si]
  2904. {          mov   bx,[bx+ImagePtr+AlignData+si]}(* ES:BX -> source video bitmap*)
  2905.           mov   bx,[bx+0+AlignData+si]
  2906.     mov   si,ax
  2907.  
  2908.     mov   ax,[LeftSkip]               (* Skip data/mask bytes in       *)
  2909.     add   bx,ax                       (* each row that have been clipped *)
  2910.     add   si,ax                       (* by the L.H.S border           *)
  2911.  
  2912.  
  2913.     mov   dx,GC_INDEX                 (* Set bit mask for all bits from*)
  2914.     mov   ax,BIT_MASK                 (* VGA latches and none from CPU *)
  2915.     out   dx,ax
  2916.     mov   dx,SC_INDEX                 (* Point SC register to map mask *)
  2917.     mov   al,MAP_MASK                 (* in preperation for masking data*)
  2918.     out   dx,al
  2919.     inc   dx                          (* Point dx to SC data register  *)
  2920.     mov   ah,byte ptr [VBMHeight]     (* AH = Scanline loop counter    *)
  2921.  
  2922. @@RowLoop:
  2923.     mov   cx,[VBMWidth]               (* Width in bytes across         *)
  2924.  
  2925. @@ColumnLoop:
  2926.     lodsb
  2927.     out   dx,al
  2928.     mov   al,es:[bx]                  (* load latches from source bitmap *)
  2929.     stosb                             (* store latches to dest. bitmap *)
  2930.     inc   bx
  2931.     loop  @@ColumnLoop
  2932.     add   bx,[DataInc]
  2933.     add   si,[DataInc]
  2934.     add   di,[NextLineIncr]           (* point to start of next dest row*)
  2935.     dec   ah                          (* decrement scan line counter   *)
  2936.     jnz   @@RowLoop                   (* jump if more scanlines left   *)
  2937.  
  2938.     mov   dx,GC_INDEX+1               (* Restore bitmask to the default - *)
  2939.     mov   al,0ffh                     (*  all data from cpu            *)
  2940.     out   dx,al
  2941.     xor   ax,ax
  2942.     pop   ds                          (* restore data segment          *)
  2943.     pop   di                          (* restore registers             *)
  2944.     pop   si
  2945. @Ok:
  2946. end;
  2947.  
  2948.  
  2949. procedure x_put_masked_vbm_clipy(X,Y:Word;Var SrcVBM); assembler;
  2950. var VBMWidth,VBMHeight,TopRow,NextLineIncr:Word;
  2951. asm
  2952.     push  si
  2953.     push  di
  2954.     push  ds
  2955.     cld
  2956.  
  2957.         mov   ax,[x]
  2958.         and   ax,not 3
  2959.         or    ax,3
  2960.         mov   [x],ax
  2961.  
  2962.     mov   di,[X]                  (* load X coord int DI and make a    *)
  2963.     mov   si,di                   (*  copy in SI                       *)
  2964.  
  2965.  
  2966.     and   si,3                    (* Calculate pixels plane alignment  *)
  2967.     shl   si,1                    (* Prepare to lookup mask & data     *)
  2968.     shl   si,1
  2969.     les   bx,[SrcVBM]             (* ES:BX -> begining of VBM data     *)
  2970.  
  2971.  
  2972. {    mov   ax,es:[bx+ImageHeight]} (* Get image height and save in AX   *)
  2973.     mov   ax,es:[bx+2]
  2974.  
  2975.  
  2976.     (**** CLIP PROCESSING FOR TOP CLIP BORDER ********************)
  2977.  
  2978.     mov   dx,[TopClip]            (* Compare u.l. Y coord with Top     *)
  2979.     sub   dx,[Y]                  (* clipping border                   *)
  2980.     jle   @@NotTopClip            (* jump if VBM not clipped from above*)
  2981.     cmp   dx,ax
  2982.     jnl   @@NotVisible            (* jump if VBM is completely obscured*)
  2983.     mov   [TopRow],dx
  2984.     sub   ax,dx
  2985.     add   [Y],dx
  2986.     jmp   @@VertClipDone
  2987.  
  2988.     (*** EXIT FOR COMPLETELY OBSCURED V.B.M's *********************)
  2989.  
  2990. @@NotVisible:
  2991.     mov   ax,1
  2992.     pop   ds                          (* restore data segment          *)
  2993.     pop   di                          (* restore registers             *)
  2994.     pop   si
  2995.         jmp   @Ok
  2996.  
  2997.     (**** CLIP PROCESSING FOR BOTTOM CLIP BORDER ******************)
  2998.  
  2999. @@NotTopClip:
  3000.     mov   dx,[BottomClip]
  3001.     sub   dx,[Y]
  3002.     js    @@NotVisible
  3003.     mov   [TopRow],0
  3004.     cmp   dx,ax
  3005.     jg    @@VertClipDone
  3006.     inc   dx
  3007.     mov   ax,dx
  3008.  
  3009. @@VertClipDone:
  3010.  
  3011.  
  3012.     shr   di,1                    (* Find Byte offset of X coord       *)
  3013.     shr   di,1
  3014.     add   di,[ScreenOfs]          (* Add the current page offset       *)
  3015. {    mov   cx,es:[bx+ImageWidth]}  (* Get image width and save in CX    *)
  3016.     mov   cx,es:[bx+2]
  3017.     mov   [VBMWidth],cx
  3018.     mov   [VBMHeight],ax
  3019.  
  3020.     (*************************************************************)
  3021.  
  3022.     mov   ax,[Y]                      (* Calculate dest screen row     *)
  3023.     mov   cx,[ScrnLogicalByteWidth]   (*  by mult. dest Y coord by Screen *)
  3024.     mul   cx                          (*  width then adding screen offset *)
  3025.     add   di,ax                       (* Add Dest Screen Row to di     *)
  3026.     sub   cx,[VBMWidth]
  3027.     mov   [NextLineIncr],cx
  3028.  
  3029.     mov   ax,es                       (* copy ES to DS                 *)
  3030.     mov   ds,ax
  3031.     mov   ax,SCREEN_SEG               (* Point es to VGA segment       *)
  3032.     mov   es,ax
  3033.  
  3034. {    mov   ax,[bx+MaskPtr+AlignData+si]} (* DS:SI -> mask data          *)
  3035.     mov   ax,[bx+2+AlignData+si]
  3036. {    mov   bx,[bx+ImagePtr+AlignData+si]}(* ES:BX -> source video bitmap*)
  3037.     mov   bx,[bx+0+AlignData+si]
  3038.         mov   si,ax
  3039.  
  3040.  
  3041.  
  3042.     mov   ax,[VBMWidth]               (* Increment DS:BX and DS:SI to  *)
  3043.     mul   [TopRow]                    (*  skip image/mask data that has*)
  3044.     add   bx,ax                       (*  been clipped by the top border*)
  3045.     add   si,ax
  3046.  
  3047.  
  3048.     mov   dx,GC_INDEX                 (* Set bit mask for all bits from*)
  3049.     mov   ax,BIT_MASK                 (* VGA latches and none from CPU *)
  3050.     out   dx,ax
  3051.     mov   dx,SC_INDEX                 (* Point SC register to map mask *)
  3052.     mov   al,MAP_MASK                 (* in preperation for masking data*)
  3053.     out   dx,al
  3054.     inc   dx                          (* Point dx to SC data register  *)
  3055.     mov   ah,byte ptr [VBMHeight]     (* AH = Scanline loop counter    *)
  3056.  
  3057. @@RowLoop:
  3058.     mov   cx,[VBMWidth]               (* Width in bytes across         *)
  3059.  
  3060. @@ColumnLoop:
  3061.     lodsb
  3062.     out   dx,al
  3063.     mov   al,es:[bx]                  (* load latches from source bitmap*)
  3064.     stosb                             (* store latches to dest. bitmap *)
  3065.     inc   bx
  3066.     loop  @@ColumnLoop
  3067.     add   di,[NextLineIncr]           (* point to start of next dest row*)
  3068.     dec   ah                          (* decrement scan line counter   *)
  3069.     jnz   @@RowLoop                   (* jump if more scanlines left   *)
  3070.  
  3071.     mov   dx,GC_INDEX+1               (* Restore bitmask to the default - *)
  3072.     mov   al,0ffh                     (*  all data from cpu            *)
  3073.     out   dx,al
  3074.  
  3075.     xor   ax,ax
  3076.     pop   ds                          (* restore data segment          *)
  3077.     pop   di                          (* restore registers             *)
  3078.     pop   si
  3079. @Ok:
  3080. end;
  3081.  
  3082. procedure x_put_masked_vbm_clipxy(X,Y:Word;Var SrcVBM); assembler;
  3083. var DataInc,LeftSkip,VBMWidth,VBMHeight,TopRow,NextLineIncr:Word;
  3084. asm
  3085.     push  si
  3086.     push  di
  3087.     push  ds
  3088.     cld
  3089.  
  3090.         mov   ax,[x]
  3091.         and   ax,not 3
  3092.         or    ax,3
  3093.         mov   [x],ax
  3094.  
  3095.     mov   di,[X]                  (* load X coord int DI and make a    *)
  3096.     mov   si,di                   (*  copy in SI                       *)
  3097.     sar   di,1                    (* Find Byte offset of X coord       *)
  3098.     sar   di,1
  3099.     and   si,3                    (* Calculate pixels plane alignment  *)
  3100.     shl   si,1                    (* Prepare to lookup mask & data     *)
  3101.     shl   si,1
  3102.     les   bx,[SrcVBM]             (* ES:BX -> begining of VBM data     *)
  3103.  
  3104. {    mov   cx,es:[bx+ImageWidth]}  (* Get image width and save in CX    *)
  3105.     mov   cx,es:[bx+2]
  3106. {    mov   ax,es:[bx+ImageHeight]} (* Get image height and save in AX   *)
  3107.     mov   ax,es:[bx+4]
  3108.  
  3109.  
  3110.  
  3111.     (**** CLIP PROCESSING FOR TOP CLIP BORDER ********************)
  3112.  
  3113.     mov   dx,[TopClip]            (* Compare u.l. Y coord with Top     *)
  3114.     sub   dx,[Y]                  (* clipping border                   *)
  3115.     jle   @@NotTopClip            (* jump if VBM not clipped from above*)
  3116.     cmp   dx,ax
  3117.     jnl   @@NotVisible            (* jump if VBM is completely obscured*)
  3118.     mov   [TopRow],dx
  3119.     sub   ax,dx
  3120.     add   [Y],dx
  3121.     jmp   @@VertClipDone
  3122.  
  3123.     (***  EXIT FOR COMPLETELY OBSCURED V.B.M's ********************)
  3124.  
  3125. @@NotVisible:
  3126.     mov   ax,1
  3127.     pop   ds                          (* restore data segment          *)
  3128.     pop   di                          (* restore registers             *)
  3129.     pop   si
  3130.         jmp   @Ok
  3131.  
  3132.     (*** CLIP PROCESSING FOR BOTTOM CLIP BORDER *******************)
  3133.  
  3134. @@NotTopClip:
  3135.     mov   dx,[BottomClip]
  3136.     sub   dx,[Y]
  3137.     js    @@NotVisible
  3138.     mov   [TopRow],0
  3139.     cmp   dx,ax
  3140.     jg    @@VertClipDone
  3141.     inc   dx
  3142.     mov   ax,dx
  3143.  
  3144. @@VertClipDone:
  3145.  
  3146.     (**** CLIP PROCESSING FOR LEFT CLIP BORDER *******************)
  3147.  
  3148.  
  3149.     mov   dx,[LeftClip]
  3150.     sub   dx,di
  3151.     jle   @@NotLeftClip
  3152.     cmp   dx,cx
  3153.     jnl   @@NotVisible
  3154.     add   di,dx
  3155.     mov   [LeftSkip],dx
  3156.     mov   [DataInc],dx
  3157.     sub   cx,dx
  3158.     jmp   @@HorizClipDone
  3159.  
  3160.     (**** CLIP PROCESSING FOR RIGHT CLIP BORDER ******************)
  3161.  
  3162. @@NotLeftClip:
  3163.     mov   dx,[RightClip]
  3164.     sub   dx,di
  3165.     js    @@NotVisible
  3166.     mov   [LeftSkip],0
  3167.     mov   [DataInc],0
  3168.     cmp   dx,cx
  3169.     jge    @@HorizClipDone
  3170.     inc   dx
  3171.     sub   cx,dx
  3172.     mov   [DataInc],cx
  3173.     mov   cx,dx
  3174.  
  3175. @@HorizClipDone:
  3176.  
  3177.     add   di,[ScreenOfs]           (* Add the current page offset      *)
  3178.     mov   [VBMWidth],cx
  3179.     mov   [VBMHeight],ax
  3180.     (*************************************************************)
  3181.  
  3182.     mov   ax,[Y]                      (* Calculate dest screen row     *)
  3183.     mov   cx,[ScrnLogicalByteWidth]   (*  by mult. dest Y coord by Screen *)
  3184.     mul   cx                          (*  width then adding screen offset *)
  3185.     add   di,ax                       (* Add Dest Screen Row to di     *)
  3186.     sub   cx,[VBMWidth]
  3187.     mov   [NextLineIncr],cx
  3188.  
  3189.     mov   ax,es                       (* copy ES to DS                 *)
  3190.     mov   ds,ax
  3191.     mov   ax,SCREEN_SEG               (* Point es to VGA segment       *)
  3192.     mov   es,ax
  3193.  
  3194. {    mov   ax,[bx+MaskPtr+AlignData+si]} (* DS:SI -> mask data          *)
  3195.     mov   ax,[bx+2+AlignData+si]
  3196. {    mov   bx,[bx+ImagePtr+AlignData+si]} (* ES:BX -> source video bitmap*)
  3197.     mov   bx,[bx+0+AlignData+si]
  3198.     mov   si,ax
  3199.  
  3200.  
  3201.  
  3202.     mov   ax,[VBMWidth]               (* Increment DS:BX and DS:SI to  *)
  3203.     add   ax,[DataInc]                (*  skip image/mask data that has*)
  3204.     mul   [TopRow]                    (*  been clipped by the top border*)
  3205.     add   ax,[LeftSkip]               (* Skip also data/mask bytes in  *)
  3206.     add   bx,ax                       (* each row that have been clipped*)
  3207.     add   si,ax                       (* by the L.H.S border           *)
  3208.  
  3209.  
  3210.     mov   dx,GC_INDEX                 (* Set bit mask for all bits from*)
  3211.     mov   ax,BIT_MASK                 (* VGA latches and none from CPU *)
  3212.     out   dx,ax
  3213.     mov   dx,SC_INDEX                 (* Point SC register to map mask *)
  3214.     mov   al,MAP_MASK                 (* in preperation for masking data*)
  3215.     out   dx,al
  3216.     inc   dx                          (* Point dx to SC data register  *)
  3217.     mov   ah,byte ptr [VBMHeight]     (* AH = Scanline loop counter    *)
  3218.  
  3219. @@RowLoop:
  3220.     mov   cx,[VBMWidth]               (* Width in bytes across         *)
  3221.  
  3222. @@ColumnLoop:
  3223.     lodsb
  3224.     out   dx,al
  3225.     mov   al,es:[bx]                  (* load latches from source bitmap*)
  3226.     stosb                             (* store latches to dest. bitmap *)
  3227.     inc   bx
  3228.     loop  @@ColumnLoop
  3229.     add   bx,[DataInc]
  3230.     add   si,[DataInc]
  3231.     add   di,[NextLineIncr]           (* point to start of next dest row*)
  3232.     dec   ah                          (* decrement scan line counter   *)
  3233.     jnz   @@RowLoop                   (* jump if more scanlines left   *)
  3234.  
  3235.     mov   dx,GC_INDEX+1               (* Restore bitmask to the default - *)
  3236.     mov   al,0ffh                     (*  all data from cpu            *)
  3237.     out   dx,al
  3238.     xor   ax,ax
  3239.     pop   ds                          (* restore data segment          *)
  3240.     pop   di                          (* restore registers             *)
  3241.     pop   si
  3242. @Ok:
  3243. end;
  3244.  
  3245.  
  3246.  
  3247. (* unit end -  yeahhh *)
  3248. end.
  3249.