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 #define ADDR_MASK (addr_max - 1)
29 #define BANK_MASK (bank_size - 1)
31 void TOWNS_MEMORY::config_page_c0()
35 set_memory_mapped_io_rw(0x000c0000, 0x000c7fff, d_planevram);
36 set_memory_mapped_io_rw(0x000c8000, 0x000c9fff, d_sprite);
38 set_memory_mapped_io_r(0x000ca000, 0x000cbfff, d_font);
39 // set_memory_mapped_io_r(0x000ca000, 0x000ca7ff, d_font);
40 // set_memory_r (0x000ca800, 0x000cafff, rd_dummy);
41 // set_memory_mapped_io_r(0x000cb000, 0x000cbfff, d_font);
42 set_memory_w (0x000ca000, 0x000cbfff, wr_dummy); // OK?
43 //set_memory_mapped_io_w(0x000ca000, 0x000cbfff, d_sprite); // OK?
45 set_memory_mapped_io_rw(0x000ca000, 0x000cbfff, d_sprite);
47 // set_memory_rw (0x000cc000, 0x000cfbff, &(ram_pagec[0xc000]));
48 set_memory_mapped_io_rw(0x000cc000, 0x000cffff, this); // MMIO and higher RAM.
49 // ToDo: Correctness wait value.
50 set_wait_rw(0x000c0000, 0x000cffff, vram_wait_val);
52 set_memory_rw (0x000c0000, 0x000cffff, ram_pagec);
53 // ToDo: Correctness wait value.
54 set_wait_rw(0x000c0000, 0x000cffff, mem_wait_val);
58 void TOWNS_MEMORY::config_page_d0_e0()
61 // TownsPhysicalMemory::UpdateSysROMDicROMMappingFlag(bool , bool )
62 // at src/towns/memory/pysmem.cpp, TSUGARU.
65 set_memory_rw (0x000d0000, 0x000effff, ram_paged);
68 set_memory_mapped_io_rw(0x000d0000, 0x000d9fff, d_dictionary);
69 set_memory_r (0x000da000, 0x000effff, rd_dummy);
70 set_memory_w (0x000da000, 0x000effff, wr_dummy);
72 //set_memory_rw (0x000d0000, 0x000dffff, ram_paged);
73 set_memory_r (0x000d0000, 0x000effff, rd_dummy);
74 set_memory_w (0x000d0000, 0x000effff, wr_dummy);
79 void TOWNS_MEMORY::config_page_f8_rom()
81 set_memory_mapped_io_rw (0x000f8000, 0x000fffff, this);
83 // if(select_d0_rom) {
84 // set_memory_mapped_io_r (0x000f8000, 0x000fffff, d_sysrom);
85 // set_memory_w (0x000f8000, 0x000fffff, wr_dummy);
87 // set_memory_rw (0x000f8000, 0x000fffff, &(ram_pagef[0x8000]));
91 void TOWNS_MEMORY::config_page00()
98 void TOWNS_MEMORY::initialize()
100 // if(initialized) return;
101 MEMORY::initialize();
102 // DEVICE::initialize();
104 extra_nmi_mask = true;
105 extra_nmi_val = false;
107 reset_happened = false;
111 if((cpu_id == 0x01) || (cpu_id == 0x03)) {
112 wait_register = 0x03;
114 wait_register = 0x83;
116 cpu_clock_val = 16000 * 1000;
118 // Initialize R/W table
119 _MEMORY_DISABLE_DMA_MMIO = osd->check_feature(_T("MEMORY_DISABLE_DMA_MMIO"));
120 if(!(addr_max_was_set) && osd->check_feature(_T("MEMORY_ADDR_MAX"))) {
121 addr_max = osd->get_feature_uint64_value(_T("MEMORY_ADDR_MAX"));
123 if(!(bank_size_was_set) && osd->check_feature(_T("MEMORY_BANK_SIZE"))) {
124 bank_size = osd->get_feature_uint64_value(_T("MEMORY_BANK_SIZE"));
127 bank_mask = BANK_MASK;
128 addr_mask = ADDR_MASK;
131 extram_size = extram_size & 0x3ff00000;
132 set_extra_ram_size(extram_size >> 20); // Check extra ram size.
134 if(extram_size >= 0x00100000) {
135 extra_ram = (uint8_t*)malloc(extram_size);
136 __LIKELY_IF(extra_ram != NULL) {
137 set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
138 memset(extra_ram, 0x00, extram_size);
141 memset(ram_page0, 0x00, sizeof(ram_page0));
142 memset(ram_pagec, 0x00, sizeof(ram_pagec));
143 memset(ram_paged, 0x00, sizeof(ram_paged));
144 memset(ram_pagef, 0x00, sizeof(ram_pagef));
146 select_d0_dict = false;
147 select_d0_rom = true;
151 set_memory_rw (0x00000000, 0x000bffff, ram_page0);
152 set_memory_rw (0x000f0000, 0x000f7fff, ram_pagef);
155 set_memory_mapped_io_rw(0x80000000, 0x8007ffff, d_vram);
156 set_memory_mapped_io_rw(0x80100000, 0x8017ffff, d_vram);
157 set_memory_mapped_io_rw(0x81000000, 0x8101ffff, d_sprite);
159 // set_memory_mapped_io_rw(0xc0000000, 0xc0ffffff, d_iccard[0]);
160 // set_memory_mapped_io_rw(0xc1000000, 0xc1ffffff, d_iccard[1]);
161 set_wait_rw(0x00000000, 0xffffffff, vram_wait_val);
163 set_memory_mapped_io_rw(0xc0000000, 0xc0ffffff, d_iccard[0]);
164 set_memory_mapped_io_rw(0xc1000000, 0xc1ffffff, d_iccard[1]);
166 set_memory_mapped_io_r (0xc2000000, 0xc207ffff, d_msdos);
167 set_memory_mapped_io_r (0xc2080000, 0xc20fffff, d_dictionary);
168 set_memory_mapped_io_r (0xc2100000, 0xc213ffff, d_font);
169 set_memory_mapped_io_rw(0xc2140000, 0xc2141fff, d_dictionary);
170 if(d_font_20pix != NULL) {
171 set_memory_mapped_io_r (0xc2180000, 0xc21fffff, d_font_20pix);
173 set_memory_mapped_io_rw(0xc2200000, 0xc2200fff, d_pcm);
174 set_memory_mapped_io_r (0xfffc0000, 0xffffffff, d_sysrom);
177 // Another devices are blank
181 vram_size = 0x80000; // OK?
185 void TOWNS_MEMORY::set_wait_values()
187 uint32_t waitfactor = 0;
188 if(cpu_clock_val < get_cpu_clocks(d_cpu)) {
189 waitfactor = (uint32_t)(((double)get_cpu_clocks(d_cpu) / (double)cpu_clock_val) * 65536.0);
191 d_cpu->write_signal(SIG_CPU_WAIT_FACTOR, waitfactor, 0xffffffff);
193 set_wait_rw(0x00000000, 0x000bffff, mem_wait_val);
194 set_wait_rw(0x000d0000, 0x000fffff, mem_wait_val);
196 set_wait_rw(0x000c0000, 0x000cffff, vram_wait_val);
198 set_wait_rw(0x000c0000, 0x000cffff, mem_wait_val);
200 set_wait_rw(0x00100000, 0x00100000 + (extram_size & 0x3ff00000) - 1, mem_wait_val);
202 // ToDo: Extend I/O Slots
203 set_wait_rw(0x80000000, 0x800fffff, vram_wait_val);
204 set_wait_rw(0x80100000, 0x801fffff, vram_wait_val);
205 set_wait_rw(0x81000000, 0x8101ffff, vram_wait_val);
207 if(d_iccard[0] != NULL) {
208 set_wait_rw(0xc0000000, 0xc0ffffff, mem_wait_val); // OK?
210 if(d_iccard[0] != NULL) {
211 set_wait_rw(0xc1000000, 0xc1ffffff, mem_wait_val); // OK?
213 set_wait_rw(0xc2000000, 0xc2141fff, mem_wait_val);
214 set_wait_rw(0xc2200000, 0xc2200fff, mem_wait_val);
215 set_wait_rw(0xfffc0000, 0xffffffff, mem_wait_val);
218 void TOWNS_MEMORY::release()
220 if(rd_table != NULL) free(rd_table);
221 if(rd_dummy != NULL) free(rd_dummy);
222 if(wr_table != NULL) free(wr_table);
223 if(wr_dummy != NULL) free(wr_dummy);
225 if(extra_ram != NULL) {
230 void TOWNS_MEMORY::reset()
234 is_compatible = true;
235 reset_happened = false;
237 nmi_vector_protect = false;
238 ankcg_enabled = false;
240 select_d0_dict = false;
241 select_d0_rom = true;
246 __LIKELY_IF(d_cpu != NULL) {
247 d_cpu->set_address_mask(0xffffffff);
250 d_dmac->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, 0xffffffff, 0xffffffff);
251 uint8_t wrap_val = 0xff; // WRAP OFF
252 if(machine_id >= 0x0b00) { // After MA/MX/ME
255 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP_REG, wrap_val, 0xff);
260 void TOWNS_MEMORY::update_machine_features()
264 if(machine_id >= 0x0b00) { // After MA/MX/ME
265 reg_misc3 &= ~0x04; // DMACMD
267 if(machine_id >= 0x0700) { // After HR/HG
268 reg_misc3 &= ~0x08; // POFFEN
270 if(machine_id >= 0x0700) { // After HR/HG
271 reg_misc3 &= ~0x10; // Free run counter
273 if(machine_id >= 0x0700) { // After HR/HG
274 reg_misc3 &= ~0x20; // CRTPOWOFF (0022h)
276 if(machine_id >= 0x0700) { // After HR/HG
277 reg_misc3 &= ~0x40; // RCREN
279 if(machine_id >= 0x0700) { // After HR/HG
280 reg_misc3 &= ~0x80; // ENPOFF
283 if(machine_id >= 0x0500) { // After CX
290 // Address (TOWNS BASIC):
291 // 0x0020 - 0x0022, 0x0030-0x0031,
295 // 0x05ec (Wait register)
296 // 0x05ed (CPU SPEED REGISTER)
297 // Is set extra NMI (0x05c0 - 0x05c2)?
298 uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
300 // uint32_t val = 0x00; // MAY NOT FILL to "1" for unused bit 20200129 K.O
301 uint32_t val = 0xff; //
302 switch(addr & 0xffff) {
303 case 0x0020: // Software reset ETC.
304 // reset cause register
305 val = ((software_reset) ? 1 : 0) | ((reset_happened) ? 2 : 0);
306 reset_happened = false;
307 software_reset = false;
308 __UNLIKELY_IF(d_cpu != NULL) {
309 d_cpu->set_shutdown_flag(0);
311 if((machine_id >= 0x0300) && ((machine_id & 0xff00) != 0x0400)) { // After UX
312 val = val | ((poff_status) ? 0x04 : 0x00);
317 // if(d_dmac != NULL) {
318 // val = d_dmac->read_signal(SIG_TOWNS_DMAC_ADDR_REG);
331 if(machine_id >= 0x0500) { // After CX
332 val = (nmi_mask) ? 0x01 : 0x00;
337 // From FMTowns::MachineID() of TSUGARU,
338 // git 83d4ec2309ac9fcbb8c01f26061ff0d49c5321e4.
339 // if((config.dipswitch & TOWNS_DIPSW_PRETEND_I386) != 0) {
340 // val = ((machine_id & 0xf8) | 1);
342 val = ((machine_id & 0xf8) | (cpu_id & 7));
346 val = ((machine_id >> 8) & 0xff);
350 //bool __cs = (d_serialrom->read_signal(SIG_SERIALROM_CS) == 0);
351 bool __clk = (d_serialrom->read_signal(SIG_SERIALROM_CLK) != 0);
352 bool __reset = (d_serialrom->read_signal(SIG_SERIALROM_RESET) != 0);
353 bool __dat = (d_serialrom->read_signal(SIG_SERIALROM_DATA) != 0);
354 val = ((__reset) ? 0x80 : 0x00) | ((__clk) ? 0x40 : 0x00) | /*0x3e |*/ ((__dat) ? 0x01 : 0x00);
357 case 0x00c0: // Cache
359 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
360 // ToDo: Implement around cache.
361 // Modified by this register and (05ECh:bit0 / Wait register).
362 // Now, cache is always disabled.
363 // RPNH = 0 (Disabled) : Bit1
364 // CMEN = 0 (Disabled) : Bit0
368 case 0x00c2: // Cache Diagnostic
370 if((cpu_id == 0x02) || (cpu_id >= 0x04)) { // i486 SX/DX or After Pentium.
371 // ToDo: Implement cache disgnostic.
372 // SDMOD (Not diagnostic) : Bit3
376 case 0x0400: // Resolution:
380 case 0x0404: // System Status Reg.
381 // val = (dma_is_vram) ? 0x7f : 0xff;
382 val = (dma_is_vram) ? 0x00 : 0x80;
385 val = (select_d0_dict) ? 0x01 : 0x00;
386 val |= ((select_d0_rom) ? 0x00 : 0x02);
389 // val = (extra_nmi_mask) ? 0xf7 : 0xff;
390 val = (extra_nmi_mask) ? 0x00 : 0x08;
393 // val = (extra_nmi_val) ? 0xff : 0xf7;
394 val = (extra_nmi_val) ? 0x08 : 0x00;
397 if(machine_id < 0x0200) { // Towns 1/2
398 return wait_register;
402 if(machine_id >= 0x0200) { // i386
403 return wait_register;
407 // After Towns1F/2F/1H/2H
409 uint16_t nid = machine_id & 0xff00;
411 val = (extram_size >> 20) & 0x7f; // MAX 128MB
412 } else if(nid >= 0x0900) { // UR,MA,MX,ME,MF
413 val = (extram_size >> 20) & 0x1f; // MAX 32MB
414 } else if(nid == 0x0800) { // HG
415 val = (extram_size >> 20) & 0x0f; // MAX 15MB
416 } else if(nid == 0x0700) { // HR
417 val = (extram_size >> 20) & 0x1f; // MAX 32MB
418 } else if(nid >= 0x0200) { // 2nd GEN,3rd Gen, UX/UG, CX
419 val = (extram_size >> 20) & 0x0f; // MAX 15MB
421 val = 0xff; // NOT SUPPORTED
427 if(machine_id >= 0x0200) { // Towns2H/2F : Is this hidden register after Towns 1F/2F/1H/2H? -> Yes
429 if(mem_wait_val < 1) val |= 0x01;
435 if(machine_id >= 0x0700) { // After HR/HG
436 uint32_t clk = get_cpu_clocks(d_cpu);
437 clk = clk / (1000 * 1000);
438 __UNLIKELY_IF(clk < 16) clk = 16;
439 __UNLIKELY_IF(clk > 127) clk = 127; // ToDo
446 if(machine_id >= 0x0700) { // After HR/HG
447 return (is_compatible) ? 0x00 : 0x01;
453 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
454 __LIKELY_IF(d_crtc != NULL) {
455 val = d_crtc->read_signal(SIG_TOWNS_CRTC_MMIO_CFF82H);
457 } else __LIKELY_IF(d_planevram != NULL) {
458 val = d_planevram->read_io8(addr);
467 __LIKELY_IF(d_font != NULL) {
468 return d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_LOW);
472 __LIKELY_IF(d_font != NULL) {
473 return d_font->read_signal(SIG_TOWNS_FONT_KANJI_DATA_HIGH);
477 __LIKELY_IF(d_timer != NULL) {
478 d_timer->write_signal(SIG_TIMER_BEEP_ON, 1, 1);
482 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
483 val = (ankcg_enabled) ? 0x01 : 0x00;
484 } else __LIKELY_IF(d_planevram != NULL) {
485 val = d_planevram->read_memory_mapped_io8(addr);
489 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
490 __LIKELY_IF(d_font != NULL) {
491 val = d_font->read_signal(SIG_TOWNS_FONT_KANJI_HIGH);
493 } else __LIKELY_IF(d_planevram != NULL) {
494 val = d_planevram->read_io8(addr);
498 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
499 __LIKELY_IF(d_font != NULL) {
500 val = d_font->read_signal(SIG_TOWNS_FONT_KANJI_LOW);
502 } else __LIKELY_IF(d_planevram != NULL) {
503 val = d_planevram->read_io8(addr);
507 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
508 __LIKELY_IF(d_font != NULL) {
509 val = d_font->read_signal(SIG_TOWNS_FONT_KANJI_ROW);
511 } else __LIKELY_IF(d_planevram != NULL) {
512 val = d_planevram->read_io8(addr);
516 __LIKELY_IF(d_planevram != NULL) {
517 val = d_planevram->read_io8(addr);
524 uint32_t TOWNS_MEMORY::read_io16(uint32_t addr)
529 n.b.l = read_io8((addr & 0xfffe) + 0);
530 n.b.h = read_io8((addr & 0xfffe) + 1);
536 void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
539 switch(addr & 0xffff) {
540 case 0x0020: // Software reset ETC.
541 // reset cause register
542 if((data & 0x80) != 0) {
543 nmi_vector_protect = true;
545 nmi_vector_protect = false;
547 if((data & 0x01) != 0) {
548 software_reset = true;
550 software_reset = false;
553 if((data & 0x40) != 0) {
555 __LIKELY_IF(d_cpu != NULL) {
556 d_cpu->set_shutdown_flag(1);
558 // Todo: Implement true power off.
559 emu->notify_power_off();
563 __LIKELY_IF(d_cpu != NULL) {
564 d_cpu->set_shutdown_flag(0);
569 __LIKELY_IF(d_cpu != NULL) {
572 uint8_t wrap_val = 0xff; // WRAP OFF
573 if(machine_id >= 0x0b00) { // After MA/MX/ME
576 __LIKELY_IF(d_dmac != NULL) {
577 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP_REG, wrap_val, 0xff);
580 // Towns SEEMS to not set addreess mask (a.k.a A20 mask). 20200131 K.O
583 if((data & 0x40) != 0) {
584 __LIKELY_IF(d_cpu != NULL) {
585 d_cpu->set_shutdown_flag(1);
587 // Todo: Implement true power off.
593 // if(d_dmac != NULL) {
594 // d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP_REG, data, 0xff);
599 d_serialrom->write_signal(SIG_SERIALROM_CS, ~data, 0x20);
600 d_serialrom->write_signal(SIG_SERIALROM_CLK, data, 0x40);
601 d_serialrom->write_signal(SIG_SERIALROM_RESET, data, 0x80);
604 case 0x0404: // System Status Reg.
606 bool _b = dma_is_vram;
607 dma_is_vram = ((data & 0x80) == 0);
608 if((_b != dma_is_vram)/* || (dma_is_vram)*/) {
616 bool _dict = select_d0_dict;
617 // bool _rom = select_d0_rom;
618 select_d0_dict = ((data & 0x01) != 0) ? true : false;
619 select_d0_rom = ((data & 0x02) == 0) ? true : false;
620 //if(_rom != select_d0_rom) {
621 // config_page_f8_rom();
623 if(_dict != select_d0_dict) {
629 extra_nmi_mask = ((data & 0x08) == 0);
633 if(machine_id < 0x0200) { // Towns 1/2
634 uint8_t nval = data & 7;
635 uint8_t val_bak = mem_wait_val;
636 if(nval < 1) nval = 1;
637 if(nval > 5) nval = 5;
638 mem_wait_val = nval + 1;
639 vram_wait_val = nval + 3 + 1;
640 wait_register = nval;
641 if(val_bak != mem_wait_val) {
647 if(machine_id >= 0x0200) { // After Towns 1H/2F. Hidden wait register.
648 uint8_t val_bak = mem_wait_val;
650 uint8_t nval = data & 7;
651 if(machine_id <= 0x0200) { // Towns 1H/2F.
652 if(nval < 1) nval = 1;
654 if(nval > 5) nval = 5;
656 vram_wait_val = nval + 3;
657 wait_register = nval;
661 wait_register = data;
663 if(val_bak != mem_wait_val) {
669 if(machine_id >= 0x0500) { // Towns2 CX :
670 uint8_t val_bak = mem_wait_val;
671 uint32_t clk_bak = cpu_clock_val;
672 vram_wait_val = ((data & 0x01) != 0) ? 3 : 6;
673 mem_wait_val = ((data & 0x01) != 0) ? 0 : 3;
674 cpu_clock_val = ((data & 0x01) != 0) ? (get_cpu_clocks(d_cpu)) : (16 * 1000 * 1000);
675 if((val_bak != mem_wait_val) || (cpu_clock_val != clk_bak)) {
681 if(machine_id >= 0x0700) { // After HR/HG
682 is_compatible = ((data & 0x01) == 0x00) ? true : false;
683 __LIKELY_IF(d_crtc != NULL) {
684 d_crtc->write_signal(SIG_TOWNS_CRTC_COMPATIBLE_MMIO, (is_compatible) ? 0xffffffff : 0x00000000, 0xffffffff);
689 __LIKELY_IF(d_font != NULL) {
690 d_font->write_signal(SIG_TOWNS_FONT_KANJI_HIGH, data, 0xff);
694 __LIKELY_IF(d_font != NULL) {
695 d_font->write_signal(SIG_TOWNS_FONT_KANJI_LOW, data, 0xff);
703 __LIKELY_IF(d_timer != NULL) {
704 d_timer->write_signal(SIG_TIMER_BEEP_ON, 0, 1);
709 bool _b = ankcg_enabled;
710 ankcg_enabled = ((data & 1) != 0) ? true : false;
711 if((_b != ankcg_enabled) && (dma_is_vram)) {
717 if((machine_id >= 0x0600) && !(is_compatible)) { // After UG
718 __LIKELY_IF(d_font != NULL) {
719 d_font->write_signal(SIG_TOWNS_FONT_KANJI_ROW, data, 0xff);
721 } else __LIKELY_IF(d_planevram != NULL) {
722 d_planevram->write_io8(addr , data);
726 __LIKELY_IF(d_planevram != NULL) {
727 d_planevram->write_io8(addr , data);
734 // At page 000C0000h - 000CFFFFh : Maybe return real memory for word/dword access.
735 uint32_t TOWNS_MEMORY::read_memory_mapped_io16(uint32_t addr)
737 if((addr >= 0xc0000) && (addr <= 0xcffff)) {
740 n.b.l = ram_pagec[(addr & 0xffff) + 0];
741 n.b.h = ram_pagec[(addr & 0xffff) + 1];
747 uint32_t TOWNS_MEMORY::read_memory_mapped_io32(uint32_t addr)
749 if((addr >= 0xc0000) && (addr <= 0xcffff)) {
752 n.b.l = ram_pagec[(addr & 0xffff) + 0];
753 n.b.h = ram_pagec[(addr & 0xffff) + 1];
754 n.b.h2 = ram_pagec[(addr & 0xffff) + 2];
755 n.b.h3 = ram_pagec[(addr & 0xffff) + 3];
761 uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
764 __LIKELY_IF(addr < 0xcff80) {
765 return ram_pagec[addr & 0xffff];
767 __LIKELY_IF((addr >= 0x000f8000) && (addr < 0x00100000)) {
768 __LIKELY_IF(!(select_d0_rom)) {
769 return ram_pagef[addr & 0xffff];
771 __LIKELY_IF(d_sysrom != nullptr) {
772 return d_sysrom->read_memory_mapped_io8(addr);
776 __UNLIKELY_IF(addr >= 0xd0000) {
789 val = read_io8(addr & 0xffff);
792 __LIKELY_IF(d_planevram != NULL) {
793 val = d_planevram->read_io8(addr & 0xffff);
797 return (uint32_t)val;
800 void TOWNS_MEMORY::write_memory_mapped_io16(uint32_t addr, uint32_t data)
802 if((addr >= 0xc0000) && (addr <= 0xcffff)) {
805 ram_pagec[(addr & 0xffff) + 0] = n.b.l;
806 ram_pagec[(addr & 0xffff) + 1] = n.b.h;
810 void TOWNS_MEMORY::write_memory_mapped_io32(uint32_t addr, uint32_t data)
812 if((addr >= 0xc0000) && (addr <= 0xcffff)) {
815 ram_pagec[(addr & 0xffff) + 0] = n.b.l;
816 ram_pagec[(addr & 0xffff) + 1] = n.b.h;
817 ram_pagec[(addr & 0xffff) + 2] = n.b.h2;
818 ram_pagec[(addr & 0xffff) + 3] = n.b.h3;
823 void TOWNS_MEMORY::write_memory_mapped_io8(uint32_t addr, uint32_t data)
825 __LIKELY_IF(addr < 0xcff80) {
826 ram_pagec[addr & 0xffff] = data;
829 __LIKELY_IF((addr >= 0x000f8000) && (addr < 0x00100000)) {
830 __LIKELY_IF(!(select_d0_rom)) {
831 ram_pagef[addr & 0xffff] = data;
835 __UNLIKELY_IF(addr >= 0xd0000) {
844 write_io8(addr & 0xffff, data);
847 __LIKELY_IF(d_planevram != NULL) {
848 d_planevram->write_io8(addr & 0xffff, data);
855 void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int* wait)
857 int bank = (addr & addr_mask) >> addr_shift;
859 MEMORY::write_data16w(addr, data, &dummy);
860 // Note: WAIT valus may be same as 1 bytes r/w.
861 __LIKELY_IF(wait != NULL) {
862 *wait = wr_table[bank].wait;
866 void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int* wait)
868 int bank = (addr & addr_mask) >> addr_shift;
870 MEMORY::write_data32w(addr, data, &dummy);
871 // Note: WAIT valus may be same as 1 bytes r/w.
872 __LIKELY_IF(wait != NULL) {
873 *wait = wr_table[bank].wait;
878 uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int* wait)
880 int bank = (addr & addr_mask) >> addr_shift;
882 uint32_t val = MEMORY::read_data16w(addr, &dummy);
883 // Note: WAIT valus may be same as 1 bytes r/w.
884 __LIKELY_IF(wait != NULL) {
885 *wait = wr_table[bank].wait;
890 uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int* wait)
892 int bank = (addr & addr_mask) >> addr_shift;
893 // Note: WAIT valus may be same as 1 bytes r/w.
895 uint32_t val = MEMORY::read_data32w(addr, &dummy);
896 __LIKELY_IF(wait != NULL) {
897 *wait = wr_table[bank].wait;
903 uint32_t TOWNS_MEMORY::read_dma_data8(uint32_t addr)
905 int bank = (addr & addr_mask) >> addr_shift;
907 __UNLIKELY_IF(rd_table[bank].device != NULL) {
908 return rd_table[bank].device->read_memory_mapped_io8(addr);
910 return rd_table[bank].memory[addr & bank_mask];
914 uint32_t TOWNS_MEMORY::read_dma_data16(uint32_t addr)
916 int bank = (addr & addr_mask) >> addr_shift;
918 __UNLIKELY_IF(rd_table[bank].device != NULL) {
919 return rd_table[bank].device->read_memory_mapped_io16(addr);
921 uint32_t naddr = addr & bank_mask;
925 __UNLIKELY_IF((naddr + 1) > bank_mask) {
926 n.b.l = rd_table[bank].memory[naddr];
927 n.b.h = read_dma_data8(addr + 1);
929 n.b.l = rd_table[bank].memory[naddr + 0];
930 n.b.h = rd_table[bank].memory[naddr + 1];
936 uint32_t TOWNS_MEMORY::read_dma_data32(uint32_t addr)
938 int bank = (addr & addr_mask) >> addr_shift;
940 __UNLIKELY_IF(rd_table[bank].device != NULL) {
941 return rd_table[bank].device->read_memory_mapped_io32(addr);
943 uint32_t naddr = addr & bank_mask;
947 __UNLIKELY_IF((naddr + 3) > bank_mask) {
948 n.b.l = rd_table[bank].memory[naddr];
949 n.b.h = read_dma_data8(addr + 1);
950 n.b.h2 = read_dma_data8(addr + 2);
951 n.b.h3 = read_dma_data8(addr + 3);
953 n.b.l = rd_table[bank].memory[naddr + 0];
954 n.b.h = rd_table[bank].memory[naddr + 1];
955 n.b.h2 = rd_table[bank].memory[naddr + 2];
956 n.b.h3 = rd_table[bank].memory[naddr + 3];
962 void TOWNS_MEMORY::write_dma_data8(uint32_t addr, uint32_t data)
964 int bank = (addr & addr_mask) >> addr_shift;
966 __UNLIKELY_IF(wr_table[bank].device != NULL) {
967 wr_table[bank].device->write_memory_mapped_io8(addr, data);
969 wr_table[bank].memory[addr & bank_mask] = data;
973 void TOWNS_MEMORY::write_dma_data16(uint32_t addr, uint32_t data)
975 int bank = (addr & addr_mask) >> addr_shift;
977 __UNLIKELY_IF(wr_table[bank].device != NULL) {
978 wr_table[bank].device->write_memory_mapped_io16(addr, data);
980 uint32_t naddr = addr & bank_mask;
984 __UNLIKELY_IF((naddr + 1) > bank_mask) {
985 wr_table[bank].memory[naddr] = n.b.l;
986 write_dma_data8(addr + 1, n.b.h);
988 wr_table[bank].memory[naddr + 0] = n.b.l;
989 wr_table[bank].memory[naddr + 1] = n.b.h;
994 void TOWNS_MEMORY::write_dma_data32(uint32_t addr, uint32_t data)
996 int bank = (addr & addr_mask) >> addr_shift;
998 __UNLIKELY_IF(wr_table[bank].device != NULL) {
999 wr_table[bank].device->write_memory_mapped_io32(addr, data);
1001 uint32_t naddr = addr & bank_mask;
1005 __UNLIKELY_IF((naddr + 3) > bank_mask) {
1006 wr_table[bank].memory[naddr] = n.b.l;
1007 write_dma_data8(addr + 1, n.b.h);
1008 write_dma_data8(addr + 2, n.b.h2);
1009 write_dma_data8(addr + 3, n.b.h3);
1011 wr_table[bank].memory[naddr + 0] = n.b.l;
1012 wr_table[bank].memory[naddr + 1] = n.b.h;
1013 wr_table[bank].memory[naddr + 2] = n.b.h2;
1014 wr_table[bank].memory[naddr + 3] = n.b.h3;
1019 uint32_t TOWNS_MEMORY::read_dma_data8w(uint32_t addr, int* wait)
1021 uint32_t val = read_dma_data8(addr);
1023 __LIKELY_IF(wait != NULL) {
1024 int bank = (addr & addr_mask) >> addr_shift;
1025 *wait = wr_table[bank].wait;
1030 uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
1032 uint32_t val = read_dma_data16(addr);
1034 __LIKELY_IF(wait != NULL) {
1035 int bank = (addr & addr_mask) >> addr_shift;
1036 *wait = wr_table[bank].wait;
1041 uint32_t TOWNS_MEMORY::read_dma_data32w(uint32_t addr, int* wait)
1043 uint32_t val = read_dma_data32(addr);
1045 __LIKELY_IF(wait != NULL) {
1046 int bank = (addr & addr_mask) >> addr_shift;
1047 *wait = wr_table[bank].wait;
1052 void TOWNS_MEMORY::write_dma_data8w(uint32_t addr, uint32_t data, int* wait)
1054 write_dma_data8(addr, data);
1056 __LIKELY_IF(wait != NULL) {
1057 int bank = (addr & addr_mask) >> addr_shift;
1058 *wait = wr_table[bank].wait;
1063 void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
1065 write_dma_data16(addr, data);
1067 __LIKELY_IF(wait != NULL) {
1068 int bank = (addr & addr_mask) >> addr_shift;
1069 *wait = wr_table[bank].wait;
1074 void TOWNS_MEMORY::write_dma_data32w(uint32_t addr, uint32_t data, int* wait)
1076 write_dma_data32(addr, data);
1078 __LIKELY_IF(wait != NULL) {
1079 int bank = (addr & addr_mask) >> addr_shift;
1080 *wait = wr_table[bank].wait;
1085 void TOWNS_MEMORY::write_signal(int ch, uint32_t data, uint32_t mask)
1087 if(ch == SIG_MEMORY_EXTNMI) {
1088 extra_nmi_val = ((data & mask) != 0);
1089 if(!(extra_nmi_mask)) {
1091 __LIKELY_IF(d_cpu != NULL) {
1092 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
1095 } else if(ch == SIG_CPU_NMI) {
1098 __LIKELY_IF(d_cpu != NULL) {
1099 d_cpu->write_signal(SIG_CPU_NMI, data, mask);
1102 } else if(ch == SIG_CPU_IRQ) {
1103 __LIKELY_IF(d_cpu != NULL) {
1104 d_cpu->write_signal(SIG_CPU_IRQ, data, mask);
1106 } else if(ch == SIG_CPU_BUSREQ) {
1107 __LIKELY_IF(d_cpu != NULL) {
1108 d_cpu->write_signal(SIG_CPU_BUSREQ, data, mask);
1110 } else if(ch == SIG_I386_A20) {
1111 __LIKELY_IF(d_cpu != NULL) {
1112 d_cpu->write_signal(SIG_I386_A20, data, mask);
1114 } else if(ch == SIG_FMTOWNS_NOTIFY_RESET) {
1115 out_debug_log("RESET FROM CPU!!!\n");
1116 reset_happened = true;
1118 nmi_vector_protect = false;
1119 ankcg_enabled = false;
1121 select_d0_dict = false;
1122 select_d0_rom = true;
1126 __LIKELY_IF(d_cpu != NULL) {
1127 d_cpu->set_address_mask(0xffffffff);
1129 __LIKELY_IF(d_dmac != NULL) {
1130 d_dmac->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, 0xffffffff, 0xffffffff);
1131 uint8_t wrap_val = 0xff; // WRAP OFF
1132 if(machine_id >= 0x0b00) { // After MA/MX/ME
1135 d_dmac->write_signal(SIG_TOWNS_DMAC_WRAP_REG, wrap_val, 0xff);
1137 } else if(ch == SIG_FMTOWNS_RAM_WAIT) {
1138 uint8_t _bak = mem_wait_val;
1139 mem_wait_val = (int)data;
1140 if(_bak != mem_wait_val) {
1143 } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
1144 // mem_wait_val = (int)data;
1146 } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
1147 uint8_t _bak = vram_wait_val;
1148 vram_wait_val = (int)data;
1149 if(_bak != vram_wait_val) {
1155 uint32_t TOWNS_MEMORY::read_signal(int ch)
1157 if(ch == SIG_FMTOWNS_MACHINE_ID) {
1158 uint16_t d = (machine_id & 0xfff8) | ((uint16_t)(cpu_id & 0x07));
1160 } else if(ch == SIG_FMTOWNS_RAM_WAIT) {
1161 return (uint32_t)mem_wait_val;
1162 } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
1164 } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
1165 return (uint32_t)vram_wait_val;
1170 void TOWNS_MEMORY::set_intr_line(bool line, bool pending, uint32_t bit)
1172 __LIKELY_IF(d_cpu != NULL) {
1173 d_cpu->set_intr_line(line, pending, bit);
1179 #define STATE_VERSION 5
1181 bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
1183 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1187 if(!state_fio->StateCheckInt32(this_device_id)) {
1190 state_fio->StateValue(machine_id);
1191 state_fio->StateValue(cpu_id);
1192 state_fio->StateValue(is_compatible);
1194 state_fio->StateValue(mem_wait_val);
1195 state_fio->StateValue(vram_wait_val);
1196 state_fio->StateValue(wait_register);
1198 state_fio->StateValue(dma_is_vram);
1199 state_fio->StateValue(nmi_vector_protect);
1200 state_fio->StateValue(software_reset);
1201 state_fio->StateValue(poff_status);
1202 state_fio->StateValue(reset_happened);
1204 state_fio->StateValue(extra_nmi_val);
1205 state_fio->StateValue(extra_nmi_mask);
1206 state_fio->StateValue(nmi_mask);
1208 state_fio->StateArray(ram_page0, sizeof(ram_page0), 1);
1209 state_fio->StateArray(ram_pagec, sizeof(ram_pagec), 1);
1210 state_fio->StateArray(ram_paged, sizeof(ram_paged), 1);
1211 state_fio->StateArray(ram_pagef, sizeof(ram_pagef), 1);
1213 state_fio->StateValue(select_d0_rom);
1214 state_fio->StateValue(select_d0_dict);
1215 state_fio->StateValue(ankcg_enabled);
1217 state_fio->StateValue(vram_wait_val);
1218 state_fio->StateValue(mem_wait_val);
1219 state_fio->StateValue(vram_size);
1220 state_fio->StateValue(cpu_clock_val);
1223 update_machine_features(); // Update MISC3, MISC4 by MACHINE ID.
1225 uint32_t length_tmp = state_fio->FgetUint32_LE();
1226 if(extra_ram != NULL) {
1230 length_tmp = length_tmp & 0x3ff00000;
1231 extram_size = length_tmp;
1232 if(length_tmp > 0) {
1233 extra_ram = (uint8_t*)malloc(length_tmp);
1235 unset_memory_rw(0x00100000, 0x3fffffff);
1236 if(extra_ram == NULL) {
1240 state_fio->Fread(extra_ram, extram_size, 1);
1241 set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
1247 if(extra_ram == NULL) {
1248 state_fio->FputUint32_LE(0);
1250 state_fio->FputUint32_LE(extram_size & 0x3ff00000);
1251 state_fio->Fwrite(extra_ram, extram_size, 1);
1255 // ToDo: Do save ROMs?