Mode 13 Text Output?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Mode 13 Text Output?

Post 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?
User avatar
~
Member
Member
Posts: 1228
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Post 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?
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post 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 :D.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post 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 8)" loop for fun).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post 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)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
xsix
Member
Member
Posts: 59
Joined: Tue Oct 24, 2006 10:52 am

Post 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 :P. 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
Post Reply