OSDN Git Service

[VM][FMTOWNS][RF5C68] MEMORY accessing must be 0000h - 0FFFh.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / towns_memory.cpp
1 /*
2         FUJITSU FM Towns Emulator 'eFMTowns'
3
4         Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2017.01.01 -
6
7         [memory]
8 */
9
10 #include "../../fileio.h"
11 #include "./towns_memory.h"
12 #include "./dmac.h"
13 #include "./vram.h"
14 #include "./planevram.h"
15 #include "./sprite.h"
16 #include "./fontroms.h"
17 #include "./serialrom.h"
18 #include "./crtc.h"
19 #include "./timer.h"
20
21 #include "../i386_np21.h"
22 //#include "../i386.h"
23
24 #include <math.h>
25
26 namespace FMTOWNS {
27
28 void TOWNS_MEMORY::initialize()
29 {
30         if(initialized) return;
31         //MEMORY::initialize();
32
33         update_machine_features();
34         extra_nmi_mask = true;
35         extra_nmi_val = false;
36         poff_status = false;
37         reset_happened = false;
38
39         vram_wait_val = 6;
40         mem_wait_val = 3;
41 //      if((cpu_id == 0x01) || (cpu_id == 0x03)) {
42 //              wait_register_older = vram_wait_val;
43 //              wait_register_vram = vram_wait_val;
44 //              wait_register_ram = mem_wait_val;
45 //      } else {
46                 wait_register_older  = 3;
47                 wait_register_vram = 0x06;
48                 wait_register_ram  = 0x03;
49 //      }
50         //cpu_clock_val = 16 * 1000 * 1000;
51         //cpu_clock_val = get_cpu_clocks(d_cpu);
52         set_cpu_clock_by_wait();
53         extram_size = extram_size & 0x3ff00000;
54         set_extra_ram_size(extram_size >> 20); // Check extra ram size.
55
56         unset_range_rw(0x00000000, 0xffffffff);
57
58         reset_wait_values();
59
60         __UNLIKELY_IF(extra_ram == NULL) {
61                 extra_ram = (uint8_t*)malloc(extram_size + 0x00100000);
62                 __LIKELY_IF(extra_ram != NULL) {
63                         set_region_memory_rw(0x00000000, (extram_size + 0x00100000) - 1, extra_ram, 0);
64                         memset(extra_ram, 0x00, extram_size + 0x00100000);
65                 }
66         }
67
68
69         initialized = true;
70
71         // Lower 100000h
72
73         config_page0c_0e(true, false, true);
74         config_page0f(true, true);
75
76         set_region_device_rw(0x80000000, 0x8007ffff, d_vram, NOT_NEED_TO_OFFSET);
77         set_region_device_rw(0x80100000, 0x8017ffff, d_vram, NOT_NEED_TO_OFFSET);
78
79         set_region_device_rw(0x81000000, 0x8101ffff, d_sprite, NOT_NEED_TO_OFFSET);
80         set_region_device_rw(0xc0000000, 0xc0ffffff, d_iccard[0], 0);
81         set_region_device_rw(0xc1000000, 0xc1ffffff, d_iccard[1], 0);
82 //      set_wait_rw(0x00000000, 0xffffffff,  vram_wait_val);
83
84         set_region_device_r (0xc2000000, 0xc207ffff, d_msdos, 0);
85         set_region_device_r (0xc2080000, 0xc20fffff, d_dictionary, NOT_NEED_TO_OFFSET);
86         set_region_device_r (0xc2100000, 0xc213ffff, d_font, NOT_NEED_TO_OFFSET);
87         // REAL IS C2140000h - C2141FFFh, but grain may be 8000h bytes.
88         set_region_device_rw(0xc2140000, 0xc2140000 + memory_map_grain() - 1, d_dictionary, NOT_NEED_TO_OFFSET);
89         if(d_font_20pix != NULL) {
90                 set_region_device_r (0xc2180000, 0xc21fffff, d_font_20pix, 0);
91         }
92         // REAL IS C2200000h - C2200FFFh, but grain may be 8000h bytes.
93         set_region_device_rw(0xc2200000, 0xc2200000 + memory_map_grain() - 1, d_pcm, 0);
94         set_region_device_r (0xfffc0000, 0xffffffff, d_sysrom, 0);
95         // Another devices are blank
96
97         // load rom image
98         // ToDo: More smart.
99         vram_size = 0x80000; // OK?
100 }
101
102 void TOWNS_MEMORY::reset_wait_values()
103 {
104         set_mmio_wait_rw(0x00000000, 0x7fffffff, WAITVAL_RAM);
105         set_dma_wait_rw (0x00000000, 0x7fffffff, WAITVAL_RAM);
106         set_mmio_wait_rw(0x80000000, 0x803fffff, WAITVAL_VRAM); // Default Value
107         set_dma_wait_rw (0x80000000, 0x803fffff, WAITVAL_VRAM); // Default Value
108         set_mmio_wait_rw(0x80400000, 0xffffffff, WAITVAL_RAM);
109         set_dma_wait_rw (0x80400000, 0xffffffff, WAITVAL_RAM);
110 }
111
112 void TOWNS_MEMORY::config_page0c_0e(const bool vrambank, const bool dictbank, const bool force)
113 {
114         const bool is_vram_bak = dma_is_vram;
115         const bool is_dict_bak = select_d0_dict;
116         __UNLIKELY_IF((vrambank != is_vram_bak) || (force)){
117                 if(vrambank) { // VRAM AND around TEXT
118                         set_region_device_rw(0x000c0000, 0x000c7fff, d_planevram, NOT_NEED_TO_OFFSET);
119                         set_region_device_rw(0x000c8000, 0x000cffff, this, NOT_NEED_TO_OFFSET);
120
121                         unset_range_rw(0x000e0000, 0x000effff); // OK?
122
123                         set_mmio_wait_rw(0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
124                         set_dma_wait_rw (0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
125                 } else {
126                         __LIKELY_IF(extra_ram != NULL) {
127                                 set_region_memory_rw(0x000c0000, 0x000cffff, extra_ram, 0x000c0000);
128                                 set_region_memory_rw(0x000e0000, 0x000effff, extra_ram, 0x000e0000);
129                         } else {
130                                 unset_range_rw(0x000c0000, 0x000cffff);
131                                 unset_range_rw(0x000e0000, 0x000effff);
132                         }
133                         set_mmio_wait_rw(0x000c0000, 0x000cffff, WAITVAL_RAM); // Default Value
134                         set_dma_wait_rw (0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
135                 }
136         }
137         __UNLIKELY_IF((vrambank != is_vram_bak) || (dictbank != is_dict_bak) || (force)){
138                 if(vrambank) { // VRAM AND around TEXT
139                         if(dictbank) {
140                                 set_region_device_r(0x000d0000, 0x000d7fff, d_dictionary, NOT_NEED_TO_OFFSET);
141                                 unset_range_w(0x000d0000, 0x000d7fff);
142                                 // REAL IS 0000D8000h - 000D9FFFh, but grain may be 8000h bytes.
143                                 set_region_device_rw(0x000d8000, 0x000d8000 + memory_map_grain() - 1, d_dictionary, NOT_NEED_TO_OFFSET);
144                         } else {
145                                 unset_range_rw(0x000d0000, 0x000dffff);
146                         }
147                 } else {
148                         __LIKELY_IF(extra_ram != NULL) {
149                                 set_region_memory_rw(0x000d0000, 0x000dffff, extra_ram, 0x000d0000);
150                         } else {
151                                 unset_range_rw(0x000d0000, 0x000dffff);
152                         }
153                 }
154         }
155         dma_is_vram = vrambank;
156         select_d0_dict = dictbank;
157 }
158 void TOWNS_MEMORY::config_page0f(const bool sysrombank, const bool force)
159 {
160         bool sysrom_bak = select_d0_rom;
161         //__LIKELY_IF(extra_ram != NULL) {
162         //      set_region_memory_rw(0x000f0000, 0x000f7fff, extra_ram, 0x000f0000);
163         //}
164         __UNLIKELY_IF((sysrombank != sysrom_bak) || (force)) {
165                 if(sysrombank) {
166                         unset_range_w(0x000f8000, 0x000fffff);
167                         set_region_device_r (0x000f8000, 0x000fffff, d_sysrom, 0x38000);
168                 } else {
169                         __LIKELY_IF(extra_ram != NULL) {
170                                 set_region_memory_rw(0x000f8000, 0x000fffff, extra_ram, 0x000f8000);
171                         } else {
172                                 unset_range_rw(0x000f8000, 0x000fffff);
173                         }
174                 }
175         }
176         select_d0_rom = sysrombank;
177 }
178
179 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)
180 {
181         uint64_t _start = (uint64_t)start;
182         uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
183         __UNLIKELY_IF(dataptr == NULL) return;
184
185         _start &= ~(memory_map_mask());
186         _end &= ~(memory_map_mask());
187
188         uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
189         const uint64_t _incval = memory_map_grain();
190         uint32_t realoffset = (base_offset == UINT32_MAX) ? 0 : base_offset;
191
192         for(uint64_t addr = _start; addr < _end; addr += _incval) {
193                 __UNLIKELY_IF(mapptr >= memory_map_size()) break; // Safety
194                 if(baseptr == NULL) {
195                         dataptr[mapptr].mem_ptr = NULL;
196                         dataptr[mapptr].device_ptr = device;
197                 } else {
198                         dataptr[mapptr].mem_ptr = baseptr;
199                         dataptr[mapptr].device_ptr = NULL;
200                 }
201                 if(base_offset == UINT32_MAX) {
202                         dataptr[mapptr].base_offset = UINT32_MAX;
203                 } else {
204                         dataptr[mapptr].base_offset = realoffset;
205                 }
206                 realoffset += _incval;
207                 mapptr++;
208         }
209 }
210
211 void TOWNS_MEMORY::set_memory_devices_map_wait(uint32_t start, uint32_t end, memory_device_map_t* dataptr, int wait)
212 {
213         uint64_t _start = (uint64_t)start;
214         uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
215         __UNLIKELY_IF(dataptr == NULL) return;
216
217         _start &= ~(memory_map_mask());
218         _end &= ~(memory_map_mask());
219
220         uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
221         const uint64_t _incval = memory_map_grain();
222
223         for(uint64_t addr = _start; addr < _end; addr += _incval) {
224                 __UNLIKELY_IF(mapptr >= memory_map_size()) break; // Safety
225                 dataptr[mapptr].waitval = wait;
226                 mapptr++;
227         }
228 }
229
230 void TOWNS_MEMORY::unset_memory_devices_map(uint32_t start, uint32_t end, memory_device_map_t* dataptr, int wait)
231 {
232         uint64_t _start = (uint64_t)start;
233         uint64_t _end =   (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
234         __UNLIKELY_IF(dataptr == NULL) return;
235
236         _start &= ~(memory_map_mask());
237         _end &= ~(memory_map_mask());
238
239         uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
240         const uint64_t _incval = memory_map_grain();
241         for(uint64_t addr = _start; addr < _end; addr += _incval) {
242                 __UNLIKELY_IF(mapptr >= memory_map_size()) break; // Safety
243                 dataptr[mapptr].mem_ptr = NULL;
244                 dataptr[mapptr].device_ptr = NULL;
245                 dataptr[mapptr].waitval = wait;
246                 dataptr[mapptr].base_offset = UINT32_MAX;
247                 mapptr++;
248         }
249
250 }
251
252 void TOWNS_MEMORY::set_mmio_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
253 {
254         set_memory_devices_map_values(start, end, &(membus_read_map[0]), baseptr, NULL, base_offset);
255 }
256
257 void TOWNS_MEMORY::set_mmio_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
258 {
259         set_memory_devices_map_values(start, end, &(membus_write_map[0]), baseptr, NULL, base_offset);
260 }
261
262 void  __FASTCALL TOWNS_MEMORY::set_mmio_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
263 {
264         set_memory_devices_map_values(start, end, &(membus_read_map[0]), NULL, ptr, baseaddress);
265 }
266
267 void  __FASTCALL TOWNS_MEMORY::set_mmio_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
268 {
269         set_memory_devices_map_values(start, end, &(membus_write_map[0]), NULL, ptr, baseaddress);
270 }
271
272 void  __FASTCALL TOWNS_MEMORY::set_mmio_wait_r(uint32_t start, uint32_t end, int wait)
273 {
274         set_memory_devices_map_wait(start, end, &(membus_read_map[0]), wait);
275 }
276
277 void  __FASTCALL TOWNS_MEMORY::set_mmio_wait_w(uint32_t start, uint32_t end, int wait)
278 {
279         set_memory_devices_map_wait(start, end, &(membus_write_map[0]), wait);
280 }
281
282 void TOWNS_MEMORY::unset_mmio_r(uint32_t start, uint32_t end, int wait)
283 {
284         unset_memory_devices_map(start, end, &(membus_read_map[0]), wait);
285 }
286
287 void TOWNS_MEMORY::unset_mmio_w(uint32_t start, uint32_t end, int wait)
288 {
289         unset_memory_devices_map(start, end, &(membus_write_map[0]), wait);
290 }
291
292 void TOWNS_MEMORY::unset_dma_r(uint32_t start, uint32_t end, int wait)
293 {
294         unset_memory_devices_map(start, end, &(dma_read_map[0]), wait);
295 }
296
297 void TOWNS_MEMORY::unset_dma_w(uint32_t start, uint32_t end, int wait)
298 {
299         unset_memory_devices_map(start, end, &(dma_write_map[0]), wait);
300 }
301
302 void TOWNS_MEMORY::set_dma_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
303 {
304         set_memory_devices_map_values(start, end, &(dma_read_map[0]), baseptr, NULL, base_offset);
305 }
306
307 void TOWNS_MEMORY::set_dma_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
308 {
309         set_memory_devices_map_values(start, end, &(dma_write_map[0]), baseptr, NULL, base_offset);
310 }
311
312 void  __FASTCALL TOWNS_MEMORY::set_dma_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
313 {
314         set_memory_devices_map_values(start, end, &(dma_read_map[0]), NULL, ptr, baseaddress);
315 }
316
317 void  __FASTCALL TOWNS_MEMORY::set_dma_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
318 {
319         set_memory_devices_map_values(start, end, &(dma_write_map[0]), NULL, ptr, baseaddress);
320 }
321
322 void  __FASTCALL TOWNS_MEMORY::set_dma_wait_r(uint32_t start, uint32_t end, int wait)
323 {
324         set_memory_devices_map_wait(start, end, &(dma_read_map[0]), wait);
325 }
326
327 void  __FASTCALL TOWNS_MEMORY::set_dma_wait_w(uint32_t start, uint32_t end, int wait)
328 {
329         set_memory_devices_map_wait(start, end, &(dma_write_map[0]), wait);
330 }
331
332
333 bool TOWNS_MEMORY::set_cpu_clock_by_wait()
334 {
335         uint32_t cpu_bak = cpu_clock_val;
336         cpu_clock_val = (is_faster_wait()) ?
337                 get_cpu_clocks(d_cpu) : (16 * 1000 * 1000);
338         return ((cpu_clock_val != cpu_bak) ? true : false);
339 }
340 void TOWNS_MEMORY::set_wait_values()
341 {
342         uint32_t waitfactor = 0;
343         if(cpu_clock_val < get_cpu_clocks(d_cpu)) {
344                 waitfactor = (uint32_t)(((double)get_cpu_clocks(d_cpu) / (double)cpu_clock_val) * 65536.0);
345         }
346         d_cpu->write_signal(SIG_CPU_WAIT_FACTOR, waitfactor, 0xffffffff);
347 }
348
349 void TOWNS_MEMORY::release()
350 {
351 //      if(rd_table != NULL) free(rd_table);
352 //      if(rd_dummy != NULL) free(rd_dummy);
353 //      if(wr_table != NULL) free(wr_table);
354 //      if(wr_dummy != NULL) free(wr_dummy);
355
356         if(extra_ram != NULL) {
357                 free(extra_ram);
358                 extra_ram = NULL;
359         }
360
361 }
362 void TOWNS_MEMORY::reset()
363 {
364         // reset memory
365         // ToDo
366         update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
367         is_compatible = true;
368         reset_happened = false;
369
370         nmi_vector_protect = false;
371         ankcg_enabled = false;
372         nmi_mask = false;
373         //config_page0c_0e(false, false, true); // VRAM, DICT, FORCE
374         reset_wait_values();
375         config_page0c_0e(false, false, true); // VRAM, DICT, FORCE
376         config_page0f(true,  true); // SYSROM, FORCE
377
378
379         set_cpu_clock_by_wait();
380         set_wait_values();
381 #if 1
382         __LIKELY_IF(d_cpu != NULL) {
383                 d_cpu->set_address_mask(0xffffffff);
384         }
385         if(d_dmac != NULL) {
386                 uint8_t wrap_val = 0xff; // WRAP ON
387                 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
388         }
389 #endif
390 }
391
392 void TOWNS_MEMORY::update_machine_features()
393 {
394         // 0024h: MISC3
395         reg_misc3 = 0xff;
396         if(machine_id >= 0x0b00) { // After MA/MX/ME
397                 reg_misc3 &= ~0x04; // DMACMD
398         }
399         if(machine_id >= 0x0700) { // After HR/HG
400                 reg_misc3 &= ~0x08; // POFFEN
401         }
402         if(machine_id >= 0x0700) { // After HR/HG
403                 reg_misc3 &= ~0x10; // Free run counter
404         }
405         if(machine_id >= 0x0700) { // After HR/HG
406                 reg_misc3 &= ~0x20; // CRTPOWOFF (0022h)
407         }
408         if(machine_id >= 0x0700) { // After HR/HG
409                 reg_misc3 &= ~0x40; // RCREN
410         }
411         if(machine_id >= 0x0700) { // After HR/HG
412                 reg_misc3 &= ~0x80; // ENPOFF
413         }
414         // 0025h: NMICNT
415         if(machine_id >= 0x0500) { // After CX
416                 reg_misc4 = 0x7f;
417         } else {
418                 reg_misc4 = 0xff;
419         }
420 }
421
422 uint8_t TOWNS_MEMORY::read_fmr_ports8(uint32_t addr)
423 {
424         uint8_t val = 0xff;
425         __UNLIKELY_IF((addr < 0xcff80) || (addr > 0xcffbb)) {
426                 return val;
427         }
428         __LIKELY_IF(addr < 0xcff88) {
429                 __LIKELY_IF(d_planevram != NULL) {
430                         val = d_planevram->read_memory_mapped_io8(addr & 0xffff);
431                 }
432                 return val;
433         }
434         if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
435                 switch(addr) {
436                 case 0xcff88:
437                         __LIKELY_IF(d_crtc != NULL) {
438                                 val = d_crtc->read_signal(SIG_TOWNS_CRTC_MMIO_CFF82H);
439                         }
440                         return val;
441                         break;
442                 case 0xcff99:
443                         return (ankcg_enabled) ? 0x01 : 0x00;
444                         break;
445                 case 0xcff9c:
446                 case 0xcff9d:
447                 case 0xcff9e:
448                         __LIKELY_IF(d_font != NULL) {
449                                 val = d_font->read_io8(addr & 0xffff);
450                         }
451                         return val;
452                         break;
453                 default:
454                         break;
455                 }
456         }
457         switch(addr) {
458         case 0xcff94:
459         case 0xcff95:
460         case 0xcff96:
461         case 0xcff97:
462                 __LIKELY_IF(d_font != NULL) {
463                         val = d_font->read_io8(addr & 0xffff);
464                 }
465                 break;
466         case 0xcff98:
467                 __LIKELY_IF(d_timer != NULL) {
468                         d_timer->write_signal(SIG_TIMER_BEEP_ON, 1, 1);
469                 }
470                 break;
471         case 0xcff99:
472                 __LIKELY_IF(d_planevram != NULL) {
473                         val = d_planevram->read_memory_mapped_io8(addr);
474                 }
475                 break;
476         default:
477                 break;
478         }
479         return val;
480 }
481 uint8_t TOWNS_MEMORY::read_sys_ports8(uint32_t addr)
482 {
483     uint8_t val;
484         val = 0xff;
485         switch(addr & 0xffff) {
486         case 0x0020: // Software reset ETC.
487                 // reset cause register
488                 val = ((software_reset) ? 1 : 0) | ((reset_happened) ? 2 : 0);
489                 reset_happened = false;
490                 software_reset = false;
491                 __UNLIKELY_IF(d_cpu != NULL) {
492                         d_cpu->set_shutdown_flag(0);
493                 }
494                 if((machine_id >= 0x0300) && ((machine_id & 0xff00) != 0x0400)) { // After UX
495                         val = val | ((poff_status) ? 0x04 : 0x00);
496                 }
497                 break;
498         case 0x0022:
499 //              val.b.l = 0xff;
500 //              if(d_dmac != NULL) {
501 //                      val = d_dmac->read_signal(SIG_TOWNS_DMAC_ADDR_REG);
502 //              }
503                 break;
504                 // 0024, 0025 : MISC3 + MISC4
505         case 0x0024:
506                 val = reg_misc3;
507                 break;
508         case 0x0025:
509                 val = reg_misc4;
510                 break;
511         case 0x0028:
512                 // NMI MASK
513                 if(machine_id >= 0x0500) { // After CX
514                         val = (nmi_mask) ? 0x01 : 0x00;
515                 }
516                 break;
517         case 0x0030:
518                 // 20210227 K.O
519                 // From FMTowns::MachineID()  of TSUGARU,
520                 // git 83d4ec2309ac9fcbb8c01f26061ff0d49c5321e4.
521 //              if((config.dipswitch & TOWNS_DIPSW_PRETEND_I386) != 0) {
522 //                      val = ((machine_id & 0xf8) | 1);
523 //              } else {
524                         val = ((machine_id & 0xf8) | (cpu_id & 7));
525 //              }
526                 break;
527         case 0x0031:
528                 val = ((machine_id >> 8) & 0xff);
529                 break;
530         case 0x0032:
531                 {
532                         //bool __cs = (d_serialrom->read_signal(SIG_SERIALROM_CS) == 0);
533                         bool __clk = (d_serialrom->read_signal(SIG_SERIALROM_CLK) != 0);
534                         bool __reset = (d_serialrom->read_signal(SIG_SERIALROM_RESET) != 0);
535                         bool __dat = (d_serialrom->read_signal(SIG_SERIALROM_DATA) != 0);
536                         val = ((__reset) ? 0x80 : 0x00) | ((__clk) ? 0x40 : 0x00) | /*0x3e |*/ ((__dat) ? 0x01 : 0x00);
537                 }
538                 break;
539         case 0x00c0: // Cache
540                 val = 0x00;
541                 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
542                         // ToDo: Implement around cache.
543                         // Modified by this register and (05ECh:bit0 / Wait register).
544                         // Now, cache is always disabled.
545                         // RPNH = 0 (Disabled) : Bit1
546                         // CMEN = 0 (Disabled) : Bit0
547                         val = 0x00;
548                 }
549                 break;
550         case 0x00c2: // Cache Diagnostic
551                 val = 0x00;
552                 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
553                         // ToDo: Implement cache disgnostic.
554                         // SDMOD (Not diagnostic) : Bit3
555                         val = 0x00;
556                 }
557                 break;
558         case 0x0400: // Resolution:
559                 val = 0xfe;
560                 break;
561         case 0x0404: // System Status Reg.
562                 val = (dma_is_vram) ? 0x7f : 0xff;
563 //              val = (dma_is_vram) ? 0x00 : 0x80;
564                 break;
565         case 0x0480:
566                 val  =  (select_d0_dict) ? 0x01 : 0x00;
567                 val |=  ((select_d0_rom) ? 0x00 : 0x02);
568                 val |= 0xfc;
569                 break;
570         case 0x05c0:
571 //              val = (extra_nmi_mask) ? 0xf7 : 0xff;
572                 val = (extra_nmi_mask) ? 0x00 : 0x08;
573                 break;
574         case 0x05c2:
575 //              val = (extra_nmi_val) ? 0xff : 0xf7;
576                 val = (extra_nmi_val) ? 0x08 : 0x00;
577                 break;
578         case 0x05e0:
579                 if(machine_id < 0x0200) { // Towns 1/2
580                         val =  wait_register_older;
581                 }
582                 break;
583         case 0x05e2:
584                 if(machine_id >= 0x0200) { // i386
585                         val = wait_register_ram;
586                 }
587                 break;
588         case 0x05e6:
589                 if(machine_id >= 0x0200) { // i386
590                         val = wait_register_vram;
591                 }
592                 break;
593         case 0x05e8:
594                 // After Towns1F/2F/1H/2H
595                 {
596                         uint16_t nid = machine_id & 0xff00;
597                         val = extram_size >> 20;
598                         switch(nid >> 8) {
599                         case 0x00:
600                         case 0x01: // Towns 1/2 : Not Supported.
601                                 val = 0xff;
602                                 break;
603                         case 0x03: // Towns II UX
604                         case 0x06: // Towns II U6
605                                 val = val & 0x0f;
606                                 if(val >= 9) val = 9;
607                                 break;
608                         case 0x02: // Towns 1F/2F/1H/2H.
609                         case 0x04: // Towns 10F/20F/40H/80H.
610                                 val = val & 0x07;
611                                 break;
612                         case 0x05: // Towns II CX
613                                 val = val & 0x0f;
614                                 break;
615                         case 0x08: // Towns II HG : OK?
616                                 val = val & 0x0f;
617                                 break;
618                         case 0x07: // Towns II HR
619                         case 0x09: // Towns II UR
620                                 val = val & 0x1f;
621                                 break;
622                         default:   // After MA/MX/ME/MF, Fresh
623                                 val = val & 0x7f;
624                                 break;
625                         }
626                 }
627                 break;
628         case 0x05ec:
629                 // 05ec, 05ed
630                 if(machine_id >= 0x0200) { // 05ec
631                         val = ((is_faster_wait()) ? 0x01 : 0x00);
632                 }
633                 break;
634         case 0x05ed:
635                 if(machine_id >= 0x0700) { // 05ed
636                         uint32_t clk = get_cpu_clocks(d_cpu);
637                         clk = clk / (1000 * 1000);
638                         __UNLIKELY_IF(clk < 16) clk = 16;
639                         __UNLIKELY_IF(clk > 127) clk = 127; // ToDo
640                         val = 0x00 | clk;
641                 }
642                 break;
643         case 0xfda4:
644                 if(machine_id >= 0x0700) { // After HR/HG
645                         val = (is_compatible) ? 0x00 : 0x01;
646                 } else {
647                         val = 0x00;
648                 }
649                 break;
650         default:
651                 break;
652         }
653         return val;
654 }
655 // Address (TOWNS BASIC):
656 // 0x0020 - 0x0022, 0x0030-0x0031,
657 // 0x0400 - 0x0404,
658 // 0x0480 - 0x0484
659 // 0x05c0 - 0x05c2
660 // 0x05ec (Wait register)
661 // 0x05ed (CPU SPEED REGISTER)
662 // Is set extra NMI (0x05c0 - 0x05c2)?
663 uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
664 {
665 //      uint32_t val = 0x00;  // MAY NOT FILL to "1" for unused bit 20200129 K.O
666         __LIKELY_IF((addr & 0xffff) >= 0xff80) {
667                 return read_fmr_ports8((addr & 0xffff) | 0x000c0000);
668         }
669         return read_sys_ports8(addr);
670 }
671
672 void TOWNS_MEMORY::write_fmr_ports8(uint32_t addr, uint32_t data)
673 {
674         __UNLIKELY_IF((addr < 0xcff80) || (addr > 0xcffbb)) {
675                 return;
676         }
677
678         __LIKELY_IF(addr < 0xcff88) {
679                 __LIKELY_IF(d_planevram != NULL) {
680                         d_planevram->write_io8(addr & 0xffff, data);
681                 }
682                 return;
683         }
684
685         if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
686                 switch(addr) {
687                 case 0xcff9e:
688                         __LIKELY_IF(d_font != NULL) {
689                                 d_font->write_io8(addr & 0xffff, data);
690                         }
691                         return;
692                 default:
693                         break;
694                 }
695         }
696         switch(addr) {
697         case 0xcff94:
698         case 0xcff95:
699                 __LIKELY_IF(d_font != NULL) {
700                         d_font->write_io8(addr & 0xffff, data);
701                 }
702                 break;
703         case 0xcff96:
704         case 0xcff97:
705                 break;
706         case 0xcff98:
707                 __LIKELY_IF(d_timer != NULL) {
708                         d_timer->write_signal(SIG_TIMER_BEEP_ON, 0, 1);
709                 }
710                 break;
711         case 0xcff99:
712                 {
713                         bool _b = ankcg_enabled;
714                         ankcg_enabled = ((data & 1) != 0) ? true : false;
715                 }
716                 break;
717         case 0xcffa0:
718                 __LIKELY_IF(d_planevram != NULL) {
719                         d_planevram->write_io8(addr & 0xffff, data);
720                 }
721                 break;
722         default:
723                 break;
724         }
725 }
726 void TOWNS_MEMORY::write_sys_ports8(uint32_t addr, uint32_t data)
727 {
728         switch(addr & 0xffff) {
729         case 0x0020: // Software reset ETC.
730                 // reset cause register
731                 if((data & 0x80) != 0) {
732                         nmi_vector_protect = true;
733                 } else {
734                         nmi_vector_protect = false;
735                 }
736                 if((data & 0x01) != 0) {
737                         software_reset = true;
738                 } else {
739                         software_reset = false;
740                 }
741
742                 if((data & 0x40) != 0) {
743                         poff_status = true;
744 //                      __LIKELY_IF(d_cpu != NULL) {
745 //                              d_cpu->set_shutdown_flag(1);
746 //                      }
747                         // Todo: Implement true power off.
748 //                      emu->notify_power_off();
749 //                      emu->power_off();
750 //                      break;
751                 } else {
752                         poff_status = false;
753 //                      __LIKELY_IF(d_cpu != NULL) {
754 //                              d_cpu->set_shutdown_flag(0);
755 //                      }
756                 }
757
758                 if((software_reset) || (poff_status)){
759 //                      __LIKELY_IF(d_cpu != NULL) {
760 //                              d_cpu->reset();
761 //                      }
762                         uint8_t wrap_val = 0xff; // WRAP ON
763                         __LIKELY_IF(d_dmac != NULL) {
764                                 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
765                         }
766                         if(poff_status) {
767                                 __LIKELY_IF(d_cpu != NULL) {
768                                         d_cpu->set_shutdown_flag(1);
769                                 }
770                                 // Todo: Implement true power off.
771                                  emu->notify_power_off();
772                                 // emu->power_off();
773                         }
774                         vm->reset();
775                 }
776                 // Towns SEEMS to not set addreess mask (a.k.a A20 mask). 20200131 K.O
777                 break;
778         case 0x0022:
779                 if((data & 0x40) != 0) {
780                         __LIKELY_IF(d_cpu != NULL) {
781                                 d_cpu->set_shutdown_flag(1);
782                         }
783                         // Todo: Implement true power off.
784                         poff_status = true;
785                         emu->notify_power_off();
786 //                      emu->power_off();
787                         vm->reset();
788                 }
789                 // Power register
790                 break;
791         case 0x0024:
792                 //if((d_dmac != NULL) && (machine_id >= 0x0b00)) { // After MA/MX/ME
793                 //      d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, data, 0xff);
794                 //}
795                 break;
796         case 0x0032:
797                 d_serialrom->write_signal(SIG_SERIALROM_CS, ~data, 0x20);
798                 d_serialrom->write_signal(SIG_SERIALROM_CLK, data, 0x40);
799                 d_serialrom->write_signal(SIG_SERIALROM_RESET, data, 0x80);
800                 break;
801         case 0x0404: // System Status Reg.
802                 {
803                         config_page0c_0e(((data & 0x80) == 0) ? true : false, select_d0_dict, false); // VRAM, DICT, FORCE
804                 }
805                 break;
806         case 0x0480:
807                 {
808                         bool is_dict, is_sysrom;
809                         is_dict = ((data & 0x01) != 0) ? true : false;
810                         is_sysrom = ((data & 0x02) == 0) ? true : false;
811                         config_page0c_0e(dma_is_vram, is_dict, false);
812                         config_page0f(is_sysrom, false);
813                 }
814                 break;
815         case 0x05c0:
816                 extra_nmi_mask = ((data & 0x08) == 0);
817                 break;
818         case 0x05e0:
819                 // From AB.COM
820                 if(machine_id < 0x0200) { // Towns 1/2
821                         uint8_t nval_bak = wait_register_older & 0x07;
822                         uint8_t nval = data & 0x07;
823                         if(nval < 1) nval = 1;
824                         mem_wait_val = nval;
825                         vram_wait_val = nval + 3; // OK?
826                         if(vram_wait_val > 6) {
827                                 vram_wait_val = 6;
828                         }
829                         wait_register_older = (data & 0xf8) | nval;
830                         cpu_clock_val = 16 * 1000 * 1000;
831                         if(nval_bak != nval) {
832                                 set_cpu_clock_by_wait();
833                                 set_wait_values();
834                         }
835                 }
836                 break;
837         case 0x05e2:
838                 if(machine_id >= 0x0200) { // After Towns 1H/2F. Hidden wait register.
839                         uint8_t vram_bak = vram_wait_val;
840                         uint8_t mem_bak = mem_wait_val;
841                         if(data != 0x83) {
842                                 uint8_t nval = data & 7;
843                                 if(machine_id <= 0x0200) { // Towns 1H/2F.
844                                         if(nval < 1) nval = 1;
845                                 }
846                                 if(nval > 6) nval = 6;
847                                 mem_wait_val = nval;
848                                 wait_register_ram = (data & 0xf8) | nval;
849                         } else {
850                                 mem_wait_val = 3;
851                                 vram_wait_val = 6;
852                                 wait_register_ram = data;
853                         }
854                         if((vram_bak != vram_wait_val) || (mem_bak != mem_wait_val)) {
855                                 set_cpu_clock_by_wait();
856                                 set_wait_values();
857                         }
858                 }
859                 break;
860         case 0x05e6:
861                 if(machine_id >= 0x0200) { // After Towns 1H/2F. Hidden wait register.
862                         uint8_t mem_bak = mem_wait_val;
863                         uint8_t vram_bak = vram_wait_val;
864                         if(data != 0x83) {
865                                 uint8_t nval = data & 7;
866                                 if(machine_id <= 0x0200) { // Towns 1H/2F.
867                                         if(nval < 1) nval = 1;
868                                 }
869                                 if(nval > 6) nval = 6;
870                                 vram_wait_val = nval;
871                                 wait_register_vram = (data & 0xf8) | nval;
872                         } else {
873                                 mem_wait_val = 3;
874                                 vram_wait_val = 3;
875                                 wait_register_vram = data;
876                         }
877                         if((vram_bak != vram_wait_val) || (mem_bak != mem_wait_val)) {
878                                 set_cpu_clock_by_wait();
879                                 set_wait_values();
880                         }
881                 }
882                 break;
883         case 0x05ec:
884                 // ToDo: 0x05ed
885                 if(machine_id >= 0x0500) { // Towns2 CX :
886                         uint8_t mem_bak = mem_wait_val;
887                         uint8_t vram_bak = vram_wait_val;
888                         vram_wait_val = ((data & 0x01) != 0) ? 0 : 6;
889                         mem_wait_val = ((data & 0x01) != 0) ? 0 : 6;
890                         wait_register_ram = mem_wait_val;
891                         wait_register_vram = vram_wait_val;
892                         if((mem_bak != mem_wait_val) || (vram_bak != vram_wait_val)) {
893                                 set_cpu_clock_by_wait();
894                                 set_wait_values();
895                         }
896                 }
897                 break;
898
899         case 0xfda4:
900                 if(machine_id >= 0x0700) { // After HR/HG
901                         is_compatible = ((data & 0x01) == 0x00) ? true : false;
902                         __LIKELY_IF(d_crtc != NULL) {
903                                 d_crtc->write_signal(SIG_TOWNS_CRTC_COMPATIBLE_MMIO, (is_compatible) ? 0xffffffff : 0x00000000, 0xffffffff);
904                         }
905                 }
906                 break;
907         default:
908                 break;
909         }
910 }
911 void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
912 {
913         __LIKELY_IF((addr & 0xffff) >= 0xff80) {
914                 write_fmr_ports8((addr & 0xffff) | 0x000c0000, data);
915                 return;
916         }
917         write_sys_ports8(addr, data);
918 }
919
920
921 uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int* wait)
922 {
923         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
924         uint32_t offset = addr & memory_map_mask();
925         return read_8bit_data(membus_read_map, mapptr, addr, offset, false, wait);
926 }
927
928 uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int* wait)
929 {
930         uint16_t val;
931         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
932         uint32_t offset = addr & memory_map_mask();
933         __UNLIKELY_IF(check_device_boundary(membus_read_map, mapptr, offset, 2)) {
934                 val = read_beyond_boundary_data16(membus_read_map, addr, offset, mapptr, false, wait);
935         } else {
936                 val = read_16bit_data(membus_read_map, mapptr, addr, offset, false, wait);
937         }
938         return val;
939 }
940
941 uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int* wait)
942 {
943         uint32_t val;
944         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
945         uint32_t offset = addr & memory_map_mask();
946         __UNLIKELY_IF(check_device_boundary(membus_read_map, mapptr, offset, 4)) {
947                 val =  read_beyond_boundary_data32(membus_read_map, addr, offset, mapptr,false,  wait);
948         } else {
949                 val = read_32bit_data(membus_read_map, mapptr, addr, offset, false, wait);
950
951         }
952         return val;
953 }
954
955 uint32_t TOWNS_MEMORY::read_dma_data8w(uint32_t addr, int* wait)
956 {
957         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
958         uint32_t offset = addr & memory_map_mask();
959         uint8_t val;
960         int waitval;
961         //return read_8bit_data(dma_read_map, mapptr, addr, offset, true, wait);
962         val = read_8bit_data(dma_read_map, mapptr, addr, offset, false, &waitval);
963         __LIKELY_IF(wait != NULL) {
964                 *wait = 0; // Discard wait value for DMA.
965         }
966         return val;
967 }
968
969 uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
970 {
971         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
972         uint32_t offset = addr & memory_map_mask();
973         uint16_t val;
974         int waitval;
975         __UNLIKELY_IF(check_device_boundary(dma_read_map, mapptr, offset, 2)) {
976                 val = read_beyond_boundary_data16(dma_read_map, addr, offset, mapptr, true, &waitval);
977         } else {
978                 val = read_16bit_data(dma_read_map, mapptr, addr, offset, false, &waitval);
979         //val =  read_16bit_data(dma_read_map, mapptr, addr, offset, true, &waitval);
980         }
981         __LIKELY_IF(wait != NULL) {
982                 *wait = 0; // Discard wait value for DMA.
983         }
984         return val;
985
986 }
987
988 uint32_t TOWNS_MEMORY::read_dma_data32w(uint32_t addr, int* wait)
989 {
990         uint32_t val;
991         int waitval;
992         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
993         uint32_t offset = addr & memory_map_mask();
994         __UNLIKELY_IF(check_device_boundary(dma_read_map, mapptr, offset, 4)) {
995                 val =  read_beyond_boundary_data32(dma_read_map, addr, offset, mapptr, true, &waitval);
996         } else {
997         //return read_32bit_data(dma_read_map, mapptr, addr, offset, true, wait);
998                 val = read_32bit_data(dma_read_map, mapptr, addr, offset, false, &waitval);
999         }
1000         __LIKELY_IF(wait != NULL) {
1001                 *wait = 0; // Discard wait value for DMA.
1002         }
1003         return val;
1004 }
1005
1006
1007 void TOWNS_MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
1008 {
1009         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1010         uint32_t offset = addr & memory_map_mask();
1011         write_8bit_data(membus_write_map, mapptr, addr, offset, false, data, wait);
1012 }
1013
1014
1015 void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int* wait)
1016 {
1017         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1018         uint32_t offset = addr & memory_map_mask();
1019         __UNLIKELY_IF(check_device_boundary(membus_write_map, mapptr, offset, 2)) {
1020                 write_beyond_boundary_data16(membus_write_map, addr, offset, mapptr, false, data, wait);
1021         } else {
1022                 write_16bit_data(membus_write_map, mapptr, addr, offset, false, data, wait);
1023         }
1024 }
1025
1026
1027 void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int* wait)
1028 {
1029         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1030         uint32_t offset = addr & memory_map_mask();
1031         __UNLIKELY_IF(check_device_boundary(membus_write_map, mapptr, offset, 4)) {
1032                 write_beyond_boundary_data32(membus_write_map, addr, offset, mapptr, false, data, wait);
1033         } else {
1034                 write_32bit_data(membus_write_map, mapptr, addr, offset, false, data, wait);
1035         }
1036 }
1037
1038 void TOWNS_MEMORY::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
1039 {
1040         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1041         uint32_t offset = addr & memory_map_mask();
1042         int waitval;
1043         //write_8bit_data(dma_write_map, mapptr, addr, offset, true, data, wait);
1044         write_8bit_data(dma_write_map, mapptr, addr, offset, false, data, &waitval);
1045         __LIKELY_IF(wait != NULL) {
1046                 *wait = 0; // Discard wait value for DMA.
1047         }
1048 }
1049
1050 void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
1051 {
1052         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1053         uint32_t offset = addr & memory_map_mask();
1054         int waitval;
1055         __UNLIKELY_IF(check_device_boundary(dma_write_map, mapptr, offset, 2)) {
1056                 write_beyond_boundary_data16(dma_write_map, addr, offset, mapptr, true, data, &waitval);
1057         } else {
1058                 //write_16bit_data(dma_write_map, mapptr, addr, offset, true, data, wait);
1059                 write_16bit_data(dma_write_map, mapptr, addr, offset, false, data, &waitval);
1060         }
1061         __LIKELY_IF(wait != NULL) {
1062                 *wait = 0; // Discard wait value for DMA.
1063         }
1064 }
1065
1066
1067 void TOWNS_MEMORY::write_dma_data32w(uint32_t addr, uint32_t data, int* wait)
1068 {
1069         uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1070         uint32_t offset = addr & memory_map_mask();
1071         int waitval;
1072         __UNLIKELY_IF(check_device_boundary(dma_write_map, mapptr, offset, 4)) {
1073                 write_beyond_boundary_data32(dma_write_map, addr, offset, mapptr, true, data, &waitval);
1074         } else {
1075                 //write_32bit_data(dma_write_map, mapptr, addr, offset, true, data, &waitval);
1076                 write_32bit_data(dma_write_map, mapptr, addr, offset, false, data, &waitval);
1077         }
1078         __LIKELY_IF(wait != NULL) {
1079                 *wait = 0; // Discard wait value for DMA.
1080         }
1081 }
1082
1083 uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
1084 {
1085         // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1086         __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1087                 // Out of bounds;
1088                 return 0xff;
1089         }
1090         __LIKELY_IF(addr >= 0x000cc000) {
1091                 // RAM: OK?
1092                 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
1093                         return read_fmr_ports8(addr);
1094                 } else {
1095                         __LIKELY_IF(extra_ram != NULL) {
1096                                 return extra_ram[addr];
1097                         }
1098                         return 0xff;
1099                 }
1100         }
1101         // ROMs?
1102         if(addr < 0x000c9000) { // TEXT VRAM (ANK)
1103                 __LIKELY_IF(d_sprite != NULL) {
1104                         return d_sprite->read_memory_mapped_io8(addr);
1105                 }
1106                 return 0xff;
1107         }
1108         if(ankcg_enabled) {
1109                 __LIKELY_IF(addr >= 0x000ca000) { // ANKCG8 and ANKCG16
1110                         __LIKELY_IF(d_font != NULL) {
1111                                 return d_font->read_memory_mapped_io8(addr);
1112                         }
1113                 }
1114         } else {
1115                 __LIKELY_IF(addr < 0x000cb000) { // TEXT VRAM (KANJI)
1116                         __LIKELY_IF(d_sprite != NULL) {
1117                                 return d_sprite->read_memory_mapped_io8(addr);
1118                         }
1119                 }
1120         }
1121         return 0xff;
1122 }
1123
1124 uint32_t TOWNS_MEMORY::read_memory_mapped_io16(uint32_t addr)
1125 {
1126         // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1127         __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1128                 // out of bounds
1129                 return 0xffff;
1130         }
1131         __LIKELY_IF(addr >= 0x000cc000) {
1132                 // RAM: OK?
1133                 pair16_t w;
1134                 __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cffff)) { // I/O
1135                         w.b.l = read_fmr_ports8(addr);
1136                         w.b.h = read_fmr_ports8(addr + 1);
1137                 } else {
1138                         __LIKELY_IF(extra_ram != NULL) {
1139                                 w.read_2bytes_le_from(&(extra_ram[addr]));
1140                         } else {
1141                                 w.w = 0xffff;
1142                         }
1143                 }
1144                 return w.w;
1145         }
1146         // ROMs?
1147         if(addr < 0x000c9000) { // TEXT VRAM (ANK)
1148                 __LIKELY_IF(d_sprite != NULL) {
1149                         return d_sprite->read_memory_mapped_io16(addr);
1150                 }
1151                 return 0xffff;
1152         }
1153         if(ankcg_enabled) {
1154                 __LIKELY_IF(addr >= 0x000ca000) { // ANKCG8 and ANKCG16
1155                         __LIKELY_IF(d_font != NULL) {
1156                                 return d_font->read_memory_mapped_io16(addr);
1157                         }
1158                 }
1159         } else {
1160                 __LIKELY_IF(addr < 0x000cb000) { // TEXT VRAM (KANJI)
1161                         __LIKELY_IF(d_sprite != NULL) {
1162                                 return d_sprite->read_memory_mapped_io16(addr);
1163                         }
1164                 }
1165         }
1166         return 0xffff;
1167 }
1168
1169 uint32_t TOWNS_MEMORY::read_memory_mapped_io32(uint32_t addr)
1170 {
1171         // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1172         __UNLIKELY_IF((addr > 0x000cffff) || (addr < 0x000c8000)) {
1173                 // out of bounds
1174                 return 0xffffffff;
1175         }
1176         __LIKELY_IF(addr >= 0x000cc000) {
1177                 // RAM: OK?
1178                 pair32_t d;
1179                 __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cfffd)) { // I/O
1180                         d.b.l  = read_fmr_ports8(addr);
1181                         d.b.h  = read_fmr_ports8(addr + 1);
1182                         d.b.h2 = read_fmr_ports8(addr + 2);
1183                         d.b.h3 = read_fmr_ports8(addr + 3);
1184                 } else {
1185                         __LIKELY_IF(extra_ram != NULL) {
1186                                 d.read_4bytes_le_from(&(extra_ram[addr]));
1187                         } else {
1188                                 d.d = 0xffffffff;
1189                         }
1190                 }
1191                 return d.d;
1192         }
1193         // ROMs?
1194         if(addr < 0x000ca000) { //SPRITE
1195                 __LIKELY_IF(d_sprite != NULL) {
1196                         return d_sprite->read_memory_mapped_io32(addr);
1197                 }
1198                 return 0xffffffff;
1199         }
1200         if(ankcg_enabled) {
1201                 __LIKELY_IF(d_font != NULL) {
1202                         return d_font->read_memory_mapped_io32(addr);
1203                 }
1204         } else {
1205                 __LIKELY_IF(d_sprite != NULL) {
1206                         return d_sprite->read_memory_mapped_io32(addr);
1207                 }
1208         }
1209         return 0xffffffff;
1210 }
1211
1212
1213 void TOWNS_MEMORY::write_memory_mapped_io8(uint32_t addr, uint32_t data)
1214 {
1215         // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1216         __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1217                 // Out of bounds
1218                 return;
1219         }
1220         __LIKELY_IF(addr >= 0x000cc000) {
1221                 // RAM: OK?
1222                 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
1223                         write_fmr_ports8(addr, data);
1224                         return;
1225                 }
1226                 __LIKELY_IF(extra_ram != NULL) {
1227                         extra_ram[addr] = data;
1228                 }
1229                 return;
1230         }
1231         // ROMs?
1232         if(addr < 0x000cb000) { // TEXT VRAM (ANK + KANJI)
1233                 __LIKELY_IF(d_sprite != NULL) {
1234                         d_sprite->write_memory_mapped_io8(addr, data);
1235                 }
1236                 return;
1237         }
1238         return;
1239 }
1240
1241 void TOWNS_MEMORY::write_memory_mapped_io16(uint32_t addr, uint32_t data)
1242 {
1243         // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1244         __UNLIKELY_IF((addr > 0x000cffff) || (addr < 0x000c8000)) {
1245                 // Out of bounds
1246                 return;
1247         }
1248         __LIKELY_IF(addr >= 0x000cc000) {
1249                 // RAM: OK?
1250                 pair16_t w;
1251                 w.w = data;
1252                 __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cffff)) { // I/O
1253                         write_fmr_ports8(addr    , w.b.l);
1254                         write_fmr_ports8(addr + 1, w.b.h);
1255                         return;
1256                 }
1257                 __LIKELY_IF(extra_ram != NULL) {
1258                         w.write_2bytes_le_to(&(extra_ram[addr]));
1259                 }
1260                 return;
1261         }
1262         // ROMs?
1263         if(addr < 0x000cb000) { // TEXT VRAM (ANK + KANJI)
1264                 __LIKELY_IF(d_sprite != NULL) {
1265                         d_sprite->write_memory_mapped_io16(addr, data);
1266                 }
1267                 return;
1268         }
1269         return;
1270 }
1271
1272 void TOWNS_MEMORY::write_memory_mapped_io32(uint32_t addr, uint32_t data)
1273 {
1274         // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1275         __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1276                 return;
1277         }
1278         __LIKELY_IF(addr >= 0x000cc000) {
1279                 // RAM: OK?
1280                 pair32_t d;
1281                 d.d = data;
1282                 __UNLIKELY_IF((addr >= 0x000cff80) && (addr < 0x000cfffd)) { // I/O
1283                         write_fmr_ports8(addr    , d.b.l);
1284                         write_fmr_ports8(addr + 1, d.b.h);
1285                         write_fmr_ports8(addr + 2, d.b.h2);
1286                         write_fmr_ports8(addr + 3, d.b.h3);
1287                         return;
1288                 }
1289                 __LIKELY_IF(extra_ram != NULL) {
1290                         d.write_4bytes_le_to(&(extra_ram[addr]));
1291                 }
1292                 return;
1293         }
1294         // ROMs?
1295         if(addr < 0x000cb000) { // TEXT VRAM (ANK + KANJI)
1296                 __LIKELY_IF(d_sprite != NULL) {
1297                         d_sprite->write_memory_mapped_io32(addr, data);
1298                 }
1299                 return;
1300         }
1301         return;
1302 }
1303
1304
1305
1306 void TOWNS_MEMORY::write_signal(int ch, uint32_t data, uint32_t mask)
1307 {
1308         if(ch == SIG_MEMORY_EXTNMI) {
1309                 extra_nmi_val = ((data & mask) != 0);
1310                 if(!(extra_nmi_mask)) {
1311                         // Not MASK
1312                         __LIKELY_IF(d_cpu != NULL) {
1313                                 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
1314                         }
1315                 }
1316         } else if(ch == SIG_CPU_NMI) {
1317                 // Check protect
1318                 if(!(nmi_mask)) {
1319                         __LIKELY_IF(d_cpu != NULL) {
1320                                 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
1321                         }
1322                 }
1323         } else if(ch == SIG_CPU_IRQ) {
1324                 __LIKELY_IF(d_cpu != NULL) {
1325                         d_cpu->write_signal(SIG_CPU_IRQ, data, mask);
1326                 }
1327         } else if(ch == SIG_CPU_BUSREQ) {
1328                 __LIKELY_IF(d_cpu != NULL) {
1329                         d_cpu->write_signal(SIG_CPU_BUSREQ, data, mask);
1330                 }
1331         } else if(ch == SIG_I386_A20) {
1332                 __LIKELY_IF(d_cpu != NULL) {
1333                         d_cpu->write_signal(SIG_I386_A20, data, mask);
1334                 }
1335         } else if(ch == SIG_FMTOWNS_NOTIFY_RESET) {
1336                 out_debug_log("RESET FROM CPU!!!\n");
1337                 reset_happened = true;
1338
1339                 nmi_vector_protect = false;
1340                 ankcg_enabled = false;
1341                 nmi_mask = false;
1342                 config_page0c_0e(true, false, true);
1343                 config_page0f(true, true);
1344                 reset_wait_values();
1345                 set_wait_values();
1346
1347                 __LIKELY_IF(d_cpu != NULL) {
1348                         d_cpu->set_address_mask(0xffffffff);
1349                 }
1350                 __LIKELY_IF(d_dmac != NULL) {
1351                         uint8_t wrap_val = 0xff; // WRAP ON
1352                         d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
1353                 }
1354         } else if(ch == SIG_FMTOWNS_RAM_WAIT) {
1355                 uint8_t _bak = mem_wait_val;
1356                 mem_wait_val = (int)data;
1357                 if(_bak != mem_wait_val) {
1358                         set_wait_values();
1359                 }
1360         } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
1361 //              mem_wait_val = (int)data;
1362                 set_wait_values();
1363         } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
1364                 uint8_t _bak = vram_wait_val;
1365                 vram_wait_val = (int)data;
1366                 if(_bak != vram_wait_val) {
1367                         set_wait_values();
1368                 }
1369         }
1370 }
1371
1372 uint32_t TOWNS_MEMORY::read_signal(int ch)
1373 {
1374         if(ch == SIG_FMTOWNS_MACHINE_ID) {
1375                 uint16_t d = (machine_id & 0xfff8) | ((uint16_t)(cpu_id & 0x07));
1376                 return (uint32_t)d;
1377         } else if(ch == SIG_FMTOWNS_RAM_WAIT) {
1378                 return (uint32_t)mem_wait_val;
1379         } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
1380                 return 6; // OK?
1381         } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
1382                 return (uint32_t)vram_wait_val;
1383         }
1384         return 0;
1385 }
1386
1387 void TOWNS_MEMORY::set_intr_line(bool line, bool pending, uint32_t bit)
1388 {
1389         __LIKELY_IF(d_cpu != NULL) {
1390                 d_cpu->set_intr_line(line, pending, bit);
1391         }
1392 }
1393
1394 // ToDo: DMA
1395
1396 #define STATE_VERSION   8
1397
1398 bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
1399 {
1400         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1401                 return false;
1402         }
1403
1404         if(!state_fio->StateCheckInt32(this_device_id)) {
1405                 return false;
1406         }
1407         state_fio->StateValue(machine_id);
1408         state_fio->StateValue(cpu_id);
1409         state_fio->StateValue(is_compatible);
1410
1411         state_fio->StateValue(mem_wait_val);
1412         state_fio->StateValue(vram_wait_val);
1413         state_fio->StateValue(wait_register_older);
1414         state_fio->StateValue(wait_register_ram);
1415         state_fio->StateValue(wait_register_vram);
1416
1417         state_fio->StateValue(dma_is_vram);
1418         state_fio->StateValue(nmi_vector_protect);
1419         state_fio->StateValue(software_reset);
1420         state_fio->StateValue(poff_status);
1421         state_fio->StateValue(reset_happened);
1422
1423         state_fio->StateValue(extra_nmi_val);
1424         state_fio->StateValue(extra_nmi_mask);
1425         state_fio->StateValue(nmi_mask);
1426
1427
1428         state_fio->StateValue(select_d0_rom);
1429         state_fio->StateValue(select_d0_dict);
1430         state_fio->StateValue(ankcg_enabled);
1431
1432         state_fio->StateValue(vram_wait_val);
1433         state_fio->StateValue(mem_wait_val);
1434         state_fio->StateValue(vram_size);
1435         state_fio->StateValue(cpu_clock_val);
1436
1437         if(loading) {
1438                 update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
1439
1440                 uint32_t length_tmp = state_fio->FgetUint32_LE();
1441                 unset_range_rw(0x00100000, 0x3fffffff);
1442                 if(extra_ram != NULL) {
1443                         free(extra_ram);
1444                         extra_ram = NULL;
1445                 }
1446                 length_tmp = length_tmp & 0x3ff00000;
1447                 extram_size = length_tmp;
1448                 extra_ram = (uint8_t*)malloc(length_tmp + 0x00100000);
1449                 __LIKELY_IF(extra_ram != NULL) {
1450                         set_region_memory_rw(0x00000000, (extram_size + 0x00100000) - 1, extra_ram, 0);
1451                         memset(extra_ram, 0x00, extram_size + 0x00100000);
1452                 }
1453
1454                 if(extra_ram == NULL) {
1455                         extram_size = 0;
1456                         return false;
1457                 } else {
1458                         state_fio->Fread(extra_ram, extram_size + 0x00100000, 1);
1459                         //set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
1460                 }
1461                 config_page0c_0e(dma_is_vram, select_d0_dict, true);
1462                 config_page0f(select_d0_rom, true);
1463                 set_wait_values();
1464                 //config_page00();
1465         } else {
1466                 // At saving
1467                 if(extra_ram == NULL) {
1468                         state_fio->FputUint32_LE(0);
1469                 } else {
1470                         state_fio->FputUint32_LE(extram_size & 0x3ff00000);
1471                         state_fio->Fwrite(extra_ram, extram_size + 0x00100000, 1);
1472                 }
1473         }
1474
1475         // ToDo: Do save ROMs?
1476         return true;
1477 }
1478
1479 }