home *** CD-ROM | disk | FTP | other *** search
/ PC Underground / UNDERGROUND.ISO / graphic / sprites.pas < prev    next >
Pascal/Delphi Source File  |  1995-08-02  |  11KB  |  240 lines

  1. {$G+}
  2. Unit Sprites;
  3. Interface
  4. Type SpriteTyp=Record           {structure of a sprite data block}
  5.   Addr:Pointer;                 {pointer to graphic data}
  6.   dtx,dty:Word;                 {width and height in pixels}
  7.   px,py,                        {current position, optional *}
  8.   sx,sy:Integer;                {current speed, optional *}
  9. End;
  10. {*: optional means that the sprite routines GetSprite and PutSprite
  11.  don't use these specifications, the variables only serve to make
  12.  control easier forthe main program}
  13.  
  14. Procedure GetSprite(Ofs,dtx,dty:Word;var zSprite:SpriteTyp);
  15. {read a sprite from vscreen-Offset ofs, with dtx width and dty height,
  16.  zsprite is the sprite record in which the sprite is to be saved}
  17.  
  18. Procedure PutSprite(pg_ofs,x,y:Integer;qsprite:spritetyp);
  19. {copies sprite from RAM (position and size taken from qsprite)
  20.  to video RAM page pg at position (x/y)}
  21.  
  22. Implementation
  23. Uses ModeXLib;
  24. Var i:Word;
  25.  
  26. Procedure GetSprite;
  27. Var ppp:Array[0..3] of Byte;    {table with number of pixels to copy}
  28.                                 {per plane}
  29.     Skip:word;                  {number of bytes to skip}
  30.     Plane_Count:Word;           {counter of copied planes}
  31. Begin
  32.   GetMem(zsprite.addr,dtx*dty); {allocate RAM}
  33.   zsprite.dtx:=dtx;             {note width and height in sprite record}
  34.   zsprite.dty:=dty;
  35.  
  36.   i:=dtx shr 2;                 {number of smooth blocks of 4}
  37.   ppp[0]:=i;ppp[1]:=i;          {equals minimum number of bytes to copy}
  38.   ppp[2]:=i;ppp[3]:=i;
  39.   For i:=1 to dtx and 3 do      {note "excess" pixels in ppp}
  40.     Inc(ppp[(i-1) and 3]);      {add pixels beginning with Startplane}
  41.   Plane_Count:=4;               {copy 4 planes}
  42. asm
  43.   push ds
  44.   mov di,word ptr zsprite       {first load pointer to data block}
  45.   les di,[di]                   {load pointer to graphic data in es:di}
  46.   lea bx,ppp                    {bx points to ppp array}
  47.  
  48.   lds si,vscreen                {load pointer to image}
  49.    add Ofs,si                   {offset of actual sprite data in addition}
  50. @lcopy_plane:                   {will be performed once per plane}
  51.   mov si,ofs                    {load si with start address of sprite data}
  52.   mov dx,dty                    {load y-counter with row number}
  53.  
  54.   xor ah,ah                     {clear ah}
  55.   mov al,ss:[bx]                {load al with current ppp entry}
  56.   shl ax,2                      {blocks of 4 get moved}
  57.   sub ax,320                    {obtain difference to 320}
  58.   neg ax                        {make 320-ax out of ax-320}
  59.   mov skip,ax                   {store value in skip}
  60.  
  61. @lcopy_y:                       {perform once per row}
  62.   mov cl,ss:[bx]                {load width from ppp-array}
  63. @lcopy_x:                       {perform once per pixel}
  64.   movsb                         {copy byte}
  65.   add si,3                      {to next pixel of this plane}
  66.   dec cl                        {copy all the pixels of this row}
  67.   jne @lcopy_x
  68.  
  69.   add si,skip                   {after that, at beginning of next row}
  70.   dec dx                        {copy all rows}
  71.   jne @lcopy_y
  72.  
  73.   inc bx                        {position at next ppp entry}
  74.   inc ofs                       {position at new plane start}
  75.   dec plane_count               {copy all planes}
  76.   jne @lcopy_plane
  77.   pop ds
  78. End;
  79. End;
  80.  
  81. Procedure PutSprite;
  82. var plane_count,                {counter of copied planes}
  83.     planemask:Byte;             {masked Write-Plane in TS-Register 2}
  84.     Skip,                       {number of bytes to skip}
  85.     ofs,                        {current offset in video RAM}
  86.     plane,                      {number of current plane}
  87.     Width,                      {width of bytes to be copied in a row,}
  88.     dty:Word;                   {height}
  89.     source:Pointer;             {pointer to graphic data, if ds modified}
  90.     clip_lt, clip_rt:integer;   {number of excess PIXELS left and right}
  91.     clipact_lt,                 {with current plane active number}
  92.     clipact_rt,                 {excess BYTES}
  93.     clip_dn,clip_up:Word;       {number of excess ROWS above and below}
  94.  
  95.     ppp:Array[0..3] of Byte;    {number of pixels per plane}
  96.     cpp:Array[0..3] of Byte;    {excess BYTES per plane}
  97.  
  98. Begin
  99.   if (x > 319) or               {Display unnecessary, }
  100.   (x+qsprite.dtx < 0) or        {because it's not even in the picture ?}
  101.   (y > 199) or
  102.   (y+qsprite.dty < 0) then exit;
  103.   clip_rt:=0;                   {no clipping normally}
  104.   clip_lt:=0;                   {-> all clipping variables to 0}
  105.   clip_dn:=0;
  106.   clip_up:=0;
  107.   clipact_rt:=0;
  108.   clipact_lt:=0;
  109.    with qsprite do begin
  110.     if y+dty > 200 then begin   {first clipping case: down}
  111.       clip_dn:=(y+dty-200);     {note excess rows}
  112.       dty:=200-y;               {and reduce sprite height}
  113.     End;
  114.     if y<0 then begin           {second clipping case: up}
  115.       clip_up:=-y;              {note excess rows}
  116.       dty:=dty+y;               {and reduce sprite height}
  117.       y:=0;                     {Start-y is 0, because upper screen border}
  118.     End;
  119.     if x+dtx > 320 then begin   {third clipping case: right}
  120.       clip_rt:=x+dtx-320;       {note excess pixels}
  121.       dtx:=320-x;               {reduce width}
  122.     End;
  123.     if x<0 then begin           {fourth clipping case: left}
  124.       clip_lt:=-x;              {note excess pixels}
  125.       plane:=4-(clip_lt mod 4); {calculate new start plane for column 0}
  126.       plane:=plane and 3;       {reduce this to 0..3}
  127.       ofs:=pg_ofs+80*y+((x+1) div 4) - 1;  {set Ofs to correct block of 4}
  128.       x:=0;                     {begin display in column}
  129.     End Else Begin              {no clipping to the right ?}
  130.       plane:=x mod 4;           {then conventional calculation of plane}
  131.       ofs:=pg_ofs+80*y+(x div 4); {and offset}
  132.     End;
  133.   End;
  134.   Source:=qsprite.addr;         {pointer graphic data}
  135.   dty:=qsprite.dty;             {and save height in local variables}
  136.   Width:=0;                     {preinitialize width and skip}
  137.   Skip:=0;
  138.  
  139.   i:=qsprite.dtx shr 2;         {even number blocks of 4}
  140.   ppp[0]:=i;ppp[1]:=i;          {equals minimum number of bytes to be copied}
  141.   ppp[2]:=i;ppp[3]:=i;
  142.   For i:=1 to qsprite.dtx and 3 do{note "excess" pixels in ppp}
  143.     Inc(ppp[(plane+i - 1) and 3]);{add pixels beginning with StartPlane}
  144.  
  145.   i:=(clip_lt+clip_rt) shr 2;
  146.   cpp[0]:=i;cpp[1]:=i;          {Clipping default : all pages 0}
  147.   cpp[2]:=i;cpp[3]:=i;
  148.   For i:=1 to clip_rt and 3 do  {if right clipping, enter corresponding number}
  149.     Inc(cpp[i-1]);              {in planes}
  150.   For i:=1 to clip_lt and 3 do  {if left clipping, enter corresponding number}
  151.     Inc(cpp[4-i]);              {in planes}
  152.  
  153. asm
  154.   mov dx,3ceh                   {GDC Register 5 (GDC Mode)}
  155.   mov ax,4005h                  {set to Write Mode 0}
  156.   out dx,ax
  157.   push ds                       {save ds}
  158.   mov ax,0a000h                 {load destination segment (VGA)}
  159.   mov es,ax
  160.  
  161.   lds si,source                 {source (pointer to graphic data) to ds:si}
  162.   mov cx,plane                  {create starting plane mask}
  163.   mov ax,1                      {move Bit 0 left by plane}
  164.   shl ax,cl
  165.   mov planemask,al              {save mask}
  166.   shl al,4                      {enter in upper nibble also}
  167.   or planemask,al
  168.   mov plane_count,4             {4 planes to copy}
  169. @lplane:                        {will run once per plane}
  170.   mov cl,byte ptr plane         {load current plane}
  171.   mov di,cx                     {in di}
  172.   mov cl,byte ptr ppp[di]       {load cx with matching ppp number}
  173.   mov byte ptr Width,cl         {recalculate step size}
  174.   mov ax,80                     {difference from 80}
  175.   sub al,cl
  176.   mov byte ptr skip,al          {and copy to skip}
  177.  
  178.   mov al,byte ptr cpp[di]       {load plane specific clipping width}
  179.   cmp clip_lt,0                 {if left no clipping, continue with right}
  180.   je @right
  181.   mov clipact_lt,ax             {save in clip_act_lt}
  182.   sub Width,ax                  {reduce width of bytes to be copied}
  183.   jmp @clip_rdy                 {no clipping right}
  184. @right:                         {if left no clipping}
  185.   mov clipact_rt,ax             {clipping for all planes, in clip_act}
  186. @clip_rdy:
  187.   mov ax,Width                  {calculate total width in bytes}
  188.   add ax,clipact_rt
  189.   add ax,clipact_lt
  190.   mul clip_up                   {multiply by number of rows at top clipping}
  191.   add si,ax                     {these bytes are not displayed}
  192.   mov cx,Width                  {load cx with width}
  193.   or cl,cl                      {width 0, then plane finished}
  194.   je @plane_finished
  195.   mov di,ofs                    {destination offset in video RAM to di}
  196.   mov ah,planemask              {reduce plane mask to bit [0..3]}
  197.   and ah,0fh
  198.   mov al,02h                    {and via TS - Register 2 (Write Plane Mask)}
  199.   mov dx,3c4h                   {set}
  200.   out dx,ax
  201.   mov bx,dty                    {initialize y-counter}
  202. @lcopy_y:                       {y-loop,perform once per row}
  203.   add si,clipact_lt             {add source pointer for left clipping}
  204.   add di,clipact_lt             {destination pointer also}
  205. @lcopy:                         {x-loop, perform once per pixel}
  206.   lodsb                         {get byte}
  207.   or al,al                      {if 0, then skip}
  208.   je @Value0
  209.   stosb                         {else set}
  210. @entry:
  211.   loop @lcopy                   {and continue loop}
  212.   add si,clipact_rt             {after complete row right clipping}
  213.   dec bx                        {continue y-counter}
  214.   je @plane_finished            {y-counter = 0, then next plane}
  215.   add di,skip                   {else skip to beginning of next row}
  216.   mov cx,Width                  {reinitialize x-counter,}
  217.   jmp @lcopy_y                  {jump back to y-loop}
  218. @value0:                        {sprite color 0:}
  219.   inc di                        {skip to destination byte}
  220.   jmp @entry                    {and back to loop }
  221. @plane_finished:                {y-loop ends here}
  222.   mov ax,Width                  {calculate total width in bytes}
  223.   add ax,clipact_rt
  224.   add ax,clipact_lt
  225.   mul clip_dn                   {multiply times number at bottom clipping}
  226.   add si,ax                     {these bytes won't be displayed}
  227.   rol planemask,1               {select next plane}
  228.   mov cl,planemask              {plane 0 selected ?}
  229.   and cx,1                      {(Bit 1 set), then}
  230.   add ofs,cx                    {increase destination offset by 1 (cx Bit 1 !)}
  231.   inc plane                     {increment plane number (Index in ppp)}
  232.   and plane,3                   {reduce to 0 to 3}
  233.   dec plane_count               {4 planes already copied ?, then end}
  234.   jne @lplane
  235.   pop ds                        {restore ds, and see you later}
  236. End;{asm}
  237. End;
  238. Begin
  239. End.
  240.