VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've been reading this(first entry):
http://www.pcjs.org/blog/2015/04/16/

If I understand this correctly, there's three kinds of memory mapping going on:
1. The actual ROM(combined from the 2 ROMs) is mapped at the high addresses (FFFF0000-FFFF7FFF and FFFF8000-FFFFFFFF), the ROMs being interleaved of course.
2. The low RAM at A0000-FFFFF can be remapped to FA0000-FFFFF, so essentially it's making the memory area at FA0000-FFFFFF access physical memory at A0000-FFFFF instead?
3. The ROM that's mapped in the HMA (A0000-FFFFF) is the same as the 80386 location(at FFFF0000-FFFFFFFF), being mapped to the same ROMs.

As far as I can see from the ioports.lst documentation, the reserved memory address(0x80C00000) can do the following:
1. Setting bit 0 ignores any writes to the currently mapped location at 0xFE0000-0xFFFFFF.
2. Clearing bit 1 disables the RAM at A0000-FFFFF and moves it to the high memory at 0xFA0000-0xFFFFFF.

Is this correct?

My code currently does the following:
= 0x80C00000 behaviour:
- Setting bit 0 protects physical memory addresses 0xFE0000-0xFFFFFF from being overwritten with new values.
- Setting bit 1 makes CPU physical addresses 0xE0000-0xFFFFF remap to physical memory 0xFE0000-0xFFFFFF(applying protection of this area after this is done). So accessing address E0000 actually access RAM location FE0000(which might be write-protected).

General behaviour:
- The CPU accessing addresses FA0000-FFFFFF is always remapped to physical memory addresses A0000-FFFFF without protection.

Is this behaviour correct?

//Memory hole start/end locations!
#define LOW_MEMORYHOLE_START 0xA0000
#define LOW_MEMORYHOLE_END 0x100000
#define MID_MEMORYHOLE_START 0xF00000
#define MID_MEMORYHOLE_END 0x1000000
#define HIGH_MEMORYHOLE_START 0xC0000000
#define HIGH_MEMORYHOLE_END 0x100000000

OPTINLINE void applyMemoryHoles(uint_32 *realaddress, byte *nonexistant, byte iswrite)
{
INLINEREGISTER byte memloc; //What memory block?
INLINEREGISTER byte memoryhole;
memloc = 0; //Default: first memory block: low memory!
memoryhole = 0; //Default: memory unavailable!
if (*realaddress>=LOW_MEMORYHOLE_START) //Start of first hole?
{
if (*realaddress<LOW_MEMORYHOLE_END) //First hole?
{
memoryhole = 1; //First memory hole!
}
else //Mid memory?
{
memloc = 1; //Second memory block: mid memory!
if (*realaddress>=MID_MEMORYHOLE_START) //Start of second hole?
{
if (*realaddress<MID_MEMORYHOLE_END) //Second hole?
{
memoryhole = 2; //Second memory hole!
}
else //High memory?
{
memloc = 2; //Third memory block!
if ((*realaddress>=HIGH_MEMORYHOLE_START) && ((uint_64)*realaddress<(uint_64)HIGH_MEMORYHOLE_END)) //Start of third hole?
{
memoryhole = 3; //Third memory hole!
}
else
{
memloc = 3; //Fourth memory block!
}
}
}
}
}

if (memoryhole) //Memory hole?
{
*nonexistant = 1; //We're non-existant!
if (BIOSROM_LowMemoryBecomesHighMemory && (memoryhole==1)) //Move memory FE0000-FFFFFF to E0000-FFFFF?
{
if ((*realaddress>=0xE0000) && (*realaddress<=0xFFFFF)) //Low memory hole to remap to the available memory hole memory? This is the size that's defined in MMU_RESERVEDMEMORY!
{
memloc = 2; //We're the second block instead!
*realaddress += MIN(MMU.size,MMU.maxsize?MMU.maxsize:MMU.size)-0xE0000; //Patch to physical FE0000-FFFFFF reserved memory range to use!
return; //Apply the new block instead!
}
}
else if ((is_Compaq==1) && (memoryhole==2)) //Compaq remaps RAM from A0000-FFFFF to FA0000-FFFFFF.
{
//This should be correct, according to PCem: https://bitbucket.org/pcem_emulator/pcem/src/66eec7c1b664f2f1496b5ed3763ec2b2738a6fab/src/compaq.c?at=default
Show last 33 lines
			if ((*realaddress>=0xFA0000) && (*realaddress<=0xFFFFFF)) //Remapped RAM area addressed?
{
*nonexistant = 0; //We're to be used directly!
*realaddress &= 0xFFFFF; //Remap the low RAM area high!
}
}
}
else //Plain memory?
{
*nonexistant = 0; //We're to be used directly!
if ((MoveLowMemoryHigh&1) && (memloc) && (is_Compaq!=1)) //Move first block lower?
{
*realaddress -= (LOW_MEMORYHOLE_END - LOW_MEMORYHOLE_START); //Patch into memory hole!
}
if ((MoveLowMemoryHigh&2) && (memloc>=2)) //Move second block lower?
{
*realaddress -= (MID_MEMORYHOLE_END - MID_MEMORYHOLE_START); //Patch into memory hole!
}
if ((MoveLowMemoryHigh&4) && (memloc>=3)) //Move third block lower?
{
*realaddress -= (uint_32)((uint_64)HIGH_MEMORYHOLE_END - (uint_64)HIGH_MEMORYHOLE_START); //Patch into memory hole!
}
if ((*realaddress >= MMU.size) || ((*realaddress>=MMU.maxsize) && MMU.maxsize)) //Reserved memory?
{
*nonexistant = 2; //Reserved for reading only!
}
}
if (memoryprotect_FE0000 && (*realaddress>=0xFE0000) && (*realaddress<=0xFFFFFF) && iswrite) //Memory protected?
{
*nonexistant = 1; //We're non-existant!
return; //Abort!
}
}

Configuration register in memory:

	if ((realaddress==0x80C00000) && (EMULATED_CPU>=CPU_80386) && (is_Compaq==1)) //Compaq special register?
{
memoryprotect_FE0000 = (value&1); //Write-protect 128KB RAM at 0xFE0000?
if (value&2) //128KB RAM only addressed at FE0000? Otherwise, relocated to (F(general documentation)/0(IOPORTS.LST)?)E0000.
{
BIOSROM_LowMemoryBecomesHighMemory = BIOSROM_DisableLowMemory = 0; //Normal low memory!
}
else
{
BIOSROM_LowMemoryBecomesHighMemory = BIOSROM_DisableLowMemory = 1; //Low memory becomes high memory!
}
}

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

Reply 1 of 2, by superfury

User metadata
Rank l33t++
Rank
l33t++

A little revision, according to the new documentation:

OPTINLINE void applyMemoryHoles(uint_32 *realaddress, byte *nonexistant, byte iswrite)
{
INLINEREGISTER byte memloc; //What memory block?
INLINEREGISTER byte memoryhole;
memloc = 0; //Default: first memory block: low memory!
memoryhole = 0; //Default: memory unavailable!
if (*realaddress>=LOW_MEMORYHOLE_START) //Start of first hole?
{
if (*realaddress<LOW_MEMORYHOLE_END) //First hole?
{
memoryhole = 1; //First memory hole!
}
else //Mid memory?
{
memloc = 1; //Second memory block: mid memory!
if (*realaddress>=MID_MEMORYHOLE_START) //Start of second hole?
{
if (*realaddress<MID_MEMORYHOLE_END) //Second hole?
{
memoryhole = 2; //Second memory hole!
}
else //High memory?
{
memloc = 2; //Third memory block!
if ((*realaddress>=HIGH_MEMORYHOLE_START) && ((uint_64)*realaddress<(uint_64)HIGH_MEMORYHOLE_END)) //Start of third hole?
{
memoryhole = 3; //Third memory hole!
}
else
{
memloc = 3; //Fourth memory block!
}
}
}
}
}

if (memoryhole) //Memory hole?
{
*nonexistant = 1; //We're non-existant!
if (BIOSROM_LowMemoryBecomesHighMemory && (memoryhole==1)) //Move memory FE0000-FFFFFF to E0000-FFFFF?
{
if ((*realaddress>=0xE0000) && (*realaddress<=0xFFFFF)) //Low memory hole to remap to the available memory hole memory? This is the size that's defined in MMU_RESERVEDMEMORY!
{
memloc = 2; //We're the second block instead!
*realaddress |= 0xF00000; //Patch to physical FE0000-FFFFFF reserved memory range to use!
}
}
}
else //Plain memory?
{
*nonexistant = 0; //We're to be used directly!
if ((MoveLowMemoryHigh&1) && (memloc) && (is_Compaq!=1)) //Move first block lower?
{
*realaddress -= (LOW_MEMORYHOLE_END - LOW_MEMORYHOLE_START); //Patch into memory hole!
}
if ((MoveLowMemoryHigh&2) && (memloc>=2)) //Move second block lower?
{
*realaddress -= (MID_MEMORYHOLE_END - MID_MEMORYHOLE_START); //Patch into memory hole!
}
Show last 32 lines
		if ((MoveLowMemoryHigh&4) && (memloc>=3)) //Move third block lower?
{
*realaddress -= (uint_32)((uint_64)HIGH_MEMORYHOLE_END - (uint_64)HIGH_MEMORYHOLE_START); //Patch into memory hole!
}
if ((*realaddress >= MMU.size) || ((*realaddress>=MMU.maxsize) && MMU.maxsize)) //Reserved memory?
{
*nonexistant = 2; //Reserved for reading only!
}
}
if ((*realaddress>=0xFE0000) && (*realaddress<=0xFFFFFF)) //Special area addressed?
{
if (memoryprotect_FE0000 && iswrite) //Memory protected?
{
*nonexistant = 1; //We're non-existant!
return; //Abort!
}
//Reading or not protected?
if (is_Compaq!=1) //Special XT 386 handling?
{
*realaddress -= MIN(MMU.size,MMU.maxsize?MMU.maxsize:MMU.size)-0xE0000; //Patch to physical FE0000-FFFFFF reserved memory range to use!
}
}
if (is_Compaq==1) //Compaq remaps RAM from A0000-FFFFF to FA0000-FFFFFF.
{
//This should be correct, according to PCem: https://bitbucket.org/pcem_emulator/pcem/src/66eec7c1b664f2f1496b5ed3763ec2b2738a6fab/src/compaq.c?at=default
if ((*realaddress>=0xFA0000) && (*realaddress<=0xFFFFFF)) //Remapped RAM area addressed?
{
*nonexistant = 0; //We're to be used directly!
*realaddress &= 0xFFFFF; //Remap the low RAM area high!
}
}
}

Is this correct?

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

Reply 2 of 2, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've improved the memory allocation a bit:

OPTINLINE void applyMemoryHoles(uint_32 *realaddress, byte *nonexistant, byte iswrite)
{
uint_32 originaladdress = *realaddress; //Original address!
INLINEREGISTER byte memloc; //What memory block?
INLINEREGISTER byte memoryhole;
memloc = 0; //Default: first memory block: low memory!
memoryhole = 0; //Default: memory unavailable!
if (*realaddress>=LOW_MEMORYHOLE_START) //Start of first hole?
{
if (*realaddress<LOW_MEMORYHOLE_END) //First hole?
{
memoryhole = 1; //First memory hole!
}
else //Mid memory?
{
memloc = 1; //Second memory block: mid memory!
if (*realaddress>=MID_MEMORYHOLE_START) //Start of second hole?
{
if (*realaddress<MID_MEMORYHOLE_END) //Second hole?
{
memoryhole = 2; //Second memory hole!
}
else //High memory?
{
memloc = 2; //Third memory block!
if ((*realaddress>=HIGH_MEMORYHOLE_START) && ((uint_64)*realaddress<(uint_64)HIGH_MEMORYHOLE_END)) //Start of third hole?
{
memoryhole = 3; //Third memory hole!
}
else
{
memloc = 3; //Fourth memory block!
}
}
}
}
}

if (memoryhole) //Memory hole?
{
*nonexistant = 1; //We're non-existant!
if (BIOSROM_LowMemoryBecomesHighMemory && (memoryhole==1) && BIOSROM_LowMemoryBecomesHighMemory) //Compaq remaps RAM from E0000-FFFFF to FE0000-FFFFFF.
{
if ((originaladdress>=0xE0000) && (originaladdress<=0xFFFFF)) //Low memory hole to remap to the available memory hole memory? This is the size that's defined in MMU_RESERVEDMEMORY!
{
memloc = 2; //We're the second block instead!
originaladdress |= 0xF00000; //Patch to physical FE0000-FFFFFF reserved memory range to use!
}
}
}
else //Plain memory?
{
*nonexistant = 0; //We're to be used directly!
if ((MoveLowMemoryHigh&1) && (memloc)) //Move first block lower?
{
*realaddress -= (LOW_MEMORYHOLE_END - LOW_MEMORYHOLE_START); //Patch into memory hole!
}
if ((MoveLowMemoryHigh&2) && (memloc>=2)) //Move second block lower?
{
*realaddress -= (MID_MEMORYHOLE_END - MID_MEMORYHOLE_START); //Patch into memory hole!
Show last 21 lines
		}
if ((MoveLowMemoryHigh&4) && (memloc>=3)) //Move third block lower?
{
*realaddress -= (uint_32)((uint_64)HIGH_MEMORYHOLE_END - (uint_64)HIGH_MEMORYHOLE_START); //Patch into memory hole!
}
}
if ((originaladdress>=0xFE0000) && (originaladdress<=0xFFFFFF)) //Special area addressed?
{
if (memoryprotect_FE0000 && iswrite) //Memory protected?
{
*nonexistant = 1; //We're non-existant!
return; //Abort!
}
//Reading or not protected?
if (((EMULATED_CPU==CPU_80386) && is_XT) || (is_Compaq==1)) //Compaq or XT reserved area?
{
*realaddress += MMU.size-0xFE0000; //Patch to physical FE0000-FFFFFF reserved memory range to use!
*nonexistant = 3; //Reserved memory!
}
}
}

Now the Compaq Deskpro 80386 detects the FE0000-FFFFFF memory correctly. But for some reason it keeps complaining about memory range 0xFA0000-0xXXXXXX? What memory does it expect to have there?

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