From: bbs.brienv@tsoft.sf-bay.org (Brien Voorhees)
Newsgroups: rec.games.programmer
Subject: fast VGA sprite routines
Date: 13 Aug 92 19:34:14 GMT
Organization: The TSoft BBS and Public Access Unix, +1 415 969 8238


  I've been working on some graphics routines for VGA mode 13h to handle
animating sprites while retaining the background and have managed to get
 'em goin' pretty fast (about 25-35 fps on a 486) but that's without 
much other overhead.  Once I add collision detection, sound, music, etc.
I don't think I'm going to have enough cpu time to spare.
  Does anyone know techniques to speed up graphics routines?  Here's an
overview of how my routines work :
  During any given cycle, the following things happen :
  The Master copy of the background (in a 64k buffer) is copied into the
work buffer (also 64k).
  All sprites are written to the work buffer.
  After all movement is done, the work buffer is copied into screen 
memory
with a REP MOVSW.  Predictably, this single instruction is where the vast
majority of the CPU's time is taken thanks to the slowness of video 
memory.
The other (much less severe)bottleneck is the putimage routine. In my 
putimg
routine, I grab each byte/pixel from the sprite image buffer and compare 
it
against zero ( the background color). If it's a zero byte, I skip it and 
go
to the next one, otherwise I write it to the WorkBuffer.
 
.............Here's the core of the CopyWorkToScreen 
routine:...............
    mov si,workoff  // offset of workbuffer
    mov ax,0a000h
    mov es,ax
    mov di,0
    mov ax,workseg  // segment of workbuffer
    mov ds,ax
#ifdef CODE386  // tc++ inline asm doesn't seem to like 386 instructions
    mov cx,03e80h
    rep movsd
#else          // so presently this (word) version is being used instead
    mov cx,07d00h
    rep movsw      // copy all that crap to slow screen memory.
#endif
 
...................Here's my PutImage routine :.......................
void putframe(char *buffer,int x1, int y1, int xwidth, int ywidth)
{
  int nextlineoffset,startaddr;
  nextlineoffset=320-xwidth; // Amount to add to get to the correct 
offset
                             // for the next line.
  startaddr=320 * y1 + x1 + workoff; // workoff = address of the 
workbuffer
 
 asm{
    push  es
    mov   ax,workseg // Segment of (far char*) Work Buffer
    mov   es,ax
    mov   di,startaddr
    mov   si,buffer  // (char*) buffer holds the sprite frame data 
    mov   cx,ywidth  // Set outer loop to run <ywidth> times
rowloop:             // once per row (duh)
    push  cx         // save what row we're on
    mov   cx,xwidth  // Set inner loop to run for each pixel on this line
subloop:  // There are actually two loop instructions that goto this 
label
    lodsb            // grab a pixel
    cmp   al,0
    je short itsblank  // if it's 0, skip it
    stosb              // otherwise, write it
    loop  subloop
    jmp short endsubloop  // Jump outta' here. Don't wanna' fall thru to  

                          // the other subloop section!
itsblank:
    inc   di              // Keep the destination index in sync
    loop  subloop         // Ready for the next pixel
 
endsubloop:             
    add   di,nextlineoffset  // Set destination pointer to proper offset 
                             // for beginning of next image line
    pop   cx              // Where were we?
    loop  rowloop         // Ready for next line
    pop   es
}
}
  Is there any way at all to speed access to video memory?  Perhaps 
slowing the refresh rate would help?  (if so, how do I?)
  Also, are there any optimizations that can be made to my PutImage 
routine?
I'm very new to assembly so, though I tried my best to optimize that 
routine, I'm sure you graphics veterans c'n come up with a few tricks! 
      Any help would be enormously appreciated!!!
While I'm at it, does anyone have the specs to the .MOD music format?

 Brien "I Link Therefore I Am" Voorhees

--
Brien Voorhees (bbs.brienv@tsoft.sf-bay.org)