/* %kw # %v %n %d %t # */ /* Version # 2 SPRITES.CPP 16-Dec-93 19:07:16 # */ /* ************************************************** */ /* METAGRAPHICS SOFTWARE CORPORATION (c) 1993 */ /* Demonstrates use of sprite animation */ /* ************************************************** */ #include #include #include #include #include #include #include "metawndo.h" /* master MetaWINDOW include file */ #include "pcxlab.h" /* PCX lab include file */ /* special stack size declaration if using Turbo or Borland C++ */ #ifdef TurboC extern unsigned _stklen = 14336U; /* stack size 14K */ #endif // this sample uses the transparent icon class developed in sample ICON.CPP // define icon class #include "icons.hpp" void FlipDisplay( int page ); void WaitDisplayBusy( int busy ); #define pcxname "icons.pcx" void main( ) { int i, x,y; pcxHead pcxHeader; /* buffer for reading the files PCX header */ palData RGBInfo[256]; /* buffer for reading the files palette */ rect tmpR; /* variables for getting the brush image */ long imsize; /* off the screen */ image *brush; Icon *brushIcon[2]; /* one icon for each page */ grafMap page2Bitmap, *bitmapPage[2]; grafPort *thePort; int page; /* init the system */ i = InitGraphics( EGA640x350 ); if( i != 0 ) { printf("MetaWINDOW Initialization error #%d\n", i); exit(2); } /* set up second page bitmap for page flip support */ i = InitBitmap( EGA640x350, &page2Bitmap ); SetBitmap( GrafPg1, &page2Bitmap ); /* keep an array of the bitmap pointers for each page */ GetPort( &thePort ); bitmapPage[0] = thePort->portMap; bitmapPage[1] = &page2Bitmap; /* put into graphics mode */ SetDisplay( GrafPg0 ); /* get a bitmap up on the screen via readpcx file */ /* Read PCX File Header Information */ if ( ReadPCXInfo( pcxname, &pcxHeader, RGBInfo ) == False ) { SetDisplay( TextPg0 ); printf("Can't read PCX file!\n"); StopGraphics(); exit(1); } /* set palette, based on palette in PCX file */ WritePalette( 0, 0, (int) QueryColors(), RGBInfo ); /* Read PCX File to both pages */ ReadPCX( pcxname, NULL, NULL ); MoveTo( 10, 300 ); DrawString( "Page 0" ); PortBitmap( bitmapPage[1] ); i = ReadPCX( pcxname, NULL, NULL ); MoveTo( 70, 300 ); DrawString( "Page 1" ); if( i == False ) { SetDisplay( TextPg0 ); printf("Can't display this file in current video mode!\n" ); StopGraphics(); exit(1); } /* allocate a buffer to hold the brush image */ SetRect( &tmpR, 0,0,40,50); imsize = ImageSize( &tmpR ); brush = ( image *) malloc( (size_t) imsize ); if( brush == NULL ) { SetDisplay( TextPg0 ); printf("Can't allocate brush image\n"); StopGraphics(); exit(1); } /* read the icon from the screen bitmap into an image buffer */ ReadImage( &tmpR, brush ); /* make an icon out of the brush image, LtBlue is the transparent color */ brushIcon[0] = new Icon( brush, LtBlue ); /* we don't need the source image anymore */ free( brush ); /* make a copy of it for the second page */ brushIcon[1] = new Icon( brushIcon[0] ); /* lets move this icon accross the screen */ page = 0; while( !kbhit() ) { for( y = 0; y < 350; y += 5 ) { for( x = 0; x < 640; x += 5 ) { /* display page */ FlipDisplay( GrafPg0 + page ); /* flip to other page */ page ^= 1; /* draw to page */ PortBitmap( bitmapPage[page] ); /* draw the icon */ brushIcon[page]->Show( x, y ); if( kbhit() ) break; } if( kbhit() ) break; } } delete brushIcon[0]; delete brushIcon[1]; SetDisplay( TextPg0 ); StopGraphics(); i = QueryError(); printf("QueryError=%d/%d\n",i >> 7,i & 127); exit(i); } /* Flip an EGA or VGA to display the second page. We don't use SetDisplay() becaue it uses the video cards BIOS ROM to request a page flip. BIOS ROMS from different manufacturers exhibit different behavior. Some wait for the page to become active before returning, some don't. Some take a verrrrry looong time to switch pages (who knows what goofy things they do). SetDisplay also has to do some extra stuff to make sure the BIOS does what it's supposed to (like modify the equipment word in case you were mode mono). */ void FlipDisplay( int page ) { switch( page ) { case GrafPg0: outp( 0x3D4, 0x0C ); // CRTC index 0C, start address high outp( 0x3D5, 0 ); break; case GrafPg1: outp( 0x3D4, 0x0C ); // CRTC index 0C, start address high outp( 0x3D5, 0x80 ); break; } // wait for a transition into vertical retrace, this will make sure // that our new page is displayed before we start modifying the other WaitDisplayBusy( True ); WaitDisplayBusy( False ); } /* wait for display to: busy = True be in display period busy = False be in vertical retrace period */ void WaitDisplayBusy( int busy ) { int CRTStatusPort, vsync; CRTStatusPort = 0x3DA; // EGA\VGA color and CGA if( busy ) { // waiting for vertical retrace bit = 0 vsync = 1; while( vsync ) // read the vertical retrace status bit of the CRT status port vsync = inp( CRTStatusPort ) & 8; } else { // waiting for vertical retrace bit = 1 vsync = 0; while( !vsync ) // read the vertical retrace status bit of the CRT status port vsync = inp( CRTStatusPort ) & 8; } }