As a little exercise I translated a small EMODE utlity from German
c't magazine. The listing you can see here:
http://tinyurl.com/meyq7yb
Unfortunately, my version doesn't work as expected; it seems to try to
change the text mode of VGA card, but reports Abnormal program
termination in the end. Maybe someone of you could suggest, what has
to be fixed? Here's my listing tried with Turbo C:
#include stdio.h
#include dos.h
#define VIDEO 0x10
int VGAvorhanden(void) {
union REGS regs;
regs.x.ax = 0x1a00; /* infobajt */
int86(VIDEO, regs, regs); /* VGA z monitorem VGA ? */
return (regs.h.al == 0x1a) ((regs.h.bl == 0x07) || (regs.h.bl == 0x08));
}
void VGAaus(void) {
__emit__ (0xfa);/* CLI - blokada przerwania */
outportb(0x3c4, 0); /* sequencer off */
outportb(0x3c5, 1);
outportb(0x3d4, 23); /* CRTC - reset */
outportb(0x3d5, inportb(0x3d5) 127);
outportb(0x3d4, 17); /* CRTC - register 0-7 freigeben */
outportb(0x3d5, inportb(0x3d5) 127);
}
void VGAein(void) {
outportb(0x3d4, 17); /* CRTC - register 0-7 sperren */
outportb(0x3d5, inportb(0x3d5) | 128);
outportb(0x3d4, 23); /* CRTC - reset freigeben */
outportb(0x3d5, inportb(0x3d5) | 128);
outportb(0x3c4, 0); /* Sequencer on */
outportb(0x3c5, 3);
__emit__ (0xfb); /* STI - zezwolenie na interrupt */
}
void VGA94spalten(void) {
unsigned char dummy;
outportb(0x3c2, (inportb(0x3cc) 0xf3) | 4); /* 720 PEL waehlen */
outportb(0x3c4, 1); /* 8-dot-mode anschalten */
outportb(0x3c5, inportb(0x3c5) | 1);
outportb(0x3d4, 0); /* Horizontal total-5 */
outportb(0x3d5, 108);
outportb(0x3d4, 1); /* Horizontal display enable end - 1 */
outportb(0x3d5, 93);
outportb(0x3d4, 2); /* Start horizontal blanking */
outportb(0x3d5, 94);
outportb(0x3d4, 3); /* End horizontal blanking */
outportb(0x3d5, 128 + 15);
outportb(0x3d4, 4); /* Start horizontal retrace */
outportb(0x3d5, 98);
outportb(0x3d4, 5); /* End horizontal retrace */
outportb(0x3d5, 128 + 14);
outportb(0x3d4, 19); /* Logical line width */
outportb(0x3d5, 94 / 2);
dummy = inportb(0x3da); /* Horizontal PEL Panning */
outportb(0x3c0, 19);
outportb(0x3c0, 0);
outportb(0x3c0, 32); /* Attribute controller */
outportb(0x3c0, 32); /* reaktivieren */
}
void VGA480rasterzeilen(void) {
outportb(0x3c2, inportb(0x3cc) | 192); /* Sync-polaritaet setzen */
outportb(0x3d4, 6); /* Vertical total */
outportb(0x3d5, 11);
outportb(0x3d4, 7); /* CRTC Overflow */
outportb(0x3d5, 62);
outportb(0x3d4, 9); /* Maximum scan line */
outportb(0x3d5, 79);
outportb(0x3d4, 16); /* Start vertical retrace */
outportb(0x3d5, 234);
outportb(0x3d4, 17); /* End vertical retrace */
outportb(0x3d5, 140);
outportb(0x3d4, 18); /* Vert. display enable end */
outportb(0x3d5, 223);
outportb(0x3d4, 21); /* Start vertical blanking */
outportb(0x3d5, 231);
outportb(0x3d4, 22); /* End vertical blanking */
outportb(0x3d5, 4);
}
void VGAzeichenhoehe(unsigned char size) {
pokeb(0, 0x485, size); /* mem[0:$485] := size; BIOS Informieren */
outportb(0x3d4, 9); /* Maximum scan line */
outportb(0x3d5, (inportb(0x3d5) 0xe0) + size - 1);
outportb(0x3d4, 10);
if (size = 12)
outportb(0x3d5, size - 2);
else
outportb(0x3d5, size - 3);
outportb(0x3d4, 11); /* Cursor End */
if (size = 12)
outportb(0x3d5, size - 1);
else
outportb(0x3d5, size - 2);
}
void VGAmodus(unsigned char zeilen, unsigned char spalten) {
union REGS regs;
/* 350 oder 400 zeilen waehlen, bei 480 zeilen vorerst nur 400 */
regs.h.ah = 0x12;
regs.h.bl = 0x30;
regs.h.al = (zeilen == 43) ? 1 : 2;
int86(VIDEO, regs, regs);
/* 40 oder 80 Spalten waehlen, bei 94 Spalten vorerst nur 80 */
regs.h.ah = 0;
regs.h.al = (spalten == 40) ? 1 : 3;
int86(VIDEO, regs, regs);
/* Passenden zeichensaetz in Video-Ram kopieren */
regs.h.ah = 0x11;
regs.h.bl = 0;
switch (zeilen) {
case 25: regs.h.al = 4; break; /* 16x8 Pixel */
case 30: regs.h.al = 4; break; /* 16x8 Pixel */
case 34: regs.h.al = 1; break; /* 14x8 Pixel */
default: regs.h.al = 2;/* 8x8 Pixel */
}
int86(VIDEO, regs, regs);
VGAaus(); /* Jetzt geht's an die register */
if (spalten == 94)
VGA94spalten();
if (zeilen == 30 || zeilen == 34 || zeilen == 60)
VGA480rasterzeilen();
switch (zeilen) {
case 25: VGAzeichenhoehe(16); break;
case 30: VGAzeichenhoehe(16); break;
case 34: VGAzeichenhoehe(14); break;
default: VGAzeichenhoehe(8);
}
VGAein(); /* Alles wieder normal */
/* BIOS ueber die Bildschirmgrosse informieren */
pokeb(0, 0x44a, (long int)spalten);
pokeb(0, 0x484, (long int)zeilen - 1);
}
void holeParameter(unsigned char *pzeilen, unsigned char *pspalten,
char *argv[]) {
int sp_allowed[] = {40, 80, 94, 0};
int ze_allowed[] = {25, 30, 34, 43, 50, 60, 0};
int *arrptr;
unsigned char tmp;
/* Zeilen und Spalten aus der Kommandozeile holen */
sscanf(argv[2], %u, tmp);
arrptr = sp_allowed;
while