VOGONS


First post, by mateusz.viste

User metadata
Rank Member
Rank
Member

EXMS86 is a specialized TSR that provides XMS 2.0 extended memory services using an EMS 4.0 expanded memory source. Designed for 16-bit DOS computers equipped with EMS cards, EXMS86 enables software requiring XMS memory to run on systems lacking native XMS support (IBM PC, XT, etc).

I wanted my DOSMid MIDI player to support EMS when XMS isn’t available. Sure, I could have added EMS support directly into DOSMid, but that would be so boring. Instead, I decided to take a more versatile route by building a generic XMS driver. It felt like a more rewarding challenge, and one that could benefit other projects too. So here it is.

http://mateusz.fr/exms86/

http://mateusz.fr

Reply 1 of 18, by Sneakernets

User metadata
Rank Newbie
Rank
Newbie

Holy crap.

So yeah, this locks up when loaded in config.sys on my V20 with a divide overflow error. When loaded after USE!UMBs and DOSMAX suite to move things into upper memory, the software claims XMS manager already exists, which... I guess UMBs are, if you stretch the definition until it breaks.

Very cool so far though. I'm willing to test whatever you need me to.

Reply 2 of 18, by wierd_w

User metadata
Rank Oldbie
Rank
Oldbie

(Imagines the horror of using a LIMulator that simulates EMS (such as via swapping to disk), with this int15h xms simulator, on an xt with 512k base ram.)

(There's a vintage tool for this, that similates LIM EMS 3.2, from the simtel archive.)

https://ftp.sunet.se/mirror/archive/ftp.sunet … il/memsim32.zip

It's vintage shareware.

I just shudder at this potential union.

Reply 3 of 18, by zb10948

User metadata
Rank Member
Rank
Member

V20, Lotech EMS card 2 MB. TSR goes up normally. mem shows no XMS, Wolf3D shows no XMS?

Reply 4 of 18, by Sneakernets

User metadata
Rank Newbie
Rank
Newbie
zb10948 wrote on 2025-07-16, 21:51:

V20, Lotech EMS card 2 MB. TSR goes up normally. mem shows no XMS, Wolf3D shows no XMS?

I dont think mem will see the XMS memory, I checked and didn't see anything listed there. It's definitely working for me with DOSMID, though...

Reply 5 of 18, by mateusz.viste

User metadata
Rank Member
Rank
Member
Sneakernets wrote on 2025-07-16, 20:48:

So yeah, this locks up when loaded in config.sys on my V20 with a divide overflow error.

It is not a device driver, only an executable TSR, so it will not load with a "DEVICE=" directive -- I take that's what you tried? It should, however, loaded with an INSTALL= directive if you insist on having it in CONFIG.SYS.

When loaded after USE!UMBs and DOSMAX suite to move things into upper memory, the software claims XMS manager already exists, which... I guess UMBs are, if you stretch the definition until it breaks.

That makes sense. USE!UMBS is a UMBS provider. The standard way to do so is through the XMS API... so indeed, use!umbs hooks on the XMS api and that's why EXMS86 cannot load. The XMS API is somewhat of a misnomer since it is not about XMS only, but also about dealing with HMA, UMB, switching the A20 line...

http://mateusz.fr

Reply 6 of 18, by mateusz.viste

User metadata
Rank Member
Rank
Member
zb10948 wrote on 2025-07-16, 21:51:

V20, Lotech EMS card 2 MB. TSR goes up normally. mem shows no XMS, Wolf3D shows no XMS?

I have tested it on 86box with a virtual lotech card and it works for me and shows up in mem. I don't know how accurate/reliable the emulation is, but at least mem detection should work the same. What system do you use? I test on SvarDOS. Perhaps your mem flavour does not care about XMS 2.0 and detects only XMS 3.0?

http://mateusz.fr

Reply 7 of 18, by mateusz.viste

User metadata
Rank Member
Rank
Member
Sneakernets wrote:

I dont think mem will see the XMS memory, I checked and didn't see anything listed there. It's definitely working for me with DOSMID, though...

Detecting XMS is very much application-dependant. The mem command from SvarDOS and FreeDOS detects XMS from EXMS86 correctly. Perhaps other systems only show XMS 3+, I'm not sure. I don't know about wolf3d but this one I can easily check tomorrow.

http://mateusz.fr

Reply 8 of 18, by Sneakernets

User metadata
Rank Newbie
Rank
Newbie
mateusz.viste wrote on 2025-07-16, 22:35:
It is not a device driver, only an executable TSR, so it will not load with a "DEVICE=" directive -- I take that's what you trie […]
Show full quote
Sneakernets wrote on 2025-07-16, 20:48:

So yeah, this locks up when loaded in config.sys on my V20 with a divide overflow error.

It is not a device driver, only an executable TSR, so it will not load with a "DEVICE=" directive -- I take that's what you tried? It should, however, loaded with an INSTALL= directive if you insist on having it in CONFIG.SYS.

When loaded after USE!UMBs and DOSMAX suite to move things into upper memory, the software claims XMS manager already exists, which... I guess UMBs are, if you stretch the definition until it breaks.

That makes sense. USE!UMBS is a UMBS provider. The standard way to do so is through the XMS API... so indeed, use!umbs hooks on the XMS api and that's why EXMS86 cannot load. The XMS API is somewhat of a misnomer since it is not about XMS only, but also about dealing with HMA, UMB, switching the A20 line...

That might explain why MS Diagnostics has such a hard time with USE!UMBs...

I wonder what a good solution is? Turbo XTs with backfill on EMS or a full megabyte on board really benefit from that UMB area in DOS.

Reply 9 of 18, by mateusz.viste

User metadata
Rank Member
Rank
Member
zb10948 wrote on 2025-07-16, 21:51:

Wolf3D shows no XMS?

It appears that wolf3d refuses to run on less than a 80286. I suppose you use some custom version on your v20, is that right? Googling around led me to a hacked edition done by Mike Chambers 16 years ago: https://forum.vcfed.org/index.php?threads/wol … us.17472/page-3

By any chance is that what you use? If so, Mike states that he had removed all XMS support.

http://mateusz.fr

Reply 10 of 18, by mateusz.viste

User metadata
Rank Member
Rank
Member
Sneakernets wrote on 2025-07-16, 23:00:

I wonder what a good solution is? Turbo XTs with backfill on EMS or a full megabyte on board really benefit from that UMB area in DOS.

Technically, I suppose exms86 could unhook umb!use, service all xms queries itself and proxify umb requests to umb!use via a direct far call. This way both xms and umb would be available, in theory. But that starts to be a little complicated and difficult to test on a virtual setup so it is not something I am eager to engage into.

http://mateusz.fr

Reply 11 of 18, by zb10948

User metadata
Rank Member
Rank
Member
mateusz.viste wrote on 2025-07-16, 22:41:
zb10948 wrote on 2025-07-16, 21:51:

V20, Lotech EMS card 2 MB. TSR goes up normally. mem shows no XMS, Wolf3D shows no XMS?

I have tested it on 86box with a virtual lotech card and it works for me and shows up in mem. I don't know how accurate/reliable the emulation is, but at least mem detection should work the same. What system do you use? I test on SvarDOS. Perhaps your mem flavour does not care about XMS 2.0 and detects only XMS 3.0?

IBM PC DOS 2000

Reply 12 of 18, by zb10948

User metadata
Rank Member
Rank
Member
mateusz.viste wrote on 2025-07-16, 23:25:
zb10948 wrote on 2025-07-16, 21:51:

Wolf3D shows no XMS?

It appears that wolf3d refuses to run on less than a 80286. I suppose you use some custom version on your v20, is that right? Googling around led me to a hacked edition done by Mike Chambers 16 years ago: https://forum.vcfed.org/index.php?threads/wol … us.17472/page-3

By any chance is that what you use? If so, Mike states that he had removed all XMS support.

https://github.com/jhhoward/WolfensteinCGA

By the way, what programs run on V20, support XMS but not EMS? I will also try your dosmid player 😀

Reply 13 of 18, by mateusz.viste

User metadata
Rank Member
Rank
Member
zb10948 wrote on 2025-07-16, 23:55:

By the way, what programs run on V20, support XMS but not EMS? I will also try your dosmid player :)

That's a good question, and to be honest I was hoping to find out here with people saying "I can run program xyz now on my 8086!". :-P

I am not sure there are any 8086-compatible programs that require XMS, but I imagine there might be some (esp. games) that use it for improved performances (caching) if it is detected, and these might not bother to look for EMS*. I asked an AI who told me that Simcity from 1989 could be such game, but AI are notorious liers so who knows. Anyway, I basically created EXMS86 as a support tool for DOSMid, and hope it might be useful for some other programs, too.

Maybe it could be used with some xms disk-caching utilities as well.

*) If there is no such game then I will create one, no issue.

http://mateusz.fr

Reply 14 of 18, by mateusz.viste

User metadata
Rank Member
Rank
Member
zb10948 wrote on 2025-07-16, 21:51:

mem shows no XMS, Wolf3D shows no XMS?

Checked these two.

It appears that MS MEM doesn't even try to detect XMS on machines that are not at least a 286:
https://github.com/verner002/ms-dos-6.0/blob/ … mem/memex.c#L42

As for Wolf3D, the starting screen doesn't actually show the amount of available memory, but rather the amount of memory that it was able to allocate. First, it looks for EMS and allocates as much as possible (ie. everything). Then, it looks for XMS and asks the XMM driver about how much memory is available - and my driver answers "0 bytes", because there is no longer any EMS memory left that I could use to back my XMS emulation.

If you'd like to play WOLF3D with EXMS86, then you need to instruct the game not to reserve all the EMS memory. It's actually easy: just run "WOLF3D NOEMS".

http://mateusz.fr

Reply 15 of 18, by mateusz.viste

User metadata
Rank Member
Rank
Member
mateusz.viste wrote on 2025-07-16, 23:42:

Technically, I suppose exms86 could unhook umb!use, service all xms queries itself and proxify umb requests to umb!use via a direct far call. This way both xms and umb would be available, in theory. But that starts to be a little complicated and difficult to test on a virtual setup so it is not something I am eager to engage into.

After all I did it, albeit again - without any testing because it is difficult to virtualize all the conditions, so can't tell if it works. You tell me :) attached.

// EDIT: uploaded a fix ("DEVEL2"), the initial upload had a nasty memory-corrupting bug

http://mateusz.fr

Reply 16 of 18, by MobyGamer

User metadata
Rank Member
Rank
Member
mateusz.viste wrote on 2025-07-16, 20:14:

Sure, I could have added EMS support directly into DOSMid, but that would be so boring.

It also would have been much more performant. See below.

mateusz.viste wrote on 2025-07-16, 23:42:

Technically, I suppose exms86 could unhook umb!use, service all xms queries itself and proxify umb requests to umb!use via a direct far call. This way both xms and umb would be available, in theory. But that starts to be a little complicated and difficult to test on a virtual setup so it is not something I am eager to engage into.

If you don't feel like implementing it, then people can always use Quarterdeck's QRAM, which was designed to do all of the above (in 1990).

mateusz.viste wrote on Yesterday, 05:41:

That's a good question, and to be honest I was hoping to find out here with people saying "I can run program xyz now on my 8086!". 😜

You won't find any. XMS was not designed to be an 8086 memory standard, because EMS already existed. XMS was meant as a way for 286+ systems to make extended memory available to real-mode programs, which it does so by copying blocks of memory around. This is less efficient than simply switching pages of memory with hardware registers, which is how EMS works with real EMS hardware boards (and how EMM386/QEMM/386MAX work on 386+ systems in protected mode, using paging).

Which is why...

It appears that MS MEM doesn't even try to detect XMS on machines that are not at least a 286:

...Which is why MS MEM won't detect XMS on 8086 systems, because it was never an 8086 standard.

As for Wolf3D, the starting screen doesn't actually show the amount of available memory, but rather the amount of memory that it was able to allocate. First, it looks for EMS and allocates as much as possible (ie. everything). Then, it looks for XMS and asks the XMM driver about how much memory is available - and my driver answers "0 bytes", because there is no longer any EMS memory left that I could use to back my XMS emulation.

That is the correct behavior for a program that supports both EMS and XMS. EMS is more peformant than XMS, so you always want to try to use EMS first if both exist on the system.

If you'd like to play WOLF3D with EXMS86, then you need to instruct the game not to reserve all the EMS memory. It's actually easy: just run "WOLF3D NOEMS".

That would be slower than letting it just use EMS.

Reply 17 of 18, by MobyGamer

User metadata
Rank Member
Rank
Member

All that said, I'm happy to see you wrote your TSR in 100% assembler.

Reply 18 of 18, by mateusz.viste

User metadata
Rank Member
Rank
Member
MobyGamer wrote on Today, 03:41:
mateusz.viste wrote on 2025-07-16, 20:14:

Sure, I could have added EMS support directly into DOSMid, but that would be so boring.

It also would have been much more performant. See below.

Not necessarily, no. At least not in the way I would have implemented it, using the EMS 4.0 copying API, which is basically doing the same thing as XMS: moving bytes back and forth.
The legacy EMS 3.2 way of doing it would, however, be more performant, that's perfectly right. But it would also require a nasty page frame, while EMS 4.0 doesn't.

MobyGamer wrote on Today, 03:41:

If you don't feel like implementing it, then people can always use Quarterdeck's QRAM, which was designed to do all of the above (in 1990).

I did end up implementing it, as I mentioned yesterday. I did not know about QRAM - very cool stuff. The more the merrier!

MobyGamer wrote on Today, 03:41:
mateusz.viste wrote on Yesterday, 05:41:

That's a good question, and to be honest I was hoping to find out here with people saying "I can run program xyz now on my 8086!". :-P

You won't find any. XMS was not designed to be an 8086 memory standard, because EMS already existed.

I think that reasoning is flawed. Considering a real-mode program, it does not cost much to be "8086-compatible". Authors may be tempted to produce 8086 binaries if it's just a compiler switch away, if only to expand their potential user base by 0.5%. This has usually negligible impact on more recent CPUs anyway. These authors may also use XMS when it's available, but do without if not (just slower), and not be invested into 8086 users enough to go the extra mile and implement an alternative memory management scheme based on EMS. That's pretty much the path I follow myself.

MobyGamer wrote on Today, 03:41:

...Which is why MS MEM won't detect XMS on 8086 systems, because it was never an 8086 standard.

Ignoring XMS on pre-286 CPUS seems like it was just an arbitrary decision, probably a programmer's shortcut to save some time on testing. I wouldn't read too much into that. There are MEM implementations out there that do not make such assumptions and happily report XMS memory on a 8088.

MobyGamer wrote on Today, 03:41:

If you'd like to play WOLF3D with EXMS86, then you need to instruct the game not to reserve all the EMS memory. It's actually easy: just run "WOLF3D NOEMS".

That would be slower than letting it just use EMS.

Of course, but that wasn't really the point - in this specific case it's only about the coolness factor of seeing Wolf3D's startup screen reporting XMS memory on a 8086. :-) I tested the CGA version that was mentioned earlier in this thread - it's surprisingly playable on a 8088 with XMS.

MobyGamer wrote on Today, 03:41:

All that said, I'm happy to see you wrote your TSR in 100% assembler.

No need for emotions. Assembly is just a tool, and it is not inherently better than C. Sometimes it is better suited to the given task, most of the time it is not. Even for a TSR, it often makes sense to do it in C rather than assembly if it is non-trivial. The C code does not have to be bloated, as I demonstrated with EtherDFS. Yes, there are hoops to jump over, but nowadays we also have WMINCRT which makes it easy to generate super compact binaries with C. There are obviously also cases where both assembly and C are a bad choice. I think it all boils down to using the right tool for the job at hand.

http://mateusz.fr