VOGONS


Reply 60 of 72, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm.... It uses OUT_DX to write the value to the attribute controller.

But afaik, port 3C0 is a port toggled by a 'hidden' flipflop(visible on the VGA though in the upper CRTC register range).

I've implemented it so:
- Port 3C0 switches between index and data mode (first byte written writes index, second byte writes data).
- Port 3C1 is a read-only port for reading the attribute controller register on the VGA. EGA doesn't have this, so it's unimplemented on that.

But the EGA BIOS seems to write the index to port 3C0, then increase DX to point to port 3C1(the OUT_DX function) and then write the value for the port to port 3C1? (Page 122 contains that, near the bottom of page 126 in the PDF)

That clashes with what the VGA documentation says about those ports? Another incompatibility?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 61 of 72, by mkarcher

User metadata
Rank l33t
Rank
l33t
superfury wrote on 2021-06-30, 21:34:
Hmmm.... It uses OUT_DX to write the value to the attribute controller. […]
Show full quote

Hmmm.... It uses OUT_DX to write the value to the attribute controller.

But afaik, port 3C0 is a port toggled by a 'hidden' flipflop(visible on the VGA though in the upper CRTC register range).

I've implemented it so:
- Port 3C0 switches between index and data mode (first byte written writes index, second byte writes data).
- Port 3C1 is a read-only port for reading the attribute controller register on the VGA. EGA doesn't have this, so it's unimplemented on that.

But the EGA BIOS seems to write the index to port 3C0, then increase DX to point to port 3C1(the OUT_DX function) and then write the value for the port to port 3C1? (Page 122 contains that, near the bottom of page 126 in the PDF)

That clashes with what the VGA documentation says about those ports? Another incompatibility?

Exactly. It seems EGA doesn't care about A0 in AC writes, so on EGA, treat writes to 3C1 as-if they were to 3C0. This is likely a bug in the EGA BIOS that got unnoticed as the hardware tolerates the bug.

Reply 62 of 72, by superfury

User metadata
Rank l33t++
Rank
l33t++
mkarcher wrote on 2021-06-30, 21:38:
superfury wrote on 2021-06-30, 21:34:
Hmmm.... It uses OUT_DX to write the value to the attribute controller. […]
Show full quote

Hmmm.... It uses OUT_DX to write the value to the attribute controller.

But afaik, port 3C0 is a port toggled by a 'hidden' flipflop(visible on the VGA though in the upper CRTC register range).

I've implemented it so:
- Port 3C0 switches between index and data mode (first byte written writes index, second byte writes data).
- Port 3C1 is a read-only port for reading the attribute controller register on the VGA. EGA doesn't have this, so it's unimplemented on that.

But the EGA BIOS seems to write the index to port 3C0, then increase DX to point to port 3C1(the OUT_DX function) and then write the value for the port to port 3C1? (Page 122 contains that, near the bottom of page 126 in the PDF)

That clashes with what the VGA documentation says about those ports? Another incompatibility?

Exactly. It seems EGA doesn't care about A0 in AC writes, so on EGA, treat writes to 3C1 as-if they were to 3C0. This is likely a bug in the EGA BIOS that got unnoticed as the hardware tolerates the bug.

I've just implemented that on the EGA only. But I've added an exception to only make it work like that if it's in data mode, not when the EGA is in index mode.

Edit: It reaches C000:0466 now! 😁
I see the call to HOW_BIG at C000:04E0 now!
Edit: At C000:05B1 I then see it write 11b into the EGA/VRAM installed VRAM field (=256KB)! 😁

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 63 of 72, by mkarcher

User metadata
Rank l33t
Rank
l33t
superfury wrote on 2021-06-30, 21:46:

I've just implemented that on the EGA only.

Sounds good so far.

superfury wrote on 2021-06-30, 21:46:

But I've added an exception to only make it work like that if it's in data mode, not when the EGA is in index mode.

This approach is (IMHO) a good idea if you implement some API and have to deal with buggy API clients that do not adhere to the specification. In the case of an EGA emulator, I would consider the original IBM EGA as "the specification". And I'm very confident the original EGA does not limit the aliasing to data mode. I can say that because the AC doesn't know what address is accessed. It just gets one signal (ATRIOW) indicating that an IO write to the / an AC address is currently in progress. This signal is generated by the I/O decoding logic consisting of the PROM U34 and the decoder U25. Whenever /IOW is asserted (i.e. low) and U34 outputs 0, U25 asserts ATRIOW. Obviously, U34 is programmed in a way that 3C1 also maps to 0, but this has to be independent of the current AC flip/flop state.

This whole design with the flip/flop is often explained as "IBM did it to save on I/O addresses", and this explanation admittedly makes zero sense if 3C1 is aliased to 3C0. I assume this explanation is just folklore and wrong, and the real reason is not to conserve I/O addresses, but because IBM was out of pins on the AC. The AC is in a DIP40 package, which is the biggest standard DIP package at that time. There just was no pin left to get A0 to the AC, so we got the flipflop as workaround.

superfury wrote on 2021-06-30, 21:46:

Edit: It reaches C000:0466 now! 😁
I see the call to HOW_BIG at C000:04E0 now!

Congratulations!

Reply 64 of 72, by superfury

User metadata
Rank l33t++
Rank
l33t++

Thanks! I just fired up CheckIt Diagnostics and it reports:

Video RAM Size: 256/512K

So the video RAM is properly detected now at least!

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 65 of 72, by superfury

User metadata
Rank l33t++
Rank
l33t++

Now there's still the issue of some weird colors being displayed (like brown for example) and various display modes somehow getting off-screen pixels they shouldn't (either because of blanking or end of active display)?

Also various whites are actually more light greenish?
And dark gray seems dark greenish?

That greenish color seems to apply to mode 04h, 05h, 0Dh, 0Eh, perhaps 10h, 04h brown, 04h white not quite very white enough.
Then there's mode 0Dh Dk. Gray and Brown, White as well.
The same for mode 0Eh.
Mode 10h looks fine.

That's all the issues that seem to be left?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 66 of 72, by kdr

User metadata
Rank Member
Rank
Member
mkarcher wrote on 2021-06-30, 22:17:

This whole design with the flip/flop is often explained as "IBM did it to save on I/O addresses", and this explanation admittedly makes zero sense if 3C1 is aliased to 3C0. I assume this explanation is just folklore and wrong, and the real reason is not to conserve I/O addresses, but because IBM was out of pins on the AC. The AC is in a DIP40 package, which is the biggest standard DIP package at that time. There just was no pin left to get A0 to the AC, so we got the flipflop as workaround.

Yeah, I've always considered the "ran out of pins" explanation to be the real reason for a lot of the EGA oddities. It turns out to be quite hard to partition the control logic. And that's also the reason for all the various register bits like odd/even mode that need to be kept in sync -- there just aren't any spare input pins available.

The incomplete decoding of the 3C0 address is quite handy, though, because you can do a word-sized I/O to 3C0 to set the index (from AL) and the data (from AH) with a single OUT instruction. Just like you can with the other index/data registers like the CRTC.

Reply 67 of 72, by mkarcher

User metadata
Rank l33t
Rank
l33t
superfury wrote on 2021-06-30, 22:23:

Now there's still the issue of some weird colors being displayed (like brown for example) and various display modes somehow getting off-screen pixels they shouldn't (either because of blanking or end of active display)?

Also various whites are actually more light greenish?
And dark gray seems dark greenish?

I already tried to explain the color stuff:

mkarcher wrote on 2021-06-29, 18:46:

In mode 1, the color values you observe are exactly what is expected. The magic brown correction (brown is #AA5500, although the RGBI pattern looks like #AAAA00) is performed by the monitor. In mode 2, the color values are 0-5, 20, 7, 37h-3Fh. The magic brown correction is done by outputting the correct RGBrbg pattern for #AA5500 (primary red, secondary green, no blue).

In the 200-line modes, the EGA is CGA compatible and outputs 4-bit color as RGBI with I on the pin called "secondary green". Only in 350-line modes, the EGA outputs 6-bit color values. This is why all bright colors (including white) look greenish. You can detect the 4-bit color mode just as the IBM 5154 Enhanced Color Display does: Using the sync polarity. If VSync is negative (misc out bit 7 is set), you have 6-bit color. If VSync is positive (misc out bit 7 is clear), you have 4-bit color.

You decode 4-bit color to 6-bit color by mapping 0-7 as is (with the exception of 6 (brown), which you need to map to 20), and mapping 0x10 to 0x17 to 0x38 to 0x3F.

Reply 68 of 72, by mkarcher

User metadata
Rank l33t
Rank
l33t
kdr wrote on 2021-06-30, 22:29:

Yeah, I've always considered the "ran out of pins" explanation to be the real reason for a lot of the EGA oddities. It turns out to be quite hard to partition the control logic. And that's also the reason for all the various register bits like odd/even mode that need to be kept in sync -- there just aren't any spare input pins available.

Indeed the "out of pins" explanation is quite good for explaining why "global state" needs to be set in each chip individually. But it doesn't explain why odd/even read plane select (3ce, index 5, bit 4) and A0 replacement (3ce, index 6, bit 1) is separated. Modes like chain-4 or odd/even don't really make sense if you don't fix the low address bits.

Reply 69 of 72, by mkarcher

User metadata
Rank l33t
Rank
l33t
mkarcher wrote on 2021-06-27, 20:47:
  • If Misc graphics bit 1 is cleared, always forward CPU A0 to VRAM A0. If Misc Graphics bit 1 is set, (A) use CPU A16 as A0 if Misc Graphics bit 2/3 are both cleared or (B) use Misc Output bit 5 otherwise.

I checked my reference book on that. It states that A0 gets replaced by the inverse of Misc Output bit 5 on both EGA and VGA, if there is no A16 available. So your first attempts to invert this bit were actually right.

Reply 70 of 72, by superfury

User metadata
Rank l33t++
Rank
l33t++

After implementing the polarity support into the DAC handling (for EGA only, before the conversion from 6-bit inputs to 32-bit RGB outputs(which are precalculated when the emulator initializes)), the colors now seem to properly work! 😁

Edit: Interestingly, http://minuszerodegrees.net/video/bios_video_modes.htm seems to confirm the vsync polarities for said modes.

The card seems to be working fully now! 😁

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 71 of 72, by mr.cat

User metadata
Rank Member
Rank
Member

Nice going guys & congrats 👍
I can only do some very limited testing (my hw is mostly on the slow/very slow side, etc.) but yes it looks like it's working now!

EDIT: Also tested with (slightly customized) Bochs BIOS, very nice.
Seems to be quite picky about the timing (may need some experimenting with the cpuspeed line in SETTING.INI).
Re: More extended CPU testsuites like test386.asm?

Reply 72 of 72, by superfury

User metadata
Rank l33t++
Rank
l33t++

I thought I'd post some direct comparing of EGA documentation and VGA bit register incompatibilities I've found by comparing the register descriptions. Nice for emulator authors still working on EGA emulation (that have VGA documentation) and generic stuff I've found out that's not always documented correctly everywhere:

on EGA:
SEQ clocking mode(0x01), bits 4(S4) and S5 (SD) unsupported. bit 1(bandwidth) added.
Character map(0x03) bits 4/5 (character map bits 2) unsupported
Extra note: SLR (bit 2 and S4 on VGA) affects loading of the latches! Usually zeroed, but can be used for multibyte rotation (ROL) of latched data, as proven by demos!
SEQ memory mode Chain 4 unsupported. Extended memory enables MA14/MA15.

CRTC horizontal total (00) is +2 instead of +5.
Extra note: CRTC hotizontal display enable end (01) is the last clock of active display (inclusive).
Extra note: End horizontal blanking register (03), bits 5/6(skew) is added to horizontal display enable end (register 01h) too, affecting both start and end of active display. Is 1 in 40-column modes.
EVRA isn't used on EGA and always active?
End horizontal retrace (05): bits 5-6 are added to retrace start. bit 7 is not End Horizontal Blanking bit 5(4-bit on EGA) and instead added to the memory address for the first pixel of every non-splitscreen (splitscreen being base 0) window scanline address on EGA!
Overflow (07) bit 5 is 'Cursor location bit 8'? It's VGA vertical total bit 9. bits 6-7 unsupported on EGA.
Luckily preset row scan(08) 'byte panning' doesn't exist, preventing conflicts with MA0 being 0/1 for the first pixel.
Maximum scanline register(09) doesn't implement scan doubling (bit 7). bits 5-6 unsupported.
Cursor start(0A) bit 5 unsupported. Perhaps in overflow register(07) bit 5 instead?
Vertical retrace end (11) bit 7 unsupported on EGA. Bit 6 is unused on EGA.
Underline location(14) bits 5/6 don't exist.
End vertical blanking(16) 5-bits (EGA) instead of 7-bits(VGA).
Mode control (17) bit 4 (EGA-only) forces the module 'output drivers' to high-impedance state?

Graphics controller:
Graphics 1 position (3CC w/o) and Graphics 2 position (3CA w/o). 1 must be 0 and 2 must be 1. unknown behaviour of setting. registers are a 2-bit binary number.
Read map select (04) is a 3-bit (EGA) instead of 2-bit(VGA) binary value?
Mode register(05): write mode 3 'Not Valid' on EGA. Real behaviour unknown if used. bit 2 puts outputs in high impedence state on EGA.

Attribute controller:
3C1 writes perform writes to 3C0 on EGA.
- Interesting, EGA documentation swaps bit layout tables of the index registers with the palette (00-0F) registers.
mode control(10): bits 5-7 not implemented on EGA (pixel panning forced as if 0 on EGA?). EGA MONO bit really affects attributes and graphics mode(adds mask 0x05 on top of color plane enable and special C0/C2 behaviour in graphics modes?).
Overscan color(11) only 6-bit on EGA and might work in monochrome monitors (using 0,8,10h,18h for intensities) although adviced zeroed to make it black?
Color plane enable(12) has additional bits 4-5 (video status MUX) on EGA required to POST. This outputs 0 in Input Status 1 without display enable.
Register 14h (color select register) doesn't exist on EGA.

DAC color registers don't exist on EGA.
Misc Output bit 4 on EGA drives color output from the feature connector instead of attribute controller. bit 5(page bit) might be inversed for both EGA and VGA?

Input Status 0 register: bits 5-6 are binary numbers from the feature connector. Their inputs for either FC0 set (lower bits) and FC1 set (higher bits) are loaded into the BIOS byte containing the switches(it's upper 4 bits). The Switch Sense bit number on VGA is obtained from the misc output register Clock Select. On EGA, the switch number (SW1-SW4) is REVERSED, so Clock Select 0 selects SW4 and Clock Select 3 selects SW1. bit 7 on EGA indicates active display(1) or (vertical?) retrace (0)? Is this inversed bit 4 of register 1 or the display enable signal itself? It documents as 'CRT interrupt'. Is this related to vertical retrace end(CRTC 11) bits 4 and 5? Perhaps set by bit 4 and cleared on retrace when bit 5 is set? Drives IRQ (2 or 9 depending on motherboard) inversed?

Input status 1 register: bit 1 indicates light pen trigger set. bit 2 indicates light pen switch is open (not pressed?). Bits 4-5 report video status MUX (see color plane enable register) on EGA, required to POST.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io