VOGONS


x86EMU vs 8088MPH MOD playback using PC speaker?

Topic actions

First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

In my emulator, when I start up Alley Cat, I do get the screen of alley cat, but it seems something goes wrong while retrieving the individual pixels (if I set the pixel color based on the coordinates of the current pixel row and horizontal pixel (even/odd pixels), I seem to get the expected output). Is this a problem in retrieving the pixels to render or is there something going wrong with the VRAM I/O from the CPU?

Current version of my VGA emulation:
https://bitbucket.org/superfury/x86emu/src/f6 … /vga/?at=master

The vga_screen/vga_sequencer.c contains the renderer of the VGA pixels (supported by vga_sequencer_graphicsmode.c in this case to get the graphics pixels). The vga_mmu.c contains the code for CPU access to VRAM. The vga_vram.c contains the routines for accessing the VRAM itself (and MAP13, MAP14 and address wrapping support).

Anyone can see something going wrong there?

Last edited by superfury on 2015-11-23, 10:19. Edited 2 times in total.

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

Reply 1 of 63, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

I just tried "Alley Cat" in my emulator and seems to work fine in both native CGA mode (using a CGA adapter) as well as CGA mode on VGA (using VGA adapter). If you want to see what I do check devices/device_vga.cpp and look for functions: graphicsModeScanline16LoRes and graphicsModeScanline16HiRes:

https://github.com/vlad-stamate/CAPE

It is possible your memory writes are wrong, and therefore reads are wrong too?

Regards,
Vlad.

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 2 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

My emulator essentially uses the equivalent of your 'graphicsModeScanline4LoRes' function on 4 planes (packed shift mode). The write/read functions look fine. We have the same VRAM layout (index SHL 2 OR plane). My planar VRAM access is in vga_vram.c, memory mapped i/o is in vga_mmu.c and graphics rendering routines are in vga_screen/vga_graphicsmode.c. It's the packed pixel mode it's using (2-bits every pixel from planes 0/2 and 1/3 interleaved). I'm using the IBM VGA BIOS to run it (tested it using Dosbox int10h putpixel routines).

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

Reply 3 of 63, by Scali

User metadata
Rank l33t
Rank
l33t

A screenshot would be really helpful here.
Anyway, for CGA memory, you need to know 3 things I guess:
1) Pixels are packed together in bytes, so for 4-colour modes you get 00112233 bits in each byte, and in 2-colour modes you get 01234567 bits in each byte.
2) Pixel data is split up into two bitplanes for even scanlines (at segment B800) and odd scanlines (at segment BA00).
3) Memory wraps around after 16k.

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

Reply 4 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

- Already gotten the 00112233 (2-bit packed pixel mode) and 01234567(1-bit pixel using the planar shift mode) implemented, so that shouldn't be the problem?
- The even/odd scanline bitplanes should have been handled during rendering using the MAP13&14 bits and address wrap using the AW bit in the CRTC mode control register?
Should the AW bit also affect CPU VRAM access?

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

Reply 5 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmmm... In my latest build, when I try to fire up alley cat, I get half the screen height and half the screen (the left half) blanked for some reason. Anyone knows what's going wrong (using MS-DOS 5.0 bootdisk and another floppy with alley cat (and the usual ROMS(IBM VGA, XT-IDE 2.0.0beta3 and Generic Turbo XT BIOS 2.5)?

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

Reply 6 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

This is what I currently get using Ultima VI in CGA mode:

Output in the emulator itself (what you see when running the emulator):

UltimaVI_firstmenu.png
Filename
UltimaVI_firstmenu.png
File size
13.57 KiB
Views
2139 views
File comment
Ultima VI intro screen in CGA mode.
File license
Fair use/fair dealing exception

Output as generated by the VGA rendering (using the emulator screencapture functionality, found in the third tab of the PSP keyboard input, in the bottomleft section. Converted from the dumped BMP to PNG):

UltimaVI_firstmenu_VGA.png
Filename
UltimaVI_firstmenu_VGA.png
File size
34.07 KiB
Views
2134 views
File comment
Ultima VI screencapture as generated by the VGA rendering.
File license
Fair use/fair dealing exception

For some reason this forum allows png uploads, but BMP files are forbidden(antivirus security maybe)?

The latest version of my VGA emulation can be found at:
https://bitbucket.org/superfury/x86emu/src/4f … /vga/?at=master

- vga_sequencer.c contains the main rendering routine (CRTC etc.), which should be correct?
- vga_sequencer_graphicsmode.c contains the rendering of graphics modes (void loadpackedshiftmode() handles the CGA video modes).
- vga_vram.c handles all VRAM accesses (and MAP13/14 and address wrapping).
- vga_mmu.c handles all input/output from/to VRAM from the CPU(VGAmemIO_rb and VGAmemIO_wb handle memory writes/reads).

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

Reply 7 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

Is it just me or does it look like the vertical timing is screwing up (it looks like lines are missing when carefully looking at the characters). So horizontal timing (pixel retrieval itself) works, but vertical timing (odd/even rows?) seems to fail?

OPTINLINE void VGA_Sequencer_calcScanlineData(VGA_Type *VGA) //Recalcs all scanline data for the sequencer!
{
//First, all our variables!
uint_32 bytepanning;
byte allow_pixelshiftcount;

SEQ_DATA *Sequencer;
Sequencer = GETSEQUENCER(VGA); //Our sequencer!

//Determine panning
bytepanning = VGA->precalcs.PresetRowScanRegister_BytePanning; //Byte panning for Start Address Register for characters or 0,0 pixel!

//Determine shifts and reset the start map if needed!
byte reset_startmap;
reset_startmap = 0; //Default: don't reset!

allow_pixelshiftcount = 1; //Allow by default!
if (Sequencer->Scanline>VGA->precalcs.topwindowstart) //Top window reached?
{
reset_startmap = 1; //Enforce start of map to 0 for the top window!
if (VGA->precalcs.AttributeModeControlRegister_PixelPanningMode)
{
bytepanning = 0; //Act like no byte panning is enabled!
allow_pixelshiftcount = 0; //Don't allow it anymore!
}
}

Sequencer->startmap = VGA->precalcs.startaddress[reset_startmap]; //What start address to use?

//Determine byte panning and pixel shift count!
Sequencer->bytepanning = bytepanning; //Pass!

if (allow_pixelshiftcount) //Allow pixel shift count to be applied?
{
Sequencer->pixelshiftcount = VGA->precalcs.pixelshiftcount; //Allowable pixel shift count!
Sequencer->presetrowscan = VGA->precalcs.presetrowscan; //Preset row scan!
}
else
{
Sequencer->pixelshiftcount = Sequencer->presetrowscan = 0; //Nothing to shift!
}
}

OPTINLINE void VGA_Sequencer_updateRow(VGA_Type *VGA, SEQ_DATA *Sequencer)
{
register word row;
register uint_32 charystart;
row = Sequencer->Scanline; //Default: our normal scanline!
if (row>VGA->precalcs.topwindowstart) //Splitscreen operations?
{
row -= VGA->precalcs.topwindowstart; //This starts after the row specified, at row #0!
--row; //We start at row #0, not row #1(1 after topwindowstart).
}
row >>= VGA->precalcs.CRTCModeControlRegister_SLDIV; //Apply scanline division!
row >>= VGA->precalcs.scandoubling; //Apply Scan Doubling here: we take effect on content!
row <<= 1; //We're always a multiple of 2 by index into charrowstatus!

//Row now is an index into charrowstatus
word *currowstatus = &VGA->CRTC.charrowstatus[row]; //Current row status!
Sequencer->chary = row = *currowstatus++; //First is chary (effective character/graphics row)!
Show last 32 lines
	Sequencer->charinner_y = *currowstatus; //Second is charinner_y!

charystart = getVRAMScanlineStart(VGA, row); //Calculate row start!
charystart += Sequencer->startmap; //Calculate the start of the map while we're at it: it's faster this way!
charystart += Sequencer->bytepanning; //Apply byte panning!
Sequencer->charystart = charystart; //What row to start with our pixels!

//Some attribute controller special 8-bit mode support!
Sequencer->active_pixelrate = 0; //Reset pixel load rate status for odd sized screens.
Sequencer->active_nibblerate = 0; //Reset nibble load rate status for odd sized screens.

VGA_loadcharacterplanes(VGA, Sequencer, 0); //Initialise the character planes for usage!
}

void VGA_HTotal(SEQ_DATA *Sequencer, VGA_Type *VGA)
{
//Process HBlank: reload display data for the next scanline!
//Sequencer itself
Sequencer->x = 0; //Reset for the next scanline!
++Sequencer->Scanline; //Next scanline to process!

//CRT
if (!vretrace) //Not retracing vertically?
{
++VGA->CRTC.y; //Next row on-screen!
}

//Sequencer rendering data
Sequencer->tempx = 0; //Reset the rendering position from the framebuffer!
VGA_Sequencer_calcScanlineData(VGA);
VGA_Sequencer_updateRow(VGA, Sequencer); //Scanline has been changed!
}

Is there an error here? As far as I can see it should be correct? Anyone?

Edit: I see that i apply The CRTC mode control SLDIV bit by dividing the scanline to draw by 2. Isn't this supposed to be applied to the CRTC timing instead of the Sequencer timing (so instead of adding another doublescanning to convert 320x400 to 320x200(in this case it converts 320x200 to 640x100 output?), it should multiply all vertical CRT values with 2 ([320x200 VRAM -> 640x400(doublescanned&double pixel)] outputted to [640x200(CRTC display resolution) -> 640x400(vertical display resolution doubled by SLDIV)?

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

Reply 8 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've moved the SLDIV bit to the CRTC calculations. Somehow, when I disable Map13/14 and Address Wrap emulation in the renderer, text output still works and mode 4/5 become better output?

I notice that scanlines are offset by 80 bytes and 8 pixels by 2 bytes due to word mode(both planar) in the renderer.

Is there an error in my VGA_MMU.c? Seeing as things seem to work correctly at the renderer end?

My current VGA_MMU.c:
https://bitbucket.org/superfury/x86emu/src/88 … mmu.c?at=master

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

Reply 9 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

This is my current memory address to VGA display memory address translation:

//decodeCPUaddress(Write from CPU=1; Read from CPU=0, offset (from VRAM start address), planes to read/write (4-bit mask), offset to read/write within the plane(s)).
OPTINLINE void decodeCPUaddress(byte towrite, uint_32 offset, byte *planes, uint_32 *realoffset)
{
register uint_32 realoffsettmp;
register byte calcplanes;
if (getActiveVGA()->registers->SequencerRegisters.REGISTERS.SEQUENCERMEMORYMODEREGISTER.Chain4Enable) //Chain 4 mode?
{
calcplanes = realoffsettmp = offset; //Original offset to start with!
calcplanes &= 0x3; //Lower 2 bits determine the plane!
*planes = (1 << calcplanes); //Give the planes to write to!
realoffsettmp &= 0xFFFC; //Rest of bits, multiples of 4 won't get written! Used to be 0xFFFB, but should be multiples of 4 ignored, so clear bit 2, changed to 0xFFFC (multiple addresses of 4 with plane bits ignored) to make it correctly linear with 256 color modes (dword mode)!
*realoffset = realoffsettmp; //Give the offset!
return; //Done!
}

if (getActiveVGA()->registers->SequencerRegisters.REGISTERS.SEQUENCERMEMORYMODEREGISTER.OEDisabled) //Odd/Even mode disabled?
{
if (towrite) //Writing access?
{
calcplanes = 0xF; //Write to all planes possible, map mask register does the rest!
}
else
{
calcplanes = 1; //Load plane 0!
calcplanes <<= getActiveVGA()->registers->GraphicsRegisters.REGISTERS.READMAPSELECTREGISTER.ReadMapSelect; //Take this plane!
}
*planes = calcplanes; //The planes to apply!
*realoffset = offset; //Load the offset directly!
return; //Done!
}

//Odd/even mode used (compatiblity case)?
//Do the same as VPC!
calcplanes = realoffsettmp = offset; //Take the default offset!
if (getActiveVGA()->registers->GraphicsRegisters.REGISTERS.MISCGRAPHICSREGISTER.EnableOddEvenMode)
{
calcplanes &= 1; //Take 1 bit to determine the plane (0/1)!
realoffsettmp &= 0xFFFE; //Clear bit 0 for our result!
}
else
{
calcplanes = 0; //Use plane 0 always!
}
*realoffset = realoffsettmp; //Give the calculated offset!
if (getActiveVGA()->registers->GraphicsRegisters.REGISTERS.MISCGRAPHICSREGISTER.MemoryMapSelect == 1) //Memory map mode 1?
{
//Determine by Page Select!
if (getActiveVGA()->registers->ExternalRegisters.MISCOUTPUTREGISTER.OE_HighPage) //Lower page?
{
*planes = (0x1 << calcplanes); //Convert to used plane 0/1!
}
else //Upper page?
{
*planes = (0x4 << calcplanes); //Convert to used plane 2/3!
}
}
else //Default behaviour?
{
*planes = (0x5 << calcplanes); //Convert to used plane (0&2 or 1&3)!
}
Show last 1 line
}

Anyone knows if this has problems with CGA video modes (all other modes seem to work fine)?

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

Reply 10 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

CGA emulation works fine now: The problem was in the processing of the Double scanning and Divide scanline clock by 2, which were in different locations causing trouble. Now even Alley cat looks fine (although it hangs when starting gameplay).

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

Reply 11 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried running the 8088MPH program. It seems to run until after the first text moving up/down on the screen (although buggy). After that I get two slightly displaced bars and the program hangs? Is this supposed to happen on a VGA?

Edit: Fixed by switching the CPU from 80186 to 8086(It seems to need the SALC instruction to run instead of hanging).

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

Reply 12 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

8088MPH currently runs until this point (a few screens, with the PC speaker music infinitely looping in the background):

1.png
Filename
1.png
File size
40.42 KiB
Views
1884 views
File comment
Screen capture during inf/long wait time.
File license
Fair use/fair dealing exception

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

Reply 13 of 63, by Scali

User metadata
Rank l33t
Rank
l33t
superfury wrote:

Just tried running the 8088MPH program. It seems to run until after the first text moving up/down on the screen (although buggy). After that I get two slightly displaced bars and the program hangs? Is this supposed to happen on a VGA?

The results on VGA are basically undefined, because we reprogram the CRTC-registers directly. VGA has slightly different CRTC registers (not backward compatible), and therefore they are protected by default. You specifically need to enable access to them, and then you need to write VGA-compatible parameters. 8088 MPH is designed only to run on CGA, and what it does exactly on a VGA card depends on the level of CGA compatibility. I doubt it will work properly on any VGA card. I've tested it on a Paradise PVGA1B, which has quite a good CGA-compatible mode, but still it didn't work correctly with the high colour modes.
These modes try to 'stack' 100 frames of 2 scanline on top of eachother inside a single refresh. On the VGA card, you ended up with frames of 2 scanlines large, at 60 Hz, so the demo ran about 100 times slower than on CGA (this is similar to what I've seen with most emulators).

TL;DR: It's pointless to run 8088 MPH on VGA, let alone to try and change your emulator code for it.

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

Reply 14 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

The first screen scrolls up very faster over and over again (it looks like textmode characters of the CGA graphics card picture, but like it's displaying 16 lines instead of 1 or 2 per vertical pixel).
After the part with it telling information about what the CGA is 'supposed' to be able to do (amount of colors vs Comodore 64 I believe?), the high color screen starts rolling over like on a real CGA, but it's monochrome instead of color. After that the screen gets blanked for a while with the music playing. At a certain point the given screen capture appears, after which it seems to do nothing anymore but play music, looping it over and over again.

Since it isn't progressing after that point, does this mean my CPU emulation has an error? Or is it waiting for something that never happens? Or is the CPU simply too slow to handle what it's trying to do? The detection at the start tells me it's running at 0% of a 8088 (according to MIPS 1.0 it's running at a quite high speed, about 1.7 MIPS)?

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

Reply 15 of 63, by Scali

User metadata
Rank l33t
Rank
l33t
superfury wrote:

The first screen scrolls up very faster over and over again (it looks like textmode characters of the CGA graphics card picture, but like it's displaying 16 lines instead of 1 or 2 per vertical pixel).

The first screen with the old/new CGA detection uses a special tweakmode, which won't work on VGA.

superfury wrote:

but it's monochrome instead of color.

That is correct. It is a 640x200 monochrome display mode. You'd see the same on CGA with an RGBI monitor. On NTSC composite, with colorburst enabled, this leads to color artifacts, turning it into a 160x200 mode with 16 colours.

superfury wrote:

Since it isn't progressing after that point, does this mean my CPU emulation has an error?

Probably. That part uses the undocumented SALC instruction in the check for ending that part. I suppose you are not emulating that instruction? I've heard that problem before with other emulators. The NEC V20/V30 CPUs have the same problem.

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

Reply 16 of 63, by crazyc

User metadata
Rank Member
Rank
Member
superfury wrote:

Edit: Fixed by switching the CPU from 80186 to 8086(It seems to need the SALC instruction to run instead of hanging).

All Intel x86 CPUs have the SALC insn including the 80186. As Scali points out, it's missing on the v20 where opcode 0xd6 is an alias to xlat.

Reply 17 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

I thought SALC was removed from the 80186 and onwards?

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

Reply 18 of 63, by Scali

User metadata
Rank l33t
Rank
l33t
superfury wrote:

I thought SALC was removed from the 80186 and onwards?

No, and according to wiki it's documented since Pentium Pro: https://en.wikipedia.org/wiki/X86_instruction … ed_instructions
It's not in the Intel instruction set reference though: http://www.intel.com/content/dam/www/public/u … nual-325383.pdf

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

Reply 19 of 63, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've fixed the SALC being undefined on the 80186+. 8088MPH now runs partly. The screencapture is taken from the point just after the starfield demo (which shows up without problems). Don't know if it's the correct term for it though. It's in b/w. After that point music continues and it stops doing anything at all (no response on the display anymore). CPU is running at max speed on a i7 4.0GHz CPU. Music has no problems, it will keep playing.

The vertex demo seems to be tripled and in B/W. The Intel Inside logo is in 4 colors. Then text in text-mode 16 colors. After that some text mode messed up (looks like the image) with the PC speaker messing up. Next more colors with the same. Next brown interlaced afaik. Next more coloured 'image' in text mode. Next what looks like the 4K image flashing by fast in text mode. After that it scrolls down with black and a colorful text mode with messed up blocks appear (looks like the 16 or 4K mode text scrolling up and down?). After that the starfield displays in b/w. Looks fine though. Next b/w information saying 'Sprites? Where we're going we don't need sprites" appears in b/w scrolling up and down, looked at from the pause menu to copy it here. After that blacks out, the above screen capture appears.

It keeps executing the same sequence it seems at the end (there's also a bit of the music processing (segment F000+ executing) in the log).

It seems to wait for the carry flag to set? (JA instruction keeps looping the same part infinitely it seems).

Filename
8088mph_log.zip
File size
14.96 KiB
Downloads
50 downloads
File comment
8088MPH log of infinite loop w/ sound routines.
File license
Fair use/fair dealing exception

Look at the end of the log for the instructions being looped.

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