SCAMP: Reworked a lot of stuff, backfill EMS should now also work.

This commit is contained in:
OBattler 2025-01-16 23:18:41 +01:00
parent bf0e243c92
commit ef8a3d8d42

View file

@ -47,13 +47,35 @@
#define ID_VL82C311 0xd6
#define RAMMAP_REMP386 (1 << 4)
#define RAMMAP_ROMMOV 0x60
#define RAMMAP_ROMMOV1 (1 << 6)
#define RAMMAP_ROMMOV0 (1 << 5)
#define RAMMAP_REMP384 (1 << 4)
#define EMSEN1_EMSMAP (1 << 4)
#define EMSEN1_BFENAB (1 << 6)
#define EMSEN1_EMSENAB (1 << 7)
#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0]))
#define EMS_MAXPAGE 4
#define EMS_PGSIZE 16384
#define EMS_PGMASK 16383
#define MEM_FLAG_SLOTBUS 0x40
#define MEM_FLAG_REMAP 0x20
#define MEM_FLAG_MEMCARD 0x10
#define MEM_FLAG_EMS 0x08
#define MEM_FLAG_ROMCS 0x04
#define MEM_FLAG_READ 0x02
#define MEM_FLAG_WRITE 0x01
#define MEM_FMASK_SLOTBUS 0x40
#define MEM_FMASK_REMAP 0x20
#define MEM_FMASK_MEMCARD 0x10
#define MEM_FMASK_EMS 0x08
#define MEM_FMASK_ROMCS 0x04
#define MEM_FMASK_RW 0x03
/*Commodore SL386SX requires proper memory slot decoding to detect memory size.
Therefore we emulate the SCAMP memory address decoding, and therefore are
limited to the DRAM combinations supported by the actual chip*/
@ -72,10 +94,12 @@ typedef struct ram_struct_t {
int bank;
} ram_struct_t;
typedef struct ems_struct_t {
void *parent;
int segment;
} ems_struct_t;
typedef struct card_mem_t {
int in_ram;
uint32_t virt_addr;
uint32_t phys_addr;
uint8_t *mem;
} mem_page_t;
typedef struct scamp_t {
int cfg_index;
@ -85,13 +109,10 @@ typedef struct scamp_t {
int ems_index;
int ems_autoinc;
uint16_t ems[0x24];
mem_mapping_t ems_mappings[20]; /*a0000-effff*/
uint32_t mappings[20];
uint16_t ems[64];
mem_mapping_t ram_mapping[2];
ram_struct_t ram_struct[2];
ems_struct_t ems_struct[20];
uint32_t ram_virt_base[2];
uint32_t ram_phys_base[2];
@ -101,7 +122,13 @@ typedef struct scamp_t {
int ram_interleaved[2];
int ibank_shift[2];
int ram_flags[24];
int mem_flags[64];
mem_mapping_t mem_mappings[64]; /* The entire first 1 MB of memory space. */
mem_page_t mem_pages[64];
uint32_t card_mem_size;
uint8_t *card_mem;
mem_page_t card_pages[4];
port_92_t *port_92;
} scamp_t;
@ -149,6 +176,70 @@ static const struct {
{ { BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED }, 0}, /*Undocumented - probably wrong!*/
};
#ifdef ENABLE_SCAMP_LOG
int scamp_do_log = ENABLE_SCAMP_LOG;
static void
scamp_log(const char *fmt, ...)
{
va_list ap;
if (scamp_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define scamp_log(fmt, ...)
#endif
/* Read one byte from paged RAM. */
static uint8_t
scamp_mem_readb(uint32_t addr, void *priv)
{
mem_page_t *dev = (mem_page_t *) priv;
uint8_t ret = 0xff;
if (dev->mem != NULL)
ret = *(uint8_t *) &(dev->mem[addr & EMS_PGMASK]);
return ret;
}
/* Read one word from paged RAM. */
static uint16_t
scamp_mem_readw(uint32_t addr, void *priv)
{
mem_page_t *dev = (mem_page_t *) priv;
uint16_t ret = 0xffff;
if (dev->mem != NULL)
ret = *(uint16_t *) &(dev->mem[addr & EMS_PGMASK]);
return ret;
}
/* Write one byte to paged RAM. */
static void
scamp_mem_writeb(uint32_t addr, uint8_t val, void *priv)
{
mem_page_t *dev = (mem_page_t *) priv;
if (dev->mem != NULL)
*(uint8_t *) &(dev->mem[addr & EMS_PGMASK]) = val;
}
/* Write one word to paged RAM. */
static void
scamp_mem_writew(uint32_t addr, uint16_t val, void *priv)
{
mem_page_t *dev = (mem_page_t *) priv;
if (dev->mem != NULL)
*(uint16_t *) &(dev->mem[addr & EMS_PGMASK]) = val;
}
/* The column bits masked when using 256kbit DRAMs in 4Mbit mode aren't contiguous,
so we use separate routines for that special case */
static uint8_t
@ -334,20 +425,23 @@ recalc_mappings(void *priv)
/* Once the BIOS programs the correct DRAM configuration, switch to regular
linear memory mapping */
if (cur_rammap == ram_configs[dev->ram_config].rammap) {
mem_mapping_set_handler(&ram_low_mapping,
mem_read_ram, mem_read_ramw, mem_read_raml,
mem_write_ram, mem_write_ramw, mem_write_raml);
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_disable(&ram_low_mapping);
for (uint8_t i = 0; i < 40; i++)
mem_mapping_enable(&(dev->mem_mappings[i]));
if (mem_size > 1024)
mem_set_mem_state_both((1 << 20), (mem_size - 1024) << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_mapping_enable(&ram_high_mapping);
return;
} else {
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
mem_mapping_disable(&ram_low_mapping);
}
for (uint8_t i = 0; i < 40; i++)
mem_mapping_disable(&(dev->mem_mappings[i]));
if (rammap[cur_rammap].bank[0] == BANK_NONE)
bank_nr = 1;
@ -502,6 +596,7 @@ recalc_mappings(void *priv)
break;
}
}
switch (rammap[cur_rammap].bank[bank_nr]) {
case BANK_256K:
case BANK_1M:
@ -550,124 +645,111 @@ recalc_mappings(void *priv)
break;
}
}
}
static void
recalc_sltptr(scamp_t *dev)
{
uint32_t sltptr = dev->cfg_regs[CFG_SLTPTR] << 16;
if (sltptr >= 0xa0000 && sltptr < 0x100000)
sltptr = 0x100000;
if (sltptr > 0xfe0000)
sltptr = 0xfe0000;
if (sltptr >= 0xa0000) {
mem_set_mem_state(0, 0xa0000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_set_mem_state(0x100000, sltptr - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_set_mem_state(sltptr, 0x1000000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
} else {
mem_set_mem_state(0, sltptr, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_set_mem_state(sltptr, 0xa0000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state(0x100000, 0xf00000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
}
static uint8_t
scamp_ems_read(uint32_t addr, void *priv)
{
const ems_struct_t *ems = (ems_struct_t *) priv;
const scamp_t *dev = ems->parent;
int segment = ems->segment;
addr = (addr & 0x3fff) | dev->mappings[segment];
return ram[addr];
}
static void
scamp_ems_write(uint32_t addr, uint8_t val, void *priv)
scamp_mem_update_state(scamp_t *dev, uint32_t addr, uint32_t size, uint8_t new_flags, uint8_t mask)
{
const ems_struct_t *ems = (ems_struct_t *) priv;
const scamp_t *dev = ems->parent;
int segment = ems->segment;
int read_ext = MEM_READ_EXTERNAL;
int write_ext = MEM_WRITE_EXTERNAL;
addr = (addr & 0x3fff) | dev->mappings[segment];
ram[addr] = val;
}
if ((addr < 0x00100000) && ((new_flags ^ dev->mem_flags[addr / EMS_PGSIZE]) & mask)) {
dev->mem_flags[addr / EMS_PGSIZE] &= ~mask;
dev->mem_flags[addr / EMS_PGSIZE] |= new_flags;
static void
scamp_mem_update_state(scamp_t *dev, uint32_t addr, uint32_t size)
{
uint8_t flags;
new_flags = dev->mem_flags[addr / EMS_PGSIZE];
if ((addr >= 0x000a0000) && (addr < 0x00100000)) {
flags = dev->ram_flags[(addr - 0x000a0000) >> 14];
if (new_flags & MEM_FLAG_ROMCS) {
read_ext = MEM_READ_ROMCS;
write_ext = MEM_WRITE_ROMCS;
}
if (flags & 4)
if (new_flags & (MEM_FLAG_REMAP | MEM_FLAG_SLOTBUS)) {
scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (REMAP)\n", addr, addr + size - 1, new_flags);
mem_set_mem_state(addr, size, read_ext | write_ext);
} else if (new_flags & (MEM_FLAG_EMS | MEM_FLAG_MEMCARD)) {
scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (EMS)\n", addr, addr + size - 1, new_flags);
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else switch (flags & 3) {
} else switch (new_flags & (MEM_FLAG_READ | MEM_FLAG_WRITE)) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (RE | WE)\n", addr, addr + size - 1, new_flags);
mem_set_mem_state(addr, size, read_ext | write_ext);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (RE | WI)\n", addr, addr + size - 1, new_flags);
mem_set_mem_state(addr, size, read_ext | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (RI | WE)\n", addr, addr + size - 1, new_flags);
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | write_ext);
break;
case 3:
scamp_log("scamp_mem_update_state(): %08X-%08X: %02X (RI | WI)\n", addr, addr + size - 1, new_flags);
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
default:
break;
}
}
flushmmucache_nopc();
}
static int
is_seg_in_ram(scamp_t *dev, uint8_t s)
{
mem_page_t *mp = (mem_page_t *) dev->mem_mappings[s].priv;
const int ret = mp->in_ram;
return ret;
}
static void
recalc_ems(scamp_t *dev)
{
const uint32_t ems_base[12] = {
0xc0000, 0xc4000, 0xc8000, 0xcc000,
0xd0000, 0xd4000, 0xd8000, 0xdc000,
0xe0000, 0xe4000, 0xe8000, 0xec000
};
uint32_t new_mappings[20];
uint16_t ems_enable;
const uint8_t seg_xlat[12] = { 40, 41, 42, 43, 52, 53, 54, 55, 44, 45, 46, 47 };
const uint16_t seg_enable = dev->cfg_regs[CFG_EMSEN2] | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 8);
for (int segment = 0; segment < 20; segment++)
new_mappings[segment] = 0xa0000 + segment * 0x4000;
for (uint8_t s = 40; s < 60; s++) {
dev->mem_pages[s].phys_addr = dev->mem_pages[s].virt_addr;
dev->mem_pages[s].mem = ram + dev->mem_pages[s].phys_addr;
if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB)
ems_enable = dev->cfg_regs[CFG_EMSEN2] | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 8);
else
ems_enable = 0;
if (is_seg_in_ram(dev, s))
mem_mapping_set_exec(&(dev->mem_mappings[s]), dev->mem_pages[s].mem);
for (int segment = 0; segment < 12; segment++) {
if (ems_enable & (1 << segment)) {
uint32_t phys_addr = dev->ems[segment] << 14;
/*If physical address is in remapped memory then adjust down to a0000-fffff range*/
if ((dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) && phys_addr >= (mem_size * 1024)
&& phys_addr < ((mem_size + 384) * 1024))
phys_addr = (phys_addr - mem_size * 1024) + 0xa0000;
new_mappings[(ems_base[segment] - 0xa0000) >> 14] = phys_addr;
}
scamp_mem_update_state(dev, s * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_EMS);
}
for (int segment = 0; segment < 20; segment++) {
if (new_mappings[segment] != dev->mappings[segment]) {
dev->mappings[segment] = new_mappings[segment];
if (new_mappings[segment] < (mem_size * 1024)) {
mem_mapping_set_exec(&dev->ems_mappings[segment], ram + dev->mappings[segment]);
mem_mapping_enable(&dev->ems_mappings[segment]);
dev->ram_flags[segment] |= 0x04;
} else {
mem_mapping_disable(&dev->ems_mappings[segment]);
dev->ram_flags[segment] &= 0xfb;
}
for (uint8_t i = 0; i < 36; i++) {
uint8_t s = (i < 12) ? (i + 48) : (i + 4);
uint8_t on = (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB);
uint32_t phys_addr = dev->ems[i] << 14;
scamp_mem_update_state(dev, 0xa0000 + segment * 0x4000, 0x4000);
if (i < 12) {
if (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSMAP)
s = seg_xlat[i];
on = on && (seg_enable & (1 << i));
} else
on = on && (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_BFENAB);
if (on) {
dev->mem_pages[s].phys_addr = phys_addr;
dev->mem_pages[s].mem = ram + dev->mem_pages[s].phys_addr;
if (is_seg_in_ram(dev, s))
mem_mapping_set_exec(&(dev->mem_mappings[s]), dev->mem_pages[s].mem);
scamp_mem_update_state(dev, s * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_EMS, MEM_FMASK_EMS);
} else if (i >= 12) {
dev->mem_pages[s].phys_addr = dev->mem_pages[s].virt_addr;
dev->mem_pages[s].mem = ram + dev->mem_pages[s].phys_addr;
if (is_seg_in_ram(dev, s))
mem_mapping_set_exec(&(dev->mem_mappings[s]), dev->mem_pages[s].mem);
scamp_mem_update_state(dev, s * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_EMS);
}
}
@ -677,32 +759,11 @@ recalc_ems(scamp_t *dev)
static void
shadow_control(scamp_t *dev, uint32_t addr, uint32_t size, int state)
{
dev->ram_flags[(addr - 0x000a0000) >> 14] &= 0xfc;
dev->ram_flags[(addr - 0x000a0000) >> 14] |= state;
if (size == 0x8000) {
dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] &= 0xfc;
dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] |= state;
}
switch (state) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
default:
break;
}
scamp_mem_update_state(dev, addr, size);
scamp_mem_update_state(dev, addr, EMS_PGSIZE, state, MEM_FMASK_RW);
scamp_mem_update_state(dev, addr + EMS_PGSIZE, EMS_PGSIZE, state, MEM_FMASK_RW);
} else
scamp_mem_update_state(dev, addr, size, state, MEM_FMASK_RW);
flushmmucache_nopc();
}
@ -710,14 +771,23 @@ shadow_control(scamp_t *dev, uint32_t addr, uint32_t size, int state)
static void
shadow_recalc(scamp_t *dev)
{
uint8_t abaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_ABAXS];
uint8_t caxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_CAXS];
uint8_t daxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_DAXS];
uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_FEAXS];
uint8_t abaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) ? 0 : dev->cfg_regs[CFG_ABAXS];
uint8_t caxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) ? 0 : dev->cfg_regs[CFG_CAXS];
uint8_t daxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) ? 0 : dev->cfg_regs[CFG_DAXS];
uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) ? 0 : dev->cfg_regs[CFG_FEAXS];
/*Enabling remapping will disable all shadowing*/
if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)
mem_remap_top(384);
if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384)
mem_remap_top_nomid(384);
else
mem_remap_top_nomid(0);
for (uint8_t i = 40; i < 64; i++) {
if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384)
scamp_mem_update_state(dev, (i * EMS_PGSIZE), EMS_PGSIZE, MEM_FLAG_REMAP, MEM_FMASK_REMAP);
else
scamp_mem_update_state(dev, (i * EMS_PGSIZE), EMS_PGSIZE, 0x00, MEM_FMASK_REMAP);
}
shadow_control(dev, 0xa0000, 0x4000, abaxs & 3);
shadow_control(dev, 0xa0000, 0x4000, abaxs & 3);
@ -748,6 +818,97 @@ shadow_recalc(scamp_t *dev)
shadow_control(dev, 0xf8000, 0x8000, (feaxs >> 6) & 3);
}
static void
recalc_sltptr(scamp_t *dev)
{
uint32_t sltptr = dev->cfg_regs[CFG_SLTPTR] << 16;
if (sltptr >= 0xa0000 && sltptr < 0x100000)
sltptr = 0x100000;
if (sltptr > 0xfe0000)
sltptr = 0xfe0000;
if (sltptr >= 0xa0000) {
for (uint8_t i = 0; i < 40; i++)
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_SLOTBUS);
mem_set_mem_state(0x100000, sltptr - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_set_mem_state(sltptr, 0x1000000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if ((sltptr >= 0x40000) && (sltptr <= 0x90000)) {
dev->cfg_regs[CFG_EMSEN1] &= ~EMSEN1_BFENAB;
recalc_ems(dev);
}
} else {
for (uint8_t i = 0; i < (sltptr / EMS_PGSIZE); i++)
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_SLOTBUS);
for (uint8_t i = (sltptr / EMS_PGSIZE); i < 40; i++)
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_SLOTBUS, MEM_FMASK_SLOTBUS);
mem_set_mem_state(sltptr, 0xa0000 - sltptr, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state(0x100000, 0xf00000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
flushmmucache_nopc();
}
static void
recalc_rommov(scamp_t *dev)
{
switch ((dev->cfg_regs[CFG_RAMMAP] & RAMMAP_ROMMOV) >> 5) {
case 0x00:
scamp_mem_update_state(dev, 0x000c0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000c4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000c8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000cc000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e0000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e4000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e8000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000ec000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
break;
case 0x01:
scamp_mem_update_state(dev, 0x000c0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000c4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000c8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000cc000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000ec000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
break;
case 0x02:
scamp_mem_update_state(dev, 0x000c0000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000c4000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000c8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000cc000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e8000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000ec000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
break;
case 0x03:
scamp_mem_update_state(dev, 0x000c0000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000c4000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000c8000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000cc000, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e0000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e4000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000e8000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
scamp_mem_update_state(dev, 0x000ec000, EMS_PGSIZE, 0x00, MEM_FMASK_ROMCS);
break;
}
flushmmucache_nopc();
}
static void
scamp_write(uint16_t addr, uint8_t val, void *priv)
{
@ -755,7 +916,7 @@ scamp_write(uint16_t addr, uint8_t val, void *priv)
switch (addr) {
case 0xe8:
dev->ems_index = val & 0x1f;
dev->ems_index = val & 0x3f;
dev->ems_autoinc = val & 0x40;
break;
@ -785,12 +946,14 @@ scamp_write(uint16_t addr, uint8_t val, void *priv)
switch (dev->cfg_index) {
case CFG_SLTPTR:
recalc_sltptr(dev);
recalc_ems(dev);
break;
case CFG_RAMMAP:
recalc_mappings(dev);
mem_mapping_disable(&ram_remapped_mapping);
shadow_recalc(dev);
recalc_rommov(dev);
break;
case CFG_EMSEN1:
@ -914,9 +1077,8 @@ scamp_init(UNUSED(const device_t *info))
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
mem_mapping_disable(&ram_mid_mapping);
mem_mapping_disable(&ram_high_mapping);
mem_mapping_set_addr(&ram_mid_mapping, 0xf0000, 0x10000);
mem_mapping_set_exec(&ram_mid_mapping, ram + 0xf0000);
addr = 0;
for (uint8_t c = 0; c < 2; c++) {
@ -988,15 +1150,45 @@ scamp_init(UNUSED(const device_t *info))
mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
for (uint8_t c = 0; c < 20; c++) {
dev->ems_struct[c].parent = dev;
dev->ems_struct[c].segment = c;
mem_mapping_add(&dev->ems_mappings[c],
0xa0000 + c * 0x4000, 0x4000,
scamp_ems_read, NULL, NULL,
scamp_ems_write, NULL, NULL,
ram + 0xa0000 + c * 0x4000, MEM_MAPPING_INTERNAL, (void *) &dev->ems_struct[c]);
dev->mappings[c] = 0xa0000 + c * 0x4000;
for (uint8_t i = 0; i < 12; i++)
dev->ems[i] = (0x000c0000 + (i * EMS_PGSIZE)) >> 14;
for (uint8_t i = 0; i < 24; i++)
dev->ems[i + 12] = (0x00040000 + (i * EMS_PGSIZE)) >> 14;
for (uint8_t i = 0; i < 64; i++) {
dev->mem_pages[i].in_ram = 1;
dev->mem_pages[i].virt_addr = i * EMS_PGSIZE;
dev->mem_pages[i].phys_addr = dev->mem_pages[i].virt_addr;
dev->mem_pages[i].mem = ram + dev->mem_pages[i].phys_addr;
mem_mapping_add(&(dev->mem_mappings[i]),
i * EMS_PGSIZE, EMS_PGSIZE,
scamp_mem_readb, scamp_mem_readw, NULL,
scamp_mem_writeb, scamp_mem_writew, NULL,
dev->mem_pages[i].mem, MEM_MAPPING_INTERNAL,
&(dev->mem_pages[i]));
if (i < 40) {
mem_mapping_disable(&(dev->mem_mappings[i]));
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_RW);
} else {
/* This is needed to the state update actually occurs. */
dev->mem_flags[i] = MEM_FLAG_READ | MEM_FLAG_WRITE;
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_RW);
if (i >= 60)
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
}
}
dev->card_mem = NULL;
for (uint8_t i = 0; i < 4; i++) {
dev->card_pages[i].virt_addr = i * EMS_PGSIZE;
dev->card_pages[i].phys_addr = dev->card_pages[i].virt_addr;
dev->card_pages[i].mem = dev->card_mem + dev->card_pages[i].phys_addr;
}
dev->port_92 = device_add(&port_92_device);