[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]

    {
    > 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.
    }

[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]