VEGA Technical Reference
VEGA is the Visual Engine for Graphics Acceleration. This is the hardware reference for the VEGA chipset in the Izarra3000. It describes the programming interface: the memory map, the display modes, and the register set.
VEGA has two graphics engines, each with its own memory:
- Margo, the 2D engine. It drives the desktop and all of the 2D display modes. It has a 4 MB frame store, and a blit engine for accelerated fills, copies, text, and lines.
- Distira, the 3D engine. It has a 2 MB frame buffer and two independent 2 MB texture stores.
VEGA shows the scanout of the active engine. Margo and Distira do not share memory addresses.
This revision describes both engines. Margo is below. Distira is in section 10.
1. Margo overview
Margo has a flat frame store, a set of linear display modes, and a memory-mapped register block. The VESA BIOS interface gives access to the display modes, and the register block operates the blit engine. A driver sets a mode through the VBE software interface. It then uses the register block to move pixels without the CPU.
- A 4 MB frame store, private to Margo. It is a flat byte space, from offset
0x000000to0x3FFFFF. - Display modes to a maximum of 1024x768 at 32 bits for each pixel.
- A palette of 256 entries for the 8-bit modes, through the standard VGA DAC ports.
- A blit engine with a solid fill, a screen-to-screen copy, a monochrome color expand (text), and a line draw. Each operation has a raster operation, optional clipping, and an optional color key.
- A tiled pattern fill, a 64x64 hardware cursor, and a scaled video overlay with YUV color conversion. Use them for desktop work and for CD video playback.
- VESA VBE 2.0 compatibility, with a linear frame buffer.
The legacy VGA text mode and mode 13h continue to be available, with no change. The VGA core document describes them. This document does not.
1.1 Datasheet
| Parameter | Value |
|---|---|
| Host interface | 66 MHz, 32-bit, bus-mastering port to the custom chipset (PCI derived) |
| Host bandwidth | about 266 MB/s peak |
| Margo core clock | 100 MHz |
| Frame store | 4 MB SGRAM, 128-bit, 100 MHz, dedicated to Margo |
| Memory bandwidth | about 1.6 GB/s |
| RAMDAC | 206 MHz, integrated |
| 2D solid fill | up to about 200 Mpixels/s |
| 2D screen-to-screen blit | up to about 100 Mpixels/s |
| Maximum mode | 1024x768 at 32-bit color |
| Process | 350 nm |
These are the rated figures. The emulator does not model the graphics timing cycle by cycle. Thus the fill rate and the blit rate describe the part, and not the emulated behavior. See section 9.
2. Physical memory map
| Range | Size | Contents |
|---|---|---|
0x000A0000 to 0x000BFFFF |
128 KB | Legacy VGA aperture (mode 13h at 0xA0000, text at 0xB8000) |
0xE0000000 to 0xE03FFFFF |
4 MB | Margo linear frame buffer. Frame store offset 0 maps to 0xE0000000. |
0xE0400000 to 0xE040FFFF |
64 KB | Margo register block (memory mapped) |
The linear frame buffer gives access to the full 4 MB frame store. The visible
surface starts at the offset in DISP_START, which is 0 by default. The
memory above the visible surface is free for offscreen work: blit sources,
cached fonts, and saved screen regions.
The frame buffer and the register block are above the 64 MB of system memory. Thus a program reaches them from protected mode or flat mode. Real-mode code uses mode 13h or the legacy VGA aperture.
3. Display modes
A program selects a mode through the VBE interface (section 6). Margo supports the standard VESA mode numbers, thus existing VESA software finds them. The 32-bit modes use numbers in the OEM range, because VESA assigned no standard numbers for 32-bit color.
Mode 0x150 is a VEGA OEM mode: 320x240 at 8 bits for each pixel. The monitor
doubles its lines. The graphical POST of the Izarra-BIOS uses it. Function
4F00h returns the mode list in ascending order, thus the OEM entries come
after the VESA entries.
| Mode | Resolution | Depth | Pixel format | Bytes/pixel |
|---|---|---|---|---|
0x100 |
640x400 | 8 | Indexed | 1 |
0x101 |
640x480 | 8 | Indexed | 1 |
0x103 |
800x600 | 8 | Indexed | 1 |
0x105 |
1024x768 | 8 | Indexed | 1 |
0x110 |
640x480 | 15 | X1R5G5B5 | 2 |
0x111 |
640x480 | 16 | R5G6B5 | 2 |
0x113 |
800x600 | 15 | X1R5G5B5 | 2 |
0x114 |
800x600 | 16 | R5G6B5 | 2 |
0x116 |
1024x768 | 15 | X1R5G5B5 | 2 |
0x117 |
1024x768 | 16 | R5G6B5 | 2 |
0x14A |
640x480 | 32 | X8R8G8B8 | 4 |
0x14C |
800x600 | 32 | X8R8G8B8 | 4 |
0x14E |
1024x768 | 32 | X8R8G8B8 | 4 |
0x150 |
320x240 | 8 | Indexed | 1 |
The scanline pitch is the visible width multiplied by the bytes for each pixel. There is no padding. The largest surface is 1024x768 at 32-bit, which is 3 MB. This leaves 1 MB of the frame store for offscreen use.
3.1 Scanout timing
Each mode refreshes at 60.000 Hz. The pixel clock is not an independent parameter. It is the clock that gives the total dots of the mode at that rate. Thus the refresh rate is the same in each mode. It does not change with the resolution or with the depth.
| Displayed resolution | Total dots | Total lines | Sync start | Sync width | Pixel clock |
|---|---|---|---|---|---|
| 640x400 | 800 | 449 | line 412 | 2 lines | 21.552 MHz |
| 640x480 | 800 | 525 | line 490 | 2 lines | 25.200 MHz |
| 800x600 | 1056 | 628 | line 601 | 4 lines | 39.790 MHz |
| 1024x768 | 1344 | 806 | line 771 | 6 lines | 64.996 MHz |
The totals and the sync positions are the standard values for these resolutions. Thus a monitor of the period locks to them. The clocks are different from the usual published figures, in the third digit or the fourth digit. The published figures are for 59.94 Hz at 640x480, and for 60.32 Hz at 800x600, and not for a flat 60 Hz.
The 640x400 signal is a different type of exception. Usually a card drives it at 70 Hz. Margo drives it at 60 Hz, as it drives each other mode. Thus its clock is lower.
Mode 0x150 holds 320x240. The display doubles its lines. Thus it scans out
on the 640x480 signal in the table.
Software can read the vertical retrace interval through Input Status 1 (port
03DAh bit 3) and Input Status 0 (port 03C2h bit 7). A VGA program reads
the same two registers. A read of 03DAh also resets the address/data
flip-flop of the attribute controller, because that behavior belongs to the
port and not to the engine that drives the display. Bits 1 and 2 of 03DAh
read 0, because the machine has no light pen. The diagnostic DAC readback bits
4 and 5 also read 0, because they have no attribute-controller path to sample
while Margo owns the display.
4. Pixel formats
| Format | Bits | Layout (high to low) |
|---|---|---|
| Indexed | 8 | Palette index. Color comes from the DAC. |
| X1R5G5B5 | 16 | 1 unused, 5 red, 5 green, 5 blue |
| R5G6B5 | 16 | 5 red, 6 green, 5 blue |
| X8R8G8B8 | 32 | 8 unused, 8 red, 8 green, 8 blue |
Margo has no packed 24-bit color. The 32-bit format gives true color, and it has no three-byte pixel.
5. VGA DAC (palette)
The 8-bit indexed modes and mode 13h take their colors from the DAC, which has 256 entries. They use the standard VGA ports.
| Port | Access | Function |
|---|---|---|
0x03C8 |
Write | Palette write index. It sets the entry for the next data writes. |
0x03C7 |
Write | Palette read index. It sets the entry for the next data reads. |
0x03C9 |
Read/Write | Palette data. Each entry needs three accesses: red, green, then blue. |
Each component is 6 bits, from 0 to 63. After three writes to 0x03C9, the
index moves to the next entry. Thus a full palette load is one write to
0x03C8, and then 768 writes to 0x03C9.
6. VBE software interface
The mode set and the frame buffer information come through INT 10h with
AH = 4Fh. This is the VESA BIOS Extensions interface. AL selects the
function. On return, AL = 4Fh shows that the function is available, and AH
is the status. A status of 0 is success.
| Function | Name | Notes |
|---|---|---|
4F00h |
Return controller information | Fills a VbeInfoBlock at ES:DI. Signature VESA, version 0x0200, total memory 64 (in 64 KB units), and a pointer to the mode list. |
4F01h |
Return mode information | Fills a ModeInfoBlock at ES:DI for the mode in CX: resolution, depth, pitch, color masks, and PhysBasePtr = 0xE0000000. |
4F02h |
Set mode | Mode number in BX. Bit 14 (0x4000) requests the linear frame buffer. Bit 15 (0x8000) keeps the memory contents. |
4F03h |
Return current mode | Current mode number in BX. |
4F05h |
Set/get display window | Banked access to the frame store, through the legacy aperture at A000h. BH=00h selects the bank in DX, and BH=01h returns it. BL selects the window, and it must be 00h, because only window A exists. The granularity and the window size are both 64 KB. Thus bank n maps frame store offset n * 64 KB to A0000h. The function fails with status 03h in a mode that uses the linear frame buffer. |
4F07h |
Set/get display start | BL=00h queues an (x,y) origin. BL=01h returns the active origin. BL=80h queues the origin and waits for the next 60 Hz frame boundary. Use these for panning and for page flips. |
4F08h |
Set/get DAC palette width | BL=00h selects the width in BH. BL=01h returns the active width in BH. The DAC supports six-bit and eight-bit entries. |
4F09h |
Set/get palette data | BL=00h loads, BL=01h reads, and BL=80h loads at the next frame boundary. Each entry at ES:DI is a four-byte record: B, G, R, and alignment. CX is the count, and DX is the first index. |
4F0Ah |
Return protected-mode interface | BL=00h returns a table of protected-mode entry points at ES:DI, with a length of CX bytes. The table holds far-callable routines for set window, set display start, and set primary palette data. After them comes the list of the I/O ports that they use. Thus a protected-mode driver reaches them without INT 10h. Other BL values are not defined. |
Functions 4F00h to 4F03h are the core of the mode set. The other functions
are extensions.
A mode set through 4F02h programs the display timing again. While a VBE mode
is active, the CRT status registers report that timing. They do not report the
timing of the previous VGA mode. See section 3 and section 9.
7. Margo register block
The register block is 64 KB at 0xE0400000. Each register is 32 bits. Use
aligned 32-bit reads and writes. A byte access or a 16-bit access to the block
is not defined.
The offsets below are relative to the base of the block.
7.1 Identification and control
| Offset | Name | Access | Description |
|---|---|---|---|
0x0000 |
ID |
R | Identity and interface version. It reads 0x4D470100. 0x4D47 is the Margo signature, and the low half is version 1.00. |
0x0004 |
CAPS |
R | Feature bitmap. A driver reads it to find the operations of this build. See below. |
0x0008 |
STATUS |
R | Bit 0 BUSY: an operation is in progress. The bit stays set until the modeled completion time (section 9). Bit 1 FIFO_FULL: reserved, reads 0. |
0x000C |
CONTROL |
R/W | Bit 0 RESET: write 1 to stop the current operation and clear the engine. The bit clears itself. Bit 1 DITHER_EN: dither where the color precision decreases (section 7.10). The other bits are reserved. Write 0 to them. |
CAPS bits:
| Bit | Meaning |
|---|---|
| 0 | FILL available |
| 1 | COPY available |
| 2 | COLOR_EXPAND available |
| 3 | LINE available |
| 4 | Full ROP3 set available (more than the plain copy and fill) |
| 5 | CLIP available |
| 6 | COLORKEY available |
| 7 | PATTERN_FILL available |
| 8 | Hardware cursor available |
| 9 | Video overlay available |
| 10 | DMA pusher available |
| 11 | Hardware dithering available |
The register map in this manual is fixed. CAPS gives the parts that the
current build has. Thus a driver for the full map continues to operate
correctly on an early build.
7.2 Display controller
These registers describe the surface that Margo scans out. 4F02h sets them.
A driver can write DISP_START to pan the display or to flip pages.
| Offset | Name | Access | Description |
|---|---|---|---|
0x0010 |
DISP_MODE |
R | Current VBE mode number. |
0x0014 |
DISP_WIDTH |
R | Visible width in pixels. |
0x0018 |
DISP_HEIGHT |
R | Visible height in pixels. |
0x001C |
DISP_BPP |
R | Bits for each pixel (8, 15, 16, 32). |
0x0020 |
DISP_PITCH |
R | Bytes for each scanline of the visible surface. |
0x0024 |
DISP_START |
R/W | Frame store byte offset of the top-left visible pixel. The default is 0. It takes effect on the next frame. |
7.3 Blit engine
Write the parameters. Then write COMMAND to start an operation.
| Offset | Name | Access | Description |
|---|---|---|---|
0x0100 |
DST_BASE |
R/W | Frame store byte offset of the destination surface origin. |
0x0104 |
DST_PITCH |
R/W | Bytes for each scanline of the destination surface. |
0x0108 |
SRC_BASE |
R/W | Frame store byte offset of the source surface origin. |
0x010C |
SRC_PITCH |
R/W | Bytes for each scanline of the source surface. |
0x0110 |
DEPTH |
R/W | Bytes for each pixel that the engine operates on (1, 2, or 4). This is usually the surface format. |
0x0114 |
DST_XY |
R/W | Destination top-left. Y in bits 31..16, X in bits 15..0, in pixels. |
0x0118 |
SRC_XY |
R/W | Source top-left, with the same packing. |
0x011C |
DIM |
R/W | Rectangle size. Height in bits 31..16, width in bits 15..0, in pixels. |
0x0120 |
FG_COLOR |
R/W | Foreground or fill color, right-justified in the destination format. |
0x0124 |
BG_COLOR |
R/W | Background color for a color expand. |
0x0128 |
ROP |
R/W | Raster operation, in the low 8 bits (ROP3 code). See section 7.6. |
0x012C |
COLORKEY |
R/W | Transparent color value, in the destination format. |
0x0130 |
FLAGS |
R/W | Bit 0 COLORKEY_EN, bit 1 CLIP_EN, bit 2 EXPAND_TRANSPARENT. See section 7.5. |
0x0134 |
CLIP_TL |
R/W | Clip rectangle top-left (Y:X packed). Inclusive. |
0x0138 |
CLIP_BR |
R/W | Clip rectangle bottom-right (Y:X packed). Exclusive. |
0x013C |
LINE_START |
R/W | Line start point (Y:X packed). |
0x0140 |
LINE_END |
R/W | Line end point (Y:X packed). |
0x0144 |
PAT_BASE |
R/W | Frame store offset of an 8x8 pattern in the destination format. The row pitch is 8 * DEPTH bytes. PATTERN_FILL uses it. |
0x0150 |
COMMAND |
W | Write a command code to start an operation. See section 7.4. |
0x0160 |
MONO_DATA |
W | Monochrome data port for COLOR_EXPAND_DATA. See section 7.4. |
7.4 Commands
Write one of these codes to COMMAND. The engine does the operation with the
values in the registers. BUSY stays set until the operation is complete.
| Code | Name | Operation |
|---|---|---|
0x01 |
FILL |
Fill the destination rectangle (DST_XY, DIM) with FG_COLOR, through ROP. ROP 0xF0 gives a solid fill. ROP 0x5A does an exclusive-OR of FG_COLOR into the destination, for a rubber-band box. |
0x02 |
COPY |
Copy the source rectangle (SRC_XY, DIM) to DST_XY, through ROP. The engine selects a safe order when the source and the destination overlap. With COLORKEY_EN, the engine does not write a source pixel that is equal to COLORKEY. |
0x03 |
COLOR_EXPAND_DATA |
Expand a monochrome bitmap into the destination rectangle. MONO_DATA carries the bitmap. A set bit gets FG_COLOR. A clear bit gets BG_COLOR, or stays unchanged with EXPAND_TRANSPARENT. |
0x04 |
COLOR_EXPAND_MEM |
The same operation, but the engine reads the monochrome source from the frame store at SRC_BASE and SRC_XY, with SRC_PITCH, at 1 bit for each pixel, most significant bit first. |
0x05 |
LINE |
Draw a line from LINE_START to LINE_END in FG_COLOR, through ROP. |
0x06 |
PATTERN_FILL |
Fill the destination rectangle with tiles of the 8x8 pattern at PAT_BASE, in the destination format. The pattern phase aligns to the surface origin, thus adjacent fills join with no visible seam. ROP and the color key apply, thus a hatch pattern can key its background through. For a monochrome GDI brush, expand the brush one time into an 8x8 color tile. |
COLOR_EXPAND_DATA reads its source as a stream. After you write the command,
write the bitmap to MONO_DATA one 32-bit word at a time, with the most
significant bit first. Each scanline starts on a word boundary. Thus a row of
W pixels needs ceil(W / 32) words. The engine reads
ceil(width / 32) * height words, and it holds BUSY until the last word
arrives.
7.5 Flags
| Bit | Name | Effect |
|---|---|---|
| 0 | COLORKEY_EN |
On COPY, the engine does not write a source pixel that is equal to COLORKEY. Use it for a transparent sprite or icon. |
| 1 | CLIP_EN |
The engine clips each operation to the rectangle in CLIP_TL and CLIP_BR. It discards a pixel outside that rectangle. |
| 2 | EXPAND_TRANSPARENT |
On a color expand, the engine does not write a clear bit with BG_COLOR. Thus a glyph draws over the existing pixels. |
7.6 Raster operations
ROP holds an 8-bit ROP3 code. The code is the boolean function of the source
(S), the destination (D), and the pattern (P). For FILL and LINE, the
pattern is FG_COLOR, and there is no source. For COPY and for a color
expand, the source is the moved pixel or the expanded pixel.
| Code | Name | Result |
|---|---|---|
0x00 |
BLACKNESS |
0 |
0x55 |
DSTINVERT |
~D |
0x5A |
PATINVERT |
D ^ P |
0x66 |
SRCINVERT |
D ^ S |
0x88 |
SRCAND |
D & S |
0xCC |
SRCCOPY |
S |
0xEE |
SRCPAINT |
D | S |
0xF0 |
PATCOPY |
P |
0xFF |
WHITENESS |
all ones |
The default is 0xCC for COPY and for a color expand. It is 0xF0 for
FILL. A code that is not in this table is reserved. CAPS bit 4 gives the
set of the build: the full set, or the plain copy and fill only.
7.7 Hardware cursor
The cursor is a 64x64 two-plane bitmap. The display path composites it, thus
the CPU does not blit the pointer. The bitmap is in the frame store, as two
planes of 512 bytes. The AND plane is first, and the XOR plane follows at
CURSOR_ADDR + 512. Each plane is 64x64 at 1 bit for each pixel, with 8 bytes
for each row, and the most significant bit first. Thus each pixel has one AND
bit and one XOR bit, and the total is 1024 bytes.
| AND | XOR | Result |
|---|---|---|
| 0 | 0 | Background color (CURSOR_BG) |
| 0 | 1 | Foreground color (CURSOR_FG) |
| 1 | 0 | Transparent. The screen is visible. |
| 1 | 1 | The screen pixel, inverted |
| Offset | Name | Access | Description |
|---|---|---|---|
0x0028 |
CURSOR_CTRL |
R/W | Bit 0 ENABLE. The other bits are reserved. |
0x002C |
CURSOR_ADDR |
R/W | Frame store offset of the 1024-byte cursor bitmap. |
0x0030 |
CURSOR_POS |
R/W | Top-left screen position. Y in bits 31..16, X in bits 15..0. Each value is a signed 16-bit value, thus the cursor can go off the top edge and the left edge. The engine clips the visible part to the screen. |
0x0034 |
CURSOR_FG |
R/W | Foreground color, in the display format. In an 8-bit mode, it is a palette index. |
0x0038 |
CURSOR_BG |
R/W | Background color. |
A move of the pointer is one write to CURSOR_POS for each frame. This is the
purpose of the hardware cursor.
7.8 Video overlay
The overlay is a scaled video window that the engine composites at scanout. The source is a YUV image in the frame store. The engine converts it to RGB with the BT.601 coefficients. It then scales it from the source size to a destination rectangle on the screen. A color key controls the overlay, thus a desktop window can cover it. Use this path for CD video, and keep the color conversion and the scaling off the CPU.
Source formats:
- YUY2: packed 4:2:2, 16 bits for each pixel, in the byte order Y0, U, Y1, V.
- YV12: planar 4:2:0, with an 8-bit Y plane, and then 8-bit V and U planes at half width and half height.
| Offset | Name | Access | Description |
|---|---|---|---|
0x0040 |
OVL_CTRL |
R/W | Bit 0 ENABLE. Bits 2..1 FORMAT (0 YUY2, 1 YV12). Bit 3 KEY_EN. |
0x0044 |
OVL_SRC_Y |
R/W | Frame store offset of the Y plane, or of the packed surface for YUY2. |
0x0048 |
OVL_SRC_PITCH |
R/W | Bytes for each scanline of the Y plane or the packed plane. |
0x004C |
OVL_SRC_DIM |
R/W | Source size. Height in bits 31..16, width in bits 15..0. |
0x0050 |
OVL_SRC_U |
R/W | Frame store offset of the U plane (YV12 only). |
0x0054 |
OVL_SRC_V |
R/W | Frame store offset of the V plane (YV12 only). |
0x0058 |
OVL_DST_XY |
R/W | Destination top-left on the screen (Y:X packed). |
0x005C |
OVL_DST_DIM |
R/W | Destination size. Height in bits 31..16, width in bits 15..0. This is the scaled size on the screen. |
0x0060 |
OVL_COLORKEY |
R/W | With KEY_EN, the overlay appears only where the primary surface is equal to this value. |
In the destination rectangle, the engine samples the source at the destination
size, converts YUV to RGB, and shows the result. With KEY_EN, an application
writes OVL_COLORKEY into its video window, and the overlay is visible there.
Where another window draws over the key, the overlay is not visible. The
engine upsamples the chroma for the 4:2:0 format.
7.9 DMA pusher
The pusher is a bus-master command engine. A driver does not have to write the registers one at a time. It builds a stream of commands in a ring buffer in system memory, and Margo reads the commands and does them. Thus the CPU stays off the bus during a long sequence of operations. This keeps the desktop fast on a slow CPU.
| Offset | Name | Access | Description |
|---|---|---|---|
0x0080 |
PUSH_CTRL |
R/W | Bit 0 ENABLE. |
0x0084 |
PUSH_BASE |
R/W | System physical address of the command ring, aligned to 16 bytes. |
0x0088 |
PUSH_SIZE |
R/W | Ring size in bytes. It must be a power of two. |
0x008C |
PUSH_PUT |
R/W | Byte offset into the ring of the end of the submitted commands. A write to this register is the doorbell that starts the pusher. |
0x0090 |
PUSH_GET |
R | The current read offset of the pusher. It is equal to PUSH_PUT when the ring is empty. |
The ring holds 32-bit words. Each command starts with a header word:
header = (count << 16) | method
method (bits 15..0) is a byte offset into this register block, and it is a
multiple of 4. count (bits 31..16) is the number of data words after the
header. The pusher writes the data words to method, method + 4,
method + 8, and so on. The result is the same as a write of those registers
by the CPU, in the same order. A write to COMMAND (offset 0x0150) through
the pusher starts an operation, as a direct write does.
The pusher moves PUSH_GET past each word that it reads. It returns to the
start of the ring at PUSH_SIZE. It stops when GET reaches PUT. For
separate registers, use one header for each register, with a count of 1. For
a continuous run of registers, use one header.
7.10 Dithering
With CONTROL.DITHER_EN set, Margo applies an ordered 4x4 dither where it
decreases the color precision. There are two such conditions. In the first,
the blit engine writes a color of higher precision into a 15-bit or 16-bit
surface. In the second, the video overlay goes to a 15-bit or 16-bit display.
The dither adds a small quantity of spatial noise, and it removes the bands.
It has no effect on a 32-bit surface, where the precision does not decrease.
8. Coordinates, colors, and bounds
- A point is packed as
(Y << 16) | X. Both values are unsigned 16-bit values, in pixels. - A color is right-justified in the destination pixel format. An 8-bit fill
uses the low 8 bits of
FG_COLOR. A 16-bit fill uses the low 16 bits. A 32-bit fill uses all 32 bits. - The engine operates in the 4 MB frame store. If the source or the destination of an operation is outside the frame store, the engine ignores the operation. It does not wrap the address.
9. Timing and fidelity
The Izarra3000 is an invented machine. This section gives each difference between the emulator and real hardware.
Timing
Margo calculates the result of an operation in one step. It does not simulate
its datapath cycle by cycle. But its register interface is correct. A cost
model gives each operation a duration: a fixed setup time, and then the work
divided by the rated throughput (section 1.1). STATUS.BUSY stays set until
that time is complete. PUSH_GET of the pusher moves through the ring as the
pusher reads the commands.
The result bytes go into the frame store immediately. But software cannot read the engine as idle before the modeled time is complete. The machine clock measures that time.
This document defines Margo, and no measurement of silicon defines it. Thus
the timing is exact by construction: the cost model is the specification, and
the emulator obeys it. Software behaves as it does on the real part. This
includes software that reads BUSY, software that races the engine, and
software that supplies the pusher as a producer to a consumer. This is a
stronger guarantee than the CPU compatibility modes, which give only an
approximation of a real 386 or 486.
One part stays an approximation: the memory contention. An operation in progress uses frame-store bandwidth and host-port bandwidth. That use can stop a CPU access to the same memory. The emulator approximates this effect. It does not model it exactly.
Display scanout
Margo does not scan the frame store out pixel by pixel behind the CPU. It
takes the full visible surface in one step, and shows it. Thus a frame is
atomic. Margo reads each pixel of a frame from the frame store at one moment,
through one palette and one DISP_START. Thus no frame can contain two
display states. There is no incomplete frame, and there is no tearing.
The frame rate controls the moment when the display registers latch. It does
not control the moment when Margo reads the surface. A write to the frame
store is visible in the next frame after the write. Thus a program with a
complete picture has two methods. It can draw into an offscreen surface and
then flip with DISP_START, which latches on the frame boundary (below). Or
it can accept a frame that Margo takes in the middle of the drawing.
This is the specified behavior of the part. It is not an approximation of a more exact behavior. A driver can depend on it. For this reason, the display controller has no register for the position of the beam in the active area.
Three properties follow, and software can depend on all three.
- The frame rate is readable. The vertical retrace interval at
03DAhand03C2hruns at the frame rate of the active mode. That rate is 60.000 Hz in each VBE mode (section 3.1), and the rate of the VGA mode when a VGA mode is active. It is the same clock that moves the frame boundary below. Thus a program that paces on the retrace and flips pages uses one clock, and not two. DISP_STARTtakes effect at a frame boundary. A write toDISP_START, or a4F07hcall withBL=00horBL=80h, queues the new origin. Margo applies it at the next frame boundary, and never before it. Thus the frame in progress does not change, and Margo draws the next frame fully from the new origin.BL=80halso holds the caller until that boundary, thus the origin is active when the call returns. A second queued origin replaces the first one, and only the last one applies. The frame boundary follows the retrace interval in the same blanking period, which is the order that a program expects when it pans during the retrace.- The palette latches one time for each frame. Margo samples the DAC state
one time, when it takes the frame. It decodes the full frame through that
one sample. Thus a palette load cannot put two color sets in one frame.
4F09hwithBL=80halso holds the caller until the frame boundary, thus the load is active for the frame that follows.
Other liberties
- A mode change has an immediate effect. There is no analog settling time, as on a real RAMDAC and monitor.
- The video overlay scales with point sampling. Real silicon interpolated, which gave a smoother scaled image.
10. Distira (3D)
Distira is the second half of VEGA. It is a fixed-function 3D rasterizer, with its own frame buffer, its own texture stores, and a 60 Hz scanout. Margo uses a register interface of its own, and Distira uses a real one. It obeys the same PCI, MMIO, frame buffer, and register contract as the 3dfx Voodoo Graphics generation, the SST-1 chipset. Thus Glide software of the period can find it and drive it, as it drives real Voodoo hardware.
This is a compatibility target, and not a licensed design. It comes from public documentation and from a study of the behavior of that generation of hardware. The method is the clean-room method of the remainder of the Izarra3000.
10.1 The board: BigDistira and SmallDistira
A Distira card has two identical rendering chips. The wiring is the wiring of a Voodoo Graphics board for its 3D chip and its texelFX units. The Izarra lab notes give them the names BigDistira and SmallDistira. These are the two chips on the board. They are not two products. A Distira card always has both chips, and software finds one device with two texture mapping units (TMUs). There is no selection between them, in the same way that a Voodoo Graphics board does not sell its 3D chip and its TMU chip separately.
10.2 Identification and memory
| Item | Value |
|---|---|
| PCI vendor ID | 0x121A |
| PCI device ID | 0x0001 |
| BAR0 size | 16 MB (MMIO and LFB windows in it) |
| MMIO window | 64 KB, register-mapped |
| Framebuffer | 2 MB, dedicated (not shared with the 4 MB frame store of Margo) |
| Texture memory | 2 MB for each TMU |
| TMU count | 2 |
| Native ID register | 0x44540100 ("DT", version 1.00) |
Distira does not share the 4 MB frame store of Margo. It has its own frame
buffer, and its own texture memory for each TMU. A driver reaches them through
the PCI base address register of the board, and not through a fixed physical
range. The driver finds the board with a PCI configuration scan, on ports
0x0CF8 and 0x0CFC. It reads the vendor ID and the device ID above to
confirm the board. It then programs BAR0 to put the MMIO window and the frame
buffer window at the addresses that it wants. This is the same procedure as
for real Voodoo Graphics hardware.
10.3 Register interface
Distira answers the real SST-1 register set, at the offsets that Voodoo
Graphics software expects. The set includes the status register, the vertex
and gradient registers (integer and floating point), triangleCMD and
fTriangleCMD, the pixel pipeline controls (fbzColorPath, fogMode,
alphaMode, fbzMode, lfbMode), the clipping registers, fastfillCMD,
swapbufferCMD, the fbiInit0 to fbiInit7 initialization registers, the
DAC data port, and the texture mode, LOD, base address, and NCC table
registers of each TMU. A real Glide 2.x driver and DOS Glide software program
the same registers directly. Distira has no new API.
Distira also has a small native register block, at MMIO offset 0xF000. It
holds ID, CAPS, STATUS, CONTROL, MODEL, and some frame-buffer
geometry, clear, and command registers. It has the same purpose as the ID
and CAPS pair of Margo. Software that knows the Izarra3000 can confirm the
chip and its capabilities there, and it does not have to read the full SST-1
map.
The pixel pipeline supports the usual linear frame buffer pixel formats: RGB565, RGB555, ARGB1555, RGB888, and ARGB8888. It also supports a combined depth and color LFB write. The rasterizer does the triangle setup and the edge functions. It interpolates the color and the texture coordinates with barycentric coordinates. It does the depth test, the alpha test, the alpha blend, the chroma key, the fog, and the dither. It samples a texture on each TMU, in the LIM formats of DOS Glide 2.x software.
10.4 Software status
The register, PCI, MMIO, LFB, and texture-aperture contracts are complete. The rasterizer draws triangles with depth, alpha, fog, chroma key, and textures. A direct SST-1 test program operates the device from end to end, as a regression check.
The direct DOS Glide path is verified in the game:
- The original Voodoo Graphics executable of Tomb Raider detects Distira and
renders in the game. Its Glide implementation is in the executable. Thus the
emulator supplies no
GLIDE2X.OVL.
The dynamic DOS Glide path is verified with test00.exe, from the 3dfx Glide
2.43 SDK. Without the OVL, the program fails at the DLL load. With a local
Voodoo Graphics GLIDE2X.OVL, it opens Distira at 640x480, renders its
expected frame, and returns exit code 0. The current Carmageddon fixture
renders without an OVL, and it has no LE import modules. Thus it is not
evidence for this path. A dynamic in-game corpus run is not done yet.
IzarraVM does not supply proprietary Glide binaries, and it does not supply game data. A local OVL and a local game are untracked test fixtures.