SCAMP: Reworked a lot of stuff, backfill EMS should now also work.
This commit is contained in:
@@ -47,13 +47,35 @@
|
|||||||
|
|
||||||
#define ID_VL82C311 0xd6
|
#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_EMSMAP (1 << 4)
|
||||||
|
#define EMSEN1_BFENAB (1 << 6)
|
||||||
#define EMSEN1_EMSENAB (1 << 7)
|
#define EMSEN1_EMSENAB (1 << 7)
|
||||||
|
|
||||||
#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0]))
|
#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.
|
/*Commodore SL386SX requires proper memory slot decoding to detect memory size.
|
||||||
Therefore we emulate the SCAMP memory address decoding, and therefore are
|
Therefore we emulate the SCAMP memory address decoding, and therefore are
|
||||||
limited to the DRAM combinations supported by the actual chip*/
|
limited to the DRAM combinations supported by the actual chip*/
|
||||||
@@ -72,10 +94,12 @@ typedef struct ram_struct_t {
|
|||||||
int bank;
|
int bank;
|
||||||
} ram_struct_t;
|
} ram_struct_t;
|
||||||
|
|
||||||
typedef struct ems_struct_t {
|
typedef struct card_mem_t {
|
||||||
void *parent;
|
int in_ram;
|
||||||
int segment;
|
uint32_t virt_addr;
|
||||||
} ems_struct_t;
|
uint32_t phys_addr;
|
||||||
|
uint8_t *mem;
|
||||||
|
} mem_page_t;
|
||||||
|
|
||||||
typedef struct scamp_t {
|
typedef struct scamp_t {
|
||||||
int cfg_index;
|
int cfg_index;
|
||||||
@@ -85,13 +109,10 @@ typedef struct scamp_t {
|
|||||||
|
|
||||||
int ems_index;
|
int ems_index;
|
||||||
int ems_autoinc;
|
int ems_autoinc;
|
||||||
uint16_t ems[0x24];
|
uint16_t ems[64];
|
||||||
mem_mapping_t ems_mappings[20]; /*a0000-effff*/
|
|
||||||
uint32_t mappings[20];
|
|
||||||
|
|
||||||
mem_mapping_t ram_mapping[2];
|
mem_mapping_t ram_mapping[2];
|
||||||
ram_struct_t ram_struct[2];
|
ram_struct_t ram_struct[2];
|
||||||
ems_struct_t ems_struct[20];
|
|
||||||
|
|
||||||
uint32_t ram_virt_base[2];
|
uint32_t ram_virt_base[2];
|
||||||
uint32_t ram_phys_base[2];
|
uint32_t ram_phys_base[2];
|
||||||
@@ -101,7 +122,13 @@ typedef struct scamp_t {
|
|||||||
int ram_interleaved[2];
|
int ram_interleaved[2];
|
||||||
int ibank_shift[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;
|
port_92_t *port_92;
|
||||||
} scamp_t;
|
} scamp_t;
|
||||||
@@ -149,6 +176,70 @@ static const struct {
|
|||||||
{ { BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED }, 0}, /*Undocumented - probably wrong!*/
|
{ { 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,
|
/* The column bits masked when using 256kbit DRAMs in 4Mbit mode aren't contiguous,
|
||||||
so we use separate routines for that special case */
|
so we use separate routines for that special case */
|
||||||
static uint8_t
|
static uint8_t
|
||||||
@@ -334,20 +425,23 @@ recalc_mappings(void *priv)
|
|||||||
/* Once the BIOS programs the correct DRAM configuration, switch to regular
|
/* Once the BIOS programs the correct DRAM configuration, switch to regular
|
||||||
linear memory mapping */
|
linear memory mapping */
|
||||||
if (cur_rammap == ram_configs[dev->ram_config].rammap) {
|
if (cur_rammap == ram_configs[dev->ram_config].rammap) {
|
||||||
mem_mapping_set_handler(&ram_low_mapping,
|
mem_mapping_disable(&ram_low_mapping);
|
||||||
mem_read_ram, mem_read_ramw, mem_read_raml,
|
|
||||||
mem_write_ram, mem_write_ramw, mem_write_raml);
|
for (uint8_t i = 0; i < 40; i++)
|
||||||
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
|
mem_mapping_enable(&(dev->mem_mappings[i]));
|
||||||
|
|
||||||
if (mem_size > 1024)
|
if (mem_size > 1024)
|
||||||
mem_set_mem_state_both((1 << 20), (mem_size - 1024) << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
mem_set_mem_state_both((1 << 20), (mem_size - 1024) << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||||
mem_mapping_enable(&ram_high_mapping);
|
mem_mapping_enable(&ram_high_mapping);
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
mem_mapping_set_handler(&ram_low_mapping,
|
mem_mapping_set_handler(&ram_low_mapping,
|
||||||
ram_mirrored_read, NULL, NULL,
|
ram_mirrored_read, NULL, NULL,
|
||||||
ram_mirrored_write, NULL, NULL);
|
ram_mirrored_write, NULL, NULL);
|
||||||
|
|
||||||
mem_mapping_disable(&ram_low_mapping);
|
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)
|
if (rammap[cur_rammap].bank[0] == BANK_NONE)
|
||||||
bank_nr = 1;
|
bank_nr = 1;
|
||||||
@@ -502,6 +596,7 @@ recalc_mappings(void *priv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (rammap[cur_rammap].bank[bank_nr]) {
|
switch (rammap[cur_rammap].bank[bank_nr]) {
|
||||||
case BANK_256K:
|
case BANK_256K:
|
||||||
case BANK_1M:
|
case BANK_1M:
|
||||||
@@ -551,123 +646,110 @@ recalc_mappings(void *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
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;
|
int read_ext = MEM_READ_EXTERNAL;
|
||||||
const scamp_t *dev = ems->parent;
|
int write_ext = MEM_WRITE_EXTERNAL;
|
||||||
int segment = ems->segment;
|
|
||||||
|
|
||||||
addr = (addr & 0x3fff) | dev->mappings[segment];
|
if ((addr < 0x00100000) && ((new_flags ^ dev->mem_flags[addr / EMS_PGSIZE]) & mask)) {
|
||||||
ram[addr] = val;
|
dev->mem_flags[addr / EMS_PGSIZE] &= ~mask;
|
||||||
|
dev->mem_flags[addr / EMS_PGSIZE] |= new_flags;
|
||||||
|
|
||||||
|
new_flags = dev->mem_flags[addr / EMS_PGSIZE];
|
||||||
|
|
||||||
|
if (new_flags & MEM_FLAG_ROMCS) {
|
||||||
|
read_ext = MEM_READ_ROMCS;
|
||||||
|
write_ext = MEM_WRITE_ROMCS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
if (new_flags & (MEM_FLAG_REMAP | MEM_FLAG_SLOTBUS)) {
|
||||||
scamp_mem_update_state(scamp_t *dev, uint32_t addr, uint32_t size)
|
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);
|
||||||
uint8_t flags;
|
} 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);
|
||||||
if ((addr >= 0x000a0000) && (addr < 0x00100000)) {
|
|
||||||
flags = dev->ram_flags[(addr - 0x000a0000) >> 14];
|
|
||||||
|
|
||||||
if (flags & 4)
|
|
||||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
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:
|
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;
|
break;
|
||||||
case 1:
|
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;
|
break;
|
||||||
case 2:
|
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;
|
break;
|
||||||
case 3:
|
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);
|
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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
|
static void
|
||||||
recalc_ems(scamp_t *dev)
|
recalc_ems(scamp_t *dev)
|
||||||
{
|
{
|
||||||
const uint32_t ems_base[12] = {
|
const uint8_t seg_xlat[12] = { 40, 41, 42, 43, 52, 53, 54, 55, 44, 45, 46, 47 };
|
||||||
0xc0000, 0xc4000, 0xc8000, 0xcc000,
|
const uint16_t seg_enable = dev->cfg_regs[CFG_EMSEN2] | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 8);
|
||||||
0xd0000, 0xd4000, 0xd8000, 0xdc000,
|
|
||||||
0xe0000, 0xe4000, 0xe8000, 0xec000
|
|
||||||
};
|
|
||||||
uint32_t new_mappings[20];
|
|
||||||
uint16_t ems_enable;
|
|
||||||
|
|
||||||
for (int segment = 0; segment < 20; segment++)
|
for (uint8_t s = 40; s < 60; s++) {
|
||||||
new_mappings[segment] = 0xa0000 + segment * 0x4000;
|
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)
|
if (is_seg_in_ram(dev, s))
|
||||||
ems_enable = dev->cfg_regs[CFG_EMSEN2] | ((dev->cfg_regs[CFG_EMSEN1] & 0xf) << 8);
|
mem_mapping_set_exec(&(dev->mem_mappings[s]), dev->mem_pages[s].mem);
|
||||||
else
|
|
||||||
ems_enable = 0;
|
|
||||||
|
|
||||||
for (int segment = 0; segment < 12; segment++) {
|
scamp_mem_update_state(dev, s * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_EMS);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int segment = 0; segment < 20; segment++) {
|
for (uint8_t i = 0; i < 36; i++) {
|
||||||
if (new_mappings[segment] != dev->mappings[segment]) {
|
uint8_t s = (i < 12) ? (i + 48) : (i + 4);
|
||||||
dev->mappings[segment] = new_mappings[segment];
|
uint8_t on = (dev->cfg_regs[CFG_EMSEN1] & EMSEN1_EMSENAB);
|
||||||
if (new_mappings[segment] < (mem_size * 1024)) {
|
uint32_t phys_addr = dev->ems[i] << 14;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
static void
|
||||||
shadow_control(scamp_t *dev, uint32_t addr, uint32_t size, int state)
|
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) {
|
if (size == 0x8000) {
|
||||||
dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] &= 0xfc;
|
scamp_mem_update_state(dev, addr, EMS_PGSIZE, state, MEM_FMASK_RW);
|
||||||
dev->ram_flags[((addr - 0x000a0000) >> 14) + 1] |= state;
|
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);
|
||||||
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);
|
|
||||||
|
|
||||||
flushmmucache_nopc();
|
flushmmucache_nopc();
|
||||||
}
|
}
|
||||||
@@ -710,14 +771,23 @@ shadow_control(scamp_t *dev, uint32_t addr, uint32_t size, int state)
|
|||||||
static void
|
static void
|
||||||
shadow_recalc(scamp_t *dev)
|
shadow_recalc(scamp_t *dev)
|
||||||
{
|
{
|
||||||
uint8_t abaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) ? 0 : dev->cfg_regs[CFG_ABAXS];
|
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_REMP386) ? 0 : dev->cfg_regs[CFG_CAXS];
|
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_REMP386) ? 0 : dev->cfg_regs[CFG_DAXS];
|
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_REMP386) ? 0 : dev->cfg_regs[CFG_FEAXS];
|
uint8_t feaxs = (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384) ? 0 : dev->cfg_regs[CFG_FEAXS];
|
||||||
|
|
||||||
/*Enabling remapping will disable all shadowing*/
|
/*Enabling remapping will disable all shadowing*/
|
||||||
if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)
|
if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP384)
|
||||||
mem_remap_top(384);
|
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);
|
||||||
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);
|
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
|
static void
|
||||||
scamp_write(uint16_t addr, uint8_t val, void *priv)
|
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) {
|
switch (addr) {
|
||||||
case 0xe8:
|
case 0xe8:
|
||||||
dev->ems_index = val & 0x1f;
|
dev->ems_index = val & 0x3f;
|
||||||
dev->ems_autoinc = val & 0x40;
|
dev->ems_autoinc = val & 0x40;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -785,12 +946,14 @@ scamp_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
switch (dev->cfg_index) {
|
switch (dev->cfg_index) {
|
||||||
case CFG_SLTPTR:
|
case CFG_SLTPTR:
|
||||||
recalc_sltptr(dev);
|
recalc_sltptr(dev);
|
||||||
|
recalc_ems(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CFG_RAMMAP:
|
case CFG_RAMMAP:
|
||||||
recalc_mappings(dev);
|
recalc_mappings(dev);
|
||||||
mem_mapping_disable(&ram_remapped_mapping);
|
mem_mapping_disable(&ram_remapped_mapping);
|
||||||
shadow_recalc(dev);
|
shadow_recalc(dev);
|
||||||
|
recalc_rommov(dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CFG_EMSEN1:
|
case CFG_EMSEN1:
|
||||||
@@ -914,9 +1077,8 @@ scamp_init(UNUSED(const device_t *info))
|
|||||||
mem_mapping_set_handler(&ram_low_mapping,
|
mem_mapping_set_handler(&ram_low_mapping,
|
||||||
ram_mirrored_read, NULL, NULL,
|
ram_mirrored_read, NULL, NULL,
|
||||||
ram_mirrored_write, NULL, NULL);
|
ram_mirrored_write, NULL, NULL);
|
||||||
|
mem_mapping_disable(&ram_mid_mapping);
|
||||||
mem_mapping_disable(&ram_high_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;
|
addr = 0;
|
||||||
for (uint8_t c = 0; c < 2; c++) {
|
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);
|
mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||||
|
|
||||||
for (uint8_t c = 0; c < 20; c++) {
|
for (uint8_t i = 0; i < 12; i++)
|
||||||
dev->ems_struct[c].parent = dev;
|
dev->ems[i] = (0x000c0000 + (i * EMS_PGSIZE)) >> 14;
|
||||||
dev->ems_struct[c].segment = c;
|
|
||||||
mem_mapping_add(&dev->ems_mappings[c],
|
for (uint8_t i = 0; i < 24; i++)
|
||||||
0xa0000 + c * 0x4000, 0x4000,
|
dev->ems[i + 12] = (0x00040000 + (i * EMS_PGSIZE)) >> 14;
|
||||||
scamp_ems_read, NULL, NULL,
|
|
||||||
scamp_ems_write, NULL, NULL,
|
for (uint8_t i = 0; i < 64; i++) {
|
||||||
ram + 0xa0000 + c * 0x4000, MEM_MAPPING_INTERNAL, (void *) &dev->ems_struct[c]);
|
dev->mem_pages[i].in_ram = 1;
|
||||||
dev->mappings[c] = 0xa0000 + c * 0x4000;
|
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);
|
dev->port_92 = device_add(&port_92_device);
|
||||||
|
|||||||
Reference in New Issue
Block a user