Graphics mode?

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

Graphics mode?

Post by pcmattman »

I've run into a problem when I try to implement my GUI - I can't set the graphics mode because I can't use BIOS interrupts from PMode. Is there any way of getting into the graphics mode from PMode? (I'm trying to do the tutorial for GUI development over at osdever.net).
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 »

several options:
- use v8086 mode
- exit pmode, call the interrupt, then re-enter pmode
- write your own drivers
- build an emulator to execute bios code
"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 ]
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

Here are some examples of the method Combuster suggested
This is a demo of go to and from real mode for mode switching (need vesa2)
http://www.dex4u.com/tuts/DemoVesa.zip

Here are examples of mode switching from pmode
http://bos.asmhackers.net/docs/vga_without_bios/
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 »

Sounds good, thankyou for your quick reply!
digo_rp
Member
Member
Posts: 233
Joined: Sun Jun 05, 2005 11:00 pm

Post by digo_rp »

to setup a v86 task is so easy,
you just set a protected mode task "32bits one" and you put 4 v86 registers like that:

process->kstack = (dword)&process->pl0_stacK+stack_size;
p = (dword)0x1fff8;
*--p = r->gs; /* v86_gs */
*--p = r->fs; /* v86_fs */
*--p = r->ds; /* v86_ds */
*--p = r->es; /* v86_es */
*--p = r->cs; /* v86_ss */
*--p = 0xfff8; /* v86_esp */
*--p = 0x20202L; /* eflags */
*--p = r->cs; /* v86_cs */
*--p = r->eip; /* v86_eip */
*--p = r->eax; /* eax */
*--p = r->ecx; /* ecx */
*--p = r->edx; /* edx */
*--p = r->ebx; /* ebx */
*--p = 0; /* nullesp*/
*--p = r->ebp; /* ebp */
*--p = r->esi; /* esi */
*--p = r->edi; /* edi */
*--p = 0x10; /* PMode_gs */
*--p = 0x10; /* PMode_fs */
*--p = 0x10; /* PMode_es */
*--p = 0x10; /* PMode_ds */
be carefull, remember that realmode access only 1MB from your memory.
so that v86 task should be below 1MB Mark.

I use the segment 0x1000

in case you want, I can send to you my sources, then you can take anything you want and change modify, or to learn.

I´ll be very glad to send to evebody.

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

Thanks, I can get into the video mode now...

The problem is, the following does not work:

Code: Select all

#include "mattise.h"

// gui code...

unsigned char* VGA = (unsigned char*) 0x000A0000;
unsigned char *dbl_buffer;
mBlock dbl_buffer_info;

typedef struct tagBITMAP              /* the structure for a bitmap. */
{
	unsigned int width;
	unsigned int height;
	unsigned char *data;
} BITMAP;

typedef struct tagRECT
{
	long x1;
	long y1;
	long x2;
	long y2;
} RECT;

void init_dbl_buffer(void)
{
	dbl_buffer = (unsigned char *) malloc_count( &dbl_buffer_info, 64 );
	// special - make it red if there aren't enough blocks
	if( dbl_buffer_info.count < 64 )
	{
		int i;
		for( i = 0; i < 64000; i++ )
			*VGA++ = 0x1;
	}
	if( dbl_buffer == (unsigned char*) NULL )
	{
		int i;
		for( i = 0; i < 64000; i++ )
			*VGA++ = 0x4;
		kputs("Not enough memory for double buffer.\n");
		getch();
	}
}

void update_screen(void)
{
	#ifdef VERTICAL_RETRACE
		while ((inportb(0x3DA) & 0x08));
		while (!(inportb(0x3DA) & 0x08));
	#endif
	int i;
	for( i = 0; i < (SCREEN_WIDTH * SCREEN_HEIGHT); i++ )
		VGA[i] = dbl_buffer[i];
//	memcpy( VGA, dbl_buffer, (unsigned int)(SCREEN_WIDTH * SCREEN_HEIGHT) );
}

void setpixel (BITMAP *bmp, int x, int y, unsigned char color)
{
	bmp->data[ ( y * bmp->width ) + x ] = color;
}

/* Draws a filled in rectangle IN A BITMAP. To fill a full bitmap call as
drawrect (&bmp, 0, 0, bmp.width, bmp.height, color); */
void drawrect(BITMAP *bmp, unsigned short x, unsigned short y,
                     unsigned short x2, unsigned short y2,
                     unsigned char color)
{
	unsigned short tx, ty;
	for (ty = y; ty < y2; ty++)
		for (tx = x; tx < x2; tx++)
			setpixel( bmp, tx, ty, color );
}

void draw_bitmap_old(BITMAP *bmp, int x, int y)
{
	int j;
	unsigned int screen_offset = (y << 8) + (y << 6) + x;
	unsigned int bitmap_offset = 0;

	for(j = 0; j < bmp->height; j++)
    	{
		memcpy( &dbl_buffer[screen_offset], &bmp->data[bitmap_offset], bmp->width );

		bitmap_offset += bmp->width;
		screen_offset += SCREEN_WIDTH;
	}
}

void RunGUI()
{
	init_dbl_buffer();
	unsigned char key;
	mBlock test_dat;
	do
	{
		//key = 0;
		//if (kbhit()) key = getch();

		/* You must clear the double buffer every time to avoid evil messes
		(go ahead and try without this, you will see) */
		memset_c( dbl_buffer, 0x0, SCREEN_WIDTH * SCREEN_HEIGHT );

		/* DRAW ALL BITMAPS AND DO GUI CODE HERE */

		BITMAP test;
		test.width = 100;
		test.height = 100;
		test.data = (unsigned char*) malloc( &test_dat );

		drawrect( &test, 0, 0, test.width, test.height, 0x1 );

		draw_bitmap_old( &test, 5, 5 );

		/* Draws the double buffer */
		update_screen();

		// free memory here
		free( test.data, test_dat );

		sleep( 100 );
	}
	while ( true );	/* keep going */
}
The bitmap draws funny, just a whole lot of lines instead of the solid blue that it should be... any ideas?

Screenshot is attached.
Attachments
The display of my OS so far...
The display of my OS so far...
graphics not working.PNG (21.79 KiB) Viewed 2666 times
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 »

it seems like you're trying to blit something with the wrong size (blitting a 100x100 bitmap as if it were 320xsomething?)
"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 ]
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 »

No, it seems my offsets are wrong. I've tried to set pixels directly to the vga location like so:

Code: Select all

*(unsigned char*)( 0x000A0000 + ( x + ( y * SCREEN_WIDTH ) ) ) = color;
But this still draws with a gap between the two 'pixels'...

I'm confused, can anyone help?

Edit: what really confuses me is that the clearing of the screen works properly, it's just the offsets from the video memory that seem to be failing. I've only tried this in 320x200x8bpp, 256x200x8bpp, 256x256x8bpp... I doubt this is a problem with the mode, though.

Edit 2: Well, it appears the resolution is wrong - I'm apparently NOT running in 320x200, but 80x25 (tested by using SetPixel( 79, 0, 0x4 ); - red line appeared at top right corner, right on edge...). This leads me to assume that somewhere along the line the mode switch got seriously messed up! Any ideas?

Edit 3: :oops: :oops: Shame on me, I realized that I forgot to enable chain4 for the resolution (ie. don't use plane switching)... now I've enabled it, everything is working really well. Sorry for wasting everyone's time :( :oops:
User avatar
stevenup7002
Member
Member
Posts: 60
Joined: Tue Sep 20, 2005 11:00 pm
Location: Ireland
Contact:

Post by stevenup7002 »

You read that tutorial wron, change the top line to:

Code: Select all

unsigned char *VGA = (unsigned char *)0xA0000L;
And it should work in pmode.
User avatar
Jeko
Member
Member
Posts: 500
Joined: Fri Mar 17, 2006 12:00 am
Location: Napoli, Italy

Post by Jeko »

digo_rp wrote:in case you want, I can send to you my sources, then you can take anything you want and change modify, or to learn.

I´ll be very glad to send to evebody.
can you send me your sources?
[email protected]
User avatar
Daedalus
Member
Member
Posts: 74
Joined: Sun Oct 16, 2005 11:00 pm
Location: Australia
Contact:

Post by Daedalus »

I found the drivers used in TabOS to be incredibly helpful to learn from.

Their sources, whilst not formatted the way I would do it, are clean, use few external files/functions, and most of all - portable.

It was quite an easy task to port their ps2 mouse and vga driver to my OS and use them successfully.

I urge you to download the source to their OS and learn from their drivers!
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

stevenup7002 wrote:You read that tutorial wron, change the top line to:

Code: Select all

unsigned char *VGA = (unsigned char *)0xA0000L;
And it should work in pmode.
pcmattman wrote:

Code: Select all

*(unsigned char*)( 0x000A0000 + ( x + ( y * SCREEN_WIDTH ) ) ) = color;
No difference between these. Doesn't matter if the cast is done before or after adding offset, as sizeof(char) is almost certainly 1.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Post by proxy »

there is one difference, the second one is technically illegal (though many compilers will accept it)

it is ill formed to cast an l-value.

so thing like:

*((T *)p) = x;

are not legal :-/

proxy
Last edited by proxy on Mon Dec 15, 2014 8:41 am, edited 1 time in total.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

proxy wrote:there is one difference, the seocnd one is technically illegal (though many compilers will accept it)

it is ill formed to cast an l-value.

so thing like:

*((T *)p) = x;

are not legal :-/

proxy
Yeah technically. But system software that needs to access memory by address will have to do it anyway, and practically every compiler will allow it, as long as it makes sense on the architecture. It doesn't make any difference whether you use the first or the second method though, because if you first cast the address into a pointer, you're technically violating the rules already, because technically you can't cast an integer into a pointer, unless it's of type intptr_t (C99) and even then it's legal only if you obtained the value from a pointer originally.

The whole issue is ofcourse purely academical, and of interest mostly to language lawyers. We aren't writing portable code here after all, if we are dealing with a specific device, like the VGA. :)
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

proxy wrote:there is one difference, the seocnd one is technically illegal (though many compilers will accept it)

it is ill formed to cast an l-value.

so thing like:

*((T *)p) = x;

are not legal :-/

proxy
I agree that (T *)p is an rvalue, but isn't *((T *)p) an lvalue in the same way that *p would be?
Post Reply