• Please review our updated Terms and Rules here

8086 emulator tech discussion

Chuck(G)

25k Member
Joined
Jan 11, 2007
Messages
40,218
Location
Pacific Northwest, USA
just got hercules mode 720x348 working.. if anybody wants to experiment with fake86 as-is, i'd gladly upload it. the more programs that get tested in it the better! jeez, hercules is so ugly.

It looks as if you're not doing it right. Real Hercules was the highest-quality graphics mode (albeit monochrome) until VGA came along. It looks as if you're skipping every 3rd line...
 

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
It looks as if you're not doing it right. Real Hercules was the highest-quality graphics mode (albeit monochrome) until VGA came along. It looks as if you're skipping every 3rd line...

actually, ultima 6 does that for some reason. it looks the same on a real herc card and mono monitor i have. windows 3.0 splash screen shows its working correctly:

fake86-win30-herc.png
 

Chuck(G)

25k Member
Joined
Jan 11, 2007
Messages
40,218
Location
Pacific Northwest, USA
Oh, okay. They were probably going for Herc support "for the heck of it". There were other ways to get better Herc support, but they obviously decided not to use then.
 

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
OH MY GOD

you will not believe how much i just sped up the emulator! this is still FreeBASIC, not even C:
http://www.youtube.com/watch?v=EhbEI_WDytE

check out how smooth wolf3d is now and at full view size! i made it multi-threaded, with the CPU, video/key/mouse engine, and sound engine all having their own separate ones. i didn't realize it would help THAT much! if you didn't see video of wolf3d in it from like a week ago, the framerate was half of what it is now and that was using the SMALLEST view window.

edit: i think i'm going to try to crank even more speed out of it by converting the huge select case statement with all possible opcodes into a function jump table...
 
Last edited:

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
made another huge bit of progress tonight. turns out what was stopping windows 3.0 from running was completely inaccurate values in video status port 3DA regarding hblank/vsync bits. now that the video subsystem has it's own thread, the CPU can keep running at the same time the video is being updated and can read the status bits during it.

fake86-win30.png

^ CGA mode

fake86-win30-2.png

^ hercules mode

that probably resolves other issues that i've been having with various programs too.
 

deathshadow

Veteran Member
Joined
Jan 4, 2011
Messages
1,363
Do you have a link to a recent build and it's source? I'd be interested in giving that hercules emulation a whirl.

Also, are you still doing the video output "the hard way"? I've got some experience with SDL and might be able to help give you a boost on that front.
 

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
Do you have a link to a recent build and it's source? I'd be interested in giving that hercules emulation a whirl.

Also, are you still doing the video output "the hard way"? I've got some experience with SDL and might be able to help give you a boost on that front.

sure, yeah i can upload the latest for you. will post shortly, let me just clean up the code a little bit. it looks nasty in parts. i get sloppy when i am doing a lot of experimenting. i'm using SDL video now, with a pointer to the surface buffer. the herc emulation should be pretty solid, but yeah give 'er a work out! :)
 

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
actually, SIMCGA won't start because it just says "no emulation - CGA active"

how does it detect that CGA is installed? my emu always will report CGA/VGA capability, but if a program tries to put it in herc mode it will do it.



EDIT: deathshadow, here are the latest files. the source still needs a big-time cleanup. i also include the latest win32 and linux binaries.

http://rubbermallet.org/fake86-0.4.4.11.rar

also check your PMs. my timer emulation is way off at many frequencies, i'm working on it. if you want to play your Paku Paku game, you'll need to uncomment "clockmult,20" in the fake86.ini otherwise it runs really slowly. most games' speeds are correct.

you could probably figure this out, but if you want to boot a floppy image uncomment "bootdisk,&h80" or change it to "bootdisk,0" in the ini.

also, this is a ghetto way of going it but it was just a quick hack... if you need to change the image mounted on floppy 0 while it's running, click on the console window that you started the program from, press 'F' then type in the new path and filename of the disk image.

the whole program is really rough around the edges... really rough. lots of work to do still.
 
Last edited:

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
wolf3d looking great now! basman and i have been helping each other with our emus via PM. i let him know how i had gotten unchained decoding working as far as i had, and dthen he pretty quickly figured out the rest which i was missing. i wasn't handling VGA write mode 1 properly (or any of them for that matter, i was not even checking the write mode)

so i re-did my whole VGA subsystem tonight and things are looking good! thanks basman.

fake86-newwolf3d.png


i need to start trying some other games that use VGA register trickery and see how they are.
 

Chuck(G)

25k Member
Joined
Jan 11, 2007
Messages
40,218
Location
Pacific Northwest, USA
how does it detect that CGA is installed? my emu always will report CGA/VGA capability, but if a program tries to put it in herc mode it will do it.

It's a little complicated, because you have to detect a CGA card not in use, co-resident with a Herc, EGA operating in a non-EGA mode, etc.

See attached code.
 

Attachments

  • DISTYPE.ZIP
    1.8 KB · Views: 1

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
i emulate the disney sound source now! the pc speaker is working pretty well too. have a peek at wolf3d playing w/ sound in fake86 in this video. the sound source output is a slight bit crackly in this video, i've fixed it completely since uploading it.

 

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
thanks, Klee! not quite. there's still plenty of work to do. i need to get EGA support working correctly, and i want to implement sound blaster support. i'd like to do adlib FM chip emulation as well, but i'll have to do some research on that one. i have a bit of experience with that sort of thing from writing my NES emulator, but adlib is probably pretty different.
 

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
alright, i've been working on re-writing it in C. the core should be working fine, but it is buggy. i can boot into DOS but there are all kinds of issues. sometimes numbers will have leading zeros when they shouldnt (like from the DOS date command) and if you're in the root path of a partition, there's an extra space trailing the \ in the DOS prompt... among other bugs.

i know this is a lot of code here, but if anybody has the time and is interested in looking, and you see some sort of problem i've missed let me know. i've gone over everything at least 10 times. i'll keep looking, but i thought i'd post it here. too much code to embed in the post, so here are pastebin links. all of this is just from the CPU core sections of the program, none of the other supporting code.

common.h: http://pastebin.com/NV1BFE23 (just so you can see what types the global variables are)
CPU.c: http://pastebin.com/vCQS3idM
grpops.c: http://pastebin.com/gzRqWC1b (most multi-meaning GRP opcodes are handled in here)
flags.c: http://pastebin.com/vDuD4Fj5 (code to calculate new flag values after operations)
ops.c: http://pastebin.com/pW5GZf69 (very short file, contains actual code for different ops like op_add(), op_sub(), etc)

this is frustrating.
 

Tor

Veteran Member
Joined
Mar 14, 2011
Messages
984
Location
Norway/Japan
I looked through it all, but it's difficult to figure out exactly what to look for when the problem isn't a bit more isolated. I couldn't see any obvious bloopers in the code, but those you would have found by your own inspection already I'm sure.

So I can't offer much.
As for the code itself, you could save yourself some if..else statements by changing e.g.
Code:
if (value & 4) pf = 1; else pf = 0;
to
Code:
pf = (value & 4)? 1:0;
or, for this specific case where you only need 1 or 0:
Code:
pf = (value & 4) == 4;
for example. And maybe use macros to the same effect to reduce the possibility of typos when doing a lot of those.
 

deathshadow

Veteran Member
Joined
Jan 4, 2011
Messages
1,363
Looking at your C version-- with the getReg routines wouldn't it be easier/faster to just overlap an array struct over your regs? Then you could just index the array instead of the painfully slow function call.
 

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
I looked through it all, but it's difficult to figure out exactly what to look for when the problem isn't a bit more isolated. I couldn't see any obvious bloopers in the code, but those you would have found by your own inspection already I'm sure.

So I can't offer much.
As for the code itself, you could save yourself some if..else statements by changing e.g.
Code:
if (value & 4) pf = 1; else pf = 0;
to
Code:
pf = (value & 4)? 1:0;
or, for this specific case where you only need 1 or 0:
Code:
pf = (value & 4) == 4;
for example. And maybe use macros to the same effect to reduce the possibility of typos when doing a lot of those.

yep, i think BASIC is just so ingrained into my thick skull that anything other than if/else looks weird to me. :p

that definitely would save a bit of typing though. thanks for having a look at the code. there is probably just some tiny little single typo somewhere that is causing these problems, but damned if i can find it... if that is indeed the problem anyway.
 

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
Looking at your C version-- with the getReg routines wouldn't it be easier/faster to just overlap an array struct over your regs? Then you could just index the array instead of the painfully slow function call.

that's a great idea! should have thought of that. there are a few other optimizations i can make as well that i can see. i have at least being making all of the frequently called functions inlines. not sure how much CPU time that saves though. thanks for having a peek at this.. i keep comparing my code with my working BASIC code, but can't seem to find any functional discrepancies. i'm a bit baffled.

i've got the BASIC version pretty optimized at this point, including using a jump table for the opcodes and most of the frequently called routines are macros in it, but it still is not fast enough to play wolf 3d smoothly on anything slower than a 1.6 GHz processor (if multi-core, it needs 2.x GHz single core for that to be smooth) or so. not good enough! and so i turn to C... :)

the FB version can play games meant for 8088s (i.e. space commander, etc) at full speed on a mid-range Pentium 3, but i found that DOSBox will play that full speed on a Pentium 166 MHz box (!!) which is extremely impressive. it would probably run fine on an even slower host, but i haven't tried.

i was hoping i could squeeze some more juice out of FreeBASIC, but that orange is about dry at this point. i just thought it would be neat to have a PC emulator in pure BASIC. to say i did i guess.

EDIT: you know, FreeBASIC has pointers as well... i am going to see what happens if i overlay an array over the registers and get rid of getreg/putreg stuff. that should help immensely, even though getreg/putreg are macros in it. i am definitely going to continue working on the C version, but this will be interesting to see.
 
Last edited:

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
alright, stupid question but how do i make these two arrays overlap in memory using C?

Code:
uint16_t wordregs[8];
uint8_t byteregs[8];

because the first 4 items in the wordregs array are ax, cx, dx, and bx. i want the byte array to overlap those to be able to access the high and low bytes of each independently.

like wordregs[0] would be functionally equivalent to using (byteregs[0] | (byteregs[1] << 8 ))

i thought i could do it by using *byteregs = *wordregs; but that doesn't seem to work.

although this whole idea would make it so the software wouldn't be portable to non-little-endian processors. is there a better way to do this without sacrificing speed while keeping it portable?


EDIT: nevermind. i figured it out myself.

Code:
uint16_t *wordregs;
uint8_t *byteregs;

then i initialize them in main() with byteregs = wordregs = malloc(16);

i'm still wondering about the portability things though. any advice? in any event, my C version of the CPU core works fine now. i just trashed and rewrote CPU.c - i was getting tired of poking through for errors so just started all over. now i get to rewrite the rest of the emulator for video/sound/etc... fun!
 
Last edited:
Top