home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
SLOWRUNS.ZIP
/
SLOWSRC.ZIP
/
MAGIC3.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-30
|
37KB
|
1,323 lines
// I N C L U D E S ///////////////////////////////////////////////////////////
#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" // the header file for this module
// G L O B A L S //////////////////////////////////////////////////////////////
unsigned char far *video_buffer = (unsigned char far *)0xA0000000L;
unsigned char far *rom_char_set = (unsigned char far *)0xF000FA6EL;
// F U N C T I O N S /////////////////////////////////////////////////////////
void Print_Char(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; // bitmask used to extract proper bit
// compute starting offset in rom character lookup table
// multiple 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))
video_buffer[offset+x] = (unsigned char)color;
else
if (!transparent) // takes care of transparency
video_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
//////////////////////////////////////////////////////////////////////////////
void Print_String(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(x+(index<<3),y,string[index],color,transparent);
} // end Print_String
void Print_Char_Mode_Y(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
// This function cuts down on OUTS by 'unrolling the loop' and printing
// a character every FOURTH row at a time.
// It was one of my first attempts to print in MODE Y, and at the time
// I didn't realize I was only cutting half the OUTS per character, only
// HALVING the OUTS per line of text.
int offset, // offset into video memory
offset2,
x, // loop variable
y; // loop variable
unsigned char far *work_char; // pointer to character being printed
unsigned char bit_mask; // bitmask used to extract proper bit
// compute starting offset in rom character lookup table
// multiple 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
offset2 = (yc << 6) + (yc << 4);
offset = (yc << 6) + (yc << 4) + (xc>>2);
// draw the character row by row
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR xc // 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=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+=4)
{
// test for transparent pixel i.e. 0, if not transparent then draw
if ((*work_char & bit_mask))
video_buffer[offset+(x>>2)] = (unsigned char)color;
else
if (!transparent) // takes care of transparency
video_buffer[offset+(x>>2)] = 0; // make black part opaque
// shift bit mask
bit_mask = (bit_mask>>4);
} // end for x
// move to next line in video buffer and in rom character data area
offset += MODE_Y_WIDTH;
work_char++;
} // end for y
xc++;
work_char = rom_char_set + c * ROM_CHAR_HEIGHT;
offset = offset2 + (xc>>2);
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR xc // 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=0; y<ROM_CHAR_HEIGHT; y++)
{
// reset bit mask
bit_mask = 0x80;
bit_mask = (bit_mask>>1);
// draw each pixel of this row
for (x=1; x<ROM_CHAR_WIDTH; x+=4)
{
// test for transparent pixel i.e. 0, if not transparent then draw
if ((*work_char & bit_mask))
video_buffer[offset+(x>>2)] = (unsigned char)color;
else
if (!transparent) // takes care of transparency
video_buffer[offset+(x>>2)] = 0; // make black part opaque
// shift bit mask
bit_mask = (bit_mask>>4);
} // end for x
// move to next line in video buffer and in rom character data area
offset += MODE_Y_WIDTH;
work_char++;
} // end for y
xc++;
work_char = rom_char_set + c * ROM_CHAR_HEIGHT;
offset = offset2 + (xc>>2);
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR xc // 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=0; y<ROM_CHAR_HEIGHT; y++)
{
// reset bit mask
bit_mask = 0x80;
bit_mask = (bit_mask>>2);
// draw each pixel of this row
for (x=2; x<ROM_CHAR_WIDTH; x+=4)
{
// test for transparent pixel i.e. 0, if not transparent then draw
if ((*work_char & bit_mask))
video_buffer[offset+(x>>2)] = (unsigned char)color;
else
if (!transparent) // takes care of transparency
video_buffer[offset+(x>>2)] = 0; // make black part opaque
// shift bit mask
bit_mask = (bit_mask>>4);
} // end for x
// move to next line in video buffer and in rom character data area
offset += MODE_Y_WIDTH;
work_char++;
} // end for y
xc++;
work_char = rom_char_set + c * ROM_CHAR_HEIGHT;
offset = offset2 + (xc>>2);
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR xc // 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=0; y<ROM_CHAR_HEIGHT; y++)
{
// reset bit mask
bit_mask = 0x80;
bit_mask = (bit_mask>>3);
// draw each pixel of this row
for (x=3; x<ROM_CHAR_WIDTH; x+=4)
{
// test for transparent pixel i.e. 0, if not transparent then draw
if ((*work_char & bit_mask))
video_buffer[offset+(x>>2)] = (unsigned char)color;
else
if (!transparent) // takes care of transparency
video_buffer[offset+(x>>2)] = 0; // make black part opaque
// shift bit mask
bit_mask = (bit_mask>>4);
} // end for x
// move to next line in video buffer and in rom character data area
offset += MODE_Y_WIDTH;
work_char++;
} // end for y
} // end Print_Char_Mode_Y
//////////////////////////////////////////////////////////////////////////////
void Print_String_Mode_Y(int x,int y,int color, char *string,int transparent)
{
// this MODE Y function prints an entire string on the screen with fixed
// spacing between each character by calling the Print_Char_Mode_Y() 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_Mode_Y(x+(index<<3),y,string[index],color,transparent);
} // end Print_String_Mode_Y
///////////////////////////////////////////////////////////////////////////////
void Write_Pixel(int x,int y,int color)
{
// plots the pixel in the desired color a little quicker using binary shifting
// to accomplish the multiplications
// use the fact that 320*y = 256*y + 64*y = y<<8 + y<<6
video_buffer[((y<<8) + (y<<6)) + x] = (unsigned char )color;
} // end Write_Pixel
///////////////////////////////////////////////////////////////////////////////
int Read_Pixel(int x,int y)
{
// this function read a pixel from the screen buffer
// use the fact that 320*y = 256*y + 64*y = y<<8 + y<<6
return((int)(video_buffer[((y<<8) + (y<<6)) + x]));
} // end Read_Pixel
//////////////////////////////////////////////////////////////////////////////
void Set_Graphics_Mode(int mode)
{
// use the video interrupt 10h and the C interrupt function to set
// the video mode
union REGS inregs,outregs;
inregs.h.ah = 0; // set video mode sub-function
inregs.h.al = (unsigned char)mode; // video mode to change to
int86(0x10, &inregs, &outregs);
} // end Set_Graphics_Mode
/////////////////////////////////////////////////////////////////////////////
void Time_Delay(int clicks)
{
// this function uses the internal timer to wait a specified number of "clicks"
// the actual amount of real time is the number of clicks * (time per click)
// usually the time per click is set to 1/18th of a second or 55ms
long far *clock = (long far *)0x0000046CL; // address of timer
long start_time; // starting time
// get current time
start_time = *clock;
// when the current time minus the starting time >= the requested delay then
// the function can exit
while(labs(*clock - start_time) < (long)clicks){}
} // end Time_Delay
////////////////////////////////////////////////////////////////////////////////
void Line_H(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
int temp; // used for temporary storage during endpoint swap
// sort x1 and x2, so that x2 > x1
if (x1>x2)
{
temp = x1;
x1 = x2;
x2 = temp;
} // end swap
// draw the row of pixels
_fmemset((char far *)(video_buffer + ((y<<8) + (y<<6)) + x1),
(unsigned char)color,x2-x1+1);
} // end Line_H
//////////////////////////////////////////////////////////////////////////////
void Line_V(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
temp; // used for temporary storage during swap
// make sure y2 > y1
if (y1>y2)
{
temp = y1;
y1 = y2;
y2 = temp;
} // end swap
// compute starting position
start_offset = video_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_V
///////////////////////////////////////////////////////////////////////////////
void Line_H_Mode_Y(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
int index;
int temp; // used for temporary storage during endpoint swap
// draw the row of pixels
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR x1 // extract lower byte from index
and cl,03h // extract the plane number = index 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 (index = x1; index <= x2; index+=4)
{
_fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
(unsigned char)color,1);
}
x1++;
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR x1 // extract lower byte from index
and cl,03h // extract the plane number = index 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 (index = x1; index <= x2; index+=4)
{
_fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
(unsigned char)color,1);
}
x1++;
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR x1 // extract lower byte from index
and cl,03h // extract the plane number = index 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 (index = x1; index <= x2; index+=4)
{
_fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
(unsigned char)color,1);
}
x1++;
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR x1 // extract lower byte from index
and cl,03h // extract the plane number = index 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 (index = x1; index <= x2; index+=4)
{
_fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
(unsigned char)color,1);
}
} // end Line_H_Mode_Y
//////////////////////////////////////////////////////////////////////////////
void Line_H_Mode_Z(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
int index;
int temp; // used for temporary storage during endpoint swap
// sort x1 and x2, so that x2 > x1
if (x1>x2)
{
temp = x1;
x1 = x2;
x2 = temp;
} // end swap
// draw the row of pixels
for (index = x1; index <= x2; index++)
{
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR index // extract lower byte from index
and cl,03h // extract the plane number = index 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
_fmemset((char far *)(video_buffer + ((y<<6) + (y<<4)) + (index>>2)),
(unsigned char)color,1);
}
} // end Line_H_Mode_Z
//////////////////////////////////////////////////////////////////////////////
void Line_V_Mode_Y(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
temp; // used for temporary storage during swap
// make sure y2 > y1
if (y1>y2)
{
temp = y1;
y1 = y2;
y2 = temp;
} // end swap
// compute starting position
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR x // extract lower byte from index
and cl,03h // extract the plane number = index 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
start_offset = video_buffer + ((y1<<6) + (y1<<4)) + (x>>2);
for (index=0; index<=y2-y1; index++)
{
// set the pixel
*start_offset = (unsigned char)color;
// move downward to next line
start_offset+=80;
} // end for index
} // end Line_V_Mode_Y
//////////////////////////////////////////////////////////////////////////////
void Line_V_Mode_Z(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
temp; // used for temporary storage during swap
// make sure y2 > y1
if (y1>y2)
{
temp = y1;
y1 = y2;
y2 = temp;
} // end swap
// compute starting position
_asm
{
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR x // extract lower byte from index
and cl,03h // extract the plane number = index 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
start_offset = video_buffer + ((y1<<6) + (y1<<4)) + (x>>2);
for (index=0; index<=y2-y1; index++)
{
// set the pixel
*start_offset = (unsigned char)color;
// move downward to next line
start_offset+=80;
} // end for index
} // end Line_V_Mode_Z
//////////////////////////////////////////////////////////////////////////////
void Write_Color_Reg(int index, RGB_color_ptr color)
{
// this function is used to write a color register with the RGB value
// within "color"
// tell vga card which color register to update
outp(COLOR_REGISTER_WR, index);
// update the color register RGB triple, note the same port is used each time
// the hardware will make sure each of the components is stored in the
// proper location
outp(COLOR_DATA,color->red);
outp(COLOR_DATA,color->green);
outp(COLOR_DATA,color->blue);
} // end Write_Color_Reg
///////////////////////////////////////////////////////////////////////////////
RGB_color_ptr Read_Color_Reg(int index, RGB_color_ptr color)
{
// this function reads the RGB triple out of a palette register and places it
// into "color"
// tell vga card which register to read
outp(COLOR_REGISTER_RD, index);
// now extract the data
color->red = (unsigned char)inp(COLOR_DATA);
color->green = (unsigned char)inp(COLOR_DATA);
color->blue = (unsigned char)inp(COLOR_DATA);
// return a pointer to color so that the function can be used as an RVALUE
return(color);
} // end Read_Color_Reg
///////////////////////////////////////////////////////////////////////////////
void Read_Palette(int start_reg,int end_reg, RGB_palette_ptr the_palette)
{
// this function will read the palette registers in the range start_reg to
// end_reg and save them into the appropriate positions in colors
int index; // used for looping
RGB_color color;
// read all the registers
for (index=start_reg; index<=end_reg; index++)
{
// read the color register
Read_Color_Reg(index,(RGB_color_ptr)&color);
// save it in database
the_palette->colors[index].red = color.red;
the_palette->colors[index].green = color.green;
the_palette->colors[index].blue = color.blue;
} // end for index
// save the interval of registers that were saved
the_palette->start_reg = start_reg;
the_palette->end_reg = end_reg;
} // end Read_Palette
///////////////////////////////////////////////////////////////////////////////
void Write_Palette(int start_reg,int end_reg, RGB_palette_ptr the_palette)
{
// this function will write to the color registers using the data in the
// sen palette structure
int index; // used for looping
// write all the registers
for (index=start_reg; index<=end_reg; index++)
{
// write the color registers using the data from the sent palette
Write_Color_Reg(index,(RGB_color_ptr)&(the_palette->colors[index]));
} // end for index
} // end Write_Palette
///////////////////////////////////////////////////////////////////////////////
void Draw_Rectangle(int x1,int y1,int x2,int y2,int color)
{
// this function will draw a rectangle from (x1,y1) - (x2,y2)
// it is assumed that each endpoint is within the screen boundaries
// and (x1,y1) is the upper left hand corner and (x2,y2) is the lower
// right hand corner
unsigned char far *start_offset; // starting memory offset of first row
int width; // width of rectangle
// compute starting offset of first row
start_offset = video_buffer + ((y1<<8) + (y1<<6)) + x1;
// compute width of rectangle
width = 1 + x2 - x1; // the "1" to reflect the true width in pixels
// draw the rectangle row by row
while(y1++<=y2)
{
// draw the line
_fmemset((char far *)start_offset,(unsigned char)color,width);
// move the memory pointer to the next line
start_offset+=320;
} // end while
} // end Draw_Rectangle
////////////////////////////////////////////////////////////////////////////////
void Fill_Screen(int color)
{
// this function will fill the entire screen with the sent color
// use the inline assembler for speed
_asm {
les di,video_buffer // point es:di to video buffer
mov al,BYTE PTR color // move the color into al and ah
mov ah,al // replicate color into ah
mov cx,320*200/2 // number of words to fill(using word is faster than bytes)
rep stosw // move the color into the video buffer really fast!
} // end inline asm
} // end Fill_Screen
//////////////////////////////////////////////////////////////////////////////
void Fill_Screen_Z(int color)
{
// this function will fill the mode Z video buffer with the sent color
// use the inline assembler for speed
_asm {
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov ah,0fh // enable all four planes
out dx,ax // do it baby!
les di,video_buffer // point es:di to video buffer
mov al,BYTE PTR color // move the color into al and ah
mov ah,al // replicate color into ah
mov cx,320*400/8 // number of words to fill(using word is faster than bytes)
rep stosw // move the color into the video buffer really fast!
} // end inline asm
} // end Fill_Screen_Z
///////////////////////////////////////////////////////////////////////////////
void Write_Pixel_Z(int x,int y,int color)
{
// this function will write a pixel to screen in mode Z
// first select the proper color plane use inline for speed
// if we used C then there would be a function call and about 10-15 more
// instructions!
_asm {
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR x // 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
// write the pixel, offset = (y*320+x)/4
video_buffer[(y<<6)+(y<<4)+(x>>2)] = (unsigned char )color;
} // end Write_Pixel_Z
///////////////////////////////////////////////////////////////////////////////
void Set_Mode_Z(void)
{
// this function will set the video mode to 320x400x256
int data; // used to store data
unsigned char far *zpage1 = (unsigned char far *)0xA0000000L;
unsigned char far *zpage2 = (unsigned char far *)0xA0008000L;
// set system to mode 13h and use it as a foundation to base 320x400 mode on
_asm {
mov ax,0013h // ah=function number 00(set graphics mode), al=13h
int 10h // video interrupt 10h
} // end asm
// make changes to the crt controller first
// set number of scanlines to 1
outp(CRT_CONTROLLER,CRT_MAX_SCANLINE);
data=inp(CRT_CONTROLLER+1);
outp(CRT_CONTROLLER+1,RESET_BITS(data,0x0f));
// use byte addressing instead of word
outp(CRT_CONTROLLER,CRT_ADDR_MODE);
data=inp(CRT_CONTROLLER+1);
outp(CRT_CONTROLLER+1,RESET_BITS(data,0x40));
// second register that needs to reflect byte addressing
outp(CRT_CONTROLLER,CRT_MODE_CONTROL);
data=inp(CRT_CONTROLLER+1);
outp(CRT_CONTROLLER+1,SET_BITS(data,0x40));
// make changes to graphics controller
// set addressing to not use odd/even memory writes
outp(GFX_CONTROLLER,GFX_WRITE_MODE);
data=inp(GFX_CONTROLLER+1);
outp(GFX_CONTROLLER+1,RESET_BITS(data,0x10));
// don't chain the memory maps together
outp(GFX_CONTROLLER,GFX_MISC);
data=inp(GFX_CONTROLLER+1);
outp(GFX_CONTROLLER+1,RESET_BITS(data,0x02));
// make changes to sequencer
// again we must select no chaining and no odd/even memory addressing
outp(SEQUENCER,SEQ_MEMORY_MODE);
data =inp(SEQUENCER+1);
data = RESET_BITS(data,0x08);
data = SET_BITS(data,0x04);
outp(SEQUENCER+1,data);
// now clear the screen
outp(SEQUENCER,SEQ_PLANE_ENABLE);
outp(SEQUENCER+1,0x0f);
// clear the screen, remember it is 320x400, but that is divided into four
// planes, hence we need only to clear 32k out since there will ne four planes
// each being cleared in parallel for a total of 4*32k or 128 = 320x400
// note: "k" in this example means 1000 not 1024
// clear BOTH pages...
_asm {
les di,zpage1 // point es:di to video buffer, same address for mode Z
xor ax,ax // move a zero into al and ah
mov cx,320*400/8 // number of words to fill(using word is faster than bytes)
rep stosw // move the color into the video buffer really fast!
} // end inline asm
_asm {
les di,zpage2 // point es:di to video buffer, same addre for mode Z
xor ax,ax // move a zero into al and ah
mov cx,320*400/8 // number of words to fill(using word is faster than bytes)
rep stosw // move the color into the video buffer really fast!
} // end inline asm
} // end Set_Mode_Z
// MODE_Y_STUFF...
void Fill_Screen_Y(int color)
{
// this function will fill the mode Z video buffer with the sent color
// use the inline assembler for speed
_asm {
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov ah,0fh // enable all four planes
out dx,ax // do it baby!
les di,video_buffer // point es:di to video buffer
mov al,BYTE PTR color // move the color into al and ah
mov ah,al // replicate color into ah
mov cx,320*200/8 // number of words to fill(using word is faster than bytes)
rep stosw // move the color into the video buffer really fast!
} // end inline asm
} // end Fill_Screen_Y
///////////////////////////////////////////////////////////////////////////////
void Write_Pixel_Y(int x,int y,int color)
{
// this function will write a pixel to screen in mode Z
// first select the proper color plane use inline for speed
// if we used C then there would be a function call and about 10-15 more
// instructions!
_asm {
mov dx,SEQUENCER // address the sequencer
mov al,SEQ_PLANE_ENABLE // select the plane enable register
mov cl,BYTE PTR x // 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
// write the pixel, offset = (y*320+x)/4
video_buffer[(y<<6)+(y<<4)+(x>>2)] = (unsigned char )color;
} // end Write_Pixel_Y
///////////////////////////////////////////////////////////////////////////////
void Set_Mode_Y(void)
{
// this function will set the video mode to 320x400x256
int data; // used to store data
// set system to mode 13h and use it as a foundation to base 320x400 mode on
_asm {
mov ax,0013h // ah=function number 00(set graphics mode), al=13h
int 10h // video interrupt 10h
} // end asm
// make changes to the crt controller first
// set number of scanlines to 1
//outp(CRT_CONTROLLER,CRT_MAX_SCANLINE);
//data=inp(CRT_CONTROLLER+1);
//outp(CRT_CONTROLLER+1,RESET_BITS(data,0x0f));
// use byte addressing instead of word
outp(CRT_CONTROLLER,CRT_ADDR_MODE);
data=inp(CRT_CONTROLLER+1);
outp(CRT_CONTROLLER+1,RESET_BITS(data,0x40));
// second register that needs to reflect byte addressing
outp(CRT_CONTROLLER,CRT_MODE_CONTROL);
data=inp(CRT_CONTROLLER+1);
outp(CRT_CONTROLLER+1,SET_BITS(data,0x40));
// make changes to graphics controller
// set addressing to not use odd/even memory writes
outp(GFX_CONTROLLER,GFX_WRITE_MODE);
data=inp(GFX_CONTROLLER+1);
outp(GFX_CONTROLLER+1,RESET_BITS(data,0x10));
// don't chain the memory maps together
outp(GFX_CONTROLLER,GFX_MISC);
data=inp(GFX_CONTROLLER+1);
outp(GFX_CONTROLLER+1,RESET_BITS(data,0x02));
// make changes to sequencer
// again we must select no chaining and no odd/even memory addressing
outp(SEQUENCER,SEQ_MEMORY_MODE);
data =inp(SEQUENCER+1);
data = RESET_BITS(data,0x08);
data = SET_BITS(data,0x04);
outp(SEQUENCER+1,data);
// now clear the screen
outp(SEQUENCER,SEQ_PLANE_ENABLE);
outp(SEQUENCER+1,0x0f);
// clear the screen, remember it is 320x200, but that is divided into four
// planes, hence we need only to clear 16k out since there will be four planes
// each being cleared in parallel for a total of 4*16k or 64 = 320x200
// note: "k" in this example means 1000 not 1024
_asm {
les di,video_buffer // point es:di to video buffer, same addre for mode Z
xor ax,ax // move a zero into al and ah
mov cx,320*200/8 // number of words to fill(using word is faster than bytes)
rep stosw // move the color into the video buffer really fast!
} // end inline asm
} // end Set_Mode_Y
void Set_Mode_X(void)
{
// this function will set the video mode to 320x400x256
unsigned char data,index,Vert_End;
// set system to mode 13h and use it as a foundation to base 320x400 mode on
_asm {
mov ax,0013h // ah=function number 00(set graphics mode), al=13h
int 10h // video interrupt 10h
} // end asm
// make changes to sequencer
// again we must select no chaining and no odd/even memory addressing
outp(SEQUENCER,SEQ_MEMORY_MODE);
outp(SEQUENCER+1,0x06);
// Preparing to reset Dot_Clock
outp(SEQUENCER,0);
outp(SEQUENCER+1,0x01);
outp(MISC_OUTPUT_REG,0xE3);
outp(SEQUENCER,0);
outp(SEQUENCER+1,0x03);
// remove write protect
outp(CRTC_INDEX_REG, VERT_RETRACE_END_INDEX);
Vert_End = inp(CRTC_INDEX_REG+1);
Vert_End &= 0x7F; // clear high bit
outp(CRTC_INDEX_REG+1, Vert_End);
// alter CRTC registers
outp(CRTC_INDEX_REG, VERT_TOTAL_INDEX);
outp(CRTC_INDEX_REG+1, 0x0D);
outp(CRTC_INDEX_REG, OVERFLOW_INDEX);
outp(CRTC_INDEX_REG+1, 0x3E);
outp(CRTC_INDEX_REG, MAX_SCAN_LINE_INDEX);
outp(CRTC_INDEX_REG+1, 0x41);
outp(CRTC_INDEX_REG, VERT_RETRACE_START_INDEX);
outp(CRTC_INDEX_REG+1, 0xEA);
outp(CRTC_INDEX_REG, VERT_RETRACE_END_INDEX);
outp(CRTC_INDEX_REG+1, 0xAC);
outp(CRTC_INDEX_REG, VERT_DISPLAY_END_INDEX);
outp(CRTC_INDEX_REG+1, 0xDF);
outp(CRTC_INDEX_REG, UNDERLINE_LOCATION_INDEX);
outp(CRTC_INDEX_REG+1, 0x00);
outp(CRTC_INDEX_REG, START_VERT_BLANK_INDEX);
outp(CRTC_INDEX_REG+1, 0xE7);
outp(CRTC_INDEX_REG, END_VERT_BLANK_INDEX);
outp(CRTC_INDEX_REG+1, 0x06);
outp(CRTC_INDEX_REG, MODE_CONTROL_INDEX);
outp(CRTC_INDEX_REG+1, 0xE3);
// now clear the screen
outp(SEQUENCER,SEQ_PLANE_ENABLE);
outp(SEQUENCER+1,0x0f);
// clear the screen, remember it is 320x200, but that is divided into four
// planes, hence we need only to clear 16k out since there will be four planes
// each being cleared in parallel for a total of 4*16k or 64 = 320x200
// note: "k" in this example means 1000 not 1024
_asm {
les di,video_buffer // point es:di to video buffer, same addre for mode Z
xor ax,ax // move a zero into al and ah
mov cx,320*200/8 // number of words to fill(using word is faster than bytes)
rep stosw // move the color into the video buffer really fast!
} // end inline asm
} // end Set_Mode_Y
// The following functions are purely HIGH-JACKED CODE.
void Wait_Vertical_Retrace_End(void)
{
unsigned char InputStatus1;
/* make sure we aren't in display state (= not retrace) */
do {
InputStatus1 = inp(VGA_INPUT_STATUS_1);
} while (!(InputStatus1 & VR_BIT));
/* wait for retrace to end */
do {
InputStatus1 = inp(VGA_INPUT_STATUS_1);
} while (InputStatus1 & VR_BIT);
}
/*
Function: WaitDisplayMode
Description:
If the VGA is currently in display mode, the function returns
immediately, else it waits until diplay mode is entered.
*/
void Wait_Display_Mode(void)
{
unsigned char InputStatus1;
/* wait for retrace to end and display mode to start */
do {
InputStatus1 = inp(VGA_INPUT_STATUS_1);
} while (InputStatus1 & DISPLAY_ENABLE);
}
/*
Function: WaitRetraceMode
Description:
If the VGA is currently in retrace mode, the function returns
immediately, else it waits until retrace mode is entered.
*/
void Wait_Retrace_Mode(void)
{
unsigned char InputStatus1;
/* wait for display mode to end and retrace to start */
do {
InputStatus1 = inp(VGA_INPUT_STATUS_1);
} while (!(InputStatus1 & VR_BIT));
}
/*
Function: VerticalRetraceOccuring
Description:
Returns the current state of the VGA vertical retrace. If
retrace is occuring, the function returns TRUE.
*/
int Vertical_Retrace_Occuring(void)
{
return (inp(VGA_INPUT_STATUS_1) & VR_BIT) >> 3;
}