OSDN Git Service

[VM][FMTOWNS][TOWNS_MEMORY] Make addressing more correctness.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / towns_memory.cpp
index a6ca6e0..5b957cd 100644 (file)
@@ -57,18 +57,11 @@ void TOWNS_MEMORY::initialize()
 
        reset_wait_values();
 
-       set_region_memory_rw(0x00000000, 0x000bffff, ram_page0);
-       set_region_memory_rw(0x000c0000, 0x000fffff, ram_pagec);
-       memset(ram_page0, 0x00, sizeof(ram_page0));
-       memset(ram_pagec, 0x00, sizeof(ram_pagec));
-
-       if(extram_size >= 0x00100000) {
-               __UNLIKELY_IF(extra_ram == NULL) {
-                       extra_ram = (uint8_t*)malloc(extram_size);
-                       __LIKELY_IF(extra_ram != NULL) {
-                               set_region_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
-                               memset(extra_ram, 0x00, extram_size);
-                       }
+       __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);
                }
        }
 
@@ -83,22 +76,22 @@ void TOWNS_MEMORY::initialize()
        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, 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, NOT_NEED_TO_OFFSET);
+       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, 0xc2140000 + memory_map_grain() - 1, d_dictionary, NOT_NEED_TO_OFFSET);
+       set_region_device_rw(0xc2140000, 0xc2147fff, d_cmos, 0);
        if(d_font_20pix != NULL) {
-               set_region_device_r (0xc2180000, 0xc21fffff, d_font_20pix, NOT_NEED_TO_OFFSET);
+               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, NOT_NEED_TO_OFFSET);
-       set_region_device_r (0xfffc0000, 0xffffffff, d_sysrom, NOT_NEED_TO_OFFSET);
+       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
@@ -120,7 +113,7 @@ void TOWNS_MEMORY::config_page0c_0e(const bool vrambank, const bool dictbank, co
 {
        const bool is_vram_bak = dma_is_vram;
        const bool is_dict_bak = select_d0_dict;
-       __UNLIKELY_IF((vrambank != is_vram_bak) || (force)){
+       //__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);
@@ -130,363 +123,210 @@ void TOWNS_MEMORY::config_page0c_0e(const bool vrambank, const bool dictbank, co
                        set_mmio_wait_rw(0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
                        set_dma_wait_rw (0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
                } else {
-                       set_region_memory_rw(0x000c0000, 0x000cffff, ram_pagec);
-                       set_region_memory_rw(0x000e0000, 0x000effff, &(ram_pagec[0x20000]));
+                       __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
                }
-       }
-       __UNLIKELY_IF((vrambank != is_vram_bak) || (dictbank != is_dict_bak) || (force)){
+       //}
+       //__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, 0x000d8000 + memory_map_grain() - 1, d_dictionary, NOT_NEED_TO_OFFSET);
+                               set_region_device_rw(0x000d8000, 0x000dffff, d_cmos, 0);
                        } else {
                                unset_range_rw(0x000d0000, 0x000dffff);
                        }
                } else {
-                       set_region_memory_rw(0x000d0000, 0x000dffff, &(ram_pagec[0x10000]));
+                       __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::config_page0f(const bool sysrombank, const bool force)
 {
        bool sysrom_bak = select_d0_rom;
-       set_region_memory_rw(0x000f0000, 0x000f7fff, &(ram_pagec[0x30000]));
-       __UNLIKELY_IF((sysrombank != sysrom_bak) || (force)) {
+       //__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_rw(0x000f8000, 0x000fffff, d_sysrom, NOT_NEED_TO_OFFSET);
+                       set_region_device_r (0x000f8000, 0x000fffff, d_sysrom, 0x38000);
                } else {
-                       set_region_memory_rw(0x000f8000, 0x000fffff, &(ram_pagec[0x38000]));
+                       __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_mmio_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr)
+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)
 {
        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());
 
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
+       uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
        const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
+       uint32_t realoffset = (base_offset == UINT32_MAX) ? 0 : base_offset;
+
        for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               mmio_memory_map_r[mapptr] = &(baseptr[realoffset]);
-               mmio_devices_map_r[mapptr] = NULL;
+               __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;
+               }
+               if(base_offset == UINT32_MAX) {
+                       dataptr[mapptr].base_offset = UINT32_MAX;
+               } else {
+                       dataptr[mapptr].base_offset = realoffset;
+               }
                realoffset += _incval;
                mapptr++;
        }
 }
 
-void TOWNS_MEMORY::set_mmio_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr)
+void TOWNS_MEMORY::set_memory_devices_map_wait(uint32_t start, uint32_t end, memory_device_map_t* dataptr, int wait)
 {
        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());
 
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
+       uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
        const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
+
        for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               mmio_memory_map_w[mapptr] = &(baseptr[realoffset]);
-               mmio_devices_map_w[mapptr] = NULL;
-               realoffset += _incval;
+               __UNLIKELY_IF(mapptr >= memory_map_size()) break; // Safety
+               dataptr[mapptr].waitval = wait;
                mapptr++;
        }
 }
 
-void  __FASTCALL TOWNS_MEMORY::set_mmio_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
+void TOWNS_MEMORY::unset_memory_devices_map(uint32_t start, uint32_t end, memory_device_map_t* dataptr, int wait)
 {
        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());
 
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
+       uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
        const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
        for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               mmio_memory_map_r[mapptr] = NULL;
-               mmio_devices_map_r[mapptr] = ptr;
-               __LIKELY_IF(baseaddress == UINT32_MAX) {
-                       mmio_devices_base_r[mapptr] = UINT32_MAX;
-               } else {
-                       mmio_devices_base_r[mapptr] = baseaddress + realoffset;
-               }
-               realoffset += _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  __FASTCALL TOWNS_MEMORY::set_mmio_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
+void TOWNS_MEMORY::set_mmio_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
+       set_memory_devices_map_values(start, end, &(membus_read_map[0]), baseptr, NULL, base_offset);
+}
 
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               mmio_memory_map_w[mapptr] = NULL;
-               mmio_devices_map_w[mapptr] = ptr;
-               __LIKELY_IF(baseaddress == UINT32_MAX) {
-                       mmio_devices_base_w[mapptr] = UINT32_MAX;
-               } else {
-                       mmio_devices_base_w[mapptr] = baseaddress + realoffset;
-               }
-               realoffset += _incval;
-               mapptr++;
-       }
+void TOWNS_MEMORY::set_mmio_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
+{
+       set_memory_devices_map_values(start, end, &(membus_write_map[0]), baseptr, NULL, base_offset);
 }
 
-void  __FASTCALL TOWNS_MEMORY::set_mmio_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)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
+       set_memory_devices_map_values(start, end, &(membus_read_map[0]), NULL, ptr, baseaddress);
+}
 
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
+void  __FASTCALL TOWNS_MEMORY::set_mmio_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
+{
+       set_memory_devices_map_values(start, end, &(membus_write_map[0]), NULL, ptr, baseaddress);
+}
 
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               mmio_wait_map_w[mapptr] = wait;
-               mapptr++;
-       }
+void  __FASTCALL TOWNS_MEMORY::set_mmio_wait_r(uint32_t start, uint32_t end, int wait)
+{
+       set_memory_devices_map_wait(start, end, &(membus_read_map[0]), wait);
 }
 
 void  __FASTCALL TOWNS_MEMORY::set_mmio_wait_w(uint32_t start, uint32_t end, int wait)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               mmio_wait_map_r[mapptr] = wait;
-               mapptr++;
-       }
+       set_memory_devices_map_wait(start, end, &(membus_write_map[0]), wait);
 }
 
-void TOWNS_MEMORY::unset_mmio_r(uint32_t start, uint32_t end)
+void TOWNS_MEMORY::unset_mmio_r(uint32_t start, uint32_t end, int wait)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               mmio_memory_map_r[mapptr] = NULL;
-               mmio_devices_map_r[mapptr] = NULL;
-               mmio_wait_map_r[mapptr] = WAITVAL_RAM;
-               realoffset += _incval;
-               mapptr++;
-       }
+       unset_memory_devices_map(start, end, &(membus_read_map[0]), wait);
 }
 
-void TOWNS_MEMORY::unset_mmio_w(uint32_t start, uint32_t end)
+void TOWNS_MEMORY::unset_mmio_w(uint32_t start, uint32_t end, int wait)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               mmio_memory_map_w[mapptr] = NULL;
-               mmio_devices_map_w[mapptr] = NULL;
-               mmio_wait_map_w[mapptr] = WAITVAL_RAM;
-               realoffset += _incval;
-               mapptr++;
-       }
+       unset_memory_devices_map(start, end, &(membus_write_map[0]), wait);
 }
 
-void TOWNS_MEMORY::unset_dma_r(uint32_t start, uint32_t end)
+void TOWNS_MEMORY::unset_dma_r(uint32_t start, uint32_t end, int wait)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               dma_memory_map_w[mapptr] = NULL;
-               dma_devices_map_w[mapptr] = NULL;
-               dma_wait_map_w[mapptr] = WAITVAL_RAM;
-               realoffset += _incval;
-               mapptr++;
-       }
+       unset_memory_devices_map(start, end, &(dma_read_map[0]), wait);
 }
 
-void TOWNS_MEMORY::unset_dma_w(uint32_t start, uint32_t end)
+void TOWNS_MEMORY::unset_dma_w(uint32_t start, uint32_t end, int wait)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               dma_memory_map_w[mapptr] = NULL;
-               dma_devices_map_w[mapptr] = NULL;
-               dma_wait_map_w[mapptr] = WAITVAL_RAM;
-               realoffset += _incval;
-               mapptr++;
-       }
+       unset_memory_devices_map(start, end, &(dma_write_map[0]), wait);
 }
 
-void TOWNS_MEMORY::set_dma_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr)
+void TOWNS_MEMORY::set_dma_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               dma_memory_map_r[mapptr] = &(baseptr[realoffset]);
-               dma_devices_map_r[mapptr] = NULL;
-               realoffset += _incval;
-               mapptr++;
-       }
+       set_memory_devices_map_values(start, end, &(dma_read_map[0]), baseptr, NULL, base_offset);
 }
 
-void TOWNS_MEMORY::set_dma_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr)
+void TOWNS_MEMORY::set_dma_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               dma_memory_map_w[mapptr] = &(baseptr[realoffset]);
-               dma_devices_map_w[mapptr] = NULL;
-               realoffset += _incval;
-               mapptr++;
-       }
+       set_memory_devices_map_values(start, end, &(dma_write_map[0]), baseptr, NULL, base_offset);
 }
 
 void  __FASTCALL TOWNS_MEMORY::set_dma_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               dma_memory_map_r[mapptr] = NULL;
-               dma_devices_map_r[mapptr] = ptr;
-               __LIKELY_IF(baseaddress == UINT32_MAX) {
-                       dma_devices_base_r[mapptr] = UINT32_MAX;
-               } else {
-                       dma_devices_base_r[mapptr] = baseaddress + realoffset;
-               }
-               realoffset += _incval;
-               mapptr++;
-       }
+       set_memory_devices_map_values(start, end, &(dma_read_map[0]), NULL, ptr, baseaddress);
 }
 
 void  __FASTCALL TOWNS_MEMORY::set_dma_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               dma_memory_map_w[mapptr] = NULL;
-               dma_devices_map_w[mapptr] = ptr;
-               __LIKELY_IF(baseaddress == UINT32_MAX) {
-                       dma_devices_base_w[mapptr] = UINT32_MAX;
-               } else {
-                       dma_devices_base_w[mapptr] = baseaddress + realoffset;
-               }
-               realoffset += _incval;
-               mapptr++;
-       }
+       set_memory_devices_map_values(start, end, &(dma_write_map[0]), NULL, ptr, baseaddress);
 }
 
 void  __FASTCALL TOWNS_MEMORY::set_dma_wait_r(uint32_t start, uint32_t end, int wait)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               dma_wait_map_w[mapptr] = wait;
-               mapptr++;
-       }
+       set_memory_devices_map_wait(start, end, &(dma_read_map[0]), wait);
 }
 
 void  __FASTCALL TOWNS_MEMORY::set_dma_wait_w(uint32_t start, uint32_t end, int wait)
 {
-       uint64_t _start = (uint64_t)start;
-       uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
-
-       _start &= ~(memory_map_mask());
-       _end &= ~(memory_map_mask());
-
-       uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
-       const uint64_t _incval = memory_map_grain();
-       uint32_t realoffset = 0;
-       for(uint64_t addr = _start; addr < _end; addr += _incval) {
-               dma_wait_map_r[mapptr] = wait;
-               mapptr++;
-       }
+       set_memory_devices_map_wait(start, end, &(dma_write_map[0]), wait);
 }
 
 
@@ -582,79 +422,58 @@ void TOWNS_MEMORY::update_machine_features()
 uint8_t TOWNS_MEMORY::read_fmr_ports8(uint32_t addr)
 {
        uint8_t val = 0xff;
-       __UNLIKELY_IF((addr & 0xffff) < 0xff80) {
-               return ram_pagec[addr & 0xffff];
+       __UNLIKELY_IF((addr < 0xcff80) || (addr > 0xcffbb)) {
+               return val;
        }
-#if 1
-       __LIKELY_IF((addr & 0xffff) < 0xff88) {
+       __LIKELY_IF(addr < 0xcff88) {
                __LIKELY_IF(d_planevram != NULL) {
                        val = d_planevram->read_memory_mapped_io8(addr & 0xffff);
                }
                return val;
-       } else if(((addr & 0xffff) >= 0xff94) && ((addr & 0xffff) < 0xff98)) {
-               __LIKELY_IF(d_font != NULL) {
-                       val = d_font->read_io8(addr & 0xffff);
-               }
-               return val;
        }
-#endif
        if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
-               switch(addr & 0xffff) {
-               case 0xff88:
+               switch(addr) {
+               case 0xcff88:
                        __LIKELY_IF(d_crtc != NULL) {
                                val = d_crtc->read_signal(SIG_TOWNS_CRTC_MMIO_CFF82H);
                        }
                        return val;
                        break;
-               case 0xff99:
+               case 0xcff99:
                        return (ankcg_enabled) ? 0x01 : 0x00;
                        break;
-               case 0xff9c:
-               case 0xff9d:
-               case 0xff9e:
+               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 & 0xffff) {
-       case 0xff88:
-               __LIKELY_IF(d_planevram != NULL) {
-                       val = d_planevram->read_io8(addr);
-               }
-               break;
-       case 0xff95:
-               val = 0x80;
-               break;
-       case 0xff96:
-               __LIKELY_IF(d_font != NULL) {
-                       return d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_LOW);
-               }
-               break;
-       case 0xff97:
+       switch(addr) {
+       case 0xcff94:
+       case 0xcff95:
+       case 0xcff96:
+       case 0xcff97:
                __LIKELY_IF(d_font != NULL) {
-                       return d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_HIGH);
+                       val = d_font->read_io8(addr & 0xffff);
                }
                break;
-       case 0xff98:
+       case 0xcff98:
                __LIKELY_IF(d_timer != NULL) {
                        d_timer->write_signal(SIG_TIMER_BEEP_ON, 1, 1);
                }
                break;
-       case 0xff99:
+       case 0xcff99:
                __LIKELY_IF(d_planevram != NULL) {
                        val = d_planevram->read_memory_mapped_io8(addr);
                }
                break;
        default:
-               __LIKELY_IF(d_planevram != NULL) {
-                       val = d_planevram->read_io8(addr & 0xffff);
-               }
                break;
        }
        return val;
@@ -746,14 +565,15 @@ uint8_t TOWNS_MEMORY::read_sys_ports8(uint32_t addr)
        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_mask) ? 0x00 : 0x08;
+//             val = (extra_nmi_mask) ? 0xf7 : 0xff;
+               val = (extra_nmi_mask) ? 0x00 : 0x08;
                break;
        case 0x05c2:
-               val = (extra_nmi_val) ? 0xff : 0xf7;
-//             val = (extra_nmi_val) ? 0x08 : 0x00;
+//             val = (extra_nmi_val) ? 0xff : 0xf7;
+               val = (extra_nmi_val) ? 0x08 : 0x00;
                break;
        case 0x05e0:
                if(machine_id < 0x0200) { // Towns 1/2
@@ -774,18 +594,34 @@ uint8_t TOWNS_MEMORY::read_sys_ports8(uint32_t addr)
                // After Towns1F/2F/1H/2H
                {
                        uint16_t nid = machine_id & 0xff00;
-                       if(nid >= 0x1000) {
-                               val = (extram_size >> 20) & 0x7f; // MAX 128MB
-                       } else if(nid >= 0x0900) { // UR,MA,MX,ME,MF
-                               val = (extram_size >> 20) & 0x1f; // MAX 32MB
-                       } else if(nid == 0x0800) { // HG
-                               val = (extram_size >> 20) & 0x0f; // MAX 15MB
-                       } else if(nid == 0x0700) { // HR
-                               val = (extram_size >> 20) & 0x1f; // MAX 32MB
-                       } else if(nid >= 0x0200) { // 2nd GEN,3rd Gen, UX/UG, CX
-                               val = (extram_size >> 20) & 0x0f; // MAX 15MB
-                       } else {
-                               val = 0xff; // NOT SUPPORTED
+                       val = extram_size >> 20;
+                       switch(nid >> 8) {
+                       case 0x00:
+                       case 0x01: // Towns 1/2 : Not Supported.
+                               val = 0xff;
+                               break;
+                       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 0x07: // Towns II HR
+                       case 0x09: // Towns II UR
+                               val = val & 0x1f;
+                               break;
+                       default:   // After MA/MX/ME/MF, Fresh
+                               val = val & 0x7f;
+                               break;
                        }
                }
                break;
@@ -826,46 +662,29 @@ uint8_t TOWNS_MEMORY::read_sys_ports8(uint32_t addr)
 // Is set extra NMI (0x05c0 - 0x05c2)?
 uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
 {
-       __LIKELY_IF((addr & 0xffff) >= 0xff80) {
-               return read_fmr_ports8(addr & 0xffff);
-       }
-       return read_sys_ports8(addr);
-}
-
-uint32_t TOWNS_MEMORY::read_io8w(uint32_t addr, int *wait)
-{
 //     uint32_t val = 0x00;  // MAY NOT FILL to "1" for unused bit 20200129 K.O
        __LIKELY_IF((addr & 0xffff) >= 0xff80) {
-               *wait = 6; // ToDo: will io_wait_val.
-               return read_fmr_ports8(addr & 0xffff);
+               return read_fmr_ports8((addr & 0xffff) | 0x000c0000);
        }
-       *wait = 6; // ToDo: will io_wait_val.
        return read_sys_ports8(addr);
 }
 
-
 void TOWNS_MEMORY::write_fmr_ports8(uint32_t addr, uint32_t data)
 {
-       __UNLIKELY_IF((addr & 0xffff) < 0xff80) {
-               ram_pagec[addr & 0xffff] = data;
+       __UNLIKELY_IF((addr < 0xcff80) || (addr > 0xcffbb)) {
                return;
        }
-#if 1
-       __LIKELY_IF((addr & 0xffff) < 0xff88) {
+
+       __LIKELY_IF(addr < 0xcff88) {
                __LIKELY_IF(d_planevram != NULL) {
                        d_planevram->write_io8(addr & 0xffff, data);
                }
                return;
-       } else if(((addr & 0xffff) >= 0xff94) && ((addr & 0xffff) < 0xff98)) {
-               __LIKELY_IF(d_font != NULL) {
-                       d_font->write_io8(addr & 0xffff, data);
-               }
-               return;
        }
-#endif
+
        if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
-               switch(addr & 0xffff) {
-               case 0xff9e:
+               switch(addr) {
+               case 0xcff9e:
                        __LIKELY_IF(d_font != NULL) {
                                d_font->write_io8(addr & 0xffff, data);
                        }
@@ -874,39 +693,33 @@ void TOWNS_MEMORY::write_fmr_ports8(uint32_t addr, uint32_t data)
                        break;
                }
        }
-       switch(addr & 0xffff) {
-       case 0xff94:
-               __LIKELY_IF(d_font != NULL) {
-                       d_font->write_signal(SIG_TOWNS_FONT_KANJI_HIGH, data, 0xff);
-               }
-               break;
-       case 0xff95:
+       switch(addr) {
+       case 0xcff94:
+       case 0xcff95:
                __LIKELY_IF(d_font != NULL) {
-                       d_font->write_signal(SIG_TOWNS_FONT_KANJI_LOW, data, 0xff);
+                       d_font->write_io8(addr & 0xffff, data);
                }
                break;
-       case 0xff96:
-       case 0xff97:
+       case 0xcff96:
+       case 0xcff97:
                break;
-       case 0xff98:
+       case 0xcff98:
                __LIKELY_IF(d_timer != NULL) {
                        d_timer->write_signal(SIG_TIMER_BEEP_ON, 0, 1);
                }
                break;
-       case 0xff99:
+       case 0xcff99:
                {
                        bool _b = ankcg_enabled;
                        ankcg_enabled = ((data & 1) != 0) ? true : false;
                }
                break;
-       case 0xffa0:
+       case 0xcffa0:
                __LIKELY_IF(d_planevram != NULL) {
                        d_planevram->write_io8(addr & 0xffff, data);
                }
+               break;
        default:
-               __LIKELY_IF(d_planevram != NULL) {
-                       d_planevram->write_io8(addr & 0xffff, data);
-               }
                break;
        }
 }
@@ -1098,360 +911,94 @@ void TOWNS_MEMORY::write_sys_ports8(uint32_t addr, uint32_t data)
 void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
 {
        __LIKELY_IF((addr & 0xffff) >= 0xff80) {
-               write_fmr_ports8(addr & 0xffff, data);
+               write_fmr_ports8((addr & 0xffff) | 0x000c0000, data);
                return;
        }
        write_sys_ports8(addr, data);
 }
 
-void TOWNS_MEMORY::write_io8w(uint32_t addr, uint32_t data, int *wait)
-{
-       __LIKELY_IF((addr & 0xffff) >= 0xff80) {
-               *wait = 6; // ToDo: will io_wait_val.
-               write_fmr_ports8(addr & 0xffff, data);
-               return;
-       }
-       *wait = 6; // ToDo: will io_wait_val.
-       write_sys_ports8(addr, data);
-       return;
-}
 
 uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int* wait)
 {
-       uint8_t val = 0xff;
-       int waitval;
        uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
        uint32_t offset = addr & memory_map_mask();
-       __LIKELY_IF(mmio_memory_map_r[mapptr] != NULL) {
-               uint8_t* ptr = mmio_memory_map_r[mapptr];
-               val = ptr[offset];
-       } else if(mmio_devices_map_r[mapptr] != NULL) {
-               DEVICE* dev = mmio_devices_map_r[mapptr];
-               __LIKELY_IF(mmio_devices_base_r[mapptr] == UINT32_MAX) {
-                       val = dev->read_memory_mapped_io8(addr);
-               } else {
-                       offset += mmio_devices_base_r[mapptr];
-                       val = dev->read_memory_mapped_io8(offset);
-               }
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = mmio_wait_map_r[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               *wait = waitval;
-       }
-       return val;
+       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 = 0xffff;
-       int waitval;
+       uint16_t val;
        uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
        uint32_t offset = addr & memory_map_mask();
-       __UNLIKELY_IF(offset == memory_map_mask()) {
-               pair16_t w;
-               int wait1, wait2;
-               w.b.l = read_data8w(addr    , &wait1);
-               w.b.h = read_data8w(addr + 1, &wait2);
-               __LIKELY_IF(wait != NULL) {
-                       *wait = wait1;
-                       //*wait = wait1 + wait2;
-               }
-               return w.w;
-       }
-       __LIKELY_IF(mmio_memory_map_r[mapptr] != NULL) {
-               uint8_t* ptr = mmio_memory_map_r[mapptr];
-               ptr = &(ptr[offset]);
-               #ifdef __BIG_ENDIAN__
-               pair16_t w;
-               w.read_2bytes_le_from(ptr);
-               val = w.w;
-               #else
-               __LIKELY_IF((offset & 1) == 0) {
-                       uint16_t* q = (uint16_t*)ptr;
-                       val = *q;
-               } else {
-                       pair16_t w;
-                       w.read_2bytes_le_from(ptr);
-                       val = w.w;
-               }
-               #endif
-       } else if(mmio_devices_map_r[mapptr] != NULL) {
-               DEVICE* dev = mmio_devices_map_r[mapptr];
-               __LIKELY_IF(mmio_devices_base_r[mapptr] == UINT32_MAX) {
-                       val = dev->read_memory_mapped_io16(addr);
-               } else {
-                       offset += mmio_devices_base_r[mapptr];
-                       val = dev->read_memory_mapped_io16(offset);
-               }
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = mmio_wait_map_r[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               //__LIKELY_IF((offset & 1) == 0) {
-                       *wait = waitval;
-               //} else {
-               //      *wait = waitval * 2;
-               //}
+       __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 = 0xffffffff;
-       int waitval;
+       uint32_t val;
        uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
        uint32_t offset = addr & memory_map_mask();
-       __UNLIKELY_IF(offset > (memory_map_mask() - 3)) {
-               pair32_t d;
-               pair16_t w;
-               int wait1, wait2, wait3;
-               switch(offset & 3) {
-               case 1:
-               case 3:
-                       d.b.l  = read_data8w (addr    , &wait1);
-                       w.w    = read_data16w(addr + 1, &wait2);
-                       d.b.h3 = read_data8w (addr + 3, &wait3);
-                       __LIKELY_IF(wait != NULL) {
-                               *wait = wait1;
-                               //*wait = wait1 + wait2 + wait3;
-                       }
-                       break;
-               case 2:
-                       d.w.l  = read_data16w(addr    , &wait1);
-                       d.w.h  = read_data16w(addr + 2, &wait2);
-                       __LIKELY_IF(wait != NULL) {
-                               *wait = wait1;
-                               //*wait = wait1 + wait2;
-                       }
-               default:
-                       __LIKELY_IF(wait != NULL) {
-                               waitval = mmio_wait_map_r[mapptr];
-                               __LIKELY_IF(waitval < 0) {
-                                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-                               }
-                               *wait = waitval;
-                               //*wait = wait1 + wait2;
-                       }
-               }
-               return d.d;
-       }
-       __LIKELY_IF(mmio_memory_map_r[mapptr] != NULL) {
-               uint8_t* ptr = mmio_memory_map_r[mapptr];
-               ptr = &(ptr[offset]);
-               #ifdef __BIG_ENDIAN__
-               pair32_t w;
-               d.read_4bytes_le_from(ptr);
-               val = d.d;
-               #else
-               __LIKELY_IF((offset & 3) == 0) {
-                       uint32_t* q = (uint32_t*)ptr;
-                       val = *q;
-               } else {
-                       pair32_t d;
-                       d.read_4bytes_le_from(ptr);
-                       val = d.d;
-               }
-               #endif
-       } else if(mmio_devices_map_r[mapptr] != NULL) {
-               DEVICE* dev = mmio_devices_map_r[mapptr];
-               __LIKELY_IF(mmio_devices_base_r[mapptr] == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += mmio_devices_base_r[mapptr];
-               }
-               val = dev->read_memory_mapped_io32(offset);
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = mmio_wait_map_r[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               //__LIKELY_IF((offset & 1) == 0) {
-                       *wait = waitval;
-               //} else {
-               //      *wait = waitval * 2;
-               //}
+       __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);
+
        }
        return val;
 }
 
 uint32_t TOWNS_MEMORY::read_dma_data8w(uint32_t addr, int* wait)
 {
-       uint8_t val = 0xff;
-       int waitval;
        uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
        uint32_t offset = addr & memory_map_mask();
-       __LIKELY_IF((dma_memory_map_r[mapptr] == NULL) && (dma_devices_map_r[mapptr] == NULL)) {
-               return read_data8w(addr, wait);
-       }
-
-       __LIKELY_IF(dma_memory_map_r[mapptr] != NULL) {
-               uint8_t* ptr = dma_memory_map_r[mapptr];
-               val = ptr[offset];
-       } else if(dma_devices_map_r[mapptr] != NULL) {
-               DEVICE* dev = dma_devices_map_r[mapptr];
-               __LIKELY_IF(dma_devices_base_r[mapptr] == UINT32_MAX) {
-                       val = dev->read_memory_mapped_io8(addr);
-               } else {
-                       offset += dma_devices_base_r[mapptr];
-                       val = dev->read_memory_mapped_io8(offset);
-               }
-       }
+       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) {
-               waitval = dma_wait_map_r[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               *wait = waitval;
+               *wait = 0; // Discard wait value for DMA.
        }
        return val;
 }
 
 uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
 {
-       uint16_t val = 0xffff;
-       int waitval;
        uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
        uint32_t offset = addr & memory_map_mask();
-       __UNLIKELY_IF(offset == memory_map_mask()) {
-               pair16_t w;
-               int wait1, wait2;
-               w.b.l = read_data8w(addr    , &wait1);
-               w.b.h = read_data8w(addr + 1, &wait2);
-               __LIKELY_IF(wait != NULL) {
-                       *wait = wait1;
-                       //*wait = wait1 + wait2;
-               }
-               return w.w;
-       }
-       __LIKELY_IF((dma_memory_map_r[mapptr] == NULL) && (dma_devices_map_r[mapptr] == NULL)) {
-               return read_data16w(addr, wait);
-       }
-       __LIKELY_IF(dma_memory_map_r[mapptr] != NULL) {
-               uint8_t* ptr = dma_memory_map_r[mapptr];
-               ptr = &(ptr[offset]);
-               #ifdef __BIG_ENDIAN__
-               pair16_t w;
-               w.read_2bytes_le_from(ptr);
-               val = w.w;
-               #else
-               __LIKELY_IF((offset & 1) == 0) {
-                       uint16_t* q = (uint16_t*)ptr;
-                       val = *q;
-               } else {
-                       pair16_t w;
-                       w.read_2bytes_le_from(ptr);
-                       val = w.w;
-               }
-               #endif
-       } else if(dma_devices_map_r[mapptr] != NULL) {
-               DEVICE* dev = dma_devices_map_r[mapptr];
-               __LIKELY_IF(dma_devices_base_r[mapptr] == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += dma_devices_base_r[mapptr];
-               }
-               val = dev->read_memory_mapped_io16(offset);
+       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) {
-               waitval = dma_wait_map_r[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               //__LIKELY_IF((offset & 1) == 0) {
-                       *wait = waitval;
-               //} else {
-               //      *wait = waitval * 2;
-               //}
+               *wait = 0; // Discard wait value for DMA.
        }
        return val;
+
 }
 
 uint32_t TOWNS_MEMORY::read_dma_data32w(uint32_t addr, int* wait)
 {
-       uint32_t val = 0xffffffff;
+       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(offset > (memory_map_mask() - 3)) {
-               pair32_t d;
-               pair16_t w;
-               int wait1, wait2, wait3;
-               switch(offset & 3) {
-               case 1:
-               case 3:
-                       d.b.l  = read_dma_data8w (addr    , &wait1);
-                       w.w    = read_dma_data16w(addr + 1, &wait2);
-                       d.b.h3 = read_dma_data8w (addr + 3, &wait3);
-                       __LIKELY_IF(wait != NULL) {
-                               *wait = wait1;
-                               //*wait = wait1 + wait2 + wait3;
-                       }
-                       break;
-               case 2:
-                       d.w.l  = read_dma_data16w(addr    , &wait1);
-                       d.w.h  = read_dma_data16w(addr + 2, &wait2);
-                       __LIKELY_IF(wait != NULL) {
-                               *wait = wait1;
-                               //*wait = wait1 + wait2;
-                       }
-               default:
-                       __LIKELY_IF(wait != NULL) {
-                               waitval = dma_wait_map_r[mapptr];
-                               __LIKELY_IF(waitval < 0) {
-                                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-                               }
-                               *wait = waitval;
-                               //*wait = wait1 + wait2;
-                       }
-               }
-               return d.d;
-       }
-       __LIKELY_IF((dma_memory_map_r[mapptr] == NULL) && (dma_devices_map_r[mapptr] == NULL)) {
-               return read_data32w(addr, wait);
-       }
-       __LIKELY_IF(dma_memory_map_r[mapptr] != NULL) {
-               uint8_t* ptr = dma_memory_map_r[mapptr];
-               ptr = &(ptr[offset]);
-               #ifdef __BIG_ENDIAN__
-               pair32_t w;
-               d.read_4bytes_le_from(ptr);
-               val = d.d;
-               #else
-               __LIKELY_IF((offset & 3) == 0) {
-                       uint32_t* q = (uint32_t*)ptr;
-                       val = *q;
-               } else {
-                       pair32_t d;
-                       d.read_4bytes_le_from(ptr);
-                       val = d.d;
-               }
-               #endif
-       } else if(dma_devices_map_r[mapptr] != NULL) {
-               DEVICE* dev = dma_devices_map_r[mapptr];
-               __LIKELY_IF(dma_devices_base_r[mapptr] == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += mmio_devices_base_r[mapptr];
-               }
-               val = dev->read_memory_mapped_io32(offset);
+       __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) {
-               waitval = dma_wait_map_r[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               //__LIKELY_IF((offset & 1) == 0) {
-                       *wait = waitval;
-               //} else {
-               //      *wait = waitval * 2;
-               //}
+               *wait = 0; // Discard wait value for DMA.
        }
        return val;
 }
@@ -1459,29 +1006,9 @@ uint32_t TOWNS_MEMORY::read_dma_data32w(uint32_t addr, int* wait)
 
 void TOWNS_MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
 {
-       int waitval;
        uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
        uint32_t offset = addr & memory_map_mask();
-       __LIKELY_IF(mmio_memory_map_w[mapptr] != NULL) {
-               uint8_t* ptr = mmio_memory_map_w[mapptr];
-               ptr[offset] = data;
-       } else if(mmio_devices_map_w[mapptr] != NULL) {
-               DEVICE* dev = mmio_devices_map_w[mapptr];
-               __LIKELY_IF(mmio_devices_base_w[mapptr] == UINT32_MAX) {
-                       dev->write_memory_mapped_io8(addr, data);
-               } else {
-                       offset += mmio_devices_base_w[mapptr];
-                       dev->write_memory_mapped_io8(offset, data);
-               }
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = mmio_wait_map_w[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               *wait = waitval;
-       }
-       return;
+       write_8bit_data(membus_write_map, mapptr, addr, offset, false, data, wait);
 }
 
 
@@ -1489,63 +1016,11 @@ 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();
-       int waitval;
-       __UNLIKELY_IF(offset == memory_map_mask()) {
-               // Beyond via bound
-               pair16_t d;
-               int wait1, wait2;
-               d.w = data;
-               write_data8w(addr    , d.b.l, &wait1);
-               write_data8w(addr + 1, d.b.h, &wait2);
-               __LIKELY_IF(wait != NULL) {
-                       *wait = wait1 + wait2;
-               }
-               return;
-       }
-       __LIKELY_IF(mmio_memory_map_w[mapptr] != NULL) {
-               uint8_t* ptr = mmio_memory_map_w[mapptr];
-               ptr = &(ptr[offset]);
-               #ifdef __BIG_ENDIAN__
-               pair16_t d;
-               d.w = data;
-               d.write_2bytes_le_to(ptr);
-               #else
-               __LIKELY_IF((offset & 1) == 0) { // Aligned
-                       uint16_t* q = (uint16_t*)ptr;
-                       *q = data;
-               } else {
-                       pair16_t d;
-                       d.w = data;
-                       d.write_2bytes_le_to(ptr);
-               }
-               #endif
-       } else if(mmio_devices_map_w[mapptr] != NULL) {
-               DEVICE* dev = mmio_devices_map_w[mapptr];
-               __LIKELY_IF(mmio_devices_base_w[mapptr] == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += mmio_devices_base_w[mapptr];
-               }
-               dev->write_memory_mapped_io16(offset, data);
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = mmio_wait_map_w[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               //#if _MEMORY_BUS_WIDTH == 16
-               //__UNLIKELY_IF((offset & 1) != 0) { // Penalty; maybe not need to.
-               //      waitval *= 2;
-               //}
-               //#else
-               // 32bit
-               //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
-               //      waitval *= 2;
-               //}
-               //#endif
-               *wait = waitval;
+       __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);
        }
-       return;
 }
 
 
@@ -1553,135 +1028,23 @@ 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();
-       int waitval;
-       __UNLIKELY_IF(offset > (memory_map_mask() - 3)) {
-               // Beyond via bound
-               pair32_t d;
-               pair16_t w;
-               int wait1, wait2, wait3;
-               d.d = data;
-               switch(offset & 3) {
-               case 1:
-               case 3:
-                       write_data8w(addr    , d.b.l, &wait1);
-                       w.b.l = d.b.h;
-                       w.b.h = d.b.h2;
-                       write_data16w(addr + 1, w.w, &wait2);
-                       write_data8w(addr + 3, d.b.h3, &wait3);
-                       __LIKELY_IF(wait != NULL) {
-                               *wait = wait1; // WORKAROUND
-                               //#if _MEMORY_BUS_WIDTH == 16
-                               //*wait = wait1 + wait2 + wait3; // OK?
-                               //#else
-                               //*wait = wait1 + wait3; // OK?
-                               //#endif
-                       }
-                       break;
-               case 2:
-                       write_data16w(addr    , d.w.l, &wait1);
-                       write_data16w(addr + 2, d.w.h, &wait2);
-                       __LIKELY_IF(wait != NULL) {
-                               *wait = wait1; // WORKAROUND
-                               //#if _MEMORY_BUS_WIDTH == 16
-                               //*wait = wait1 + wait2 + wait3; // OK?
-                               //#else
-                               //*wait = wait1 + wait3; // OK?
-                               //#endif
-                       }
-                       break;
-               default:
-                       __LIKELY_IF(wait != NULL) {
-                               waitval = mmio_wait_map_w[mapptr];
-                               __LIKELY_IF(waitval < 0) {
-                                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-                               }
-                               *wait = waitval; // WORKAROUND
-                               //#if _MEMORY_BUS_WIDTH == 16
-                               //*wait = wait1 + wait2 + wait3; // OK?
-                               //#else
-                               //*wait = wait1 + wait3; // OK?
-                               //#endif
-                       }
-                       break;
-               }
-               return;
-       }
-
-       __LIKELY_IF(mmio_memory_map_w[mapptr] != NULL) {
-               uint8_t* ptr = mmio_memory_map_w[mapptr];
-               ptr = &(ptr[offset]);
-               #ifdef __BIG_ENDIAN__
-               pair32_t d;
-               d.d = data;
-               d.write_4bytes_le_to(ptr);
-               #else
-               __LIKELY_IF((offset & 3) == 0) { // Aligned
-                       uint32_t* q = (uint32_t*)ptr;
-                       *q = data;
-               } else {
-                       pair32_t d;
-                       d.d = data;
-                       d.write_4bytes_le_to(ptr);
-               }
-               #endif
-       } else if(mmio_devices_map_w[mapptr] != NULL) {
-               DEVICE* dev = mmio_devices_map_w[mapptr];
-               __LIKELY_IF(mmio_devices_base_w[mapptr] == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += mmio_devices_base_w[mapptr];
-               }
-               dev->write_memory_mapped_io32(offset, data);
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = mmio_wait_map_w[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               //#if _MEMORY_BUS_WIDTH == 16
-               //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
-               //      waitval *= 4;
-               //}
-               //#else
-               // 32bit
-               //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
-               //      waitval *= 4;
-               //}
-               //#endif
-               *wait = waitval;
+       __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);
        }
-       return;
 }
 
 void TOWNS_MEMORY::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
 {
-       int waitval;
        uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
        uint32_t offset = addr & memory_map_mask();
-       __LIKELY_IF((dma_memory_map_w[mapptr] == NULL) && (dma_devices_map_w[mapptr] == NULL)) {
-               write_data8w(addr, data, wait);
-               return;
-       }
-       __LIKELY_IF(dma_memory_map_w[mapptr] != NULL) {
-               uint8_t* ptr = dma_memory_map_w[mapptr];
-               ptr[offset] = data;
-       } else if(dma_devices_map_w[mapptr] != NULL) {
-               DEVICE* dev = dma_devices_map_w[mapptr];
-               __LIKELY_IF(dma_devices_base_w[mapptr] == UINT32_MAX) {
-                       dev->write_memory_mapped_io8(addr, data);
-               } else {
-                       offset += dma_devices_base_w[mapptr];
-                       dev->write_memory_mapped_io8(offset, data);
-               }
-       }
+       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) {
-               waitval = dma_wait_map_w[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               *wait = waitval;
+               *wait = 0; // Discard wait value for DMA.
        }
-       return;
 }
 
 void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
@@ -1689,67 +1052,15 @@ 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(offset == memory_map_mask()) {
-               // Beyond via bound
-               pair16_t d;
-               int wait1, wait2;
-               d.w = data;
-               write_dma_data8w(addr    , d.b.l, &wait1);
-               write_dma_data8w(addr + 1, d.b.h, &wait2);
-               __LIKELY_IF(wait != NULL) {
-                       *wait = wait1 + wait2;
-               }
-               return;
-       }
-       __LIKELY_IF((dma_memory_map_w[mapptr] == NULL) && (dma_devices_map_w[mapptr] == NULL)) {
-               // ToDO: BEYOND THE BOUNDARY.
-               write_data16w(addr, data, wait);
-               return;
-       }
-       __LIKELY_IF(dma_memory_map_w[mapptr] != NULL) {
-               uint8_t* ptr = dma_memory_map_w[mapptr];
-               ptr = &(ptr[offset]);
-               #ifdef __BIG_ENDIAN__
-               pair16_t d;
-               d.w = data;
-               d.write_2bytes_le_to(ptr);
-               #else
-               __LIKELY_IF((offset & 1) == 0) { // Aligned
-                       uint16_t* q = (uint16_t*)ptr;
-                       *q = data;
-               } else {
-                       pair16_t d;
-                       d.w = data;
-                       d.write_2bytes_le_to(ptr);
-               }
-               #endif
-       } else if(dma_devices_map_w[mapptr] != NULL) {
-               DEVICE* dev = dma_devices_map_w[mapptr];
-               __LIKELY_IF(dma_devices_base_w[mapptr] == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += dma_devices_base_w[mapptr];
-               }
-               dev->write_memory_mapped_io16(offset, data);
+       __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) {
-               waitval = dma_wait_map_w[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               //#if _MEMORY_BUS_WIDTH == 16
-               //__UNLIKELY_IF((offset & 1) != 0) { // Penalty; maybe not need to.
-               //      waitval *= 2;
-               //}
-               //#else
-               // 32bit
-               //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
-               //      waitval *= 2;
-               //}
-               //#endif
-               *wait = waitval;
+               *wait = 0; // Discard wait value for DMA.
        }
-       return;
 }
 
 
@@ -1758,223 +1069,175 @@ 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(offset > (memory_map_mask() - 3)) {
-               // Beyond via bound
-               pair32_t d;
-               pair16_t w;
-               int wait1, wait2, wait3;
-               d.d = data;
-               switch(offset & 3) {
-               case 1:
-               case 3:
-                       write_dma_data8w(addr    , d.b.l, &wait1);
-                       w.b.l = d.b.h;
-                       w.b.h = d.b.h2;
-                       write_dma_data16w(addr + 1, w.w, &wait2);
-                       write_dma_data8w(addr + 3, d.b.h3, &wait3);
-                       __LIKELY_IF(wait != NULL) {
-                               *wait = wait1; // WORKAROUND
-                               //#if _MEMORY_BUS_WIDTH == 16
-                               //*wait = wait1 + wait2 + wait3; // OK?
-                               //#else
-                               //*wait = wait1 + wait3; // OK?
-                               //#endif
-                       }
-                       break;
-               case 2:
-                       write_dma_data16w(addr    , d.w.l, &wait1);
-                       write_dma_data16w(addr + 2, d.w.h, &wait2);
-                       __LIKELY_IF(wait != NULL) {
-                               *wait = wait1; // WORKAROUND
-                               //#if _MEMORY_BUS_WIDTH == 16
-                               //*wait = wait1 + wait2 + wait3; // OK?
-                               //#else
-                               //*wait = wait1 + wait3; // OK?
-                               //#endif
-                       }
-                       break;
-               default:
-                       __LIKELY_IF(wait != NULL) {
-                               waitval = dma_wait_map_w[mapptr];
-                               __LIKELY_IF(waitval < 0) {
-                                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-                               }
-                               *wait = waitval; // WORKAROUND
-                               //#if _MEMORY_BUS_WIDTH == 16
-                               //*wait = wait1 + wait2 + wait3; // OK?
-                               //#else
-                               //*wait = wait1 + wait3; // OK?
-                               //#endif
-                       }
-                       break;
-               }
-               return;
-       }
-
-       __LIKELY_IF((dma_memory_map_w[mapptr] == NULL) && (dma_devices_map_w[mapptr] == NULL)) {
-               // ToDO: BEYOND THE BOUNDARY.
-               write_data32w(addr, data, wait);
-               return;
-       }
-       __LIKELY_IF(dma_memory_map_w[mapptr] != NULL) {
-               uint8_t* ptr = dma_memory_map_w[mapptr];
-               ptr = &(ptr[offset]);
-               #ifdef __BIG_ENDIAN__
-               pair32_t d;
-               d.d = data;
-               d.write_4bytes_le_to(ptr);
-               #else
-               __LIKELY_IF((offset & 3) == 0) { // Aligned
-                       uint32_t* q = (uint32_t*)ptr;
-                       *q = data;
-               } else {
-                       pair32_t d;
-                       d.d = data;
-                       d.write_4bytes_le_to(ptr);
-               }
-               #endif
-       } else if(dma_devices_map_w[mapptr] != NULL) {
-               DEVICE* dev = dma_devices_map_w[mapptr];
-               __LIKELY_IF(dma_devices_base_w[mapptr] == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += dma_devices_base_w[mapptr];
-               }
-               dev->write_memory_mapped_io32(offset, data);
+       __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) {
-               waitval = dma_wait_map_w[mapptr];
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               //#if _MEMORY_BUS_WIDTH == 16
-               //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
-               //      waitval *= 4;
-               //}
-               //#else
-               // 32bit
-               //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
-               //      waitval *= 4;
-               //}
-               //#endif
-               *wait = waitval;
+               *wait = 0; // Discard wait value for DMA.
        }
-       return;
 }
 
-
-
-uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
+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);
+               }
                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;
                }
-               return ram_pagec[addr & 0x0000ffff];
        }
        // ROMs?
-       if(addr < 0x000ca000) { //SPRITE
-               __LIKELY_IF(d_sprite != NULL) {
-                       return d_sprite->read_memory_mapped_io8(addr);
-               }
-               return 0xff;
-       }
        if(ankcg_enabled) {
-               __LIKELY_IF(d_font != NULL) {
-                       return d_font->read_memory_mapped_io8(addr);
+               if(addr >= 0xca000) {
+                       __LIKELY_IF(d_font != NULL) {
+                               return d_font->read_memory_mapped_io8(addr);
+                       }
                }
        } else {
-               __LIKELY_IF(d_sprite != NULL) {
-                       return d_sprite->read_memory_mapped_io8(addr);
+               if(addr < 0xcb000) {
+                       __LIKELY_IF(d_sprite != NULL) {
+                               return d_sprite->read_memory_mapped_io8w(addr - 0xc8000, wait);
+                       }
                }
        }
        return 0xff;
 }
 
-uint32_t TOWNS_MEMORY::read_memory_mapped_io16(uint32_t addr)
+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);
+               }
                return 0xffff;
        }
        __LIKELY_IF(addr >= 0x000cc000) {
                // RAM: OK?
                pair16_t w;
-               __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
+               __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cffff)) { // I/O
                        w.b.l = read_fmr_ports8(addr);
                        w.b.h = read_fmr_ports8(addr + 1);
                } else {
-                       w.read_2bytes_le_from(&(ram_pagec[addr & 0x0000ffff]));
+                       __LIKELY_IF(extra_ram != NULL) {
+                               w.read_2bytes_le_from(&(extra_ram[addr]));
+                       } else {
+                               w.w = 0xffff;
+                       }
                }
                return w.w;
        }
        // ROMs?
-       if(addr < 0x000ca000) { //SPRITE
-               __LIKELY_IF(d_sprite != NULL) {
-                       return d_sprite->read_memory_mapped_io16(addr);
-               }
-               return 0xffff;
-       }
        if(ankcg_enabled) {
-               __LIKELY_IF(d_font != NULL) {
-                       return d_font->read_memory_mapped_io16(addr);
+               if(addr >= 0xca000) {
+                       __LIKELY_IF(d_font != NULL) {
+                               return d_font->read_memory_mapped_io16(addr);
+                       }
                }
        } else {
-               __LIKELY_IF(d_sprite != NULL) {
-                       return d_sprite->read_memory_mapped_io16(addr);
+               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_io32(uint32_t addr)
+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 >= 0x000d0000) || (addr < 0x000c8000)) {
+       __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) { // I/O
+               __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 {
-                       d.read_4bytes_le_from(&(ram_pagec[addr & 0x0000ffff]));
+                       __LIKELY_IF(extra_ram != NULL) {
+                               d.read_4bytes_le_from(&(extra_ram[addr]));
+                       } else {
+                               d.d = 0xffffffff;
+                       }
                }
                return d.d;
        }
        // ROMs?
-       if(addr < 0x000ca000) { //SPRITE
-               __LIKELY_IF(d_sprite != NULL) {
-                       return d_sprite->read_memory_mapped_io32(addr);
-               }
-               return 0xffffffff;
-       }
        if(ankcg_enabled) {
-               __LIKELY_IF(d_font != NULL) {
-                       return d_font->read_memory_mapped_io32(addr);
+               if(addr >= 0xca000) {
+                       __LIKELY_IF(d_font != NULL) {
+                               return d_font->read_memory_mapped_io32(addr);
+                       }
                }
        } else {
-               __LIKELY_IF(d_sprite != NULL) {
-                       return d_sprite->read_memory_mapped_io32(addr);
+               if(addr < 0xcb000) {
+                       __LIKELY_IF(d_sprite != NULL) {
+                               return d_sprite->read_memory_mapped_io32w(addr - 0xc8000, wait);
+                       }
                }
        }
        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)
 {
        // 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;
+       }
+       __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);
+               }
                return;
        }
        __LIKELY_IF(addr >= 0x000cc000) {
@@ -1983,89 +1246,83 @@ void TOWNS_MEMORY::write_memory_mapped_io8(uint32_t addr, uint32_t data)
                        write_fmr_ports8(addr, data);
                        return;
                }
-               ram_pagec[addr & 0x0000ffff] = data;
-               return;
-       }
-       // ROMs?
-       if(addr < 0x000ca000) { //SPRITE
-               __LIKELY_IF(d_sprite != NULL) {
-                       d_sprite->write_memory_mapped_io8(addr, data);
+               __LIKELY_IF(extra_ram != NULL) {
+                       extra_ram[addr] = data;
                }
                return;
        }
-       if(!(ankcg_enabled)) {
-               __LIKELY_IF(d_sprite != NULL) {
-                       d_sprite->write_memory_mapped_io8(addr, data);
-               }
-       }
+       // ROMs?
        return;
 }
 
-void TOWNS_MEMORY::write_memory_mapped_io16(uint32_t addr, uint32_t data)
+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)
-       __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
+       __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);
+               }
                return;
        }
        __LIKELY_IF(addr >= 0x000cc000) {
                // RAM: OK?
                pair16_t w;
                w.w = data;
-               __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
+               __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cffff)) { // I/O
                        write_fmr_ports8(addr    , w.b.l);
                        write_fmr_ports8(addr + 1, w.b.h);
                        return;
                }
-               w.write_2bytes_le_to(&(ram_pagec[addr & 0x0000ffff]));
-               return;
-       }
-       // ROMs?
-       if(addr < 0x000ca000) { //SPRITE
-               __LIKELY_IF(d_sprite != NULL) {
-                       d_sprite->write_memory_mapped_io16(addr, data);
+               __LIKELY_IF(extra_ram != NULL) {
+                       w.write_2bytes_le_to(&(extra_ram[addr]));
                }
                return;
        }
-       if(!(ankcg_enabled)) {
-               __LIKELY_IF(d_sprite != NULL) {
-                       d_sprite->write_memory_mapped_io16(addr, data);
-               }
-       }
+       // ROMs?
        return;
 }
 
-void TOWNS_MEMORY::write_memory_mapped_io32(uint32_t addr, uint32_t data)
+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);
+               }
+               return;
+       }
        __LIKELY_IF(addr >= 0x000cc000) {
                // RAM: OK?
                pair32_t d;
                d.d = data;
-               __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
+               __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;
                }
-               d.write_4bytes_le_to(&(ram_pagec[addr & 0x0000ffff]));
-               return;
-       }
-       // ROMs?
-       if(addr < 0x000ca000) { //SPRITE
-               __LIKELY_IF(d_sprite != NULL) {
-                       d_sprite->write_memory_mapped_io32(addr, data);
+               __LIKELY_IF(extra_ram != NULL) {
+                       d.write_4bytes_le_to(&(extra_ram[addr]));
                }
                return;
        }
-       if(!(ankcg_enabled)) {
-               __LIKELY_IF(d_sprite != NULL) {
-                       d_sprite->write_memory_mapped_io32(addr, data);
-               }
-       }
+       // ROMs?
        return;
 }
 
@@ -2161,7 +1418,7 @@ void TOWNS_MEMORY::set_intr_line(bool line, bool pending, uint32_t bit)
 
 // ToDo: DMA
 
-#define STATE_VERSION  6
+#define STATE_VERSION  8
 
 bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
 {
@@ -2192,8 +1449,6 @@ bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
        state_fio->StateValue(extra_nmi_mask);
        state_fio->StateValue(nmi_mask);
 
-       state_fio->StateArray(ram_page0,  sizeof(ram_page0), 1);
-       state_fio->StateArray(ram_pagec,  sizeof(ram_pagec), 1);
 
        state_fio->StateValue(select_d0_rom);
        state_fio->StateValue(select_d0_dict);
@@ -2215,19 +1470,17 @@ bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
                }
                length_tmp = length_tmp & 0x3ff00000;
                extram_size = length_tmp;
-               if(length_tmp > 0) {
-                       extra_ram = (uint8_t*)malloc(length_tmp);
-                       __LIKELY_IF(extra_ram != NULL) {
-                               set_region_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
-                               memset(extra_ram, 0x00, extram_size);
-                       }
+               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);
                }
 
                if(extra_ram == NULL) {
                        extram_size = 0;
                        return false;
                } else {
-                       state_fio->Fread(extra_ram, extram_size, 1);
+                       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);
@@ -2240,7 +1493,7 @@ bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
                        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);
                }
        }