namespace FMTOWNS {
// Note: Bank width will be 0x2000 bytes.
+void TOWNS_MEMORY::set_device_range_r(DEVICE* dev, uint32_t begin_addr, uint32_t end_addr)
+{
+ if(begin_addr >= 0xc40000000) return;
+ if(begin_addr < 0xc0000000) {
+ if(begin_addr >= 0x80000000) {
+ if(begin_addr < 0x84000000) {
+ if(end_addr >= 0x84000000) {
+ end_addr = 0x84000000;
+ }
+ for(uint32_t addr = begin_addr, uint32_t i = 0; addr < end_addr; addr += 0x00020000, i++) {
+ devmap_80000000h[i] = dev;
+ //offsetmap_80000000h[i] = addr - begin_addr;
+ }
+ return;
+ }
+ return;
+ } else if(begin_addr < 0x000f0000) {
+ if(begin_addr >= 0x000c0000) {
+ if(end_addr >= 0x000f0000) {
+ end_addr = 0x000f0000;
+ }
+ for(uint32_t addr = begin_addr, uint32_t i = 0; addr < end_addr; addr += 0x00001000, i++) {
+ devmap_c0000h_read[i] = dev;
+ //offsetmap_c0000h_read[i] = addr - begin_addr;
+ }
+ return;
+ }
+ }
+ return;
+ }
+ // C0000000h - C3ffffffh
+ if(end_addr >= 0xc4000000) {
+ end_addr = 0xc4000000;
+ }
+ for(uint32_t addr = begin_addr, uint32_t i = 0; addr < end_addr; addr += 0x00001000, i++) {
+ devmap_c0000000h_read[i] = dev;
+ //offsetmap_c0000000h_read[i] = addr - begin_addr;
+ }
+}
+
+void TOWNS_MEMORY::set_device_range_w(DEVICE* dev, uint32_t begin_addr, uint32_t end_addr)
+{
+ if(begin_addr >= 0xc40000000) return;
+ if(begin_addr < 0xc0000000) {
+ if(begin_addr >= 0x80000000) {
+ if(begin_addr < 0x84000000) {
+ if(end_addr >= 0x84000000) {
+ end_addr = 0x84000000;
+ }
+ for(uint32_t addr = begin_addr, uint32_t i = 0; addr < end_addr; addr += 0x00020000, i++) {
+ devmap_80000000h[i] = dev;
+ //offsetmap_80000000h[i] = addr - begin_addr;
+ }
+ return;
+ }
+ return;
+ } else if(begin_addr < 0x000f0000) {
+ if(begin_addr >= 0x000c0000) {
+ if(end_addr >= 0x000f0000) {
+ end_addr = 0x000f0000;
+ }
+ for(uint32_t addr = begin_addr, uint32_t i = 0; addr < end_addr; addr += 0x00001000, i++) {
+ devmap_c0000h_write[i] = dev;
+ //offsetmap_c0000h_write[i] = addr - begin_addr;
+ }
+ return;
+ }
+ }
+ return;
+ }
+ // C0000000h - C3ffffffh
+ if(end_addr >= 0xc4000000) {
+ end_addr = 0xc4000000;
+ }
+ for(uint32_t addr = begin_addr, uint32_t i = 0; addr < end_addr; addr += 0x00001000, i++) {
+ devmap_c0000000h_write[i] = dev;
+ //offsetmap_c0000000h_write[i] = addr - begin_addr;
+ }
+}
+
+
void TOWNS_MEMORY::config_page_c0()
{
if(dma_is_vram) {
set_memory_mapped_io_r (0x000f8000, 0x000fffff, d_sysrom);
unset_memory_w (0x000f8000, 0x000fffff);
} else {
- set_memory_rw (0x000f8000, 0x000fffff, &(ram_pagef[0x8000]));
+ set_memory_rw (0x000f8000, 0x000fffff, &(ram_paged[0x28000]));
}
}
memset(ram_page0, 0x00, sizeof(ram_page0));
memset(ram_pagec, 0x00, sizeof(ram_pagec));
memset(ram_paged, 0x00, sizeof(ram_paged));
- memset(ram_pagef, 0x00, sizeof(ram_pagef));
select_d0_dict = false;
select_d0_rom = true;
// Lower 100000h
set_memory_rw (0x00000000, 0x000bffff, ram_page0);
- set_memory_rw (0x000f0000, 0x000f7fff, ram_pagef);
+ set_memory_rw (0x000f0000, 0x000f7fff, &(ram_paged[0x20000]));
config_page00();
set_memory_mapped_io_rw(0x80000000, 0x8007ffff, d_vram);
return;
}
+uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int* wait)
+{
+ int waitval;
+ bool is_exists;
+ uintptr_t memptr;
+ uint32_t offset;
+
+ DEVICE* dev = select_bank_memory_mpu(addr, false, true, is_exists, memptr, offset, waitval);
+
+ __UNLIKELY_IF(!(is_exists)) {
+ __LIKELY_IF(wait != NULL) {
+ *wait = mem_wait_val;
+ }
+ return 0xff;
+ }
+ __LIKELY_IF(dev == NULL) {
+ __LIKELY_IF(wait != NULL) {
+ *wait = mem_wait_val;
+ }
+ __LIKELY_IF(memptr != UINTPTR_MAX) {
+ uint8_t* p = (uint8_t*)memptr;
+ return memptr[offset];
+ }
+ return 0xff; // OK?
+ } else { // DEVICE
+ __LIKELY_IF(wait != NULL) {
+ *wait = waitval;
+ }
+ __LIKELY_IF(offset == UINT32_MAX) {
+ // THROUGH ADDRESS
+ return dev->read_memory_mapped_io8(addr);
+ } else {
+ return dev->read_memory_mapped_io8(offset);
+ }
+ }
+ return 0xff;
+}
+
+uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int* wait)
+{
+ int waitval;
+ bool is_exists;
+ uintptr_t memptr;
+ uint32_t offset;
+
+ int waitval2;
+ bool is_exists2;
+ uintptr_t memptr2;
+ uint32_t offset2;
+
+ DEVICE* dev = select_bank_memory_mpu(addr, false, true, is_exists, memptr, offset, waitval);
+ DEVICE* dev2 = select_bank_memory_mpu(((addr & 0x0ffe) + 1) + (addr & 0xfffff000)), false, true, is_exists2, memptr2, offset2, waitval2);
+
+ __UNLIKELY_IF(!(is_exists) && !(is_exists2)) {
+ __LIKELY_IF(wait != NULL) {
+ *wait = mem_wait_val;
+ }
+ return 0xffff;
+ }
+ // ToDO: Implement correctness.
+ __LIKELY_IF(dev == NULL) {
+ __LIKELY_IF(wait != NULL) {
+ *wait = mem_wait_val;
+ }
+ bool is_boundary = ((addr & 0x7fff) == 0x7fff) ? true : false;
+ __UNLIKELY_IF(addr == 0x000cff7f) {
+ is_boundary = true;
+ }
+ __LIKELY_IF(memptr != UINTPTR_MAX) {
+ uint8_t* p = (uint8_t*)memptr;
+ pair16_t nd;
+ __LIKELY_IF(!(is_boundary)) {
+ nd.read_2bytes_le_from(p);
+ } else {
+ nd.b.l = p[0];
+ int waitval2;
+ DEVICE* dev2 = select_bank_memory_mpu(addr + 1, false, true, is_exists, memptr, offset, waitval2);
+ __LIKELY_IF(dev2 == NULL) {
+ // UNCHANGED WAIT
+ nd.b.h = p[1];
+ } else {
+ __LIKELY_IF(offset == UINT32_MAX) {
+ nd.b.h = dev2->read_memory_mapped_io8(addr + 1);
+ } else {
+ nd.b.h = dev2->read_memory_mapped_io8(offset);
+ }
+ __LIKELY_IF(wait != NULL) {
+ *wait += waitval2;
+ }
+ }
+ }
+ return nd.w;
+ }
+ return 0xffff; // OK?
+ } else { // DEVICE
+ __LIKELY_IF(wait != NULL) {
+ *wait = waitval;
+ }
+ __LIKELY_IF(offset == UINT32_MAX) {
+ // THROUGH ADDRESS
+ return dev->read_memory_mapped_io16(addr);
+ } else {
+ return dev->read_memory_mapped_io16(offset);
+ }
+ }
+ return 0xffff;
+}
+
+uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int* wait)
+{
+ int waitval;
+ bool is_exists;
+ uintptr_t memptr;
+ uint32_t offset;
+
+ int waitval2;
+ bool is_exists2;
+ uintptr_t memptr2;
+ uint32_t offset2;
+
+ pair32_t dat;
+
+ DEVICE* dev = select_bank_memory_mpu(addr, false, true, is_exists, memptr, offset, waitval);
+ DEVICE* dev2 = select_bank_memory_mpu(((addr & 0x0ffc) + 3) + (addr & 0xfffff000)), false, true, is_exists2, memptr2, offset2, waitval2);
+ if(!(is_exists) && !(is_exists2)) {
+ __LIKELY_IF(wait != NULL) {
+ *wait = mem_wait_val;
+ }
+ return 0xffffffff; // OK?
+ }
+
+ dat.d = 0xffffffff; // OK?
+
+ uint32_t bytes1 = 4 - (addr & 3);
+ uint32_t bytes2 = 4 - bytes1;
+ uint32_t addr1 = (offset == UINT32_MAX) ? addr : offset;
+ uint32_t addr2 = (offset2 == UINT32_MAX) ? (addr + bytes1) : offset2;
+ __LIKELY_IF((dev == NULL) && (dev2 == NULL)) {
+ __LIKELY_IF((is_exists) && (memptr != UINTPTR_MAX)) {
+ uint8_t *ptr1 = (uint8_t*)(memptr + (uintptr_t)((offset == UINT32_MAX) ? 0 : offset));
+ dat.read_4bytes_le_from(p);
+ }
+ waitval = ((addr & 3) == 0) ? mem_wait_val : (mem_wait_val * 2); // OK?
+ __LIKELY_IF(wait != NULL) {
+ *wait = waitval;
+ }
+ return dat.d;
+ }
+ __LIKELY_IF(dev != NULL) {
+ __LIKELY_IF(bytes1 > 1) {
+ dat.w.l = dev->read_memory_mapped_io16(addr1);
+ }
+ __UNLIKELY_IF(bytes1 == 3) {
+ dat.b.h = dev->read_memory_mapped_io8(addr1 + 2);
+ } else if(bytes1 > 3) {
+ dat.w.h = dev->read_memory_mapped_io16(addr1 + 2);
+ } else if(bytes1 == 1) {
+ dat.b.l = dev->read_memory_mapped_io8(addr1);
+ }
+ if((bytes1 & 3) != 0) {
+ waitval = waitval * 2;
+ }
+ } else if(memptr != UINTPTR_MAX) {
+ uint8_t *ptr1 = (uint8_t*)(memptr + (uintptr_t)((offset == UINT32_MAX) ? 0 : offset));
+ switch(bytes1) {
+ case 0:
+ break;
+ case 1:
+ dat.b.l = ptr1[0];
+ waitval = mem_wait_val * 2;
+ break;
+ case 2:
+ dat.b.l = ptr1[0];
+ dat.b.h = ptr1[1];
+ waitval = mem_wait_val * 2;
+ break;
+ case 3:
+ dat.b.l = ptr1[0];
+ dat.b.h = ptr1[1];
+ dat.b.h2 = ptr1[2];
+ waitval = mem_wait_val * 2;
+ break;
+ default:
+ dat.read_4bytes_le_from(ptr1);
+ waitval = mem_wait_val;
+ break;
+ }
+ }
+ __LIKELY_IF(dev2 != NULL) {
+ switch(bytes2) {
+ case 0:
+ break;
+ case 1:
+ dat.b.h3 = dev2->read_memory_mapped_io8(addr2);
+ waitval += waitval2
+ break;
+ case 2:
+ dat.w.h = dev2->read_memory_mapped_io16(addr2);
+ waitval += waitval2
+ break;
+ case 3:
+ w.w = dev2->read_memory_mapped_io16(addr2);
+ dat.b.h = w.b.l;
+ dat.b.h2 = w.b.h;
+ dat.b.h3 = dev2->read_memory_mapped_io8(addr2);
+ waitval += waitval2
+ break;
+ default:
+ dat.d = dev2->read_memory_mapped_io32(addr2);
+ waitval = waitval2;
+ break;
+ }
+ } else if(memptr2 != UINTPTR_MAX) {
+ uint8_t *ptr2 = (uint8_t*)(memptr2 + (uintptr_t)((offset2 == UINT32_MAX) ? 0 : offset2));
+ switch(bytes2) {
+ case 0:
+ break;
+ case 1:
+ dat.b.h3 = ptr2[0];
+ waitval = waitval + mem_wait_val;
+ break;
+ case 2:
+ dat.b.h2 = ptr2[0];
+ dat.b.h3 = ptr2[1];
+ waitval = waitval + mem_wait_val;
+ break;
+ case 3:
+ dat.b.h = ptr2[0];
+ dat.b.h2 = ptr2[1];
+ dat.b.h3 = ptr2[2];
+ waitval = waitval + mem_wait_val;
+ break;
+ default:
+ dat.read_4bytes_le_from(ptr2);
+ waitval = mem_wait_val;
+ break;
+ }
+ }
+ __LIKELY_IF(wait != NULL) {
+ *wait = waitval;
+ }
+ return dat.d;
+}
+
+
uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
{
int wait = 0;
state_fio->StateArray(ram_page0, sizeof(ram_page0), 1);
state_fio->StateArray(ram_pagec, sizeof(ram_pagec), 1);
state_fio->StateArray(ram_paged, sizeof(ram_paged), 1);
- state_fio->StateArray(ram_pagef, sizeof(ram_pagef), 1);
state_fio->StateValue(select_d0_rom);
state_fio->StateValue(select_d0_dict);
}
namespace FMTOWNS {
-class TOWNS_MEMORY : public MEMORY
+class TOWNS_MEMORY : public DEVICE
{
protected:
DEVICE* d_vram;
DEVICE* d_sprite; // 0x81000000 - 0x8101ffff ?
- DEVICE* d_romcard[2]; // 0xc0000000 - 0xc0ffffff / 0xc1000000 - 0xc1ffffff
DEVICE* d_pcm; // 0xc2200000 - 0xc2200fff
DEVICE* d_timer;
DEVICE* d_dmac;
DEVICE* d_iccard[2];
- outputs_t outputs_ram_wait;
+ // Add memory MAP
+ DEVICE* devmap_c0000h_read[0x00030000 >> 12]; // Per 1000h bytes
+ uint32_t offsetmap_c0000h_read[0x00030000 >> 12];
+ DEVICE* devmap_c0000h_write[0x00030000 >> 12]; // Per 1000h bytes
+ uint32_t offsetmap_c0000h_write[0x00030000 >> 12];
+
+ DEVICE* devmap_80000000h[0x04000000 >> 17];
+ uint32_t offsetmap_80000000h[0x04000000 >> 17];
+
+ DEVICE* devmap_c0000000h_read[0x04000000 >> 12];
+ uint32_t offsetmap_c0000000h_read[0x04000000 >> 12];
+ DEVICE* devmap_c0000000h_write[0x04000000 >> 12];
+ uint32_t offsetmap_c0000000h_write[0x04000000 >> 12];
+
+ virtual inline __FASTCALL DEVICE* select_bank_memory_mpu(uint32_t addr, constexpr bool is_dma, constexpr bool is_read, bool& is_exists, uintptr_t& memptr, uint32_t& offset, int& waitval)
+ {
+ memptr = UINTPTR_MAX;
+ offset = UINT32_MAX;
+ waitval = mem_wait_val;
+ is_exists = false;
+ __LIKELY_IF(addr < (extram_size + 0x00100000)) {
+ __LIKELY_IF(addr >= 0x00100000) { // Extra RAM
+ is_exists = (extra_ram != NULL) ? true : false;
+ offset = addr - 0x00100000;
+ memptr = (uintptr_t)extra_ram;
+ return NULL;
+ }
+ __LIKELY_IF(addr < 0x000c0000) { // 1st RAM
+ is_exists = true;
+ offset = addr;
+ memptr = (uintptr_t)ram_page0;
+ return NULL;
+ }
+ __LIKELY_IF((dma_is_vram) && (addr < 0x000f0000)) {
+ uint32_t map_ptr = (addr - 0x000c0000) >> 12; // Per 4KBytes
+ DEVICE* p = (is_read) ? devmap_c0000h_read[map_ptr] : devmap_c0000h_write[map_ptr];
+ __LIKELY_IF(p != NULL) {
+ is_exists = true;
+ offset = (is_read) ? offsetmap_c0000h_read[map_ptr] : offsetmap_c0000h_write[map_ptr];
+ __UNLIKELY_IF(addr < 0x000d0000) {
+ waitval = vram_wait_val;
+ }
+ }
+ return p;
+ }
+ __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000d0000)) { // MMIO
+ is_exists = true;
+ return this;
+ }
+ // 0x000f8000 - 0x000fffff
+ __LIKELY_IF((select_d0_rom) && (addr >= 0x000f8000)) {
+ is_exists = (is_read) ? true : false;
+ offset = (addr - 0x000f8000) + 0x38000;
+ return (is_read) ? d_sysrom : NULL;
+ }
+ is_exists = true;
+ offset = addr - 0x0000c0000;
+ memptr = (uintptr_t)ram_pagec;
+ return NULL;
+ }
+ __LIKELY_IF(addr >= 0x80000000) {
+ __LIKELY_IF(addr >= 0xfffc0000) { // SYSROM
+ is_exists = true;
+ offset = addr - 0xfffc0000;
+ return d_sysrom;
+ }
+ __LIKELY_IF(addr < 0x84000000) { // VRAM
+ uint32_t map_ptr = (addr - 0x80000000) >> 17; // Per 128KBytes
+ DEVICE* p = devmap_80000000h[map_ptr];
+ waitval = vram_wait_val; // ToDo.
+ __LIKELY_IF(p != NULL) {
+ offset = offsetmap_80000000h[map_ptr];
+ is_exists = true;
+ }
+ return p;
+ }
+ __LIKELY_IF(addr >= 0xc0000000) {
+ __LIKELY_IF(addr < 0xc2400000) { // MISC DEVICES
+ uint32_t map_ptr = (addr - 0xc0000000) >> 12; // Per 4KBytes
+ DEVICE* p = (is_read) ? devmap_c0000000h_read[map_ptr] : devmap_c0000000h_write[map_ptr];
+ __LIKELY_IF(p != NULL) {
+ offset = (is_read) ? offsetmap_c0000000h_read[map_ptr] : offsetmap_c0000000h_write[map_ptr];
+ is_exists = true;
+ }
+ return p;
+ }
+ return NULL;
+ }
+ return NULL;
+ }
+ // ToDo: I/O SLOTS (40000000h)
+ return NULL;
+ }
+ virtual void __FASTCALL set_device_range_r(DEVICE* dev, uint32_t begin_addr, uint32_t end_addr);
+ virtual void __FASTCALL set_device_range_w(DEVICE* dev, uint32_t begin_addr, uint32_t end_addr);
+ outputs_t outputs_ram_wait;
outputs_t outputs_rom_wait;
bool bankc0_vram;
// RAM
uint8_t ram_page0[0xc0000]; // 0x00000000 - 0x000bffff : RAM
- uint8_t ram_pagec[0x10000]; // 0x000c0000 - 0x000cffff : URA? RAM
- uint8_t ram_paged[0x20000]; // 0x000d0000 - 0x000effff : RAM
- uint8_t ram_pagef[0x10000]; // 0x000f0000 - 0x000fffff : RAM
+ uint8_t ram_pagec[0x40000]; // 0x000c0000 - 0x000fffff : URA? RAM
uint8_t *extra_ram; // 0x00100000 - (0x3fffffff) : Size is defined by extram_size;
uint32_t extram_size;
d_vram = NULL;
d_sprite = NULL;
- d_romcard[0] = d_romcard[1] = NULL;
d_pcm = NULL;
d_timer = NULL;
d_dmac = NULL;
initialize_output_signals(&outputs_ram_wait);
initialize_output_signals(&outputs_rom_wait);
+ for(int i = 0; i < (sizeof(devmap_c0000h_read) / sizeof(DEVICE*)); i++) {
+ devmap_c0000h_read[i] = NULL;
+ devmap_c0000h_write[i] = NULL;
+ offsetmap_c0000h_read[i] = UINT32_MAX;
+ offsetmap_c0000h_write[i] = UINT32_MAX;
+ }
+ for(int i = 0; i < (sizeof(devmap_80000000h) / sizeof(DEVICE*)); i++) {
+ devmap_80000000h[i] = NULL;
+ offsetmap_80000000h[i] = UINT32_MAX;
+ }
+ for(int i = 0; i < (sizeof(devmap_c0000000h_read) / sizeof(DEVICE*)); i++) {
+ devmap_c0000000h_read[i] = NULL;
+ devmap_c00000000h_write[i] = NULL;
+ offsetmap_c00000000h_read[i] = UINT32_MAX;
+ offsetmap_c00000000h_write[i] = UINT32_MAX;
+ }
// Note: machine id must set before initialize() from set_context_machine_id() by VM::VM().
// machine_id = 0x0100; // FM-Towns 1,2
// machine_id = 0x0200 // FM-Towns 1F/2F/1H/2H
{
d_dmac = device;
}
- void set_context_vram(DEVICE* device)
+ virtual void set_context_vram(DEVICE* device)
{
d_vram = device;
+
}
void set_context_system_rom(DEVICE* device)
{
void set_context_font_rom(DEVICE* device)
{
d_font = device;
+ set_device_range_r(device, 0xc2100000, 0xc2140000);
}
void set_context_font_20pix_rom(DEVICE* device)
{
d_font_20pix = device;
+ set_device_range_r(device, 0xc2180000, 0xc2200000);
}
void set_context_dictionary(DEVICE* device)
{
d_dictionary = device;
+ set_device_range_r(device, 0xc2080000, 0xc2100000);
+ set_device_range_r(device, 0xc2140000, 0xc2142000);
+ // CMOS
+ set_device_range_w(device, 0xc2140000, 0xc2142000);
}
void set_context_msdos(DEVICE* device)
{
d_msdos = device;
+ set_device_range_r(device, 0xc2000000, 0xc2080000);
}
void set_context_timer(DEVICE* device)
{
void set_context_sprite(DEVICE* device)
{
d_sprite = device;
+ set_device_range_r(device, 0x81000000, 0x81020000);
+ set_device_range_w(device, 0x81000000, 0x81020000);
}
void set_context_crtc(DEVICE* device)
{
d_crtc = device;
}
- void set_context_romcard(DEVICE* device, int num)
+ void set_context_iccard(DEVICE* device, int num)
{
- d_romcard[num & 1] = device;
+ d_iccard[num & 1] = device;
+ uint32_t begin_addr = ((num & 1) == 0) ? 0xc0000000 : 0xc1000000;
+ set_device_range_r(device, begin_addr, begin_addr + 0x01000000);
+ set_device_range_w(device, begin_addr, begin_addr + 0x01000000);
}
void set_context_pcm(DEVICE* device)
{
d_pcm = device;
+ set_device_range_r(device, 0xc2200000, 0xc2200fff);
+ set_device_range_w(device, 0xc2200000, 0xc2200fff);
}
void set_context_serial_rom(DEVICE* device)
{
{
d_planevram = dev;
}
- void set_context_iccard(DEVICE* device, int num)
- {
- if((num >= 0) && (num < 2)) {
- d_iccard[num] = device;
- }
- }
void set_machine_id(uint16_t val)
{
machine_id = val & 0xfff8;