Support 'strange' memory sizes, such as 256K, 192K

Additional ROM patches manually set the memTop variable to a given
memory size, and the memory test routine is skipped.  This allows
the Plus ROM to cope with a Mac 256K configuration, but also non-
power-of-two sizes.  That's useful for an MCU, making a Mac 208K,
Mac 192K, etc. possible.

Memory addresses are clamped such that wrapping within the RAM
region works, and any emulated address can be used without
overflowing the host RAM allocation.  For a power-of-two memory
size this boils down (after compiler optimisation) to a plain
tmask; for non-Po2, this involves a divide/mod in the weird ROM
probing "off the end" cases, and a simple compare in all other
runtime cases (so shouldn't be too slow).
This commit is contained in:
Matt Evans 2024-07-01 22:54:58 +01:00
parent 1ada25b956
commit 954636e9db
3 changed files with 34 additions and 10 deletions

View file

@ -78,6 +78,13 @@ extern int overlay;
/* RAM: always at 0x600000-0x7fffff, sometimes at 0 (0 most likely so check first!) */
#define IS_RAM(x) ((!overlay && ((ADR24(x) & 0xc00000) == 0)) || ((ADR24(x) & 0xe00000) == RAM_HIGH_ADDR))
/* For regular power-of-two memory sizes, this should resolve to a
* simple mask (i.e. be fast). For non-Po2 (e.g. a Mac208K), this
* involves a divide when an access is made off the end of memory.
* But, that should never happen post-boot.
*/
#define CLAMP_RAM_ADDR(x) ((x) >= RAM_SIZE ? (x) % RAM_SIZE : (x))
#define IS_VIA(x) ((ADR24(x) & 0xe80000) == 0xe80000)
#define IS_IWM(x) ((ADR24(x) >= 0xdfe1ff) && (ADR24(x) < (0xdfe1ff + 0x2000)))
#define IS_SCC_RD(x) ((ADR24(x) & 0xf00000) == 0x900000)

View file

@ -341,7 +341,7 @@ static unsigned int FAST_FUNC(cpu_read_instr_normal)(unsigned int address)
{
/* Can check for 0x400000 (ROM) and otherwise RAM */
if ((address & 0xf00000) != ROM_ADDR)
return RAM_RD_ALIGNED_BE16(address & (RAM_SIZE - 1));
return RAM_RD_ALIGNED_BE16(CLAMP_RAM_ADDR(address));
else
return ROM_RD_ALIGNED_BE16(address & (ROM_SIZE - 1));
}
@ -353,7 +353,7 @@ static unsigned int FAST_FUNC(cpu_read_instr_overlay)(unsigned int address)
if (IS_ROM(address))
return ROM_RD_ALIGNED_BE16(address & (ROM_SIZE - 1));
else /* RAM */
return RAM_RD_ALIGNED_BE16(address & (RAM_SIZE - 1));
return RAM_RD_ALIGNED_BE16(CLAMP_RAM_ADDR(address));
}
unsigned int (*cpu_read_instr)(unsigned int address) = cpu_read_instr_overlay;
@ -363,7 +363,7 @@ unsigned int FAST_FUNC(cpu_read_byte)(unsigned int address)
{
/* Most likely a RAM access, followed by a ROM access, then I/O */
if (IS_RAM(address))
return RAM_RD8(address & (RAM_SIZE - 1));
return RAM_RD8(CLAMP_RAM_ADDR(address));
if (IS_ROM(address))
return ROM_RD8(address & (ROM_SIZE - 1));
@ -384,7 +384,7 @@ unsigned int FAST_FUNC(cpu_read_byte)(unsigned int address)
unsigned int FAST_FUNC(cpu_read_word)(unsigned int address)
{
if (IS_RAM(address))
return RAM_RD16(address & (RAM_SIZE - 1));
return RAM_RD16(CLAMP_RAM_ADDR(address));
if (IS_ROM(address))
return ROM_RD16(address & (ROM_SIZE - 1));
@ -398,7 +398,7 @@ unsigned int FAST_FUNC(cpu_read_word)(unsigned int address)
unsigned int FAST_FUNC(cpu_read_long)(unsigned int address)
{
if (IS_RAM(address))
return RAM_RD32(address & (RAM_SIZE - 1));
return RAM_RD32(CLAMP_RAM_ADDR(address));
if (IS_ROM(address))
return ROM_RD32(address & (ROM_SIZE - 1));
@ -413,7 +413,7 @@ unsigned int FAST_FUNC(cpu_read_long)(unsigned int address)
unsigned int cpu_read_word_dasm(unsigned int address)
{
if (IS_RAM(address))
return RAM_RD16(address & (RAM_SIZE - 1));
return RAM_RD16(CLAMP_RAM_ADDR(address));
if (IS_ROM(address))
return ROM_RD16(address & (ROM_SIZE - 1));
@ -424,7 +424,7 @@ unsigned int cpu_read_word_dasm(unsigned int address)
unsigned int cpu_read_long_dasm(unsigned int address)
{
if (IS_RAM(address))
return RAM_RD32(address & (RAM_SIZE - 1));
return RAM_RD32(CLAMP_RAM_ADDR(address));
if (IS_ROM(address))
return ROM_RD32(address & (ROM_SIZE - 1));
@ -437,7 +437,7 @@ unsigned int cpu_read_long_dasm(unsigned int address)
void FAST_FUNC(cpu_write_byte)(unsigned int address, unsigned int value)
{
if (IS_RAM(address)) {
RAM_WR8(address & (RAM_SIZE - 1), value);
RAM_WR8(CLAMP_RAM_ADDR(address), value);
return;
}
@ -468,7 +468,7 @@ void FAST_FUNC(cpu_write_byte)(unsigned int address, unsigned int value)
void FAST_FUNC(cpu_write_word)(unsigned int address, unsigned int value)
{
if (IS_RAM(address)) {
RAM_WR16(address & (RAM_SIZE - 1), value);
RAM_WR16(CLAMP_RAM_ADDR(address), value);
return;
}
printf("Ignoring write %04x to address %08x\n", value&0xffff, address);
@ -477,7 +477,7 @@ void FAST_FUNC(cpu_write_word)(unsigned int address, unsigned int value)
void FAST_FUNC(cpu_write_long)(unsigned int address, unsigned int value)
{
if (IS_RAM(address)) {
RAM_WR32(address & (RAM_SIZE - 1), value);
RAM_WR32(CLAMP_RAM_ADDR(address), value);
return;
}
printf("Ignoring write %08x to address %08x\n", value, address);

View file

@ -97,6 +97,23 @@ static void rom_patch_plusv3(uint8_t *rom_base)
* - No IWM init
* - new Sound?
*/
#if UMAC_MEMSIZE > 128 && UMAC_MEMSIZE < 512
/* Hack to change memtop: try out a 256K Mac :) */
for (int i = 0x376; i < 0x37e; i += 2)
ROM_WR16(i, M68K_INST_NOP);
ROM_WR16(0x376, 0x2a7c); // moveal #RAM_SIZE, A5
ROM_WR16(0x378, RAM_SIZE >> 16);
ROM_WR16(0x37a, RAM_SIZE & 0xffff);
/* That overrides the probed memory size, but
* P_ChecksumRomAndTestMemory returns a failure code for
* things that aren't 128/512. Skip that:
*/
ROM_WR16(0x132, 0x6000); // Bra (was BEQ)
/* FIXME: We should also remove the memory probe routine, by
* allowing the ROM checksum to fail (it returns failure, then
* we carry on). This avoids wild RAM addrs being accessed.
*/
#endif
}
int rom_patch(uint8_t *rom_base)