2 FUJITSU FM Towns Emulator 'eFMTowns'
4 Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
10 #include "../../fileio.h"
11 #include "./towns_memory.h"
14 #include "./planevram.h"
16 #include "./fontroms.h"
17 #include "./serialrom.h"
21 #include "../i386_np21.h"
22 //#include "../i386.h"
28 void TOWNS_MEMORY::initialize()
30 if(initialized) return;
31 //MEMORY::initialize();
33 update_machine_features();
34 extra_nmi_mask = true;
35 extra_nmi_val = false;
37 reset_happened = false;
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;
46 wait_register_older = 3;
47 wait_register_vram = 0x06;
48 wait_register_ram = 0x03;
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.
56 unset_range_rw(0x00000000, 0xffffffff);
60 set_region_memory_rw(0x00000000, 0x000bffff, ram_page0);
61 set_region_memory_rw(0x000c0000, 0x000fffff, ram_pagec);
62 memset(ram_page0, 0x00, sizeof(ram_page0));
63 memset(ram_pagec, 0x00, sizeof(ram_pagec));
65 if(extram_size >= 0x00100000) {
66 __UNLIKELY_IF(extra_ram == NULL) {
67 extra_ram = (uint8_t*)malloc(extram_size);
68 __LIKELY_IF(extra_ram != NULL) {
69 set_region_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
70 memset(extra_ram, 0x00, extram_size);
80 config_page0c_0e(true, false, true);
81 config_page0f(true, true);
83 set_region_device_rw(0x80000000, 0x8007ffff, d_vram, NOT_NEED_TO_OFFSET);
84 set_region_device_rw(0x80100000, 0x8017ffff, d_vram, NOT_NEED_TO_OFFSET);
86 set_region_device_rw(0x81000000, 0x8101ffff, d_sprite, NOT_NEED_TO_OFFSET);
87 set_region_device_rw(0xc0000000, 0xc0ffffff, d_iccard[0], 0);
88 set_region_device_rw(0xc1000000, 0xc1ffffff, d_iccard[1], 0);
89 // set_wait_rw(0x00000000, 0xffffffff, vram_wait_val);
91 set_region_device_r (0xc2000000, 0xc207ffff, d_msdos, NOT_NEED_TO_OFFSET);
92 set_region_device_r (0xc2080000, 0xc20fffff, d_dictionary, NOT_NEED_TO_OFFSET);
93 set_region_device_r (0xc2100000, 0xc213ffff, d_font, NOT_NEED_TO_OFFSET);
94 // REAL IS C2140000h - C2141FFFh, but grain may be 8000h bytes.
95 set_region_device_rw(0xc2140000, 0xc2140000 + memory_map_grain() - 1, d_dictionary, NOT_NEED_TO_OFFSET);
96 if(d_font_20pix != NULL) {
97 set_region_device_r (0xc2180000, 0xc21fffff, d_font_20pix, NOT_NEED_TO_OFFSET);
99 // REAL IS C2200000h - C2200FFFh, but grain may be 8000h bytes.
100 set_region_device_rw(0xc2200000, 0xc2200000 + memory_map_grain() - 1, d_pcm, NOT_NEED_TO_OFFSET);
101 set_region_device_r (0xfffc0000, 0xffffffff, d_sysrom, NOT_NEED_TO_OFFSET);
102 // Another devices are blank
106 vram_size = 0x80000; // OK?
109 void TOWNS_MEMORY::reset_wait_values()
111 set_mmio_wait_rw(0x00000000, 0x7fffffff, WAITVAL_RAM);
112 set_dma_wait_rw (0x00000000, 0x7fffffff, WAITVAL_RAM);
113 set_mmio_wait_rw(0x80000000, 0x803fffff, WAITVAL_VRAM); // Default Value
114 set_dma_wait_rw (0x80000000, 0x803fffff, WAITVAL_VRAM); // Default Value
115 set_mmio_wait_rw(0x80400000, 0xffffffff, WAITVAL_RAM);
116 set_dma_wait_rw (0x80400000, 0xffffffff, WAITVAL_RAM);
119 void TOWNS_MEMORY::config_page0c_0e(const bool vrambank, const bool dictbank, const bool force)
121 const bool is_vram_bak = dma_is_vram;
122 const bool is_dict_bak = select_d0_dict;
123 __UNLIKELY_IF((vrambank != is_vram_bak) || (force)){
124 if(vrambank) { // VRAM AND around TEXT
125 set_region_device_rw(0x000c0000, 0x000c7fff, d_planevram, NOT_NEED_TO_OFFSET);
126 set_region_device_rw(0x000c8000, 0x000cffff, this, NOT_NEED_TO_OFFSET);
128 unset_range_rw(0x000e0000, 0x000effff); // OK?
130 set_mmio_wait_rw(0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
131 set_dma_wait_rw (0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
133 set_region_memory_rw(0x000c0000, 0x000cffff, ram_pagec);
134 set_region_memory_rw(0x000e0000, 0x000effff, &(ram_pagec[0x20000]));
135 set_mmio_wait_rw(0x000c0000, 0x000cffff, WAITVAL_RAM); // Default Value
136 set_dma_wait_rw (0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
139 __UNLIKELY_IF((vrambank != is_vram_bak) || (dictbank != is_dict_bak) || (force)){
140 if(vrambank) { // VRAM AND around TEXT
142 set_region_device_r(0x000d0000, 0x000d7fff, d_dictionary, NOT_NEED_TO_OFFSET);
143 unset_range_w(0x000d0000, 0x000d7fff);
144 // REAL IS 0000D8000h - 000D9FFFh, but grain may be 8000h bytes.
145 set_region_device_rw(0x000d8000, 0x000d8000 + memory_map_grain() - 1, d_dictionary, NOT_NEED_TO_OFFSET);
147 unset_range_rw(0x000d0000, 0x000dffff);
150 set_region_memory_rw(0x000d0000, 0x000dffff, &(ram_pagec[0x10000]));
153 dma_is_vram = vrambank;
154 select_d0_dict = dictbank;
156 void TOWNS_MEMORY::config_page0f(const bool sysrombank, const bool force)
158 bool sysrom_bak = select_d0_rom;
159 set_region_memory_rw(0x000f0000, 0x000f7fff, &(ram_pagec[0x30000]));
160 __UNLIKELY_IF((sysrombank != sysrom_bak) || (force)) {
162 unset_range_w(0x000f8000, 0x000fffff);
163 set_region_device_rw(0x000f8000, 0x000fffff, d_sysrom, NOT_NEED_TO_OFFSET);
165 set_region_memory_rw(0x000f8000, 0x000fffff, &(ram_pagec[0x38000]));
168 select_d0_rom = sysrombank;
172 void TOWNS_MEMORY::set_mmio_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr)
174 uint64_t _start = (uint64_t)start;
175 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
177 _start &= ~(memory_map_mask());
178 _end &= ~(memory_map_mask());
180 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
181 const uint64_t _incval = memory_map_grain();
182 uint32_t realoffset = 0;
183 for(uint64_t addr = _start; addr < _end; addr += _incval) {
184 mmio_memory_map_r[mapptr] = &(baseptr[realoffset]);
185 mmio_devices_map_r[mapptr] = NULL;
186 realoffset += _incval;
191 void TOWNS_MEMORY::set_mmio_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr)
193 uint64_t _start = (uint64_t)start;
194 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
196 _start &= ~(memory_map_mask());
197 _end &= ~(memory_map_mask());
199 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
200 const uint64_t _incval = memory_map_grain();
201 uint32_t realoffset = 0;
202 for(uint64_t addr = _start; addr < _end; addr += _incval) {
203 mmio_memory_map_w[mapptr] = &(baseptr[realoffset]);
204 mmio_devices_map_w[mapptr] = NULL;
205 realoffset += _incval;
210 void __FASTCALL TOWNS_MEMORY::set_mmio_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
212 uint64_t _start = (uint64_t)start;
213 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
215 _start &= ~(memory_map_mask());
216 _end &= ~(memory_map_mask());
218 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
219 const uint64_t _incval = memory_map_grain();
220 uint32_t realoffset = 0;
221 for(uint64_t addr = _start; addr < _end; addr += _incval) {
222 mmio_memory_map_r[mapptr] = NULL;
223 mmio_devices_map_r[mapptr] = ptr;
224 __LIKELY_IF(baseaddress == UINT32_MAX) {
225 mmio_devices_base_r[mapptr] = UINT32_MAX;
227 mmio_devices_base_r[mapptr] = baseaddress + realoffset;
229 realoffset += _incval;
234 void __FASTCALL TOWNS_MEMORY::set_mmio_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
236 uint64_t _start = (uint64_t)start;
237 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
239 _start &= ~(memory_map_mask());
240 _end &= ~(memory_map_mask());
242 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
243 const uint64_t _incval = memory_map_grain();
244 uint32_t realoffset = 0;
245 for(uint64_t addr = _start; addr < _end; addr += _incval) {
246 mmio_memory_map_w[mapptr] = NULL;
247 mmio_devices_map_w[mapptr] = ptr;
248 __LIKELY_IF(baseaddress == UINT32_MAX) {
249 mmio_devices_base_w[mapptr] = UINT32_MAX;
251 mmio_devices_base_w[mapptr] = baseaddress + realoffset;
253 realoffset += _incval;
258 void __FASTCALL TOWNS_MEMORY::set_mmio_wait_r(uint32_t start, uint32_t end, int wait)
260 uint64_t _start = (uint64_t)start;
261 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
263 _start &= ~(memory_map_mask());
264 _end &= ~(memory_map_mask());
266 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
267 const uint64_t _incval = memory_map_grain();
268 uint32_t realoffset = 0;
269 for(uint64_t addr = _start; addr < _end; addr += _incval) {
270 mmio_wait_map_w[mapptr] = wait;
275 void __FASTCALL TOWNS_MEMORY::set_mmio_wait_w(uint32_t start, uint32_t end, int wait)
277 uint64_t _start = (uint64_t)start;
278 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
280 _start &= ~(memory_map_mask());
281 _end &= ~(memory_map_mask());
283 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
284 const uint64_t _incval = memory_map_grain();
285 uint32_t realoffset = 0;
286 for(uint64_t addr = _start; addr < _end; addr += _incval) {
287 mmio_wait_map_r[mapptr] = wait;
292 void TOWNS_MEMORY::unset_mmio_r(uint32_t start, uint32_t end)
294 uint64_t _start = (uint64_t)start;
295 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
297 _start &= ~(memory_map_mask());
298 _end &= ~(memory_map_mask());
300 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
301 const uint64_t _incval = memory_map_grain();
302 uint32_t realoffset = 0;
303 for(uint64_t addr = _start; addr < _end; addr += _incval) {
304 mmio_memory_map_r[mapptr] = NULL;
305 mmio_devices_map_r[mapptr] = NULL;
306 mmio_wait_map_r[mapptr] = WAITVAL_RAM;
307 realoffset += _incval;
312 void TOWNS_MEMORY::unset_mmio_w(uint32_t start, uint32_t end)
314 uint64_t _start = (uint64_t)start;
315 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
317 _start &= ~(memory_map_mask());
318 _end &= ~(memory_map_mask());
320 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
321 const uint64_t _incval = memory_map_grain();
322 uint32_t realoffset = 0;
323 for(uint64_t addr = _start; addr < _end; addr += _incval) {
324 mmio_memory_map_w[mapptr] = NULL;
325 mmio_devices_map_w[mapptr] = NULL;
326 mmio_wait_map_w[mapptr] = WAITVAL_RAM;
327 realoffset += _incval;
332 void TOWNS_MEMORY::unset_dma_r(uint32_t start, uint32_t end)
334 uint64_t _start = (uint64_t)start;
335 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
337 _start &= ~(memory_map_mask());
338 _end &= ~(memory_map_mask());
340 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
341 const uint64_t _incval = memory_map_grain();
342 uint32_t realoffset = 0;
343 for(uint64_t addr = _start; addr < _end; addr += _incval) {
344 dma_memory_map_w[mapptr] = NULL;
345 dma_devices_map_w[mapptr] = NULL;
346 dma_wait_map_w[mapptr] = WAITVAL_RAM;
347 realoffset += _incval;
352 void TOWNS_MEMORY::unset_dma_w(uint32_t start, uint32_t end)
354 uint64_t _start = (uint64_t)start;
355 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
357 _start &= ~(memory_map_mask());
358 _end &= ~(memory_map_mask());
360 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
361 const uint64_t _incval = memory_map_grain();
362 uint32_t realoffset = 0;
363 for(uint64_t addr = _start; addr < _end; addr += _incval) {
364 dma_memory_map_w[mapptr] = NULL;
365 dma_devices_map_w[mapptr] = NULL;
366 dma_wait_map_w[mapptr] = WAITVAL_RAM;
367 realoffset += _incval;
372 void TOWNS_MEMORY::set_dma_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr)
374 uint64_t _start = (uint64_t)start;
375 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
377 _start &= ~(memory_map_mask());
378 _end &= ~(memory_map_mask());
380 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
381 const uint64_t _incval = memory_map_grain();
382 uint32_t realoffset = 0;
383 for(uint64_t addr = _start; addr < _end; addr += _incval) {
384 dma_memory_map_r[mapptr] = &(baseptr[realoffset]);
385 dma_devices_map_r[mapptr] = NULL;
386 realoffset += _incval;
391 void TOWNS_MEMORY::set_dma_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr)
393 uint64_t _start = (uint64_t)start;
394 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
396 _start &= ~(memory_map_mask());
397 _end &= ~(memory_map_mask());
399 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
400 const uint64_t _incval = memory_map_grain();
401 uint32_t realoffset = 0;
402 for(uint64_t addr = _start; addr < _end; addr += _incval) {
403 dma_memory_map_w[mapptr] = &(baseptr[realoffset]);
404 dma_devices_map_w[mapptr] = NULL;
405 realoffset += _incval;
410 void __FASTCALL TOWNS_MEMORY::set_dma_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
412 uint64_t _start = (uint64_t)start;
413 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
415 _start &= ~(memory_map_mask());
416 _end &= ~(memory_map_mask());
418 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
419 const uint64_t _incval = memory_map_grain();
420 uint32_t realoffset = 0;
421 for(uint64_t addr = _start; addr < _end; addr += _incval) {
422 dma_memory_map_r[mapptr] = NULL;
423 dma_devices_map_r[mapptr] = ptr;
424 __LIKELY_IF(baseaddress == UINT32_MAX) {
425 dma_devices_base_r[mapptr] = UINT32_MAX;
427 dma_devices_base_r[mapptr] = baseaddress + realoffset;
429 realoffset += _incval;
434 void __FASTCALL TOWNS_MEMORY::set_dma_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
436 uint64_t _start = (uint64_t)start;
437 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
439 _start &= ~(memory_map_mask());
440 _end &= ~(memory_map_mask());
442 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
443 const uint64_t _incval = memory_map_grain();
444 uint32_t realoffset = 0;
445 for(uint64_t addr = _start; addr < _end; addr += _incval) {
446 dma_memory_map_w[mapptr] = NULL;
447 dma_devices_map_w[mapptr] = ptr;
448 __LIKELY_IF(baseaddress == UINT32_MAX) {
449 dma_devices_base_w[mapptr] = UINT32_MAX;
451 dma_devices_base_w[mapptr] = baseaddress + realoffset;
453 realoffset += _incval;
458 void __FASTCALL TOWNS_MEMORY::set_dma_wait_r(uint32_t start, uint32_t end, int wait)
460 uint64_t _start = (uint64_t)start;
461 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
463 _start &= ~(memory_map_mask());
464 _end &= ~(memory_map_mask());
466 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
467 const uint64_t _incval = memory_map_grain();
468 uint32_t realoffset = 0;
469 for(uint64_t addr = _start; addr < _end; addr += _incval) {
470 dma_wait_map_w[mapptr] = wait;
475 void __FASTCALL TOWNS_MEMORY::set_dma_wait_w(uint32_t start, uint32_t end, int wait)
477 uint64_t _start = (uint64_t)start;
478 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
480 _start &= ~(memory_map_mask());
481 _end &= ~(memory_map_mask());
483 uint32_t mapptr = (uint32_t)(_start >> memory_map_shift());
484 const uint64_t _incval = memory_map_grain();
485 uint32_t realoffset = 0;
486 for(uint64_t addr = _start; addr < _end; addr += _incval) {
487 dma_wait_map_r[mapptr] = wait;
493 bool TOWNS_MEMORY::set_cpu_clock_by_wait()
495 uint32_t cpu_bak = cpu_clock_val;
496 cpu_clock_val = (is_faster_wait()) ?
497 get_cpu_clocks(d_cpu) : (16 * 1000 * 1000);
498 return ((cpu_clock_val != cpu_bak) ? true : false);
500 void TOWNS_MEMORY::set_wait_values()
502 uint32_t waitfactor = 0;
503 if(cpu_clock_val < get_cpu_clocks(d_cpu)) {
504 waitfactor = (uint32_t)(((double)get_cpu_clocks(d_cpu) / (double)cpu_clock_val) * 65536.0);
506 d_cpu->write_signal(SIG_CPU_WAIT_FACTOR, waitfactor, 0xffffffff);
509 void TOWNS_MEMORY::release()
511 // if(rd_table != NULL) free(rd_table);
512 // if(rd_dummy != NULL) free(rd_dummy);
513 // if(wr_table != NULL) free(wr_table);
514 // if(wr_dummy != NULL) free(wr_dummy);
516 if(extra_ram != NULL) {
522 void TOWNS_MEMORY::reset()
526 update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
527 is_compatible = true;
528 reset_happened = false;
530 nmi_vector_protect = false;
531 ankcg_enabled = false;
533 //config_page0c_0e(false, false, true); // VRAM, DICT, FORCE
535 config_page0c_0e(false, false, true); // VRAM, DICT, FORCE
536 config_page0f(true, true); // SYSROM, FORCE
539 set_cpu_clock_by_wait();
542 __LIKELY_IF(d_cpu != NULL) {
543 d_cpu->set_address_mask(0xffffffff);
546 uint8_t wrap_val = 0xff; // WRAP ON
547 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
552 void TOWNS_MEMORY::update_machine_features()
556 if(machine_id >= 0x0b00) { // After MA/MX/ME
557 reg_misc3 &= ~0x04; // DMACMD
559 if(machine_id >= 0x0700) { // After HR/HG
560 reg_misc3 &= ~0x08; // POFFEN
562 if(machine_id >= 0x0700) { // After HR/HG
563 reg_misc3 &= ~0x10; // Free run counter
565 if(machine_id >= 0x0700) { // After HR/HG
566 reg_misc3 &= ~0x20; // CRTPOWOFF (0022h)
568 if(machine_id >= 0x0700) { // After HR/HG
569 reg_misc3 &= ~0x40; // RCREN
571 if(machine_id >= 0x0700) { // After HR/HG
572 reg_misc3 &= ~0x80; // ENPOFF
575 if(machine_id >= 0x0500) { // After CX
582 uint8_t TOWNS_MEMORY::read_fmr_ports8(uint32_t addr)
585 __UNLIKELY_IF((addr & 0xffff) < 0xff80) {
586 return ram_pagec[addr & 0xffff];
589 __LIKELY_IF((addr & 0xffff) < 0xff88) {
590 __LIKELY_IF(d_planevram != NULL) {
591 val = d_planevram->read_memory_mapped_io8(addr & 0xffff);
594 } else if(((addr & 0xffff) >= 0xff94) && ((addr & 0xffff) < 0xff98)) {
595 __LIKELY_IF(d_font != NULL) {
596 val = d_font->read_io8(addr & 0xffff);
601 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
602 switch(addr & 0xffff) {
604 __LIKELY_IF(d_crtc != NULL) {
605 val = d_crtc->read_signal(SIG_TOWNS_CRTC_MMIO_CFF82H);
610 return (ankcg_enabled) ? 0x01 : 0x00;
615 __LIKELY_IF(d_font != NULL) {
616 val = d_font->read_io8(addr & 0xffff);
625 switch(addr & 0xffff) {
627 __LIKELY_IF(d_planevram != NULL) {
628 val = d_planevram->read_io8(addr);
635 __LIKELY_IF(d_font != NULL) {
636 return d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_LOW);
640 __LIKELY_IF(d_font != NULL) {
641 return d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_HIGH);
645 __LIKELY_IF(d_timer != NULL) {
646 d_timer->write_signal(SIG_TIMER_BEEP_ON, 1, 1);
650 __LIKELY_IF(d_planevram != NULL) {
651 val = d_planevram->read_memory_mapped_io8(addr);
655 __LIKELY_IF(d_planevram != NULL) {
656 val = d_planevram->read_io8(addr & 0xffff);
662 uint8_t TOWNS_MEMORY::read_sys_ports8(uint32_t addr)
666 switch(addr & 0xffff) {
667 case 0x0020: // Software reset ETC.
668 // reset cause register
669 val = ((software_reset) ? 1 : 0) | ((reset_happened) ? 2 : 0);
670 reset_happened = false;
671 software_reset = false;
672 __UNLIKELY_IF(d_cpu != NULL) {
673 d_cpu->set_shutdown_flag(0);
675 if((machine_id >= 0x0300) && ((machine_id & 0xff00) != 0x0400)) { // After UX
676 val = val | ((poff_status) ? 0x04 : 0x00);
681 // if(d_dmac != NULL) {
682 // val = d_dmac->read_signal(SIG_TOWNS_DMAC_ADDR_REG);
685 // 0024, 0025 : MISC3 + MISC4
694 if(machine_id >= 0x0500) { // After CX
695 val = (nmi_mask) ? 0x01 : 0x00;
700 // From FMTowns::MachineID() of TSUGARU,
701 // git 83d4ec2309ac9fcbb8c01f26061ff0d49c5321e4.
702 // if((config.dipswitch & TOWNS_DIPSW_PRETEND_I386) != 0) {
703 // val = ((machine_id & 0xf8) | 1);
705 val = ((machine_id & 0xf8) | (cpu_id & 7));
709 val = ((machine_id >> 8) & 0xff);
713 //bool __cs = (d_serialrom->read_signal(SIG_SERIALROM_CS) == 0);
714 bool __clk = (d_serialrom->read_signal(SIG_SERIALROM_CLK) != 0);
715 bool __reset = (d_serialrom->read_signal(SIG_SERIALROM_RESET) != 0);
716 bool __dat = (d_serialrom->read_signal(SIG_SERIALROM_DATA) != 0);
717 val = ((__reset) ? 0x80 : 0x00) | ((__clk) ? 0x40 : 0x00) | /*0x3e |*/ ((__dat) ? 0x01 : 0x00);
720 case 0x00c0: // Cache
722 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
723 // ToDo: Implement around cache.
724 // Modified by this register and (05ECh:bit0 / Wait register).
725 // Now, cache is always disabled.
726 // RPNH = 0 (Disabled) : Bit1
727 // CMEN = 0 (Disabled) : Bit0
731 case 0x00c2: // Cache Diagnostic
733 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
734 // ToDo: Implement cache disgnostic.
735 // SDMOD (Not diagnostic) : Bit3
739 case 0x0400: // Resolution:
742 case 0x0404: // System Status Reg.
743 val = (dma_is_vram) ? 0x7f : 0xff;
744 // val = (dma_is_vram) ? 0x00 : 0x80;
747 val = (select_d0_dict) ? 0x01 : 0x00;
748 val |= ((select_d0_rom) ? 0x00 : 0x02);
751 // val = (extra_nmi_mask) ? 0xf7 : 0xff;
752 val = (extra_nmi_mask) ? 0x00 : 0x08;
755 // val = (extra_nmi_val) ? 0xff : 0xf7;
756 val = (extra_nmi_val) ? 0x08 : 0x00;
759 if(machine_id < 0x0200) { // Towns 1/2
760 val = wait_register_older;
764 if(machine_id >= 0x0200) { // i386
765 val = wait_register_ram;
769 if(machine_id >= 0x0200) { // i386
770 val = wait_register_vram;
774 // After Towns1F/2F/1H/2H
776 uint16_t nid = machine_id & 0xff00;
778 val = (extram_size >> 20) & 0x7f; // MAX 128MB
779 } else if(nid >= 0x0900) { // UR,MA,MX,ME,MF
780 val = (extram_size >> 20) & 0x1f; // MAX 32MB
781 } else if(nid == 0x0800) { // HG
782 val = (extram_size >> 20) & 0x0f; // MAX 15MB
783 } else if(nid == 0x0700) { // HR
784 val = (extram_size >> 20) & 0x1f; // MAX 32MB
785 } else if(nid >= 0x0200) { // 2nd GEN,3rd Gen, UX/UG, CX
786 val = (extram_size >> 20) & 0x0f; // MAX 15MB
788 val = 0xff; // NOT SUPPORTED
794 if(machine_id >= 0x0200) { // 05ec
795 val = ((is_faster_wait()) ? 0x01 : 0x00);
799 if(machine_id >= 0x0700) { // 05ed
800 uint32_t clk = get_cpu_clocks(d_cpu);
801 clk = clk / (1000 * 1000);
802 __UNLIKELY_IF(clk < 16) clk = 16;
803 __UNLIKELY_IF(clk > 127) clk = 127; // ToDo
808 if(machine_id >= 0x0700) { // After HR/HG
809 val = (is_compatible) ? 0x00 : 0x01;
819 // Address (TOWNS BASIC):
820 // 0x0020 - 0x0022, 0x0030-0x0031,
824 // 0x05ec (Wait register)
825 // 0x05ed (CPU SPEED REGISTER)
826 // Is set extra NMI (0x05c0 - 0x05c2)?
827 uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
829 // uint32_t val = 0x00; // MAY NOT FILL to "1" for unused bit 20200129 K.O
830 __LIKELY_IF((addr & 0xffff) >= 0xff80) {
831 return read_fmr_ports8(addr & 0xffff);
833 return read_sys_ports8(addr);
836 void TOWNS_MEMORY::write_fmr_ports8(uint32_t addr, uint32_t data)
838 __UNLIKELY_IF((addr & 0xffff) < 0xff80) {
839 ram_pagec[addr & 0xffff] = data;
843 __LIKELY_IF((addr & 0xffff) < 0xff88) {
844 __LIKELY_IF(d_planevram != NULL) {
845 d_planevram->write_io8(addr & 0xffff, data);
848 } else if(((addr & 0xffff) >= 0xff94) && ((addr & 0xffff) < 0xff98)) {
849 __LIKELY_IF(d_font != NULL) {
850 d_font->write_io8(addr & 0xffff, data);
855 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
856 switch(addr & 0xffff) {
858 __LIKELY_IF(d_font != NULL) {
859 d_font->write_io8(addr & 0xffff, data);
866 switch(addr & 0xffff) {
868 __LIKELY_IF(d_font != NULL) {
869 d_font->write_signal(SIG_TOWNS_FONT_KANJI_HIGH, data, 0xff);
873 __LIKELY_IF(d_font != NULL) {
874 d_font->write_signal(SIG_TOWNS_FONT_KANJI_LOW, data, 0xff);
881 __LIKELY_IF(d_timer != NULL) {
882 d_timer->write_signal(SIG_TIMER_BEEP_ON, 0, 1);
887 bool _b = ankcg_enabled;
888 ankcg_enabled = ((data & 1) != 0) ? true : false;
892 __LIKELY_IF(d_planevram != NULL) {
893 d_planevram->write_io8(addr & 0xffff, data);
896 __LIKELY_IF(d_planevram != NULL) {
897 d_planevram->write_io8(addr & 0xffff, data);
902 void TOWNS_MEMORY::write_sys_ports8(uint32_t addr, uint32_t data)
904 switch(addr & 0xffff) {
905 case 0x0020: // Software reset ETC.
906 // reset cause register
907 if((data & 0x80) != 0) {
908 nmi_vector_protect = true;
910 nmi_vector_protect = false;
912 if((data & 0x01) != 0) {
913 software_reset = true;
915 software_reset = false;
918 if((data & 0x40) != 0) {
920 // __LIKELY_IF(d_cpu != NULL) {
921 // d_cpu->set_shutdown_flag(1);
923 // Todo: Implement true power off.
924 // emu->notify_power_off();
929 // __LIKELY_IF(d_cpu != NULL) {
930 // d_cpu->set_shutdown_flag(0);
934 if((software_reset) || (poff_status)){
935 // __LIKELY_IF(d_cpu != NULL) {
938 uint8_t wrap_val = 0xff; // WRAP ON
939 __LIKELY_IF(d_dmac != NULL) {
940 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
943 __LIKELY_IF(d_cpu != NULL) {
944 d_cpu->set_shutdown_flag(1);
946 // Todo: Implement true power off.
947 emu->notify_power_off();
952 // Towns SEEMS to not set addreess mask (a.k.a A20 mask). 20200131 K.O
955 if((data & 0x40) != 0) {
956 __LIKELY_IF(d_cpu != NULL) {
957 d_cpu->set_shutdown_flag(1);
959 // Todo: Implement true power off.
961 emu->notify_power_off();
968 //if((d_dmac != NULL) && (machine_id >= 0x0b00)) { // After MA/MX/ME
969 // d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, data, 0xff);
973 d_serialrom->write_signal(SIG_SERIALROM_CS, ~data, 0x20);
974 d_serialrom->write_signal(SIG_SERIALROM_CLK, data, 0x40);
975 d_serialrom->write_signal(SIG_SERIALROM_RESET, data, 0x80);
977 case 0x0404: // System Status Reg.
979 config_page0c_0e(((data & 0x80) == 0) ? true : false, select_d0_dict, false); // VRAM, DICT, FORCE
984 bool is_dict, is_sysrom;
985 is_dict = ((data & 0x01) != 0) ? true : false;
986 is_sysrom = ((data & 0x02) == 0) ? true : false;
987 config_page0c_0e(dma_is_vram, is_dict, false);
988 config_page0f(is_sysrom, false);
992 extra_nmi_mask = ((data & 0x08) == 0);
996 if(machine_id < 0x0200) { // Towns 1/2
997 uint8_t nval_bak = wait_register_older & 0x07;
998 uint8_t nval = data & 0x07;
999 if(nval < 1) nval = 1;
1000 mem_wait_val = nval;
1001 vram_wait_val = nval + 3; // OK?
1002 if(vram_wait_val > 6) {
1005 wait_register_older = (data & 0xf8) | nval;
1006 cpu_clock_val = 16 * 1000 * 1000;
1007 if(nval_bak != nval) {
1008 set_cpu_clock_by_wait();
1014 if(machine_id >= 0x0200) { // After Towns 1H/2F. Hidden wait register.
1015 uint8_t vram_bak = vram_wait_val;
1016 uint8_t mem_bak = mem_wait_val;
1018 uint8_t nval = data & 7;
1019 if(machine_id <= 0x0200) { // Towns 1H/2F.
1020 if(nval < 1) nval = 1;
1022 if(nval > 6) nval = 6;
1023 mem_wait_val = nval;
1024 wait_register_ram = (data & 0xf8) | nval;
1028 wait_register_ram = data;
1030 if((vram_bak != vram_wait_val) || (mem_bak != mem_wait_val)) {
1031 set_cpu_clock_by_wait();
1037 if(machine_id >= 0x0200) { // After Towns 1H/2F. Hidden wait register.
1038 uint8_t mem_bak = mem_wait_val;
1039 uint8_t vram_bak = vram_wait_val;
1041 uint8_t nval = data & 7;
1042 if(machine_id <= 0x0200) { // Towns 1H/2F.
1043 if(nval < 1) nval = 1;
1045 if(nval > 6) nval = 6;
1046 vram_wait_val = nval;
1047 wait_register_vram = (data & 0xf8) | nval;
1051 wait_register_vram = data;
1053 if((vram_bak != vram_wait_val) || (mem_bak != mem_wait_val)) {
1054 set_cpu_clock_by_wait();
1061 if(machine_id >= 0x0500) { // Towns2 CX :
1062 uint8_t mem_bak = mem_wait_val;
1063 uint8_t vram_bak = vram_wait_val;
1064 vram_wait_val = ((data & 0x01) != 0) ? 0 : 6;
1065 mem_wait_val = ((data & 0x01) != 0) ? 0 : 6;
1066 wait_register_ram = mem_wait_val;
1067 wait_register_vram = vram_wait_val;
1068 if((mem_bak != mem_wait_val) || (vram_bak != vram_wait_val)) {
1069 set_cpu_clock_by_wait();
1076 if(machine_id >= 0x0700) { // After HR/HG
1077 is_compatible = ((data & 0x01) == 0x00) ? true : false;
1078 __LIKELY_IF(d_crtc != NULL) {
1079 d_crtc->write_signal(SIG_TOWNS_CRTC_COMPATIBLE_MMIO, (is_compatible) ? 0xffffffff : 0x00000000, 0xffffffff);
1087 void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
1089 __LIKELY_IF((addr & 0xffff) >= 0xff80) {
1090 write_fmr_ports8(addr & 0xffff, data);
1093 write_sys_ports8(addr, data);
1097 uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int* wait)
1101 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1102 uint32_t offset = addr & memory_map_mask();
1103 __LIKELY_IF(mmio_memory_map_r[mapptr] != NULL) {
1104 uint8_t* ptr = mmio_memory_map_r[mapptr];
1106 } else if(mmio_devices_map_r[mapptr] != NULL) {
1107 DEVICE* dev = mmio_devices_map_r[mapptr];
1108 __LIKELY_IF(mmio_devices_base_r[mapptr] == UINT32_MAX) {
1109 val = dev->read_memory_mapped_io8(addr);
1111 offset += mmio_devices_base_r[mapptr];
1112 val = dev->read_memory_mapped_io8(offset);
1115 __LIKELY_IF(wait != NULL) {
1116 waitval = mmio_wait_map_r[mapptr];
1117 __LIKELY_IF(waitval < 0) {
1118 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1125 uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int* wait)
1127 uint16_t val = 0xffff;
1129 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1130 uint32_t offset = addr & memory_map_mask();
1131 __UNLIKELY_IF(offset == memory_map_mask()) {
1134 w.b.l = read_data8w(addr , &wait1);
1135 w.b.h = read_data8w(addr + 1, &wait2);
1136 __LIKELY_IF(wait != NULL) {
1138 //*wait = wait1 + wait2;
1142 __LIKELY_IF(mmio_memory_map_r[mapptr] != NULL) {
1143 uint8_t* ptr = mmio_memory_map_r[mapptr];
1144 ptr = &(ptr[offset]);
1145 #ifdef __BIG_ENDIAN__
1147 w.read_2bytes_le_from(ptr);
1150 __LIKELY_IF((offset & 1) == 0) {
1151 uint16_t* q = (uint16_t*)ptr;
1155 w.read_2bytes_le_from(ptr);
1159 } else if(mmio_devices_map_r[mapptr] != NULL) {
1160 DEVICE* dev = mmio_devices_map_r[mapptr];
1161 __LIKELY_IF(mmio_devices_base_r[mapptr] == UINT32_MAX) {
1162 val = dev->read_memory_mapped_io16(addr);
1164 offset += mmio_devices_base_r[mapptr];
1165 val = dev->read_memory_mapped_io16(offset);
1168 __LIKELY_IF(wait != NULL) {
1169 waitval = mmio_wait_map_r[mapptr];
1170 __LIKELY_IF(waitval < 0) {
1171 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1173 //__LIKELY_IF((offset & 1) == 0) {
1176 // *wait = waitval * 2;
1182 uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int* wait)
1184 uint32_t val = 0xffffffff;
1186 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1187 uint32_t offset = addr & memory_map_mask();
1188 __UNLIKELY_IF(offset > (memory_map_mask() - 3)) {
1191 int wait1, wait2, wait3;
1192 switch(offset & 3) {
1195 d.b.l = read_data8w (addr , &wait1);
1196 w.w = read_data16w(addr + 1, &wait2);
1197 d.b.h3 = read_data8w (addr + 3, &wait3);
1198 __LIKELY_IF(wait != NULL) {
1200 //*wait = wait1 + wait2 + wait3;
1204 d.w.l = read_data16w(addr , &wait1);
1205 d.w.h = read_data16w(addr + 2, &wait2);
1206 __LIKELY_IF(wait != NULL) {
1208 //*wait = wait1 + wait2;
1211 __LIKELY_IF(wait != NULL) {
1212 waitval = mmio_wait_map_r[mapptr];
1213 __LIKELY_IF(waitval < 0) {
1214 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1217 //*wait = wait1 + wait2;
1222 __LIKELY_IF(mmio_memory_map_r[mapptr] != NULL) {
1223 uint8_t* ptr = mmio_memory_map_r[mapptr];
1224 ptr = &(ptr[offset]);
1225 #ifdef __BIG_ENDIAN__
1227 d.read_4bytes_le_from(ptr);
1230 __LIKELY_IF((offset & 3) == 0) {
1231 uint32_t* q = (uint32_t*)ptr;
1235 d.read_4bytes_le_from(ptr);
1239 } else if(mmio_devices_map_r[mapptr] != NULL) {
1240 DEVICE* dev = mmio_devices_map_r[mapptr];
1241 __LIKELY_IF(mmio_devices_base_r[mapptr] == UINT32_MAX) {
1244 offset += mmio_devices_base_r[mapptr];
1246 val = dev->read_memory_mapped_io32(offset);
1248 __LIKELY_IF(wait != NULL) {
1249 waitval = mmio_wait_map_r[mapptr];
1250 __LIKELY_IF(waitval < 0) {
1251 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1253 //__LIKELY_IF((offset & 1) == 0) {
1256 // *wait = waitval * 2;
1262 uint32_t TOWNS_MEMORY::read_dma_data8w(uint32_t addr, int* wait)
1266 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1267 uint32_t offset = addr & memory_map_mask();
1268 __LIKELY_IF((dma_memory_map_r[mapptr] == NULL) && (dma_devices_map_r[mapptr] == NULL)) {
1269 return read_data8w(addr, wait);
1272 __LIKELY_IF(dma_memory_map_r[mapptr] != NULL) {
1273 uint8_t* ptr = dma_memory_map_r[mapptr];
1275 } else if(dma_devices_map_r[mapptr] != NULL) {
1276 DEVICE* dev = dma_devices_map_r[mapptr];
1277 __LIKELY_IF(dma_devices_base_r[mapptr] == UINT32_MAX) {
1278 val = dev->read_memory_mapped_io8(addr);
1280 offset += dma_devices_base_r[mapptr];
1281 val = dev->read_memory_mapped_io8(offset);
1284 __LIKELY_IF(wait != NULL) {
1285 waitval = dma_wait_map_r[mapptr];
1286 __LIKELY_IF(waitval < 0) {
1287 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1294 uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
1296 uint16_t val = 0xffff;
1298 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1299 uint32_t offset = addr & memory_map_mask();
1300 __UNLIKELY_IF(offset == memory_map_mask()) {
1303 w.b.l = read_data8w(addr , &wait1);
1304 w.b.h = read_data8w(addr + 1, &wait2);
1305 __LIKELY_IF(wait != NULL) {
1307 //*wait = wait1 + wait2;
1311 __LIKELY_IF((dma_memory_map_r[mapptr] == NULL) && (dma_devices_map_r[mapptr] == NULL)) {
1312 return read_data16w(addr, wait);
1314 __LIKELY_IF(dma_memory_map_r[mapptr] != NULL) {
1315 uint8_t* ptr = dma_memory_map_r[mapptr];
1316 ptr = &(ptr[offset]);
1317 #ifdef __BIG_ENDIAN__
1319 w.read_2bytes_le_from(ptr);
1322 __LIKELY_IF((offset & 1) == 0) {
1323 uint16_t* q = (uint16_t*)ptr;
1327 w.read_2bytes_le_from(ptr);
1331 } else if(dma_devices_map_r[mapptr] != NULL) {
1332 DEVICE* dev = dma_devices_map_r[mapptr];
1333 __LIKELY_IF(dma_devices_base_r[mapptr] == UINT32_MAX) {
1336 offset += dma_devices_base_r[mapptr];
1338 val = dev->read_memory_mapped_io16(offset);
1340 __LIKELY_IF(wait != NULL) {
1341 waitval = dma_wait_map_r[mapptr];
1342 __LIKELY_IF(waitval < 0) {
1343 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1345 //__LIKELY_IF((offset & 1) == 0) {
1348 // *wait = waitval * 2;
1354 uint32_t TOWNS_MEMORY::read_dma_data32w(uint32_t addr, int* wait)
1356 uint32_t val = 0xffffffff;
1358 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1359 uint32_t offset = addr & memory_map_mask();
1360 __UNLIKELY_IF(offset > (memory_map_mask() - 3)) {
1363 int wait1, wait2, wait3;
1364 switch(offset & 3) {
1367 d.b.l = read_dma_data8w (addr , &wait1);
1368 w.w = read_dma_data16w(addr + 1, &wait2);
1369 d.b.h3 = read_dma_data8w (addr + 3, &wait3);
1370 __LIKELY_IF(wait != NULL) {
1372 //*wait = wait1 + wait2 + wait3;
1376 d.w.l = read_dma_data16w(addr , &wait1);
1377 d.w.h = read_dma_data16w(addr + 2, &wait2);
1378 __LIKELY_IF(wait != NULL) {
1380 //*wait = wait1 + wait2;
1383 __LIKELY_IF(wait != NULL) {
1384 waitval = dma_wait_map_r[mapptr];
1385 __LIKELY_IF(waitval < 0) {
1386 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1389 //*wait = wait1 + wait2;
1394 __LIKELY_IF((dma_memory_map_r[mapptr] == NULL) && (dma_devices_map_r[mapptr] == NULL)) {
1395 return read_data32w(addr, wait);
1397 __LIKELY_IF(dma_memory_map_r[mapptr] != NULL) {
1398 uint8_t* ptr = dma_memory_map_r[mapptr];
1399 ptr = &(ptr[offset]);
1400 #ifdef __BIG_ENDIAN__
1402 d.read_4bytes_le_from(ptr);
1405 __LIKELY_IF((offset & 3) == 0) {
1406 uint32_t* q = (uint32_t*)ptr;
1410 d.read_4bytes_le_from(ptr);
1414 } else if(dma_devices_map_r[mapptr] != NULL) {
1415 DEVICE* dev = dma_devices_map_r[mapptr];
1416 __LIKELY_IF(dma_devices_base_r[mapptr] == UINT32_MAX) {
1419 offset += mmio_devices_base_r[mapptr];
1421 val = dev->read_memory_mapped_io32(offset);
1423 __LIKELY_IF(wait != NULL) {
1424 waitval = dma_wait_map_r[mapptr];
1425 __LIKELY_IF(waitval < 0) {
1426 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1428 //__LIKELY_IF((offset & 1) == 0) {
1431 // *wait = waitval * 2;
1438 void TOWNS_MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
1441 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1442 uint32_t offset = addr & memory_map_mask();
1443 __LIKELY_IF(mmio_memory_map_w[mapptr] != NULL) {
1444 uint8_t* ptr = mmio_memory_map_w[mapptr];
1446 } else if(mmio_devices_map_w[mapptr] != NULL) {
1447 DEVICE* dev = mmio_devices_map_w[mapptr];
1448 __LIKELY_IF(mmio_devices_base_w[mapptr] == UINT32_MAX) {
1449 dev->write_memory_mapped_io8(addr, data);
1451 offset += mmio_devices_base_w[mapptr];
1452 dev->write_memory_mapped_io8(offset, data);
1455 __LIKELY_IF(wait != NULL) {
1456 waitval = mmio_wait_map_w[mapptr];
1457 __LIKELY_IF(waitval < 0) {
1458 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1466 void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int* wait)
1468 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1469 uint32_t offset = addr & memory_map_mask();
1471 __UNLIKELY_IF(offset == memory_map_mask()) {
1476 write_data8w(addr , d.b.l, &wait1);
1477 write_data8w(addr + 1, d.b.h, &wait2);
1478 __LIKELY_IF(wait != NULL) {
1479 *wait = wait1 + wait2;
1483 __LIKELY_IF(mmio_memory_map_w[mapptr] != NULL) {
1484 uint8_t* ptr = mmio_memory_map_w[mapptr];
1485 ptr = &(ptr[offset]);
1486 #ifdef __BIG_ENDIAN__
1489 d.write_2bytes_le_to(ptr);
1491 __LIKELY_IF((offset & 1) == 0) { // Aligned
1492 uint16_t* q = (uint16_t*)ptr;
1497 d.write_2bytes_le_to(ptr);
1500 } else if(mmio_devices_map_w[mapptr] != NULL) {
1501 DEVICE* dev = mmio_devices_map_w[mapptr];
1502 __LIKELY_IF(mmio_devices_base_w[mapptr] == UINT32_MAX) {
1505 offset += mmio_devices_base_w[mapptr];
1507 dev->write_memory_mapped_io16(offset, data);
1509 __LIKELY_IF(wait != NULL) {
1510 waitval = mmio_wait_map_w[mapptr];
1511 __LIKELY_IF(waitval < 0) {
1512 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1514 //#if _MEMORY_BUS_WIDTH == 16
1515 //__UNLIKELY_IF((offset & 1) != 0) { // Penalty; maybe not need to.
1520 //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
1530 void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int* wait)
1532 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1533 uint32_t offset = addr & memory_map_mask();
1535 __UNLIKELY_IF(offset > (memory_map_mask() - 3)) {
1539 int wait1, wait2, wait3;
1541 switch(offset & 3) {
1544 write_data8w(addr , d.b.l, &wait1);
1547 write_data16w(addr + 1, w.w, &wait2);
1548 write_data8w(addr + 3, d.b.h3, &wait3);
1549 __LIKELY_IF(wait != NULL) {
1550 *wait = wait1; // WORKAROUND
1551 //#if _MEMORY_BUS_WIDTH == 16
1552 //*wait = wait1 + wait2 + wait3; // OK?
1554 //*wait = wait1 + wait3; // OK?
1559 write_data16w(addr , d.w.l, &wait1);
1560 write_data16w(addr + 2, d.w.h, &wait2);
1561 __LIKELY_IF(wait != NULL) {
1562 *wait = wait1; // WORKAROUND
1563 //#if _MEMORY_BUS_WIDTH == 16
1564 //*wait = wait1 + wait2 + wait3; // OK?
1566 //*wait = wait1 + wait3; // OK?
1571 __LIKELY_IF(wait != NULL) {
1572 waitval = mmio_wait_map_w[mapptr];
1573 __LIKELY_IF(waitval < 0) {
1574 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1576 *wait = waitval; // WORKAROUND
1577 //#if _MEMORY_BUS_WIDTH == 16
1578 //*wait = wait1 + wait2 + wait3; // OK?
1580 //*wait = wait1 + wait3; // OK?
1588 __LIKELY_IF(mmio_memory_map_w[mapptr] != NULL) {
1589 uint8_t* ptr = mmio_memory_map_w[mapptr];
1590 ptr = &(ptr[offset]);
1591 #ifdef __BIG_ENDIAN__
1594 d.write_4bytes_le_to(ptr);
1596 __LIKELY_IF((offset & 3) == 0) { // Aligned
1597 uint32_t* q = (uint32_t*)ptr;
1602 d.write_4bytes_le_to(ptr);
1605 } else if(mmio_devices_map_w[mapptr] != NULL) {
1606 DEVICE* dev = mmio_devices_map_w[mapptr];
1607 __LIKELY_IF(mmio_devices_base_w[mapptr] == UINT32_MAX) {
1610 offset += mmio_devices_base_w[mapptr];
1612 dev->write_memory_mapped_io32(offset, data);
1614 __LIKELY_IF(wait != NULL) {
1615 waitval = mmio_wait_map_w[mapptr];
1616 __LIKELY_IF(waitval < 0) {
1617 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1619 //#if _MEMORY_BUS_WIDTH == 16
1620 //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
1625 //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
1634 void TOWNS_MEMORY::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
1637 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1638 uint32_t offset = addr & memory_map_mask();
1639 __LIKELY_IF((dma_memory_map_w[mapptr] == NULL) && (dma_devices_map_w[mapptr] == NULL)) {
1640 write_data8w(addr, data, wait);
1643 __LIKELY_IF(dma_memory_map_w[mapptr] != NULL) {
1644 uint8_t* ptr = dma_memory_map_w[mapptr];
1646 } else if(dma_devices_map_w[mapptr] != NULL) {
1647 DEVICE* dev = dma_devices_map_w[mapptr];
1648 __LIKELY_IF(dma_devices_base_w[mapptr] == UINT32_MAX) {
1649 dev->write_memory_mapped_io8(addr, data);
1651 offset += dma_devices_base_w[mapptr];
1652 dev->write_memory_mapped_io8(offset, data);
1655 __LIKELY_IF(wait != NULL) {
1656 waitval = dma_wait_map_w[mapptr];
1657 __LIKELY_IF(waitval < 0) {
1658 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1665 void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
1667 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1668 uint32_t offset = addr & memory_map_mask();
1670 __UNLIKELY_IF(offset == memory_map_mask()) {
1675 write_dma_data8w(addr , d.b.l, &wait1);
1676 write_dma_data8w(addr + 1, d.b.h, &wait2);
1677 __LIKELY_IF(wait != NULL) {
1678 *wait = wait1 + wait2;
1682 __LIKELY_IF((dma_memory_map_w[mapptr] == NULL) && (dma_devices_map_w[mapptr] == NULL)) {
1683 // ToDO: BEYOND THE BOUNDARY.
1684 write_data16w(addr, data, wait);
1687 __LIKELY_IF(dma_memory_map_w[mapptr] != NULL) {
1688 uint8_t* ptr = dma_memory_map_w[mapptr];
1689 ptr = &(ptr[offset]);
1690 #ifdef __BIG_ENDIAN__
1693 d.write_2bytes_le_to(ptr);
1695 __LIKELY_IF((offset & 1) == 0) { // Aligned
1696 uint16_t* q = (uint16_t*)ptr;
1701 d.write_2bytes_le_to(ptr);
1704 } else if(dma_devices_map_w[mapptr] != NULL) {
1705 DEVICE* dev = dma_devices_map_w[mapptr];
1706 __LIKELY_IF(dma_devices_base_w[mapptr] == UINT32_MAX) {
1709 offset += dma_devices_base_w[mapptr];
1711 dev->write_memory_mapped_io16(offset, data);
1713 __LIKELY_IF(wait != NULL) {
1714 waitval = dma_wait_map_w[mapptr];
1715 __LIKELY_IF(waitval < 0) {
1716 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1718 //#if _MEMORY_BUS_WIDTH == 16
1719 //__UNLIKELY_IF((offset & 1) != 0) { // Penalty; maybe not need to.
1724 //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
1734 void TOWNS_MEMORY::write_dma_data32w(uint32_t addr, uint32_t data, int* wait)
1736 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1737 uint32_t offset = addr & memory_map_mask();
1739 __UNLIKELY_IF(offset > (memory_map_mask() - 3)) {
1743 int wait1, wait2, wait3;
1745 switch(offset & 3) {
1748 write_dma_data8w(addr , d.b.l, &wait1);
1751 write_dma_data16w(addr + 1, w.w, &wait2);
1752 write_dma_data8w(addr + 3, d.b.h3, &wait3);
1753 __LIKELY_IF(wait != NULL) {
1754 *wait = wait1; // WORKAROUND
1755 //#if _MEMORY_BUS_WIDTH == 16
1756 //*wait = wait1 + wait2 + wait3; // OK?
1758 //*wait = wait1 + wait3; // OK?
1763 write_dma_data16w(addr , d.w.l, &wait1);
1764 write_dma_data16w(addr + 2, d.w.h, &wait2);
1765 __LIKELY_IF(wait != NULL) {
1766 *wait = wait1; // WORKAROUND
1767 //#if _MEMORY_BUS_WIDTH == 16
1768 //*wait = wait1 + wait2 + wait3; // OK?
1770 //*wait = wait1 + wait3; // OK?
1775 __LIKELY_IF(wait != NULL) {
1776 waitval = dma_wait_map_w[mapptr];
1777 __LIKELY_IF(waitval < 0) {
1778 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1780 *wait = waitval; // WORKAROUND
1781 //#if _MEMORY_BUS_WIDTH == 16
1782 //*wait = wait1 + wait2 + wait3; // OK?
1784 //*wait = wait1 + wait3; // OK?
1792 __LIKELY_IF((dma_memory_map_w[mapptr] == NULL) && (dma_devices_map_w[mapptr] == NULL)) {
1793 // ToDO: BEYOND THE BOUNDARY.
1794 write_data32w(addr, data, wait);
1797 __LIKELY_IF(dma_memory_map_w[mapptr] != NULL) {
1798 uint8_t* ptr = dma_memory_map_w[mapptr];
1799 ptr = &(ptr[offset]);
1800 #ifdef __BIG_ENDIAN__
1803 d.write_4bytes_le_to(ptr);
1805 __LIKELY_IF((offset & 3) == 0) { // Aligned
1806 uint32_t* q = (uint32_t*)ptr;
1811 d.write_4bytes_le_to(ptr);
1814 } else if(dma_devices_map_w[mapptr] != NULL) {
1815 DEVICE* dev = dma_devices_map_w[mapptr];
1816 __LIKELY_IF(dma_devices_base_w[mapptr] == UINT32_MAX) {
1819 offset += dma_devices_base_w[mapptr];
1821 dev->write_memory_mapped_io32(offset, data);
1823 __LIKELY_IF(wait != NULL) {
1824 waitval = dma_wait_map_w[mapptr];
1825 __LIKELY_IF(waitval < 0) {
1826 waitval = (waitval == WAITVAL_VRAM) ? vram_wait_val : mem_wait_val;
1828 //#if _MEMORY_BUS_WIDTH == 16
1829 //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
1834 //__UNLIKELY_IF((offset & 3) != 0) { // Penalty; maybe not need to.
1845 uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
1847 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1848 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1851 __LIKELY_IF(addr >= 0x000cc000) {
1853 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
1854 return read_fmr_ports8(addr);
1856 return ram_pagec[addr & 0x0000ffff];
1859 if(addr < 0x000ca000) { //SPRITE
1860 __LIKELY_IF(d_sprite != NULL) {
1861 return d_sprite->read_memory_mapped_io8(addr);
1866 __LIKELY_IF(d_font != NULL) {
1867 return d_font->read_memory_mapped_io8(addr);
1870 __LIKELY_IF(d_sprite != NULL) {
1871 return d_sprite->read_memory_mapped_io8(addr);
1877 uint32_t TOWNS_MEMORY::read_memory_mapped_io16(uint32_t addr)
1879 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1880 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1883 __LIKELY_IF(addr >= 0x000cc000) {
1886 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
1887 w.b.l = read_fmr_ports8(addr);
1888 w.b.h = read_fmr_ports8(addr + 1);
1890 w.read_2bytes_le_from(&(ram_pagec[addr & 0x0000ffff]));
1895 if(addr < 0x000ca000) { //SPRITE
1896 __LIKELY_IF(d_sprite != NULL) {
1897 return d_sprite->read_memory_mapped_io16(addr);
1902 __LIKELY_IF(d_font != NULL) {
1903 return d_font->read_memory_mapped_io16(addr);
1906 __LIKELY_IF(d_sprite != NULL) {
1907 return d_sprite->read_memory_mapped_io16(addr);
1913 uint32_t TOWNS_MEMORY::read_memory_mapped_io32(uint32_t addr)
1915 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1916 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1919 __LIKELY_IF(addr >= 0x000cc000) {
1922 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
1923 d.b.l = read_fmr_ports8(addr);
1924 d.b.h = read_fmr_ports8(addr + 1);
1925 d.b.h2 = read_fmr_ports8(addr + 2);
1926 d.b.h3 = read_fmr_ports8(addr + 3);
1928 d.read_4bytes_le_from(&(ram_pagec[addr & 0x0000ffff]));
1933 if(addr < 0x000ca000) { //SPRITE
1934 __LIKELY_IF(d_sprite != NULL) {
1935 return d_sprite->read_memory_mapped_io32(addr);
1940 __LIKELY_IF(d_font != NULL) {
1941 return d_font->read_memory_mapped_io32(addr);
1944 __LIKELY_IF(d_sprite != NULL) {
1945 return d_sprite->read_memory_mapped_io32(addr);
1952 void TOWNS_MEMORY::write_memory_mapped_io8(uint32_t addr, uint32_t data)
1954 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1955 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1958 __LIKELY_IF(addr >= 0x000cc000) {
1960 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
1961 write_fmr_ports8(addr, data);
1964 ram_pagec[addr & 0x0000ffff] = data;
1968 if(addr < 0x000ca000) { //SPRITE
1969 __LIKELY_IF(d_sprite != NULL) {
1970 d_sprite->write_memory_mapped_io8(addr, data);
1974 if(!(ankcg_enabled)) {
1975 __LIKELY_IF(d_sprite != NULL) {
1976 d_sprite->write_memory_mapped_io8(addr, data);
1982 void TOWNS_MEMORY::write_memory_mapped_io16(uint32_t addr, uint32_t data)
1984 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1985 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1988 __LIKELY_IF(addr >= 0x000cc000) {
1992 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
1993 write_fmr_ports8(addr , w.b.l);
1994 write_fmr_ports8(addr + 1, w.b.h);
1997 w.write_2bytes_le_to(&(ram_pagec[addr & 0x0000ffff]));
2001 if(addr < 0x000ca000) { //SPRITE
2002 __LIKELY_IF(d_sprite != NULL) {
2003 d_sprite->write_memory_mapped_io16(addr, data);
2007 if(!(ankcg_enabled)) {
2008 __LIKELY_IF(d_sprite != NULL) {
2009 d_sprite->write_memory_mapped_io16(addr, data);
2015 void TOWNS_MEMORY::write_memory_mapped_io32(uint32_t addr, uint32_t data)
2017 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
2018 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
2021 __LIKELY_IF(addr >= 0x000cc000) {
2025 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
2026 write_fmr_ports8(addr , d.b.l);
2027 write_fmr_ports8(addr + 1, d.b.h);
2028 write_fmr_ports8(addr + 2, d.b.h2);
2029 write_fmr_ports8(addr + 3, d.b.h3);
2032 d.write_4bytes_le_to(&(ram_pagec[addr & 0x0000ffff]));
2036 if(addr < 0x000ca000) { //SPRITE
2037 __LIKELY_IF(d_sprite != NULL) {
2038 d_sprite->write_memory_mapped_io32(addr, data);
2042 if(!(ankcg_enabled)) {
2043 __LIKELY_IF(d_sprite != NULL) {
2044 d_sprite->write_memory_mapped_io32(addr, data);
2052 void TOWNS_MEMORY::write_signal(int ch, uint32_t data, uint32_t mask)
2054 if(ch == SIG_MEMORY_EXTNMI) {
2055 extra_nmi_val = ((data & mask) != 0);
2056 if(!(extra_nmi_mask)) {
2058 __LIKELY_IF(d_cpu != NULL) {
2059 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
2062 } else if(ch == SIG_CPU_NMI) {
2065 __LIKELY_IF(d_cpu != NULL) {
2066 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
2069 } else if(ch == SIG_CPU_IRQ) {
2070 __LIKELY_IF(d_cpu != NULL) {
2071 d_cpu->write_signal(SIG_CPU_IRQ, data, mask);
2073 } else if(ch == SIG_CPU_BUSREQ) {
2074 __LIKELY_IF(d_cpu != NULL) {
2075 d_cpu->write_signal(SIG_CPU_BUSREQ, data, mask);
2077 } else if(ch == SIG_I386_A20) {
2078 __LIKELY_IF(d_cpu != NULL) {
2079 d_cpu->write_signal(SIG_I386_A20, data, mask);
2081 } else if(ch == SIG_FMTOWNS_NOTIFY_RESET) {
2082 out_debug_log("RESET FROM CPU!!!\n");
2083 reset_happened = true;
2085 nmi_vector_protect = false;
2086 ankcg_enabled = false;
2088 config_page0c_0e(true, false, true);
2089 config_page0f(true, true);
2090 reset_wait_values();
2093 __LIKELY_IF(d_cpu != NULL) {
2094 d_cpu->set_address_mask(0xffffffff);
2096 __LIKELY_IF(d_dmac != NULL) {
2097 uint8_t wrap_val = 0xff; // WRAP ON
2098 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
2100 } else if(ch == SIG_FMTOWNS_RAM_WAIT) {
2101 uint8_t _bak = mem_wait_val;
2102 mem_wait_val = (int)data;
2103 if(_bak != mem_wait_val) {
2106 } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
2107 // mem_wait_val = (int)data;
2109 } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
2110 uint8_t _bak = vram_wait_val;
2111 vram_wait_val = (int)data;
2112 if(_bak != vram_wait_val) {
2118 uint32_t TOWNS_MEMORY::read_signal(int ch)
2120 if(ch == SIG_FMTOWNS_MACHINE_ID) {
2121 uint16_t d = (machine_id & 0xfff8) | ((uint16_t)(cpu_id & 0x07));
2123 } else if(ch == SIG_FMTOWNS_RAM_WAIT) {
2124 return (uint32_t)mem_wait_val;
2125 } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
2127 } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
2128 return (uint32_t)vram_wait_val;
2133 void TOWNS_MEMORY::set_intr_line(bool line, bool pending, uint32_t bit)
2135 __LIKELY_IF(d_cpu != NULL) {
2136 d_cpu->set_intr_line(line, pending, bit);
2142 #define STATE_VERSION 6
2144 bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
2146 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
2150 if(!state_fio->StateCheckInt32(this_device_id)) {
2153 state_fio->StateValue(machine_id);
2154 state_fio->StateValue(cpu_id);
2155 state_fio->StateValue(is_compatible);
2157 state_fio->StateValue(mem_wait_val);
2158 state_fio->StateValue(vram_wait_val);
2159 state_fio->StateValue(wait_register_older);
2160 state_fio->StateValue(wait_register_ram);
2161 state_fio->StateValue(wait_register_vram);
2163 state_fio->StateValue(dma_is_vram);
2164 state_fio->StateValue(nmi_vector_protect);
2165 state_fio->StateValue(software_reset);
2166 state_fio->StateValue(poff_status);
2167 state_fio->StateValue(reset_happened);
2169 state_fio->StateValue(extra_nmi_val);
2170 state_fio->StateValue(extra_nmi_mask);
2171 state_fio->StateValue(nmi_mask);
2173 state_fio->StateArray(ram_page0, sizeof(ram_page0), 1);
2174 state_fio->StateArray(ram_pagec, sizeof(ram_pagec), 1);
2176 state_fio->StateValue(select_d0_rom);
2177 state_fio->StateValue(select_d0_dict);
2178 state_fio->StateValue(ankcg_enabled);
2180 state_fio->StateValue(vram_wait_val);
2181 state_fio->StateValue(mem_wait_val);
2182 state_fio->StateValue(vram_size);
2183 state_fio->StateValue(cpu_clock_val);
2186 update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
2188 uint32_t length_tmp = state_fio->FgetUint32_LE();
2189 unset_range_rw(0x00100000, 0x3fffffff);
2190 if(extra_ram != NULL) {
2194 length_tmp = length_tmp & 0x3ff00000;
2195 extram_size = length_tmp;
2196 if(length_tmp > 0) {
2197 extra_ram = (uint8_t*)malloc(length_tmp);
2198 __LIKELY_IF(extra_ram != NULL) {
2199 set_region_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
2200 memset(extra_ram, 0x00, extram_size);
2204 if(extra_ram == NULL) {
2208 state_fio->Fread(extra_ram, extram_size, 1);
2209 //set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
2211 config_page0c_0e(dma_is_vram, select_d0_dict, true);
2212 config_page0f(select_d0_rom, true);
2217 if(extra_ram == NULL) {
2218 state_fio->FputUint32_LE(0);
2220 state_fio->FputUint32_LE(extram_size & 0x3ff00000);
2221 state_fio->Fwrite(extra_ram, extram_size, 1);
2225 // ToDo: Do save ROMs?