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 __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);
73 config_page0c_0e(true, false, true);
74 config_page0f(true, true);
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);
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);
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);
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
99 vram_size = 0x80000; // OK?
102 void TOWNS_MEMORY::reset_wait_values()
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);
112 void TOWNS_MEMORY::config_page0c_0e(const bool vrambank, const bool dictbank, const bool force)
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);
121 unset_range_rw(0x000e0000, 0x000effff); // OK?
123 set_mmio_wait_rw(0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
124 set_dma_wait_rw (0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
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);
130 unset_range_rw(0x000c0000, 0x000cffff);
131 unset_range_rw(0x000e0000, 0x000effff);
133 set_mmio_wait_rw(0x000c0000, 0x000cffff, WAITVAL_RAM); // Default Value
134 set_dma_wait_rw (0x000c0000, 0x000cffff, WAITVAL_VRAM); // Default Value
137 __UNLIKELY_IF((vrambank != is_vram_bak) || (dictbank != is_dict_bak) || (force)){
138 if(vrambank) { // VRAM AND around TEXT
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);
145 unset_range_rw(0x000d0000, 0x000dffff);
148 __LIKELY_IF(extra_ram != NULL) {
149 set_region_memory_rw(0x000d0000, 0x000dffff, extra_ram, 0x000d0000);
151 unset_range_rw(0x000d0000, 0x000dffff);
155 dma_is_vram = vrambank;
156 select_d0_dict = dictbank;
158 void TOWNS_MEMORY::config_page0f(const bool sysrombank, const bool force)
160 bool sysrom_bak = select_d0_rom;
161 //__LIKELY_IF(extra_ram != NULL) {
162 // set_region_memory_rw(0x000f0000, 0x000f7fff, extra_ram, 0x000f0000);
164 __UNLIKELY_IF((sysrombank != sysrom_bak) || (force)) {
166 unset_range_w(0x000f8000, 0x000fffff);
167 set_region_device_r (0x000f8000, 0x000fffff, d_sysrom, 0x38000);
169 __LIKELY_IF(extra_ram != NULL) {
170 set_region_memory_rw(0x000f8000, 0x000fffff, extra_ram, 0x000f8000);
172 unset_range_rw(0x000f8000, 0x000fffff);
176 select_d0_rom = sysrombank;
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)
181 uint64_t _start = (uint64_t)start;
182 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
183 __UNLIKELY_IF(dataptr == NULL) return;
185 _start &= ~(memory_map_mask());
186 _end &= ~(memory_map_mask());
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;
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;
198 dataptr[mapptr].mem_ptr = baseptr;
199 dataptr[mapptr].device_ptr = NULL;
201 if(base_offset == UINT32_MAX) {
202 dataptr[mapptr].base_offset = UINT32_MAX;
204 dataptr[mapptr].base_offset = realoffset;
206 realoffset += _incval;
211 void TOWNS_MEMORY::set_memory_devices_map_wait(uint32_t start, uint32_t end, memory_device_map_t* dataptr, int wait)
213 uint64_t _start = (uint64_t)start;
214 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
215 __UNLIKELY_IF(dataptr == NULL) return;
217 _start &= ~(memory_map_mask());
218 _end &= ~(memory_map_mask());
220 uint64_t mapptr = (uint32_t)(_start >> memory_map_shift());
221 const uint64_t _incval = memory_map_grain();
223 for(uint64_t addr = _start; addr < _end; addr += _incval) {
224 __UNLIKELY_IF(mapptr >= memory_map_size()) break; // Safety
225 dataptr[mapptr].waitval = wait;
230 void TOWNS_MEMORY::unset_memory_devices_map(uint32_t start, uint32_t end, memory_device_map_t* dataptr, int wait)
232 uint64_t _start = (uint64_t)start;
233 uint64_t _end = (end == 0xffffffff) ? 0x100000000 : (uint64_t)(end + 1);
234 __UNLIKELY_IF(dataptr == NULL) return;
236 _start &= ~(memory_map_mask());
237 _end &= ~(memory_map_mask());
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;
252 void TOWNS_MEMORY::set_mmio_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
254 set_memory_devices_map_values(start, end, &(membus_read_map[0]), baseptr, NULL, base_offset);
257 void TOWNS_MEMORY::set_mmio_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
259 set_memory_devices_map_values(start, end, &(membus_write_map[0]), baseptr, NULL, base_offset);
262 void __FASTCALL TOWNS_MEMORY::set_mmio_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
264 set_memory_devices_map_values(start, end, &(membus_read_map[0]), NULL, ptr, baseaddress);
267 void __FASTCALL TOWNS_MEMORY::set_mmio_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
269 set_memory_devices_map_values(start, end, &(membus_write_map[0]), NULL, ptr, baseaddress);
272 void __FASTCALL TOWNS_MEMORY::set_mmio_wait_r(uint32_t start, uint32_t end, int wait)
274 set_memory_devices_map_wait(start, end, &(membus_read_map[0]), wait);
277 void __FASTCALL TOWNS_MEMORY::set_mmio_wait_w(uint32_t start, uint32_t end, int wait)
279 set_memory_devices_map_wait(start, end, &(membus_write_map[0]), wait);
282 void TOWNS_MEMORY::unset_mmio_r(uint32_t start, uint32_t end, int wait)
284 unset_memory_devices_map(start, end, &(membus_read_map[0]), wait);
287 void TOWNS_MEMORY::unset_mmio_w(uint32_t start, uint32_t end, int wait)
289 unset_memory_devices_map(start, end, &(membus_write_map[0]), wait);
292 void TOWNS_MEMORY::unset_dma_r(uint32_t start, uint32_t end, int wait)
294 unset_memory_devices_map(start, end, &(dma_read_map[0]), wait);
297 void TOWNS_MEMORY::unset_dma_w(uint32_t start, uint32_t end, int wait)
299 unset_memory_devices_map(start, end, &(dma_write_map[0]), wait);
302 void TOWNS_MEMORY::set_dma_memory_r(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
304 set_memory_devices_map_values(start, end, &(dma_read_map[0]), baseptr, NULL, base_offset);
307 void TOWNS_MEMORY::set_dma_memory_w(uint32_t start, uint32_t end, uint8_t* baseptr, uint32_t base_offset)
309 set_memory_devices_map_values(start, end, &(dma_write_map[0]), baseptr, NULL, base_offset);
312 void __FASTCALL TOWNS_MEMORY::set_dma_device_r(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
314 set_memory_devices_map_values(start, end, &(dma_read_map[0]), NULL, ptr, baseaddress);
317 void __FASTCALL TOWNS_MEMORY::set_dma_device_w(uint32_t start, uint32_t end, DEVICE* ptr, uint32_t baseaddress)
319 set_memory_devices_map_values(start, end, &(dma_write_map[0]), NULL, ptr, baseaddress);
322 void __FASTCALL TOWNS_MEMORY::set_dma_wait_r(uint32_t start, uint32_t end, int wait)
324 set_memory_devices_map_wait(start, end, &(dma_read_map[0]), wait);
327 void __FASTCALL TOWNS_MEMORY::set_dma_wait_w(uint32_t start, uint32_t end, int wait)
329 set_memory_devices_map_wait(start, end, &(dma_write_map[0]), wait);
333 bool TOWNS_MEMORY::set_cpu_clock_by_wait()
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);
340 void TOWNS_MEMORY::set_wait_values()
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);
346 d_cpu->write_signal(SIG_CPU_WAIT_FACTOR, waitfactor, 0xffffffff);
349 void TOWNS_MEMORY::release()
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);
356 if(extra_ram != NULL) {
362 void TOWNS_MEMORY::reset()
366 update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
367 is_compatible = true;
368 reset_happened = false;
370 nmi_vector_protect = false;
371 ankcg_enabled = false;
373 //config_page0c_0e(false, false, true); // VRAM, DICT, FORCE
375 config_page0c_0e(false, false, true); // VRAM, DICT, FORCE
376 config_page0f(true, true); // SYSROM, FORCE
379 set_cpu_clock_by_wait();
382 __LIKELY_IF(d_cpu != NULL) {
383 d_cpu->set_address_mask(0xffffffff);
386 uint8_t wrap_val = 0xff; // WRAP ON
387 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
392 void TOWNS_MEMORY::update_machine_features()
396 if(machine_id >= 0x0b00) { // After MA/MX/ME
397 reg_misc3 &= ~0x04; // DMACMD
399 if(machine_id >= 0x0700) { // After HR/HG
400 reg_misc3 &= ~0x08; // POFFEN
402 if(machine_id >= 0x0700) { // After HR/HG
403 reg_misc3 &= ~0x10; // Free run counter
405 if(machine_id >= 0x0700) { // After HR/HG
406 reg_misc3 &= ~0x20; // CRTPOWOFF (0022h)
408 if(machine_id >= 0x0700) { // After HR/HG
409 reg_misc3 &= ~0x40; // RCREN
411 if(machine_id >= 0x0700) { // After HR/HG
412 reg_misc3 &= ~0x80; // ENPOFF
415 if(machine_id >= 0x0500) { // After CX
422 uint8_t TOWNS_MEMORY::read_fmr_ports8(uint32_t addr)
425 __UNLIKELY_IF((addr < 0xcff80) || (addr > 0xcffbb)) {
428 __LIKELY_IF(addr < 0xcff88) {
429 __LIKELY_IF(d_planevram != NULL) {
430 val = d_planevram->read_memory_mapped_io8(addr & 0xffff);
434 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
437 __LIKELY_IF(d_crtc != NULL) {
438 val = d_crtc->read_signal(SIG_TOWNS_CRTC_MMIO_CFF82H);
443 return (ankcg_enabled) ? 0x01 : 0x00;
448 __LIKELY_IF(d_font != NULL) {
449 val = d_font->read_io8(addr & 0xffff);
462 __LIKELY_IF(d_font != NULL) {
463 val = d_font->read_io8(addr & 0xffff);
467 __LIKELY_IF(d_timer != NULL) {
468 d_timer->write_signal(SIG_TIMER_BEEP_ON, 1, 1);
472 __LIKELY_IF(d_planevram != NULL) {
473 val = d_planevram->read_memory_mapped_io8(addr);
481 uint8_t TOWNS_MEMORY::read_sys_ports8(uint32_t addr)
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);
494 if((machine_id >= 0x0300) && ((machine_id & 0xff00) != 0x0400)) { // After UX
495 val = val | ((poff_status) ? 0x04 : 0x00);
500 // if(d_dmac != NULL) {
501 // val = d_dmac->read_signal(SIG_TOWNS_DMAC_ADDR_REG);
504 // 0024, 0025 : MISC3 + MISC4
513 if(machine_id >= 0x0500) { // After CX
514 val = (nmi_mask) ? 0x01 : 0x00;
519 // From FMTowns::MachineID() of TSUGARU,
520 // git 83d4ec2309ac9fcbb8c01f26061ff0d49c5321e4.
521 // if((config.dipswitch & TOWNS_DIPSW_PRETEND_I386) != 0) {
522 // val = ((machine_id & 0xf8) | 1);
524 val = ((machine_id & 0xf8) | (cpu_id & 7));
528 val = ((machine_id >> 8) & 0xff);
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);
539 case 0x00c0: // Cache
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
550 case 0x00c2: // Cache Diagnostic
552 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
553 // ToDo: Implement cache disgnostic.
554 // SDMOD (Not diagnostic) : Bit3
558 case 0x0400: // Resolution:
561 case 0x0404: // System Status Reg.
562 val = (dma_is_vram) ? 0x7f : 0xff;
563 // val = (dma_is_vram) ? 0x00 : 0x80;
566 val = (select_d0_dict) ? 0x01 : 0x00;
567 val |= ((select_d0_rom) ? 0x00 : 0x02);
571 // val = (extra_nmi_mask) ? 0xf7 : 0xff;
572 val = (extra_nmi_mask) ? 0x00 : 0x08;
575 // val = (extra_nmi_val) ? 0xff : 0xf7;
576 val = (extra_nmi_val) ? 0x08 : 0x00;
579 if(machine_id < 0x0200) { // Towns 1/2
580 val = wait_register_older;
584 if(machine_id >= 0x0200) { // i386
585 val = wait_register_ram;
589 if(machine_id >= 0x0200) { // i386
590 val = wait_register_vram;
594 // After Towns1F/2F/1H/2H
596 uint16_t nid = machine_id & 0xff00;
597 val = extram_size >> 20;
600 case 0x01: // Towns 1/2 : Not Supported.
603 case 0x03: // Towns II UX
604 case 0x06: // Towns II U6
606 if(val >= 9) val = 9;
608 case 0x02: // Towns 1F/2F/1H/2H.
609 case 0x04: // Towns 10F/20F/40H/80H.
612 case 0x05: // Towns II CX
615 case 0x08: // Towns II HG : OK?
618 case 0x07: // Towns II HR
619 case 0x09: // Towns II UR
622 default: // After MA/MX/ME/MF, Fresh
630 if(machine_id >= 0x0200) { // 05ec
631 val = ((is_faster_wait()) ? 0x01 : 0x00);
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
644 if(machine_id >= 0x0700) { // After HR/HG
645 val = (is_compatible) ? 0x00 : 0x01;
655 // Address (TOWNS BASIC):
656 // 0x0020 - 0x0022, 0x0030-0x0031,
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)
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);
669 return read_sys_ports8(addr);
672 void TOWNS_MEMORY::write_fmr_ports8(uint32_t addr, uint32_t data)
674 __UNLIKELY_IF((addr < 0xcff80) || (addr > 0xcffbb)) {
678 __LIKELY_IF(addr < 0xcff88) {
679 __LIKELY_IF(d_planevram != NULL) {
680 d_planevram->write_io8(addr & 0xffff, data);
685 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
688 __LIKELY_IF(d_font != NULL) {
689 d_font->write_io8(addr & 0xffff, data);
699 __LIKELY_IF(d_font != NULL) {
700 d_font->write_io8(addr & 0xffff, data);
707 __LIKELY_IF(d_timer != NULL) {
708 d_timer->write_signal(SIG_TIMER_BEEP_ON, 0, 1);
713 bool _b = ankcg_enabled;
714 ankcg_enabled = ((data & 1) != 0) ? true : false;
718 __LIKELY_IF(d_planevram != NULL) {
719 d_planevram->write_io8(addr & 0xffff, data);
726 void TOWNS_MEMORY::write_sys_ports8(uint32_t addr, uint32_t data)
728 switch(addr & 0xffff) {
729 case 0x0020: // Software reset ETC.
730 // reset cause register
731 if((data & 0x80) != 0) {
732 nmi_vector_protect = true;
734 nmi_vector_protect = false;
736 if((data & 0x01) != 0) {
737 software_reset = true;
739 software_reset = false;
742 if((data & 0x40) != 0) {
744 // __LIKELY_IF(d_cpu != NULL) {
745 // d_cpu->set_shutdown_flag(1);
747 // Todo: Implement true power off.
748 // emu->notify_power_off();
753 // __LIKELY_IF(d_cpu != NULL) {
754 // d_cpu->set_shutdown_flag(0);
758 if((software_reset) || (poff_status)){
759 // __LIKELY_IF(d_cpu != NULL) {
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);
767 __LIKELY_IF(d_cpu != NULL) {
768 d_cpu->set_shutdown_flag(1);
770 // Todo: Implement true power off.
771 emu->notify_power_off();
776 // Towns SEEMS to not set addreess mask (a.k.a A20 mask). 20200131 K.O
779 if((data & 0x40) != 0) {
780 __LIKELY_IF(d_cpu != NULL) {
781 d_cpu->set_shutdown_flag(1);
783 // Todo: Implement true power off.
785 emu->notify_power_off();
792 //if((d_dmac != NULL) && (machine_id >= 0x0b00)) { // After MA/MX/ME
793 // d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, data, 0xff);
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);
801 case 0x0404: // System Status Reg.
803 config_page0c_0e(((data & 0x80) == 0) ? true : false, select_d0_dict, false); // VRAM, DICT, FORCE
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);
816 extra_nmi_mask = ((data & 0x08) == 0);
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;
825 vram_wait_val = nval + 3; // OK?
826 if(vram_wait_val > 6) {
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();
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;
842 uint8_t nval = data & 7;
843 if(machine_id <= 0x0200) { // Towns 1H/2F.
844 if(nval < 1) nval = 1;
846 if(nval > 6) nval = 6;
848 wait_register_ram = (data & 0xf8) | nval;
852 wait_register_ram = data;
854 if((vram_bak != vram_wait_val) || (mem_bak != mem_wait_val)) {
855 set_cpu_clock_by_wait();
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;
865 uint8_t nval = data & 7;
866 if(machine_id <= 0x0200) { // Towns 1H/2F.
867 if(nval < 1) nval = 1;
869 if(nval > 6) nval = 6;
870 vram_wait_val = nval;
871 wait_register_vram = (data & 0xf8) | nval;
875 wait_register_vram = data;
877 if((vram_bak != vram_wait_val) || (mem_bak != mem_wait_val)) {
878 set_cpu_clock_by_wait();
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();
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);
911 void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
913 __LIKELY_IF((addr & 0xffff) >= 0xff80) {
914 write_fmr_ports8((addr & 0xffff) | 0x000c0000, data);
917 write_sys_ports8(addr, data);
921 uint32_t TOWNS_MEMORY::read_data8w(uint32_t addr, int* wait)
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);
928 uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int* wait)
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);
936 val = read_16bit_data(membus_read_map, mapptr, addr, offset, false, wait);
941 uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int* wait)
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);
949 val = read_32bit_data(membus_read_map, mapptr, addr, offset, false, wait);
955 uint32_t TOWNS_MEMORY::read_dma_data8w(uint32_t addr, int* wait)
957 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
958 uint32_t offset = addr & memory_map_mask();
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.
969 uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
971 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
972 uint32_t offset = addr & memory_map_mask();
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);
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);
981 __LIKELY_IF(wait != NULL) {
982 *wait = 0; // Discard wait value for DMA.
988 uint32_t TOWNS_MEMORY::read_dma_data32w(uint32_t addr, int* wait)
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);
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);
1000 __LIKELY_IF(wait != NULL) {
1001 *wait = 0; // Discard wait value for DMA.
1007 void TOWNS_MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
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);
1015 void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int* wait)
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);
1022 write_16bit_data(membus_write_map, mapptr, addr, offset, false, data, wait);
1027 void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int* wait)
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);
1034 write_32bit_data(membus_write_map, mapptr, addr, offset, false, data, wait);
1038 void TOWNS_MEMORY::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
1040 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1041 uint32_t offset = addr & memory_map_mask();
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.
1050 void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
1052 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1053 uint32_t offset = addr & memory_map_mask();
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);
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);
1061 __LIKELY_IF(wait != NULL) {
1062 *wait = 0; // Discard wait value for DMA.
1067 void TOWNS_MEMORY::write_dma_data32w(uint32_t addr, uint32_t data, int* wait)
1069 uint32_t mapptr = (uint32_t)(((uint64_t)addr) >> memory_map_shift());
1070 uint32_t offset = addr & memory_map_mask();
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);
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);
1078 __LIKELY_IF(wait != NULL) {
1079 *wait = 0; // Discard wait value for DMA.
1083 uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
1085 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1086 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1090 __LIKELY_IF(addr >= 0x000cc000) {
1092 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
1093 return read_fmr_ports8(addr);
1095 __LIKELY_IF(extra_ram != NULL) {
1096 return extra_ram[addr];
1102 if(addr < 0x000c9000) { // TEXT VRAM (ANK)
1103 __LIKELY_IF(d_sprite != NULL) {
1104 return d_sprite->read_memory_mapped_io8(addr);
1109 __LIKELY_IF(addr >= 0x000ca000) { // ANKCG8 and ANKCG16
1110 __LIKELY_IF(d_font != NULL) {
1111 return d_font->read_memory_mapped_io8(addr);
1115 __LIKELY_IF(addr < 0x000cb000) { // TEXT VRAM (KANJI)
1116 __LIKELY_IF(d_sprite != NULL) {
1117 return d_sprite->read_memory_mapped_io8(addr);
1124 uint32_t TOWNS_MEMORY::read_memory_mapped_io16(uint32_t addr)
1126 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1127 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1131 __LIKELY_IF(addr >= 0x000cc000) {
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);
1138 __LIKELY_IF(extra_ram != NULL) {
1139 w.read_2bytes_le_from(&(extra_ram[addr]));
1147 if(addr < 0x000c9000) { // TEXT VRAM (ANK)
1148 __LIKELY_IF(d_sprite != NULL) {
1149 return d_sprite->read_memory_mapped_io16(addr);
1154 __LIKELY_IF(addr >= 0x000ca000) { // ANKCG8 and ANKCG16
1155 __LIKELY_IF(d_font != NULL) {
1156 return d_font->read_memory_mapped_io16(addr);
1160 __LIKELY_IF(addr < 0x000cb000) { // TEXT VRAM (KANJI)
1161 __LIKELY_IF(d_sprite != NULL) {
1162 return d_sprite->read_memory_mapped_io16(addr);
1169 uint32_t TOWNS_MEMORY::read_memory_mapped_io32(uint32_t addr)
1171 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1172 __UNLIKELY_IF((addr > 0x000cffff) || (addr < 0x000c8000)) {
1176 __LIKELY_IF(addr >= 0x000cc000) {
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);
1185 __LIKELY_IF(extra_ram != NULL) {
1186 d.read_4bytes_le_from(&(extra_ram[addr]));
1194 if(addr < 0x000ca000) { //SPRITE
1195 __LIKELY_IF(d_sprite != NULL) {
1196 return d_sprite->read_memory_mapped_io32(addr);
1201 __LIKELY_IF(d_font != NULL) {
1202 return d_font->read_memory_mapped_io32(addr);
1205 __LIKELY_IF(d_sprite != NULL) {
1206 return d_sprite->read_memory_mapped_io32(addr);
1213 void TOWNS_MEMORY::write_memory_mapped_io8(uint32_t addr, uint32_t data)
1215 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1216 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1220 __LIKELY_IF(addr >= 0x000cc000) {
1222 __UNLIKELY_IF(addr >= 0x000cff80) { // I/O
1223 write_fmr_ports8(addr, data);
1226 __LIKELY_IF(extra_ram != NULL) {
1227 extra_ram[addr] = data;
1232 if(addr < 0x000cb000) { // TEXT VRAM (ANK + KANJI)
1233 __LIKELY_IF(d_sprite != NULL) {
1234 d_sprite->write_memory_mapped_io8(addr, data);
1241 void TOWNS_MEMORY::write_memory_mapped_io16(uint32_t addr, uint32_t data)
1243 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1244 __UNLIKELY_IF((addr > 0x000cffff) || (addr < 0x000c8000)) {
1248 __LIKELY_IF(addr >= 0x000cc000) {
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);
1257 __LIKELY_IF(extra_ram != NULL) {
1258 w.write_2bytes_le_to(&(extra_ram[addr]));
1263 if(addr < 0x000cb000) { // TEXT VRAM (ANK + KANJI)
1264 __LIKELY_IF(d_sprite != NULL) {
1265 d_sprite->write_memory_mapped_io16(addr, data);
1272 void TOWNS_MEMORY::write_memory_mapped_io32(uint32_t addr, uint32_t data)
1274 // This should be for VRAM MODE, with ROMs (000C8000h - 000CFFFFh)
1275 __UNLIKELY_IF((addr >= 0x000d0000) || (addr < 0x000c8000)) {
1278 __LIKELY_IF(addr >= 0x000cc000) {
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);
1289 __LIKELY_IF(extra_ram != NULL) {
1290 d.write_4bytes_le_to(&(extra_ram[addr]));
1295 if(addr < 0x000cb000) { // TEXT VRAM (ANK + KANJI)
1296 __LIKELY_IF(d_sprite != NULL) {
1297 d_sprite->write_memory_mapped_io32(addr, data);
1306 void TOWNS_MEMORY::write_signal(int ch, uint32_t data, uint32_t mask)
1308 if(ch == SIG_MEMORY_EXTNMI) {
1309 extra_nmi_val = ((data & mask) != 0);
1310 if(!(extra_nmi_mask)) {
1312 __LIKELY_IF(d_cpu != NULL) {
1313 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
1316 } else if(ch == SIG_CPU_NMI) {
1319 __LIKELY_IF(d_cpu != NULL) {
1320 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
1323 } else if(ch == SIG_CPU_IRQ) {
1324 __LIKELY_IF(d_cpu != NULL) {
1325 d_cpu->write_signal(SIG_CPU_IRQ, data, mask);
1327 } else if(ch == SIG_CPU_BUSREQ) {
1328 __LIKELY_IF(d_cpu != NULL) {
1329 d_cpu->write_signal(SIG_CPU_BUSREQ, data, mask);
1331 } else if(ch == SIG_I386_A20) {
1332 __LIKELY_IF(d_cpu != NULL) {
1333 d_cpu->write_signal(SIG_I386_A20, data, mask);
1335 } else if(ch == SIG_FMTOWNS_NOTIFY_RESET) {
1336 out_debug_log("RESET FROM CPU!!!\n");
1337 reset_happened = true;
1339 nmi_vector_protect = false;
1340 ankcg_enabled = false;
1342 config_page0c_0e(true, false, true);
1343 config_page0f(true, true);
1344 reset_wait_values();
1347 __LIKELY_IF(d_cpu != NULL) {
1348 d_cpu->set_address_mask(0xffffffff);
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);
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) {
1360 } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
1361 // mem_wait_val = (int)data;
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) {
1372 uint32_t TOWNS_MEMORY::read_signal(int ch)
1374 if(ch == SIG_FMTOWNS_MACHINE_ID) {
1375 uint16_t d = (machine_id & 0xfff8) | ((uint16_t)(cpu_id & 0x07));
1377 } else if(ch == SIG_FMTOWNS_RAM_WAIT) {
1378 return (uint32_t)mem_wait_val;
1379 } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
1381 } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
1382 return (uint32_t)vram_wait_val;
1387 void TOWNS_MEMORY::set_intr_line(bool line, bool pending, uint32_t bit)
1389 __LIKELY_IF(d_cpu != NULL) {
1390 d_cpu->set_intr_line(line, pending, bit);
1396 #define STATE_VERSION 8
1398 bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
1400 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1404 if(!state_fio->StateCheckInt32(this_device_id)) {
1407 state_fio->StateValue(machine_id);
1408 state_fio->StateValue(cpu_id);
1409 state_fio->StateValue(is_compatible);
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);
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);
1423 state_fio->StateValue(extra_nmi_val);
1424 state_fio->StateValue(extra_nmi_mask);
1425 state_fio->StateValue(nmi_mask);
1428 state_fio->StateValue(select_d0_rom);
1429 state_fio->StateValue(select_d0_dict);
1430 state_fio->StateValue(ankcg_enabled);
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);
1438 update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
1440 uint32_t length_tmp = state_fio->FgetUint32_LE();
1441 unset_range_rw(0x00100000, 0x3fffffff);
1442 if(extra_ram != NULL) {
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);
1454 if(extra_ram == NULL) {
1458 state_fio->Fread(extra_ram, extram_size + 0x00100000, 1);
1459 //set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
1461 config_page0c_0e(dma_is_vram, select_d0_dict, true);
1462 config_page0f(select_d0_rom, true);
1467 if(extra_ram == NULL) {
1468 state_fio->FputUint32_LE(0);
1470 state_fio->FputUint32_LE(extram_size & 0x3ff00000);
1471 state_fio->Fwrite(extra_ram, extram_size + 0x00100000, 1);
1475 // ToDo: Do save ROMs?