Skip to content

Commit

Permalink
Allow up to 768KB of memory for Tandy machine type, adjust memory con…
Browse files Browse the repository at this point in the history
…figuration. This fixes Might and Magic III Isles of Terra in Tandy machine type and Tandy graphics modes
  • Loading branch information
joncampbell123 committed Dec 10, 2022
1 parent 0f0bd94 commit 982c441
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 16 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
Unreleased
- Allow more than 640KB of conventional memory,
regardless of "allow more than 640kb" option, for
Tandy machine type. The setting is capped to 768KB
to reflect Tandy systems with that upgrade, which
is said to allow a full 640KB for DOS and 128KB for
video RAM without any conflict from the MCB chain.
Adjust Tandy video emulation for 768KB case. This
fixes "Might and Magic III Isles of Terra" crashes
in Tandy mode and Tandy graphics because the game
does not correctly handle the memory configuration
when less RAM is involved. (joncampbell123).
- Fix code page CPI/CPX loader to allocate 128KB of
memory instead of 84KB. The code allocates a 64KB
stack for the executable code within. The 84KB
Expand Down
62 changes: 46 additions & 16 deletions src/ints/bios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9915,11 +9915,30 @@ class BIOS:public Module_base{

ulimit = 640;
t_conv = MEM_TotalPages() << 2; /* convert 4096/byte pages -> 1024/byte KB units */
if (allow_more_than_640kb) {
if (machine == MCH_CGA)
ulimit = 736; /* 640KB + 64KB + 32KB 0x00000-0xB7FFF */
/* NTS: Tandy machines, because top of memory shares video memory, need more than 640KB of memory to present 640KB of memory
* to DOS. In that case, apparently, that gives 640KB to DOS and 128KB to video memory. 640KB of memory in a Tandy system
* means 624KB for DOS and 16KB for Tandy video memory... except that 16-color higher Tandy modes need 32KB of video
* memory, so the top of memory has to be adjusted or handled carefully to avoid corruption of the MCB chain. In the 768KB
* case video memory is high enough not to conflict with DOS conventional memory at all.
*
* Might and Magic III Isles of Terra will crash in Tandy graphics modes unless we emulate the 768KB Tandy case because the
* game doesn't appear to correctly handle the conflict between the DOS MCB chain and video memory (causing an MCB corruption
* error) and it appears to make some effort to allocate memory blocks from top of memory which makes the problem worse.
*
* I am fairly certain that there is nothing on Tandy systems to occupy A0000-AFFFFh. Unless of course you install EGA/VGA
* hardware in such a system. */
if (allow_more_than_640kb || machine == MCH_TANDY) {
if (machine == MCH_CGA || machine == MCH_TANDY)
ulimit = 736; /* 640KB + 64KB + 32KB = 0x00000-0xB7FFF */
else if (machine == MCH_HERC || machine == MCH_MDA)
ulimit = 704; /* 640KB + 64KB = 0x00000-0xAFFFF */
else if (machine == MCH_TANDY)
ulimit = 768; /* 640KB + 128KB = 0x00000-0xBFFFF */

/* NTS: Yes, this means Tandy video memory at B8000 overlaps conventional memory, but the
* top of conventional memory is stolen as video memory anyway. Tandy documentation
* suggests that memory is only installed in multiples of 128KB so there doesn't seem
* to be a way to install only 704KB for example. */

if (t_conv > ulimit) t_conv = ulimit;
if (t_conv > 640) { /* because the memory emulation has already set things up */
Expand Down Expand Up @@ -9991,21 +10010,32 @@ class BIOS:public Module_base{
* converting KB to paragraphs. Note that it calls INT 12h while in CGA mode, and subtracts 16KB
* knowing video memory will extend downward 16KB into a 32KB region when it switches into the
* Tandy/PCjr 16-color mode. */
if (t_conv > 640) t_conv = 640;
if (ulimit > 640) ulimit = 640;
t_conv -= 16;
ulimit -= 16;

/* if 32KB would cross a 128KB boundary, then adjust again or else
* things will horribly break between text and graphics modes */
if ((t_conv % 128) < 16)
/* Tandy systems can present full 640KB of conventional memory with 128KB for video memory if 768KB
* is installed! */
if (t_conv > (640+32)) {
if (t_conv > 640) t_conv = 640;
if (ulimit > 640) ulimit = 640;

/* Video memory takes the rest */
tandy_128kbase = 0xA0000;
}
else {
if (t_conv > 640) t_conv = 640;
if (ulimit > 640) ulimit = 640;
t_conv -= 16;
ulimit -= 16;

/* Our choice also affects which 128KB bank within which the 16KB banks
* select what system memory becomes video memory.
*
* FIXME: Is this controlled by the "extended ram page register?" How? */
tandy_128kbase = ((t_conv - 16u) << 10u) & 0xE0000; /* byte offset = (KB - 16) * 64, round down to multiple of 128KB */
/* if 32KB would cross a 128KB boundary, then adjust again or else
* things will horribly break between text and graphics modes */
if ((t_conv % 128) < 16)
t_conv -= 16;

/* Our choice also affects which 128KB bank within which the 16KB banks
* select what system memory becomes video memory.
*
* FIXME: Is this controlled by the "extended ram page register?" How? */
tandy_128kbase = ((t_conv - 16u) << 10u) & 0xE0000; /* byte offset = (KB - 16) * 64, round down to multiple of 128KB */
}
LOG(LOG_MISC,LOG_DEBUG)("BIOS: setting tandy 128KB base region to %lxh",(unsigned long)tandy_128kbase);
}
else if (machine == MCH_PCJR) {
Expand Down

0 comments on commit 982c441

Please sign in to comment.