home *** CD-ROM | disk | FTP | other *** search
- {─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
- Msg : 293 of 310
- From : Kai Rohrbacher 2:241/7451.7 15 Apr 93 23:14
- To : David Todd 1:259/423.0
- Subj : Mode X/Y
- ────────────────────────────────────────────────────────────────────────────────
- KR>> Basically, Mode Y works like this: use the BIOS to switch
- KR>> into normal 320x200x256 mode, then reprogram the sequencer to
- KR>> unchain the 4 bitplanes. This results in a bitplaned VRAM layout
- KR>> very similiar to the EGA/VGA's 16 color modes:
- DT>
- DT> By saying 4 bitplanes, are you referering to the pages? I know that
- DT> you can specify 4 pages in mode X/Y.
- No, it just means that with each VRAM address, 4 physically different RAM cells
- can be addressed: you may think of a "3-dimensional" architecture of your VGA's
- VRAM (ASCII sucks, I know...)
- ____________
- |* plane3 |
- ___|_________ |
- |* plane2 |__|
- ___|__________ |
- |* plane1 |__|
- ___|___________ |
- |* plane0 |__|
- | |
- |_______________|
-
- The upper left corner of each bitplane (marked by a "*") is referenced with the
- address $A000:0, but refers to 4 pixels! It is quite simple: instead of
- counting "$A000:0 is the first pixel, $A000:1 is the 2nd, $A000:2 is the 3rd,
- $A000:3 is the 4th, $A000:4 is the 5th" (as you would do in the normal BIOS
- mode 320x200x256), the pixels now are distributed this way: "$A000:0/plane 0 is
- the 1st, $A000:0/plane 1 is the 2nd, $A000:0/plane 2 is the 3rd, $A000:0/plane
- 3 is the 4th, $A000:1/plane 0 is the 5th" and so on.
- So obviously, w/o doing some "bitplane switching", you are always restricted to
- work on one bitplane at a time --the one actually being activated. If this is
- plane0, you may only change pixels which (x mod 4) remainder is 0, the other
- ones with (x mod 4)=1|2|3 aren't accessible, you have to "switch to the plane"
- first. Thus the name "bitplane"!
-
- DT> And what exactly does "unchain" mean, as opposed to "chained". I have the
- DT> feeling that they refer to each page(bitplane) being on its own.
- Huhh, that would go pretty much into details; a bit simplified, "chained" means
- that the bitplanes mentioned above are "glued" together for the simple BIOS
- mode, so that bitplane switching isn't necessary anymore (that is equivalent in
- saying that one VRAM address refers to one RAM cell). As there are only 65536
- addresses in the $A000 segment and we need 320x200=64000 for a full page, you
- only have 65536/64000=1.024 pages therefore. "Unchaining" means to make each
- bitplane accessible explicitely.
-
- DT> Now here is another problem I don't understand. I am familiar with VGA's
- DT> mode 13h which has one byte specifying each pixel on the screen,
- DT> therefore 1 byte = 1 pixel. But this takes up 64k.
- Small note on this: not 64K, but only 64000 bytes!
-
- DT> But how do you have one address represent 4 pixels, which only occupies
- DT> 16000 address bytes, and still be able to specify 256 colours. Won't 4
- DT> bitplanes at 320x200 each take up 64000x4 bytes of space?
- We have 320x200=64000 pixels=64000 bytes. As each 4 pixels share one address,
- 16000 address bytes per page suffice. The $A000 segment has 64K address bytes,
- thus 4*64K=256K VRAM can be addressed. 64K address bytes = 65536 address bytes;
- 65536/16000 = 4.096 pages.
-
- DT> How would you go about adjusting the vertical retraces, and memory
- DT> location you mentioned.
- Assuming that the DX-register has been set to 3DAh or 3BAh for color/monochrome
- display, respectively, you can trace the status of the electronic beam like
- this:
- @WaitNotVSyncLoop:
- in al,dx
- and al,8
- jnz @WaitNotVSyncLoop
- @WaitVSyncLoop:
- in al,dx
- and al,8
- jz @WaitVSyncLoop
- now change the starting address
-
- (If you use "1" instead of "8" and exchange "jz" <-> "jnz" and vice vs., then
- you sync on the shorter horizontal retrace (better: horizontal _enable_)
- signal).
- The alteration of the starting address is done by the code I already posted in
- my first mail! (Its done by addressing the registers $C and $D of the
- CRT-controller).
- Note that reprogramming the starting address isn't restricted to mode X/Y, you
- can have it in normal mode 13h, too: there are 65536 addresses available, but
- only 64000 needed, thus giving a scroll range of 4.8 lines! And to complicate
- things even further, for start addressing purposes, even the BIOS mode is
- planed (that is, a row consists of 320/4 bytes only). Just for the case you
- don't believe...}
-
- PROGRAM Scroll;
- VAR CRTAddress,StatusReg:WORD;
- a:ARRAY[0..199,0..319] OF BYTE ABSOLUTE $A000:0000;
- i,j:WORD;
-
- PROCEDURE SetAddress(ad:WORD); ASSEMBLER;
- ASM
- MOV BX,ad
-
- MOV DX,StatusReg
- @WaitNotVSyncLoop:
- in al,dx
- and al,8
- jnz @WaitNotVSyncLoop
- @WaitVSyncLoop:
- in al,dx
- and al,8
- jz @WaitVSyncLoop
-
- MOV DX,CRTAddress
- MOV AL,$0D
- CLI
- OUT DX,AL
- INC DX
- MOV AL,BL
- OUT DX,AL
- DEC DX
- MOV AL,$0C
- OUT DX,AL
- INC DX
- MOV AL,BH
- OUT DX,AL
- STI
- END;
-
- BEGIN
- IF ODD(port[$3CC])
- THEN CRTAddress:=$3D4
- ELSE CRTAddress:=$3B4;
- StatusReg:=CRTAddress+6;
- ASM
- MOV AX,13h
- INT 10h
- END;
-
- FOR i:=1 TO 1000 DO
- a[Random(200),Random(320)]:=Random(256);
-
- {scroll horizontally by 4 pixels}
- FOR i:=1 TO 383 DO SetAddress(i);
- FOR i:=382 DOWNTO 0 DO SetAddress(i);
-
- {scroll vertically by 1 row}
- FOR j:=1 TO 20 DO
- BEGIN
- FOR i:=1 TO 4 DO SetAddress(i*80);
- FOR i:=3 DOWNTO 0 DO SetAddress(i*80)
- END;
-
- ASM {back to 80x25}
- MOV AX,3
- INT 10h
- END;
-
- END.
-
- DT> Your said you could specify how the memory can be layed out by the user,
- DT> but I am in need of what each PORT does. I know you have to send
- DT> different values to the port to program it, but I have no idea what each
- DT> port reads.
- There are incredibly much registers to program! For a good overview of most of
- them, try to get your hands on a copy of VGADOC*.* by Finn Thoegersen
- (jesperf@daimi.aau.dk) which covers programming a lot of SVGA's chipsets, too.
-
- cu,
- Kai