2 * Main memory MMR for FM-7 [FM7_MAINMEM]
10 #include "fm7_mainmem.h"
11 #include "fm7_mainio.h"
12 #include "fm7_display.h"
13 #if defined(CAPABLE_DICTROM)
19 FM7_MAINMEM::FM7_MAINMEM(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
21 #if !defined(_FM77AV_VARIANTS)
22 for(int i = 0; i < 8; i++) fm7_bootroms[i] = (uint8_t *)malloc(0x200);
27 #if defined(CAPABLE_DICTROM)
30 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
31 defined(_FM77_VARIANTS)
32 fm7_mainmem_extram = NULL;
34 cpu_clocks = CPU_CLOCKS;
36 set_device_name(_T("MAIN MEMORY"));
39 FM7_MAINMEM::~FM7_MAINMEM()
41 #if !defined(_FM77AV_VARIANTS)
42 for(int i = 0; i < 8; i++) if(fm7_bootroms[i] != NULL) free(fm7_bootroms[i]);
46 void FM7_MAINMEM::reset()
52 ioaccess_wait = false;
53 sub_halted = (display->read_signal(SIG_DISPLAY_HALT) == 0) ? false : true;
55 memset(fm7_mainmem_bootrom_vector, 0x00, 0x10); // Clear without vector
57 #if defined(_FM77AV_VARIANTS)
58 memset(fm7_bootram, 0x00, 0x1f0);
59 initiator_enabled = true;
60 boot_ram_write = true;
61 #elif defined(_FM77_VARIANTS)
62 boot_ram_write = false;
64 #if defined(_FM77_VARIANTS) || defined(_FM8)
65 bootmode = config.boot_mode & 7;
67 bootmode = config.boot_mode & 3;
70 if((config.dipswitch & FM7_DIPSW_EXTRAM) != 0) {
71 extram_connected = true;
73 extram_connected = false;
76 #if defined(_FM77AV_VARIANTS)
77 if(dictrom_connected) {
78 use_page2_extram = true;
80 use_page2_extram = ((config.dipswitch & FM7_DIPSW_EXTRAM_AV) != 0) ? true : false;
89 window_enabled = false;
93 if((bootmode & 0x03) == 0) { // IF BASIC BOOT THEN ROM
96 basicrom_fd0f = false;
98 clockmode = (config.cpu_type == 0) ? true : false;
99 is_basicrom = ((bootmode & 0x03) == 0) ? true : false;
100 setclock(clockmode ? 0 : 1);
102 update_all_mmr_jumptable();
107 void FM7_MAINMEM::setclock(int mode)
109 uint32_t clock = MAINCLOCK_SLOW;
110 if(mode == 1) { // SLOW
111 clock = MAINCLOCK_SLOW; // Temporally
113 if(!mmr_fast && !window_fast) {
115 if(mmr_enabled || window_enabled) {
116 clock = (uint32_t)((double)clock * 1.089);
118 clock = (uint32_t)((double)clock * 1.086);
125 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
126 // Thanks to Ryu Takegami, around DRAM refresh.
127 // DRAM refresh makes halting MAIN MPU per 13.02uS.
128 if(!mmr_fast && !window_fast) { // SLOW
130 clock = MAINCLOCK_FAST_MMR - ((100000000 / 1302) * 1); // Fast Refresh: 1wait
132 clock = MAINCLOCK_FAST_MMR - ((100000000 / 1302) * 3); // Slow Refresh: 3Wait(!)
134 if(mmr_enabled || window_enabled) {
135 clock = (uint32_t)((double)clock * 0.87);
138 clock = MAINCLOCK_FAST_MMR;
139 //if(!(mmr_enabled) && !(window_enabled)) clock = MAINCLOCK_NORMAL;
142 if(mmr_enabled || window_enabled) {
143 clock = MAINCLOCK_MMR;
145 clock = MAINCLOCK_NORMAL;
149 clock = MAINCLOCK_NORMAL;
153 uint32_t before_waitfactor = mem_waitfactor;
154 if(CPU_CLOCKS > clock) {
155 mem_waitfactor = (uint32_t)(65536.0 * ((1.0 - (double)clock / (double)CPU_CLOCKS)));
156 //out_debug_log(_T("CLOCK=%d WAIT FACTOR=%d"), clock, mem_waitfactor);
159 //out_debug_log(_T("CLOCK=%d WAIT FACTOR=%d"), clock, mem_waitfactor);
162 // Below is ugly hack cause of CPU#0 cannot modify clock.
163 if(before_waitfactor != mem_waitfactor) maincpu->write_signal(SIG_CPU_WAIT_FACTOR, mem_waitfactor, 0xffffffff);
167 void FM7_MAINMEM::iowait()
170 if(config.cpu_type == 1) return; // SLOW
172 if((window_enabled) || (mmr_enabled)) {
175 } else { // Not MMR, TWR or enabled FAST MMR mode
176 _waitfactor = 3; // If(MMR or TWR) and NOT FAST MMR factor = 3, else factor = 2
177 if(mmr_fast) _waitfactor = 2;
185 if(_waitfactor <= 0) return;
187 if(waitcount >= _waitfactor) {
188 maincpu->set_extra_clock(1);
190 ioaccess_wait = !ioaccess_wait;
196 int FM7_MAINMEM::check_extrom(uint32_t raddr, uint32_t *realaddr)
198 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
199 if(extrom_bank) { // Extra ROM selected.
200 uint32_t dbank = extcard_bank & 0x3f;
201 if(dbank < 0x20) { // KANJI
202 if((dbank == 0x07) || (dbank == 0x06)) {
203 // NOT KANJI AS IS.Thanks Ryu.
204 *realaddr = raddr & 0x01;
205 return FM7_MAINMEM_KANJI_DUMMYADDR;
207 *realaddr = (dbank << 12) | raddr;
208 return FM7_MAINMEM_KANJI_LEVEL1;
209 } else if(dbank < 0x2c) {
210 raddr = ((dbank << 12) - 0x20000) | raddr;
212 return FM7_MAINMEM_77AV40_EXTRAROM;
213 } else if(dbank < 0x30) {
215 return FM7_MAINMEM_NULL;
217 raddr = ((dbank << 12) - 0x30000) | raddr;
218 if((raddr >= 0x8000) && (raddr < 0xfc00)) {
219 *realaddr = raddr - 0x8000;
220 return FM7_MAINMEM_BASICROM;
221 } else if((raddr >= 0xfe00) && (raddr < 0xffe0)) {
222 *realaddr = raddr - 0xfe00;
223 return FM7_MAINMEM_BOOTROM_MMR;
224 } else if(raddr >= 0xfffe) {
225 *realaddr = raddr - 0xfffe;
226 return FM7_MAINMEM_RESET_VECTOR;
228 //*realaddr = raddr + 0x10000;
229 //return FM7_MAINMEM_77AV40_EXTRAROM;
231 return FM7_MAINMEM_NULL;
239 uint32_t FM7_MAINMEM::read_signal(int sigid)
241 uint32_t value = 0x00000000;
243 case FM7_MAINIO_PUSH_FD0F:
244 value = (basicrom_fd0f) ? 0xffffffff : 0x00000000;
246 case FM7_MAINIO_IS_BASICROM:
247 value = (is_basicrom) ? 0xffffffff : 0x00000000;
249 case FM7_MAINIO_CLOCKMODE:
250 value = (clockmode) ? 0xffffffff : 0x00000000;
252 case FM7_MAINIO_BOOTMODE:
253 value = (uint32_t)bootmode & 0x07;
255 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
256 case FM7_MAINIO_BOOTRAM_RW:
257 value = (boot_ram_write) ? 0xffffffff : 0x00000000;
261 case FM7_MAINIO_WINDOW_ENABLED:
262 value = (window_enabled) ? 0xffffffff : 0x00000000;
264 case FM7_MAINIO_WINDOW_FAST:
265 value = (window_fast) ? 0xffffffff : 0x00000000;
267 case FM7_MAINIO_FASTMMR_ENABLED:
268 value = (mmr_fast) ? 0xffffffff : 0x00000000;
270 case FM7_MAINIO_MMR_ENABLED:
271 value = (mmr_enabled) ? 0xffffffff : 0x00000000;
273 case FM7_MAINIO_MMR_EXTENDED:
274 value = (mmr_extend) ? 0xffffffff : 0x00000000;
276 case FM7_MAINIO_MEM_REFRESH_FAST:
277 value = (refresh_fast) ? 0xffffffff : 0x00000000;
280 #if defined(_FM77AV_VARIANTS)
281 case FM7_MAINIO_INITROM_ENABLED:
282 value = (initiator_enabled) ? 0xffffffff: 0x00000000;
284 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
285 case FM7_MAINIO_EXTROM:
286 value = (extrom_bank) ? 0xffffffff: 0x00000000;
289 case FM7_MAINIO_EXTBANK:
290 value = extcard_bank & 0x3f;
291 value |= (dictram_enabled) ? 0x80 : 0;
292 value |= (dictrom_enabled) ? 0x40 : 0;
300 void FM7_MAINMEM::write_signal(int sigid, uint32_t data, uint32_t mask)
302 bool flag = ((data & mask) != 0);
304 case SIG_FM7_SUB_HALT:
307 case FM7_MAINIO_IS_BASICROM:
310 case FM7_MAINIO_PUSH_FD0F:
311 basicrom_fd0f = flag;
313 case FM7_MAINIO_CLOCKMODE:
315 setclock(clockmode ? 0 : 1);
317 case FM7_MAINIO_BOOTMODE:
318 bootmode = data & 0x07;
320 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
321 case FM7_MAINIO_BOOTRAM_RW:
322 boot_ram_write = flag;
325 #ifdef _FM77AV_VARIANTS
326 case FM7_MAINIO_INITROM_ENABLED:
327 initiator_enabled = flag;
329 case FM7_MAINIO_EXTBANK:
330 extcard_bank = data & 0x3f;
331 dictram_enabled = ((data & 0x80) != 0) ? true : false;
332 dictrom_enabled = ((data & 0x40) != 0) ? true : false;
334 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
335 case FM7_MAINIO_EXTROM:
341 case FM7_MAINIO_WINDOW_ENABLED:
342 window_enabled = flag;
343 setclock(config.cpu_type);
345 case FM7_MAINIO_WINDOW_FAST:
347 setclock(config.cpu_type);
349 case FM7_MAINIO_FASTMMR_ENABLED:
351 setclock(config.cpu_type);
353 case FM7_MAINIO_MMR_ENABLED:
355 setclock(config.cpu_type);
357 case FM7_MAINIO_MMR_EXTENDED:
360 case FM7_MAINIO_MEM_REFRESH_FAST:
362 setclock(config.cpu_type);
368 uint32_t FM7_MAINMEM::read_io8(uint32_t addr)
370 return mainio->read_io8(addr);
373 void FM7_MAINMEM::write_io8(uint32_t addr, uint32_t data)
375 return mainio->write_io8(addr, data);
378 uint32_t FM7_MAINMEM::read_dma_data8(uint32_t addr)
382 val = this->read_data8_main(addr & 0xffff, true);
385 return this->read_data8(addr & 0xffff);
389 uint32_t FM7_MAINMEM::read_dma_io8(uint32_t addr)
393 val = this->read_data8_main(addr & 0xffff, true);
396 return this->read_data8(addr & 0xffff);
400 uint32_t FM7_MAINMEM::read_data8(uint32_t addr)
403 if(addr >= FM7_MAINIO_WINDOW_OFFSET) {
405 case FM7_MAINIO_WINDOW_OFFSET:
406 return (uint32_t)window_offset;
408 case FM7_MAINIO_MMR_SEGMENT:
409 return (uint32_t)mmr_segment;
412 if((addr >= FM7_MAINIO_MMR_BANK) && (addr < (FM7_MAINIO_MMR_BANK + 0x80))){
413 return mmr_map_data[addr - FM7_MAINIO_MMR_BANK];
420 return read_data8_main(addr, false);
423 void FM7_MAINMEM::write_dma_data8(uint32_t addr, uint32_t data)
426 write_data8_main(addr & 0xffff, data, true);
428 write_data8(addr & 0xffff, data);
432 void FM7_MAINMEM::write_dma_io8(uint32_t addr, uint32_t data)
435 write_data8_main(addr & 0xffff, data, true);
437 write_data8(addr & 0xffff, data);
441 void FM7_MAINMEM::write_data8(uint32_t addr, uint32_t data)
444 if(addr >= FM7_MAINIO_WINDOW_OFFSET) {
446 case FM7_MAINIO_WINDOW_OFFSET:
447 window_offset = data;
449 case FM7_MAINIO_MMR_SEGMENT:
451 mmr_segment = data & 0x07;
453 mmr_segment = data & 0x03;
457 if((addr >= FM7_MAINIO_MMR_BANK) && (addr < (FM7_MAINIO_MMR_BANK + 0x80))){
458 mmr_map_data[addr - FM7_MAINIO_MMR_BANK] = (uint8_t)data;
459 update_mmr_jumptable(addr - FM7_MAINIO_MMR_BANK);
466 write_data8_main(addr, data, false);
469 // Read / Write data(s) as big endian.
470 uint32_t FM7_MAINMEM::read_data16(uint32_t addr)
475 hi = read_data8(addr) & 0xff;
476 lo = read_data8(addr + 1) & 0xff;
482 uint32_t FM7_MAINMEM::read_data32(uint32_t addr)
484 uint32_t ah, a2, a3, al;
487 ah = read_data8(addr) & 0xff;
488 a2 = read_data8(addr + 1) & 0xff;
489 a3 = read_data8(addr + 2) & 0xff;
490 al = read_data8(addr + 3) & 0xff;
492 val = ah * (65536 * 256) + a2 * 65536 + a3 * 256 + al;
496 void FM7_MAINMEM::write_data16(uint32_t addr, uint32_t data)
500 write_data8(addr + 1, d & 0xff);
502 write_data8(addr + 0, d & 0xff);
505 void FM7_MAINMEM::write_data32(uint32_t addr, uint32_t data)
509 write_data8(addr + 3, d & 0xff);
511 write_data8(addr + 2, d & 0xff);
513 write_data8(addr + 1, d & 0xff);
515 write_data8(addr + 0, d & 0xff);
519 void FM7_MAINMEM::update_config()
521 setclock(config.cpu_type);
524 #define STATE_VERSION 8
526 bool FM7_MAINMEM::decl_state(FILEIO *state_fio, bool loading)
528 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
531 if(!state_fio->StateCheckInt32(this_device_id)) {
535 state_fio->StateBool(ioaccess_wait);
536 state_fio->StateInt32(waitfactor);
537 state_fio->StateInt32(waitcount);
538 state_fio->StateBool(sub_halted);
540 state_fio->StateBool(diag_load_basicrom);
541 state_fio->StateBool(diag_load_bootrom_bas);
542 state_fio->StateBool(diag_load_bootrom_dos);
543 state_fio->StateBool(diag_load_bootrom_mmr);
544 state_fio->StateBool(diag_load_bootrom_bubble);
545 state_fio->StateBool(diag_load_bootrom_bubble_128k);
546 state_fio->StateBool(diag_load_bootrom_sfd8);
547 state_fio->StateBool(diag_load_bootrom_2hd);
549 state_fio->StateBuffer(fm7_mainmem_omote, sizeof(fm7_mainmem_omote), 1);
550 state_fio->StateBuffer(fm7_mainmem_ura, sizeof(fm7_mainmem_ura), 1);
551 state_fio->StateBuffer(fm7_mainmem_basicrom, sizeof(fm7_mainmem_basicrom), 1);
552 state_fio->StateBuffer(fm7_mainmem_bioswork, sizeof(fm7_mainmem_bioswork), 1);
553 state_fio->StateBuffer(fm7_mainmem_bootrom_vector, sizeof(fm7_mainmem_bootrom_vector), 1);
554 state_fio->StateBuffer(fm7_mainmem_reset_vector, sizeof(fm7_mainmem_reset_vector), 1);
556 state_fio->StateBuffer(fm7_mainmem_null, sizeof(fm7_mainmem_null), 1);
558 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
559 state_fio->StateBuffer(fm7_bootram, sizeof(fm7_bootram), 1);
561 #if defined(_FM77_VARIANTS) || defined(_FM8)
562 for(int i = 0; i < 8; i++) state_fio->StateBuffer(fm7_bootroms[i], 0x200, 1);
563 #elif defined(_FM7) || defined(_FMNEW7)
564 for(int i = 0; i < 4; i++) state_fio->StateBuffer(fm7_bootroms[i], 0x200, 1);
568 state_fio->StateBool(diag_load_sm11_14);
569 state_fio->StateBool(diag_load_sm11_15);
570 #elif defined(_FM77_VARIANTS)
571 state_fio->StateBool(diag_load_wb11_12);
572 #elif defined(_FM7) || defined(_FMNEW7)
573 state_fio->StateBool(diag_load_tl11_11);
574 # if defined(_FMNEW7)
575 state_fio->StateBool(diag_load_tl11_12);
577 #elif defined(_FM77AV_VARIANTS)
578 state_fio->StateBool(dictrom_connected);
579 state_fio->StateBool(use_page2_extram);
581 state_fio->StateBool(diag_load_initrom);
582 state_fio->StateBool(diag_load_dictrom);
583 state_fio->StateBool(diag_load_learndata);
584 state_fio->StateBuffer(fm7_mainmem_initrom, sizeof(fm7_mainmem_initrom), 1);
585 state_fio->StateBuffer(fm77av_hidden_bootmmr, sizeof(fm77av_hidden_bootmmr), 1);
587 state_fio->StateBuffer(fm7_mainmem_mmrbank_0, sizeof(fm7_mainmem_mmrbank_0), 1);
588 state_fio->StateBuffer(fm7_mainmem_mmrbank_2, sizeof(fm7_mainmem_mmrbank_2), 1);
590 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
591 state_fio->StateBool(diag_load_extrarom);
592 state_fio->StateBuffer(fm7_mainmem_extrarom, sizeof(fm7_mainmem_extrarom), 1);
594 # if defined(CAPABLE_DICTROM)
595 state_fio->StateBuffer(fm7_mainmem_dictrom, sizeof(fm7_mainmem_dictrom), 1);
596 state_fio->StateBuffer(fm7_mainmem_learndata, sizeof(fm7_mainmem_learndata), 1);
601 state_fio->StateBool(extram_connected);
602 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
603 defined(_FM77_VARIANTS)
604 state_fio->StateInt32(extram_pages);
605 state_fio->StateBuffer(fm7_mainmem_extram, extram_size, 1);
606 # if defined(_FM77_VARIANTS)
607 state_fio->StateBuffer(fm77_shadowram, sizeof(fm77_shadowram), 1);
613 state_fio->StateBool(is_basicrom);
614 state_fio->StateBool(clockmode);
615 state_fio->StateBool(basicrom_fd0f);
616 state_fio->StateUint32(bootmode);
617 #if defined(_FM77AV_VARIANTS)
618 state_fio->StateUint32(extcard_bank);
619 state_fio->StateBool(extrom_bank);
620 state_fio->StateBool(initiator_enabled);
621 state_fio->StateBool(dictrom_enabled);
622 state_fio->StateBool(dictram_enabled);
624 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
625 state_fio->StateBool(boot_ram_write);
628 state_fio->StateBool(window_enabled);
629 state_fio->StateBool(mmr_enabled);
630 state_fio->StateBool(mmr_fast);
631 state_fio->StateBool(mmr_extend);
633 state_fio->StateUint16(window_offset);
634 state_fio->StateBool(window_fast);
635 state_fio->StateBool(refresh_fast);
636 state_fio->StateUint8(mmr_segment);
637 state_fio->StateBuffer(mmr_map_data, sizeof(mmr_map_data), 1);
640 state_fio->StateUint32(mem_waitfactor); // OK?
641 state_fio->StateUint32(mem_waitcount); // OK?
643 state_fio->StateInt32(cpu_clocks); // OK?
648 void FM7_MAINMEM::save_state(FILEIO *state_fio)
650 decl_state(state_fio, false);
652 # if defined(_FM77_VARIANTS)
653 if(extram_pages > 3) extram_pages = 3;
654 # elif defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
655 if(extram_pages > 12) extram_pages = 12;
658 //extram_size = extram_pages * 0x10000;
661 bool FM7_MAINMEM::load_state(FILEIO *state_fio)
663 bool mb = decl_state(state_fio, true);
664 this->out_debug_log(_T("Load State: MAINMEM: id=%d stat=%s\n"), this_device_id, (mb) ? _T("OK") : _T("NG"));
665 if(!mb) return false;
668 # if defined(_FM77_VARIANTS)
669 if(extram_pages > 3) extram_pages = 3;
670 # elif defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
671 if(extram_pages > 12) extram_pages = 12;
674 //extram_size = extram_pages * 0x10000;
676 update_all_mmr_jumptable();