VOGONS


Reply 20 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

This is what Windows 3.0 setup gives with 640x480x256 colors:

212-Windows3.0setup-640x480x256col.png

It even more wrong than with normal Windows 3.0 booting. Anyone can see what happens here?

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

Reply 21 of 36, by Scali

User metadata
Rank l33t
Rank
l33t

Well, for starters... are you getting the same CRTC values for 640x480 in 256 colour mode as you do for 640x480 in 16-colour mode?
It's really weird to see you have two 'overlapping' screens on the right side, and nothing on the left.
I would expect the display timings to be the same regardless of the colour modes.
The only difference should be in where and how it fetches the pixel data.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 22 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

Scali, in theory, you should be correct.

I now notice that, every 8 pixel clocks, the next plane address (ranging from 0-64K, with each entry being 4 bytes of VRAM) is fetched. So every 8 pixels, a DWORD is fetched from VRAM(all 4 planes), seperated in 8 'pixels'(8 4-bit values), Every block is right after the previous block(4 bytes later in linear VRAM, due to byte mode being set). The only problem is that my emulation is hardcoded to apply one character clock once every 8 pixels. But in graphics modes this might be less? 8 pixels in 16-color mode, 4 in 8-bit mode, 2 in 16-bit mode?
How should my emulation divide those 8 pixels down to 4(8-bit color) or 2(16-bit color)? What should make this effect happen?

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

Reply 23 of 36, by Scali

User metadata
Rank l33t
Rank
l33t

Well, some things...
VGA actually supports two different pixel clocks, 25 MHz and 28 MHz, some SVGAs have even more. So you need to make sure you emulate the correct clock for starters.
The video circuit will have a clock divider which converts the pixel clock to a character clock. VGA can use either a divisor of 8 pixels (graphics) or 9 pixels (textmode).

Anyway, I would expect that all that stuff is the same in 16-colour and 256-colour mode, and the difference is in how a pixel is addressed and fetched.
So if your character clock-related code works correctly for one mode, I expect it to work correctly for another. You have the same amount of pixels per scanline and per frame. The format of the pixels is just different.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 24 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

So every character clock(this should already work correctly, although in the 640x480x256 mode each width is doubled due to the Attribute Controller register 16's setting.

When using planar 1-bit(4 bits fetched from each plane), the pixel results in 8 pixels per character clock, with one increase in memory each character clock(thus linearly addressing 4-bit pixels as supposed to do).

But in 256-color mode the same happens(each 8 pixels), but only 4 pixels are given, the other four aren't fetched until the next character clock(this would require a total of 64 bits, while only 32 bits are fetched each character clock). What is the correct way to handle this? And that doesn't even consider 128 bits(with 16-bits pixels in 64K color mode, theoretically already supported by the DAC emulation, based on the two bytes of data given each pixel clock tick) or 256 bits(in 32-bit RGBA mode, although this one is a different DAC).

What is the correct way to do this?

Sequencer/CRTC operation: https://bitbucket.org/superfury/x86emu/src/78 … cer.c?at=master
Graphic mode taking data apart(32-bits always, so a byte for each plane): https://bitbucket.org/superfury/x86emu/src/78 … ode.c?at=master
Attribute controller using the data the graphics/text mode takes apart to form pixels: https://bitbucket.org/superfury/x86emu/src/78 … ler.c?at=master
Finally the DAC takes the pixels formed by one(4-bit), two(8-bit) or four(16-bit) pixel clock cycles from the attribute controller and places a dot with the specified color on the screen. It also might(when set up like the Sierra Hi-color DAC) do part of the attribute controller's job and combine two pixel clock to two pixels of the same color(two 4-bit cycles giving two same 8-bit pixels(VGA-like DAC mode using the 256-entry DAC lookup) or two 8-bit cycles giving one 16-bit pixel from one of the two hardcoded 5:6:5 or 5:5:5 16-bit RGB lookup tables).

As for why the left half of the display is black, I don't know.

Each row seems to increase the row start position with 0x100. So 0x100*4=0x400(1024 bytes) of memory is consumed in byte mode for each row. Each block retrieved is 4 bytes further in VRAM(byte mode). So it's in fact linearly addressing VRAM. I only don't get why active display starts on the right half of the screen?

vga_vram_640x480x256col.zip

The same VRAM rendered through the DAC and directly dumped using the offset register as it's row offset:

VGA256col.png

I notice that I get the clearest (but still invalid) result when I dump the VRAM, with 4 times as much offset between rows:

		uint_32 *pixels = (uint_32 *)zalloc(((480*8192)<<2),"BMPDATA",NULL); //To draw our bitmap on!
int x,y;
for (y = 0;y<480;)
{
for (x = 0;x < 640;)
{
pixels[(y<<12)+x] = getActiveVGA()->precalcs.effectiveDAC[getActiveVGA()->VRAM[((y<<12)+x)&(getActiveVGA()->VRAM_size-1)]]; //Linear VRAM assumed, converted through DAC to a color!
++x; //Next pixel!
}
++y; //Next row!
}
writeBMP("captures/VGA256col",pixels,640,480,0,0,2048); //Dump the VRAM direct to test!
freez(&pixels, (480 *8192) << 2,"BMPDATA"); //Release the temporary data!

This results in:

VGA256col-PlanarOffset4.png

So the problem isn't just in the renderer? There's a problem putting pixels in VRAM(CPU memory window) too?

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

Reply 25 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

Switching the code to even larger quantities reveals even more:

		uint_32 *pixels = (uint_32 *)zalloc(((480*8192)<<2),"BMPDATA",NULL); //To draw our bitmap on!
int x,y;
for (y = 0;y<480;)
{
for (x = 0;x < 8192;)
{
pixels[(y<<12)+x] = getActiveVGA()->precalcs.effectiveDAC[getActiveVGA()->VRAM[((y<<12)+x)&(getActiveVGA()->VRAM_size-1)]]; //Linear VRAM assumed, converted through DAC to a color!
++x; //Next pixel!
}
++y; //Next row!
}
writeBMP("captures/VGA256col",pixels,1<<12,480,0,0,1<<12); //Dump the VRAM direct to test!
freez(&pixels, 480 * (getActiveVGA()->precalcs.rowsize << 2) << 2,"BMPDATA"); //Release the temporary data!
VGA256col-PlanarOffsetX4-640x480_readas8192x480_with4096bytesperrow.png

Edit: Just realized something: I was assuming that the 64K/128K/1M modes actually are extra bits added to the PLANAR VRAM OFFSET (each planar index(range 0x0000-0xFFFF) being added 3(ET3000) or 4(ET4000) extra bits). But when doing so, you would access 256K(the 16-bit address addressed)*16(ET4000)=4MB of RAM, instead of the 1MB RAM the card has. The same applies to 2MB RAM and 512KB RAM in the case of the ET3000.
So changing the offset to add to the actual VRAM location (or simply put, shifting the current value left with 2 bits less than is currently done and convert the OR-operations(|) adding it the offset to additions (+). That should fix the problem with not enough RAM being available, and thus address the correct 512K(ET3000) and 1M(ET4000) RAM.

Edit: Seems this isn't the only problem? Probably the AND ~3 used in the ET3000/ET4000 is simply a shift to the right with 2 bits?

Edit: It seems this isn't the cause. I'm still trying to compare the
https://ia801004.us.archive.org/BookReader/Bo … ale=16&rotate=0

document and the normal VGA memory addressing my emulator uses and draw a valid conclusion. Or are the two incompatible? When is that 'Linear Graphics'(LG) mode activated? Is A0&A1 simply the plane? (32-bit integer pointer offset)

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

Reply 26 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

After looking at the document again, I seem to notice that the 00 values actually are the DWORD memory pointer offset(which is why bits 0-1 are always 0 when DWORD-aligned). I just don't understand why the data in the VRAM when using the 640x480x256colors gives such messed up VRAM? It should be writing the data as linear bytes to memory when writing to A0000-AFFFF(planar chained mode, which the offset shifted right by 2 bits to make memory linear). Register 0x3CD then, when accessing VRAM, selects the 64K VRAM to start at (so A0000 becomes VRAM 0, A0001 becomes VRAM 1, A00002 becomes VRAM 2, A0003 becomes VRAM 3, A0004 becomes VRAM 4 until AFFFF becomes VRAM FFFF(all when having 0x3CD set to 0x00). When setting 0x3CD to 0x11(On the ET4000, which uses 4-bit 64k banks instead of the 3-bits banks of the ET3000), A0000 maps to VRAM 10000, A0001 maps to VRAM 10001 etc.

Is this correct?

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

Reply 27 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

One little problem now: SInce i've worked on the ET3000/ET4000 emulation, it seems to have broken the CGA emulation(which was about perfect afaik). Now 8088MPH shows several screens twice vertically(one good copy and one bad copy at the bottom). Also the scrolling vertical text seems to scroll off the top of the screen now.

Scali? Reenigne?

I think it still worked one week ago (commit c6a5cfd, the last commit of 2016/06/10). I have changed some things for better compatibility with the SVGA/VGA, but it appears some of them have broken the CGA emulation?

Edit: Confirmed still working at commit 6144117 (2016/06/12).

Edit: After returning to the current commit from 2016/06/16 1:54(which somehow seems to introduce the bug), I think it might have something to do with the offset between scanlines?

Edit: The bugs have been fixed: The way the byte mode affected the new row offset(compared to the previous row, VGA CRTC register 13h), Start address(index 0xC and 0xD) and cursor location (index 0xE and 0xF) all needed to be shifted left ONLY when the VGA is in byte mode(to apply CGA timings to the VGA modes, which count in byte instead of words, like the CGA does). There also was an error in applying the clock shift to the cursor location(shifting it up on the screen). This has been removed(as this is usually done when rendering only. as It doesn't affect the address pointed to(the character in VRAM).
8088 MPH works without problems now again.

Windows 3.0 in 256 colors still seems to fail though:(
Anyone can see what's going wrong?

The entire VGA/CGA/SVGA(ET3000/ET4000) emulation:
https://bitbucket.org/superfury/x86emu/src/6f … /vga/?at=master

Edit: It seems even the normal VGA games on the ET3000 (Tested with Ultima 6) go wrong on the ET3000, while working on the normal VGA emulation:

213.png
Ultima6_VGA_x86EMU.zip
214.png
Ultima6_ET3000_x86EMU.zip

Edit: The updated source code of the above images and files, with et4000.h/c renamed to tseng.h/c(Since it's not purely the Tseng ET4000 graphics card being emulated).

https://bitbucket.org/superfury/x86emu/src/ad … /vga/?at=master

Anyone can see what's going wrong here? Is the VRAM itself incorrect? Or is the rendering incorrect?

Within the .zip files:
VGA_ATT.bmp, VGA_DAC.bmp: Full dump of the two palettes (Attributes and DAC 256-color table).
vga_*regs.dat: A direct dump of the VGA registers themselves.
VGA256col.bmp: A direct dump of the VRAM(linear graphics assumed) using the offset between rows from the VGA precalculations and each pixel next to each other without padding in VRAM(for comparison).
VRAMtext.bmp: A dump of VGA plane 2 text graphic data in text mode(each bit being pixel on/off for that font).
vga_vram.dat: A full dump of the entire VRAM(256K used for VGA, 512K for ET3000/ET4000(Tseng)).

Anyone can see what's going wrong?

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

Reply 28 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

I seem to have fixed the mode 13h in both the VGA and ET3000:
The PLANAR offset of the CPU VRAM access is always shifted right by 2 bits(instead of ANDing with 0xFFFC/0xFFFD(according to osdev documentation, which my emulation is based off). This makes VRAM access linear, just like the ET3000/ET4000 do.
The Byte/Word/Doubleword modes aren't shifts left by 0(byte), 1(word) or 2(doubleword) bytes, but are instead the reverse (2 in byte mode(skipping 3 doublewords each fetch for rendering), 1 in word mode(unchanged, skipping 1 doubleword each fetch for rendering) and 0 in doubleword mode(accessing entire Doubleword addresses).

With these changes implemented, the mode 13h works without problems in both VGA(with doubleword mode) and ET3000(with byte mode).

Edit: For some reason the game Prehistorik fails rendering correctly: It now does the same what Ultima VI did on it's doubleword mode?

Anyone can tell me the exact effect the byte/word/dword mode has on the CPU VRAM address and the rendering VRAM address?

Edit: It seems all normal modes now work on VGA and ET3000(and thus ET4000). Somehow mode 2Eh(640x480x256) still messes up it's output. Maybe there's a problem with banked RAM?

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

Reply 29 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

Anyone can explain to me the effect of the entire 0x3CD (memory bank) register? Do, on the ET3000 and/or ET4000, the lower 3(ET3000) or 4(ET4000) always select a 64K bank in VRAM to address? What is the effect of bits 6-7 on the ET3000? Does it multiply the bank address with 2(ET3000, when bits 6-7=00b) or 4(ET3000, when bits 6-7=10b)?

In my case, it's 1(64K) most of the time during the Windows 3.0 setup(when entering the 640x480x256colors graphics mode) when moving the mouse. VRAM, unfortunately, is still messed up.

Edit: Just improved the emulation a bit. It will now (when running the test routine in the emulator itself) generate an almost correct image. I see the colors (just like the mode 13h test) on the screen, it just has black bars between the colors(it prints a simple calibration pattern and color wheel. The colors from left to right, in the horizontal center a vertical line with the same colors as horizontally, but a line displaying those colors vertically) and a white line in the vertical center.

Mode 13h(320x200x256):

216.png

Mode 2Eh(640x480x256):

217.png

Edit: Looking at the dumped VRAM, the image shown in 217.png(640x480x256) does have it's complete VRAM area (0x00000-0x4AFFF) filled with the correct data. So there's a problem in loading and displaying the data itself now?

Edit: Just made a little dump of the VRAM converted to active display manually using the offset register, as the Dosbox interrupt 10h handler set it up:

VGA256col.png

It looks like something's going wrong here? So either the active display is incorrect, or the Dosbox code is? I've modified the Dosbox SVN code to support the banked VRAM:

        case M_LIN8:
rowoffs = (y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8)+x; //The offset to retrieve!
//Translate the offset to a bank number&offset if needed
if (svgaCard==SVGA_TsengET4K) //ET4K?
{
curbank = IO_Read(0x3CD); //Read the current bank!
curbank &= 0xF; //Clear read bank!
curbank |= (rowoffs >> 12) & 0xF0; //The bank to use!
rowoffs &= 0xFFFF; //Pixel in the bank!
IO_Write(0x3CD, curbank); //Set the new bank!
}
else if (svgaCard==SVGA_TsengET3K) //ET3K?
{
curbank = IO_Read(0x3CD); //Read the current bank!
curbank &= 0x7; //Clear read bank!
curbank |= (rowoffs >> 13) & 0x38; //The bank to use!
curbank |= 0x40; //64k bank!
rowoffs &= 0xFFFF; //Pixel in the bank!
IO_Write(0x3CD, curbank); //Set the new bank!
}
RealPt off=RealMake(0xA000,rowoffs); //Pointer to memory!
*color = mem_readb(off);
break;

Is this even correct? It should write the data directly to linear display, with (as far as I can make out from the data in VRAM itself) 640 pixels with no virtual width added(so the offset register is 0x50, meaning 640 virtual pixels per line, since offset times 2 times 4 planes=640 pixels).

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

Reply 30 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

I know I'm repetitive, but I need to know. How are all VGA clocks and divisions executed? How are they used/increased, starting at the top: The Master Clock(MCLK).

So, quoting from the http://www.osdever.net/FreeVGA/vga/crtcreg.htm documentation:

I know that in the ET4000(and partly also the VGA, since it's an extension of it), there's the Master clock(MCLK) running at (in the case of the VGA) 25MHz or 28MHz.
The master clock can be divided by the Dot Clock Rate bit in the Sequencer Clocking Mode register? This somehow affects output?

Anyone can explain to me, how the following clocks/counters relate to each other(taken from the descriptions in the FreeVGA CRTC registers). When is each one ticked or increased compared to the Master Clock? I know that I have part of them implemented already, but I want a clear picture of how each and every one of them relate to each other, running in parallel or simply divide parts further before having effect.

memory address counter address counter vertical timing counter horizontal retrace clock character clock vertical counter row sca […]
Show full quote

memory address counter
address counter
vertical timing counter
horizontal retrace clock
character clock
vertical counter
row scan counter
dot clock

Anyone can explain these terms to me and how they affect display and output sent from display memory/timings to the DAC(which then can chain multiple pixels together in the case of 8-bit, 16-bit or 32-bit pixels when the DAC supports it(always linear and 8-bit input in the case of the VGA DAC, two 4-bit clocks, two 8-bit clocks, one 8-bit clock or 16-bit clock in the case Sierra Hi-color DAC).

Anyone????

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

Reply 31 of 36, by Jo22

User metadata
Rank l33t++
Rank
l33t++

Sorry for the late response. I'm quite busy this week..
If you would send me a little test program, I could setup a PC with a real ET3000 in the next days (maybe weekend ?).
It's been a while since i toyed around with VGA stuff (no idea if a simple port write to $3CD is sufficienct).

"Time, it seems, doesn't flow. For some it's fast, for some it's slow.
In what to one race is no time at all, another race can rise and fall..." - The Minstrel

//My video channel//

Reply 32 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

I'd love to, but atm I don't know how all those rendering stuff relates/combines, let alone write a test program that's based on that. Anyone has a good source that explains how all the timing in a (S)VGA relates to each other(ET3000/ET4000)?

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

Reply 33 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

Can you make me a dump of all VGA and ET3000 registers of mode 13h and 2Eh? That way I can at least compare it's registers with my emulation without having to fear for errors from CPU emulation.

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

Reply 34 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've made a little summary of all those things I mentioned earlier, anyone can tell me if this is correct?

Of all multiple divisions used, the higher division has priority over the lower division, except when noted. […]
Show full quote

Of all multiple divisions used, the higher division has priority over the lower division, except when noted.

Information from FreeVGA:
*** CRTC ***
memory address counter: based on character clock divided by 1, 2(DIV2 bit set) or 4(DIV4 bit set); setting both DIV2 and DIV4 on the Tseng video cards(ET{3/4}000) takes half a character clock(each fourth pixel, so inner character pixels 0 and 4 in both 9 and 8 dots mode).
address counter: =memory address counter?
vertical timing counter: based on horizontal retrace clock divided by 1(SLDIV=0) or 2(SLDIV=1)
horizontal retrace clock: HRetrace signal itself, based on the character clock(horizontal character)?
vertical counter: horizontal retrace divided by 1 (SLDIV=0) or 2(SLDIV=1), =vertical timing counter?
row scan counter: horizontal scan rate(vertical (timing) counter) divided by 1(SD=0) or 2(SD=1).

*** Sequencer ***
dot clock: Master clock divided by 1(DCR=0) or 2(DCR=1)
character clock: dot clock divided by 9(9/8DM=0) or 8(9/8DM=1).
serializer loading data from VRAM: character clock divided by 1(SLR=0, S4=0), 2(SLR=1, S4=0) or 4(S4=1).

I'm currently working on all that info combined into a single logic.

Edit: This is the result I've made, based on the data above:

*** Total timing(same amount of '-' are parallel to each other, increasing '-' means it's based on the level with one less '-') […]
Show full quote

*** Total timing(same amount of '-' are parallel to each other, increasing '-' means it's based on the level with one less '-') ***
- Master clock: 25 or 28MHz clock.
-- dot clock: Master clock divided by 1(DCR=0) or 2(DCR=1)
--- character clock: dot clock divided by 9(9/8DM=0) or 8(9/8DM=1).
---- memory address counter: based on character clock divided by 1, 2(DIV2 bit set) or 4(DIV4 bit set); setting both DIV2 and DIV4 on the Tseng video cards(ET{3/4}000) takes half a character clock(each fourth pixel, so inner character pixels 0 and 4 in both 9 and 8 dots mode).
---- serializer loading data from VRAM: character clock divided by 1(SLR=0, S4=0), 2(SLR=1, S4=0) or 4(S4=1).
---- horizontal retrace clock: HRetrace signal itself, based on the character clock(horizontal character)?
----- vertical timing counter: based on horizontal retrace clock divided by 1(SLDIV=0) or 2(SLDIV=1)
------ row scan counter: horizontal scan rate(vertical (timing) counter) divided by 1(SD=0) or 2(SD=1).

This will result in one 4-bit or 8-bit pixel each dot clock. This then can be further combined by the attribute controller in 8-bit color mode to draw two adjacent pixels with the same colour, or finally done by the DAC(Only on the Sierra Hi-color DAC: doing the same in 8-bit mode with bit value 0x10 set, with either 4-bits per clock(when bit 0x80 is 0) or 8-bits per clock(when bit 0x80 is 1)).

Anyone can confirm this timing? Although I suspect this will give problems with 8-bit pixels with the current emulation, since they are processed twice each dot clock in 8-bit mode.

I've managed to get the entire 640x480 display somewhat working. For some reason it goes too slow through VRAM now (see bitbucket repository sequencer.c file). For some reason, I only get half a screen, the other half being blanked(The VRAM direct dump shows the entire screen in VRAM).

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

Reply 35 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

The screen captures of the current progress:

What my custom routine dumps from VRAM:

VGA256col-ET3000_Mode2E_directdump.png

What the ET3000 SVGA emulation renders:

219-ET3000_Mode2E_renderer.png

It seems that for some reason the DIV4 bit is set, but the DIV2 bit is cleared? It sets the underline register to 0x60, which means:

Bit 5, when.set to I, clocks the memory address counter with the character clock divided by 4, used when doubleword addressing i […]
Show full quote

Bit 5, when.set to I, clocks the memory address counter with the character clock
divided by 4, used when doubleword addressing is used. Note when Bit 3 of the
CRTC Mode Register is also = I, then the linear counter will increment twice
per character.
Bit 6, when set to I, indicates that memory addresses being used are doubleword
addresses.

So it uses doubleword addressing, which is fine: Each pixel block of 4 pixels are 4 bytes further in memory.
But it also implies (together with the CRTC mode control register being 0xA3) that it needs to only fetch the data once every 4 clocks(increase the counter once every 4 clocks). Or does this actually mean that, while only increasing the counter once every 4 clocks, it also increases that counter with 4 clocks all at once?

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

Reply 36 of 36, by superfury

User metadata
Rank l33t++
Rank
l33t++

Anyone can explain to me why you would want to increase the memory address counter only once every 4 clocks(4*8=32 pixels), by only setting the DIV4 bit(and not the DIV2 bit to obtain 4-pixel refreshes)? Unless you would want to display 4 8-bit pixels 4 times repeated?

Edit: This seems to be correct, as Dosbox's source code says the same:

If set memory address is only changed every fourth character clock.

Anyone can explain to me why this is used in 8-bit and higher color modes? It would be strange to replicate each set of 4 pixels(in 8-bit mode) 4 times on the screen? Why would anyone in their right mind use that? Or does this have a strange effect I don't know about?

Also, it seems the 1024x768x16 mode has changed somewhat now (compared to 640x480x16):

220.png
221.png

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