Posted by Weasel on 1999-03-22
Will wrote:
>
> Could anyone please explain more of the mode 13 issue and mode z to me? I don't quite understand the Hardware accessing portion.
> Will
in Mode 13 the vga-memory is accessable in segment 0a000h and has a very
simple structure: every pixel is assigned one byte. (something you need
not to know: the value in this byte points to one color-register of the
DAC). addressing starts top left (like always).
to set a pixel you can use the following pascal procedure:
CONST
ScrSeg = $0a000;
PROCEDURE PutPixel(x,y : word; c : byte);
var
PxlOfs : word;
BEGIN
PxlOfs := y * 320 + x;
Mem[ScrSeg:PxlOfs] := c;
END;
or to make it a bit simplier:
VAR
SCREEN : array[0..199, 0..319] of byte ABSOLUTE $a000:0000;
screen[x,y]:=c;
background:
-----------
In Mode 13 the video adapter hides its 4 planes and fakes this linear
structure. Internal the vga card converts this address and spreds the
data to its 4 planes by using the 2 least significant bits to select the
plane. for purposes of address generation these two bits are then set to
zero.
so it looks like this:
/-- Address
|
Plane 0 Plane 1 Plane 2 Plane 3
0 Pixel 0/0 1/0 2/0 3/0
1 - - - -
2 - - - -
3 - - - -
4 4/0 5/0 6/0 7/0
5 - - - -
6 - - - -
7 - - - -
distribution of pixels(x/y) in the video ram
ModeX
=====
=====
One big disadvantage of Mode 13 is that it offers only one page. To get
4 pages you just need to do a few things:
* switch of chain-4
* ensure odd/even mode is not active
* switch CRTC to bytemode
PROCEDURE EnterModeX;
BEGIN
{ switch to Mode13 first}
ASM
mov ax,13h
int 10h
END;
{chain-4 , odd/even}
Port[$3c4]:= 4;
Port[$3c5]:= (Port[$3c5] and (not 8)) or 4;
{doubleword addressing OFF, byte addressing ON}
Port[$3d4]:= $14;
Port[$3d5]:= Port[$3d5] and (not 64);
Port[$3d4]:= $17;
Port[$3d5]:= Port[$3d5] or 64;
END;
after switching to ModeX you should clean the videoRAM since there is
still bit-rubbish at places wich where not visible before. (see later)
Accessing gets a little more complicated now since you have to select
the right planes yourself now.
Addressing:
offset = Y * 80 + X div 4
plane = X mod 4;
VAR
ScreenWidth : word ABSOLUTE $0040:$004a; {BIOS variable}
{should be 80 IIRC}
PROCEDURE PutPixel(x, y: word; c: byte; PageOffset : word);
VAR
ScrOfs : word;
BEGIN
ScrOfs:=ScreenWidth * 2 * y + x div 4 + PageOffset;
Port[$3c4]:= 2;
Port[$3c5]:= 1 SHL (x and 3); { set pitplane mask}
mem[ScrSeg:ScrOfs] := c;
END;
with PageOffset you can select the page you want to edit.
You see that this value is simply added up to the ofset value, so
setting it to 0 shows you the zero-th page, setting it to
2*200*ScreenWidth = 32000 shows you the first page, 64000 the second and
9600 the third page.
To read a pixel we need to use the Read Plane Select Register:
FUNCTION GetPixel(x, y : word; PageOffset : word) : byte;
VAR
ScrOfs : word;
BEGIN
ScrOfs:=ScreenWidth * 2 * y + x div 4 + PageOffset;
Port[$3ce]:= 4;
Port[$3cf]:= x and 3; { set read-plane select}
mem[ScrSeg:ScrOfs] := c;
END;
To display page 1 instead of page 0 do the following:
SetLinearStartingAddress(PageOffset : word);
with the same PageOffsets like above. (It may be that you have to double
these values of divide them by two. I simply cannot remember)
VAR
CRTCPort : word ABSOLUTE $0040:$0063; {BIOS variable}
{ this should be 3d4 IIRC in Mode13 but is different for other modes
}
PROCEDURE SetLinearStartingAddress(LSA : word);
BEGIN
Port[CRTCPort ]:= $0c;
Port[CRTCPort+1]:= hi(LSA);
Port[CRTCPort ]:= $0d;
Port[CRTCPort+1]:= lo(LSA);
END;
Don't hestitate to ask if you have any questions.
--
Weasel mailto:palfrader@xxxxxxx.xxx
Peter http://www.cosy.sbg.ac.at/~ppalfrad/
------------------------------------------------------------
We have full klingon console support just in case.
-- Alan Cox on linux-kernel
Previous post | Next post | Timeline | Home