home *** CD-ROM | disk | FTP | other *** search
- #include<io.h>
- #include<conio.h>
- #include<stdio.h>
- #include<stdlib.h>
- #include<dos.h>
- #include<bios.h>
- #include<fcntl.h>
- #include<memory.h>
- #include<malloc.h>
- #include<math.h>
- #include<string.h>
-
- #include "magic3.h"
- #include "magic4.h"
-
- // G L O B A L S ////////////////////////////////////////////////////////////
-
- // default sprite width and height
-
- unsigned int sprite_width = SPRITE_WIDTH;
-
- unsigned int sprite_height = SPRITE_HEIGHT;
-
- unsigned char far *double_buffer = NULL; // the double buffer
-
- // the default dimensions of the double buffer
-
- unsigned int double_buffer_height = SCREEN_HEIGHT;
-
- // size of double buffer in WORDS
-
- unsigned int double_buffer_size = SCREEN_WIDTH*SCREEN_HEIGHT/2;
-
- // MODE Z STUFF
-
- unsigned char far *page_0_buffer = (unsigned char far *)0xA0000000L;
-
- unsigned char far *page_1_buffer = (unsigned char far *)0xA0008000L;
-
- int mode_z_page = PAGE_0;
-
- // MODE Y STUFF
-
- unsigned char far *pagey_0_buffer = (unsigned char far *)0xA0000000L;
-
- unsigned char far *pagey_1_buffer = (unsigned char far *)0xA0004000L;
-
- unsigned char far *pagey_2_buffer = (unsigned char far *)0xA0008000L;
-
- unsigned char far *pagey_3_buffer = (unsigned char far *)0xA000C000L;
-
- int mode_y_page = PAGE_0;
-
- // "SLOW RUNNINGS" SPECIFIC STUFF
-
- unsigned char far *never_displayed_buffer_mode_y = (unsigned char far *)0xA0008000L;
-
- unsigned char far *never_prime = (unsigned char far *)0xA000C900L;
-
- // F U N C T I O N S /////////////////////////////////////////////////////////
-
- void Line_HDB(int x1,int x2,int y,int color)
- {
- // draw a horizontal line using the memset function
- // this function does not do clipping hence x1,x2 and y must all be within
- // the bounds of the screen
-
- _fmemset((char far *)(double_buffer + ((y<<8) + (y<<6)) + x1),
- (unsigned char)color,x2-x1+1);
-
- } // end Line_HDB
-
- //////////////////////////////////////////////////////////////////////////////
-
- void Line_VDB(int y1,int y2,int x,int color)
- {
- // draw a vertical line, note that a memset function can no longer be
- // used since the pixel addresses are no longer contiguous in memory
- // note that the end points of the line must be on the screen
-
- unsigned char far *start_offset; // starting memory offset of line
-
- int index; // loop index
-
- // compute starting position
-
- start_offset = double_buffer + ((y1<<8) + (y1<<6)) + x;
-
- for (index=0; index<=y2-y1; index++)
- {
- // set the pixel
-
- *start_offset = (unsigned char)color;
-
- // move downward to next line
-
- start_offset+=320;
-
- } // end for index
-
- } // end Line_VDB
-
- void Screen_Transition(int effect)
- {
- // this function can be called to perform a myriad of screen transitions
- // to the video buffer, note I have left one for you to create!
-
- int pal_reg; // used as loop counter
- long index; // used as loop counter
- RGB_color color; // temporary
-
- // test which screen effect is being selected
-
- switch(effect)
- {
- case SCREEN_DARKNESS:
- {
- // fade to black
-
- for(index=0; index<20; index++)
- {
- // loop thru all palette registers
-
- for(pal_reg=0; pal_reg<255; pal_reg++)
- {
- // get the next color to fade
-
- Read_Color_Reg(pal_reg,(RGB_color_ptr)&color);
-
- // test if this color register is already black
- if (color.red > 4) color.red-=3;
- else
- color.red = 0;
-
- if (color.green > 4) color.green-=3;
- else
- color.green = 0;
-
- if (color.blue > 4) color.blue-=3;
- else
- color.blue = 0;
-
- // set the color to a diminshed intensity
-
- Write_Color_Reg(pal_reg,(RGB_color_ptr)&color);
-
- } // end for pal reg
-
- // wait a bit
-
- Time_Delay(1);
-
- } // end for index
-
- }
- break;
-
- case SCREEN_WHITENESS:
- {
- // fade to white
-
- for(index=0; index<20; index++)
- {
- // loop thru all palette registers
-
- for(pal_reg=0; pal_reg<255; pal_reg++)
- {
- // get the next color to fade
-
- Read_Color_Reg(pal_reg,(RGB_color_ptr)&color);
-
- color.red += 4;
-
- // test if this color register is already white
- if (color.red > 63)
- color.red=63;
-
- color.green += 4;
-
- if (color.green > 63)
- color.green=63;
-
- color.blue +=4;
-
- if (color.blue > 63)
- color.blue=63;
-
- // set the color to a brighter intensity
-
- Write_Color_Reg(pal_reg,(RGB_color_ptr)&color);
-
- } // end for pal reg
-
- // wait a bit
-
- Time_Delay(1);
-
- } // end for index
-
- }
- break;
-
- case SCREEN_WARP:
- {
- // THIS ONE I'LL DO LATER!
- }
- break;
-
- case SCREEN_SWIPE_X:
- {
- // do a screen swipe from right to left, left to right
-
- for (index = 0; index < 160; index+=2)
- {
- // use this as a 1/70th of second time delay
-
- Wait_For_Vertical_Retrace();
-
- // draw two vertical lines at opposite ends of the screen
-
- Line_V(0,199,319-index,0);
- Line_V(0,199,index,0);
- Line_V(0,199,319-(index+1),0);
- Line_V(0,199,index+1,0);
- } // end for index
- }
- break;
-
- case SCREEN_SWIPE_Y:
- {
- // do a screen swipe from top to bottom, bottom to top
-
- for (index = 0; index < 100; index+=2)
- {
- // use this as a 1/70th of second time delay
-
- Wait_For_Vertical_Retrace();
-
- // draw two horizontal lines at opposite ends of the screen
-
- Line_H(0,319,199-index,0);
- Line_H(0,319,index,0);
- Line_H(0,319,199-(index+1),0);
- Line_H(0,319,index+1,0);
- } // end for index
- }
- break;
-
- case SCREEN_DISSOLVE:
- {
- // disolve the screen by plotting zillions of little black dots
- for (index = 0; index <= 300000; index++)
- Write_Pixel(rand()%320, rand()%200, 0);
- }
- break;
-
- case FULL_SCREEN_DARKNESS:
- {
- // fade to black
-
- for(index=0; index<20; index++)
- {
- // loop thru all palette registers
-
- for(pal_reg=0; pal_reg<=255; pal_reg++)
- {
- // get the next color to fade
-
- Read_Color_Reg(pal_reg,(RGB_color_ptr)&color);
-
- // test if this color register is already black
- if (color.red > 4) color.red-=3;
- else
- color.red = 0;
-
- if (color.green > 4) color.green-=3;
- else
- color.green = 0;
-
- if (color.blue > 4) color.blue-=3;
- else
- color.blue = 0;
-
- // set the color to a diminshed intensity
-
- Write_Color_Reg(pal_reg,(RGB_color_ptr)&color);
-
- } // end for pal reg
-
- // wait a bit
-
- Time_Delay(1);
-
- } // end for index
-
- }
- break;
-
- default:break;
-
- } // end switch
- } // end Screen_Transition
-
- int Create_Double_Buffer(int num_lines)
- {
- // allocate enoughmemoryto hold the double buffer
-
- if ((double_buffer = (unsigned char far *)_fmalloc(SCREEN_WIDTH * (num_lines + 1))) == NULL)
- {
- printf("\nCouldn't allocate double buffer.");
- return(0);
- } // end if couldn't allocate
-
- // set the height of the buffer andcompute its size
-
- double_buffer_height = num_lines;
- double_buffer_size = SCREEN_WIDTH * num_lines/2;
-
- // fill the buffer with black
-
- _fmemset(double_buffer,0,SCREEN_WIDTH * num_lines);
-
- // everything was O.K....
-
- return(1);
-
- } // end Create_Double_Buffer
-
- void Fill_Double_Buffer(int color)
- {
- // this function fills in the double buffer with the sent color a WORD at
- // a time
-
- _asm
- {
- mov cx,double_buffer_size ; this is the size of buffer is WORDS
- mov al,BYTE PTR color ; move the color into al
- mov ah,al ; move the color into ah
- les di,double_buffer ; es:di points to the double buffer
- rep stosw ; fill all the words
- } // end asm
- } // end Fill_Double_Buffer
-
- void Display_Double_Buffer(unsigned char far *buffer, int y)
- {
- // this function copies the double buffer into the video buffer at the
- // starting y location
-
- _asm
- {
- push ds ; save DS on stack
- mov cx,double_buffer_size ; this is the size of buffer in WORDS
- les di,video_buffer ; es:di is destination of memory move
- mov ax,320 ; multiply y by 320 i.e. screen width
- mul y
- add di, ax ; add result to es:di
- lds si,buffer ; ds:si is source of memory move
- rep movsw ; mov all the words
- pop ds ; restore the data segment
- } // end asm
- } // end Display_Double_Buffer
-
- void Delete_Double_Buffer(void)
- {
- // this function frees upthe memory allocated by the double buffer
- // make sure to use FAR version
-
- if (double_buffer)
- _ffree(double_buffer);
-
- } // end Delete_Double_Buffer
-
- void Bitmap_Put(bitmap_ptr image, unsigned char far *destination, int transparent)
- {
- // this function draw a bitmap on the destination buffer which can
- // be a double buffer or the video buffer
-
- int x,y, // looping variables
- width,height; // size of bitmap
-
- unsigned char far *bitmap_data; // pointer to bitmap buffer
- unsigned char far *dest_buffer; // pointer to destination buffer
-
- unsigned char pixel; // current pixel value being processed
-
- // compute offset of bitmap in destination buffer. Note: all video or
- // double buffers must be 320 bytes wide!
-
- dest_buffer = destination + (image->y << 8) + (image->y << 6) + image->x;
-
- // create aliases to variables so the structure doesn't need to be
- // dereferenced continually
-
- height = image->height;
- width = image->width;
- bitmap_data = image->buffer;
-
- // test if transparency is on or off
-
- if (transparent)
- {
- // use version that will draw a transparent bitmap (slightly slower)
- // draw each line of the bitmap
-
- for (y = 0; y<height; y++)
- {
- // copy the next row into the destination buffer
-
- for (x = 0; x<width; x++)
- {
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((pixel=bitmap_data[x]))
- dest_buffer[x] = pixel;
-
- } // end for x
-
- // move to next line in double buffer and in bitmap buffer
-
- dest_buffer += SCREEN_WIDTH;
- bitmap_data += width;
-
- } // end for y
- } // end if transparent
-
- else
- {
- // draw each line of the bitmap, note how each pixel doesn't need to be
- // tested for transparency hence a memcpy can be used (ver fast!)
-
- for (y = 0; y<height; y++)
- {
- // copy the next row into the destination buffer using memcpy for speed
-
- _fmemcpy((void far *)dest_buffer, (void far *)bitmap_data, width);
-
- // move to next line in destination buffer and in bitmap buffer
-
- dest_buffer += SCREEN_WIDTH;
- bitmap_data += width;
- } // end for y
- } // end else non-transparent version
-
- } // end Bitmap_Put
-
- void Bitmap_Get(bitmap_ptr image, unsigned char far *source)
- {
- // this function will scan a bitmap from the source buffer
- // could be a double buffer, video buffer or any other buffer with
- // logical row width of 320 bytes
-
- unsigned int source_off, // offsets into destination and source buffers
- bitmap_off;
-
- int y, // looping variable
- width,height; // size of bitmap
-
- unsigned char far *bitmap_data; // pointer to bitmap buffer
-
- // compute offset of bitmap in source buffer. Note: all video or double
- // buffers must be 320 bytes wide!
-
- source_off = (image->y << 8) + (image->y << 6) + image->x;
- bitmap_off = 0;
-
- // create aliases to variable so the structure doesn't need to be
- // dereferenced continually
-
- height = image->height;
- width = image->width;
- bitmap_data = image->buffer;
-
- // data each line of the bitmap, note now each pixel doesn't need to be
- // tested for transparency hence a memcpy can be used (very fast!)
-
- for (y=0; y<height; y++)
- {
- // copy the next row into the bitmap buffer using memcpy for speed
-
- _fmemcpy((void far *)&bitmap_data[bitmap_off],(void far *)&source[source_off],width);
-
- // move to next line in source buffer and in bitmap buffer
-
- source_off += SCREEN_WIDTH;
- bitmap_off += width;
- } // end for y
-
- } // end Bitmap_Get
-
- int PCX_Init(pcx_picture_ptr image)
- {
- // this function allocates the buffer that the image data will be loaded into
- // when a PCX file is decompressed
-
- if (!(image->buffer = (unsigned char far *)_fmalloc(SCREEN_WIDTH * SCREEN_HEIGHT + 1)))
- {
- printf("\nPCX SYSTEM - Couldn't allocate PCX image buffer");
- return(0);
- } // end if
-
- // success
-
- return(1);
- } // end PCX_Init
-
- void PCX_Delete(pcx_picture_ptr image)
- {
- // this function de-allocates the buffer region used for the pcx file load
-
- _ffree(image->buffer);
-
- } // end PCX_Delete
-
- int PCX_Load(char *filename, pcx_picture_ptr image, int load_palette)
- {
- // this function loads a PCX file into the image structure. The function
- // has three main parts: 1. Load the PCX header, 2. Load the image data and
- // decompress it and 3. Load the palette data and update the VGA palette
- // note: the palette will only be laoded if the load_palette flag is 1
-
- FILE *fp; // the file poiinter used to open the PCX file
-
- int num_bytes, // number of bytes in current RLE run
- index; // loop variable
-
- long count; // the total number of bytes decompressed
- unsigned char data; // the current pixel data
- char far *temp_buffer; // working buffer
-
- // open the file, test if it exists
-
- if ((fp = fopen(filename,"rb")) == NULL)
- {
- printf("/nPCX SYSTEM - Couldn't find file: %s", filename);
- return(0);
- } // end if couldn't find file
-
- // load the header
-
- temp_buffer = (char far *)image;
-
- for (index = 0; index<128; index++)
- {
- temp_buffer[index] = (char)getc(fp);
- } // end for index
-
- // load the data and decompress into buffer, we need a total of 64,000 bytes
-
- count = 0;
-
- // loop while 64,000 bytes haven't been decompressed
-
- while(count<=SCREEN_WIDTH * SCREEN_HEIGHT)
- {
- // get the first piece of data
-
- data = (unsigned char)getc(fp);
-
- // is this a RLE run?
- if (data>=192 && data<=255)
- {
- // compute number of bytes in run
-
- num_bytes = data-192;
-
- // get the actual data for the run
-
- data = (unsigned char)getc(fp);
-
- // replicate data in buffer num_bytes times
-
- while(num_bytes-->0)
- {
- image->buffer[count++] = data;
- } // end while
-
- } // end if rle
-
- else
- {
- // actual data, just copy it into buffer at next location
-
- image->buffer[count++] = data;
-
- } // end else not rle
-
- } // end while
-
- // load color palette
-
- // move to end of file then back up 768 bytes i.e. to beginning of palette
-
- fseek(fp,-768L,SEEK_END);
-
- // load the PCX palette into the VGA color registers
-
- for (index=0; index<256; index++)
- {
- // get the red component
-
- image->palette[index].red = (unsigned char)(getc(fp) >> 2);
-
- // get the green component
-
- image->palette[index].green = (unsigned char)(getc(fp) >> 2);
-
- // get the blue component
-
- image->palette[index].blue = (unsigned char)(getc(fp) >> 2);
-
- } // end for index
-
- // time to close the file
-
- fclose(fp);
-
- // change the palette to newly loaded palette if comanded to do so
-
- if (load_palette)
- {
- // for each palette register set to the new color values
-
- for (index = 0; index < 256; index++)
- {
- Write_Color_Reg(index,(RGB_color_ptr)&image->palette[index]);
- } // end for index
-
- } // end if load palette data into VGA
-
- // success
-
- return(1);
-
- } // end PCX_Load
-
- void PCX_Show_Buffer(pcx_picture_ptr image)
- {
- // copy the pcx buffer into the video buffer
-
- char far *data; // temp variable used for aliasing
-
- // alias image buffer
-
- data = image->buffer;
-
- // use inline assembly for speed
-
- _asm
- {
- push ds ; save the data segment
- les di,video_buffer ; point es:di to video buffer
- lds si,data ; point ds:si to data area
- mov cx,320*200/2 ; move 32000 words
- cld ; set direction to forward
- rep movsw ; do the string operation
- pop ds ; restore the data segment
- } // end inline asm
-
- } // end PCX_Show_Buffer
-
- void Sprite_Init(sprite_ptr sprite, int x, int y, int width, int height, int c1, int c2, int c3, int t1, int t2, int t3)
- {
- // this function initializes a sprite
-
- int index;
-
- sprite->x = x;
- sprite->y = y;
- sprite->width = width;
- sprite->height = height;
- sprite->visible = 1;
- sprite->counter_1 = c1;
- sprite->counter_2 = c2;
- sprite->counter_3 = c3;
- sprite->threshold_1 = t1;
- sprite->threshold_2 = t2;
- sprite->threshold_3 = t3;
- sprite->curr_frame = 0;
- sprite->state = SPRITE_DEAD;
- sprite->num_frames = 0;
- sprite->background = (unsigned char far *)_fmalloc(width * height+1);
-
- // set all bitmap pointers to null
-
- for (index = 0; index < MAX_SPRITE_FRAMES; index++)
- sprite->frames[index] = NULL;
-
- } // end Sprite_Init
-
- void Sprite_Delete(sprite_ptr sprite)
- {
- // this function dletes all the memory associated with a sprite
-
- int index;
-
- _ffree(sprite->background);
-
- // now de-allocate all the animation frames
-
- for (index = 0; index < MAX_SPRITE_FRAMES; index++)
- _ffree(sprite->frames[index]);
-
- } // end Sprite_Delete
-
- void PCX_Get_Sprite(pcx_picture_ptr image, sprite_ptr sprite, int sprite_frame, int cell_x, int cell_y)
- {
- // this function is used to load the images for a sprite into the sprite
- // frames array. It functions by using the size of the sprite and the
- // position of the requested cell to compute the proper location in the
- // pcx image buffer to extract the data from.
-
- int x_off, // position of sprite cell in PCX image buffer
- y_off,
- y, // looping variable
- width, // size of sprite
- height;
-
- unsigned char far *sprite_data;
-
- // extract width and height of sprite
-
- width = sprite->width;
- height = sprite->height;
-
- // first allocate the memory for the sprite in the sprite structure
-
- sprite->frames[sprite_frame] = (unsigned char far *)_fmalloc(width * height + 1);
-
- // create an alias to the sprite frame for ease of access
-
- sprite_data = sprite->frames[sprite_frame];
-
- // now load the sprite data into the sprite frame array from the pcx
- // picture
-
- x_off = (width+1) * cell_x + 1;
- y_off = (height+1) * cell_y + 1;
-
- // compute starting y address
-
- y_off = y_off * 320; // 320 bytes per line
-
- // scan the data row by row
-
- for (y=0; y<height; y++,y_off+=320)
- {
- // copy the row of pixels
-
- _fmemcpy((void far *)&sprite_data[y*width],(void far *)&(image->buffer[y_off + x_off]), width);
- } // end for y
-
- // increment number of frames
-
- sprite->num_frames++;
-
- // done!, let's bail!
- } // end PCX_Get_Sprite
-
- void Sprite_Draw(sprite_ptr sprite, unsigned char far *buffer, int transparent)
- {
- // this function draw a sprite on the screen row by row very quickly
- // note the use of shifting to implement multiplication
- // if the transparent flag is true the pixels will be drawn one by one
- // else a memcpy will be used to draw each line
-
- unsigned char far *sprite_data; // pointer to sprite data
- unsigned char far *dest_buffer; // pointer to destination buffer
-
- int x,y, // looping variables
- width, // width of sprite
- height; // height of sprite
-
- unsigned char pixel; // the current pixel being processed
-
- // alias a pointer to sprite for ease of access
-
- sprite_data = sprite->frames[sprite->curr_frame];
-
- // alias a variable to sprite size
-
- width = sprite->width;
- height = sprite->height;
-
- // compute number of bytes between adjacent video lines after a row of pixels
- // has been drawn
-
- // compute offset of sprite in destination buffer
-
- dest_buffer = buffer + (sprite->y << 8) + (sprite->y << 6) + sprite->x;
-
- // copy each line of the sprite data into destination buffer
-
- if (transparent)
- {
- for (y=0; y<height; y++)
- {
- // copy the next row into the destination buffer
-
- for (x=0; x<width; x++)
- {
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((pixel=sprite_data[x]))
- dest_buffer[x] = pixel;
-
- } // end for x
-
- // move to next line in destination buffer and sprite image buffer
-
- dest_buffer += SCREEN_WIDTH;
- sprite_data += width;
-
- } // end for y
- } // end if transparent
-
- else
- {
- // draw sprite with transparency off
-
- for (y=0; y<height; y++)
- {
- // copy the next row into the destination buffer
-
- _fmemcpy((void far *)dest_buffer, (void far *)sprite_data, width);
-
- // move to next line in destination buffer and sprite image buffer
-
- dest_buffer += SCREEN_WIDTH;
- sprite_data += width;
-
- } // end for y
- } // end else
-
- } // end Sprite_Draw
-
- void Sprite_Under(sprite_ptr sprite, unsigned char far *buffer)
- {
- // this function scans the background under a sprite so that when the sprite
- // is drawn the background isn't obliterated
-
- unsigned char far *back_buffer; // background buffer for sprite
-
- int y, // current line being scanned
- width, // size of sprite
- height;
-
- // alias a pointer to sprite background for ease of access
-
- back_buffer = sprite->background;
-
- // alias width and height
-
- width = sprite->width;
- height = sprite->height;
-
- // compute offset of background in source buffer
-
- buffer = buffer + (sprite->y << 8) + (sprite->y << 6) + sprite->x;
-
- for (y=0; y<height; y++)
- {
- // copy the next row out of image buffer into sprite background buffer
-
- _fmemcpy((void far *)back_buffer, (void far *)buffer, width);
-
- // move to next line in source buffer and in sprite background buffer
-
- buffer += SCREEN_WIDTH;
- back_buffer += width;
- } // end for y
- } // end Sprite_Under
-
- void Sprite_Erase(sprite_ptr sprite, unsigned char far *buffer)
- {
- // replace the background that was behind the sprite
- // this function replaces the background that was saved from where a sprite
- // was going to be placed
-
- unsigned char far *back_buffer; // background buffer for sprite
-
- int y, // current line being scanned
- width, // size of sprite
- height;
-
- // alias a pointer to sprite background for ease of access
-
- back_buffer = sprite->background;
-
- // alias width and height
-
- width = sprite->width;
- height = sprite->height;
-
- // compute offset in destination buffer
-
- buffer = buffer + (sprite->y << 8) + (sprite->y << 6) + sprite->x;
-
- for (y=0; y<height; y++)
- {
- // copy the next from sprite backgroundbuffer to destination buffer
-
- _fmemcpy((void far *)buffer, (void far *)back_buffer, width);
-
- // move to next line in destination buffer and in sprite background buffer
-
- buffer += SCREEN_WIDTH;
- back_buffer += width;
-
- } // end for y
- } // end Sprite_Erase
-
- void PCX_Copy_To_Buffer(pcx_picture_ptr image, unsigned char far *buffer)
- {
- // this function is used to copy the data in the PCX buffer to another buffer
- // usually the double buffer
-
- // use the word copy function, note: double_buffer_size is in WORDS
-
- fwordcpy((void far *)buffer,(void far *)image->buffer,double_buffer_size);
-
- } // end PCX_Copy_To_Buffer
-
- void PCX_Copy_To_Buffer_XYZ_Mode(pcx_picture_ptr image, unsigned char far *buffer)
- {
- // this function is used to copy the data in the PCX buffer to video memory
- // in planar modes - X, Y, and Z!
-
- // The Width and Height is assumed to be 320x200 here...
- // because it's being developed for mode Y!
-
- int x_index;
- int y_index;
- unsigned int image_buffer_offset;
- unsigned int vid_offset;
-
- for (x_index = 0; x_index<320; x_index++)
- {
- // first select the proper color plane to write to...
- // I could have written to one plane at a time but - Oh Hell!...
-
- _asm
- {
- mov dx,SEQUENCER ; address the sequencer
- mov al,SEQ_PLANE_ENABLE ; select the plane enable register
- mov cl,BYTE PTR x_index ; extract lower byte from x
- and cl,03h ; extract the plane number = x MOD 4
- mov ah,1 ; a "1" selects the plane in the plane enable
- shl ah,cl ; shift the "1" bit proper number of times
- out dx,ax ; do it baby!
- } // end asm
-
- for (y_index = 0; y_index<200; y_index++)
- {
- image_buffer_offset = (y_index<<8) + (y_index<<6) + x_index;
-
- vid_offset = (y_index<<6) + (y_index<<4) + (x_index>>2);
-
- video_buffer[vid_offset] = image->buffer[image_buffer_offset];
- }
- }
-
- } // end PCX_Copy_To_Buffer_XYZ_Mode
-
- void fwordcpy(void far *destination, void far *source, int num_words)
- {
- // this function is similar to fmemcpy execpt that it moves data in words
- // it is about 25% faster than memcpy which uses bytes
-
- _asm
- {
- push ds ; need to save segment registers i.e. ds
- les di,destination ; point es:di to destination of memory move
- lds si,source ; point ds:si to source of memory move
- mov cx,num_words ; move into cx the number of words to be moved
- rep movsw ; let the processor do the memory move
- pop ds ; restore the ds segment register
- } // end inline asm
- } // end fwordcpy
-
- ////////////////////////////////////////////////////////////////////////////////
-
- void fwordset(void far *destination, int color, int num_words)
- {
- // this function is similar to fmemset except that it sets data in words
- // it is about 25% faster than memset which uses bytes
-
- _asm
- {
- mov ax,WORD PTR color ; move the color into ax
- les di,destination ; point es:di to destination of memory set
- mov cx,num_words ; move into cx the number of words to be set
- rep stosw ; let the processor do the memory set
- } // end inline asm
- } // end fwordset
-
- ////////////////////////////////////////////////////////////////////////////////
-
- void Sprite_Under_Clip(sprite_ptr sprite, unsigned char far *buffer)
- {
-
- // this function scans the background under a sprite, but only those
- // portions that are visible
-
- unsigned char far *back_buffer; // pointer to sprite background buffer
- unsigned char far *source_buffer; // pointer to source buffer
-
- int x,y, // looping variables
- sx,sy, // position of sprite
- width, // width of sprite
- bitmap_width =0, // width and height of sub-bitmap
- bitmap_height =0;
-
- unsigned char pixel; // the current pixel being processed
-
- // alias a variable to sprite size
-
- width = sprite->width;
- bitmap_width = width;
- bitmap_height = sprite->height;
- sx = sprite->x;
- sy = sprite->y;
-
- // perform trivial rejection tests
-
- if (sx >= (int)SCREEN_WIDTH || sy >= (int)double_buffer_height ||
- (sx+width) <= 0 || (sy+bitmap_height) <= 0)
- {
- // sprite is totally invisible therefore don't scan
-
- // set invisible flag in strucuture so that the draw sub-function
- // doesn't do anything
-
- sprite->visible = 0;
-
- return;
-
- } // end if invisible
-
- // the sprite background region must be clipped before scanning
- // therefore compute visible portion
-
- // first compute upper left hand corner of clipped sprite background
-
- if (sx<0)
- {
-
- bitmap_width += sx;
- sx = 0;
-
-
- } // end off left edge
- else
- if (sx+width>=(int)SCREEN_WIDTH)
- {
-
- bitmap_width = (int)SCREEN_WIDTH-sx;
-
- } // end off right edge
-
- // now process y
-
- if (sy<0)
- {
-
- bitmap_height += sy;
- sy = 0;
-
- } // end off top edge
- else
- if (sy+bitmap_height>=(int)double_buffer_height)
- {
-
- bitmap_height = (int)double_buffer_height - sy;
-
- } // end off lower edge
-
- // this point we know were to start scanning the bitmap i.e.
- // sx,sy
- // and we know the size of the bitmap to be scanned i.e.
- // width,height, so plug it all into the rest of function
-
- // compute number of bytes between adjacent video lines after a row of pixels
- // has been drawn
-
- // compute offset of sprite background in source buffer
-
- source_buffer = buffer + (sy << 8) + (sy << 6) + sx;
-
- // alias a pointer to sprite background
-
- back_buffer = sprite->background;
-
- for (y=0; y<bitmap_height; y++)
- {
- // copy the next row into the destination buffer
-
- _fmemcpy((void far *)back_buffer,(void far *)source_buffer,bitmap_width);
-
- // move to next line in desintation buffer and sprite image buffer
-
- source_buffer += SCREEN_WIDTH;
- back_buffer += width; // note this width is the actual width of the
- // entire bitmap NOT the visible portion
- } // end for y
-
- // set variables in strucuture so that the erase sub-function can operate
- // faster
-
- sprite->x_clip = sx;
- sprite->y_clip = sy;
- sprite->width_clip = bitmap_width;
- sprite->height_clip = bitmap_height;
- sprite->visible = 1;
-
- } // end Sprite_Under_Clip
-
- //////////////////////////////////////////////////////////////////////////////
-
- void Sprite_Erase_Clip(sprite_ptr sprite,unsigned char far *buffer)
- {
- // replace the background that was behind the sprite
- // this function replaces the background that was saved from where a sprite
- // was going to be placed
-
- unsigned char far *back_buffer; // background buffer for sprite
-
- int y, // current line being scanned
- width, // size of sprite background buffer
- bitmap_height, // size of clipped bitmap
- bitmap_width;
-
- // make sure sprite was visible
-
- if (!sprite->visible)
- return;
-
- // alias a pointer to sprite background for ease of access
-
- back_buffer = sprite->background;
-
- // alias width and height
-
- bitmap_width = sprite->width_clip;
- bitmap_height = sprite->height_clip;
- width = sprite->width;
-
- // compute offset in destination buffer
-
- buffer = buffer + (sprite->y_clip << 8) + (sprite->y_clip << 6)
- + sprite->x_clip;
-
- for (y=0; y<bitmap_height; y++)
- {
- // copy the next row from sprite background buffer to destination buffer
-
- _fmemcpy((void far *)buffer,
- (void far *)back_buffer,
- bitmap_width);
-
- // move to next line in destination buffer and in sprite background buffer
-
- buffer += SCREEN_WIDTH;
- back_buffer += width;
-
- } // end for y
-
- } // end Sprite_Erase_Clip
-
- //////////////////////////////////////////////////////////////////////////////
-
- void Sprite_Draw_Clip(sprite_ptr sprite, unsigned char far *buffer,int transparent)
- {
-
- // this function draws a sprite on the screen row by row very quickly
- // note the use of shifting to implement multplication
- // if the transparent flag is true then pixels wil be draw one by one
- // else a memcpy will be used to draw each line
- // this function also performs clipping. It will test if the sprite
- // is totally visible/invisible and will only draw the portions that are visible
-
- unsigned char far *sprite_data; // pointer to sprite data
- unsigned char far *dest_buffer; // pointer to destination buffer
-
- int x,y, // looping variables
- sx,sy, // position of sprite
- width, // width of sprite
- bitmap_x =0, // starting upper left corner of sub-bitmap
- bitmap_y =0, // to be drawn after clipping
- bitmap_width =0, // width and height of sub-bitmap
- bitmap_height =0;
-
- unsigned char pixel; // the current pixel being processed
-
- // alias a variable to sprite size
-
- width = sprite->width;
- bitmap_width = width;
- bitmap_height = sprite->height;
- sx = sprite->x;
- sy = sprite->y;
-
- // perform trivial rejection tests
-
- if (sx >= (int)SCREEN_WIDTH || sy >= (int)double_buffer_height ||
- (sx+width) <= 0 || (sy+bitmap_height) <= 0 || !sprite->visible)
- {
- // sprite is totally invisible therefore don't draw
-
- // set invisible flag in strucuture so that the erase sub-function
- // doesn't do anything
-
- sprite->visible = 0;
-
- return;
-
- } // end if invisible
-
- // the sprite needs some clipping or no clipping at all, so compute
- // visible portion of sprite rectangle
-
- // first compute upper left hand corner of clipped sprite
-
- if (sx<0)
- {
-
- bitmap_x = -sx;
- sx = 0;
- bitmap_width -= bitmap_x;
-
- } // end off left edge
- else
- if (sx+width>=(int)SCREEN_WIDTH)
- {
-
- bitmap_x = 0;
- bitmap_width = (int)SCREEN_WIDTH-sx;
-
- } // end off right edge
-
- // now process y
-
- if (sy<0)
- {
-
- bitmap_y = -sy;
- sy = 0;
- bitmap_height -= bitmap_y;
-
- } // end off top edge
- else
- if (sy+bitmap_height>=(int)double_buffer_height)
- {
-
- bitmap_y = 0;
- bitmap_height = (int)double_buffer_height - sy;
-
- } // end off lower edge
-
- // this point we know were to start drawing the bitmap i.e.
- // sx,sy
- // and we know were in the data to extract the bitmap i.e.
- // bitmap_x, bitmap_y,
- // and finaly we know the size of the bitmap to be drawn i.e.
- // width,height, so plug it all into the rest of function
-
- // compute number of bytes between adjacent video lines after a row of pixels
- // has been drawn
-
- // compute offset of sprite in destination buffer
-
- dest_buffer = buffer + (sy << 8) + (sy << 6) + sx;
-
- // alias a pointer to sprite for ease of access and locate starting sub
- // bitmap that will be drawn
-
- sprite_data = sprite->frames[sprite->curr_frame] + (bitmap_y*width) + bitmap_x;
-
- // copy each line of the sprite data into destination buffer
-
- if (transparent)
- {
- for (y=0; y<bitmap_height; y++)
- {
- // copy the next row into the destination buffer
-
- for (x=0; x<bitmap_width; x++)
- {
-
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((pixel=sprite_data[x]))
- dest_buffer[x] = pixel;
-
- } // end for x
-
- // move to next line in desintation buffer and sprite image buffer
-
- dest_buffer += SCREEN_WIDTH;
- sprite_data += width; // note this width is the actual width of the
- // entire bitmap NOT the visible portion
- } // end for y
-
- } // end if transparent
- else
- {
- // draw sprite with transparency off
-
- for (y=0; y<bitmap_height; y++)
- {
- // copy the next row into the destination buffer
-
- _fmemcpy((void far *)dest_buffer,(void far *)sprite_data,bitmap_width);
-
- // move to next line in desintation buffer and sprite image buffer
-
- dest_buffer += SCREEN_WIDTH;
- sprite_data += width; // note this width is the actual width of the
- // entire bitmap NOT the visible portion
- } // end for y
-
- } // end else
-
- // set variables in strucuture so that the erase sub-function can operate
- // faster
-
- sprite->x_clip = sx;
- sprite->y_clip = sy;
- sprite->width_clip = bitmap_width;
- sprite->height_clip = bitmap_height;
- sprite->visible = 1;
-
- } // end Sprite_Draw_Clip
-
- void Sprite_Draw_Clip_Special(sprite_ptr sprite, unsigned char far *buffer)
- {
-
- // this function draws a sprite on the screen row by row very quickly
- // note the use of shifting to implement multplication
- // if the transparent flag is true then pixels wil be draw one by one
- // else a memcpy will be used to draw each line
- // this function also performs clipping. It will test if the sprite
- // is totally visible/invisible and will only draw the portions that are visible
-
- unsigned char far *sprite_data; // pointer to sprite data
- unsigned char far *dest_buffer; // pointer to destination buffer
-
- int x_factor,y_factor, // looping variables
- sx,sy, // position of sprite
- width, // width of sprite
- bitmap_x =0, // starting upper left corner of sub-bitmap
- bitmap_y =0, // to be drawn after clipping
- bitmap_width =0, // width and height of sub-bitmap
- bitmap_height =0;
-
- unsigned char pixel; // the current pixel being processed
-
- // alias a variable to sprite size
-
- width = sprite->width;
- bitmap_width = width;
- bitmap_height = sprite->height;
- sx = sprite->x;
- sy = sprite->y;
-
- // perform trivial rejection tests
-
-
- // first compute upper left hand corner of clipped sprite
-
-
- // now process y
-
- if (sy<0)
- {
-
- bitmap_y = -sy;
- sy = 0;
- bitmap_height -= bitmap_y;
-
- } // end off top edge
- else
- if (sy+bitmap_height>=(int)200)
- {
-
- bitmap_y = 0;
- bitmap_height = (int)200 - sy;
-
- } // end off lower edge
-
- // this point we know were to start drawing the bitmap i.e.
- // sx,sy
- // and we know were in the data to extract the bitmap i.e.
- // bitmap_x, bitmap_y,
- // and finaly we know the size of the bitmap to be drawn i.e.
- // width,height, so plug it all into the rest of function
-
- // compute number of bytes between adjacent video lines after a row of pixels
- // has been drawn
-
- // compute offset of sprite in destination buffer
-
- _asm
- {
- mov dx,SEQUENCER // address the sequencer
- mov al,SEQ_PLANE_ENABLE // select the plane enable register
- mov ah,0x01 // extract lower byte from x_factor
- out dx,ax // do it baby!
- } // end asm
-
- dest_buffer = buffer + (sy << 6) + (sy << 4) + (sx>>2);
-
- // alias a pointer to sprite for ease of access and locate starting sub
- // bitmap that will be drawn
-
- sprite_data = sprite->frames[sprite->curr_frame] + (bitmap_y*width) + bitmap_x;
-
- // copy each line of the sprite data into destination buffer
-
- for (y_factor=0; y_factor<bitmap_height; y_factor++)
- {
- // copy the next row into the destination buffer
-
- for (x_factor=0; x_factor<bitmap_width; x_factor+=4)
- {
-
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((pixel=sprite_data[x_factor]))
- dest_buffer[(x_factor>>2)] = pixel;
-
- } // end for x_factor
-
- // move to next line in desintation buffer and sprite image buffer
-
- dest_buffer += 80;
- sprite_data += width; // note this width is the actual width of the
- // entire bitmap NOT the visible portion
- } // end for y_factor
-
- _asm
- {
- mov dx,SEQUENCER // address the sequencer
- mov al,SEQ_PLANE_ENABLE // select the plane enable register
- mov ah,0x02 // extract lower byte from x_factor
- out dx,ax // do it baby!
- } // end asm
-
- dest_buffer = buffer + (sy << 6) + (sy << 4) + (sx>>2);
-
- // alias a pointer to sprite for ease of access and locate starting sub
- // bitmap that will be drawn
-
- sprite_data = sprite->frames[sprite->curr_frame] + (bitmap_y*width) + bitmap_x;
-
- // copy each line of the sprite data into destination buffer
-
- for (y_factor=0; y_factor<bitmap_height; y_factor++)
- {
- // copy the next row into the destination buffer
-
- for (x_factor=0; x_factor<bitmap_width; x_factor+=4)
- {
-
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((pixel=sprite_data[x_factor+1]))
- dest_buffer[(x_factor>>2)] = pixel;
-
- } // end for x_factor
-
- // move to next line in desintation buffer and sprite image buffer
-
- dest_buffer += 80;
- sprite_data += width; // note this width is the actual width of the
- // entire bitmap NOT the visible portion
- } // end for y_factor
-
- _asm
- {
- mov dx,SEQUENCER // address the sequencer
- mov al,SEQ_PLANE_ENABLE // select the plane enable register
- mov ah,0x04 // extract lower byte from x_factor
- out dx,ax // do it baby!
- } // end asm
-
- dest_buffer = buffer + (sy << 6) + (sy << 4) + (sx>>2);
-
- // alias a pointer to sprite for ease of access and locate starting sub
- // bitmap that will be drawn
-
- sprite_data = sprite->frames[sprite->curr_frame] + (bitmap_y*width) + bitmap_x;
-
- // copy each line of the sprite data into destination buffer
-
- for (y_factor=0; y_factor<bitmap_height; y_factor++)
- {
- // copy the next row into the destination buffer
-
- for (x_factor=0; x_factor<bitmap_width; x_factor+=4)
- {
-
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((pixel=sprite_data[x_factor+2]))
- dest_buffer[(x_factor>>2)] = pixel;
-
- } // end for x_factor
-
- // move to next line in desintation buffer and sprite image buffer
-
- dest_buffer += 80;
- sprite_data += width; // note this width is the actual width of the
- // entire bitmap NOT the visible portion
- } // end for y_factor
-
- _asm
- {
- mov dx,SEQUENCER // address the sequencer
- mov al,SEQ_PLANE_ENABLE // select the plane enable register
- mov ah,0x08 // extract lower byte from x_factor
- out dx,ax // do it baby!
- } // end asm
-
- dest_buffer = buffer + (sy << 6) + (sy << 4) + (sx>>2);
-
- // alias a pointer to sprite for ease of access and locate starting sub
- // bitmap that will be drawn
-
- sprite_data = sprite->frames[sprite->curr_frame] + (bitmap_y*width) + bitmap_x;
-
- // copy each line of the sprite data into destination buffer
-
- for (y_factor=0; y_factor<bitmap_height; y_factor++)
- {
- // copy the next row into the destination buffer
-
- for (x_factor=0; x_factor<bitmap_width; x_factor+=4)
- {
-
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((pixel=sprite_data[x_factor+3]))
- dest_buffer[(x_factor>>2)] = pixel;
-
- } // end for x_factor
-
- // move to next line in desintation buffer and sprite image buffer
-
- dest_buffer += 80;
- sprite_data += width; // note this width is the actual width of the
- // entire bitmap NOT the visible portion
- } // end for y_factor
-
- } // end Sprite_Draw_Clip_Special
-
-
- int Layer_Create(layer_ptr dest_layer, int width, int height)
- {
- // this function can be used to allocate the memory needed for a layer
- // the width must be divisible by 2
-
- if ((dest_layer->buffer = (unsigned char far *)_fmalloc(width*height+2))==NULL)
- return(0);
- else
- {
- // save the dimensions of layer
-
- dest_layer->width = width;
- dest_layer->height = height;
-
- return(1);
- } // end else
-
- } // end Layer_Create
-
- void Layer_Delete(layer_ptr the_layer)
- {
- // this function deletes the memory used by a layer
-
- if (the_layer->buffer)
- _ffree(the_layer->buffer);
- } // end Layer_Delete
-
- void Layer_Build(layer_ptr dest_layer, int dest_x, int dest_y, unsigned char far *source_buffer, int source_x, int source_y, int width, int height)
- {
- // this function is used to build up the layer out of smaller pieces
- // this allows a layer to be very long, tall etc. also the source data buffer
- // must be constructed such that there are 320 bytes per row
-
- int y, // looping variable
- layer_width; // the width of the layer
-
- unsigned char far *source_data; // pointer to start of source bitmap image
- unsigned char far *layer_buffer; // pointer to layer buffer
-
- // extract width of layer
-
- layer_width = dest_layer->width;
-
- // compute starting location in layer buffer
-
- layer_buffer = dest_layer->buffer + layer_width*dest_y + dest_x;
-
- // compute starting location in source image buffer
-
- source_data = source_buffer + (source_y << 8) + (source_y << 6) + source_x;
-
- // scan each line of source image into layer buffer
-
- for (y=0; y<height; y++)
- {
- // copy the next row into the layer buffer using memcpy for speed
-
- _fmemcpy((void far *)layer_buffer, (void far *)source_data, width);
-
- // move to next line in source buffer and in layer buffer
-
- source_data +=SCREEN_WIDTH;
- layer_buffer +=layer_width;
-
- } // end for y
-
- } // end Layer_Build
-
- void Layer_Draw(layer_ptr source_layer, int source_x, int source_y, unsigned char far *dest_buffer, int dest_y, int dest_height, int transparent)
- {
- // this function will map down a section of the layer onto the destination
- // buffer at the desired location, note the width of the destination buffer
- // is always assumed to be 320 bytes width. Also, the function will always
- // wrap around the layer
-
- int x,y, // looping variables
- layer_width, // the width of the layer
- right_width, // the width of the right and left half of
- left_width; // the layer to be drawn
-
- unsigned char far *layer_buffer_l; // pointers to the left and right halves
- unsigned char far *dest_buffer_l; // of the layer buffer and destination
- unsigned char far *layer_buffer_r; // buffer
- unsigned char far *dest_buffer_r;
-
- unsigned char pixel; // current pixel value being processed
-
- layer_width = source_layer->width;
- dest_buffer_l = dest_buffer + (dest_y << 8) + (dest_y << 6);
- layer_buffer_l = source_layer->buffer + layer_width*source_y + source_x;
-
- // test if wrapping is needed
-
- if (((layer_width-source_x) - (int)SCREEN_WIDTH) >= 0)
- {
- // there's enough data in layer to draw a complete line, no wrapping needed
-
- left_width = SCREEN_WIDTH;
- right_width = 0; // no wrapping flag
- } // end if
- else
- {
- // wrapping needed
-
- left_width = layer_width - source_x;
- right_width = SCREEN_WIDTH - left_width;
- dest_buffer_r = dest_buffer_l + left_width;
- layer_buffer_r = layer_buffer_l - source_x; // move to far left end of layer
- } // end else need to wrap
-
- // test if transparency is on or off
-
- if (transparent)
- {
- // use this version that will draw a transparent bitmap (slightly slower)
- // first draw left half then right half
- // draw each line of the bitmap
-
- for (y=0; y<dest_height; y++)
- {
- // copy the next row into the destination buffer
-
- for (x=0; x<left_width; x++)
- {
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((pixel=layer_buffer_l[x]))
- dest_buffer_l[x] = pixel;
-
- } // end for x
-
- // move to next line in destination buffer and in layer buffer
-
- dest_buffer_l += SCREEN_WIDTH;
- layer_buffer_l += layer_width;
- } // end for y
-
- // now right half
-
- // draw each line of the bitmap
-
- if (right_width)
- {
- for (y=0; y<dest_height; y++)
- {
- // copy the next row into the destination buffer
-
- for (x=0; x<right_width; x++)
- {
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((pixel=layer_buffer_r[x]))
- dest_buffer_r[x] = pixel;
-
- } // end for x
-
- // move to next line in destination buffer and in layer buffer
-
- dest_buffer_r += SCREEN_WIDTH;
- layer_buffer_r += layer_width;
- } // end for y
- } // end if right side needs to be drawn
-
- } // end if transparent
- else
- {
- // draw each line of the bitmap, note how each pixel doesn't need to be
- // test for transparency hence a memcpy can be used (very fast!)
-
- for (y=0; y<dest_height; y++)
- {
- // copy the next row into the destination buffer using memcpy for speed
-
- _fmemcpy((void far *)dest_buffer_l,(void far *)layer_buffer_l, left_width);
-
- // move to next line in double buffer and in bitmap buffer
-
- dest_buffer_l += SCREEN_WIDTH;
- layer_buffer_l += layer_width;
- } // end for y
-
- // now right half if needed
-
- if (right_width)
- {
- for (y=0; y<dest_height; y++)
- {
- // copy the next row into the destination buffer using memcpy for speed
-
- _fmemcpy((void far *)dest_buffer_r,(void far *)layer_buffer_r, right_width);
-
- // move to next line in double buffer and in bitmap buffer
-
- dest_buffer_r += SCREEN_WIDTH;
- layer_buffer_r += layer_width;
- } // end for y
-
- } // end if right half
-
- } // end else non-transparent version
-
- } // end Layer_Draw
-
- void Wait_For_Vertical_Retrace(void)
- {
- // this function waits for the start of a vertical retrace, if a vertical
- // retrace is in progress then it waits until the next one
- // therefore the function can wait a maximum of 2/70ths of a second
- // before returning
- // this function can be used to synchronize video updates to the vertical blank
- // or as a high resolution time reference
-
- while(_inp(VGA_INPUT_STATUS_1) & VGA_VRETRACE_MASK)
- {
- // do nothing, vga is already in retrace
- } // end while
-
- // now wait for start of vertical retrace and exit
-
- while(!(_inp(VGA_INPUT_STATUS_1) & VGA_VRETRACE_MASK))
- {
- // do nothing, wait for start of retrace
- } // end while
-
- // at this point a vertical retrace is occurring, so return back to caller
-
- } // end Wait_For_Vertical_Retrace
-
- void Print_Char_DB(int xc, int yc, char c, int color, int transparent)
- {
- // this function is used to print a character on the screen. It uses the
- // internal 8x8 character set to do this. Note that each character is
- // 8 bytes where each byte represents the 8 pixels that make up the row
- // of pixels
-
- int offset, // offset into video memory
- x, // loop variable
- y; // loop variable
-
- unsigned char far *work_char; // pointer to character being printed
-
- unsigned char bit_mask; // bit mask used to extract proper bit
-
- // compute starting offset in rom character lookup table
- // multiply the character by 8 and add the result to the starting address
- // of the ROM character set
-
- work_char = rom_char_set + c * ROM_CHAR_HEIGHT;
-
- // compute offset of character in video buffer, use shifting to multiply
-
- offset = (yc << 8) + (yc << 6) + xc;
-
- // draw the character row by row
-
- for (y = 0; y < ROM_CHAR_HEIGHT; y++)
- {
- // reset bit mask
-
- bit_mask = 0x80;
-
- // draw each pixel of this row
-
- for (x = 0; x < ROM_CHAR_WIDTH; x++)
- {
- // test for transparent pixel i.e. 0, if not transparent then draw
-
- if ((*work_char & bit_mask))
- double_buffer[offset+x] = (unsigned char)color;
-
- else
- if (!transparent) // takes care of transparency
- double_buffer[offset+x] = 0; // make black part opaque
-
- // shift bit mask
-
- bit_mask = (bit_mask>>1);
-
- } // end for x
-
- // move to next line in video buffer and in rom character data area
-
- offset += MODE13_WIDTH;
- work_char++;
- } // end for y
- } // end Print_Char_DB
-
- void Print_String_DB(int x, int y, int color, char *string, int transparent)
- {
- // this function prints an entire string on the screen with fixed spacing
- // between each character by calling the Print_Char() function
-
- int index, // loop index
- length; // length of string
-
- // compute length of string
-
- length = strlen(string);
-
- // print the string a character at a time
-
- for (index = 0; index<length; index ++)
- Print_Char_DB(x+(index<<3),y,string[index],color,transparent);
-
- } // end Print_String_DB
-
- void Write_Pixel_DB(int x, int y, int color)
- {
-
- // plots the pixel in the desired color a little quicker using binary shifting
- // to accomplish the multiplications
-
- // uses the fact that 320*y = 256*y + 64*y = y<<8 + y<<6
-
- double_buffer[((y<<8) + (y<<6)) + x] = (unsigned char)color;
-
- } // end Write_Pixel_DB
-
- int Read_Pixel_DB(int x, int y)
- {
- // This function reads a pixel from the screen buffer
-
- return((int)(double_buffer[((y<<8) + (y<<6)) + x]));
-
- }
-
- void Set_Visual_Page_Mode_Z(int page)
- {
- // this function sets the visual page that will be displayed by the VGA
-
- if (page==PAGE_0)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 0 @ 0xA000:0000
-
- // first low byte of address
-
- _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x00);
-
- } // end if page 0
- else
- if (page==PAGE_1)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 1 @ 0xA000:8000
-
- // first low byte of address
-
- _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x80);
-
- } // end else page 1
-
- // note: we could use WORD out's, but this is clearer, feel free to change them
-
- } // end Set_Visual_Page_Mode_Z
-
- ///////////////////////////////////////////////////////////////////////////////
-
- void Set_Visual_Page_Mode_Z_Half(int page)
- {
- // THIS VERSION OF THE FUNCTION SAVES AN OUTS WORTH OF COMPUTER CYCLES!!!
-
- // this function sets the visual page that will be displayed by the VGA
-
- if (page==PAGE_0)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 0 @ 0xA000:0000
-
- // first low byte of address
-
- // _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- // _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x00);
-
- } // end if page 0
- else
- if (page==PAGE_1)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 1 @ 0xA000:8000
-
- // first low byte of address
-
- // _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- // _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x80);
-
- } // end else page 1
-
- // note: we could use WORD out's, but this is clearer, feel free to change them
-
- } // end Set_Visual_Page_Mode_Z
-
- ///////////////////////////////////////////////////////////////////////////////
- void Set_Working_Page_Mode_Z(int page)
- {
- // this function sets the page that all mode Z functions will update when
- // called
-
- if (page==PAGE_0)
- video_buffer = page_0_buffer;
- else
- video_buffer = page_1_buffer;
-
- } // end Set_Working_Page_Mode_Z
-
- void Set_Visual_Page_Mode_Y(int page)
- {
- // this function sets the visual page that will be displayed by the VGA
-
- if (page==PAGE_0)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 0 @ 0xA000:0000
-
- // first low byte of address
-
- _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x00);
-
- } // end if page 0
- else
- if (page==PAGE_1)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 1 @ 0xA000:4000
-
- // first low byte of address
-
- _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x40);
-
- } // end else page 1
- else
- if (page==PAGE_2)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 1 @ 0xA000:8000
-
- // first low byte of address
-
- _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x80);
-
- } // end else page 2
- else
- if (page==PAGE_3)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 1 @ 0xA000:C000
-
- // first low byte of address
-
- _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0xC0);
-
- } // end else page 3
-
- // note: we could use WORD out's, but this is clearer, feel free to change them
-
- } // end Set_Visual_Page_Mode_Y
-
- ///////////////////////////////////////////////////////////////////////////////
-
- void Set_Visual_Page_Mode_Y_Half(int page)
- {
- // THIS VERSION OF THE FUNCTION SAVES AN OUTS WORTH OF COMPUTER CYCLES!!!
-
- // this function sets the visual page that will be displayed by the VGA
-
- if (page==PAGE_0)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 0 @ 0xA000:0000
-
- // SINCE THE LOW BYTE DOESN'T CHANGE IN THIS CONFIGURATION, I'LL
- // COMMENT OUT THE LOW BYTE STUFF...
-
- // first low byte of address
-
- // _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- // _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x00);
-
- } // end if page 0
- else
- if (page==PAGE_1)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 1 @ 0xA000:4000
-
- // first low byte of address
-
- // _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- // _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x40);
-
- } // end else page 1
- if (page==PAGE_2)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 1 @ 0xA000:8000
-
- // first low byte of address
-
- // _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- // _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0x80);
-
- } // end else page 2
- if (page==PAGE_3)
- {
- // re-program the start address registers in the CRT controller
- // to point at page 1 @ 0xA000:C000
-
- // first low byte of address
-
- // _outp(CRT_CONTROLLER,CRT_ADDR_LOW);
- // _outp(CRT_CONTROLLER+1,0x00);
-
- // now high byte
-
- _outp(CRT_CONTROLLER,CRT_ADDR_HI);
- _outp(CRT_CONTROLLER+1,0xC0);
-
- } // end else page 3
-
-
- } // end Set_Visual_Page_Mode_Y_Half
-
- ///////////////////////////////////////////////////////////////////////////////
-
- void Set_Working_Page_Mode_Y(int page)
- {
- // this function sets the page that all MODE Y functions will update when
- // called
-
- if (page==PAGE_0)
- video_buffer = pagey_0_buffer;
- else
- if (page==PAGE_1)
- video_buffer = pagey_1_buffer;
- else
- if (page==PAGE_2)
- video_buffer = pagey_2_buffer;
- else
- if (page==PAGE_3)
- video_buffer = pagey_3_buffer;
-
- } // end Set_Working_Page_Mode_Y
-
- // THESE LAST FEW FUNCTION WERE USED FOR 'SLOW RUNNINGS', THEY ARE A LITTLE
- // BIT APPLICATION SPECIFIC, BUT i COULDN'T THINK OF ANYWHERE ELSE TO PUT
- // THEM.
-
- void PCX_Copy_To_Video_Mem(pcx_picture_ptr image, unsigned char far *dest)
- {
- // This function copies a PCX PICTURE into a region of memory that will
- // not be displayed.
-
- int x_index; // looping variable
- int y_index; // looping variable
-
- unsigned int image_buffer_offset; // offset into image to be copied
- unsigned int vid_offset; // offset into never displayed memory
-
- for (x_index = 0; x_index<320; x_index++)
- {
- // first select the proper color plane to write to...
- // I could have written to one plane at a time but - Oh Hell!...
-
- _asm
- {
- mov dx,SEQUENCER ; address the sequencer
- mov al,SEQ_PLANE_ENABLE ; select the plane enable register
- mov cl,BYTE PTR x_index ; extract lower byte from x
- and cl,03h ; extract the plane number = x MOD 4
- mov ah,1 ; a "1" selects the plane in the plane enable
- shl ah,cl ; shift the "1" bit proper number of times
- out dx,ax ; do it baby!
- } // end asm
-
- for (y_index = 0; y_index<200; y_index++)
- {
- image_buffer_offset = (y_index<<8) + (y_index<<6) + x_index;
-
- vid_offset = (y_index<<6) + (y_index<<4) + (x_index>>2);
-
- dest[vid_offset] =
- image->buffer[image_buffer_offset];
- }
- }
- } // end PCX_Copy_To_Video_Mem
-
- void Copy_From_Unseen_Vram_to_Page(unsigned char far *buffer1, unsigned char far *buffer2,int to_row)
- {
- // this function copies a [mode Y] screen full 'o data from the area of
- // memory pointed to by 'buffer', and copies it to the page pointed to by
- // 'buffer2' (usually PAGE 0 or PAGE 1)...
-
- // THIS IS MY FIRST REAL W R I T E M O D E O N E experiment!
-
- // The function uses WRITE MODE ONE to copy all four planes at ONCE!
-
- unsigned int ModeRegTemp;
-
- unsigned char pixel_color;
-
- unsigned char far *buff2;
- unsigned char far *buff1;
- int xw,yw;
-
- // Write Mode ONE...
-
- _outp(GFX_CONTROLLER, GFX_WRITE_MODE);
-
- ModeRegTemp = _inp(GC_DATA_REG);
- ModeRegTemp = (ModeRegTemp & 0xFC) | 0x01;
- _outp(GC_DATA_REG, ModeRegTemp);
-
- // ... and the stuff
-
- buff1 = buffer1;
- buff2 = buffer2;
-
- // enable all planes
-
- _asm
- {
- mov dx,SEQUENCER
- mov al,SEQ_PLANE_ENABLE
- mov ah,0x0f
- out dx,ax
- }
-
- for (yw = 0; yw<to_row; yw++)
- {
- for (xw = 0; xw < 80; xw++)
- {
- *buff2=*buff1;
- buff2++;
- buff1++;
- }
- }
-
- // Now... leave WRITE MODE ONE!
-
- ModeRegTemp &= 0xFC;
-
- _outp(GFX_CONTROLLER, GFX_WRITE_MODE);
- _outp(GC_DATA_REG, ModeRegTemp);
-
- } // end Copy_From_Unseen_Vram_to_Page
-
- void Planar_Special_Fade_to(unsigned char far *buffer1, unsigned char far *buffer2, int to_row)
- {
- // this function copies a [mode Y] screen full 'o data from the area of
- // memory pointed to by 'buffer', and copies it to the page point to by
- // 'buffer2' (usually PAGE 0 or PAGE 1)...
-
- // THIS IS MY FIRST REAL W R I T E M O D E O N E experiment!
-
- unsigned int ModeRegTemp;
-
- unsigned char pixel_color;
-
- unsigned char far *buff2;
- unsigned char far *buff1;
- int xw,yw;
-
- // Write Mode ONE...
-
- _outp(GFX_CONTROLLER, GFX_WRITE_MODE);
-
- ModeRegTemp = _inp(GC_DATA_REG);
- ModeRegTemp = (ModeRegTemp & 0xFC) | 0x01;
- _outp(GC_DATA_REG, ModeRegTemp);
-
- // ... and the stuff
-
- buff1 = buffer1;
- buff2 = buffer2;
-
- _asm
- {
- mov dx,SEQUENCER
- mov al,SEQ_PLANE_ENABLE
- mov ah,0x08
- out dx,ax
- }
-
- for (yw = 0; yw<to_row; yw++)
- {
- for (xw = 0; xw < 80; xw++)
- {
- *buff2=*buff1;
- buff2++;
- buff1++;
- }
- }
-
- buff1 = buffer1;
- buff2 = buffer2;
-
- _asm
- {
- les di,buff1
- mov dx,SEQUENCER // address the sequencer
- mov al,SEQ_PLANE_ENABLE // select the plane enable register
- mov ah,0x04 // a "1" selects the plane in the plane enable
- out dx,ax // do it baby!
- } // end asm
-
- for (yw = 0; yw<to_row; yw++)
- {
- for (xw = 0; xw < 80; xw++)
- {
- *buff2=*buff1;
- buff2++;
- buff1++;
-
- }
- }
-
- buff1 = buffer1;
- buff2 = buffer2;
-
- _asm
- {
- mov dx,SEQUENCER // address the sequencer
- mov al,SEQ_PLANE_ENABLE // select the plane enable register
- mov ah,0x02 // a "1" selects the plane in the plane enable
- out dx,ax // do it baby!
- } // end asm
-
- for (yw = 0; yw<to_row; yw++)
- {
- for (xw = 0; xw < 80; xw++)
- {
- *buff2=*buff1;
- buff2++;
- buff1++;
-
- }
- }
-
- buff1 = buffer1;
- buff2 = buffer2;
-
- _asm
- {
- mov dx,SEQUENCER // address the sequencer
- mov al,SEQ_PLANE_ENABLE // select the plane enable register
- mov ah,0x01 // a "1" selects the plane in the plane enable
- out dx,ax // do it baby!
- } // end asm
-
- for (yw = 0; yw<to_row; yw++)
- {
- for (xw = 0; xw < 80; xw++)
- {
- *buff2=*buff1;
- buff2++;
- buff1++;
-
- }
- }
-
- // Now... leave WRITE MODE ONE!
-
- ModeRegTemp &= 0xFC;
-
- _outp(GFX_CONTROLLER, GFX_WRITE_MODE);
- _outp(GC_DATA_REG, ModeRegTemp);
-
- } // end Planar_Special_Fade_to
-