#include /* memcpy(), memset() */ /* FILE, fopen(), fseek(), fwrite(), fputc(), fclose() */ #include /* struct REGPACK, intr(), MK_FP(), FP_SEG(), FP_OFF(), peekb(), poke() */ #include /* when VGA is in text mode, and characters are 9 pixels wide, characters 0xC0-0xDF in the character set will have their 8th (rightmost) pixel extended into the 9th pixel. This is for box- and line-drawing characters */ #define CG_BASE 0xD0 /********************************* TURBO C **********************************/ #if defined(__TURBOC__) #define R_AX r_ax #define R_BX r_bx #define R_CX r_cx #define R_DX r_dx #define R_BP r_bp #define R_ES r_es typedef struct REGPACK regs_t; /******************************** WATCOM C **********************************/ #elif defined(__WATCOMC__) #if defined(__386__) #error Sorry, this is a 16-bit program #endif #define peekb(S,O) *(unsigned char far *)MK_FP(S,O) #define poke(S,O,V) *(unsigned short far *)MK_FP(S,O)=(V) #define R_AX x.ax #define R_BX x.bx #define R_CX x.cx #define R_DX x.dx #define R_BP x.bp #define R_ES x.es typedef union REGPACK regs_t; #else #error Unsupported compiler #endif static char g_font[2048]; /* 256x8 */ /***************************************************************************** reprograms characters CG_BASE through CG_BASE+15 of g_font for use with chunky graphics *****************************************************************************/ static void reprogram_font(void) { static char my_font[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /**/ char far *src; regs_t regs; unsigned i; /* find 8x8 (#3) ROM font */ regs.R_AX = 0x1130; regs.R_BX = 0x0300; intr(0x10, ®s); src = MK_FP(regs.R_ES, regs.R_BP); /* copy font from ROM to RAM */ for(i = 0; i < sizeof(g_font); i++) { g_font[i] = *src; src++; } /* change 16 characters of font */ memcpy(g_font + CG_BASE * 8, my_font, sizeof(my_font)); /* set 80x50 text mode (8x8 ROM font) */ regs.R_AX = 0x1112; regs.R_BX = 0; intr(0x10, ®s); /* set the user-defined font */ regs.R_AX = 0x1100; regs.R_BX = 0x800; /* BH=8, BL="block to load in map 2" */ regs.R_CX = 256; /* chars */ regs.R_DX = 0; /* "character offset into map 2 block" */ regs.R_ES = FP_SEG(g_font); regs.R_BP = FP_OFF(g_font); intr(0x10, ®s); } /***************************************************************************** brings back fond memories of my old Color Computer ::sniff:: *****************************************************************************/ static void write_pixelt(unsigned x, unsigned y, unsigned c) { unsigned off, val; off = ((y / 2) * 80 + (x / 2)) * 2; /* Turbo C peekb() returns signed char, so you need the cast! */ val = (unsigned char)peekb(0xB800, off); if(val < CG_BASE || val > CG_BASE + 15) val = CG_BASE; if(y & 1) if(x & 1) val |= 0x08; else val |= 0x04; else if(x & 1) val |= 0x02; else val |= 0x01; c = (c & 0x0F) * 256; poke(0xB800, off, val | c); } /***************************************************************************** Win95 screen shot function doesn't notice that we changed the font, so it doesn't work. Here's a crappy function to make a 640x400x256 .BMP file of the screen contents. There are only 16 colors in text mode, but use a 256-color .BMP to simplify code here. *****************************************************************************/ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; static void dump(void) { static unsigned char pal[64] = { 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x00, 0xAA, 0xAA, 0x00, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00 }; /**/ struct { /* hdr1 (14 bytes) */ char magic[2]; /* "BM" */ uint32_t file_size; uint32_t unused0; uint32_t raster_offset; /* (14+40+pal_size) */ /* hdr2 (40 bytes) */ uint32_t hdr2_size; /* 40 bytes */ uint32_t wd; uint32_t ht; uint16_t planes; uint16_t depth; uint32_t compression; uint32_t unused1[5]; } hdr; unsigned y, x, row, col, i, c; unsigned pal_size = 1024; FILE *out; out = fopen("dump.bmp", "wb"); if(out == NULL) return; /* create header */ memset(&hdr, 0, sizeof(hdr)); hdr.magic[0] = 'B'; hdr.magic[1] = 'M'; hdr.file_size = sizeof(hdr) + pal_size + 640uL * 400; hdr.raster_offset = sizeof(hdr) + pal_size; hdr.hdr2_size = 40; hdr.wd = 640; hdr.ht = 400; hdr.planes = 1; hdr.depth = 8; /* write header */ fwrite(&hdr, 1, sizeof(hdr), out); /* write pallette */ fwrite(&pal, 1, sizeof(pal), out); /* entries 16-255 are bogus...good thing they're not used */ fseek(out, pal_size - sizeof(pal), SEEK_CUR); /* write raster it'll be upside-down, but that's easily fixed with Paint */ for(y = 0; y < 50; y++) for(row = 0; row < 8; row++) for(x = 0; x < 80; x++) { /* compute offset */ i = (y * 80 + x) * 2; /* read attribute byte (color) at offset mask off the Blink bit */ c = (unsigned char)peekb(0xB800, i + 1) & 0x7F; /* read char at offset */ i = (unsigned char)peekb(0xB800, i); /* index into font */ i = 8 * i + row; /* get character generator byte */ i = g_font[i]; /* dump 8 pixels */ for(col = 0x80; col != 0; col >>= 1) { if(i & col) /* foreground color */ fputc(c & 0x0F, out); else /* background color */ fputc(c / 16, out); } } fclose(out); } /***************************************************************************** *****************************************************************************/ int main(void) { unsigned y, i; /* 160x100 If you could get 80x60 text mode, that'd be 4:3 aspect ratio (square pixels) */ reprogram_font(); for(y = 0; y < 60; y++) { for(i = 0; i < 16; i++) write_pixelt(6 * i + y, y, i); } /* crappy screenshot */ dump(); return 0; }