Page 1 of 1
Change VGA Font Bitmap
Posted: Thu Sep 03, 2009 7:35 pm
by arabasso
Hello everyone.
I'm having trouble changing the font bitmap from VGA card. I am developing a 32-bit paging kernel for the x86 architecture. Following is the code:
Code: Select all
static void set_plane(unsigned p)
{
unsigned char pmask;
p &= 3;
pmask = 1 << p;
outportb(0x3CE, 4);
outportb(0x3CF, p);
outportb(0x3C4, 2);
outportb(0x3C5, pmask);
}
static void write_font(unsigned char *buf)
{
unsigned char seq2, seq4, gc4, gc5, gc6;
unsigned font_height, i, j;
unsigned char * ptr;
outportb(0x3C4, 2);
seq2 = inportb(0x3C5);
outportb(0x3C4, 4);
seq4 = inportb(0x3C5);
outportb(0x3C5, seq4 | 0x04);
outportb(0x3CE, 4);
gc4 = inportb(0x3CF);
outportb(0x3CE, 5);
gc5 = inportb(0x3CF);
outportb(0x3CF, gc5 & ~0x10);
outportb(0x3CE, 6);
gc6 = inportb(0x3CF);
outportb(0x3CF, gc6 & ~0x02);
set_plane(2);
font_height = 16;
ptr = (unsigned char *) 0xB8000;
for(i = 0; i < 256; i++)
{
for(j = 0; j < font_height; j++)
{
ptr[0x1000 + 32 * i + j] = buf[font_height * i + j];
}
}
outportb(0x3C4, 2);
outportb(0x3C5, seq2);
outportb(0x3C4, 4);
outportb(0x3C5, seq4);
outportb(0x3CE, 4);
outportb(0x3CF, gc4);
outportb(0x3CE, 5);
outportb(0x3CF, gc5);
outportb(0x3CE, 6);
outportb(0x3CF, gc6);
}
This code runs normally, but nothing happens. I even pulled the first character to finally added to the letters scrambled stayed, but when I write something on the screen nothing happens.
Does anyone know what could it be?
Re: Change VGA Font Bitmap
Posted: Fri Sep 04, 2009 3:53 am
by egos
Look at
New fonts.
Try
instead of
Re: Change VGA Font Bitmap
Posted: Fri Sep 04, 2009 8:27 am
by Creature
Are you sure that you've identity mapped whatever video memory address you're using? I know I forgot that when I tried VGA programming once, it took me weeks to find out that I hadn't identity mapped video memory, all my other code was perfectly fine. But usually the VGA memory addresses are all under 1 MB, which you should identity map anyways (I think), I had some special address above 1 MB which made it necessary to identity map it myself.
Re: Change VGA Font Bitmap
Posted: Sat Sep 05, 2009 1:44 am
by egos
Try
Code: Select all
ptr[32 * i + j] = buf[font_height * i + j];
instead of
Code: Select all
ptr[0x1000 + 32 * i + j] = buf[font_height * i + j];
Why you use the 0x1000 item? It's middle position for bitmap 0. In this case you would load only last 128 glyphs (for characters with codes 0x80-0xFF). Additionally, there's a probability that the frame address for fixing VRAM is other than 0xB8000. To force a setting this address set bits 2 and 3 of miscellaneous graphics register (graph[0x06]) to 11b.
Re: Change VGA Font Bitmap
Posted: Mon Sep 07, 2009 5:10 pm
by arabasso
Thanks for posts.
I managed to map a new VGA font bitmap with the following code:
Code: Select all
#define VGA_GFX_REG 0x3CE
#define VGA_SEQ_REG 0x3C4
#define VGA_CRT_REG 0x3D4
#define VGA_GFX_I_RESET 0x00
#define VGA_GFX_I_ENABLE 0x01
#define VGA_GFX_I_COLORCMP 0x02
#define VGA_GFX_I_ROTATE 0x03
#define VGA_GFX_I_READMAP 0x04
#define VGA_GFX_I_MODE 0x05
#define VGA_GFX_I_MISC 0x06
#define VGA_GFX_I_CNOCARE 0x07
#define VGA_GFX_I_BITMASK 0x08
#define VGA_SEQ_I_RESET 0x00
#define VGA_SEQ_I_CLOCK 0x01
#define VGA_SEQ_I_MAPMASK 0x02
#define VGA_SEQ_I_CHARMAP 0x03
#define VGA_SEQ_I_MEMMODE 0x04
unsigned char readRegVGA(unsigned short reg, unsigned char idx)
{
outb(reg, idx);
return inb(reg + 0x01);
}
void writeRegVGA(unsigned short reg, unsigned char idx, unsigned char val)
{
outb(reg, idx);
outb(reg + 1, val);
}
void setFontVGA(const unsigned char * buffer, int h)
{
unsigned char seq2, seq4, gfx6;
int i, j;
unsigned char * mem;
seq2 = readRegVGA(VGA_SEQ_REG, VGA_SEQ_I_MAPMASK);
writeRegVGA(VGA_SEQ_REG, VGA_SEQ_I_MAPMASK, 0x04);
seq4 = readRegVGA(VGA_SEQ_REG, VGA_SEQ_I_MEMMODE);
writeRegVGA(VGA_SEQ_REG, VGA_SEQ_I_MEMMODE, 0x06);
writeRegVGA(VGA_SEQ_REG, VGA_SEQ_I_CHARMAP, 0x00);
gfx6 = readRegVGA(VGA_GFX_REG, VGA_GFX_I_MISC);
writeRegVGA(VGA_SEQ_REG, VGA_GFX_I_MISC, 0x00);
mem = (unsigned char *) 0xB0000;
for (i = 0; i < 256; i++)
{
for (j = 0; j < h; j++)
mem[j] = buffer[h * i + j];
mem += 32;
}
writeRegVGA(VGA_GFX_REG, VGA_GFX_I_MISC, gfx6);
writeRegVGA(VGA_SEQ_REG, VGA_SEQ_I_MEMMODE, seq4);
writeRegVGA(VGA_SEQ_REG, VGA_SEQ_I_MAPMASK, seq2);
writeRegVGA(VGA_GFX_REG, VGA_GFX_I_MODE, 0x10);
writeRegVGA(VGA_GFX_REG, VGA_GFX_I_BITMASK, 0xFF);
}
The strange thing is that both the address 0xB0000 and 0xA0000 remaps the font bitmap. Another thing about this code: it works well on bochs, qemu and the real PC, but not in wmware. I've seen in many places there are a range of problems in vmware VGA. Does anyone know a fix for the problem of VGA in vmware? Or just right is to a specific driver for it?
Re: Change VGA Font Bitmap
Posted: Mon Sep 07, 2009 11:51 pm
by egos
It is not problem of VMWare. You would use VGA specification and its agreements. And exactly when you specify the address 0xA0000 for fixing VRAM by setting graph[0x06] to zero, you would use this one.
Re: Change VGA Font Bitmap
Posted: Tue Sep 08, 2009 5:26 am
by arabasso
Why?
I did not understand what you mean about the VGA vmware. I assume that the real PC and other emulators everything is working OK, then the problem is with vmware. Or not?
I'm using the 0xA0000 base address for setting VGA font, but vmware does not work in any way.
if you know how to solve this, could you be more specific?
Re: Change VGA Font Bitmap
Posted: Tue Sep 08, 2009 6:24 am
by egos
arabasso wrote:I'm using the 0xA0000 base address for setting VGA font, but vmware does not work in any way.
I couldn't see this in your code.
arabasso wrote:if you know how to solve this, could you be more specific?
In last code fragment you missed one thing. I gave the link here.
I wrote:Font loading:
graph[0x05] = 0x00 (bit 4 = 0)
graph[0x06] = 0x0C (bit 1 = 0) ; 0 for 0xA0000
seq[0x02] = 0x04 (0100b)
seq[0x04] = 0x06/0x07 (bit 2 = 1)
Characters and attributes writing (normal mode):
graph[0x05] = 0x10 (bit 4 = 1)
graph[0x06] = 0x0E (bit 1 = 1) ; 2 for 0xA0000
seq[0x02] = 0x03 (0011b)
seq[0x04] = 0x02/0x03 (bit 2 = 0)