Skip to content

Instantly share code, notes, and snippets.

@skull-squadron
Created November 30, 2023 02:18
Show Gist options
  • Save skull-squadron/0cc4f0f346ac02c925924ea1b6615cdf to your computer and use it in GitHub Desktop.
Save skull-squadron/0cc4f0f346ac02c925924ea1b6615cdf to your computer and use it in GitHub Desktop.
Mode X 320x400 256 color VGA mode
/* */
/* 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, &regs, &regs);
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