#include #include #include #include struct { char VESASignature[4]; /* 'VESA' 4 byte signature */ short VESAVersion; /* VBE version number */ char far *OEMStringPtr; /* Pointer to OEM string */ long Capabilities; /* Capabilities of video card */ unsigned far *VideoModePtr; /* Pointer to supported modes */ short TotalMemory; /* Number of 64kb memory blocks */ char reserved[236]; /* Pad to 256 byte block size */ } VbeInfoBlock; struct { unsigned short ModeAttributes; /* Mode attributes */ unsigned char WinAAttributes; /* Window A attributes */ unsigned char WinBAttributes; /* Window B attributes */ unsigned short WinGranularity; /* Window granularity in k */ unsigned short WinSize; /* Window size in k */ unsigned short WinASegment; /* Window A segment */ unsigned short WinBSegment; /* Window B segment */ void (far *WinFuncPtr)(void); /* Pointer to window function */ unsigned short BytesPerScanLine; /* Bytes per scanline */ unsigned short XResolution; /* Horizontal resolution */ unsigned short YResolution; /* Vertical resolution */ unsigned char XCharSize; /* Character cell width */ unsigned char YCharSize; /* Character cell height */ unsigned char NumberOfPlanes; /* Number of memory planes */ unsigned char BitsPerPixel; /* Bits per pixel */ unsigned char NumberOfBanks; /* Number of CGA style banks */ unsigned char MemoryModel; /* Memory model type */ unsigned char BankSize; /* Size of CGA style banks */ unsigned char NumberOfImagePages; /* Number of images pages */ unsigned char res1; /* Reserved */ unsigned char RedMaskSize; /* Size of direct color red mask */ unsigned char RedFieldPosition; /* Bit posn of lsb of red mask */ unsigned char GreenMaskSize; /* Size of direct color green mask */ unsigned char GreenFieldPosition; /* Bit posn of lsb of green mask */ unsigned char BlueMaskSize; /* Size of direct color blue mask */ unsigned char BlueFieldPosition; /* Bit posn of lsb of blue mask */ unsigned char RsvdMaskSize; /* Size of direct color res mask */ unsigned char RsvdFieldPosition; /* Bit posn of lsb of res mask */ unsigned char DirectColorModeInfo; /* Direct color mode attributes */ unsigned char res2[216]; /* Pad to 256 byte block size */ } ModeInfoBlock; typedef enum { memPL = 3, /* Planar memory model */ memPK = 4, /* Packed pixel memory model */ memRGB = 6, /* Direct color RGB memory model */ memYUV = 7, /* Direct color YUV memory model */ } memModels; char mystr[256]; char *get_str(); int xres,yres; /* Resolution of video mode used */ int bytesperline; /* Logical CRT scanline length */ int curBank; /* Current read/write bank */ unsigned int bankShift; /* Bank granularity adjust factor */ int oldMode; /* Old video mode number */ char far *screenPtr; /* Pointer to start of video memory */ void (far *bankSwitch)(void); /* Direct bank switching function */ int getVbeInfo() { union REGS in,out; struct SREGS segs; char far *VbeInfo = (char far *)&VbeInfoBlock; in.x.ax = 0x4F00; in.x.di = FP_OFF(VbeInfo); segs.es = FP_SEG(VbeInfo); int86x(0x10, &in, &out, &segs); return (out.x.ax == 0x4F); } int getModeInfo(int mode) { union REGS in,out; struct SREGS segs; char far *modeInfo = (char far *)&ModeInfoBlock; if (mode < 0x100) return 0; /* Ignore non-VBE modes */ in.x.ax = 0x4F01; in.x.cx = mode; in.x.di = FP_OFF(modeInfo); segs.es = FP_SEG(modeInfo); int86x(0x10, &in, &out, &segs); if (out.x.ax != 0x4F) return 0; if ((ModeInfoBlock.ModeAttributes & 0x1) && ModeInfoBlock.MemoryModel == memPK && ModeInfoBlock.BitsPerPixel == 8 && ModeInfoBlock.NumberOfPlanes == 1) { return 1; } return 0; } void setVBEMode(int mode) { union REGS in,out; in.x.ax = 0x4F02; in.x.bx = mode; int86(0x10,&in,&out); } int getVBEMode(void) { union REGS in,out; in.x.ax = 0x4F03; int86(0x10,&in,&out); return out.x.bx; } void setBank(int bank) { union REGS in,out; if (bank == curBank) /* Bank is already active */ return; curBank = bank; /* Save current bank number */ bank <<= bankShift; /* Adjust to window granularity */ #ifdef DIRECT_BANKING setbxdx(0,bank); bankSwitch(); setbxdx(1,bank); bankSwitch(); #else in.x.ax = 0x4F05; in.x.bx = 0; in.x.dx = bank; int86(0x10, &in, &out); in.x.ax = 0x4F05; in.x.bx = 1; in.x.dx = bank; int86(0x10, &in, &out); #endif } void put_pixel(int x, int y, int color) { long addr = (long)y * bytesperline + x; setBank((int)(addr >> 16)); *(screenPtr + (addr & 0xFFFF)) = (char)color; } char *get_str(char far *p) { int i; char *q = mystr; for(i = 0; i < 255; i++) { if ( *p ) { *q++ = *p++; } else { break; } } *q = '\0'; return(mystr); } void availableModes(void) { unsigned far *p; if (!getVbeInfo()) { printf("No VESA VBE detected\n"); exit(1); } printf("VESA VBE Version %d.%d detected (%s)\n\n", VbeInfoBlock.VESAVersion >> 8, VbeInfoBlock.VESAVersion & 0xF, get_str(VbeInfoBlock.OEMStringPtr)); printf("Available 256 color video modes:\n"); for (p = VbeInfoBlock.VideoModePtr; *p !=(unsigned)-1; p++) { if (getModeInfo(*p)) { printf(" %4d x %4d %d bits per pixel\n", ModeInfoBlock.XResolution, ModeInfoBlock.YResolution, ModeInfoBlock.BitsPerPixel); } } } int init_graphics(unsigned int x, unsigned int y) { unsigned far *p; if (!getVbeInfo()) { printf("No VESA VBE detected\n"); return -1; } for (p = VbeInfoBlock.VideoModePtr; *p != (unsigned)-1; p++) { if (getModeInfo(*p) && ModeInfoBlock.XResolution == x && ModeInfoBlock.YResolution == y) { xres = x; yres = y; bytesperline = ModeInfoBlock.BytesPerScanLine; bankShift = 0; while ((unsigned)(64 >> bankShift) != ModeInfoBlock.WinGranularity) bankShift++; bankSwitch = ModeInfoBlock.WinFuncPtr; curBank = -1; screenPtr = (char far *)( ((long)0xA000)<<16 | 0); oldMode = getVBEMode(); setVBEMode(*p); return 0; } } printf("Valid video mode not found\n"); return -1; } // mouse cursors made with 2L8 Cursor editor // downloaded from http://ftp.gnome.org/mirror/archive/ftp.sunet.se/pub/simtelnet/msdos/mouse/ int POINT[32] = { 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff, 0x00ff, 0x007f, 0x003f, 0x003f, 0x01ff, 0x10ff, 0x30ff, 0xf87f, 0xf87f, 0xfc7f, 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x7f00, 0x7f80, 0x7c00, 0x6c00, 0x4600, 0x0600, 0x0300, 0x0300, 0x0000 }; short Mouse_Init (void) { union REGS in_reg, out_reg; struct SREGS segreg; segread(&segreg); in_reg.x.ax = (unsigned char)0x0; int86x(0x33, &in_reg, &out_reg, &segreg); // return # of mouse buttons (-1 if no mouse) return out_reg.x.bx; } void Mouse_Show (void) { union REGS in_reg, out_reg; struct SREGS segreg; segread(&segreg); in_reg.x.ax = (unsigned char)0x1; int86x(0x33, &in_reg, &out_reg, &segreg); } void Mouse_Hide (void) { union REGS in_reg, out_reg; struct SREGS segreg; segread(&segreg); in_reg.x.ax = (unsigned char)0x2; int86x(0x33, &in_reg, &out_reg, &segreg); } void Mouse_Status( int *x, int *y, int *b ) { union REGS in_reg, out_reg; struct SREGS segreg; segread(&segreg); in_reg.x.ax = 0x3; in_reg.x.bx = 0; in_reg.x.cx = 0; in_reg.x.dx = 0; int86x(0x33, &in_reg, &out_reg, &segreg); *b = out_reg.x.bx; *x = out_reg.x.cx; *y = out_reg.x.dx; } void Mouse_Cursor(int *shape, int x, int y) { union REGS inreg, outreg; struct SREGS s; inreg.x.ax = 0x9; inreg.x.bx = x; inreg.x.cx = y; inreg.x.dx = (unsigned)shape; segread(&s); s.es = s.ds; int86x(0x33,&inreg,&outreg,&s); } int GetKey() { union REGS in, out; in.h.ah = 0x08; int86(0x21, &in, &out); if (out.h.al == 0) { return getkey() + 0x100; } else { return out.h.al; } } #define SCREEN_WIDTH 1024 #define SCREEN_HEIGHT 768 void clear(unsigned char color) { unsigned int x, y; for(y = 0; y < SCREEN_HEIGHT; y++) { for(x = 0; x < SCREEN_WIDTH; x++) { put_pixel(x, y, color); } } } unsigned char car_sprite[] = {21, 0, 6, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0 }; unsigned char ball_sprite[] = {5, 0, 5, 0, /* width 5, height 5 */ 0, 11, 11, 11, 0, 11, 14, 3, 3, 9, 11, 3, 3, 3, 9, 11, 3, 3, 3, 9, 0, 9, 9, 9, 0 }; void put_sprite (int x, int y, unsigned char sprite[]) { int x_count, y_count; int width, height; /* Extract the width from the first two bytes of the array, and the height from the third and fourth bytes of the array: */ width = sprite[0] + (sprite[1] << 8); height = sprite[2] + (sprite[3] << 8); for (y_count = 0; y_count <= height - 1; y_count++) { for (x_count = 0; x_count <= width - 1; x_count++) { put_pixel (x + x_count, y + y_count, sprite[4 + (y_count * width) + x_count]); } } } int render() { int j = 0; int x = 0; int y = 0; clear(0); while (j < 60 * 10) { j++; PutSprite(50 + x, 100 + x, car_sprite); PutSprite(150 + y, 100 + 2 * y, ball_sprite); x++; y++; delay(15); clear(0); } return 0; } void main(int argc,char *argv[]) { init_graphics(SCREEN_WIDTH, SCREEN_HEIGHT); Mouse_Init(); Mouse_Show(); Mouse_Cursor(POINT, 0, 0); while (1) { if ( render() == -1 ) { break; } } setVBEMode(oldMode); }