home *** CD-ROM | disk | FTP | other *** search
- // Listing 5. SCREEN.CPP
- // C++ screen driver program that uses inline assembly
-
- #pragma inline // Inform compiler that we're doing inline assembly
- #include <bios.h>
-
- class screen { // Define a screen object with assembly methods
- public:
- int wd, ht; // Screen width and height
- void far *vram; // Pointer to video ram
- screen(void);
- void print(int x, int y, char far *charstr, char attr);
- void hzfill(int x, int y, char fill, char attr, unsigned cnt);
- void vtfill(int x, int y, char fill, char attr, unsigned cnt);
- };
-
- screen::screen(void)
- // This constructor calls BIOS to get the current video mode,
- // ram pointer, display page, and screen width and height.
- {
- asm {
- mov ah, 0x0f // Fctn code to get video state
- int 0x10 // Get video state into al, bh
- mov si, word ptr this // Point to screen object data
- push ax // Save video mode
- mov ax, 0x1000 // Compute offset using page number
- mov bl, bh // Set BX = page number
- mov bh, 0
- mul bx // Multiply by page no. to get offset
- mov [si].vram, ax // Store offset in low word of vram
- pop ax // Restore video mode
- cmp al, 7 // Monochrome?
- jnz color
- mov [si].vram+2, 0xb000 // Use monochrome segment
- jmp short more
- }
- color:
- asm mov [si].vram+2, 0xb800 // Use color segment
- more:
- asm {
- mov ax, 0x0040 // Load ES:DI with 0x0040:0x004A
- mov es, ax // which has current screen width
- mov ax, 0x004a
- mov di, ax
- mov ax, es:[di] // Load AX with current screen width
- mov [si].wd, al // Store width in screen object
- mov ax, 0x0084 // Load ES:DI with 0x0040:0x0084
- mov di, ax // which has current screen height-1
- mov al, es:[di] // AL = current screen height-1
- inc al
- mov ah, 0 // AX = screen height
- mov [si].ht, ax // Store height in screen object
- }
- }
-
- void screen::print(int x, int y, char far *s, char attr)
- // Writes character string s with attribute attr at location (x,y)
- {
- asm {
- push ds // Save DS register!
- mov si, word ptr this // Point to screen object's data
- mov ax, [si].wd // Load AX with screen width
- mul word ptr y // Multiply by y
- add ax, word ptr x // Add x
- shl ax, 1 // Multiply by 2 to get offset
- les di, dword ptr [si].vram // Store video ram pointer in ES:DI
- add di, ax // Add in offset
- lds si, dword ptr s // String pointer to DS:SI
- mov ah, byte ptr attr // Load ah with attribute
- }
- cycle:
- asm lodsb // Load next char into al (ah has attr)
- asm cmp al, 0 // Terminate when null char reached
- asm jz quit
- asm stosw // Store char & attr, increment to next
- asm jmp short cycle // Around the loop
- quit:
- asm pop ds
- }
-
- void screen::hzfill(int x, int y, char fill, char attr, unsigned cnt)
- // Fills a row of width cnt with the character fill, and attribute
- // attr at the relative screen location (x,y)
- {
- asm {
- mov cx, word ptr cnt // Load CX with fill count
- jcxz quit // Quit if CX = 0
- mov si, word ptr this // Point to screen object's data
- mov ax, [si].wd // Load AX with screen width
- mul word ptr y // Multiply by y
- add ax, word ptr x // Add x
- shl ax, 1 // Multiply by two to get offset
- les di, dword ptr [si].vram // Store video ram pointer in ES:DI
- add di, ax // Add in offset
- mov al, byte ptr fill // Load AX with char & attr
- mov ah, byte ptr attr
- cld // Be sure to clear direction bit
- rep stosw // Store char & attr cnt times
- }
- quit: return;
- }
-
- void screen::vtfill(int x, int y, char fill, char attr, unsigned cnt)
- // Fills a column at location (x,y), using the fill character fill,
- // color attr, and making the fill cnt rows high
- {
- asm {
- mov cx, word ptr cnt // Load CX with fill count
- jcxz quit // Quit if cnt = 0
- mov si, word ptr this // Point to screen object's data
- mov ax, [si].wd // Load AX with screen width
- mul word ptr y // Multiply by y
- add ax, word ptr x // Add x
- shl ax, 1 // Multiply by 2 to get offset
- les di, dword ptr [si].vram // Store video pointer in ES:DI
- add di, ax // Add in offset
- mov al, byte ptr fill // Load AX with char/attribute
- mov ah, byte ptr attr
- mov bx, [si].wd // BX = (screen width-1) * 2
- dec bx // Which is offset to next row,
- shl bx, 1 // same column
- cld // Make sure direction bit cleared
- }
- cycle:
- asm {
- stosw // Store char & attr in video ram
- add di, bx // Skip down to next row
- loop cycle // Loop until CX = 0
- }
- quit: return;
- }
-
- main()
- {
- screen sc; // Declare and initialize screen object
- // Draw a black-on-cyan box around screen border
- sc.hzfill(1, 0, 196, 0x30, sc.wd-2);
- sc.hzfill(1, sc.ht-1, 196, 0x30, sc.wd-2);
- sc.vtfill(0, 1, 179, 0x30, sc.ht-1);
- sc.vtfill(sc.wd-1, 1, 179, 0x30, sc.ht-1);
- sc.hzfill(0, 0, 218, 0x30, 1);
- sc.hzfill(sc.wd-1, 0, 191, 0x30, 1);
- sc.hzfill(0, sc.ht-1, 192, 0x30, 1);
- sc.hzfill(sc.wd-1, sc.ht-1, 217, 0x30, 1);
- // Fill in interior
- for (int i=1; i<sc.ht-1; i++) sc.hzfill(1, i, ' ', 0x30, sc.wd-2);
- // Write a message in the middle of the screen, wait for key press
- sc.print(sc.wd/2-6, sc.ht/2, "PC Techniques", 0x30);
- bioskey(0);
- }