#include <dpmi.h> __dpmi_regs regs; memset(®s, 0, sizeof regs); regs.x.ax = 0x13; /* 0x13 is the mode number */ __dpmi_int(0x10, ®s);Ok, you've got the mode. Now, how do we write to the frame buffer?
#include <sys/farptr.h> #include <go32.h> /* for _dos_ds */ _farpokeb(_dos_ds, 0xa0000, 1)
sets the pixel in the upper left hand corner of the screen to 1. It compiles to:
movl $0xa0000, %eax movw $_dos_ds, %fs movb $1, fs:(%eax)
as long as you have at least -O1 turned on. (That's kind of a mangled AT&T+TASM syntax.) You can do a _farsetsel(_dos_ds) once before your sequence of peeks and pokes, and it'll leave FS set, and you can then use the _farns* functions like so:
#include <sys/farptr.h> #include <go32.h> /* for _dos_ds */ _farsetsel(_dos_ds); _farnspokeb(0xa0000, 1); _farnspokeb(0xa0001, 2);
which will avoid loading FS every iteration.
#include <sys/nearptr.h> char *screen; if (__djgpp_nearptr_enable() == 0) return ERROR; /* could happen */ /* You must recalculate the screen pointer every time you enter this mode because __djgpp_conventional_base can change when you malloc/new and other misc stuff. */ screen = 0xa0000 + __djgpp_conventional_base; screen[0] = 1; screen[1] = 1; /* etc. */ __djgpp_nearptr_disable();
Each of those screen moves is one instruction, of course. And screen is a honest-to-god [19] pointer, that you can memcpy to and from, or whatever. (Hint: If the length of a memcpy is fixed, and -O1 and up is turned on, memcpy becomes an inline rep movsl (rep movsd in TASM notation).)
Extra Note: __djgpp_nearptr_enable() is SLOW. Call it at most once per frame, and preferably just once at startup. While you're still debugging, though, you might want to turn it off and on per memory access.
#include <sys/movedata.h>
void putpixel(int x, int y, int c) {
_dosmemputb(&c, 1, 0xa0000 + x + y * 320);
}
Cheesey putpixel via far pointers:
#include <sys/farptr.h>
#include <go32.h> /* for _dos_ds */
void putpixel(int x, int y, int c) {
_farpokeb(_dos_ds, 0xa0000 + x + y * 320, c)
}
Cheesey putpixel via near pointers:
#include <sys/nearptr.h>
void init_putpixel(void) {
__djgpp_nearptr_enable();
}
void putpixel(int x, int y, int c) {
char *screen = 0xa0000 + __djgpp_conventional_base;
*(screen + x + y * 320) = c;
}
Example code:
#include <pc.h>
char my_palette[768]; /* 256 rgb triplets */
void get_palette(char *pal) {
int i;
/* get the palette */
outportb(0x3c7, 0); /* want to read */
for (i = 0; i < 768; i++)
pal[i] = inportb(0x3c9);
}
void set_palette(char *pal) {
int i;
/* set palette */
outportb(0x3c8, 0); /* want to write */
for (i = 0; i < 768; i++)
outportb(0x3c9, pal[i]);
}
Viola!