Page 1 of 1
Mode 13 Text Output?
Posted: Thu Mar 08, 2007 3:17 am
by pcmattman
I really need some help here, I need to know how to output text in mode 13 (ie. 320x200, 8 bits per pixel). I've tried just using a char array with the pixel info (ie. 0xF for on, 0x0 for off) but the characters come out really terribly. Is there any really simple algorithm or something I can follow?
Posted: Thu Mar 08, 2007 3:27 am
by ~
Maybe if you use bit array instead of byte array. It is more compact and you just need to rotate them to the left (ROL) if I am not wrong, otherwise the characters will be printed inverted like in a mirror. It could also be a little bit more slow. By testing, if the bit is 1, output a pixel; otherwise, if the bit is 0, either output a darker pixel (black) or nothing at all and just update the screen offset.
And I think that it should be 0xFF instead of 0x0F for outputting something like a white pixel.
Some snapshot and also what you had intended?
Posted: Thu Mar 08, 2007 4:02 am
by pcmattman
When I said 0x0 and 0xF I was meaning something more like OFF and ON... The other problem with the byte array is that it takes a long time to create each character because I need to test each one (with > 50 characters
). There has got to be a better way.
And about the 0x0F and 0xFF thing - I think I just figured out why the whites in my OS just don't look white
.
Posted: Thu Mar 08, 2007 5:45 am
by Brendan
Hi,
pcmattman wrote:The other problem with the byte array is that it takes a long time to create each character because I need to test each one (with > 50 characters
). There has got to be a better way.
The problem with the byte array is that for each character you end up with something like:
Code: Select all
for(y = 0 to 8) {
for(y = 0 to 8) {
if( !lucky ) causeBranchMispredictionAndPipelineFlush();
}
}
A better idea is to use a lookup table, where the byte of character data is used as the index into a 256 entry array, and where each entry in the array is an 8 byte pixel mask.
Code: Select all
lookupTable:
dd 0x00000000, 0x00000000 ;0x00
dd 0x00000000, 0x000000FF ;0x01
dd 0x00000000, 0x0000FF00 ;0x02
dd 0x00000000, 0x0000FFFF ;0x03
Code: Select all
void drawCharacter(unsigned char character, unsigned char colour, unsigned char *videoAddress) {
colourMask = colour * 0x01010101;
for(y = 0 to 8) {
charData = characterData[character][y];
data1 = lookupTable[charData].firstDword;
data2 = lookupTable[charData].secondDword;
invData1 = ~data1;
invData2 = ~data2;
*videoAddress = (data1 & colourMask) | (*videoAddress & invData1);
*(videoAddress+4) = (data2 & colourMask) | (*(videoAddress+4) & invData2);
videoAddress += bytes_per_screen_line;
}
}
The other thing is that you end up operating on up to 16 dwords rather than operating on 64 bytes. Using 64-bit registers (MMX or 64-bit code) you could make this more efficient by operating on 8 qwords instead (and then unroll the "for(y = 0 to
" loop for fun).
Cheers,
Brendan
Posted: Thu Mar 08, 2007 8:50 am
by Combuster
you can also try to hijack the vga font and use that. (this means copying it to memory)
Some sample code:
here (BASIC)
Posted: Thu Mar 08, 2007 9:47 am
by xsix
when i was creating my GUI, i just dumped out VGA fonts, they are located at erm... i dont remember the address but there are a bitmap of font(s) and you can just use it as i used it. to print a char it will not be slow
. i used 8x8 characters and everything was OKAY. just mov ah, 0x80 and let the AL will be the one line of 8x8 char's array, and just use TEST AL, AH JNZ draw_pixel and then SHR AH, 1 so another bit will be checked out next time