#include "../../fileio.h"
#include "./towns_memory.h"
-#include "./towns_dmac.h"
-#include "./towns_vram.h"
-#include "./towns_sprite.h"
+#include "./dmac.h"
+#include "./vram.h"
+#include "./planevram.h"
+#include "./sprite.h"
#include "./fontroms.h"
#include "./serialrom.h"
-#include "../i386.h"
-#include "../pcm1bit.h"
+#include "./crtc.h"
+#include "./timer.h"
+
+#include "../i386_np21.h"
+//#include "../i386.h"
#include <math.h>
namespace FMTOWNS {
-#define ADDR_MASK (addr_max - 1)
-#define BANK_MASK (bank_size - 1)
-
-void TOWNS_MEMORY::config_page00()
-{
- if(dma_is_vram) {
- set_memory_rw (0x00000000, 0x000bffff, ram_page0);
-// set_memory_mapped_io_r (0x000b0000, 0x000bffff, d_msdos); // OK? <- for compatible ROM.
- set_memory_rw (0x000c0000, 0x000cffff, ram_pagec);
- set_memory_mapped_io_rw(0x000c0000, 0x000c7fff, d_vram);
- set_memory_mapped_io_rw(0x000c8000, 0x000cafff, d_sprite);
-// set_memory_mapped_io_rw(0x000cb000, 0x000cbfff, d_font);
- set_memory_mapped_io_rw(0x000cf000, 0x000cffff, this);
- set_memory_rw (0x000d0000, 0x000d7fff, ram_paged);
-// set_memory_mapped_io_rw(0x000d0000, 0x000d9fff, d_dictionary); // CMOS
- set_memory_mapped_io_rw(0x000d8000, 0x000d9fff, d_dictionary); // CMOS
- } else {
- set_memory_rw (0x00000000, 0x000bffff, ram_page0);
- set_memory_rw (0x000c0000, 0x000cffff, ram_pagec);
-// set_memory_mapped_io_rw(0x000c8000, 0x000cbfff, d_sprite);
- set_memory_rw (0x000d0000, 0x000d9fff, ram_paged);
-// set_memory_mapped_io_rw(0x000cc000, 0x000cffff, this);
- }
- set_memory_rw (0x000da000, 0x000effff, ram_pagee);
- set_memory_rw (0x000f0000, 0x000f7fff, ram_pagef);
- set_memory_mapped_io_rw(0x000f8000, 0x000fffff, d_sysrom);
-}
-
void TOWNS_MEMORY::initialize()
{
-// if(initialized) return;
-// DEVICE::initialize();
-
+ if(initialized) return;
+ //MEMORY::initialize();
+
+ update_machine_features();
extra_nmi_mask = true;
extra_nmi_val = false;
+ poff_status = false;
+ reset_happened = false;
vram_wait_val = 6;
mem_wait_val = 3;
+// if((cpu_id == 0x01) || (cpu_id == 0x03)) {
+// wait_register_older = vram_wait_val;
+// wait_register_vram = vram_wait_val;
+// wait_register_ram = mem_wait_val;
+// } else {
+ wait_register_older = 3;
+ wait_register_vram = 0x06;
+ wait_register_ram = 0x03;
+// }
+ //cpu_clock_val = 16 * 1000 * 1000;
+ //cpu_clock_val = get_cpu_clocks(d_cpu);
+ set_cpu_clock_by_wait();
+ extram_size = extram_size & 0x3ff00000;
+ set_extra_ram_size(extram_size >> 20); // Check extra ram size.
- // Initialize R/W table
- _MEMORY_DISABLE_DMA_MMIO = osd->check_feature(_T("MEMORY_DISABLE_DMA_MMIO"));
- if(!(addr_max_was_set) && osd->check_feature(_T("MEMORY_ADDR_MAX"))) {
- addr_max = osd->get_feature_uint64_value(_T("MEMORY_ADDR_MAX"));
- }
- if(!(bank_size_was_set) && osd->check_feature(_T("MEMORY_BANK_SIZE"))) {
- bank_size = osd->get_feature_uint64_value(_T("MEMORY_BANK_SIZE"));
- }
-#if 1
- MEMORY::initialize();
- bank_mask = BANK_MASK;
- addr_mask = ADDR_MASK;
-#else
- // allocate tables here to support multiple instances with different address range
- if(rd_table == NULL) {
- int64_t bank_num = addr_max / bank_size;
- bank_mask = BANK_MASK;
- addr_mask = ADDR_MASK;
-
- rd_dummy = (uint8_t *)malloc(bank_size);
- wr_dummy = (uint8_t *)malloc(bank_size);
-
- rd_table = (bank_t *)calloc(bank_num, sizeof(bank_t));
- wr_table = (bank_t *)calloc(bank_num, sizeof(bank_t));
-
- for(int i = 0; i < bank_num; i++) {
- rd_table[i].dev = NULL;
- rd_table[i].memory = rd_dummy;
- rd_table[i].wait = 0;
-
- wr_table[i].dev = NULL;
- wr_table[i].memory = wr_dummy;
- rd_table[i].wait = 0;
- }
- for(int i = 0;; i++) {
- if(bank_size == (uint64_t)(1 << i)) {
- addr_shift = i;
- break;
- }
+ unset_range_rw(0x00000000, 0xffffffff);
+
+ reset_wait_values();
+
+ __UNLIKELY_IF(extra_ram == NULL) {
+ extra_ram = (uint8_t*)malloc(extram_size + 0x00100000);
+ __LIKELY_IF(extra_ram != NULL) {
+ set_region_memory_rw(0x00000000, (extram_size + 0x00100000) - 1, extra_ram, 0);
+ memset(extra_ram, 0x00, extram_size + 0x00100000);
}
- memset(rd_dummy, 0xff, bank_size);
}
-#endif
+
+
initialized = true;
- extram_size = extram_size & 0x3ff00000;
- set_extra_ram_size(extram_size >> 20); // Check extra ram size.
- if(extram_size >= 0x00100000) {
- extra_ram = (uint8_t*)malloc(extram_size);
- if(extra_ram != NULL) {
- set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
- memset(extra_ram, 0x00, extram_size);
- }
- }
- memset(ram_page0, 0x00, sizeof(ram_page0));
- memset(ram_pagec, 0x00, sizeof(ram_pagec));
- memset(ram_paged, 0x00, sizeof(ram_paged));
- memset(ram_pagee, 0x00, sizeof(ram_pagee));
- memset(ram_pagef, 0x00, sizeof(ram_pagef));
-
- dma_is_vram = true;
- config_page00();
-
- set_memory_mapped_io_rw(0x80000000, 0x81ffffff, d_vram);
-// set_memory_mapped_io_rw(0xc0000000, 0xc0ffffff, d_iccard[0]);
-// set_memory_mapped_io_rw(0xc1000000, 0xc1ffffff, d_iccard[1]);
- set_memory_mapped_io_r (0xc2000000, 0xc207ffff, d_msdos);
- set_memory_mapped_io_r (0xc2080000, 0xc20fffff, d_dictionary);
- set_memory_mapped_io_r (0xc2100000, 0xc213ffff, d_font);
- set_memory_mapped_io_rw(0xc2140000, 0xc2141fff, d_dictionary);
-// set_memory_mapped_io_r (0xc2180000, 0xc21fffff, d_font_20);
-
- set_memory_mapped_io_r (0xfffc0000, 0xffffffff, d_sysrom);
- set_wait_values();
+
+ // Lower 100000h
+
+ config_page0c_0e(true, false, true);
+ config_page0f(true, true);
+
+ set_region_device_rw(0x80000000, 0x8007ffff, d_vram, NOT_NEED_TO_OFFSET);
+ set_region_device_rw(0x80100000, 0x8017ffff, d_vram, NOT_NEED_TO_OFFSET);
+
+ set_region_device_rw(0x81000000, 0x8101ffff, d_sprite, 0);
+ set_region_device_rw(0xc0000000, 0xc0ffffff, d_iccard[0], 0);
+ set_region_device_rw(0xc1000000, 0xc1ffffff, d_iccard[1], 0);
+// set_wait_rw(0x00000000, 0xffffffff, vram_wait_val);
+
+ set_region_device_r (0xc2000000, 0xc207ffff, d_msdos, 0);
+ set_region_device_r (0xc2080000, 0xc20fffff, d_dictionary, NOT_NEED_TO_OFFSET);
+ set_region_device_r (0xc2100000, 0xc213ffff, d_font, NOT_NEED_TO_OFFSET);
+ // REAL IS C2140000h - C2141FFFh, but grain may be 8000h bytes.
+ set_region_device_rw(0xc2140000, 0xc2147fff, d_cmos, 0);
+ if(d_font_20pix != NULL) {
+ set_region_device_r (0xc2180000, 0xc21fffff, d_font_20pix, 0);
+ }
+ // REAL IS C2200000h - C2200FFFh, but grain may be 8000h bytes.
+ set_region_device_rw(0xc2200000, 0xc2200000 + memory_map_grain() - 1, d_pcm, 0);
+ set_region_device_r (0xfffc0000, 0xffffffff, d_sysrom, 0);
// Another devices are blank
-
+
// load rom image
// ToDo: More smart.
vram_size = 0x80000; // OK?
}
-void TOWNS_MEMORY::set_wait_values()
+void TOWNS_MEMORY::reset_wait_values()
{
- set_wait_rw(0x00000000, 0x00100000 + (extram_size & 0x3ff00000) - 1, mem_wait_val);
- // ToDo: Extend I/O Slots
- set_wait_rw(0x80000000, 0x800fffff, vram_wait_val);
- set_wait_rw(0x80100000, 0x801fffff, vram_wait_val);
- // ToDo: pattern RAM
- // ToDo: ROM CARDS
- set_wait_rw(0xc2000000, 0xc213ffff, mem_wait_val);
- // ToDo: DICT RAM and PCM RAM
- set_wait_rw(0xfffc0000, 0xffffffff, mem_wait_val);
+ set_mmio_wait_rw(0x00000000, 0x7fffffff, WAITVAL_RAM);
+ set_dma_wait_rw (0x00000000, 0x7fffffff, WAITVAL_RAM);
+ set_mmio_wait_rw(0x80000000, 0x803fffff, WAITVAL_VRAM); // Default Value
+ set_dma_wait_rw (0x80000000, 0x803fffff, WAITVAL_VRAM); // Default Value
+ set_mmio_wait_rw(0x80400000, 0xffffffff, WAITVAL_RAM);
+ set_dma_wait_rw (0x80400000, 0xffffffff, WAITVAL_RAM);
}
-#if 0
-// Note: This contains SUBSET of MEMORY:: class (except read_bios()).
-void TOWNS_MEMORY::set_memory_r(uint32_t start, uint32_t end, uint8_t *memory)
+
+void TOWNS_MEMORY::config_page0c_0e(const bool vrambank, const bool dictbank, const bool force)
{
- TOWNS_MEMORY::initialize(); // May overload initialize()
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
- if(memory == NULL) {
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- rd_table[i].dev = NULL;
- rd_table[i].memory = rd_dummy;
+ const bool is_vram_bak = dma_is_vram;
+ const bool is_dict_bak = select_d0_dict;
+ //__UNLIKELY_IF((vrambank != is_vram_bak) || (force)){
+ if(vrambank) { // VRAM AND around TEXT
+ set_region_device_rw(0x000c0000, 0x000c7fff, d_planevram, NOT_NEED_TO_OFFSET);
+ set_region_device_rw(0x000c8000, 0x000cffff, this, NOT_NEED_TO_OFFSET);
+
+ unset_range_rw(0x000e0000, 0x000effff); // OK?
+
+ set_mmio_wait_rw(0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
+ set_dma_wait_rw (0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
+ } else {
+ __LIKELY_IF(extra_ram != NULL) {
+ set_region_memory_rw(0x000c0000, 0x000cffff, extra_ram, 0x000c0000);
+ set_region_memory_rw(0x000e0000, 0x000effff, extra_ram, 0x000e0000);
+ } else {
+ unset_range_rw(0x000c0000, 0x000cffff);
+ unset_range_rw(0x000e0000, 0x000effff);
+ }
+ set_mmio_wait_rw(0x000c0000, 0x000cffff, WAITVAL_RAM); // Default Value
+ set_dma_wait_rw (0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
}
- } else {
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- rd_table[i].dev = NULL;
- rd_table[i].memory = memory + bank_size * (i - start_bank);
+ //}
+ //__UNLIKELY_IF((vrambank != is_vram_bak) || (dictbank != is_dict_bak) || (force)){
+ if(vrambank) { // VRAM AND around TEXT
+ if(dictbank) {
+ set_region_device_r(0x000d0000, 0x000d7fff, d_dictionary, NOT_NEED_TO_OFFSET);
+ unset_range_w(0x000d0000, 0x000d7fff);
+ // REAL IS 0000D8000h - 000D9FFFh, but grain may be 8000h bytes.
+ set_region_device_rw(0x000d8000, 0x000dffff, d_cmos, 0);
+ } else {
+ unset_range_rw(0x000d0000, 0x000dffff);
+ }
+ } else {
+ __LIKELY_IF(extra_ram != NULL) {
+ set_region_memory_rw(0x000d0000, 0x000dffff, extra_ram, 0x000d0000);
+ } else {
+ unset_range_rw(0x000d0000, 0x000dffff);
+ }
}
- }
+ //}
+ dma_is_vram = vrambank;
+ select_d0_dict = dictbank;
}
-
-void TOWNS_MEMORY::set_memory_w(uint32_t start, uint32_t end, uint8_t *memory)
+void TOWNS_MEMORY::config_page0f(const bool sysrombank, const bool force)
{
- TOWNS_MEMORY::initialize(); // May overload initialize()
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
- if(memory == NULL) {
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- wr_table[i].dev = NULL;
- wr_table[i].memory = wr_dummy;
- }
- } else {
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- wr_table[i].dev = NULL;
- wr_table[i].memory = memory + bank_size * (i - start_bank);
+ bool sysrom_bak = select_d0_rom;
+ //__LIKELY_IF(extra_ram != NULL) {
+ // set_region_memory_rw(0x000f0000, 0x000f7fff, extra_ram, 0x000f0000);
+ //}
+ //__UNLIKELY_IF((sysrombank != sysrom_bak) || (force)) {
+ if(sysrombank) {
+ unset_range_w(0x000f8000, 0x000fffff);
+ set_region_device_r (0x000f8000, 0x000fffff, d_sysrom, 0x38000);
+ } else {
+ __LIKELY_IF(extra_ram != NULL) {
+ set_region_memory_rw(0x000f8000, 0x000fffff, extra_ram, 0x000f8000);
+ } else {
+ unset_range_rw(0x000f8000, 0x000fffff);
+ }
}
- }
+ //}
+ select_d0_rom = sysrombank;
}
-void TOWNS_MEMORY::set_memory_rw(uint32_t start, uint32_t end, uint8_t *memory)
+void TOWNS_MEMORY::set_memory_devices_map_values(uint32_t start, uint32_t end, memory_device_map_t* dataptr, uint8_t* baseptr, DEVICE* device, uint32_t base_offset)
{
- TOWNS_MEMORY::initialize(); // May overload initialize()
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
- if(memory == NULL) {
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- wr_table[i].dev = NULL;
- wr_table[i].memory = wr_dummy;
- rd_table[i].dev = NULL;
- rd_table[i].memory = rd_dummy;
- }
- } else {
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- wr_table[i].dev = NULL;
- wr_table[i].memory = memory + bank_size * (i - start_bank);
- rd_table[i].dev = NULL;
- rd_table[i].memory = memory + bank_size * (i - start_bank);
+ uint64_t _start = (uint64_t)start;
+ uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
+ __UNLIKELY_IF(dataptr == NULL) return;
+
+ _start &= ~(memory_map_mask());
+ _end &= ~(memory_map_mask());
+
+ uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
+ const uint64_t _incval = memory_map_grain();
+ uint32_t realoffset = (base_offset == UINT32_MAX) ? 0 : base_offset;
+
+ for(uint64_t addr = _start; addr < _end; addr += _incval) {
+ __UNLIKELY_IF(mapptr >= memory_map_size()) break; // Safety
+ if(baseptr == NULL) {
+ dataptr[mapptr].mem_ptr = NULL;
+ dataptr[mapptr].device_ptr = device;
+ } else {
+ dataptr[mapptr].mem_ptr = baseptr;
+ dataptr[mapptr].device_ptr = NULL;
}
- }
-}
-
-void TOWNS_MEMORY::set_memory_mapped_io_r(uint32_t start, uint32_t end, DEVICE *device)
-{
- TOWNS_MEMORY::initialize();
-
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
-
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- rd_table[i].dev = device;
+ if(base_offset == UINT32_MAX) {
+ dataptr[mapptr].base_offset = UINT32_MAX;
+ } else {
+ dataptr[mapptr].base_offset = realoffset;
+ }
+ realoffset += _incval;
+ mapptr++;
}
}
-void TOWNS_MEMORY::set_memory_mapped_io_w(uint32_t start, uint32_t end, DEVICE *device)
+void TOWNS_MEMORY::set_memory_devices_map_wait(uint32_t start, uint32_t end, memory_device_map_t* dataptr, int wait)
{
- TOWNS_MEMORY::initialize();
-
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
-
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- wr_table[i].dev = device;
- }
-}
-
-void TOWNS_MEMORY::set_memory_mapped_io_rw(uint32_t start, uint32_t end, DEVICE *device)
-{
- TOWNS_MEMORY::initialize();
-
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
-
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- rd_table[i].dev = device;
- wr_table[i].dev = device;
- }
-}
+ uint64_t _start = (uint64_t)start;
+ uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
+ __UNLIKELY_IF(dataptr == NULL) return;
-void TOWNS_MEMORY::unset_memory_r(uint32_t start, uint32_t end)
-{
- TOWNS_MEMORY::initialize();
-
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
-
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- rd_table[i].dev = NULL;
- rd_table[i].memory = rd_dummy;
- }
-}
+ _start &= ~(memory_map_mask());
+ _end &= ~(memory_map_mask());
-void TOWNS_MEMORY::unset_memory_w(uint32_t start, uint32_t end)
-{
- TOWNS_MEMORY::initialize();
-
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
-
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- wr_table[i].dev = NULL;
- wr_table[i].memory = wr_dummy;
- }
-}
-void TOWNS_MEMORY::unset_memory_rw(uint32_t start, uint32_t end)
-{
- unset_memory_w(start, end);
- unset_memory_r(start, end);
-}
-
-void TOWNS_MEMORY::copy_table_w(uint32_t to, uint32_t start, uint32_t end)
-{
- TOWNS_MEMORY::initialize();
-
- uint64_t start_bank = start >> addr_shift;
- uint64_t end_bank = end >> addr_shift;
- uint64_t to_bank = to >> addr_shift;
- uint64_t blocks = addr_max / bank_size;
-
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- if(to_bank >= blocks) break;
- wr_table[to_bank].dev = wr_table[i].dev;
- wr_table[to_bank].memory = wr_table[i].memory;
- wr_table[to_bank].wait = wr_table[i].wait;
- to_bank++;
+ uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
+ const uint64_t _incval = memory_map_grain();
+
+ for(uint64_t addr = _start; addr < _end; addr += _incval) {
+ __UNLIKELY_IF(mapptr >= memory_map_size()) break; // Safety
+ dataptr[mapptr].waitval = wait;
+ mapptr++;
}
}
-void TOWNS_MEMORY::copy_table_r(uint32_t to, uint32_t start, uint32_t end)
+void TOWNS_MEMORY::unset_memory_devices_map(uint32_t start, uint32_t end, memory_device_map_t* dataptr, int wait)
{
- TOWNS_MEMORY::initialize();
+ uint64_t _start = (uint64_t)start;
+ uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
+ __UNLIKELY_IF(dataptr == NULL) return;
- uint64_t start_bank = start >> addr_shift;
- uint64_t end_bank = end >> addr_shift;
- uint64_t to_bank = to >> addr_shift;
- uint64_t blocks = addr_max / bank_size;
+ _start &= ~(memory_map_mask());
+ _end &= ~(memory_map_mask());
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- if(to_bank >= blocks) break;
- rd_table[to_bank].dev = rd_table[i].dev;
- rd_table[to_bank].memory = rd_table[i].memory;
- rd_table[to_bank].wait = rd_table[i].wait;
- to_bank++;
+ uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
+ const uint64_t _incval = memory_map_grain();
+ for(uint64_t addr = _start; addr < _end; addr += _incval) {
+ __UNLIKELY_IF(mapptr >= memory_map_size()) break; // Safety
+ dataptr[mapptr].mem_ptr = NULL;
+ dataptr[mapptr].device_ptr = NULL;
+ dataptr[mapptr].waitval = wait;
+ dataptr[mapptr].base_offset = UINT32_MAX;
+ mapptr++;
}
+
}
-void TOWNS_MEMORY::copy_table_rw(uint32_t to, uint32_t start, uint32_t end)
+void TOWNS_MEMORY::set_mmio_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
{
- copy_table_r(to, start, end);
- copy_table_w(to, start, end);
-}
+ set_memory_devices_map_values(start, end, &(membus_read_map[0]), baseptr, NULL, base_offset);
+}
-void TOWNS_MEMORY::set_wait_w(uint32_t start, uint32_t end, int wait)
+void TOWNS_MEMORY::set_mmio_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
{
- TOWNS_MEMORY::initialize();
-
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
-
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- wr_table[i].wait = wait;
- }
+ set_memory_devices_map_values(start, end, &(membus_write_map[0]), baseptr, NULL, base_offset);
}
-void TOWNS_MEMORY::set_wait_r(uint32_t start, uint32_t end, int wait)
+void __FASTCALL TOWNS_MEMORY::set_mmio_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
{
- TOWNS_MEMORY::initialize();
-
- uint32_t start_bank = start >> addr_shift;
- uint32_t end_bank = end >> addr_shift;
-
- for(uint32_t i = start_bank; i <= end_bank; i++) {
- rd_table[i].wait = wait;
- }
+ set_memory_devices_map_values(start, end, &(membus_read_map[0]), NULL, ptr, baseaddress);
}
-void TOWNS_MEMORY::set_wait_rw(uint32_t start, uint32_t end, int wait)
+void __FASTCALL TOWNS_MEMORY::set_mmio_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
{
- set_wait_r(start, end, wait);
- set_wait_w(start, end, wait);
+ set_memory_devices_map_values(start, end, &(membus_write_map[0]), NULL, ptr, baseaddress);
}
-// MEMORY:: don't allow to override member functions , re-made.
-// Because Towns's memory access rules are multiple depended by per device.
-// 20191202 K.Ohta
-uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int *wait)
+void __FASTCALL TOWNS_MEMORY::set_mmio_wait_r(uint32_t start, uint32_t end, int wait)
{
- uint32_t bank = (addr & ADDR_MASK) >> addr_shift;
- if(wait != NULL) {
- *wait = rd_table[bank].wait;
- }
-// printf("READ %08X\n", addr);
- if(rd_table[bank].dev != NULL) {
-// return rd_table[bank].dev->read_data8w(addr, wait);
- return rd_table[bank].dev->read_memory_mapped_io8(addr);
- } else if(rd_table[bank].memory != NULL) {
- return rd_table[bank].memory[addr & bank_mask];
- }
- return 0xff;
+ set_memory_devices_map_wait(start, end, &(membus_read_map[0]), wait);
}
-uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int *wait)
+void __FASTCALL TOWNS_MEMORY::set_mmio_wait_w(uint32_t start, uint32_t end, int wait)
{
- uint32_t bank = addr >> addr_shift;
- if(wait != NULL) {
- *wait = rd_table[bank].wait;
- }
- if(rd_table[bank].dev != NULL) {
- return rd_table[bank].dev->read_memory_mapped_io16(addr);
-// return rd_table[bank].dev->read_data16w(addr, wait);
- } else if(rd_table[bank].memory != NULL) {
- // Internal memories may access with 32bit width.
- pair32_t nd;
- nd.b.l = rd_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 0];
- nd.b.h = rd_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 1];
- return nd.w.l;
- }
- return 0xffff;
+ set_memory_devices_map_wait(start, end, &(membus_write_map[0]), wait);
}
-uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int *wait)
+void TOWNS_MEMORY::unset_mmio_r(uint32_t start, uint32_t end, int wait)
{
- uint32_t bank = addr >> addr_shift;
- if(wait != NULL) {
- *wait = rd_table[bank].wait;
- }
- if(rd_table[bank].dev != NULL) {
- return rd_table[bank].dev->read_memory_mapped_io32(addr);
-// return rd_table[bank].dev->read_data32w(addr, wait);
- } else if(rd_table[bank].memory != NULL) {
- // Internal memories may access with 32bit width.
- pair32_t nd;
- nd.b.l = rd_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 0];
- nd.b.h = rd_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 1];
- nd.b.h2 = rd_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 2];
- nd.b.h3 = rd_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 3];
- return nd.d;
- }
- return 0xffffffff;
+ unset_memory_devices_map(start, end, &(membus_read_map[0]), wait);
}
-void TOWNS_MEMORY::write_data8w(uint32_t addr, uint32_t data, int *wait)
+void TOWNS_MEMORY::unset_mmio_w(uint32_t start, uint32_t end, int wait)
{
- uint32_t bank = addr >> addr_shift;
- if(wait != NULL) {
- *wait = wr_table[bank].wait;
- }
- if(wr_table[bank].dev != NULL) {
- wr_table[bank].dev->write_memory_mapped_io8(addr, data);
- } else if(wr_table[bank].memory != NULL) {
- // Internal memories may access with 32bit width.
- wr_table[bank].memory[addr & bank_mask] = data;
- }
+ unset_memory_devices_map(start, end, &(membus_write_map[0]), wait);
}
-void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int *wait)
+void TOWNS_MEMORY::unset_dma_r(uint32_t start, uint32_t end, int wait)
{
- uint32_t bank = addr >> addr_shift;
- if(wait != NULL) {
- *wait = wr_table[bank].wait;
- }
- if(wr_table[bank].dev != NULL) {
- wr_table[bank].dev->write_memory_mapped_io16(addr, data);
-// wr_table[bank].dev->write_data16w(addr, data, wait);
- } else if(wr_table[bank].memory != NULL) {
- // Internal memories may access with 32bit width.
- pair32_t nd;
- nd.d = data;
- wr_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 0] = nd.b.l;
- wr_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 1] = nd.b.h;
- }
+ unset_memory_devices_map(start, end, &(dma_read_map[0]), wait);
}
-void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int *wait)
+void TOWNS_MEMORY::unset_dma_w(uint32_t start, uint32_t end, int wait)
{
- uint32_t bank = addr >> addr_shift;
- if(wait != NULL) {
- *wait = wr_table[bank].wait;
- }
- if(wr_table[bank].dev != NULL) {
- wr_table[bank].dev->write_memory_mapped_io32(addr, data);
-// wr_table[bank].dev->write_data32w(addr, data, wait);
- } else if(wr_table[bank].memory != NULL) {
- // Internal memories may access with 32bit width.
- pair32_t nd;
- nd.d = data;
- wr_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 0] = nd.b.l;
- wr_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 1] = nd.b.h;
- wr_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 2] = nd.b.h2;
- wr_table[bank].memory[(addr & bank_mask & 0xfffffffc) + 3] = nd.b.h3;
- }
+ unset_memory_devices_map(start, end, &(dma_write_map[0]), wait);
}
-uint32_t TOWNS_MEMORY::read_dma_data8(uint32_t addr)
+void TOWNS_MEMORY::set_dma_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
{
- int dummy;
- return read_dma_data8w(addr, &dummy);
+ set_memory_devices_map_values(start, end, &(dma_read_map[0]), baseptr, NULL, base_offset);
}
-uint32_t TOWNS_MEMORY::read_dma_data16(uint32_t addr)
+void TOWNS_MEMORY::set_dma_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
{
- int dummy;
- return read_dma_data16w(addr, &dummy);
+ set_memory_devices_map_values(start, end, &(dma_write_map[0]), baseptr, NULL, base_offset);
}
-uint32_t TOWNS_MEMORY::read_dma_data8w(uint32_t addr, int* wait)
+void __FASTCALL TOWNS_MEMORY::set_dma_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
{
- int bank = addr >> addr_shift;
- if(rd_table[bank].dev != NULL) {
- if(wait != NULL) {
- *wait = rd_table[bank].wait;
- }
- rd_table[bank].dev->read_memory_mapped_io8(addr);
-// return rd_table[bank].dev->read_dma_data8w(addr, wait);
- } else if(rd_table[bank].memory != NULL) {
- if(wait != NULL) {
- *wait = mem_wait_val;
- }
- return rd_table[bank].memory[addr & bank_mask];
- }
- return 0xff;
+ set_memory_devices_map_values(start, end, &(dma_read_map[0]), NULL, ptr, baseaddress);
}
-uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
+void __FASTCALL TOWNS_MEMORY::set_dma_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
{
- int bank = addr >> addr_shift;
- if(rd_table[bank].dev != NULL) {
- if(wait != NULL) {
- *wait = rd_table[bank].wait;
- }
- rd_table[bank].dev->read_memory_mapped_io16(addr);
- } else if(rd_table[bank].memory != NULL) {
- if(wait != NULL) {
- *wait = mem_wait_val;
- }
- pair16_t nd;
- nd.b.l = rd_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 0];
- nd.b.h = rd_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 1];
- return nd.w;
- }
- return 0xffff;
+ set_memory_devices_map_values(start, end, &(dma_write_map[0]), NULL, ptr, baseaddress);
}
-void TOWNS_MEMORY::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
+void __FASTCALL TOWNS_MEMORY::set_dma_wait_r(uint32_t start, uint32_t end, int wait)
{
- int bank = addr >> addr_shift;
- if(wr_table[bank].dev != NULL) {
- if(wait != NULL) {
- *wait = wr_table[bank].wait;
- }
- wr_table[bank].dev->write_memory_mapped_io8(addr, data);
- return;
- } else if(wr_table[bank].memory != NULL) {
- if(wait != NULL) {
- *wait = mem_wait_val;
- }
- wr_table[bank].memory[addr & bank_mask] = data;
- }
- return;
+ set_memory_devices_map_wait(start, end, &(dma_read_map[0]), wait);
}
-void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
+void __FASTCALL TOWNS_MEMORY::set_dma_wait_w(uint32_t start, uint32_t end, int wait)
{
- int bank = addr >> addr_shift;
- if(wr_table[bank].dev != NULL) {
- if(wait != NULL) {
- *wait = wr_table[bank].wait;
- }
- wr_table[bank].dev->write_memory_mapped_io16(addr, data);
- return;
- } else if(wr_table[bank].memory != NULL) {
- if(wait != NULL) {
- *wait = mem_wait_val;
- }
- pair32_t nd;
- nd.d = data;
- wr_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 0] = nd.b.l;
- wr_table[bank].memory[(addr & bank_mask & 0xfffffffe) + 1] = nd.b.h;
- }
- return;
+ set_memory_devices_map_wait(start, end, &(dma_write_map[0]), wait);
}
-void TOWNS_MEMORY::write_dma_data8(uint32_t addr, uint32_t data)
+
+bool TOWNS_MEMORY::set_cpu_clock_by_wait()
{
- int dummy;
- return write_dma_data8w(addr, data, &dummy);
+ uint32_t cpu_bak = cpu_clock_val;
+ cpu_clock_val = (is_faster_wait()) ?
+ get_cpu_clocks(d_cpu) : (16 * 1000 * 1000);
+ return ((cpu_clock_val != cpu_bak) ? true : false);
}
-
-void TOWNS_MEMORY::write_dma_data16(uint32_t addr, uint32_t data)
+void TOWNS_MEMORY::set_wait_values()
{
- int dummy;
- return write_dma_data16w(addr, data, &dummy);
+ uint32_t waitfactor = 0;
+ if(cpu_clock_val < get_cpu_clocks(d_cpu)) {
+ waitfactor = (uint32_t)(((double)get_cpu_clocks(d_cpu) / (double)cpu_clock_val) * 65536.0);
+ }
+ d_cpu->write_signal(SIG_CPU_WAIT_FACTOR, waitfactor, 0xffffffff);
}
-#endif
+
void TOWNS_MEMORY::release()
{
- if(rd_table != NULL) free(rd_table);
- if(rd_dummy != NULL) free(rd_dummy);
- if(wr_table != NULL) free(wr_table);
- if(wr_dummy != NULL) free(wr_dummy);
-
+// if(rd_table != NULL) free(rd_table);
+// if(rd_dummy != NULL) free(rd_dummy);
+// if(wr_table != NULL) free(wr_table);
+// if(wr_dummy != NULL) free(wr_dummy);
+
if(extra_ram != NULL) {
free(extra_ram);
extra_ram = NULL;
}
+
}
void TOWNS_MEMORY::reset()
{
// reset memory
// ToDo
- if(d_cpu != NULL) {
+ update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
+ is_compatible = true;
+ reset_happened = false;
+
+ nmi_vector_protect = false;
+ ankcg_enabled = false;
+ nmi_mask = false;
+ //config_page0c_0e(false, false, true); // VRAM, DICT, FORCE
+ reset_wait_values();
+ config_page0c_0e(false, false, true); // VRAM, DICT, FORCE
+ config_page0f(true, true); // SYSROM, FORCE
+
+
+ set_cpu_clock_by_wait();
+ set_wait_values();
+#if 1
+ __LIKELY_IF(d_cpu != NULL) {
d_cpu->set_address_mask(0xffffffff);
}
if(d_dmac != NULL) {
- d_dmac->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, 0xffffffff, 0xffffffff);
+ uint8_t wrap_val = 0xff; // WRAP ON
+ d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
}
- dma_is_vram = true;
- nmi_vector_protect = false;
- config_page00();
- set_wait_values();
-}
-#if 0
-uint32_t TOWNS_MEMORY::read_data8(uint32_t addr)
-{
- int dummy;
- return read_data8w(addr, &dummy);
-}
-
-uint32_t TOWNS_MEMORY::read_data16(uint32_t addr)
-{
- int dummy;
- return read_data16w(addr, &dummy);
-}
-
-uint32_t TOWNS_MEMORY::read_data32(uint32_t addr)
-{
- int dummy;
- return read_data32w(addr, &dummy);
-}
-
-void TOWNS_MEMORY::write_data8(uint32_t addr, uint32_t data)
-{
- int dummy;
- return write_data8w(addr, data, &dummy);
+#endif
}
-void TOWNS_MEMORY::write_data16(uint32_t addr, uint32_t data)
+void TOWNS_MEMORY::update_machine_features()
{
- int dummy;
- return write_data16w(addr, data, &dummy);
+ // 0024h: MISC3
+ reg_misc3 = 0xff;
+ if(machine_id >= 0x0b00) { // After MA/MX/ME
+ reg_misc3 &= ~0x04; // DMACMD
+ }
+ if(machine_id >= 0x0700) { // After HR/HG
+ reg_misc3 &= ~0x08; // POFFEN
+ }
+ if(machine_id >= 0x0700) { // After HR/HG
+ reg_misc3 &= ~0x10; // Free run counter
+ }
+ if(machine_id >= 0x0700) { // After HR/HG
+ reg_misc3 &= ~0x20; // CRTPOWOFF (0022h)
+ }
+ if(machine_id >= 0x0700) { // After HR/HG
+ reg_misc3 &= ~0x40; // RCREN
+ }
+ if(machine_id >= 0x0700) { // After HR/HG
+ reg_misc3 &= ~0x80; // ENPOFF
+ }
+ // 0025h: NMICNT
+ if(machine_id >= 0x0500) { // After CX
+ reg_misc4 = 0x7f;
+ } else {
+ reg_misc4 = 0xff;
+ }
}
-void TOWNS_MEMORY::write_data32(uint32_t addr, uint32_t data)
+uint8_t TOWNS_MEMORY::read_fmr_ports8(uint32_t addr)
{
- int dummy;
- return write_data32w(addr, data, &dummy);
+ uint8_t val = 0xff;
+ __UNLIKELY_IF((addr < 0xcff80) || (addr > 0xcffbb)) {
+ return val;
+ }
+ __LIKELY_IF(addr < 0xcff88) {
+ __LIKELY_IF(d_planevram != NULL) {
+ val = d_planevram->read_memory_mapped_io8(addr & 0xffff);
+ }
+ return val;
+ }
+ if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
+ switch(addr) {
+ case 0xcff88:
+ __LIKELY_IF(d_crtc != NULL) {
+ val = d_crtc->read_signal(SIG_TOWNS_CRTC_MMIO_CFF82H);
+ }
+ return val;
+ break;
+ case 0xcff99:
+ return (ankcg_enabled) ? 0x01 : 0x00;
+ break;
+ case 0xcff9c:
+ case 0xcff9d:
+ case 0xcff9e:
+ __LIKELY_IF(d_font != NULL) {
+ val = d_font->read_io8(addr & 0xffff);
+ }
+ return val;
+ break;
+ default:
+ break;
+ }
+ }
+ switch(addr) {
+ case 0xcff94:
+ case 0xcff95:
+ case 0xcff96:
+ case 0xcff97:
+ __LIKELY_IF(d_font != NULL) {
+ val = d_font->read_io8(addr & 0xffff);
+ }
+ break;
+ case 0xcff98:
+ __LIKELY_IF(d_timer != NULL) {
+ d_timer->write_signal(SIG_TIMER_BEEP_ON, 1, 1);
+ }
+ break;
+ case 0xcff99:
+ __LIKELY_IF(d_planevram != NULL) {
+ val = d_planevram->read_memory_mapped_io8(addr);
+ }
+ break;
+ default:
+ break;
+ }
+ return val;
}
-#endif
-// Address (TOWNS BASIC):
-// 0x0020 - 0x0022, 0x0030-0x0031,
-// 0x0400 - 0x0404,
-// 0x0480 - 0x0484
-// 0x05c0 - 0x05c2
-// 0x05ec (Wait register)
-// Is set extra NMI (0x05c0 - 0x05c2)?
-
-uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
+uint8_t TOWNS_MEMORY::read_sys_ports8(uint32_t addr)
{
- uint32_t val = 0x00; // MAY NOT FILL to "1" for unused bit 20200129 K.O
+ uint8_t val;
+ val = 0xff;
switch(addr & 0xffff) {
case 0x0020: // Software reset ETC.
// reset cause register
- if(d_cpu != NULL) {
- val = ((software_reset) ? 1 : 0) | ((d_cpu->get_shutdown_flag() != 0) ? 2 : 0);
- }
+ val = ((software_reset) ? 1 : 0) | ((reset_happened) ? 2 : 0);
+ reset_happened = false;
software_reset = false;
- if(d_cpu != NULL) {
+ __UNLIKELY_IF(d_cpu != NULL) {
d_cpu->set_shutdown_flag(0);
}
-// val = val | 0x7c; // MAY NOT FILL to "1" for unused bit 20200129 K.O
+ if((machine_id >= 0x0300) && ((machine_id & 0xff00) != 0x0400)) { // After UX
+ val = val | ((poff_status) ? 0x04 : 0x00);
+ }
break;
case 0x0022:
- // Power register
+// val.b.l = 0xff;
// if(d_dmac != NULL) {
// val = d_dmac->read_signal(SIG_TOWNS_DMAC_ADDR_REG);
// }
break;
+ // 0024, 0025 : MISC3 + MISC4
case 0x0024:
- // Power register
-// if(d_dmac != NULL) {
-// val = d_dmac->read_signal(SIG_TOWNS_DMAC_WRAP_REG);
-// }
+ val = reg_misc3;
+ break;
+ case 0x0025:
+ val = reg_misc4;
+ break;
+ case 0x0028:
+ // NMI MASK
+ if(machine_id >= 0x0500) { // After CX
+ val = (nmi_mask) ? 0x01 : 0x00;
+ }
break;
case 0x0030:
- val = (((machine_id & 0x1f) << 3) | (cpu_id & 7));
- // SPEED: bit0/Write
+ // 20210227 K.O
+ // From FMTowns::MachineID() of TSUGARU,
+ // git 83d4ec2309ac9fcbb8c01f26061ff0d49c5321e4.
+// if((config.dipswitch & TOWNS_DIPSW_PRETEND_I386) != 0) {
+// val = ((machine_id & 0xf8) | 1);
+// } else {
+ val = ((machine_id & 0xf8) | (cpu_id & 7));
+// }
break;
case 0x0031:
- val = ((machine_id >> 5) & 0xff);
+ val = ((machine_id >> 8) & 0xff);
break;
case 0x0032:
{
bool __clk = (d_serialrom->read_signal(SIG_SERIALROM_CLK) != 0);
bool __reset = (d_serialrom->read_signal(SIG_SERIALROM_RESET) != 0);
bool __dat = (d_serialrom->read_signal(SIG_SERIALROM_DATA) != 0);
- val = ((__reset) ? 0x80 : 0x00) | ((__clk) ? 0x40 : 0x00) | 0x3e | ((__dat) ? 0x01 : 0x00);
+ val = ((__reset) ? 0x80 : 0x00) | ((__clk) ? 0x40 : 0x00) | /*0x3e |*/ ((__dat) ? 0x01 : 0x00);
}
break;
- case 0x0400: // Resolution:
-// val = 0xfe;
+ case 0x00c0: // Cache
val = 0x00;
+ if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
+ // ToDo: Implement around cache.
+ // Modified by this register and (05ECh:bit0 / Wait register).
+ // Now, cache is always disabled.
+ // RPNH = 0 (Disabled) : Bit1
+ // CMEN = 0 (Disabled) : Bit0
+ val = 0x00;
+ }
+ break;
+ case 0x00c2: // Cache Diagnostic
+ val = 0x00;
+ if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
+ // ToDo: Implement cache disgnostic.
+ // SDMOD (Not diagnostic) : Bit3
+ val = 0x00;
+ }
+ break;
+ case 0x0400: // Resolution:
+ val = 0xfe;
break;
case 0x0404: // System Status Reg.
-// val = (dma_is_vram) ? 0x7f : 0xff;
- val = (dma_is_vram) ? 0x00 : 0x80;
+ val = (dma_is_vram) ? 0x7f : 0xff;
+// val = (dma_is_vram) ? 0x00 : 0x80;
+ break;
+ case 0x0480:
+ val = (select_d0_dict) ? 0x01 : 0x00;
+ val |= ((select_d0_rom) ? 0x00 : 0x02);
+ val |= 0xfc;
break;
case 0x05c0:
// val = (extra_nmi_mask) ? 0xf7 : 0xff;
// val = (extra_nmi_val) ? 0xff : 0xf7;
val = (extra_nmi_val) ? 0x08 : 0x00;
break;
+ case 0x05e0:
+ if(machine_id < 0x0200) { // Towns 1/2
+ val = wait_register_older;
+ }
+ break;
+ case 0x05e2:
+ if(machine_id >= 0x0200) { // i386
+ val = wait_register_ram;
+ }
+ break;
+ case 0x05e6:
+ if(machine_id >= 0x0200) { // i386
+ val = wait_register_vram;
+ }
+ break;
case 0x05e8:
// After Towns1F/2F/1H/2H
{
- switch(machine_id & 0xff00) {
- case 0x0000:
- case 0x0100:
+ uint16_t nid = machine_id & 0xff00;
+ val = extram_size >> 20;
+ switch(nid >> 8) {
+ case 0x00:
+ case 0x01: // Towns 1/2 : Not Supported.
val = 0xff;
break;
- case 0x0200:
- case 0x0300:
- case 0x0400:
- case 0x0500:
- case 0x0600:
- case 0x0700:
- case 0x0800:
- case 0x0a00:
- val = ((extram_size >> 20) & 0x1f);
+ case 0x03: // Towns II UX
+ case 0x06: // Towns II U6
+ val = val & 0x0f;
+ if(val >= 9) val = 9;
+ break;
+ case 0x02: // Towns 1F/2F/1H/2H.
+ case 0x04: // Towns 10F/20F/40H/80H.
+ val = val & 0x07;
+ break;
+ case 0x05: // Towns II CX
+ val = val & 0x0f;
+ break;
+ case 0x08: // Towns II HG : OK?
+ val = val & 0x0f;
break;
- case 0x0b00:
- case 0x0c00:
- case 0x0d00:
- case 0x0f00:
- val = ((extram_size >> 20) & 0x7f);
+ case 0x07: // Towns II HR
+ case 0x09: // Towns II UR
+ val = val & 0x1f;
break;
- default:
- val = 0x00; // ???
+ default: // After MA/MX/ME/MF, Fresh
+ val = val & 0x7f;
break;
}
}
break;
-
case 0x05ec:
- if(machine_id >= /*0x0500*/0x0200) { // Towns2 CX : Is this hidden register after Towns 1F/2F/1H/2H? -> Yes
- val = 0x00 | ((mem_wait_val > 0) ? 0x01 : 0x00);
+ // 05ec, 05ed
+ if(machine_id >= 0x0200) { // 05ec
+ val = ((is_faster_wait()) ? 0x01 : 0x00);
+ }
+ break;
+ case 0x05ed:
+ if(machine_id >= 0x0700) { // 05ed
+ uint32_t clk = get_cpu_clocks(d_cpu);
+ clk = clk / (1000 * 1000);
+ __UNLIKELY_IF(clk < 16) clk = 16;
+ __UNLIKELY_IF(clk > 127) clk = 127; // ToDo
+ val = 0x00 | clk;
+ }
+ break;
+ case 0xfda4:
+ if(machine_id >= 0x0700) { // After HR/HG
+ val = (is_compatible) ? 0x00 : 0x01;
+ } else {
+ val = 0x00;
}
break;
default:
}
return val;
}
-
-uint32_t TOWNS_MEMORY::read_io16(uint32_t addr)
+// Address (TOWNS BASIC):
+// 0x0020 - 0x0022, 0x0030-0x0031,
+// 0x0400 - 0x0404,
+// 0x0480 - 0x0484
+// 0x05c0 - 0x05c2
+// 0x05ec (Wait register)
+// 0x05ed (CPU SPEED REGISTER)
+// Is set extra NMI (0x05c0 - 0x05c2)?
+uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
{
- {
- // OK?
- pair16_t n;
- n.b.l = read_io8((addr & 0xfffe) + 0);
- n.b.h = read_io8((addr & 0xfffe) + 1);
- return n.w;
+// uint32_t val = 0x00; // MAY NOT FILL to "1" for unused bit 20200129 K.O
+ __LIKELY_IF((addr & 0xffff) >= 0xff80) {
+ return read_fmr_ports8((addr & 0xffff) | 0x000c0000);
}
- return 0xffff;
+ return read_sys_ports8(addr);
}
-void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
+void TOWNS_MEMORY::write_fmr_ports8(uint32_t addr, uint32_t data)
{
+ __UNLIKELY_IF((addr < 0xcff80) || (addr > 0xcffbb)) {
+ return;
+ }
+
+ __LIKELY_IF(addr < 0xcff88) {
+ __LIKELY_IF(d_planevram != NULL) {
+ d_planevram->write_io8(addr & 0xffff, data);
+ }
+ return;
+ }
+ if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
+ switch(addr) {
+ case 0xcff9e:
+ __LIKELY_IF(d_font != NULL) {
+ d_font->write_io8(addr & 0xffff, data);
+ }
+ return;
+ default:
+ break;
+ }
+ }
+ switch(addr) {
+ case 0xcff94:
+ case 0xcff95:
+ __LIKELY_IF(d_font != NULL) {
+ d_font->write_io8(addr & 0xffff, data);
+ }
+ break;
+ case 0xcff96:
+ case 0xcff97:
+ break;
+ case 0xcff98:
+ __LIKELY_IF(d_timer != NULL) {
+ d_timer->write_signal(SIG_TIMER_BEEP_ON, 0, 1);
+ }
+ break;
+ case 0xcff99:
+ {
+ bool _b = ankcg_enabled;
+ ankcg_enabled = ((data & 1) != 0) ? true : false;
+ }
+ break;
+ case 0xcffa0:
+ __LIKELY_IF(d_planevram != NULL) {
+ d_planevram->write_io8(addr & 0xffff, data);
+ }
+ break;
+ default:
+ break;
+ }
+}
+void TOWNS_MEMORY::write_sys_ports8(uint32_t addr, uint32_t data)
+{
switch(addr & 0xffff) {
case 0x0020: // Software reset ETC.
// reset cause register
} else {
software_reset = false;
}
-
+
if((data & 0x40) != 0) {
-// if(d_cpu != NULL) {
+ poff_status = true;
+// __LIKELY_IF(d_cpu != NULL) {
// d_cpu->set_shutdown_flag(1);
// }
// Todo: Implement true power off.
+// emu->notify_power_off();
// emu->power_off();
+// break;
} else {
- if(d_cpu != NULL) {
- d_cpu->set_shutdown_flag(0);
- }
+ poff_status = false;
+// __LIKELY_IF(d_cpu != NULL) {
+// d_cpu->set_shutdown_flag(0);
+// }
}
-
- if(software_reset) {
- if(d_cpu != NULL) {
- d_cpu->reset();
+
+ if((software_reset) || (poff_status)){
+// __LIKELY_IF(d_cpu != NULL) {
+// d_cpu->reset();
+// }
+ uint8_t wrap_val = 0xff; // WRAP ON
+ __LIKELY_IF(d_dmac != NULL) {
+ d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
}
+ if(poff_status) {
+ __LIKELY_IF(d_cpu != NULL) {
+ d_cpu->set_shutdown_flag(1);
+ }
+ // Todo: Implement true power off.
+ emu->notify_power_off();
+ // emu->power_off();
+ }
+ vm->reset();
}
- // Towns SEEMS to not set addreess mask (a.k.a A20 mask). 20200131 K.O
- if(d_dmac != NULL) {
- d_dmac->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, 0xffffffff, 0xffffffff);
- }
+ // Towns SEEMS to not set addreess mask (a.k.a A20 mask). 20200131 K.O
break;
case 0x0022:
if((data & 0x40) != 0) {
-// if(d_cpu != NULL) {
-// d_cpu->set_shutdown_flag(1);
-// }
+ __LIKELY_IF(d_cpu != NULL) {
+ d_cpu->set_shutdown_flag(1);
+ }
// Todo: Implement true power off.
+ poff_status = true;
+ emu->notify_power_off();
// emu->power_off();
- }
- if(d_dmac != NULL) {
- d_dmac->write_signal(SIG_TOWNS_DMAC_ADDR_REG, data, 0xff);
+ vm->reset();
}
// Power register
break;
case 0x0024:
-// if(d_dmac != NULL) {
-// d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP_REG, data, 0xff);
-// }
+ //if((d_dmac != NULL) && (machine_id >= 0x0b00)) { // After MA/MX/ME
+ // d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, data, 0xff);
+ //}
break;
case 0x0032:
+ d_serialrom->write_signal(SIG_SERIALROM_CS, ~data, 0x20);
+ d_serialrom->write_signal(SIG_SERIALROM_CLK, data, 0x40);
+ d_serialrom->write_signal(SIG_SERIALROM_RESET, data, 0x80);
+ break;
+ case 0x0404: // System Status Reg.
{
- d_serialrom->write_signal(SIG_SERIALROM_CS, ~data, 0x20);
- d_serialrom->write_signal(SIG_SERIALROM_CLK, data, 0x40);
- d_serialrom->write_signal(SIG_SERIALROM_RESET, data, 0x80);
+ config_page0c_0e(((data & 0x80) == 0) ? true : false, select_d0_dict, false); // VRAM, DICT, FORCE
}
break;
- break;
- case 0x0404: // System Status Reg.
- dma_is_vram = ((data & 0x80) == 0);
- config_page00();
- if(d_font != NULL) {
- d_font->write_signal(SIG_TOWNS_FONT_DMA_IS_VRAM, (dma_is_vram) ? 0xffffffff : 0x00000000, 0xffffffff);
+ case 0x0480:
+ {
+ bool is_dict, is_sysrom;
+ is_dict = ((data & 0x01) != 0) ? true : false;
+ is_sysrom = ((data & 0x02) == 0) ? true : false;
+ config_page0c_0e(dma_is_vram, is_dict, false);
+ config_page0f(is_sysrom, false);
}
break;
case 0x05c0:
extra_nmi_mask = ((data & 0x08) == 0);
break;
+ case 0x05e0:
+ // From AB.COM
+ if(machine_id < 0x0200) { // Towns 1/2
+ uint8_t nval_bak = wait_register_older & 0x07;
+ uint8_t nval = data & 0x07;
+ if(nval < 1) nval = 1;
+ mem_wait_val = nval;
+ vram_wait_val = nval + 3; // OK?
+ if(vram_wait_val > 6) {
+ vram_wait_val = 6;
+ }
+ wait_register_older = (data & 0xf8) | nval;
+ cpu_clock_val = 16 * 1000 * 1000;
+ if(nval_bak != nval) {
+ set_cpu_clock_by_wait();
+ set_wait_values();
+ }
+ }
+ break;
+ case 0x05e2:
+ if(machine_id >= 0x0200) { // After Towns 1H/2F. Hidden wait register.
+ uint8_t vram_bak = vram_wait_val;
+ uint8_t mem_bak = mem_wait_val;
+ if(data != 0x83) {
+ uint8_t nval = data & 7;
+ if(machine_id <= 0x0200) { // Towns 1H/2F.
+ if(nval < 1) nval = 1;
+ }
+ if(nval > 6) nval = 6;
+ mem_wait_val = nval;
+ wait_register_ram = (data & 0xf8) | nval;
+ } else {
+ mem_wait_val = 3;
+ vram_wait_val = 6;
+ wait_register_ram = data;
+ }
+ if((vram_bak != vram_wait_val) || (mem_bak != mem_wait_val)) {
+ set_cpu_clock_by_wait();
+ set_wait_values();
+ }
+ }
+ break;
+ case 0x05e6:
+ if(machine_id >= 0x0200) { // After Towns 1H/2F. Hidden wait register.
+ uint8_t mem_bak = mem_wait_val;
+ uint8_t vram_bak = vram_wait_val;
+ if(data != 0x83) {
+ uint8_t nval = data & 7;
+ if(machine_id <= 0x0200) { // Towns 1H/2F.
+ if(nval < 1) nval = 1;
+ }
+ if(nval > 6) nval = 6;
+ vram_wait_val = nval;
+ wait_register_vram = (data & 0xf8) | nval;
+ } else {
+ mem_wait_val = 3;
+ vram_wait_val = 3;
+ wait_register_vram = data;
+ }
+ if((vram_bak != vram_wait_val) || (mem_bak != mem_wait_val)) {
+ set_cpu_clock_by_wait();
+ set_wait_values();
+ }
+ }
+ break;
case 0x05ec:
- if(machine_id >= /*0x0500*/0x0200) { // Towns2 CX : Is this hidden register after Towns 1F/2F/1H/2H? -> Yes
- vram_wait_val = ((data & 0x01) != 0) ? 3 : 6;
- mem_wait_val = ((data & 0x01) != 0) ? 0 : 3;
+ // ToDo: 0x05ed
+ if(machine_id >= 0x0500) { // Towns2 CX :
+ uint8_t mem_bak = mem_wait_val;
+ uint8_t vram_bak = vram_wait_val;
+ vram_wait_val = ((data & 0x01) != 0) ? 0 : 6;
+ mem_wait_val = ((data & 0x01) != 0) ? 0 : 6;
+ wait_register_ram = mem_wait_val;
+ wait_register_vram = vram_wait_val;
+ if((mem_bak != mem_wait_val) || (vram_bak != vram_wait_val)) {
+ set_cpu_clock_by_wait();
+ set_wait_values();
+ }
+ }
+ break;
+
+ case 0xfda4:
+ if(machine_id >= 0x0700) { // After HR/HG
+ is_compatible = ((data & 0x01) == 0x00) ? true : false;
+ __LIKELY_IF(d_crtc != NULL) {
+ d_crtc->write_signal(SIG_TOWNS_CRTC_COMPATIBLE_MMIO, (is_compatible) ? 0xffffffff : 0x00000000, 0xffffffff);
+ }
}
- set_wait_values();
break;
default:
break;
}
- return;
+}
+void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
+{
+ __LIKELY_IF((addr & 0xffff) >= 0xff80) {
+ write_fmr_ports8((addr & 0xffff) | 0x000c0000, data);
+ return;
+ }
+ write_sys_ports8(addr, data);
}
-uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
+
+uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int* wait)
{
- uint32_t val = 0xff;
- if((addr < 0xcc000) || (addr >= 0xd0000)) return 0xff;
- if(addr < 0xcff80) {
- val = ram_pagec[addr & 0xffff];
- return val;
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ return read_8bit_data(membus_read_map, mapptr, addr, offset, false, wait);
+}
+
+uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int* wait)
+{
+ uint16_t val;
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ __UNLIKELY_IF(check_device_boundary(membus_read_map, mapptr, offset, 2)) {
+ val = read_beyond_boundary_data16(membus_read_map, addr, offset, mapptr, false, wait);
+ } else {
+ val = read_16bit_data(membus_read_map, mapptr, addr, offset, false, wait);
+ }
+ return val;
+}
+
+uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int* wait)
+{
+ uint32_t val;
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ __UNLIKELY_IF(check_device_boundary(membus_read_map, mapptr, offset, 4)) {
+ val = read_beyond_boundary_data32(membus_read_map, addr, offset, mapptr,false, wait);
+ } else {
+ val = read_32bit_data(membus_read_map, mapptr, addr, offset, false, wait);
+
}
- switch(addr & 0x7f) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- if(d_vram != NULL) {
- val = d_vram->read_memory_mapped_io8(addr);
+ return val;
+}
+
+uint32_t TOWNS_MEMORY::read_dma_data8w(uint32_t addr, int* wait)
+{
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ uint8_t val;
+ int waitval;
+ val = read_8bit_data(dma_read_map, mapptr, addr, offset, true, &waitval);
+ //val = read_8bit_data(dma_read_map, mapptr, addr, offset, false, &waitval);
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // Discard wait value for DMA.
+ }
+ return val;
+}
+
+uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
+{
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ uint16_t val;
+ int waitval;
+ __UNLIKELY_IF(check_device_boundary(dma_read_map, mapptr, offset, 2)) {
+ val = read_beyond_boundary_data16(dma_read_map, addr, offset, mapptr, true, &waitval);
+ } else {
+ val = read_16bit_data(dma_read_map, mapptr, addr, offset, true, &waitval);
+ //val = read_16bit_data(dma_read_map, mapptr, addr, offset, false, &waitval);
+ }
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // Discard wait value for DMA.
+ }
+ return val;
+
+}
+
+uint32_t TOWNS_MEMORY::read_dma_data32w(uint32_t addr, int* wait)
+{
+ uint32_t val;
+ int waitval;
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ __UNLIKELY_IF(check_device_boundary(dma_read_map, mapptr, offset, 4)) {
+ val = read_beyond_boundary_data32(dma_read_map, addr, offset, mapptr, true, &waitval);
+ } else {
+ val = read_32bit_data(dma_read_map, mapptr, addr, offset, true, &waitval);
+ //val = read_32bit_data(dma_read_map, mapptr, addr, offset, false, &waitval);
+ }
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // Discard wait value for DMA.
+ }
+ return val;
+}
+
+
+void TOWNS_MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
+{
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ write_8bit_data(membus_write_map, mapptr, addr, offset, false, data, wait);
+}
+
+
+void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int* wait)
+{
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ __UNLIKELY_IF(check_device_boundary(membus_write_map, mapptr, offset, 2)) {
+ write_beyond_boundary_data16(membus_write_map, addr, offset, mapptr, false, data, wait);
+ } else {
+ write_16bit_data(membus_write_map, mapptr, addr, offset, false, data, wait);
+ }
+}
+
+
+void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int* wait)
+{
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ __UNLIKELY_IF(check_device_boundary(membus_write_map, mapptr, offset, 4)) {
+ write_beyond_boundary_data32(membus_write_map, addr, offset, mapptr, false, data, wait);
+ } else {
+ write_32bit_data(membus_write_map, mapptr, addr, offset, false, data, wait);
+ }
+}
+
+void TOWNS_MEMORY::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
+{
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ int waitval;
+ write_8bit_data(dma_write_map, mapptr, addr, offset, true, data, &waitval);
+ //write_8bit_data(dma_write_map, mapptr, addr, offset, false, data, &waitval);
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // Discard wait value for DMA.
+ }
+}
+
+void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
+{
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ int waitval;
+ __UNLIKELY_IF(check_device_boundary(dma_write_map, mapptr, offset, 2)) {
+ write_beyond_boundary_data16(dma_write_map, addr, offset, mapptr, true, data, &waitval);
+ } else {
+ write_16bit_data(dma_write_map, mapptr, addr, offset, true, data, &waitval);
+ //write_16bit_data(dma_write_map, mapptr, addr, offset, false, data, &waitval);
+ }
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // Discard wait value for DMA.
+ }
+}
+
+
+void TOWNS_MEMORY::write_dma_data32w(uint32_t addr, uint32_t data, int* wait)
+{
+ uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
+ uint32_t offset = addr & memory_map_mask();
+ int waitval;
+ __UNLIKELY_IF(check_device_boundary(dma_write_map, mapptr, offset, 4)) {
+ write_beyond_boundary_data32(dma_write_map, addr, offset, mapptr, true, data, &waitval);
+ } else {
+ write_32bit_data(dma_write_map, mapptr, addr, offset, true, data, &waitval);
+ //write_32bit_data(dma_write_map, mapptr, addr, offset, false, data, &waitval);
+ }
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // Discard wait value for DMA.
+ }
+}
+
+uint32_t TOWNS_MEMORY::read_memory_mapped_io8w(uint32_t addr, int* wait)
+{
+ // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // ToDo
+ }
+ __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
+ // Out of bounds;
+ return 0xff;
+ }
+ __LIKELY_IF(addr < 0x000c9000) { // TEXT VRAM (ANK)
+ __LIKELY_IF(d_sprite != NULL) {
+ return d_sprite->read_memory_mapped_io8w(addr - 0xc8000, wait);
}
- break;
- case 0x04:
- val = 0x7f; // Reserve.FIRQ
- break;
- case 0x06:
- if(d_vram != NULL) {
- val = d_vram->read_memory_mapped_io8(addr);
+ return 0xff;
+ }
+ __LIKELY_IF(addr >= 0x000cc000) {
+ // RAM: OK?
+ __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
+ return read_fmr_ports8(addr);
+ } else {
+ __LIKELY_IF(extra_ram != NULL) {
+ return extra_ram[addr];
+ }
+ return 0xff;
}
- break;
- case 0x14:
- val = 0x80;
- break;
-// case 0x15:
- case 0x16:
- if(d_font != NULL) {
- val = d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_LOW);
+ }
+ // ROMs?
+ if(ankcg_enabled) {
+ if(addr >= 0xca000) {
+ __LIKELY_IF(d_font != NULL) {
+ return d_font->read_memory_mapped_io8(addr);
+ }
}
- break;
- case 0x17:
- if(d_font != NULL) {
- val = d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_HIGH);
+ } else {
+ if(addr < 0xcb000) {
+ __LIKELY_IF(d_sprite != NULL) {
+ return d_sprite->read_memory_mapped_io8w(addr - 0xc8000, wait);
+ }
}
- break;
- case 0x18:
- if(d_beep != NULL) {
- d_beep->write_signal(SIG_PCM1BIT_ON, 1, 1);
+ }
+ return 0xff;
+}
+
+uint32_t TOWNS_MEMORY::read_memory_mapped_io16w(uint32_t addr, int* wait)
+{
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // ToDo
+ }
+ // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
+ __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
+ // out of bounds
+ return 0xffff;
+ }
+ if(addr < 0x000c9000) { // TEXT VRAM (ANK)
+ __LIKELY_IF(d_sprite != NULL) {
+ return d_sprite->read_memory_mapped_io16w(addr - 0xc8000, wait);
}
- break;
- case 0x19:
- if(d_sprite != NULL) {
- val = val & ((d_sprite->read_signal(SIG_TOWNS_SPRITE_ANKCG) != 0) ? 0x00 : 0x01);
+ return 0xffff;
+ }
+ __LIKELY_IF(addr >= 0x000cc000) {
+ // RAM: OK?
+ pair16_t w;
+ __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cffff)) { // I/O
+ w.b.l = read_fmr_ports8(addr);
+ w.b.h = read_fmr_ports8(addr + 1);
+ } else {
+ __LIKELY_IF(extra_ram != NULL) {
+ w.read_2bytes_le_from(&(extra_ram[addr]));
+ } else {
+ w.w = 0xffff;
+ }
}
- break;
- case 0x20:
- val = 0xff;
- val = val & 0x7f;
- break;
- default:
- if(d_vram != NULL) {
- val = d_vram->read_memory_mapped_io8(addr);
+ return w.w;
+ }
+ // ROMs?
+ if(ankcg_enabled) {
+ if(addr >= 0xca000) {
+ __LIKELY_IF(d_font != NULL) {
+ return d_font->read_memory_mapped_io16(addr);
+ }
+ }
+ } else {
+ if(addr < 0xcb000) {
+ __LIKELY_IF(d_sprite != NULL) {
+ return d_sprite->read_memory_mapped_io16w(addr - 0xc8000, wait);
+ }
+ }
+ }
+ return 0xffff;
+}
+
+uint32_t TOWNS_MEMORY::read_memory_mapped_io32w(uint32_t addr, int* wait)
+{
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // ToDo
+ }
+ // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
+ __UNLIKELY_IF((addr > 0x000cffff) || (addr < 0x000c8000)) {
+ // out of bounds
+ return 0xffffffff;
+ }
+ if(addr < 0x000c9000) { //SPRITE
+ __LIKELY_IF(d_sprite != NULL) {
+ return d_sprite->read_memory_mapped_io32w(addr - 0xc8000, wait);
+ }
+ return 0xffffffff;
+ }
+ __LIKELY_IF(addr >= 0x000cc000) {
+ // RAM: OK?
+ pair32_t d;
+ __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cfffd)) { // I/O
+ d.b.l = read_fmr_ports8(addr);
+ d.b.h = read_fmr_ports8(addr + 1);
+ d.b.h2 = read_fmr_ports8(addr + 2);
+ d.b.h3 = read_fmr_ports8(addr + 3);
+ } else {
+ __LIKELY_IF(extra_ram != NULL) {
+ d.read_4bytes_le_from(&(extra_ram[addr]));
+ } else {
+ d.d = 0xffffffff;
+ }
+ }
+ return d.d;
+ }
+ // ROMs?
+ if(ankcg_enabled) {
+ if(addr >= 0xca000) {
+ __LIKELY_IF(d_font != NULL) {
+ return d_font->read_memory_mapped_io32(addr);
+ }
+ }
+ } else {
+ if(addr < 0xcb000) {
+ __LIKELY_IF(d_sprite != NULL) {
+ return d_sprite->read_memory_mapped_io32w(addr - 0xc8000, wait);
+ }
}
- break;
}
- return (uint32_t)val;
+ return 0xffffffff;
}
-void TOWNS_MEMORY::write_memory_mapped_io8(uint32_t addr, uint32_t data)
+
+void TOWNS_MEMORY::write_memory_mapped_io8w(uint32_t addr, uint32_t data, int* wait)
{
- if((addr < 0xcc000) || (addr >= 0xd0000)) return;
- if(addr < 0xcff80) {
- ram_pagec[addr & 0xffff] = data;
+ // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // ToDo
+ }
+ __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
+ // Out of bounds
return;
}
- switch(addr & 0x7f) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- if(d_vram != NULL) {
- d_vram->write_memory_mapped_io8(addr , data);
+ __LIKELY_IF(addr < 0xcb000) { // From Tsugaru.
+ __LIKELY_IF(d_sprite != NULL) {
+ d_sprite->write_memory_mapped_io8w(addr - 0xc8000, data, wait);
+ d_sprite->write_signal(SIG_TOWNS_SPRITE_TVRAM_ENABLED, 0xffffffff, 0xffffffff);
}
- break;
- case 0x04:
- break;
- case 0x06:
- break;
- case 0x14:
- if(d_font != NULL) {
- d_font->write_signal(SIG_TOWNS_FONT_KANJI_HIGH, data, 0xff);
+ return;
+ }
+ __LIKELY_IF(addr >= 0x000cc000) {
+ // RAM: OK?
+ __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
+ write_fmr_ports8(addr, data);
+ return;
}
- break;
- case 0x15:
- if(d_font != NULL) {
- d_font->write_signal(SIG_TOWNS_FONT_KANJI_LOW, data, 0xff);
+ __LIKELY_IF(extra_ram != NULL) {
+ extra_ram[addr] = data;
}
- break;
- case 0x16:
- case 0x17:
- if(d_vram != NULL) {
- d_vram->write_memory_mapped_io8(addr , data);
+ return;
+ }
+ // ROMs?
+ return;
+}
+
+void TOWNS_MEMORY::write_memory_mapped_io16w(uint32_t addr, uint32_t data, int* wait)
+{
+ // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // ToDo
+ }
+ __UNLIKELY_IF((addr > 0x000cffff) || (addr < 0x000c8000)) {
+ // Out of bounds
+ return;
+ }
+ __LIKELY_IF(addr < 0xcb000) { // From Tsugaru.
+ __LIKELY_IF(d_sprite != NULL) {
+ d_sprite->write_memory_mapped_io16w(addr - 0xc8000, data, wait);
+ d_sprite->write_signal(SIG_TOWNS_SPRITE_TVRAM_ENABLED, 0xffffffff, 0xffffffff);
}
- break;
- case 0x18:
- if(d_beep != NULL) {
- d_beep->write_signal(SIG_PCM1BIT_ON, 0, 1);
+ return;
+ }
+ __LIKELY_IF(addr >= 0x000cc000) {
+ // RAM: OK?
+ pair16_t w;
+ w.w = data;
+ __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cffff)) { // I/O
+ write_fmr_ports8(addr , w.b.l);
+ write_fmr_ports8(addr + 1, w.b.h);
+ return;
}
- break;
- case 0x19:
- if(d_sprite != NULL) {
- d_sprite->write_signal(SIG_TOWNS_SPRITE_ANKCG, ((data & 1) == 0) ? 0xffffffff : 0, 0xffffffff);
+ __LIKELY_IF(extra_ram != NULL) {
+ w.write_2bytes_le_to(&(extra_ram[addr]));
}
- break;
- case 0x20:
- break;
- default:
- if(d_vram != NULL) {
- d_vram->write_memory_mapped_io8(addr , data);
+ return;
+ }
+ // ROMs?
+ return;
+}
+
+void TOWNS_MEMORY::write_memory_mapped_io32w(uint32_t addr, uint32_t data, int* wait)
+{
+ // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
+ __LIKELY_IF(wait != NULL) {
+ *wait = 0; // ToDo
+ }
+ __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
+ return;
+ }
+ __LIKELY_IF(addr < 0xcb000) { // From Tsugaru.
+ __LIKELY_IF(d_sprite != NULL) {
+ d_sprite->write_memory_mapped_io32w(addr - 0xc8000, data, wait);
+ d_sprite->write_signal(SIG_TOWNS_SPRITE_TVRAM_ENABLED, 0xffffffff, 0xffffffff);
}
- break;
+ return;
}
+ __LIKELY_IF(addr >= 0x000cc000) {
+ // RAM: OK?
+ pair32_t d;
+ d.d = data;
+ __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cfffd)) { // I/O
+ write_fmr_ports8(addr , d.b.l);
+ write_fmr_ports8(addr + 1, d.b.h);
+ write_fmr_ports8(addr + 2, d.b.h2);
+ write_fmr_ports8(addr + 3, d.b.h3);
+ return;
+ }
+ __LIKELY_IF(extra_ram != NULL) {
+ d.write_4bytes_le_to(&(extra_ram[addr]));
+ }
+ return;
+ }
+ // ROMs?
return;
}
+
+
+
void TOWNS_MEMORY::write_signal(int ch, uint32_t data, uint32_t mask)
{
if(ch == SIG_MEMORY_EXTNMI) {
extra_nmi_val = ((data & mask) != 0);
if(!(extra_nmi_mask)) {
// Not MASK
- if(d_cpu != NULL) {
+ __LIKELY_IF(d_cpu != NULL) {
d_cpu->write_signal(SIG_CPU_NMI, data, mask);
}
- }
+ }
} else if(ch == SIG_CPU_NMI) {
// Check protect
- if(d_cpu != NULL) {
- d_cpu->write_signal(SIG_CPU_NMI, data, mask);
+ if(!(nmi_mask)) {
+ __LIKELY_IF(d_cpu != NULL) {
+ d_cpu->write_signal(SIG_CPU_NMI, data, mask);
+ }
}
} else if(ch == SIG_CPU_IRQ) {
- if(d_cpu != NULL) {
+ __LIKELY_IF(d_cpu != NULL) {
d_cpu->write_signal(SIG_CPU_IRQ, data, mask);
}
} else if(ch == SIG_CPU_BUSREQ) {
- if(d_cpu != NULL) {
+ __LIKELY_IF(d_cpu != NULL) {
d_cpu->write_signal(SIG_CPU_BUSREQ, data, mask);
}
} else if(ch == SIG_I386_A20) {
- if(d_cpu != NULL) {
+ __LIKELY_IF(d_cpu != NULL) {
d_cpu->write_signal(SIG_I386_A20, data, mask);
}
} else if(ch == SIG_FMTOWNS_NOTIFY_RESET) {
out_debug_log("RESET FROM CPU!!!\n");
- if(d_cpu != NULL) {
+ reset_happened = true;
+
+ nmi_vector_protect = false;
+ ankcg_enabled = false;
+ nmi_mask = false;
+ config_page0c_0e(true, false, true);
+ config_page0f(true, true);
+ reset_wait_values();
+ set_wait_values();
+
+ __LIKELY_IF(d_cpu != NULL) {
d_cpu->set_address_mask(0xffffffff);
}
- if(d_dmac != NULL) {
- d_dmac->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, 0xffffffff, 0xffffffff);
+ __LIKELY_IF(d_dmac != NULL) {
+ uint8_t wrap_val = 0xff; // WRAP ON
+ d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
}
} else if(ch == SIG_FMTOWNS_RAM_WAIT) {
+ uint8_t _bak = mem_wait_val;
mem_wait_val = (int)data;
- set_wait_values();
+ if(_bak != mem_wait_val) {
+ set_wait_values();
+ }
} else if(ch == SIG_FMTOWNS_ROM_WAIT) {
// mem_wait_val = (int)data;
set_wait_values();
} else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
+ uint8_t _bak = vram_wait_val;
vram_wait_val = (int)data;
- set_wait_values();
+ if(_bak != vram_wait_val) {
+ set_wait_values();
+ }
}
}
return 6; // OK?
} else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
return (uint32_t)vram_wait_val;
- }
+ }
return 0;
}
void TOWNS_MEMORY::set_intr_line(bool line, bool pending, uint32_t bit)
{
- if(d_cpu != NULL) {
+ __LIKELY_IF(d_cpu != NULL) {
d_cpu->set_intr_line(line, pending, bit);
}
}
// ToDo: DMA
-#define STATE_VERSION 1
+#define STATE_VERSION 8
bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
{
if(!state_fio->StateCheckUint32(STATE_VERSION)) {
return false;
}
-
+
if(!state_fio->StateCheckInt32(this_device_id)) {
return false;
}
state_fio->StateValue(machine_id);
state_fio->StateValue(cpu_id);
-
+ state_fio->StateValue(is_compatible);
+
+ state_fio->StateValue(mem_wait_val);
+ state_fio->StateValue(vram_wait_val);
+ state_fio->StateValue(wait_register_older);
+ state_fio->StateValue(wait_register_ram);
+ state_fio->StateValue(wait_register_vram);
+
state_fio->StateValue(dma_is_vram);
state_fio->StateValue(nmi_vector_protect);
state_fio->StateValue(software_reset);
-
+ state_fio->StateValue(poff_status);
+ state_fio->StateValue(reset_happened);
+
state_fio->StateValue(extra_nmi_val);
state_fio->StateValue(extra_nmi_mask);
-
- 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_pagee, sizeof(ram_pagee), 1);
- state_fio->StateArray(ram_pagef, sizeof(ram_pagef), 1);
+ state_fio->StateValue(nmi_mask);
+
+
+ state_fio->StateValue(select_d0_rom);
+ state_fio->StateValue(select_d0_dict);
+ state_fio->StateValue(ankcg_enabled);
+
+ state_fio->StateValue(vram_wait_val);
+ state_fio->StateValue(mem_wait_val);
+ state_fio->StateValue(vram_size);
+ state_fio->StateValue(cpu_clock_val);
+
if(loading) {
+ update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
+
uint32_t length_tmp = state_fio->FgetUint32_LE();
+ unset_range_rw(0x00100000, 0x3fffffff);
if(extra_ram != NULL) {
free(extra_ram);
extra_ram = NULL;
}
length_tmp = length_tmp & 0x3ff00000;
extram_size = length_tmp;
- if(length_tmp > 0) {
- extra_ram = (uint8_t*)malloc(length_tmp);
+ extra_ram = (uint8_t*)malloc(length_tmp + 0x00100000);
+ __LIKELY_IF(extra_ram != NULL) {
+ set_region_memory_rw(0x00000000, (extram_size + 0x00100000) - 1, extra_ram, 0);
+ memset(extra_ram, 0x00, extram_size + 0x00100000);
}
- unset_memory_rw(0x00100000, 0x3fffffff);
+
if(extra_ram == NULL) {
extram_size = 0;
return false;
} else {
- state_fio->Fread(extra_ram, extram_size, 1);
- set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
+ state_fio->Fread(extra_ram, extram_size + 0x00100000, 1);
+ //set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
}
+ config_page0c_0e(dma_is_vram, select_d0_dict, true);
+ config_page0f(select_d0_rom, true);
set_wait_values();
+ //config_page00();
} else {
// At saving
if(extra_ram == NULL) {
state_fio->FputUint32_LE(0);
} else {
state_fio->FputUint32_LE(extram_size & 0x3ff00000);
- state_fio->Fwrite(extra_ram, extram_size, 1);
+ state_fio->Fwrite(extra_ram, extram_size + 0x00100000, 1);
}
}
-
- state_fio->StateValue(vram_wait_val);
- state_fio->StateValue(mem_wait_val);
- state_fio->StateValue(vram_size);
// ToDo: Do save ROMs?
return true;