Graphics Bitmaps Drawing characters glyphs and multicolor patterns

advertisement
Graphics Bitmaps
Drawing characters glyphs and
multicolor patterns
Limitations of BIOS routines
• Last time we used a ROM-BIOS routine to
draw a text message on a graphics screen
(i.e., the so-called ‘write_string’ service)
• But some limitations were apparent:
– String-location had to conform to a cell-grid
– Background color pattern was obliterated
• We can overcome both these limitations if
we draw the character-glyphs ourselves
Built-in character bitmaps
• The ROM-BIOS has full sets of bitmaps for
the images of all the ASCII characters in
several sizes (e.g., 8x8, 8x14 and 8x16)
Example: An 8-by-8 glyph for the letter ‘H’
Layout of 8x16 glyph-table
• The Glyph-Table is an array of bit-images
• Each bit-image is 16-bytes in length
• Each ascii-code serves as array-index
0x40
0x41
0x42
0x43
0x44
0x45
0x46
‘@’
‘A’
‘B’
‘C’
‘D’
‘E’
‘F’
etc
The 8086 physical memory
The VGA firmware
Character-Glyph
tables are located
in this region
Boot ROM 0xF0000
Reserved for
add-ins
Video ROM 0xC0000
VRAM
0xA0000
EBDA
1-MB
A built-in BIOS
function will
report each of
the glyph-table
start-locations
RAM
BIOS DATA
VECTORS
0x00000
Finding the ROM fonts
• Standard BIOS service locates ROM fonts
• Designed to execute in 8086 real-mode
• Normal service-call protocol is followed:
– Parameters are placed in CPU registers
– Software interrupt instruction is executed
– ROM-BIOS code performs desired service
– Parameters may be returned in registers
Example
# AT&T assembly language syntax
mov
$0x11, %ah # char. gen. services
mov
$0x30, %al # get font information
mov
$6, %bh
# 8x16 font address
int
$0x10
# request BIOS service
# the font address is returned in ES:BP
# (and count of scanlines should be in CX)
Invoking BIOS from Linux
• Include our “int86.h” header-file
• Define ‘struct vm86plus_struct’ object: vm
• Initialize necessary register-fields of ‘vm’
– vm.regs.eax = 0x1130;
– vm.regs.ebx = 0x0600;
• Call our function: int86( 0x10, vm );
• Retrieve the returned parameters from vm
– e.g., from ‘vm.regs.es’ and ‘vm.regs.ebp’
Drawing a character (in mode 18)
•
•
•
•
•
•
Must enable I/O and 1-MB memory-map
Virtual address of VRAM is 0x000A0000
Use any ascii-code as a glyph-table index
Use x,y coordinates for character location
Specify the character’s ‘foreground color’
Thus your function-call could look like:
draw_char( x, y, color, ascii );
Using VGA Write Mode 3
• To preserve the background pattern when
a character-glyph is drawn, you can use a
‘Masked Write’ operation (‘Write Mode 3’)
• To position the character at an arbitrary
horizontal pixel position, use Data-Rotate
• The foreground color goes in ‘Set/Reset’
• The Bit Mask register prevents unwanted
pixels from being drawn when rotation
Illustration
Adjacent bytes on the screen
Character-glyph
is right-rotated
Afterward this
rotated glyph
gets ‘masked’
Left-hand
Bit Mask
Right-hand
Bit Mask
Implementation details
void draw_char( int x, int y, int fg, int ascii )
{
int which = y * hres + x;
int where = which / 8;
int shift = which % 8;
int left_mask = 0xFF >> shift;
int right_mask = ~(left_mask);
char *glyph = (char*)fontbase + 16*ascii;
Draw_char() (continued)
outw( 0x0305, GCPORT ); // use Mode 3
outw( color<<8, GCPORT ); // Set/Reset
// first-pass draws glyph’s left portion
outw( (left_mask<<8) | 8, GCPORT );
for (int row = 0; row < 16; row++) {
char temp = vram[ where + row*80 ];
vram[ where + row*80 ] = glyph[ row ];
}
Draw_char() (concluded)
if ( shift == 0 ) return; // we can do an early exit
// else second-pass draws glyph’s right portion
++where;
// location of the adjacent byte
outw( (right_mask<<8) | 8, GCPORT ); // Bit Mask
for (int row = 0; row < 16; row++) {
char temp = vram[ where + row*80 ];
vram[ where + row*80 ] = glyph[ row ];
}
}
Our ‘drawtext.cpp’ demo
• We used an 8-by-8 bitmap to generate the
patterned background for drawing text on
Background color
0001 (binary)
Foreground color
1001 (binary)
0x00
0x00
0x33
0x33
0x00
0x00
0x33
0x33
How ‘Write Mode 0’ works
Byte from pattern-glyph
ENABLE
SET/RESET
0 0 1 1 0 0 1 1
Data from CPU
SET/RESET
0
x
0 0 1 1 0 0 1 1
Latch plane 3
1
0
0 0 0 0 0 0 0 0
Latch plane 2
1
0
0 0 0 0 0 0 0 0
Latch plane 1
1
1
1 1 1 1 1 1 1 1
Latch plane 0
VRAM byte
Screen Pixel (planar)
Algorithm to ‘tile’ screen-area
// Use Write Mode 0 (“Direct Write”)
// Data-Rotate = 0, Function-Select is ‘copy’
// Bit Mask is 0xFF (e.g., all pixels writable)
// Enable Set/Reset is 0x7, Set/Reset is 0x1
// pattern-glyph described by array of 8-bytes
for (y = ymin; y < ymax; y++)
for (x = xmin; x < xmax; x++)
vram[ y * 80 + x ] = glyph[ y % 8 ];
Designing bitmap ‘patterns’
• You can create interesting backgrounds
• Fill screen regions with a copied pattern
0xFF
0x80
0x80
0x80
0xFF
0x08
0x08
0x08
foreground
color
background
color
Algorithm for ‘tiling’ (mode 19)
unsigned char pat[ 8 ];
# 8x8 2-color bitmap
unsigned char *vram = 0x000A0000, color;
for (int y = 0; y < vres; v++)
for (int x = 0; x < hres; x++)
{
int
r = y % 8, k = x % 8;
color = ( pat[ r ] & (0x80>>k) ) ? fg : bg;
vram[ y*hres + x ] = color;
}
In-class exercise
•
•
•
•
Take a look at our ‘brickpat.cpp’ demo
It tiles the screen with a brick-wall pattern
But it executes in mode 19 (256-colors)
Can you revise this demo so that it will
work in a ‘planar’ mode (i.e., 16-colors)?
• Hint: Apply the principles of Write Mode 0
in a manner similar to ‘drawtext.cpp’ demo
• Can you write text against your brick-wall?
Download