VOGONS


First post, 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 against FreeVGA documentation. Nice for emulator authors still working on EGA emulation (that have (Free)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 5 (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.

EGA/(S)VGA counters and latching behaviour details some extra information on the graphics controller shifting registers and it's supposed behaviour on EGA/(S)VGA cards.


Feel free to correct me or specify anything to add to this. I'll modify if more information gets known or discovered!

Last edited by superfury on 2024-02-26, 22:16. Edited 1 time in total.

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

Reply 1 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just have been thinking...
UniPCemu latches pixel shift count and byte panning (which are combined) on vertical retrace end (pixel shift count) and vertical retrace start (byte panning).

Are those even latched? Or always live?
Byte panning btw is counted as pixel shift count addition measured in character clock sizes (8 or 9 pixels multiples).

End horizontal retrace (CRTC 05) bit 7 is also weird? I doubt it's directly added on EGA to the start address registers? Is it used instead of VGA's byte panning register value?

Also found https://forum.vcfed.org/index.php?threads/ega … 3/#post-1366687 , might be a test case?
Edit: Also found (for VGA and SVGA cards): Re: Solved(?): Why does Commander Keen 4-6 hardware scrolling glitch on ATI (Mach) PCI video cards
Getting complicated now...

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

Reply 2 of 20, by GloriousCow

User metadata
Rank Member
Rank
Member
superfury wrote on 2024-02-21, 11:50:
Just have been thinking... UniPCemu latches pixel shift count and byte panning (which are combined) on vertical retrace end (pix […]
Show full quote

Just have been thinking...
UniPCemu latches pixel shift count and byte panning (which are combined) on vertical retrace end (pixel shift count) and vertical retrace start (byte panning).

Are those even latched? Or always live?
Byte panning btw is counted as pixel shift count addition measured in character clock sizes (8 or 9 pixels multiples).

End horizontal retrace (CRTC 05) bit 7 is also weird? I doubt it's directly added on EGA to the start address registers? Is it used instead of VGA's byte panning register value?

Also found https://forum.vcfed.org/index.php?threads/ega … 3/#post-1366687 , might be a test case?
Edit: Also found (for VGA and SVGA cards): Re: Solved(?): Why does Commander Keen 4-6 hardware scrolling glitch on ATI (Mach) PCI video cards
Getting complicated now...

As you can see from that thread on the EGA at least pel panning is not latched, but behavior differs on clones / VGA cards

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 3 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++
GloriousCow wrote on 2024-02-21, 14:31:
superfury wrote on 2024-02-21, 11:50:
Just have been thinking... UniPCemu latches pixel shift count and byte panning (which are combined) on vertical retrace end (pix […]
Show full quote

Just have been thinking...
UniPCemu latches pixel shift count and byte panning (which are combined) on vertical retrace end (pixel shift count) and vertical retrace start (byte panning).

Are those even latched? Or always live?
Byte panning btw is counted as pixel shift count addition measured in character clock sizes (8 or 9 pixels multiples).

End horizontal retrace (CRTC 05) bit 7 is also weird? I doubt it's directly added on EGA to the start address registers? Is it used instead of VGA's byte panning register value?

Also found https://forum.vcfed.org/index.php?threads/ega … 3/#post-1366687 , might be a test case?
Edit: Also found (for VGA and SVGA cards): Re: Solved(?): Why does Commander Keen 4-6 hardware scrolling glitch on ATI (Mach) PCI video cards
Getting complicated now...

As you can see from that thread on the EGA at least pel panning is not latched, but behavior differs on clones / VGA cards

OK. Now UniPCemu does the following:
- Latch byte count and pel panning together always (instead of during start of vretrace (byte panning) and end of vretrace(pixel shift count) that was used until now for each respectively).
- Latch them at horizontal total and new video frame(at vertical total's first clock of the new EGA frame) and use them immediately on said clock. This effectively makes it tick at the start of each scanline, where the latches are used to discard pixels read from VRAM.
- Latch them at start of vertical retrace on MDA/CGA(they're always zero pixels and unused) and VGA and SVGA cards (Tseng ET3000/ET4000AX/W32i)).
- EGA CRTC register bit 5 sets byte panning instead of the documented VGA register.

So EGA has the effect of them being unlatched and VGA/SVGA now latch them during vertical retrace start (UniPCemu's Tseng chips). MDA/CGA have them set to not shift always, so it has no effect.

Edit: OK. MELT gives sets of scanlines that move small bars across the screen?

1807-UniPCemu_EGA_melt_20240221_1719.png
Filename
1807-UniPCemu_EGA_melt_20240221_1719.png
File size
16.5 KiB
Views
901 views
File comment
EGA MELT result
File license
Fair use/fair dealing exception
Filename
1808-UniPCemu_EGA_beveryhillscop_20240221_1719.png
File size
8.77 KiB
Downloads
No downloads
File comment
Bevely Hills Cop screen
File license
Fair use/fair dealing exception

Using the 8088 running at 20MHz there (cycle-accurate mode, with current cycle accuracy of the limited instruction accurate instruction set (above opcode 83h's EU timings is probably inaccurate (still the old timings))).
Edit: Just fixed the PEL shifting of DCR modes (dot clock rate divided by 2) to behave properly (actually shifting 8 double clocks instead of single clocks(which are one half of the dot clock in that case when enabled)).
Edit: And fixing the not-ready state during powerup (when the sequencer is disabled from ticking) fixes the emulator to not hang in such a case anymore.

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

Reply 4 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++

I see that the EGA is skipping pixels from the start of the buffer depending on the current PEL panning. But the wavey effect from the screen capture on the forums isn't there? Only some scanlines being shifted each X scanlines for n lines the same? It's about an NNNNNNNNNNNNNNNNNNNNNNNNNSSSSSSSSSSSS pattern repeating (N being not shifted, S being shifted)? Although I see the skipping moving left and right in the rendered frames the emulator outputs?

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

Reply 5 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm.. Just been thinking... What if I put said pixel panning effect (a copy of said table with the assembly code) into my MDA monochrome mode 0Fh demo? If the EGA pixel panning is operating properly, it should give me a sinus pattern on the screen with those straight vertical lines?

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

Reply 6 of 20, by GloriousCow

User metadata
Rank Member
Rank
Member

melt (game.exe) in MartyPC:

melt_02.gif
Filename
melt_02.gif
File size
1.43 MiB
Views
810 views
File comment
MELT effect in MartyPC
File license
Fair use/fair dealing exception

(click for animated version)

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 7 of 20, by GloriousCow

User metadata
Rank Member
Rank
Member

I implemented pel panning as a fundamental operator of the Attribute Controller. There's nothing to 'latch' per se; when you write a new value to the attribute controller's pel panning register it takes effect immediately. If you maintain a two-character / 16 pixel FIFO, then you can just shift the fifo left by the amount of pel panning. Each character clock the attribute controller serializes 8 pixels (shifted out of fifo, after shift by pel pan) and is loaded with 8 pixels (or 1 char + 1 attribute, in text mode)

code is here:
https://github.com/dbalsom/martypc/blob/565ff … troller.rs#L397

still uncertain of handling of pel panning values > 7 so i am limiting to 7. I still need to play with MOD 0x07 as you suggested. The bit twiddling is because i pack 8 pixels into u64 values and draw a hchar (64 bits) or lchar (64+64bits) at a time, so you're seeing the pixel doubling logic. The FIFO is implemented as a u128; this should probably be done with SIMD but I wanted to get the basics working first

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 8 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++
GloriousCow wrote on 2024-02-22, 18:43:
I implemented pel panning as a fundamental operator of the Attribute Controller. There's nothing to 'latch' per se; when you wr […]
Show full quote

I implemented pel panning as a fundamental operator of the Attribute Controller. There's nothing to 'latch' per se; when you write a new value to the attribute controller's pel panning register it takes effect immediately. If you maintain a two-character / 16 pixel FIFO, then you can just shift the fifo left by the amount of pel panning. Each character clock the attribute controller serializes 8 pixels (shifted out of fifo, after shift by pel pan) and is loaded with 8 pixels (or 1 char + 1 attribute, in text mode)

code is here:
https://github.com/dbalsom/martypc/blob/565ff … troller.rs#L397

still uncertain of handling of pel panning values > 7 so i am limiting to 7. I still need to play with MOD 0x07 as you suggested. The bit twiddling is because i pack 8 pixels into u64 values and draw a hchar (64 bits) or lchar (64+64bits) at a time, so you're seeing the pixel doubling logic. The FIFO is implemented as a u128; this should probably be done with SIMD but I wanted to get the basics working first

What I do is pretty simple right now. Simply perform the first steps until the attribute controller pel panning count times. That pretty much shifts data out of the shift register (which is precalculated when a latch occurs every 8 (or 4 in 8-bit SVGA color modes), 16 or 32 clocks (this is determined as my other thread I made explaining the timings).
It uses MOD 7 in graphics modes (as it's 8 pixels per clock) and above 8 becomes 0 panning in 9 dots modes.
Unknown what happens on SVGA with Tseng's odd character widths (5,6,7,14 and 15 wide text characters). UniPCemu just looks at the one Sequencer register 01 bit to determine PEL panning operation right now.

Edit: First attempt running it failed. Forgot to put the input status 1 register from the demo (which obviously doesn't work yet for some reason) into 3BA instead of 3DA (as it's monochrome mode 😖 ). First try hanged because of that 🤣

One nice thing is that if pixel panning actually works on UniPCemu, I should see the image wobble more easily, as it's simple straight lines vertically accross the screen. It should show a vertical sinus pattern that's used if it works at least. If it doesn't, it's immediately visible that that's not functioning at all. And if the earlier pattern applies again, there's probably something odd going on.

Edit: Ooh! I see it's actually modulating the pixel shift count as it should, every scanline (using the current cycle-accurate 4.77MHz 8088 CPU).

So the modulation itself is working from register pov. I see the precalcs getting updated for rendering.
But the actual rendering, instead of going left to right and back, is caused to become more of a flip-flop toggle it looks like?

1810-UniPCemu_EGA_pixelpanning_flipflopeffect.png
Filename
1810-UniPCemu_EGA_pixelpanning_flipflopeffect.png
File size
1.7 KiB
Views
765 views
File comment
Pixel panning having a flip-flop effect on UniPCemu instead of properly panning pixels somehow?
File license
Fair use/fair dealing exception

Since the modulation of the register is actually working, why does the pixel panning get a flip-flop effect?
It's in graphics mode, so it's mod 7.

Also as a note why the bottom part of the screen isn't continuing the pattern, it's because it's not modifying the pixel panning effect after 200 scanlines (it's rendering 350 scanlines in mode 0F). So the last 150 scanlines are using the panning of the 200th scanline.
One nice thing (a side effect essentially) that this gives is that it clearly displays how the pixel panning is operating in the top and bottom 'window' as it were. The top window that's created uses a normal wave effect on all scanlines that's moving upwards, while the bottom 'window' should instead just wobble parallel lines (the 4 block colors rendered) horizontally from left and right, clearly displaying how the PEL panning (and byte panning on the different register of the EGA) is modifying a scanline if modulated (and not moving a pattern).

The odd thing is that both the vertical pattern and the horizontal pattern are displaying the on/off pattern (either moving right some amount or not moving at all).

That pretty much confirms that the PEL panning isn't operating as it should (like it's being rounded or truncated in some odd way (low bits cleared or something like that)).
Edit: Found a bug in the horizontal rendering timing that was resetting horizontal timing AFTER the pel panning was applied when it shouldn't (thus causing the whole latching to become undone because it resets all horizontal timing related to VRAM, SLR and character counter etc., causing the actual first pixel to restart the horizontal timing like the PEL panning didn't happen!).

Edit: I'm getting the weird pattern on the EGAMELT program too? How is that even possible?

1813-UniPCemu_EGA_EGAMELT_pixelpanningbeingeffective.png
Filename
1813-UniPCemu_EGA_EGAMELT_pixelpanningbeingeffective.png
File size
16.44 KiB
Views
739 views
File comment
EGAMELT on UniPCemu's fixed pixel panning
File license
Fair use/fair dealing exception
Last edited by superfury on 2024-02-22, 21:26. Edited 1 time in total.

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

Reply 9 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++

Finally, I see movement! 😁

1812-UniPCemu_EGA_pixelpanningbeingeffective.png
Filename
1812-UniPCemu_EGA_pixelpanningbeingeffective.png
File size
2.12 KiB
Views
754 views
File comment
EGA pixel panning happening in MODE0F test program.
File license
Fair use/fair dealing exception

And the executable used:

Filename
MODE0F.EXE
File size
6.94 KiB
Downloads
9 downloads
File comment
MODE0F compiled.
File license
Fair use/fair dealing exception

Again, beware, as it's written for mode 0F.

UniPCemu running EGAMELT shows the same vertical pattern oddly enough? It's supposed to be a sinusoidal PEL shift pattern according to the lookup table though (it's like it's inversed or overflowing)?

Edit: Also, the entire horizontal logic (VRAM reloading, SLR, character counter and subcharacter(for shifting out one bit at a time from all 4 planes, or the text font pattern (with unchanging attribute)) is simply processed (so all but CRTC (which drives this instead) and attribute controller (as it's supposed to ignore the pixel inputs for rendering)).
I also see the 32 entries from the table being used on every 32 scanlines, cycling ahead on every frame(by 1 ahead to move it upwards) and the bottom half following the 200th scanline accordingly.
So then, why is it looking like it's clipping (binary AND) the waveform in the rendered image? Flipping my own app's output sideways reveals a clipping-like behaviour (Something like: 0,0,0,0,0,6,7,8,3,4,5,6,5,4,3,8,7,6,0,0,0,0,0 -ish pattern)?

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

Reply 11 of 20, by mkarcher

User metadata
Rank l33t
Rank
l33t
GloriousCow wrote on 2024-02-23, 02:13:

Is Mode F supposed to use the 14Mhz clock?

I didn't intuitively expect it, but it would make sense. The MDA monitor displays 720 active horizontal pixels in Mode 07 at 16.257MHz. If you calculate the number of pixels at 14.318 MHz that take the same time, you get to 634, which is quite close (within 1%) to 640.

Reply 12 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++
mkarcher wrote on 2024-02-23, 02:26:
GloriousCow wrote on 2024-02-23, 02:13:

Is Mode F supposed to use the 14Mhz clock?

I didn't intuitively expect it, but it would make sense. The MDA monitor displays 720 active horizontal pixels in Mode 07 at 16.257MHz. If you calculate the number of pixels at 14.318 MHz that take the same time, you get to 634, which is quite close (within 1%) to 640.

It looks like that is the case?
Mode 7 has Misc Output A6(EGA documentation), so clock #1=16MHz.
Mode F has Misc Output A2(EGA documentation), so clock #0=14MHz.

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

Reply 13 of 20, by GloriousCow

User metadata
Rank Member
Rank
Member

Well, my Mode F needs some work, but I can see a smooth sinus pattern with the pel panning, just like the melt demo.

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 14 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++
GloriousCow wrote on 2024-02-23, 13:48:

Well, my Mode F needs some work, but I can see a smooth sinus pattern with the pel panning, just like the melt demo.

OK. Added some more options to MODE0F.PAS. A 'fastdrawing' option (reduces the screen to one scanline in VRAM by manipulating the offset register, as well as the drawing of course) and a 'specialpattern' option (makes the colors the x coordinate modulo 4 instead). Also made parameters parsed in random order, in order of the parameters supplied overriding each other if that's the case (as well as supporting random order of parameters).

Still would need to test and compile it though.
Edit: Made all effect options configurable as well (a parameter added for the original sine wave effect and even added a second triangle wave effect (which runs at 2 scanlines for each movement for simple table implementation, so 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,7,7,6,6,5,5,4,4,3,3,2,2,1,1,0,0)).

Edit: The executable:

Filename
MODE0F.EXE
File size
7.77 KiB
Downloads
8 downloads
File comment
Latest MODE0F executable.
File license
Fair use/fair dealing exception

The parameter options are now (applied in revers order, if they overwrite one another (for example, the wave pattern to use)):

43-UniPCemu_MODE0F_fastdrawing_specialpattern_trianglewaveeffect_20240224-1309.png
Filename
43-UniPCemu_MODE0F_fastdrawing_specialpattern_trianglewaveeffect_20240224-1309.png
File size
2.72 KiB
Views
524 views
File comment
"MODE0F fastdrawing specialpattern trianglewaveeffect" results inside UniPCemu
File license
Fair use/fair dealing exception

That pattern seems to begin at, what, the second character clock or something like that? It's not shifting correctly at least somehow?

Edit: Added some more functionality, this time a noanimation switch to disable the frames increasing the start position (generating a static image with only static 0-based PEL panning at scanline #0).

Filename
MODE0F.EXE
File size
7.83 KiB
Downloads
9 downloads
File comment
Mode0F latest with noanimation implemented.
File license
Fair use/fair dealing exception

Edit: Hmmm... When comparing the clocks of the rendered image, I see something weird when compating it to the unshifted image (with PEL panning being 0)?
The first 4 rows are actually what happens without PEL panning (correct behaviour). The first 8 pixel clocks are spent reading from VRAM in all cases (skewing the graphics clocks).
Then from scanline 4 and onwards, the PEL panning starts to shift the display. But instead of shifting the display in 8 pixel multiples, it somehow starts with 1 equalling 4, then 2=5, 3=6, 4=7, 5=4, 6=5, 7=6 pixels shifted? So it's having the effect of
"(n&3)+4" pixels shifted somehow?
Also, somehow, with PEL panning, somehow the scanline seems to start 8 pixels earlier?
Edit: Hmmm... Perhaps an issue with pre-display clocks conflicting? That's exactly 4 pixels in graphics modes always.

Btw, one funny thing is on the EGA in monochrome mode as well. It doesn't document anything special about the overscan color register in monochrome graphics modes. So theoretically you can simply set it to 00h, 08h, 10h and 18h to display overscan in various greyscales supported by a MDA monitor (don't know if any software does this though)?

Edit: That fixes the effect! 😁

48-UniPCemu_MODE0F_fastdrawing_specialpattern_trianglewaveeffect_noanimation_20240224-1525.png
Filename
48-UniPCemu_MODE0F_fastdrawing_specialpattern_trianglewaveeffect_noanimation_20240224-1525.png
File size
2.54 KiB
Views
512 views
File comment
"MODE0F fastdrawing specialpattern trianglewaveeffect noanimation" results
File license
Fair use/fair dealing exception

Btw I also modified the MODE0F program to render the sinus and triangle wave until scanline 175 instead of 200 (as it's a 350 scanline screen).
Edit: EGAMELT is running at last! 😁

Attachments

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

Reply 15 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++

UniPCemu's EGAMELT output:

50-UniPCemu_EGAMELT_runningatlast.png
Filename
50-UniPCemu_EGAMELT_runningatlast.png
File size
16.81 KiB
Views
507 views
File comment
EGA MELT is running at last!
File license
Fair use/fair dealing exception

Edit: So does beverly hills cop (CPU changed to 8MHz).

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

Reply 17 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++

There's odd behaviour with the cursor end register though?

After POST, the Cursor End register is zeroed for some odd reason?

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

Reply 18 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just looked a bit more into the EGA/VGA blink bit in graphics modes.

Apparently, when plane 3 is 0 in 4-bit graphics modes, the top bit (bit 3) is set for the LUT lookup?
So it forces the foreground and background bit 3 to be 1 instead of the simple masked 0 (according to Lotus 1-2-3 2.3)?

https://github.com/86Box/86Box/pull/3845

UniPCemu still leaves it zero right now though.
Edit: Forced the bit 3 to become 1 when blinking isn't enabled on a graphics pixel that has blinking enabled in the attribute controller mode control register.

So the new logic of EGA attribute controller processing is:

UniPCemu's EGA/VGA New attribute controller pixel processing
OPTINLINE byte getattributeback(byte textmodeshift, byte attr,byte filter)
{
//Only during text mode: shift!
attr >>= textmodeshift; //Shift high nibble to low nibble with text mode!
attr &= filter; //Apply filter!
return attr; //Need attribute registers below used!
}
byte pixelon, charinnery, currentblink;
word Attribute; //This changes!

byte color256;
color256 = GETBITS(VGA->registers->AttributeControllerRegisters.REGISTERS.ATTRIBUTEMODECONTROLREGISTER,6,1); //8-bit colors?

byte enableblink;
enableblink = GETBITS(VGA->registers->AttributeControllerRegisters.REGISTERS.ATTRIBUTEMODECONTROLREGISTER,3,1); //Enable blink?

byte enableblink2;

byte underlinelocation;
underlinelocation = GETBITS(VGA->registers->CRTControllerRegisters.REGISTERS.UNDERLINELOCATIONREGISTER,0,0x1F); //Underline location is the value desired minus 1!

byte textmode;
textmode = (GETBITS(VGA->registers->AttributeControllerRegisters.REGISTERS.ATTRIBUTEMODECONTROLREGISTER, 0, 1) == 0); //Are we in text mode?

byte textmodeshift;
textmodeshift = (GETBITS(VGA->registers->AttributeControllerRegisters.REGISTERS.ATTRIBUTEMODECONTROLREGISTER,0,1)==0)?4:0; //Text mode? Also the number of bits to shift to get the high nibble, if used!

byte monomode;
monomode = GETBITS(VGA->registers->AttributeControllerRegisters.REGISTERS.ATTRIBUTEMODECONTROLREGISTER,1,1); //Monochrome emulation mode(attribute) with b/w emulation(misc output)?

byte graphicsforced;
byte effectiveattr;
byte fontstatus;
byte paletteenable=0;
byte palette54=0; //palette 5-4 used?
byte colorselect54=0; //Color select bits 5-4!
byte colorselect76=0; //Color select bits 7-6!
byte backgroundfilter=0,effectivebackgroundfilter;
byte VGADisabled = 0;
byte palettecopy[0x10];

paletteenable = GETBITS(VGA->registers->CRTControllerRegisters.REGISTERS.ATTRIBUTECONTROLLERTOGGLEREGISTER,5,1); //Internal palette enabled?
INLINEREGISTER byte CurrentDAC; //Current DAC to use!
if (paletteenable) //Precalcs for palette?
{
for (CurrentDAC = 0;CurrentDAC < 0x10;++CurrentDAC) //Copy the palette internally for fast reference!
{
palettecopy[CurrentDAC] = GETBITS(VGA->registers->AttributeControllerRegisters.REGISTERS.PALETTEREGISTERS[CurrentDAC],0,0x3F); //Translate base index into DAC Base index!
}
palette54 = GETBITS(VGA->registers->AttributeControllerRegisters.REGISTERS.ATTRIBUTEMODECONTROLREGISTER,7,1); //Use palette bits 5-4?
if (palette54) //Use palette bits 5-4?
{
colorselect54 = VGA->precalcs.colorselect54; //Retrieve pallete bits 5-4!
}
colorselect76 = VGA->precalcs.colorselect76; //Retrieve pallete bits 7-6!
}
paletteenable &= ((VGA->precalcs.BypassPalette)?0:1); //Bypass the palette if needed!

backgroundfilter = ((~(enableblink<<3))&0xF); //Background filter depends on blink & full background when not in monochrome mode!

Show last 136 lines
	INLINEREGISTER byte colorplanes;
colorplanes = VGA->registers->AttributeControllerRegisters.REGISTERS.COLORPLANEENABLEREGISTER; //Read colorplane 256-color!
colorplanes &= 0xF; //Only 4 bits can be used!

INLINEREGISTER word pos;
INLINEREGISTER word pos2;

for (pixelon=0;pixelon<2;++pixelon) //All values of pixelon!
{
for (currentblink=0;currentblink<2;++currentblink) //All values of currentblink!
{
for (charinnery=0;charinnery<0x20;++charinnery)
{
//Take the
pos2 = charinnery; //Set!
pos2 <<= 1; //Create room!
pos2 |= currentblink; //Add!
pos2 <<= 1; //Create room!
pos2 |= pixelon; //Add!

for (Attribute=0;Attribute<0x100;++Attribute)
{
fontstatus = pixelon; //What font status? By default this is the font/back status!

enableblink2 = enableblink; //Local copy for processing!

graphicsforced = 0; //Default behaviour!

effectiveattr = Attribute; //Default: effective attribute!
effectivebackgroundfilter = backgroundfilter; //Default: effective background filter!
//Underline(text mode)&Off capability!
if (unlikely(monomode)) //Only in mono mode do we have underline capability and other stuff!
{
if (likely(textmode)) //This is active in text mode only!
{
if (unlikely(charinnery == underlinelocation)) //Underline (Non-graphics monochrome mode only)? Ignore textmode?
{
if (unlikely((Attribute & 7) == 1)) //Underline used for this character? Bits 6-4=0(not according to seasip.info/VintagePC/mda.html, so ignore that fact!) and 2-0=1 only according to freeVGA!
{
fontstatus = 1; //Force font color for underline WHEN FONT ON (either <blink enabled and blink ON> or <blink disabled>)!
}
}
if (unlikely((Attribute & 0x77) == 0)) //Are we always displayed as background (values 0, 8, 0x80 and 0x88)?
{
fontstatus = 0; //Force background!
}
if ((Attribute & 0xF0) && ((Attribute & 0x77) != 0x70)) //Background set and not inversed?
{
effectiveattr &= 0xF; //Mask off any background bits!
}
if (((Attribute & 0x77) != 0x70)) //Not inversed?
{
effectivebackgroundfilter &= 7; //Never include the blink bit!
if ((Attribute & 0x7) == 0) //Font black?
{
effectiveattr |= 1; //Use font color 1 for example?
}
}
}
else //Monochrome Graphics mode (EGA+ only case)?
{
//Special behaviour! Planes 1/3 are masked off. Planes 0/2 being 0/1 respectively enables blinking.
fontstatus = 1; //Default: always font to mask properly!
effectiveattr &= 0x55; //Planes 1/3 are always masked off (undocumented EGA behaviour)!
enableblink2 = (enableblink ? (((effectiveattr&5)==4)?2:3) : 3); //Enable blinking or forced behaviour!
}
}
else if (!textmode) //Graphics mode?
{
fontstatus = 1; //Ignore font input by default!
}

//Blinking capability! Applies to the font/background only!
if (likely(enableblink2)) //Blink affects font?
{
if (unlikely(((getattributeback(textmodeshift,(byte)Attribute,0x8) && ((enableblink2&2)==0))) || (enableblink2==2))) //Blink enabled?
{
fontstatus &= currentblink; //Need blink on to show foreground!
}
else if (!(monomode | textmode)) //Non-blink bit behaviour in graphics mode is bit 3 forced set for the lookup?
{
graphicsforced = 8; //Force the bit plane high!
}
}

//Determine pixel font or back color to PAL index!
if (unlikely(fontstatus))
{
CurrentDAC = (byte)effectiveattr; //Load attribute!
}
else
{
CurrentDAC = getattributeback(textmodeshift,(byte)effectiveattr,effectivebackgroundfilter); //Back!
}

CurrentDAC &= colorplanes; //Apply color planes(4-bits)!
CurrentDAC |= graphicsforced; //Forced bits high?

if ((enableblink2 == 2) && (fontstatus)) //Blinking forced bit 3 in the lookup on?
{
CurrentDAC |= 8; //High plane: blink on!
}

if (unlikely(paletteenable==0)) goto skippalette; //Internal palette enable?
//Use original 16 color palette!
CurrentDAC = palettecopy[CurrentDAC]; //Translate base index into DAC Base index!

if (unlikely(VGADisabled)) goto skippalette; //Are we not on a CGA? Skip the further lookup!
if (unlikely(color256)) //8-bit colors and not monochrome mode?
{
CurrentDAC &= 0xF; //Take 4 bits only!
}
else //Process fully to a DAC index!
{
//First, bit 4&5 processing if needed!
if (palette54) //Bit 4&5 map to the C45 field of the Color Select Register, determined by bit 7?
{
CurrentDAC &= ~0x30; //Clear bits 5-4!
CurrentDAC |= colorselect54; //Use them as 4th&5th bit!
}
//Else: already 6 bits wide fully!
CurrentDAC &= 0x3F; //Clear the high 2 bits for inserting the selected base!
//Finally, bit 6&7 always processing!
CurrentDAC |= colorselect76; //Apply bits 6&7!
}

skippalette:
pos = Attribute;
pos <<= 7; //Create room for the global data!
pos |= pos2; //Apply charinner_y, currentblink and pixelon!
//attribute,charinnery,currentblink,pixelon: 8,5,1,1: Less shifting at a time=More speed!
attributeprecalcs[pos] = CurrentDAC; //Our result for this combination!
}
}
}
}

(code unused for CGA/MDA clipped out), VGA->precalcs.BypassPalette is usually 0 for normal EGA/VGA operation (used in some SVGA chips, like the Tseng chips extensions).

The attributeprecalcs variable is basically a lookup table of all input signals and output signals of the attribute controller for any color lookup (the 8-bit/16-bit accumulation shifts etc. is performed after this step). It's inputs are the Attribute(from text mode or graphics pixel), charinner_y(the scanline within the character), currentblink(the current blinking status of the rendering frame) and pixelon(foreground or background pixel in text modes, always 1 in graphics modes).
The lookup table is 32768 bytes large.

GETBITS(x,shift,mask) shifts x to bit 0 and applies mask using an AND operation (basically ((x>>shift)&mask)).

Edit: Lotus 1-2-3 r2.3 now behaves as expected in WYSIWYG mode 😁
(It uses 16-color graphics with blinking bit)

It matches the video now (https://youtu.be/jHUaneVUkfQ)!

I'm getting (as in the video)
(text mode -> graphics mode)
light gray (difficult to see on the video, but probably the case there as well?) on blue -> cyan on blue
black on cyan -> black on cyan
active: cyan, black cursor
inactive: light gray

Another thing that happens is that text that's in a selected text box becomes red in the video (@9:47). The same happens in UniPCemu now!

Nice test case for other emulators as well btw 😉 !

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

Reply 19 of 20, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. After checking some documentation on SVGA cards wrt the vertical retrace interrupt, I found that it seems that only bit 5 of the vertical retrace end register blocks IRQs. Bit 4 only seems to exist to detect 0 being written to it to clear the IRQ.
Interrupt Status #0 register bit 7 reads the value of the IRQ line.

So writing 1 to bit 4 doesn't have any effect, other than not counting as a 0 write to clear the IRQ. It doesn't block vertical retrace IRQs from the graphics card.

In fact, setting bit 4 to 1 isn't documented at all by the EGA or W32i documentation at all to have any effect?

Edit: And once again, FLAND leaves the flipflop set for some odd reason?

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