mirror of
https://github.com/86Box/86Box.git
synced 2025-01-22 09:11:50 -05:00
SCAMP: Reworked a lot of stuff, backfill EMS should now also work.
This commit is contained in:
parent
bf0e243c92
commit
ef8a3d8d42
1 changed files with 520 additions and 328 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue