reenigne wrote on 2020-03-12, 14:08:
superfury wrote on 2020-03-12, 09:59:
Just found out something: CGA applies the memory write waitstates when updating the memory mode(changing mapped memory layout)? So when updating the memory with the new layout(due to changing VGA memory mapping it uses) it sets the waitstate for the current instruction(which it shouldn't)!
Not sure what you mean by this. The CGA memory wait states are the same for all modes. There are no additional wait states for CGA port writes, only the one imposed by the motherboard.
Well, that was one of UniPCemu's issues. When software would write the CGA ports to change the memory mapping for rendering(e.g. switching the memory mode by writing the CGA mode control register with a new mode), chainging bit 2,4,5 to switch to 2-color, 4-color or text mode(and being in a different mode of those 3 previously), it would trigger UniPCemu to rewrite the CGA/MDA shadow RAM(which it keeps for any writes to the CGA memory addresses) back to the VRAM, effectively moving the current bytes of the CGA RAM to their VGA-compatible locations(which are used with the selected mode).
Using said shadow RAM for reads makes sure that the reads and writes to CGA/MDA RAM behave as expected on a CGA/MDA card. Otherwise, the memory would leave the old values in their VGA-compatible places, messing up the entire CGA emulation.
The issue with said remapping lied with the way it would trigger the CPU(writing the shadow RAM to real VRAM) into using the CGA waitstates(wait for 8 dots, next lchar(16 dots period), next CPU cycle) in a semi-HLT state(actually a HLT state with a special meaning, effectively acting as a delay to the CPU's EU and BIU). It was only supposed to do that for memory accesses(reads and writes), not for the updating of CGA memory(by writing to the mode control register).
From your own blog: https://www.reenigne.org/blog/the-cga-wait-states/
UniPCemu just was applying that not only to CGA memory accesses(which is correct) but also to the mode control register being written with a new mode which changes the memory layout when compared to VGA adapter settings(because it's in actuality still keeping a VGA-based system in the background for it's rendering. It just has some modifications making it act like a CGA/MDA instead of a VGA(although lots of VGA registers are still used in the background to handle things like memory mapping, some rendering parameters etc.)).
You can see it actually working out CGA to VGA mapping values in the VGA registers at https://bitbucket.org/superfury/unipcemu/src/ … a/vga_cga_mda.c applyCGAmodecontrol function, applyCGAPaletteRegister function for CGA, and the applyMDAModeControl for MDA. Those write special values into the VGA's registers(most of them are actually still used during rendering) compatible with the CGA.
Mostly the only thing that changes with the CGA compared to the newer video cards(EGA and up) is the way it handles some translations between the CGA registers to the VGA registers(mostly for memory writes, reads use the shadowed VRAM instead), writes applying to the shadow VRAM as well, and various rendering parameters using the VGA's precalcs and some VGA registers unchanged.