home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pctchnqs
/
1990
/
number6
/
screen.cpp
< prev
next >
Wrap
Text File
|
1990-12-11
|
6KB
|
151 lines
// 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);
}