Frenkel wrote: ↑Sun Jan 09, 2022 0:56
So the problem is in ID_MM.C function MML_SetupXMS()
where
mminfo.XMSmem is 32 bits but
size is 16 bits, right?
This answer probably comes two and a half years too late, but yes, that line is the problem. The code should really have been something like this:
For those who don't know: The "l" suffix at the end of a number constant causes the compiler to treat that number as a signed long (32 bit) value, which means the result of the multiplication will be 32 bits as well. After changing the code like above, the correct amount will be added when size is >= 0x1000.
I suspect that this bug might be the reason why DOSBox doesn't provide a full 64k block of UMB memory.
Not adding the reclaimed 4000 bytes to the memory size values is negligable. The size values are really only used by the CheckMemory() function when the game starts. Everything else uses the numbers reported by the MM_UnusedMemory() and MM_TotalFree() functions, which are always accurate. Yes, you could add 4000 to mminfo.mainmem and mminfo.farheap (the F10+M memory usage window uses mminfo.mainmem, the minimum memory check at startup uses mminfo.nearheap+mminfo.farheap). But simply subtracting 4000 from the hard-coded minimum value would lead to the same result during the minimum memory check without adding any extra code.
I suspect that this is exactly what the id team did for Keen 4-6. When I use my memory checking patches to calculate how much memory is actually used by each level, I get the following results for v1.4 of the games:
KEEN 4 EGA (MINMEMORY is 310000):
310992 (level 15, no sound, no music)
316080 (level 15, AdLib sounds, no music)
318832 (level 15, AdLib sounds + music)
KEEN 5 EGA (MINMEMORY is 310000):
310480 (level 13, no sound, no music)
316992 (level 13, AdLib sounds, no music)
323440 (level 13, AdLib sounds + music)
KEEN 6 EGA (MINMEMORY is 300000):
303664 (level 10, no sound, no music)
309264 (level 10, AdLib sounds, no music)
321696 (level 10, AdLib sounds + music)
I have only listed the highest requirements for each setup to keep things short. As you can see, the MINMEMORY value would
always be insufficient for at least one level of each game. But if you take into account that there will be 4000 bytes more available, then all three games would be playable with the given minimum amount of memory, but only if you play without sounds and music.
Also keep in mind that the requirements for music may be slightly higher than what's shown here. The compressed music data needs to be loaded into memory before it can be decompressed into the final music buffer. If the compressed data is is bigger than 4096 bytes, then the game needs to allocate a temporary buffer for it, which means the memory requirements for playing that level with music would be a bit higher.
Another contributing factor that can cause the "Insufficient memory to load music" error is the fact that the memory blocks can become fragmented. That means there may be 2000 bytes free in one section (let's say in the far heap) and another 5000 bytes in a different section (in the XMS UMB memory, for example), but no contiguous block of 6000 bytes, which means that even though there are 7000 bytes free in total, the memory manager won't be able to allocate a 6000 byte buffer. I added some extra features for the memory manager in Foray in the Forest that allow the memory manager to "defrag" the memory blocks to merge as much free memory as possible into one big block. The FITF memory manager will also stop any music and turn the sounds off to avoid an "out of memory" crash if possible.
Bounder wrote: ↑Sun Aug 25, 2024 19:01
Has anyone figured out a way to make Keen use "XMS" (i.e. upper memory blocks) on an 80286?
I described one possible way of making XMS UMB memory available for Foray in the Forest on 286 machines in the HELPME.COM file that comes with FITF:
If your system is equipped with a 286 CPU, then you cannot use EMM386.EXE to emulate EMS and provide UMBs. If you have more than 640K of memory installed and some of that memory is already mapped into the Upper Memory Area (i.e. the addresses above the 640K limit in the first megabyte of the address space) then you can use that memory as Upper Memory Blocks.
There is a utility called "USE!UMBS", written by Marco van Zwetselaar, that can be used to provide UMBs on 286 systems and below. Search for "USE!UMBS" or "use_umbs.zip". The download should include a tool named TEST!UMB.EXE that you can use to check if any real memory is mapped into the Upper Memory Area on your system.
If your system does not provide such memory, you will have to install a memory expansion card that can map memory into the Upper Memory Area.
If TEST!UMB confirms that you have memory that can be used for UMBs, you can add USE!UMBS.SYS to your CONFIG.SYS (please refer to the USE!UMBS documentation for more information on how to use it). Since USE!UMBS version 2.0 does not implement freeing UMBs after use, we recommend using the setting DOS=HIGH,UMB in your CONFIG.SYS to let DOS manage the UMBs. Otherwise you might have to reboot the system before running Foray in the Forest to make sure UMB memory is still available.
I haven't been able to verify this on my own, since the only 286 board I own doesn't map the extra memory (it has 1 MB RAM on board) into the Upper Memory Area, it maps the memory to the addresses at 1 MB and above. But keenmaster486 sent me a photo of the Keen 4 startup screen displaying "111 Kbytes" extended memory on his 286 system after installing the USE!UMBS driver.
My 286 board has a Morse chipset with a 12 MHz 80286 CPU. I have tested FITF using this board, using a 16 bit SVGA card (the only ISA graphics card I have) and I have concluded that the game would be playable in 12 MHz mode, but 6 MHz mode was too slow in my opinion.
And yes, you don't really need EMS memory for the Keen games. Since the game's memory manager will only use 64k of EMS memory anyway, simply using the EMS page frame addresses for UMB memory will give you the same amount of memory. You can test this on MS-DOS 6.22 systems by loading EMM386.EXE with the NOEMS parameter and using DOS=HIGH,NOUMB in your CONFIG.SYS file. This might also work for other DOS versions, but I have only tested it with 6.22. But unless the system already has some real memory mapped into the upper memory area, you will still need the EMS driver (or a similar driver) to allow 386+ systems to remap some real memory addresses into the upper memory area.