V22.0201, Machine Organization I, Yap


A basic reference used in these notes is "Programmer's guide to PC and PS/2: VIDEO SYSTEMS" by Richard Wilton, Microsoft Pres, 1987.

We will focus on EGA and VGA graphics, since CGA is adequately covered in the book and elsewhere. VGA is similar to EGA in many ways. Here is a very easy guide to VGA graphics mode 13h. But below we go into more details.

    CGA graphics maps video memory directly to pixels on the screen. But EGA and VGA uses its video memory in a rather unusual way: it is divided into 4 bit planes, and the address of these bit planes are common. This means that we address these 4 planes in parallel. The term "bit" in bit plane is literal: each addressable byte of video memory really refers to 8 pixels (and so we have 4 bits per pixel).

    To exploit this parallelism, we introduce a level of indirection, via the latches. Each bit plane has an associated 8-bit latch. The following data flow is crucial to understand:

    When we perform a CPU Read (e.g., mov reg,mem) from video buffer, we actually move 4 bytes (one per bit plane) into the four latches. Then, depending on the read mode, some combination of the bytes in these 4 latches are copied to the CPU. There are 2 read modes.
    Likewise, in a CPU Write (e.g., mov mem,reg) to the video buffer is mediated by these 4 latches. In this case, the 4 bit planes are updated in parallel, using a combination of the data in the latches, CPU register, and special registers of the GC. There are 4 write modes in VGA (one of these are not available in EGA).
    Of course, some instructions (e.g., xor mem,reg) generate both a CPU Read and a CPU Write.

    An interesting phenomenon arises in moving bytes between two bit plane addresses. We actually move 4 bytes in parallel. E.g.

    	mov ax,VideoBufferSegment	; A000 or B000, depending on mode
    	mov ds, ax
    	mov es, ax
    	mov si, 1	 	; source ds:si
    	mov di, 0		; destination es:di
    	movsb			; source --> destination 
    This moves one byte from the second byte of each bit plane to the first byte of the corresponding bit plane.

    What if we had used "movsw" instead? In this case, this translates into two movement of bytes into the latches, followed by two movement of bytes into the destination. So the first movement of bytes is lost, and the second set of bytes is actually duplicated into words. MORAL: be careful of using word size operands on video memory.

    In EGA and VGA, the Graphics Controller (GC) manages transfers of data among the video memory, CPU registers and the latches. The GC has 9 registers which are addressable at the port 3cfh, via an address register at port 3ceh. (What does this mean?)

    These registers are summarized as follows:
    0		set/reset			0
    1		enable set/reset		0
    2		color compare			0
    3		data rotate/function select	0
    4		read map select			0
    5		mode				bits 0-3 always 0
    6		miscellaneous			(depends on video mode)
    7		color don't care		0fh (16-color mode)
    						01h (640x480, 2-color mode)
    8		bit mask			0ffh 
    E.g., register 5 is called the MODE register. Various 2-bit fields in this register specify the graphics read and write modes. To establish read mode 0 (bit 3 of MODE register is 0) and write mode 1 (bits 0-1 of MODE register is 1), we do:

    	mov ax, 0105h	; ah=1 specifies write mode 1
    			;    al=5 specifies register 5 (MODE register)
    	mov dx,3ceh	; dx = GC port number
    	out dx, ax
    The basic actions of the GC are
    -- copy contents of latches to and from video buffer
    -- move the contents of one of the latches to a CPU register
    -- combine the byte contents of a CPU register with the bytes in any or all of the latches in a single CPU read.
    We now describe the specific modes:

    READ MODE 0:
    The GC returns the contents of one of the 4 latches to the CPU. The latch is selected by the 0-1 bits of the READ MAP SELECT REGISTER (register 4).

    READ MODE 1:
    This uses two registers: COLOR DON'T CARE REGISTER (register 7) and COLOR COMPARE REGISTER (register 2). We first treat the 4 latches are specifying 8 pixel values, each pixel value having 4 bits. For each pixel value, we first AND it with the 0-3 bits of the COLOR DON'T CARE REGISTER. Then, we COMPARE it with the 0-3 bits of ((COLOR COMPARE) and (COLOR DON'T CARE)). Note that when we COMPARE two sets of 4-bit values, the result is a 1 if the two sets of values agree, and 0 otherwise.

    	E.g., suppose a particular pixel value is 1011.  
    	Let the 0-3 bits of the
    	COLOR DON'T CARE REGISTER be 0111 and the 0-3 bits of the
    	COLOR COMPARE REGISTER be 1010.  Then we have to compare
    		(1011 and 0111) with (1010 and 0111)
    		0011 with 0010.
    	Since these 2 values are different, the output of this 
    	comparison is 0.
    In effect, setting a COLOR DON'T CARE REGISTER bit to 0 amounts to ignoring the corresponding bit plane in our comparisons. In particular, if the COLOR DON'T CARE REGISTER is set to 0, then the output of every comparison will be 1.

    REMARK: note that read mode 0 is byte-oriented while read mode 1 is pixel-oriented.

    This is a combination of byte-oriented and pixel-oriented operations. It depends on the values in the Enable Set/Reset, Data Rotate/Function Select, and Bit Mask Registers (registers 1,3,8).

    Bit Mask Register: this specifies for each of the 8 pixels, whether (i) the new pixel value is to be directly copied from the 4 latches or (ii) the new pixel value is to be obtained from the latched pixel value, combined with either CPU data or pixels in the Set/Reset registers. If the i-th bit of the Bit Mask Register is 0, then method (i) is used. Otherwise we use method (ii).

    The Data Rotate/Function Select register contains two bit-fields that affects the update of the l atched pixels: Bits 0-2 specify the number of times to right-rotate the CPU data byte before combining it with the latched data. Bits 3-4 specify the logical function to use for updating pixels:

    	Bit 4	Bit 3	Function
    	0	0	Replace
    	0	1	AND
    	1	0	OR
    	1	1	XOR
    The Enable Set/Reset register determines whether the bit planes are updated byte by byte or pixel by pixel. If the value of this register is 0Fh, each pixel is updated by combining the latched pixel value with the value in the Set/Reset register, using the logical operation specified by the Function Select register. When the Enable Set/Reset register is 0, the rotated CPU data byte is combined with each of the latches, again using the logical operation specified by the Function Select register. In either case, only the pixels masked by the bit mask registers are updated. [Of course, you can set the Enable Set/Reset register to any value from 0 to 0Fh, and the obvious generalization applies. But this can be tricky and is seldom used. Note that the Enable Set/Reset value of 0Fh is "unnatural" in the sense that it makes the write operation independent of the CPU register data.]

    The latches are copied directly to the bit planes. Note that the CPU registers are not used! For this mode to make sense, you must first perform a CPU read instruction to initialize the latches.

    The 0-3 bits of the CPU register plays the role of the Set/Reset register in write mode 0. That is, the bit planes are updated by combining the pixel values in the latches with the CPU data, using the logical operation specified by bits 3-4 in the Function Select register. As in write mode 0, the Bit Mask register is again used to specify which pixels are to be directly replaced by latch values and which is to be updated by the function selector.

    (Only available on VGA, not EGA.) This is similar to write mode 0 except that the CPU register data is always used, but it is rotated (using the Data Rotate register bits 0-2) and then logically combined (using the function specified by the Function Select register bits 3-4) with the Bit Mask Register! The Set/Reset register is used direcly on the pixel values derived from the latches, as before. [Somewhat unclear in the text.]


    (p.125 of book reference)

    ReadPixel13 (p.135)

    SetPixel10 (p.141)

    	; **** sets value of pixel in native EGA mode
    	;  called from Microsoft C: void SetPixel(x,y,n);
    	;  It is supposed to be superior to the BIOS interrupt 
    	;  INT 10h, function 0Ch.