Graphics mode?
-
- 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?
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).
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/
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/
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.
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.
-
- 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:
Thanks, I can get into the video mode now...
The problem is, the following does not work:
The bitmap draws funny, just a whole lot of lines instead of the solid blue that it should be... any ideas?
Screenshot is attached.
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 */
}
Screenshot is attached.
- Attachments
-
- The display of my OS so far...
- graphics not working.PNG (21.79 KiB) Viewed 2665 times
-
- 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:
No, it seems my offsets are wrong. I've tried to set pixels directly to the vga location like so:
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: 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
Code: Select all
*(unsigned char*)( 0x000A0000 + ( x + ( y * SCREEN_WIDTH ) ) ) = color;
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: 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
- stevenup7002
- Member
- Posts: 60
- Joined: Tue Sep 20, 2005 11:00 pm
- Location: Ireland
- Contact:
You read that tutorial wron, change the top line to:
And it should work in pmode.
Code: Select all
unsigned char *VGA = (unsigned char *)0xA0000L;
can you send me your sources?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.
[email protected]
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!
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!
stevenup7002 wrote:You read that tutorial wron, change the top line to:
And it should work in pmode.Code: Select all
unsigned char *VGA = (unsigned char *)0xA0000L;
No difference between these. Doesn't matter if the cast is done before or after adding offset, as sizeof(char) is almost certainly 1.pcmattman wrote:Code: Select all
*(unsigned char*)( 0x000A0000 + ( x + ( y * SCREEN_WIDTH ) ) ) = color;
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
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
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.
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.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
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.
I agree that (T *)p is an rvalue, but isn't *((T *)p) an lvalue in the same way that *p would be?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