{
> Another problem is plotting sprites with "invisible" pixels.  In other
> words, all pixels in the sprite are plotted except for ones with a color
> of 255 (I think I've heard that Origin used this method in Ultima 6).
> Because of my unsuccessful try with asm earlier, I didn't even bother to
> try this in asm.  Unfortunately, the following is MUCH too slow:

try this!
}
uses crt;
type SpriteType = array[0..15,0..15] of byte;

var sprite : spritetype;
    f : file of spritetype;     {sprite's image is stored in file}
    x, y : word;

procedure putinvspriteinasm(x, y : word; sprite : spritetype);
var p : pointer;
    segm, offs : word;
    {these are used to calculate destination address
     in video memory}

begin
  p := addr(sprite[0,0]);
  {this pointer is used only to cheat tp. tp doesn't allow to use addr or
   @ operators in inline asm - or i don't know how to do it}
  segm := $a000 + (320 * y) div 16;
  offs := x;
  {segm:offs is address of upper left corner of sprite in video RAM}
      asm
          push   ds
  {ds is one of the important registers in tp and must be saved}
          lds    si, p
  {ds:si now is source address for sprite's array}
          mov    es, segm
          mov    di, offs
  {es:di now is target address in VRAM}
          mov    bh, 16
  {counter for outer loop}
@loop2:   mov    bl, 16
@loop1:   mov    al, [ds:si]
  {innner loop (marked with label @loop1) is used to draw each line of
   sprite}
          cmp    al, $ff
   {make sure if pixel is $ff or not}
          je     @skip
   {it is - so we don't draw it}
          mov    [es:di], al
   {no, it's not - draw!}
@skip:    inc    si
          inc    di
          dec    bl
          jnz    @loop1
   {we haven't finished to draw this line if bl > 0}
          dec    bh
   {we haven't finished to draw all image if bh > 0}
          jz     @end
          add    di, 320 - 16
   {calculate beginning of next line}
          jmp    @loop2
@end:
          pop    ds

      end
end;

begin
  asm mov ax, 0013h
      int 10h
  end;
  assign(f, 'sprite');
  reset(f);
  read(f, sprite);
  close(f);
  randomize;
  repeat
    x := random(320);
    y := random(200);
    putinvspriteinasm(x, y, sprite);
  until keypressed;
end.
{
i added into code some quick'n'dirty comments to let you understand
how assembly works. i've tested this code and found that it won't work with
Microsoft's workgrp.sys driver - the programm simply crashes when you press a
key. (workgrp.sys driver is one of the Windows for Workgroups drivers).
strange... with all other things (qemm386, lan drivers etc.) programm seems to
work fine. one more thing i must add that better is to pass to procedure
putsprite not array with sprite's data but only pointer to it - because tp
moves all this data around memory - and in this case it's 256 bytes.
}
