====== Details ====== According to [[https://ext.3dodev.com/3DO/Portfolio_2.5/OnLineDoc/DevDocs/ppgfldr/pgsfldr/spg/01spg003.html#XREF36250|3DO development documents]]:
A minimum 3DO system includes 2 MB of DRAM and 1 MB of VRAM for a total of 3 MB of RAM. Optional memory configurations can, for this version of the hardware, go up to a maximum of 16 MB of RAM: 1 MB of VRAM and 15 MB of DRAM, or 2 MB of VRAM and 14 MB of DRAM.Memory address 0x0330_0004, a MADAM register (MSYSBits), is used to indicate the 3DO's memory configuration. From the Portfolio OS source we find [[http://github.com/trapexit/portfolio_os/blob/master/src/dipir/dipirutils.c#L58|FindMemSize()]] and [[https://github.com/trapexit/portfolio_os/blob/bee7b0c8e4287083c73cb5497b658880c9e7af8e/src/kernel/mem.c#L337|FindRamSize()]].
/*
* Compute size of DRAM based on contents of the Madam System Control Register.
*
* | x8 == 0 | x8 == 0 | x8 == 1
* MSYS | MSYS DRAM | MSYS DRAM | MSYS
* 2:0 VRAM | 6:5 SET0 | 4:3 SET1 | 6:3 DRAM
* --- ---- | ---- ---- | ---- ---- | ---- ----
* | 00 0 MB | 00 0 MB |
* 001 1 MB | 01 1 MB | 01 1 MB | 0101 2 MB
* 010 2 MB | 10 4 MB | 10 4 MB | 1010 8 MB
*
* Combinations not shown in the above tables are not supported and
* this routine is not guaranteed to return anything sensible (even
* though it usually will do something vaguely rational).
*/
void
FindMemSize(uint32 *pDramSize, uint32 *pVramSize)
{
uint32 bits = *MSYSBits;
uint32 dram_size;
uint32 vram_size;
/*
* This may look complex, but it only takes about eight ARM
* instructions to evaluate. Basicly, take each DRAM set size
* field, and double it to get the left-shift count. Then
* shift "a quarter megabyte" left by the count, casting off
* anything less than a megabyte; this is easiest to do if you
* shift "1" left by the count, then right by two. We turn it
* into megabytes later.
*/
dram_size =
(((1<<((bits>> (DRAMSIZE_SET0SHIFT-1))&(DRAMSIZE_SETMASK<<1)))>>2) +
((1<<((bits>> (DRAMSIZE_SET1SHIFT-1))&(DRAMSIZE_SETMASK<<1)))>>2));
vram_size = ((bits & VRAMSIZE_MASK)>> VRAMSIZE_SHIFT);
/* Convert to megabytes */
*pDramSize = dram_size * 1024*1024;
*pVramSize = vram_size * 1024*1024;
}
/*
* FindRamSize(): compute "vram_size" and "dram_size" based on the
* contents of the Madam System Control Register.
*
* | x8 == 0 | x8 == 0 | x8 == 1
* MSYS | MSYS DRAM | MSYS DRAM | MSYS
* 2:0 VRAM | 6:5 SET0 | 4:3 SET1 | 6:3 DRAM
* --- ---- | ---- ---- | ---- ---- | ---- ----
* | 00 0 MB | 00 0 MB |
* 001 1 MB | 01 1 MB | 01 1 MB | 0101 2 MB
* 010 2 MB | 10 4 MB | 10 4 MB | 1010 8 MB
* | 11 16MB |
*
* Combinations not shown in the above tables are not supported and
* this routine is not guaranteed to return anything sensible (even
* though it usually will do something vaguely rational).
*
* Note: only 16 MB address space is available for system memory, so
* the actual amount of DRAM available is reduced so that the sum of
* the DRAM and VRAM is no larger than 16 MB.
*/
void
FindRamSize (void)
{
uint32 bits = *MSYSBits;
/*
* This may look complex, but it only takes about eight ARM
* instructions to evaluate. Basicly, take each DRAM set size
* field, and double it to get the left-shift count. Then
* shift "a quarter megabyte" left by the count, casting off
* anything less than a megabyte; this is easiest to do if you
* shift "1" left by the count, then right by two. We turn it
* into megabytes later.
*/
dram_size =
(((1<<((bits>> (DRAMSIZE_SET0SHIFT-1))&(DRAMSIZE_SETMASK<<1)))>>2) +
((1<<((bits>> (DRAMSIZE_SET1SHIFT-1))&(DRAMSIZE_SETMASK<<1)))>>2));
/*
* Only two VRAM sizes are defined. I'd guess that this gets
* more complex if we start seeing more VRAM sizes.
*/
vram_size = ((bits & VRAMSIZE_MASK)>> VRAMSIZE_SHIFT);
/*
* Opera only provides 16 Megabytes of physical address space
* to contain both the VRAM and DRAM, and the VRAM is above
* the DRAM. If the calculations above give more than 16M of
* total memory, trim DRAM back so the total is exactly 16M.
*/
if ((dram_size + vram_size)> 16)
dram_size = 16 - vram_size;
/*
* The rest of the system wants to deal with byte counts, not
* numbers of megabytes, so be nice to it.
*/
dram_size <<= 20;
vram_size <<= 20;
/*
* As mentioned above, VRAM starts where DRAM ends; note the
* actual VRAM starting address for future consumption.
*/
vram_start = (uint8 *) dram_size;
if (vram_size> ONEMEG)
two_vram_banks = TRUE;
else
two_vram_banks = FALSE;
}
====== TODO ======
* Given there is 48MB of address space between 0x0000_0000 and the ROM at 0x0300_0000 it might be possible to hack the ROM to allow for 16MB + 16MB of DRAM and 16MB of VRAM.
* FreeDO/4DO was hard coded to support the retail model's memory configuration. In the least it should be possible to enhance Opera to support the official permutations.