VOGONS


Reply 40 of 58, by Scali

User metadata
Rank l33t
Rank
l33t
superfury wrote:

Anyone knows why the display of the kefrens is scrolling up instead of being stationary? Scali?

I'm not sure if you're familiar with the 'classic' Kefrens bars effect, as it is performed on Amiga.
In short, the effect is performed by repeating the same scanline over the entire screen. If you draw a 'shade/gradient' thingie in there, it will get stretched over the entire width. This is how vertical bars are performed.
Step two is to make the bars move around horizontally. This is done by drawing a new shade/gradient at every scanline (not erasing what was already there), moving it around with some sine-based pattern for example.

On CGA, the effect is done in pretty much the same way. On Amiga it is trivial to repeat the same scanline: you can just do that with the modulo register, which contains the distance between scanlines in memory. With the proper value, it will restart at the same address for each scanline. The same can be done on VGA.
On CGA however, there is no concept of 'modulo', because the scanlines in memory are assumed to be contiguous.
Is there another way to reset the scanline address? Yes, you can set the start offset. However, this is latched, and when you write a new value, it won't become active until the current frame ends (vblank).
The trick in 8088 MPH is to compose a screen of multiple frames. Each frame is 2 scanlines high, and there is no vblank area. The result is that when a new address is written, it will become active after 2 scanlines (this is why the Kefrens bars work on a 2-scanline resolution, rather than single-scanline as on Amiga), because the CRTC starts a new frame.
Since the monitor just continues tracing the image, these scanlines will all get stacked on top of eachother, just like on a 'regular' frame. After the last scanline is drawn, a proper vblank is inserted so the monitor can retrace. So effectively the signal seen by the monitor is the same 262-line 59.92 Hz signal that you'd get in regular modes. The CRTC thinks it has done 100 frames though.

So in order to emulate this, you need to decouple the CRTC's concept of frames from the 'monitor' frames (I haven't seen any real VGA card that is capable either... generally what happens is that it draws an entire frame of 262 scanlines for every 2 scanlines. This also means that the effect is slowed down a lot).

An additional problem here is that the Kefrens code is timed cycle-exact for a real IBM PC/XT with real IBM CGA (there is no time for polling the CRTC status). So on this machine, the code for drawing the bar, updating the background colour and resetting the CRTC registers takes exactly 2 scanlines. If your timing is off even just a little, the CRTC will not be reprogrammed at the correct time, and the whole thing falls apart. You may miss scanlines, or the vblank is inserted in the wrong place etc.
A relatively easy way to tell if the timing is off is to check the background colour. At the proper speed, the colour is changed in the horizontal blank interval, so hidden in the left border. If it is too fast or too slow, you will see 'stair stepping' artifacts mid-screen, when the colour is changed.

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

Reply 41 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

I'm still working out how to actually detect whether it should respond like a CGA(using the values in the mode control register as input) or like a VGA(use normal VGA operation and ignore CGA operation modes).
Currently Turbo XT BIOS v2.5 with the IBM VGA BIOS starts up in the normal 80x25 text mode, but since a CGA register write (3D8) is detected, the double height is applied to fix the things in my previous post, however this destroys the normal VGA 80x25 text mode. Anyone knows a solution for this?

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

Reply 42 of 58, by Scali

User metadata
Rank l33t
Rank
l33t
superfury wrote:

I'm still working out how to actually detect whether it should respond like a CGA(using the values in the mode control register as input) or like a VGA(use normal VGA operation and ignore CGA operation modes).

In short: you can't.
VGA is not CGA-compatible by design. It re-uses some of the CGA registers and redefines their meaning. On top of that, VGA is not compatible by CGA at the signal level, since CGA is 200-line at 59.92 Hz, where VGA has 400-line and 480-line modes, and runs at 70 Hz in 400-line mode (the protection bit was introduced exactly for these reasons, to prevent software designed for CGA to write invalid values to VGA, and possibly damage your monitor).
So even if VGA were register-compatible with CGA, you'd need to program the CRTC differently when a VGA monitor is connected, and you need to time your software differently.

The only way to be CGA-compatible is to specifically switch your emulator to CGA-mode. Some VGA cards offered extended CGA-compatibility, which was invoked by running a special utility to switch the card to CGA mode. Still this does not make them anywhere near 100% CGA-compatible, but at least they respond to basic things like palette changes, which IBM VGA will not.

In short, running CGA software on VGA (or EGA for that matter) is different from running CGA software on an real CGA card. The VGA BIOS and logic 'fake' various things to make basic CGA software work. But you can't run advanced CGA software properly on anything other than a real CGA card.
So you need to specifically have a VGA-compatible mode and a CGA-compatible mode in your emulator, and let the user choose which one to use.

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

Reply 43 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

Although, the whole 'damage the monitor' isn't really applicatable to CRT emulation? The worst that can happen is that my VGA emulation ends up with a window with invalid content and maybe a way too big/small window(although limited to 800x600, since it's the maximum window, as well as the window size used when applying 4:3 aspect ratio). Another thing that might happen is that the VGA emulation crashes the emulator(writing to invalid memory past the VRAM pointer)), but even that shouldn't happen, as checks are made for every VGA address supplied by the software(aborting the write/read to the memory address specified and returning invalid memory on reads(this is done by the I/O processing itself. Currently both for emulated memory and I/O ports, invalid accesses(past end of RAM and VGA registers or unmapped/invalid I/O ports)) end up returning 0xFF currently. It might need to be adjusted to be correct?).

Afaik(according to read documentation) memory reads from invalid addresses/ports end up with the resulting byte filled with 1s(0xFF/0xFFFF/0xFFFFFFFF). One piece of source code I saw once tried to write to an unused I/O port which affects that resulting byte(so essentially reads return the last outputted I/O byte. Though I don't know if this only applies to invalid I/O writes or all I/O writes). Anyone knows which of the two is correct behaviour with the IBM PC(and AT by extension)?

Above invalid memory/I/O reads also are applied to invalid VGA reads(invalid CRTC/Attribute/Graphics/Sequencer registers being read etc). All invalid memory reads are handled in the MMU controller(mmu.c). All invalid hardware reads(port I/O) are handled by the I/O read handler itself(the one that calls all connected hardware for the address supplied. Then when anything is returned it's OR'ed into the result(which is given when all hardware is handled). When no hardware responds to the address(also applied to the invalid VGA CRTC, Attribute controller etc. indexed registers), 0xFF is returned by byte reads. Word and doubleword reads return extended values(0xFFFF/0xFFFFFFFF).

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

Reply 44 of 58, by Scali

User metadata
Rank l33t
Rank
l33t
superfury wrote:

Although, the whole 'damage the monitor' isn't really applicatable to CRT emulation?

In a way it is. You are emulating hardware that has this behaviour. There is protection against writing to certain registers. Even if there's no risk of damaging an actual display, you still need to emulate it.
The PC platform basically works exactly in the opposite way of what you want.
Namely, VGA and CGA are mutually exclusive. A real system has either one or the other, not both.
And software asks the user whether to run in CGA or VGA mode. You want the 'hardware' to 'guess' what the software wants. But there's no way to know. The same commands mean different things, depending on what hardware it is running on.
Your emulator just needs to emulate the hardware. Which means the user first selects whether they have a CGA or VGA card in their emulated machine. Then they configure their software to run either in CGA or VGA mode.

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

Reply 45 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

But the CGA and VGA can be used at the same time (as a dual/triple monitor system)? With the VGA having one/two monitors(w/ or w/o split screen monochrome emulation at I/O addresses 3BXh&3CXh) and the CGA having 1 monitor at I/O addresses 3DXh?

Can I just use the VGA with disabled I/O ports(all ports except the CGA ports, where the CRTC registers are redirected to the CGA handling, which translates them into VGA values, puts them into the VGA registers(unreachable by the CPU emulation), then calls the usual update function (calcPrecalcs) to update the VGA state according to the VGA registers. Although, maybe an extra CRT handler(VGA_activeDisplay) needs to be handled to process the CGA pixels like a CGA using NTSC methods to make 8088 MPH work with it's 1K/16c/256c hacked modes)? Doesn't Dosbox do this already? Although Dosbox seems to use the same int10h handler as the VGA for mode changes? But those registers don't exist in a CGA?

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

Reply 46 of 58, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

But the CGA and VGA can be used at the same time (as a dual/triple monitor system)? With the VGA having one/two monitors(w/ or w/o split screen monochrome emulation at I/O addresses 3BXh&3CXh) and the CGA having 1 monitor at I/O addresses 3DXh?

Yes, the IBM VGA (as the EGA) is designed to be able to coexist with either a CGA or a monochrome card. The VGA card can only be connected to a single monitor, though.

superfury wrote:

Can I just use the VGA with disabled I/O ports(all ports except the CGA ports, where the CRTC registers are redirected to the CGA handling, which translates them into VGA values, puts them into the VGA registers(unreachable by the CPU emulation), then calls the usual update function (calcPrecalcs) to update the VGA state according to the VGA registers.

I'm not sure what you mean by this. If you're disabling ports 0x3dX on the VGA card, it's presumably because you're using a real (emulated) CGA card, not the (emulated) VGA's emulated CGA modes, so there's no CRTC translation going on. A VGA card can never run 8088 MPH Kefrens correctly because the timing is totally different - VGA's pixel clock is 160/91 times the CGA's, there are 800 pixels per scanline time instead of 912, it's double-scanned instead of single-scanned, and there 449 scanlines instead of 262.

superfury wrote:

Although, maybe an extra CRT handler(VGA_activeDisplay) needs to be handled to process the CGA pixels like a CGA using NTSC methods to make 8088 MPH work with it's 1K/16c/256c hacked modes)? Doesn't Dosbox do this already? Although Dosbox seems to use the same int10h handler as the VGA for mode changes? But those registers don't exist in a CGA?

DOSBox's int10 handlers are implemented on the host side, not the guest side - they don't translate directly into simple port writes and memory accesses like they would do if they were implemented in the guest code. Instead they just modify the data structures used by the emulator directly. This is due to the way that DOSBox has evolved, but it's also a source of bugs (for example the text at the top of the screen in Bruce Lee) so I'd avoid doing the same thing if writing a new emulator.

Reply 47 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

So I should just copy the VGA's CRT emulation and rewrite the copy to apply the new CGA text mode(using a fixed 8x8 font) and graphics modes with CGA registers? Or is the CGA's CRT method of handling too different from the VGA? What about the NTSC signal used with 8088 MPH? Would this require a complete rewrite of the CRT rendering as x86EMU's VGA emulation uses now? Or are most of the signaling (htotal/retrace/blank and vtotal/retrace/blank and misc signals) the same from the programming point of view(and thus rendering it to a virtual raster, like the VGA does)?

Although the only things of Dosbox my emulator uses are the code for setting up the character set in the VGA ROM area during initialisation(the fonts in ROM) and the video mode set(which writes a bunch of (S)VGA registers according to the little table of up to 0x14 entries in my emulator(modes 00h-13h for VGA, 7h(1 entry) for MDA, 00h-07h for CGA) copied and fixed for my VGA emulation from Dosbox). It's an adjustment of Dosbox's INT10_SetVideoMode in ints/int10_modes.cpp my emulator is currently using(of Dosbox-X to be exact), although slightly modified to use my emulator I/O(port I/O and types). My code is in interrupts/interrupt10_switchvideomode.c and interrupts/interrupt10_modelist_vga.c(with some text support from Dosbox, which is also patched, in interrupts/interrupt10_romfont.c and interrupts/interrupt10_textmodedata.c).

That interrupt handler DOES write to the virtual I/O VGA ports? I can adjust that one to apply the CGA modes by writing to the VGA directly(using the registers themselves in real memory and calling the precalculation update functions when finished to apply them to the 'VGA' emulation). Then I would just have to add some extra stuff for dealing with CGA-specific things, like the register mentioned before(CGA CRTC register 04h if I remember correctly, the Interleave Register). Although I can't find anything on the Interleave register in any public manuals through Google. It just says what it sets up and nothing about what different values in the register do, like the FreeVGA and IBM VGA documentation tells?

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

Reply 48 of 58, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

So I should just copy the VGA's CRT emulation and rewrite the copy to apply the new CGA text mode(using a fixed 8x8 font) and graphics modes with CGA registers? Or is the CGA's CRT method of handling too different from the VGA?

It's too different - the CRTC registers are different, the values are different, the timings are different and the VGA has more variables than the CGA. They're not comparable at all.

superfury wrote:

What about the NTSC signal used with 8088 MPH? Would this require a complete rewrite of the CRT rendering as x86EMU's VGA emulation uses now? Or are most of the signaling (htotal/retrace/blank and vtotal/retrace/blank and misc signals) the same from the programming point of view(and thus rendering it to a virtual raster, like the VGA does)?

It's similar in that both have total, retrace and blank for both horizontal and vertical, but the CGA's retrace pulses are not programmable relative to the blank pulses. So you might be able to share some code.

When you say "the NTSC signal used with 8088 MPH" are you talking about the CGA's timings in general (which are always NTSC compatible on a real CGA), or how to generate the analogue composite signal from the digital RGBI signal so that the 1k colour pictures from the demo look correct?

Reply 49 of 58, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

That interrupt handler DOES write to the virtual I/O VGA ports?

Only with an EGA or VGA adapter. It first checks IS_EGAVGA_ARCH and programs a different set of CRTC registers for CGA, which end up in write_crtc_data_other() instead of vga_write_p3d5().

superfury wrote:

CGA CRTC register 04h if I remember correctly, the Interleave Register

4 is vertical total. 8 is the interlace mode register, if that's what you're thinking of.

superfury wrote:

Although I can't find anything on the Interleave register in any public manuals through Google. It just says what it sets up and nothing about what different values in the register do, like the FreeVGA and IBM VGA documentation tells?

It's described in the MC6845 datasheet - see http://www.reenigne.org/crtc/mc6845.pdf. All known published CGA software so far (including 8088 MPH) uses only the non-interlaced mode, though, hence it's obscurity.

Reply 50 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm. Looks like it should be doable to convert the VGA CRT rendering to use that (copied and adjusted for CGA rendering). It's not that different from the VGA, except no doublescanning and character fonts in RAM(Just use a copy of the Dosbox 8x8 font directly, already have code for that in my Text Surface rendering). Also, since characters are always 8 pixels wide, text character lines are just loading the index, index into the table shl 3, OR the line. Then pixels by AND 1=Pixel, shr 1 for each pixel(in 7 operations and 8 ANDs). Finally font/back with blink by the cursor registers, use the attribute 4 high/low bits for the attribute and simply convert to the color. Although the color might be influenced by the NTSC color cycle and previous pixel color (phase)? What would be the best way to handle this?

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

Reply 51 of 58, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

Although the color might be influenced by the NTSC color cycle and previous pixel color (phase)? What would be the best way to handle this?

Generate an RGBI image first (1 byte per high-res pixel with values 0-15) and then pass it through the two transformations I wrote, that are now used in DOSBox SVN and PCem. The first looks at adjacent pairs of pixels and uses a phase-dependent lookup table to generate an analogue composite waveform (8 bit samples at 14.318MHz). The second performs NTSC decoding on the composite waveform to get 24-bit RGB data. The algorithm has inputs for CGA type (old/new), brightness, contrast, saturation and hue. The DOSBox patch can be found at download/file.php?id=18638 . The underlying algorithm can also be found at https://github.com/reenigne/reenigne/blob/mas … sc/cga2ntsc.cpp which is under UNLICENSE and can be relicensed however you like (in case you don't like the license DOSBox uses).

Reply 52 of 58, by Scali

User metadata
Rank l33t
Rank
l33t
superfury wrote:

But the CGA and VGA can be used at the same time (as a dual/triple monitor system)? With the VGA having one/two monitors(w/ or w/o split screen monochrome emulation at I/O addresses 3BXh&3CXh) and the CGA having 1 monitor at I/O addresses 3DXh?

Note that this would be a setup where your VGA will probably be incompatible with most software, which expects VGA to be at I/O range 3Dxh.

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

Reply 53 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

@reenigne: Can I also apply that transformation process (both at the rendering process instead of after rendering a line/screen) when drawing single pixels? So essentially insert that code in my pixel drawing process, instead of the usual DAC conversion and plotting that value? So take the output from the Attribute Controller(which skips the DAC translation, which uses the lookup table and the color registers filling bits 4-5 and 6-7 in the case of the VGA emulation(essentially forcing the Attribute Index register bit 5 to 0 to disable palette access)), pass that result through the two transformations(so each pixel seperate), then drawing the result(ignoring the VGA DAC conversion, as it's already RGB) on the raster for rendering like the VGA normally does(which is resized by the GPU processing as needed to fit in the Window, Fullscreen or 800x600(when selecting 4:3 aspect ratio in the emulator BIOS Settings menu))? I could, for compatibility, just implement the Old-Style CGA conversion, as most/all programs probably are built for that CGA?

Also, does that CGA conversion work with 8088 MPH's 1K images and other hacks?

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

Reply 54 of 58, by reenigne

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

@reenigne: Can I also apply that transformation process (both at the rendering process instead of after rendering a line/screen) when drawing single pixels?

You can, but bear in mind that changing a single input (RGBI) pixel has an effect on a span of as many as 9 consecutive output pixels (and, equivalently, the colour of each output pixel depends on the colours of as many as 9 consecutive input pixels).

superfury wrote:

So essentially insert that code in my pixel drawing process, instead of the usual DAC conversion and plotting that value?

That would probably be slow compared to the way that the code I wrote for DOSBox SVN does it. If you don't want to do the conversion for an entire scanline at a time, I suggest instead you do a block of (say) 16 input pixels at a time (the largest number, horizontally, that can be changed by a single write to CGA RAM).

superfury wrote:

I could, for compatibility, just implement the Old-Style CGA conversion, as most/all programs probably are built for that CGA?

If you want to do that, you should first read all of the big thread at CGA Composite Mode under DOSBOX (Commited r3804) and understand all the consequences (it would probably be quicker to allow the user to change between old and new CGA - the amount of drawing code needed to support both is pretty small).

superfury wrote:

Also, does that CGA conversion work with 8088 MPH's 1K images and other hacks?

Yes, that code takes care of everything needed for the colours in 8088 MPH to be correct (the timing is another matter).

Reply 55 of 58, by Scali

User metadata
Rank l33t
Rank
l33t
superfury wrote:

I could, for compatibility, just implement the Old-Style CGA conversion, as most/all programs probably are built for that CGA?

I have no idea how many old style vs new style CGA cards were sold (and then there's all the clones).
I would say that developers probably didn't really pay attention to the type of card used (they may not even have been aware of differences), as for the 'classic' CGA modes, the difference is very small.
CGA-support in games remained common at least until 1990, possibly later. So chances are that later games targeted clone CGA/RGB display, since that was more common by then.

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

Reply 56 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've adjusted the VGA rendering to disable double scanning when emulating CGA (w/ and w/o on VGA base). It now also renders it's output to a CGA line buffer(Up to 1024 pixels), which are rendered in a special CGA(NTSC) conversion function seperate from the usual rendering. It now generates the 0x0-0xF values in the line buffer for color modes and 0x0(pixel attribute 0)/0xF(pixel attribute 1-F) for monochrome modes.

Now I just still need to apply that NTSC conversion on the scanline and adjust the VGA to use the CRT registers as specified in the manual(essentially remapping it with 8 pixels/character only).

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

Reply 57 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

Depends how you look at it: When software is programming the VGA, usually the CRT registers are unprotected. Thus VGA is accessable normally. Only when the CRT registers are locked(Protection bit is 1) the VGA will redirect the CGA CRT registers. Thus normal software using the VGA will unlock it(Protection bit=0) and access the VGA registers. CGA software won't try to unlock those(Protection is still set and unknown by the CGA software). Thus CGA software will try to access the locked VGA registers, which are redirected to the CGA registers. Only VGA software reading the CRT registers while 'VGA with CGA/MDA extension' mode is enabled with protection is on will read the CGA registers instead of VGA registers. But this can be fixed by setting it to either CGA only or VGA only mode before running the emulator(Settings menu when starting the emulator). The mode is only meant to simply fix the CGA, while setting it up with a VGA BIOS(Which removes protection during setup of the CRT registers), at least until full CGA emulation is ready(which only disables the VGA emulation when the CGA mode is enabled, entering the new mode currently implemented). Currently only two CGA registers are supported(not tested yet): Index 8(Currently sets VGA's CRT mode control register Wrapping, MAP13 and MAP14 bits to archieve this. Although something more might be needed. Bit 0-1 values now do:
00/10: Set all bits to 0.
10: Sets Map bits to 1, Wrapping to 0.
11: Set Map bits to 1, Wrapping to 1
Although I'm not 100% sure about the wrapping(Address Wrap/AW bit) applying those modes fully(Affecting odd scanlines being either equal to even scanlines or being odd scanlines, thus even increasing odd). Although MAP13 might need to be reversed in either modes 10 or 11? Is this correct?
).

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

Reply 58 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

I changed the CGA on VGA emulation to store it's CRT data in seperate CGA registers. Then any change of those registers should apply CGA timing instead of VGA timing accordingly.
Address wrapping and MAP13/14 are applies according to what's said in the previous post.
Writing to the CGA Mode Control register will now apply some changes to the VGA registers (essentially anything not having anything to do with the CGA timing, which is seperated from normal VGA emulation(timing generation lookup table only)).
Writing to the CGA Palette register will now update the Attribute Controller Palette and Overscan color according to the Palette register(Assuming RGB monitor for now instead of Composite monitor), using data of the CGA palette register and CGA Mode Control register(to enable the third palette),

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

Look at the attribute controller, VGA_IO, Precalcs, VGA_CGA and VGA_Sequencer for the changes applied to convert to CGA output(the parts applying VGA->registers->specialCGAflags&0x(8)1, which apply the CGA emulation(and of course complete VGA_CGA.c itself)).

Anyone knows if this is correct? I'm not getting any output(essentially 0FPS) or sound from the Turbo XT BIOS v2.5 with CGA only mode enabled(CGA flags are set to 0x81 in that case, to imply Pure CGA mode).

Edit: Moved this to my other thread concerning CGA on VGA emulation.

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