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 118beb3..5b957cd 100644 (file)
@@ -57,18 +57,11 @@ void TOWNS_MEMORY::initialize()
 
        reset_wait_values();
 
-       set_region_memory_rw(0x00000000, 0x000bffff, ram_page0, 0);
-       set_region_memory_rw(0x000c0000, 0x000fffff, ram_pagec, 0);
-       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, 0);
-                               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,41 +123,56 @@ 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, 0x000c0000 - 0x000c0000);
-                       set_region_memory_rw(0x000e0000, 0x000effff, ram_pagec, 0x000e0000 - 0x000c0000);
+                       __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, 0x000d0000 - 0x000c0000);
+                       __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, 0x000f0000 - 0x000c0000);
-       __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, 0x000f8000 - 0x000c0000);
+                       __LIKELY_IF(extra_ram != NULL) {
+                               set_region_memory_rw(0x000f8000, 0x000fffff, extra_ram, 0x000f8000);
+                       } else {
+                               unset_range_rw(0x000f8000, 0x000fffff);
+                       }
                }
-       }
+       //}
        select_d0_rom = sysrombank;
 }
 
@@ -187,7 +195,7 @@ void TOWNS_MEMORY::set_memory_devices_map_values(uint32_t start, uint32_t end, m
                        dataptr[mapptr].mem_ptr = NULL;
                        dataptr[mapptr].device_ptr = device;
                } else {
-                       dataptr[mapptr].mem_ptr = &(baseptr[realoffset]);
+                       dataptr[mapptr].mem_ptr = baseptr;
                        dataptr[mapptr].device_ptr = NULL;
                }
                if(base_offset == UINT32_MAX) {
@@ -414,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:
+       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_LOW);
-               }
-               break;
-       case 0xff97:
-               __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;
@@ -578,6 +565,7 @@ 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;
@@ -606,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;
@@ -660,33 +664,27 @@ uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
 {
 //     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);
+               return read_fmr_ports8((addr & 0xffff) | 0x000c0000);
        }
        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);
                        }
@@ -695,39 +693,33 @@ void TOWNS_MEMORY::write_fmr_ports8(uint32_t addr, uint32_t data)
                        break;
                }
        }
-       switch(addr & 0xffff) {
-       case 0xff94:
+       switch(addr) {
+       case 0xcff94:
+       case 0xcff95:
                __LIKELY_IF(d_font != NULL) {
-                       d_font->write_signal(SIG_TOWNS_FONT_KANJI_HIGH, data, 0xff);
-               }
-               break;
-       case 0xff95:
-               __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;
        }
 }
@@ -919,7 +911,7 @@ 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);
@@ -928,397 +920,95 @@ void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
 
 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(membus_read_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = membus_read_map[mapptr].mem_ptr;
-               val = ptr[offset];
-       } else if(membus_read_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = membus_read_map[mapptr].device_ptr;
-               __LIKELY_IF(membus_read_map[mapptr].base_offset == UINT32_MAX) {
-                       val = dev->read_memory_mapped_io8(addr);
-               } else {
-                       offset += membus_read_map[mapptr].base_offset;
-                       val = dev->read_memory_mapped_io8(offset);
-               }
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = membus_read_map[mapptr].waitval;
-               __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(membus_read_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = membus_read_map[mapptr].mem_ptr;
-               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(membus_read_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = membus_read_map[mapptr].device_ptr;
-               __LIKELY_IF(membus_read_map[mapptr].base_offset == UINT32_MAX) {
-                       val = dev->read_memory_mapped_io16(addr);
-               } else {
-                       offset += membus_read_map[mapptr].base_offset;
-                       val = dev->read_memory_mapped_io16(offset);
-               }
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = membus_read_map[mapptr].waitval;
-               __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 = membus_read_map[mapptr].waitval;
-                               __LIKELY_IF(waitval < 0) {
-                                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-                               }
-                               *wait = waitval;
-                               //*wait = wait1 + wait2;
-                       }
-               }
-               return d.d;
-       }
-       __LIKELY_IF(membus_read_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = membus_read_map[mapptr].mem_ptr;
-               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(membus_read_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = membus_read_map[mapptr].device_ptr;
-               __LIKELY_IF(membus_read_map[mapptr].base_offset == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += membus_read_map[mapptr].base_offset;
-               }
-               val = dev->read_memory_mapped_io32(offset);
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = membus_read_map[mapptr].waitval;
-               __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)
 {
-       #if 1
-       int dummywait;
-       uint8_t val = read_data8w(addr, &dummywait);
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       return val;
-       #else
-       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_read_map[mapptr].mem_ptr == NULL) && (dma_read_map[mapptr].device_ptr == NULL)) {
-               return read_data8w(addr, wait);
-       }
-
-       __LIKELY_IF(dma_read_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = dma_read_map[mapptr].mem_ptr;
-               val = ptr[offset];
-       } else if(dma_read_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = dma_read_map[mapptr].device_ptr;
-               __LIKELY_IF(dma_read_map[mapptr].base_offset == UINT32_MAX) {
-                       val = dev->read_memory_mapped_io8(addr);
-               } else {
-                       offset += dma_read_map[mapptr].base_offset;
-                       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_read_map[mapptr].waitval;
-               __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;
-       #endif
 }
 
 uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
 {
-       #if 1
-       int dummywait;
-       uint16_t val = read_data16w(addr, &dummywait);
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       return val;
-       #else
-       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_read_map[mapptr].mem_ptr == NULL) && (dma_read_map[mapptr].device_ptr == NULL)) {
-               return read_data16w(addr, wait);
-       }
-       __LIKELY_IF(dma_read_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = dma_read_map[mapptr].mem_ptr;
-               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_read_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = dma_read_map[mapptr].device_ptr;
-               __LIKELY_IF(dma_read_map[mapptr].base_offset == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += dma_read_map[mapptr].base_offset;
-               }
-               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_read_map[mapptr].waitval;
-               __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;
-       #endif
+
 }
 
 uint32_t TOWNS_MEMORY::read_dma_data32w(uint32_t addr, int* wait)
 {
-       #if 1
-       int dummywait;
-       uint32_t val = read_data32w(addr, &dummywait);
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       return val;
-       #else
-       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_read_map[mapptr].waitval;
-                               __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_read_map[mapptr].mem_ptr == NULL) && (dma_read_map[mapptr].device_ptr == NULL)) {
-               return read_data32w(addr, wait);
-       }
-       __LIKELY_IF(dma_read_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = dma_read_map[mapptr].mem_ptr;
-               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_read_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = dma_read_map[mapptr].device_ptr;
-               __LIKELY_IF(dma_read_map[mapptr].base_offset == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += membus_read_map[mapptr].base_offset;
-               }
-               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_read_map[mapptr].waitval;
-               __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;
-       #endif
 }
 
 
 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(membus_write_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = membus_write_map[mapptr].mem_ptr;
-               ptr[offset] = data;
-       } else if(membus_write_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = membus_write_map[mapptr].device_ptr;
-               __LIKELY_IF(membus_write_map[mapptr].base_offset == UINT32_MAX) {
-                       dev->write_memory_mapped_io8(addr, data);
-               } else {
-                       offset += membus_write_map[mapptr].base_offset;
-                       dev->write_memory_mapped_io8(offset, data);
-               }
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = membus_write_map[mapptr].waitval;
-               __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);
 }
 
 
@@ -1326,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(membus_write_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = membus_write_map[mapptr].mem_ptr;
-               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(membus_write_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = membus_write_map[mapptr].device_ptr;
-               __LIKELY_IF(membus_write_map[mapptr].base_offset == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += membus_write_map[mapptr].base_offset;
-               }
-               dev->write_memory_mapped_io16(offset, data);
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = membus_write_map[mapptr].waitval;
-               __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;
 }
 
 
@@ -1390,452 +1028,216 @@ 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 = membus_write_map[mapptr].waitval;
-                               __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(membus_write_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = membus_write_map[mapptr].mem_ptr;
-               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(membus_write_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = membus_write_map[mapptr].device_ptr;
-               __LIKELY_IF(membus_write_map[mapptr].base_offset == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += membus_write_map[mapptr].base_offset;
-               }
-               dev->write_memory_mapped_io32(offset, data);
-       }
-       __LIKELY_IF(wait != NULL) {
-               waitval = membus_write_map[mapptr].waitval;
-               __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)
 {
-       #if 1
-       int dummywait;
-       write_data8w(addr, data, &dummywait);
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       #else
-       int waitval;
        uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
        uint32_t offset = addr & memory_map_mask();
-       __LIKELY_IF((dma_write_map[mapptr].mem_ptr == NULL) && (dma_write_map[mapptr].device_ptr == NULL)) {
-               write_data8w(addr, data, wait);
-               return;
-       }
-       __LIKELY_IF(dma_write_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = dma_write_map[mapptr].mem_ptr;
-               ptr[offset] = data;
-       } else if(dma_write_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = dma_write_map[mapptr].device_ptr;
-               __LIKELY_IF(dma_write_map[mapptr].base_offset == UINT32_MAX) {
-                       dev->write_memory_mapped_io8(addr, data);
-               } else {
-                       offset += dma_write_map[mapptr].base_offset;
-                       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_write_map[mapptr].waitval;
-               __LIKELY_IF(waitval < 0) {
-                       waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
-               }
-               *wait = waitval;
+               *wait = 0; // Discard wait value for DMA.
        }
-       return;
-       #endif
 }
 
 void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
 {
-       #if 1
-       int dummywait;
-       write_data16w(addr, data, &dummywait);
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       #else
        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_write_map[mapptr].mem_ptr == NULL) && (dma_write_map[mapptr].device_ptr == NULL)) {
-               // ToDO: BEYOND THE BOUNDARY.
-               write_data16w(addr, data, wait);
-               return;
-       }
-       __LIKELY_IF(dma_write_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = dma_write_map[mapptr].mem_ptr;
-               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_write_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = dma_write_map[mapptr].device_ptr;
-               __LIKELY_IF(dma_write_map[mapptr].base_offset == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += dma_write_map[mapptr].base_offset;
-               }
-               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_write_map[mapptr].waitval;
-               __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;
-       #endif
 }
 
 
 void TOWNS_MEMORY::write_dma_data32w(uint32_t addr, uint32_t data, int* wait)
 {
-       #if 1
-       int dummywait;
-       write_data32w(addr, data, &dummywait);
-       __LIKELY_IF(wait != NULL) {
-               *wait = 0;
-       }
-       #else
        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_write_map[mapptr].waitval;
-                               __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_write_map[mapptr].mem_ptr == NULL) && (dma_write_map[mapptr].device_ptr == NULL)) {
-               // ToDO: BEYOND THE BOUNDARY.
-               write_data32w(addr, data, wait);
-               return;
-       }
-       __LIKELY_IF(dma_write_map[mapptr].mem_ptr != NULL) {
-               uint8_t* ptr = dma_write_map[mapptr].mem_ptr;
-               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_write_map[mapptr].device_ptr != NULL) {
-               DEVICE* dev = dma_write_map[mapptr].device_ptr;
-               __LIKELY_IF(dma_write_map[mapptr].base_offset == UINT32_MAX) {
-                       offset = addr;
-               } else {
-                       offset += dma_write_map[mapptr].base_offset;
-               }
-               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_write_map[mapptr].waitval;
-               __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;
-       #endif
 }
 
-
-
-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) {
@@ -1844,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;
 }
 
@@ -2022,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)
 {
@@ -2053,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);
@@ -2076,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, 0);
-                               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);
@@ -2101,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);
                }
        }