Created
November 30, 2023 02:18
-
-
Save skull-squadron/0cc4f0f346ac02c925924ea1b6615cdf to your computer and use it in GitHub Desktop.
Mode X 320x400 256 color VGA mode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* */ | |
/* PAGEDEMO.C */ | |
/* */ | |
/* There is a nonstandard 320x400 256 color VGA mode which has two pages. */ | |
/* This program demonstrates its use by setting up the mode, drawing to */ | |
/* the two pages, and flipping the pages for instanteous appearance of */ | |
/* of the graphics. */ | |
/* */ | |
/* A scanline function is included which shows how to take advantage of */ | |
/* memory plane masking to draw four pixels simutaneously. */ | |
/* */ | |
/* The mode setting routine is based upon Michael Abrash's demo which */ | |
/* can be found in PJ71.ARC in LDOS/lib 10. */ | |
/* */ | |
/* Thanks to Lawrence Gozum, Paul Lefevre, Joseph Wofford, Dave Angel, */ | |
/* Neil Rubenking, Brian Buck, and Eric Ace for their patience and help. */ | |
/* */ | |
/* Written for Turbo C. Compile with: tcc pagedemo */ | |
/* */ | |
/* Copyright Gary Boone 1991. Free for use in Free/Share/Comm. programs. */ | |
/* */ | |
/* Enjoy! */ | |
/* Gary Boone CIS:73040,3725 -- 23 April 1991 */ | |
/* */ | |
#include "dos.h" /* for getch() */ | |
void switchModes(int mode); | |
void clearScreen(int page); | |
void scanline(int page, int x1, int x2, int y, int color); | |
void main(void) | |
{ int i,p,j; | |
switchModes(0x13); | |
for (i=0;i<400;i++) /* Draw a pattern on page 0 */ | |
scanline(0,0,i%320,i,i%256); /* while we watch. */ | |
for (i=0;i<400;i++) /* Draw another pattern on the */ | |
scanline(1,i%320,319,i,i%256); /* hidden page. */ | |
getch(); /* Wait for any key to be hit. */ | |
outport(0x3D4, 0x800C); /* Flip to other page, */ | |
getch(); /* and wait. */ | |
p=0; /* For fun, flip the pages */ | |
outportb(0x3D4, 0x0C); /* quickly. */ | |
for (i=0;i<500;i++) | |
{ outportb(0x3D5, 0x80*(p=1-p)); | |
for(j=1;j<1000;j++); /* delay so you can see the page */ | |
} | |
getch(); | |
switchModes(3); /* Done. Back to text mode. */ | |
} | |
void clearScreen(int page) /* how to quickly fill the screen with a color */ | |
{ char far *addr; | |
unsigned int i; | |
addr = (char far*) (0xA0000000+0x8000000*page); /* point into video mem */ | |
outport(0x3C4,0x0f02); /* set all planes on */ | |
for (i=0;i<0x8000;i++) | |
*(addr++)=(char) 0; /* four pixels at once! */ | |
} | |
/* Scanline(): Draws horizontal lines quickly. */ | |
/* To increase speed, masks are determined from a look-up */ | |
/* table and written four at once, instead of being calculated */ | |
/* one at a time. Further, the middle pixels are masked and */ | |
/* written four at a time. (In this mode, there are four pixels*/ | |
/* at each address, one per plane. To pick one of the four, or */ | |
/* any combination, just set the plane mask accordingly.) */ | |
/* Note that if the pixels are (in order) a,b,c,d, then the */ | |
/* individual masks would be 0001b, 0010b, 0100b, and 1000b. */ | |
/* */ | |
void scanline(int page, int x1, int x2, int y, int color) | |
{ char far *addr; | |
int plane,i,i2; | |
char masks[]={1,3,7,15,2,6,14,14,4,12,12,12,8,8,8,8}; | |
addr = (char far*) (0xA0000000+0x8000000*page); | |
addr+=320/4*y+x1/4; /* order matters! y*320/4 will wrap when y*320 */ | |
/* overflows the word length! */ | |
outportb(0x3C4, 2); /* point Sequence Controller to Map Mask reg. */ | |
/* first four pixels */ | |
i2=x2-x1; /* figure number of pixels after first */ | |
if (x2-x1>3) i2=3; /* but limit to first 4 pixels */ | |
plane=masks[(x1%4)*4+i2]; /* table is (x,y): x=start pix, y=length */ | |
outportb(0x3C5,plane); /* set the planes */ | |
*(addr++)=(char) color; /* draw! (then increment mem. pointer.) */ | |
/* middle four-byte groups */ | |
outportb(0x3C5,0xf); /* set all four planes */ | |
if ((x2-x1)/4>1) /* if there are middle 4 byte groups... */ | |
for (i=x1/4+1; i<x2/4; i++) /* draw all of 'em */ | |
*(addr++)=(char) color; | |
/* do last four pixels */ | |
if (x1/4 != x2/4) /* if there is a last 4 byte group... */ | |
{ plane=masks[x2%4]; /* obviously it starts at pixel 0... */ | |
outportb(0x3C5,plane); | |
*(addr++)=(char) color; | |
} | |
} | |
void switchModes(int mode) /* set mode including extended mode 13x */ | |
{ unsigned int i, far *addr; | |
union REGS regs; | |
regs.x.ax = mode; /* normal mode set for all modes */ | |
int86(0x10, ®s, ®s); | |
if (mode==0x13) /* modify mode 13 to get 320x400 */ | |
{ outport(0x3C4, 0x0604); /* Seq. Cont. turn off Chain 4 and odd/even */ | |
outport(0x3CE, 0x4005); /* Gr. Cont.: turn off odd/even */ | |
outport(0x3CE, 0x0106); /* turn off chain */ | |
outport(0x3C4, 0x0F02); /* enable all planes */ | |
addr = (unsigned int far*) 0xA0000000; /* points to words so */ | |
for (i=0; i < 0x8000; i++) *addr++ = 0; /* erases both pages... */ | |
outport(0x3D4, 0x0009); /* CRTC: set max. scan line to 0 */ | |
outport(0x3D4, 0x2014); /* set normal word addressing */ | |
outport(0x3D4, 0xE317); /* turn on byte mode */ | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment