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 // Note: Bank width will be 0x2000 bytes.
29 void TOWNS_MEMORY::config_page_c0()
33 set_memory_mapped_io_rw(0x000c0000, 0x000c7fff, d_planevram);
34 set_memory_mapped_io_rw(0x000c8000, 0x000c9fff, d_sprite);
36 set_memory_mapped_io_r(0x000ca000, 0x000cbfff, d_font);
37 unset_memory_w (0x000ca000, 0x000cbfff); // OK?
39 set_memory_mapped_io_rw(0x000ca000, 0x000cbfff, d_sprite);
41 set_memory_rw (0x000cc000, 0x000cdfff, &(ram_pagec[0xc000]));
42 set_memory_mapped_io_rw(0x000ce000, 0x000cffff, this); // MMIO and higher RAM.
43 // ToDo: Correctness wait value.
44 set_wait_rw(0x000c0000, 0x000cffff, vram_wait_val);
45 config_page_d0_e0(); // By Tsugaru, Changeing mapping of D0000h-EFFFFh effects only at vram changing,
48 set_memory_rw (0x000c0000, 0x000cffff, ram_pagec);
49 set_memory_rw (0x000d0000, 0x000effff, ram_paged);
51 set_memory_rw (0x000c0000, 0x000cdfff, ram_pagec);
52 set_memory_mapped_io_rw(0x000ce000, 0x000cffff, this); // MMIO and higher RAM.
54 // ToDo: Correctness wait value.
55 set_wait_rw(0x000c0000, 0x000cffff, mem_wait_val);
56 set_wait_rw(0x000d0000, 0x000effff, mem_wait_val);
61 void TOWNS_MEMORY::config_page_d0_e0()
64 // TownsPhysicalMemory::UpdateSysROMDicROMMappingFlag(bool , bool )
65 // at src/towns/memory/pysmem.cpp, TSUGARU.
68 set_memory_rw (0x000d0000, 0x000effff, ram_paged);
71 set_memory_mapped_io_r (0x000d0000, 0x000d7fff, d_dictionary);
73 unset_memory_w (0x000d0000, 0x000d7fff);
74 set_memory_mapped_io_w (0x000d8000, 0x000d9fff, d_dictionary);
76 //set_memory_rw (0x000d0000, 0x000dffff, ram_paged);
77 unset_memory_rw (0x000d0000, 0x000d9fff);
79 unset_memory_rw (0x000da000, 0x000effff);
83 void TOWNS_MEMORY::config_page_f8_rom()
86 set_memory_mapped_io_r (0x000f8000, 0x000fffff, d_sysrom);
87 unset_memory_w (0x000f8000, 0x000fffff);
89 set_memory_rw (0x000f8000, 0x000fffff, &(ram_pagef[0x8000]));
93 void TOWNS_MEMORY::config_page00()
96 //config_page_f8_rom();
99 void TOWNS_MEMORY::initialize()
101 if(initialized) return;
102 MEMORY::initialize();
104 update_machine_features();
106 extra_nmi_mask = true;
107 extra_nmi_val = false;
109 reset_happened = false;
113 if((cpu_id == 0x01) || (cpu_id == 0x03)) {
114 wait_register = 0x03;
116 wait_register = 0x83;
118 cpu_clock_val = 16000 * 1000;
119 extram_size = extram_size & 0x3ff00000;
120 set_extra_ram_size(extram_size >> 20); // Check extra ram size.
122 if(extram_size >= 0x00100000) {
123 __UNLIKELY_IF(extra_ram == NULL) {
124 extra_ram = (uint8_t*)malloc(extram_size);
125 __LIKELY_IF(extra_ram != NULL) {
126 set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
127 memset(extra_ram, 0x00, extram_size);
131 memset(ram_page0, 0x00, sizeof(ram_page0));
132 memset(ram_pagec, 0x00, sizeof(ram_pagec));
133 memset(ram_paged, 0x00, sizeof(ram_paged));
134 memset(ram_pagef, 0x00, sizeof(ram_pagef));
136 select_d0_dict = false;
137 select_d0_rom = true;
143 set_memory_rw (0x00000000, 0x000bffff, ram_page0);
144 set_memory_rw (0x000f0000, 0x000f7fff, ram_pagef);
147 set_memory_mapped_io_rw(0x80000000, 0x8007ffff, d_vram);
148 set_memory_mapped_io_rw(0x80100000, 0x8017ffff, d_vram);
149 set_memory_mapped_io_rw(0x81000000, 0x8101ffff, d_sprite);
151 set_memory_mapped_io_rw(0xc0000000, 0xc0ffffff, d_iccard[0]);
152 set_memory_mapped_io_rw(0xc1000000, 0xc1ffffff, d_iccard[1]);
153 // set_wait_rw(0x00000000, 0xffffffff, vram_wait_val);
155 set_memory_mapped_io_r (0xc2000000, 0xc207ffff, d_msdos);
156 set_memory_mapped_io_r (0xc2080000, 0xc20fffff, d_dictionary);
157 set_memory_mapped_io_r (0xc2100000, 0xc213ffff, d_font);
158 set_memory_mapped_io_rw(0xc2140000, 0xc2141fff, d_dictionary);
159 if(d_font_20pix != NULL) {
160 set_memory_mapped_io_r (0xc2180000, 0xc21fffff, d_font_20pix);
162 set_memory_mapped_io_rw(0xc2200000, 0xc2200fff, d_pcm);
163 set_memory_mapped_io_r (0xfffc0000, 0xffffffff, d_sysrom);
166 // Another devices are blank
170 vram_size = 0x80000; // OK?
174 void TOWNS_MEMORY::set_wait_values()
176 uint32_t waitfactor = 0;
177 if(cpu_clock_val < get_cpu_clocks(d_cpu)) {
178 waitfactor = (uint32_t)(((double)get_cpu_clocks(d_cpu) / (double)cpu_clock_val) * 65536.0);
180 d_cpu->write_signal(SIG_CPU_WAIT_FACTOR, waitfactor, 0xffffffff);
182 set_wait_rw(0x00000000, 0x000bffff, mem_wait_val);
183 set_wait_rw(0x000d0000, 0x000fffff, mem_wait_val);
185 set_wait_rw(0x000c0000, 0x000cffff, vram_wait_val);
187 set_wait_rw(0x000c0000, 0x000cffff, mem_wait_val);
189 set_wait_rw(0x00100000, 0x00100000 + (extram_size & 0x3ff00000) - 1, mem_wait_val);
191 // ToDo: Extend I/O Slots
192 set_wait_rw(0x80000000, 0x800fffff, vram_wait_val);
193 set_wait_rw(0x80100000, 0x801fffff, vram_wait_val);
194 set_wait_rw(0x81000000, 0x8101ffff, vram_wait_val);
196 if(d_iccard[0] != NULL) {
197 set_wait_rw(0xc0000000, 0xc0ffffff, mem_wait_val); // OK?
199 if(d_iccard[0] != NULL) {
200 set_wait_rw(0xc1000000, 0xc1ffffff, mem_wait_val); // OK?
202 set_wait_rw(0xc2000000, 0xc2141fff, mem_wait_val);
203 set_wait_rw(0xc2200000, 0xc2200fff, mem_wait_val);
204 set_wait_rw(0xfffc0000, 0xffffffff, mem_wait_val);
207 void TOWNS_MEMORY::release()
209 // if(rd_table != NULL) free(rd_table);
210 // if(rd_dummy != NULL) free(rd_dummy);
211 // if(wr_table != NULL) free(wr_table);
212 // if(wr_dummy != NULL) free(wr_dummy);
214 if(extra_ram != NULL) {
221 void TOWNS_MEMORY::reset()
226 is_compatible = true;
227 reset_happened = false;
229 nmi_vector_protect = false;
230 ankcg_enabled = false;
232 select_d0_dict = false;
233 select_d0_rom = true;
238 __LIKELY_IF(d_cpu != NULL) {
239 d_cpu->set_address_mask(0xffffffff);
242 uint8_t wrap_val = 0xff; // WRAP ON
243 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
248 void TOWNS_MEMORY::update_machine_features()
252 if(machine_id >= 0x0b00) { // After MA/MX/ME
253 reg_misc3 &= ~0x04; // DMACMD
255 if(machine_id >= 0x0700) { // After HR/HG
256 reg_misc3 &= ~0x08; // POFFEN
258 if(machine_id >= 0x0700) { // After HR/HG
259 reg_misc3 &= ~0x10; // Free run counter
261 if(machine_id >= 0x0700) { // After HR/HG
262 reg_misc3 &= ~0x20; // CRTPOWOFF (0022h)
264 if(machine_id >= 0x0700) { // After HR/HG
265 reg_misc3 &= ~0x40; // RCREN
267 if(machine_id >= 0x0700) { // After HR/HG
268 reg_misc3 &= ~0x80; // ENPOFF
271 if(machine_id >= 0x0500) { // After CX
278 uint8_t TOWNS_MEMORY::read_fmr_ports8(uint32_t addr)
281 __UNLIKELY_IF((addr & 0xffff) < 0xff80) {
282 return ram_pagec[addr & 0xffff];
285 __LIKELY_IF((addr & 0xffff) < 0xff88) {
286 __LIKELY_IF(d_planevram != NULL) {
287 val = d_planevram->read_memory_mapped_io8(addr & 0xffff);
290 } else if(((addr & 0xffff) >= 0xff94) && ((addr & 0xffff) < 0xff98)) {
291 __LIKELY_IF(d_font != NULL) {
292 val = d_font->read_io8(addr & 0xffff);
297 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
298 switch(addr & 0xffff) {
300 __LIKELY_IF(d_crtc != NULL) {
301 val = d_crtc->read_signal(SIG_TOWNS_CRTC_MMIO_CFF82H);
306 return (ankcg_enabled) ? 0x01 : 0x00;
311 __LIKELY_IF(d_font != NULL) {
312 val = d_font->read_io8(addr & 0xffff);
321 switch(addr & 0xffff) {
323 __LIKELY_IF(d_planevram != NULL) {
324 val = d_planevram->read_io8(addr);
331 __LIKELY_IF(d_font != NULL) {
332 return d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_LOW);
336 __LIKELY_IF(d_font != NULL) {
337 return d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_HIGH);
341 __LIKELY_IF(d_timer != NULL) {
342 d_timer->write_signal(SIG_TIMER_BEEP_ON, 1, 1);
346 __LIKELY_IF(d_planevram != NULL) {
347 val = d_planevram->read_memory_mapped_io8(addr);
351 __LIKELY_IF(d_planevram != NULL) {
352 val = d_planevram->read_io8(addr & 0xffff);
358 uint8_t TOWNS_MEMORY::read_sys_ports8(uint32_t addr)
362 switch(addr & 0xffff) {
363 case 0x0020: // Software reset ETC.
364 // reset cause register
365 val = ((software_reset) ? 1 : 0) | ((reset_happened) ? 2 : 0);
366 reset_happened = false;
367 software_reset = false;
368 __UNLIKELY_IF(d_cpu != NULL) {
369 d_cpu->set_shutdown_flag(0);
371 if((machine_id >= 0x0300) && ((machine_id & 0xff00) != 0x0400)) { // After UX
372 val = val | ((poff_status) ? 0x04 : 0x00);
377 // if(d_dmac != NULL) {
378 // val = d_dmac->read_signal(SIG_TOWNS_DMAC_ADDR_REG);
381 // 0024, 0025 : MISC3 + MISC4
390 if(machine_id >= 0x0500) { // After CX
391 val = (nmi_mask) ? 0x01 : 0x00;
396 // From FMTowns::MachineID() of TSUGARU,
397 // git 83d4ec2309ac9fcbb8c01f26061ff0d49c5321e4.
398 // if((config.dipswitch & TOWNS_DIPSW_PRETEND_I386) != 0) {
399 // val = ((machine_id & 0xf8) | 1);
401 val = ((machine_id & 0xf8) | (cpu_id & 7));
405 val = ((machine_id >> 8) & 0xff);
409 //bool __cs = (d_serialrom->read_signal(SIG_SERIALROM_CS) == 0);
410 bool __clk = (d_serialrom->read_signal(SIG_SERIALROM_CLK) != 0);
411 bool __reset = (d_serialrom->read_signal(SIG_SERIALROM_RESET) != 0);
412 bool __dat = (d_serialrom->read_signal(SIG_SERIALROM_DATA) != 0);
413 val = ((__reset) ? 0x80 : 0x00) | ((__clk) ? 0x40 : 0x00) | /*0x3e |*/ ((__dat) ? 0x01 : 0x00);
416 case 0x00c0: // Cache
418 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
419 // ToDo: Implement around cache.
420 // Modified by this register and (05ECh:bit0 / Wait register).
421 // Now, cache is always disabled.
422 // RPNH = 0 (Disabled) : Bit1
423 // CMEN = 0 (Disabled) : Bit0
427 case 0x00c2: // Cache Diagnostic
429 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
430 // ToDo: Implement cache disgnostic.
431 // SDMOD (Not diagnostic) : Bit3
435 case 0x0400: // Resolution:
438 case 0x0404: // System Status Reg.
439 // val = (dma_is_vram) ? 0x7f : 0xff;
440 val = (dma_is_vram) ? 0x00 : 0x80;
443 val = (select_d0_dict) ? 0x01 : 0x00;
444 val |= ((select_d0_rom) ? 0x00 : 0x02);
447 // val = (extra_nmi_mask) ? 0xf7 : 0xff;
448 val = (extra_nmi_mask) ? 0x00 : 0x08;
451 // val = (extra_nmi_val) ? 0xff : 0xf7;
452 val = (extra_nmi_val) ? 0x08 : 0x00;
455 if(machine_id < 0x0200) { // Towns 1/2
460 if(machine_id >= 0x0200) { // i386
465 // After Towns1F/2F/1H/2H
467 uint16_t nid = machine_id & 0xff00;
469 val = (extram_size >> 20) & 0x7f; // MAX 128MB
470 } else if(nid >= 0x0900) { // UR,MA,MX,ME,MF
471 val = (extram_size >> 20) & 0x1f; // MAX 32MB
472 } else if(nid == 0x0800) { // HG
473 val = (extram_size >> 20) & 0x0f; // MAX 15MB
474 } else if(nid == 0x0700) { // HR
475 val = (extram_size >> 20) & 0x1f; // MAX 32MB
476 } else if(nid >= 0x0200) { // 2nd GEN,3rd Gen, UX/UG, CX
477 val = (extram_size >> 20) & 0x0f; // MAX 15MB
479 val = 0xff; // NOT SUPPORTED
485 if(machine_id >= 0x0200) { // 05ec
486 val = ((mem_wait_val < 1) ? 0x01 : 0x00);
490 if(machine_id >= 0x0700) { // 05ed
491 uint32_t clk = get_cpu_clocks(d_cpu);
492 clk = clk / (1000 * 1000);
493 __UNLIKELY_IF(clk < 16) clk = 16;
494 __UNLIKELY_IF(clk > 127) clk = 127; // ToDo
499 if(machine_id >= 0x0700) { // After HR/HG
500 val = (is_compatible) ? 0x00 : 0x01;
510 // Address (TOWNS BASIC):
511 // 0x0020 - 0x0022, 0x0030-0x0031,
515 // 0x05ec (Wait register)
516 // 0x05ed (CPU SPEED REGISTER)
517 // Is set extra NMI (0x05c0 - 0x05c2)?
518 uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
520 __LIKELY_IF((addr & 0xffff) >= 0xff80) {
521 return read_fmr_ports8(addr & 0xffff);
523 return read_sys_ports8(addr);
526 uint32_t TOWNS_MEMORY::read_io8w(uint32_t addr, int *wait)
528 // uint32_t val = 0x00; // MAY NOT FILL to "1" for unused bit 20200129 K.O
529 __LIKELY_IF((addr & 0xffff) >= 0xff80) {
530 *wait = 6; // ToDo: will io_wait_val.
531 return read_fmr_ports8(addr & 0xffff);
533 *wait = 6; // ToDo: will io_wait_val.
534 return read_sys_ports8(addr);
538 void TOWNS_MEMORY::write_fmr_ports8(uint32_t addr, uint32_t data)
540 __UNLIKELY_IF((addr & 0xffff) < 0xff80) {
541 ram_pagec[addr & 0xffff] = data;
545 __LIKELY_IF((addr & 0xffff) < 0xff88) {
546 __LIKELY_IF(d_planevram != NULL) {
547 d_planevram->write_io8(addr & 0xffff, data);
550 } else if(((addr & 0xffff) >= 0xff94) && ((addr & 0xffff) < 0xff98)) {
551 __LIKELY_IF(d_font != NULL) {
552 d_font->write_io8(addr & 0xffff, data);
557 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
558 switch(addr & 0xffff) {
560 __LIKELY_IF(d_font != NULL) {
561 d_font->write_io8(addr & 0xffff, data);
568 switch(addr & 0xffff) {
570 __LIKELY_IF(d_font != NULL) {
571 d_font->write_signal(SIG_TOWNS_FONT_KANJI_HIGH, data, 0xff);
575 __LIKELY_IF(d_font != NULL) {
576 d_font->write_signal(SIG_TOWNS_FONT_KANJI_LOW, data, 0xff);
583 __LIKELY_IF(d_timer != NULL) {
584 d_timer->write_signal(SIG_TIMER_BEEP_ON, 0, 1);
589 bool _b = ankcg_enabled;
590 ankcg_enabled = ((data & 1) != 0) ? true : false;
591 //if((_b != ankcg_enabled) && (dma_is_vram)) {
597 __LIKELY_IF(d_planevram != NULL) {
598 d_planevram->write_io8(addr & 0xffff, data);
601 __LIKELY_IF(d_planevram != NULL) {
602 d_planevram->write_io8(addr & 0xffff, data);
607 void TOWNS_MEMORY::write_sys_ports8(uint32_t addr, uint32_t data)
609 switch(addr & 0xffff) {
610 case 0x0020: // Software reset ETC.
611 // reset cause register
612 if((data & 0x80) != 0) {
613 nmi_vector_protect = true;
615 nmi_vector_protect = false;
617 if((data & 0x01) != 0) {
618 software_reset = true;
620 software_reset = false;
623 if((data & 0x40) != 0) {
625 // __LIKELY_IF(d_cpu != NULL) {
626 // d_cpu->set_shutdown_flag(1);
628 // Todo: Implement true power off.
629 // emu->notify_power_off();
634 // __LIKELY_IF(d_cpu != NULL) {
635 // d_cpu->set_shutdown_flag(0);
639 if((software_reset) || (poff_status)){
640 // __LIKELY_IF(d_cpu != NULL) {
643 uint8_t wrap_val = 0xff; // WRAP ON
644 __LIKELY_IF(d_dmac != NULL) {
645 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
648 __LIKELY_IF(d_cpu != NULL) {
649 d_cpu->set_shutdown_flag(1);
651 // Todo: Implement true power off.
652 emu->notify_power_off();
657 // Towns SEEMS to not set addreess mask (a.k.a A20 mask). 20200131 K.O
660 if((data & 0x40) != 0) {
661 __LIKELY_IF(d_cpu != NULL) {
662 d_cpu->set_shutdown_flag(1);
664 // Todo: Implement true power off.
666 emu->notify_power_off();
673 //if((d_dmac != NULL) && (machine_id >= 0x0b00)) { // After MA/MX/ME
674 // d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, data, 0xff);
678 d_serialrom->write_signal(SIG_SERIALROM_CS, ~data, 0x20);
679 d_serialrom->write_signal(SIG_SERIALROM_CLK, data, 0x40);
680 d_serialrom->write_signal(SIG_SERIALROM_RESET, data, 0x80);
682 case 0x0404: // System Status Reg.
684 bool _b = dma_is_vram;
685 dma_is_vram = ((data & 0x80) == 0);
686 if((_b != dma_is_vram)/* || (dma_is_vram)*/) {
688 //config_page_d0_e0();
694 bool _dict = select_d0_dict;
695 bool _rom = select_d0_rom;
696 select_d0_dict = ((data & 0x01) != 0) ? true : false;
697 select_d0_rom = ((data & 0x02) == 0) ? true : false;
698 if((_dict != select_d0_dict) ||(_rom != select_d0_rom)){
699 //config_page_d0_e0();
701 //config_page_f8_rom();
706 extra_nmi_mask = ((data & 0x08) == 0);
710 if(machine_id < 0x0200) { // Towns 1/2
711 uint8_t nval = data & 7;
712 uint8_t val_bak = mem_wait_val;
713 if(nval < 1) nval = 1;
714 if(nval > 5) nval = 5;
715 mem_wait_val = nval + 1;
716 vram_wait_val = nval + 3 + 1;
717 wait_register = nval;
718 if(val_bak != mem_wait_val) {
724 if(machine_id >= 0x0200) { // After Towns 1H/2F. Hidden wait register.
725 uint8_t val_bak = mem_wait_val;
727 uint8_t nval = data & 7;
728 if(machine_id <= 0x0200) { // Towns 1H/2F.
729 if(nval < 1) nval = 1;
731 if(nval > 5) nval = 5;
733 vram_wait_val = nval + 3;
734 wait_register = nval;
738 wait_register = data;
740 if(val_bak != mem_wait_val) {
747 if(machine_id >= 0x0500) { // Towns2 CX :
748 uint8_t val_bak = mem_wait_val;
749 uint32_t clk_bak = cpu_clock_val;
750 vram_wait_val = ((data & 0x01) != 0) ? 3 : 6;
751 mem_wait_val = ((data & 0x01) != 0) ? 0 : 3;
752 cpu_clock_val = ((data & 0x01) != 0) ? (get_cpu_clocks(d_cpu)) : (16 * 1000 * 1000);
753 if((val_bak != mem_wait_val) || (cpu_clock_val != clk_bak)) {
760 if(machine_id >= 0x0700) { // After HR/HG
761 is_compatible = ((data & 0x01) == 0x00) ? true : false;
762 __LIKELY_IF(d_crtc != NULL) {
763 d_crtc->write_signal(SIG_TOWNS_CRTC_COMPATIBLE_MMIO, (is_compatible) ? 0xffffffff : 0x00000000, 0xffffffff);
771 void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
773 __LIKELY_IF((addr & 0xffff) >= 0xff80) {
774 write_fmr_ports8(addr & 0xffff, data);
777 write_sys_ports8(addr, data);
780 void TOWNS_MEMORY::write_io8w(uint32_t addr, uint32_t data, int *wait)
782 __LIKELY_IF((addr & 0xffff) >= 0xff80) {
783 *wait = 6; // ToDo: will io_wait_val.
784 write_fmr_ports8(addr & 0xffff, data);
787 *wait = 6; // ToDo: will io_wait_val.
788 write_sys_ports8(addr, data);
792 uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
795 return read_memory_mapped_io8w(addr, &wait);
797 uint32_t TOWNS_MEMORY::read_memory_mapped_io8w(uint32_t addr, int *wait)
799 __LIKELY_IF(addr < 0xcff80) {
800 *wait = mem_wait_val;
801 return ram_pagec[addr & 0xffff];
803 __UNLIKELY_IF(addr >= 0xd0000) {
804 *wait = mem_wait_val;
807 *wait = 6; // Maybe 6.
808 return read_fmr_ports8(addr);
811 uint32_t TOWNS_MEMORY::read_memory_mapped_io16(uint32_t addr)
814 return read_memory_mapped_io16w(addr, &wait);
817 uint32_t TOWNS_MEMORY::read_memory_mapped_io16w(uint32_t addr, int *wait)
819 __LIKELY_IF(addr < 0xcff80) {
821 __LIKELY_IF((addr & 1) == 0) {
822 *wait = mem_wait_val;
823 v.read_2bytes_le_from(&(ram_pagec[addr & 0xfffe]));
825 *wait = mem_wait_val * 2;
826 v.b.l = ram_pagec[addr & 0xffff];
827 v.b.h = ram_pagec[(addr + 1) & 0xffff];
831 __UNLIKELY_IF(addr >= 0xd0000) {
832 *wait = mem_wait_val;
835 // OK? This may be bus width has 8bit ?
836 *wait = 6; // Maybe 6.
838 val.b.l = read_fmr_ports8(addr & 0xffff);
839 val.b.h = read_fmr_ports8((addr & 0xffff) + 1);
843 void TOWNS_MEMORY::write_memory_mapped_io8(uint32_t addr, uint32_t data)
846 write_memory_mapped_io8w(addr, data, &wait);
849 void TOWNS_MEMORY::write_memory_mapped_io8w(uint32_t addr, uint32_t data, int *wait)
851 __LIKELY_IF(addr < 0xcff80) {
852 *wait = mem_wait_val;
853 ram_pagec[addr & 0xffff] = data;
856 __LIKELY_IF(addr < 0xd0000) {
857 *wait = 6; // Maybe 6.
858 write_fmr_ports8(addr, data);
861 *wait = mem_wait_val;
865 void TOWNS_MEMORY::write_memory_mapped_io16(uint32_t addr, uint32_t data)
868 write_memory_mapped_io16w(addr, data, &wait);
871 void TOWNS_MEMORY::write_memory_mapped_io16w(uint32_t addr, uint32_t data, int *wait)
873 __LIKELY_IF(addr < 0xcff80) {
876 __LIKELY_IF((addr & 1) == 0) {
877 *wait = mem_wait_val;
878 v.write_2bytes_le_to(&(ram_pagec[addr & 0xffff]));
880 *wait = mem_wait_val * 2;
881 ram_pagec[(addr & 0xffff) + 0] = v.b.l;
882 ram_pagec[(addr & 0xffff) + 1] = v.b.h;
886 __LIKELY_IF(addr < 0xd0000) {
889 *wait = 6 * 2; // Maybe 6.
890 write_fmr_ports8(addr, v.b.l);
891 write_fmr_ports8(addr + 1, v.b.h);
894 *wait = mem_wait_val;
899 void TOWNS_MEMORY::write_signal(int ch, uint32_t data, uint32_t mask)
901 if(ch == SIG_MEMORY_EXTNMI) {
902 extra_nmi_val = ((data & mask) != 0);
903 if(!(extra_nmi_mask)) {
905 __LIKELY_IF(d_cpu != NULL) {
906 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
909 } else if(ch == SIG_CPU_NMI) {
912 __LIKELY_IF(d_cpu != NULL) {
913 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
916 } else if(ch == SIG_CPU_IRQ) {
917 __LIKELY_IF(d_cpu != NULL) {
918 d_cpu->write_signal(SIG_CPU_IRQ, data, mask);
920 } else if(ch == SIG_CPU_BUSREQ) {
921 __LIKELY_IF(d_cpu != NULL) {
922 d_cpu->write_signal(SIG_CPU_BUSREQ, data, mask);
924 } else if(ch == SIG_I386_A20) {
925 __LIKELY_IF(d_cpu != NULL) {
926 d_cpu->write_signal(SIG_I386_A20, data, mask);
928 } else if(ch == SIG_FMTOWNS_NOTIFY_RESET) {
929 out_debug_log("RESET FROM CPU!!!\n");
930 reset_happened = true;
932 nmi_vector_protect = false;
933 ankcg_enabled = false;
935 select_d0_dict = false;
936 select_d0_rom = true;
940 __LIKELY_IF(d_cpu != NULL) {
941 d_cpu->set_address_mask(0xffffffff);
943 __LIKELY_IF(d_dmac != NULL) {
944 uint8_t wrap_val = 0xff; // WRAP ON
945 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP, wrap_val, 0xff);
947 } else if(ch == SIG_FMTOWNS_RAM_WAIT) {
948 uint8_t _bak = mem_wait_val;
949 mem_wait_val = (int)data;
950 if(_bak != mem_wait_val) {
953 } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
954 // mem_wait_val = (int)data;
956 } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
957 uint8_t _bak = vram_wait_val;
958 vram_wait_val = (int)data;
959 if(_bak != vram_wait_val) {
965 uint32_t TOWNS_MEMORY::read_signal(int ch)
967 if(ch == SIG_FMTOWNS_MACHINE_ID) {
968 uint16_t d = (machine_id & 0xfff8) | ((uint16_t)(cpu_id & 0x07));
970 } else if(ch == SIG_FMTOWNS_RAM_WAIT) {
971 return (uint32_t)mem_wait_val;
972 } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
974 } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
975 return (uint32_t)vram_wait_val;
980 void TOWNS_MEMORY::set_intr_line(bool line, bool pending, uint32_t bit)
982 __LIKELY_IF(d_cpu != NULL) {
983 d_cpu->set_intr_line(line, pending, bit);
989 #define STATE_VERSION 5
991 bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
993 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
997 if(!state_fio->StateCheckInt32(this_device_id)) {
1000 state_fio->StateValue(machine_id);
1001 state_fio->StateValue(cpu_id);
1002 state_fio->StateValue(is_compatible);
1004 state_fio->StateValue(mem_wait_val);
1005 state_fio->StateValue(vram_wait_val);
1006 state_fio->StateValue(wait_register);
1008 state_fio->StateValue(dma_is_vram);
1009 state_fio->StateValue(nmi_vector_protect);
1010 state_fio->StateValue(software_reset);
1011 state_fio->StateValue(poff_status);
1012 state_fio->StateValue(reset_happened);
1014 state_fio->StateValue(extra_nmi_val);
1015 state_fio->StateValue(extra_nmi_mask);
1016 state_fio->StateValue(nmi_mask);
1018 state_fio->StateArray(ram_page0, sizeof(ram_page0), 1);
1019 state_fio->StateArray(ram_pagec, sizeof(ram_pagec), 1);
1020 state_fio->StateArray(ram_paged, sizeof(ram_paged), 1);
1021 state_fio->StateArray(ram_pagef, sizeof(ram_pagef), 1);
1023 state_fio->StateValue(select_d0_rom);
1024 state_fio->StateValue(select_d0_dict);
1025 state_fio->StateValue(ankcg_enabled);
1027 state_fio->StateValue(vram_wait_val);
1028 state_fio->StateValue(mem_wait_val);
1029 state_fio->StateValue(vram_size);
1030 state_fio->StateValue(cpu_clock_val);
1033 update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
1035 uint32_t length_tmp = state_fio->FgetUint32_LE();
1036 if(extra_ram != NULL) {
1040 length_tmp = length_tmp & 0x3ff00000;
1041 extram_size = length_tmp;
1042 if(length_tmp > 0) {
1043 extra_ram = (uint8_t*)malloc(length_tmp);
1045 unset_memory_rw(0x00100000, 0x3fffffff);
1046 if(extra_ram == NULL) {
1050 state_fio->Fread(extra_ram, extram_size, 1);
1051 set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
1057 if(extra_ram == NULL) {
1058 state_fio->FputUint32_LE(0);
1060 state_fio->FputUint32_LE(extram_size & 0x3ff00000);
1061 state_fio->Fwrite(extra_ram, extram_size, 1);
1065 // ToDo: Do save ROMs?