Log in

View Full Version : VGA IN PROTECTED MODE



kbronico
14-04-2006, 03:52 PM
Hi, I see that everyone here uses d3d or opengl to create his own programs, but i feel myself and oldschool user.

Im new in this forum. Im used to create low level dos real mode aplications under TP7, including my own 3d engine (you can imagine is not like quake 3 arena's engine jeje), but i have big trouble trying to port my programs to protected mode (and that's neccesary for my poor games, so i can use more than a little heap of lees than 650kbs).

The main problem is accesing vga video memory, cause in real mode it addres is at $a000:000 and there is no problem in modyfing it. but protected mode dont allow to do that, and borland pascal only can access 16 bit memory address. (in PM vga memory segment is $a0000 with is 32 bit memory address).

If someone can help me i will be infinitly pleased. thanks

PD: Im from spain, so you can understand that my english is not as good as i want it to be. Feel you can forgive my faults. thanks.

jdarling
14-04-2006, 04:00 PM
I'd start by migrating to FPC instead of TP7. FPC has support for what your wanting and allows for 16/32/64 bit memory addressing (maybe even higher). Its free and its well maintained.

Then download and take a look at SWAG (Sourceware Archive Group) it can be found at: http://www.gdsoft.com/swag/ and litterally 100's of other places.

If your still wanting to compile for DOS FPC still does this as well as for; ARM, MAC, Linux (many flavors), Alpha, PDP, etc... In other words the gain from the upgrade is more then worth it.

Sorry I didn't answer your question directly, but I don't remember TP7 too well :).

vgo
14-04-2006, 04:08 PM
I've used FPC on DOS back in the day when it was still called FPK Pascal. :)

My memory is a bit hazy, but I've used SWAG too. I'll have to dig thru my old backups and see if I can find any suitable code...

But as jdarling said, FPC is the way to go.

vgo
14-04-2006, 04:34 PM
Here's an old framework I found for FPC, it uses the AT&T(?) assembly syntax...


PROGRAM Test;

Procedure SetMCGA;
Begin
asm
movw $0x0013,%ax
pushl %ebp
int $0x10
popl %ebp
leave
ret
end;
End;

Procedure DoneMCGA;
begin
asm
movw $0x0003,%ax
pushl %ebp
int $0x10
popl %ebp
leave
ret
end;
end;

Procedure PutPixel(X,Y,Color:longint);
begin
asm
movl 8(%ebp),%ebx
movl 12(%ebp),%edx
movl %ebx,%edi
movl %edx,%ebx {; bx = dx}
shll $8,%edx
shll $6,%ebx
addl %ebx,%edx {; dx = dx + bx (ie y*320)}
addl %edx,%edi {; finalise location}
addl $0xE00A0000,%edi
movb 16(%ebp),%al
stosb
leave
ret $12
end;
end;

function GetPixel(X,Y:LongInt):longint;
begin
asm
movl 8(%ebp),%ebx
movl 12(%ebp),%edx
movl %ebx,%edi
movl %edx,%ebx
shll $8,%edx
shll $6,%ebx
addl %ebx,%edx
addl %edx,%edi
addl $0xE00A0000,%edi
movl (%edi),%eax
leave
ret $8
end;
end;

BEGIN
SetMCGA;

DoneMCGA;
END.


I'll try to dig up some more, but there's a shitload of old code to go thru... :P

kbronico
15-04-2006, 04:55 PM
Thanks, it have been much useful for my purpose (but i still have to work a lot on it).

thanks again.

Wiering
16-04-2006, 03:58 PM
Not sure if this helps, but in Borland Pascal you have the variable SegA000, which is set differently in real mode or protected mode.

fragle
20-04-2006, 06:35 AM
Correct me if i'm wrong, but isn't it possible to access memory while in real mode with the help of xms or ems? If it's only some more memory you need, this might help to stay in real mode a little longer ;)

I'll try digging up a book in the evening and see if what i've written is correct.

Edit: ookay, the evening came two days late, but looks like it was not for naught. You can indeed use xms and ems services without having to worry about protected mode. So here ;)

kbronico
26-04-2006, 09:30 PM
Finally, after days of suffering, investigation and a LOT OF LUCK, i got it. and only cost myself the greatest conflict whith my gildfriend. She at least understood that i haven¬Ąt changed her for my computer.

well, its posible to acces memory almost directly runing under protected mode. The way (for those who want to investigate or think that directx or opengl its not the way):

1) I used FPC for GO32v2, a dos extender. It works perfect under windows XP and other OS with dos emulation, and uses the DPMI, a Protected mode interface. Its free download in the Free pascal main page.

2) To start 13h mode its like in real mode (i havent started to investigate vesa implementation, but for my purpose, 13h mode runs perfect), calling int 10h with 13h in ax.

3) you can access videomemory this way: In real mode you were used to access with the $a000 segment, and the offset (obtained this way offset = y*320+x). In protected mode you have no segment, but a selector and a offset. Using the apropiate selector you can access videoram directly. Using assembler: in the FS register you have all msdos memory directions, and videoram is at FS:[$A0000 + offset]. ($A0000 is $A000 selector).

4) to read or write directly in memory, you need the offset, and no need of the segment (in protected mode, segment dont have real meaning). All variables are loaded at the DS register. With the offset you can access a memory value at DS:[offset+pos], where pos is the position in the range of memory you want to access.

here is some code to create virtual memory pages and flip them to vga.
As you see, im from spain, so excuse my poor english. the code is in spanish.

const
VGA = $A0000; {VGA selector}
MaxScreens = 100; {You can use much more virtual screens}

type
screen = array[1..64000] of byte;

var
Vir:array[1..MaxScreens] of longint;
Pan:array[1..Maxscreens] of ^screen;
Usada:array[1..MaxScreens] of boolean; {not important, only for my games}

Procedure ModoGrafico; {init graph mode}
begin
asm
mov ax,13h
int 10h
end;
end;

Procedure ModoTexto;assembler; {end graph mode}
asm
mov ax,3h
int 10h
end;

procedure VirtualUp (numero:byte); {load a virtual screen into memory}
var
temp:longint;
begin
getmem (pan[numero],sizeof(pan[numero]^));
vir[numero]:=ofs(pan[numero]^);
usada[numero]:=false;
end;

procedure VirtualDown (numero:byte); {dispose a virtual page}
begin
freemem (pan[numero]);
end;

Function ExtraerByte (offset_:longint):byte; {offset_ must be }
{vir[n] + (y*320+x) }
var
temp:byte;
begin
temp:=0;
asm
mov esi,offset_
mov al,ds:[esi]
mov temp,al
end;
ExtraerByte:=temp;
end;

Procedure PonerByte (offset_:longint;valor:byte); assembler; {same as above}
asm
mov esi,offset_
mov al,valor
mov ds:[esi],al
end;

Procedure Flip32 (p:longint); assembler; {reveal a virtual screen into vga}
asm {p must be vir[n]}
mov edi,vga
mov esi,p
mov cx,64000
@salto1:
mov eax,ds:[esi]
mov fs:[edi],eax
add edi,4
add esi,4
sub cx,4
cmp cx,0
jne @salto1
end;

Procedure EnviaPantalla32 (p0,pf:longint); assembler; {copy a virtual}
asm { page into other. }
mov edi,pf { p0 must be vir[n] source and }
mov esi,p0 { pf vir[m] destiny }
mov cx,64000
@salto1:
mov eax,ds:[esi]
mov ds:[edi],eax
add edi,4
add esi,4
sub cx,4
cmp cx,0
jne @salto1
end;

procedure FillVGA32 (b:byte); assembler; {simply fills vga with b color }
asm
mov edi,$A0000
mov al,b
mov cx,64000
@salto:
mov fs:[edi],al
inc edi
dec cx
cmp cx,0
jne @salto
end;

procedure Fill32 (b:byte;p:longint); assembler; {same as above but for }
asm { a virtual page p = vir[n] }
mov esi,p
mov al,b
mov cx,64000
@salto:
mov ds:[esi],al
inc esi
dec cx
cmp cx,0
jne @salto
end;

jdarling
27-04-2006, 01:54 AM
You should place together a small test app that shows off how to use your code. Others may find it of interest, in fact I think I find it of nostelgic interest :)

kbronico
28-04-2006, 06:46 PM
Well, here comes a main code to use the unit of above:

program example;

uses crt,graf32; { I call graf32 the unit that contain the functions and procedures from above. The full version includes other low level methods to work with the virtual pages, like loading .CEL and .BMP (320x200 8 bit) image files, load .COL palete files, etc... }

var
key:char; { used to read keyboard }


procedure FillScreen (page:longint); {fills the virtual page with random colors}
var
x,y:integer;
color:byte;
begin
for x:=0 to 319 do
for y:=0 to 199 do
begin
color:=random (255);
ponerbyte (page+(y*320+x),color);
end;
end;

begin
modografico;
virtualup (1); { we create 2 virtual pages to work with }
virtualup (2);
repeat
repeat

fill32 (15,vir[1]); {fills vir[1] with white color}
flip32 (vir[1]); {sends vir[1] to vga so you see a white screen}
fillscreen (vir[2]); {fills vir[2] with random colors}
enviapantalla32 (vir[2],vir[1]); {send vir[2] to vir[1] }
flip32 (vir[1]); {sends vir[1] to vga so you see a beautyfull druglike screen }

until keypressed;
key:=readkey;
until key in [#27]; { ends when <esc> is pressed }
virtualdown (2);
virtualdown (1);
modotexto;
end.

hope this little code be helpfull to your purpose. I have more Object Based Units to work with 2D/3D sprites (a 3D sprite is something like doom enemies), 3D poligons, 3D Lights (Includes a really complex real shadow system from my own), and
3D Terrains/Enviroments/Objects that someone could find usefull to learn.

If someone is interested, can mail me to guybrush26@hotmail.com.