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:

Code: Select all

mov ax, 4F02h
mov bx,108h
int 10h
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 :D

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 :D

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