Page 1 of 3
Problem setting vesa text mode
Posted: Sun Mar 23, 2008 11:11 pm
by gzaloprgm
Hi, I'm having a problem with setting a vesa mode on my 16-bit bootloader.
My code is the following:
It should switch to 80*60 mode but it doesn't do anything. I tried with bochs, qemu and virtual box.
Can anyone tell me what am I doing wrong?
Thanks,
Gonzalo
Posted: Mon Mar 24, 2008 1:41 am
by zaleschiemilgabriel
I think you got the mode number wrong.
In standard VESA resolutions, mode 108h is graph 1280x1024 256 colors and mode 109h is text 80x60. ;)
However, with VESA/VBE 2.0 and above you should not count on it being available. You should always check the video modes supported using tha appropriate function.
Note: Newer video boards don't support any VESA text modes (that might also be your case). You could always use VGA mode 80x50, though. It's guaranteed to work.
Cheers,
Gabriel
Posted: Mon Mar 24, 2008 11:29 am
by gzaloprgm
Thanks for answering my question.
So I guess if I wanna make a big console I'll have to switch to a vesa graphic mode and write to the screen with a bitmap font.
Cheers,
Gonzalo
Posted: Mon Mar 24, 2008 4:25 pm
by lukem95
Thats what i do, i have a shell in 1024x768x32bpp
Posted: Mon Mar 24, 2008 8:46 pm
by Philip
it's terrible to make a bitmap font yourself, quite a long tiring job
Posted: Mon Mar 24, 2008 10:24 pm
by gzaloprgm
Not necessarily.
You can make a simple bitmap font in less than an hour, but if you want a good font you'll obviously have to spend more time on it.
Cheers,
Gonzalo
Posted: Tue Mar 25, 2008 4:32 am
by jal
gzaloprgm wrote:So I guess if I wanna make a big console I'll have to switch to a vesa graphic mode and write to the screen with a bitmap font.
Not necessarily. Standard VGA supports up to 90x60. You can set this mode by setting a number of VGA registers. It works on real hardware and Bochs, although I think VMWare doesn't like it. Haven't tried it on Qemu yet. Next, you'll have to set an 8x8 font.
The attachment has some code to achieve this. I don't have time to make dedicated routines, but it's somewhere near the bottom. Note that I took the font data (font.cpp) from DOSbox, which is GPLed, but no doubt they just dumped it from whatever video card they used, so I doubt the GPL really holds on that one.
If I have time, I'll maybe write a Wiki entry about setting the 90x60, if anyone would like.
JAL
Posted: Tue Mar 25, 2008 8:58 am
by lukem95
I think it would be beneficial if it was contributed to the wiki, chances are somebody will find it useful, and additional information is always useful
Posted: Tue Mar 25, 2008 2:32 pm
by gzaloprgm
Lots of Thanks Jal!!!
With this code the 90*60 mode worked perfectly.
Code: Select all
unsigned int Regs[] = {0x6900, 0x5901, 0x5a02, 0x8c03, 0x5e04, 0x8a05, 0x0b06, 0x3e07, 0x4709, 0xea10, 0x8c11, 0xdf12, 0x2d13, 0xe715, 0x0416};
outportw(0x3c4, 0x100);
outportb(0x3c2, 0xe7);
outportw(0x3c4, 0x0300);
outportw(0x3c4, 0x0000);
outportw(0x3c4, 0x0101);
outportw(0x3c4, 0x0300);
outportw(0x3d4, 0x0e11);
int i;
for ( i = 0; i < 15; i++){
outportw(0x3d4, Regs[i]);
}
inportb(0x3da);
outportb(0x3c0, 0x33);
outportb(0x3c0, 0x00);
I dont need to set a font because in my bootloader I set 8x8 font and 80*50 mode.
jal wrote:It works on real hardware and Bochs, although I think VMWare doesn't like it. Haven't tried it on Qemu yet.
In my case it worked in Qemu, Bochs, VirtualBox and real Hardware
Cheers,
Gonzalo
Posted: Wed Mar 26, 2008 2:12 am
by jal
lukem95 wrote:I think it would be beneficial if it was contributed to the wiki, chances are somebody will find it useful, and additional information is always useful :)
Yeah, I'll see if I can find some time this week. Must also try to explain, that array with port values is nice, but one perhaps likes to know what it does :). Time to get Ferraro out...
JAL
Posted: Wed Mar 26, 2008 2:14 am
by jal
gzaloprgm wrote:With this code the 90*60 mode worked perfectly.
Glad to hear it!
I dont need to set a font because in my bootloader I set 8x8 font and 80*50 mode.
You're right, it's not needed then. I use Grub, so I must set it in protected mode the hard way.
JAL
Posted: Wed Mar 26, 2008 2:14 am
by trolly
I dont need to set a font because in my bootloader I set 8x8 font and 80*50 mode.
how did it set the 8x8 font?
Posted: Wed Mar 26, 2008 3:29 am
by Ready4Dis
gzaloprgm wrote:Lots of Thanks Jal!!!
With this code the 90*60 mode worked perfectly.
Code: Select all
unsigned int Regs[] = {0x6900, 0x5901, 0x5a02, 0x8c03, 0x5e04, 0x8a05, 0x0b06, 0x3e07, 0x4709, 0xea10, 0x8c11, 0xdf12, 0x2d13, 0xe715, 0x0416};
outportw(0x3c4, 0x100);
outportb(0x3c2, 0xe7);
outportw(0x3c4, 0x0300);
outportw(0x3c4, 0x0000);
outportw(0x3c4, 0x0101);
outportw(0x3c4, 0x0300);
outportw(0x3d4, 0x0e11);
int i;
for ( i = 0; i < 15; i++){
outportw(0x3d4, Regs[i]);
}
inportb(0x3da);
outportb(0x3c0, 0x33);
outportb(0x3c0, 0x00);
I dont need to set a font because in my bootloader I set 8x8 font and 80*50 mode.
jal wrote:It works on real hardware and Bochs, although I think VMWare doesn't like it. Haven't tried it on Qemu yet.
In my case it worked in Qemu, Bochs, VirtualBox and real Hardware
Cheers,
Gonzalo
I just use mode 0x1112, 80x50, it's much simpler to set (just an interrupt call), so it saves me space in my bootloader
.
mov ax, 0x1112
xor bx, bx
int 0x10
I also get rid of the cursor cause I don't like it, but that's another story
mov word [0x60], 0x07 ;Just incase you wanted to know how
I do this before entering pmode in my bootloader, so any information displayed from then forward is not lost (until I either clear the screen manually, scroll the screen with to much data, or switch modes).
Posted: Wed Mar 26, 2008 4:21 am
by Stevo14
jal wrote:Must also try to explain, that array with port values is nice, but one perhaps likes to know what it does
. Time to get Ferraro out...
Already done.
Here is the code with the values moved out of the array. IMHO it is easer to read and easier to use as a learning tool.
EDIT: Updated code
Code: Select all
void set_small_font()
{
int line_height = 8;//8 pixels high characters
outportb(SEQ_ADDR, SEQ_I_MAPMASK);
unsigned char org_mapmask = inportb(SEQ_DATA);
outportb(SEQ_DATA, 0x04); //(0100) select plane 2 (the font plane)
outportb(SEQ_ADDR, SEQ_I_MEMMODE);
unsigned char org_memmode = inportb(SEQ_DATA);
outportb(SEQ_DATA , 0x06);
outportb(SEQ_ADDR, SEQ_I_CHARMAP);
outportb(SEQ_DATA, 0x00); //(000000) font a and b are mapped to zero (the first font)
outportb(GFX_ADDR, GFX_I_MISC);
unsigned char org_gfx = inportb(GFX_DATA);
outportb(GFX_ADDR, GFX_I_MISC);
outportb(GFX_DATA, 0x00); //(0000) disable odd/even
unsigned char *pVidMem = (unsigned char*)0xA0000;
int i,j = 0;
for (i = 0; i < 256; i++)
{
for (j = 0; j < line_height; j++)
{
*(pVidMem + j) = 0x00;//clear it first
*(pVidMem + j) = smallfont[i*8+j];//then set the value
}
pVidMem += 32;
}
outportb(SEQ_ADDR, SEQ_I_MEMMODE);
outportb(SEQ_DATA , org_memmode);
outportb(SEQ_ADDR, SEQ_I_MAPMASK);
outportb(SEQ_DATA , org_mapmask);
outportb(GFX_ADDR, GFX_I_MISC); //restore the old gfx misc settings
outportb(GFX_DATA, org_gfx);
outportb(GFX_ADDR, GFX_I_MODE);
outportb(GFX_DATA, 0x10);
outportb(GFX_ADDR, GFX_I_BITMASK);
outportb(GFX_DATA, 0xFF);
}
void set90x60()
{
int i = 0;
set_small_font();
outportb(SEQ_ADDR, SEQ_I_RESET);//asynchronously clear and halt.
outportb(SEQ_DATA, 0x01);
outportb(VGA_MISC_W, 0xE7);//set part of the clock data through the misc regester
outportb(SEQ_ADDR, SEQ_I_RESET);//continue operation
outportb(SEQ_DATA, 0x03);
outportb(SEQ_ADDR, SEQ_I_RESET);//synchronously clear and halt
outportb(SEQ_DATA, 0x02);
outportb(SEQ_ADDR, SEQ_I_CLOCK);
outportb(SEQ_DATA, 0x01);//(8 dot wide characters)
outportb(SEQ_ADDR, SEQ_I_RESET);//continue operation
outportb(SEQ_DATA, 0x03);
outportb(CRT_ADDR, CRT_I_END_V_RET);
outportb(CRT_DATA, 0x0E);
outportb(CRT_ADDR, CRT_I_H_TOTAL);
outportb(CRT_DATA, 0x6B);
outportb(CRT_ADDR, CRT_I_END_H_DIS);
outportb(CRT_DATA, 0x59);//(89) the number of characters wide - 1
outportb(CRT_ADDR, CRT_I_START_H_BLANK);
outportb(CRT_DATA, 0x5A);
outportb(CRT_ADDR, CRT_I_END_H_BALNK);
outportb(CRT_DATA, 0x82);
outportb(CRT_ADDR, CRT_I_START_H_RET);
outportb(CRT_DATA, 0x60);
outportb(CRT_ADDR, CRT_I_END_H_RET);
outportb(CRT_DATA, 0x8D);
outportb(CRT_ADDR, CRT_I_V_TOTAL);
outportb(CRT_DATA, 0x0B);
outportb(CRT_ADDR, CRT_I_OVERFLOW);
outportb(CRT_DATA, 0x3E);
outportb(CRT_ADDR, CRT_I_PRE_ROW_SCN);
outportb(CRT_DATA, 0x00);
outportb(CRT_ADDR, CRT_I_MAX_SCN_LINE);
outportb(CRT_DATA, 0x47);
outportb(CRT_ADDR, CRT_I_START_V_RET);
outportb(CRT_DATA, 0xEA);
outportb(CRT_ADDR, CRT_I_END_V_RET);
outportb(CRT_DATA, 0x0C);
outportb(CRT_ADDR, CRT_I_END_V_DIS);
outportb(CRT_DATA, 0xDF);
outportb(CRT_ADDR, CRT_I_OFFSET);
outportb(CRT_DATA, 0x2D);
outportb(CRT_ADDR, CRT_I_UND_LOC);
outportb(CRT_DATA, 0x08);
outportb(CRT_ADDR, CRT_I_START_V_BLANK);
outportb(CRT_DATA, 0xE8);
outportb(CRT_ADDR, CRT_I_END_V_BLANK);
outportb(CRT_DATA, 0x05);
outportb(CRT_ADDR, CRT_I_MODE);
outportb(CRT_DATA, 0xA3);
outportb(CRT_ADDR, CRT_I_LINE_CMP);
outportb(CRT_DATA, 0xFF);
width = 90;
height = 60;
}
Some of the comments may be wrong. Especially the part near the beginning with all the set/reset stuff on the sequencer.
EDIT: Comments are now fine.
And here is the #define section
Code: Select all
#define GFX_ADDR 0x3CE
#define GFX_DATA 0x3CF
#define GFX_I_RESET 0x00
#define GFX_I_ENABLE 0x01
#define GFX_I_COLORCMP 0x02
#define GFX_I_ROTATE 0x03
#define GFX_I_READMAP 0x04
#define GFX_I_MODE 0x05
#define GFX_I_MISC 0x06
#define GFX_I_CNOCARE 0x07
#define GFX_I_BITMASK 0x08
#define SEQ_ADDR 0x3C4
#define SEQ_DATA 0x3C5
#define SEQ_I_RESET 0x00
#define SEQ_I_CLOCK 0x01
#define SEQ_I_MAPMASK 0x02
#define SEQ_I_CHARMAP 0x03
#define SEQ_I_MEMMODE 0x04
#define ATR_ADDR_DATA 0x3C0
#define ATR_DATA_READ 0x3C1
#define CRT_ADDR 0x3D4
#define CRT_DATA 0x3D5
#define CRT_I_H_TOTAL 0x00
#define CRT_I_END_H_DIS 0x01
#define CRT_I_START_H_BLANK 0x02
#define CRT_I_END_H_BALNK 0x03
#define CRT_I_START_H_RET 0x04
#define CRT_I_END_H_RET 0x05
#define CRT_I_V_TOTAL 0x06
#define CRT_I_OVERFLOW 0x07
#define CRT_I_PRE_ROW_SCN 0x08
#define CRT_I_MAX_SCN_LINE 0x09
#define CRT_I_START_CUR 0x0A
#define CRT_I_END_CUR 0x0B
#define CRT_I_START_ADDR_H 0x0C
#define CRT_I_START_ADDR_L 0x0D
#define CRT_I_CUR_LOC_H 0x0E
#define CRT_I_CUR_LOC_L 0x0F
#define CRT_I_START_V_RET 0x10
#define CRT_I_END_V_RET 0x11
#define CRT_I_END_V_DIS 0x12
#define CRT_I_OFFSET 0x13
#define CRT_I_UND_LOC 0x14
#define CRT_I_START_V_BLANK 0x15
#define CRT_I_END_V_BLANK 0x16
#define CRT_I_MODE 0x17
#define CRT_I_LINE_CMP 0x18
#define DAC_ADDR_W 0x3C8
#define DAC_ADDR_R 0x3C7
#define DAC_DATA 0x3C9
#define DAC_STATE 0x3C7
#define VGA_MISC_W 0x3C2
#define VGA_MISC_R 0x3CC
#define VGA_FEATURE_W 0x3DA
#define VGA_FEATURE_R 0x3CA
#define VGA_STATUS_0 0x3C2
#define VGA_STATUS_1 0x3DA
Posted: Wed Mar 26, 2008 1:50 pm
by gzaloprgm
trolly wrote:
I dont need to set a font because in my bootloader I set 8x8 font and 80*50 mode.
how did it set the 8x8 font?
Code: Select all
mov ax,1112h ;Function 1112
xor bl,bl ;BL - 8x8 font
int 10h
mov ah,01 ;Function 1: change cursor
mov cx,0x06FF ;Starting sline: 6h, ending ffh
int 10h
Cheers,
Gonzalo