//------------------------------------------------------------------- // newzero.cpp // // This program temporarily alters some register-values within // the VGA's Graphics Controller and Timer-Sequencer, in order // to gain access to the portion of Video Display Memory where // the VGA character-generator's glyph-tables reside while the // system is executing in text mode, so it can install there a // new image for the zero chartacter ('0') whose ascii-code is // equal to 0x30. Thus for proper operation this demo-program // must be executed from a text-mode console, rather than from // a window in the graphical desktop environment. Note that a // separate task must run to restore the normal-looking zero.) // // compile using: $ g++ newzero.cpp int86.cpp -o newzro // // Reference: Richard Wilton, "Programmer's Guide to PC Video // Systems (Second Edition)," Microsoft Press (1994), 294-299. // // programmer: ALLAN CRUSE // written on: 04 SEP 2003 // revised on: 07 SEP 2005 - replaced 'mmap()' by 'init8086()' //------------------------------------------------------------------- #include // for printf() #include // for outw() #include "int86.h" // for init8086(), int86() #define TSEQ_PORT 0x3C4 // for i/o to the VGA Timer-Sequencer #define GRAF_PORT 0x3CE // for i/o to the Graphics Controller #define VRAM_BASE 0x000A0000 // address of the VGA graphics memory unsigned char *vram = (unsigned char*)VRAM_BASE; struct vm86plus_struct vm; unsigned char newglyph[ 16 ] = { 0x00, // 00000000 0x00, // 00000000 0x7C, // 01111100 0x82, // 10000010 0x82, // 10000010 0x82, // 10000010 0x82, // 10000010 0x82, // 10000010 0x82, // 10000010 0x82, // 10000010 0x82, // 10000010 0x7C, // 01111100 0x00, // 00000000 0x00, // 00000000 0x00, // 00000000 0x00 // 00000000 }; int main( int argc, char **argv ) { // display some sample text that has a few zeros within it printf( "\e[H\e[J\n\n" ); // start with a clear screen printf( "\nOK, a few facts every computer student should know:\n" ); printf( "\nTest message #1: one kilobyte equals 1024 bytes" ); printf( "\nTest message #2: one megabyte equals 1024 kilobytes" ); printf( "\nTest message #3: one gigabyte equals 1024 megabytes" ); printf( "\nTest message #4: one terabyte equals 1024 gigabytes" ); printf( "\n\nNow, to see a new glyph for zero, press " ); getchar(); // now setup 1-MB memory-mapping and direct I/O privileges init8086(); // prologue (makes character ram accessible to the cpu) outw( 0x0100, TSEQ_PORT ); // enter synchronous reset outw( 0x0402, TSEQ_PORT ); // write only to map 2 outw( 0x0704, TSEQ_PORT ); // use sequential addressing outw( 0x0300, TSEQ_PORT ); // leave synchronous reset outw( 0x0204, GRAF_PORT ); // select map 2 for reads outw( 0x0005, GRAF_PORT ); // disable odd-even addressing outw( 0x0006, GRAF_PORT ); // map starts at 0xA000:0000 // load our new image for '0' into character generator ram int zlocn = 0x30 * 32; for (int i = 0; i < 16; i++) vram[ zlocn + i ] = newglyph[ i ]; // epilogue (makes character ram inaccessible to the cpu) outw( 0x0100, TSEQ_PORT ); // enter synchronous reset outw( 0x0302, TSEQ_PORT ); // write to maps 0 and 1 outw( 0x0304, TSEQ_PORT ); // use odd-even addressing outw( 0x0300, TSEQ_PORT ); // leave synchronous reset outw( 0x0004, GRAF_PORT ); // select map 0 for reads outw( 0x1005, GRAF_PORT ); // enable odd-even addressing outw( 0x0E06, GRAF_PORT ); // map starts at 0xB800:0000 }