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)
16 FM7_MAINMEM::FM7_MAINMEM(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
18 #if !defined(_FM77AV_VARIANTS)
19 for(int i = 0; i < 8; i++) fm7_bootroms[i] = (uint8_t *)malloc(0x200);
24 #if defined(CAPABLE_DICTROM)
27 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
28 defined(_FM77_VARIANTS)
29 fm7_mainmem_extram = NULL;
31 cpu_clocks = CPU_CLOCKS;
33 set_device_name(_T("MAIN MEMORY"));
36 FM7_MAINMEM::~FM7_MAINMEM()
38 #if !defined(_FM77AV_VARIANTS)
39 for(int i = 0; i < 8; i++) if(fm7_bootroms[i] != NULL) free(fm7_bootroms[i]);
43 void FM7_MAINMEM::reset()
49 ioaccess_wait = false;
50 sub_halted = (display->read_signal(SIG_DISPLAY_HALT) == 0) ? false : true;
52 memset(fm7_mainmem_bootrom_vector, 0x00, 0x10); // Clear without vector
54 #if defined(_FM77AV_VARIANTS)
55 memset(fm7_bootram, 0x00, 0x1f0);
56 initiator_enabled = true;
57 boot_ram_write = true;
58 #elif defined(_FM77_VARIANTS)
59 boot_ram_write = false;
61 #if defined(_FM77_VARIANTS) || defined(_FM8)
62 bootmode = config.boot_mode & 7;
64 bootmode = config.boot_mode & 3;
67 if((config.dipswitch & FM7_DIPSW_EXTRAM) != 0) {
68 extram_connected = true;
70 extram_connected = false;
73 #if defined(_FM77AV_VARIANTS)
74 if(dictrom_connected) {
75 use_page2_extram = true;
77 use_page2_extram = ((config.dipswitch & FM7_DIPSW_EXTRAM_AV) != 0) ? true : false;
86 window_enabled = false;
90 if((bootmode & 0x03) == 0) { // IF BASIC BOOT THEN ROM
93 basicrom_fd0f = false;
95 clockmode = (config.cpu_type == 0) ? true : false;
96 is_basicrom = ((bootmode & 0x03) == 0) ? true : false;
97 setclock(clockmode ? 0 : 1);
99 update_all_mmr_jumptable();
104 void FM7_MAINMEM::setclock(int mode)
106 uint32_t clock = MAINCLOCK_SLOW;
107 if(mode == 1) { // SLOW
108 clock = MAINCLOCK_SLOW; // Temporally
110 if(!mmr_fast && !window_fast) {
112 if(mmr_enabled || window_enabled) {
113 clock = (uint32_t)((double)clock * 1.089);
115 clock = (uint32_t)((double)clock * 1.086);
122 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
123 // Thanks to Ryu Takegami, around DRAM refresh.
124 // DRAM refresh makes halting MAIN MPU per 13.02uS.
125 if(!mmr_fast && !window_fast) { // SLOW
127 clock = MAINCLOCK_FAST_MMR - ((100000000 / 1302) * 1); // Fast Refresh: 1wait
129 clock = MAINCLOCK_FAST_MMR - ((100000000 / 1302) * 3); // Slow Refresh: 3Wait(!)
131 if(mmr_enabled || window_enabled) {
132 clock = (uint32_t)((double)clock * 0.87);
135 clock = MAINCLOCK_FAST_MMR;
136 //if(!(mmr_enabled) && !(window_enabled)) clock = MAINCLOCK_NORMAL;
139 if(mmr_enabled || window_enabled) {
140 clock = MAINCLOCK_MMR;
142 clock = MAINCLOCK_NORMAL;
146 clock = MAINCLOCK_NORMAL;
150 uint32_t before_waitfactor = mem_waitfactor;
151 if(CPU_CLOCKS > clock) {
152 mem_waitfactor = (uint32_t)(65536.0 * ((1.0 - (double)clock / (double)CPU_CLOCKS)));
153 //out_debug_log(_T("CLOCK=%d WAIT FACTOR=%d"), clock, mem_waitfactor);
156 //out_debug_log(_T("CLOCK=%d WAIT FACTOR=%d"), clock, mem_waitfactor);
159 // Below is ugly hack cause of CPU#0 cannot modify clock.
160 if(before_waitfactor != mem_waitfactor) maincpu->write_signal(SIG_CPU_WAIT_FACTOR, mem_waitfactor, 0xffffffff);
164 void FM7_MAINMEM::iowait()
167 if(config.cpu_type == 1) return; // SLOW
169 if((window_enabled) || (mmr_enabled)) {
172 } else { // Not MMR, TWR or enabled FAST MMR mode
173 _waitfactor = 3; // If(MMR or TWR) and NOT FAST MMR factor = 3, else factor = 2
174 if(mmr_fast) _waitfactor = 2;
182 if(_waitfactor <= 0) return;
184 if(waitcount >= _waitfactor) {
185 maincpu->set_extra_clock(1);
187 ioaccess_wait = !ioaccess_wait;
193 int FM7_MAINMEM::check_extrom(uint32_t raddr, uint32_t *realaddr)
195 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
196 if(extrom_bank) { // Extra ROM selected.
197 uint32_t dbank = extcard_bank & 0x3f;
198 if(dbank < 0x20) { // KANJI
199 if((dbank == 0x07) || (dbank == 0x06)) {
200 // NOT KANJI AS IS.Thanks Ryu.
201 *realaddr = raddr & 0x01;
202 return FM7_MAINMEM_KANJI_DUMMYADDR;
204 *realaddr = (dbank << 12) | raddr;
205 return FM7_MAINMEM_KANJI_LEVEL1;
206 } else if(dbank < 0x2c) {
207 raddr = ((dbank << 12) - 0x20000) | raddr;
209 return FM7_MAINMEM_77AV40_EXTRAROM;
210 } else if(dbank < 0x30) {
212 return FM7_MAINMEM_NULL;
214 raddr = ((dbank << 12) - 0x30000) | raddr;
215 if((raddr >= 0x8000) && (raddr < 0xfc00)) {
216 *realaddr = raddr - 0x8000;
217 return FM7_MAINMEM_BASICROM;
218 } else if((raddr >= 0xfe00) && (raddr < 0xffe0)) {
219 *realaddr = raddr - 0xfe00;
220 return FM7_MAINMEM_BOOTROM_MMR;
221 } else if(raddr >= 0xfffe) {
222 *realaddr = raddr - 0xfffe;
223 return FM7_MAINMEM_RESET_VECTOR;
225 //*realaddr = raddr + 0x10000;
226 //return FM7_MAINMEM_77AV40_EXTRAROM;
228 return FM7_MAINMEM_NULL;
236 uint32_t FM7_MAINMEM::read_signal(int sigid)
238 uint32_t value = 0x00000000;
240 case FM7_MAINIO_PUSH_FD0F:
241 value = (basicrom_fd0f) ? 0xffffffff : 0x00000000;
243 case FM7_MAINIO_IS_BASICROM:
244 value = (is_basicrom) ? 0xffffffff : 0x00000000;
246 case FM7_MAINIO_CLOCKMODE:
247 value = (clockmode) ? 0xffffffff : 0x00000000;
249 case FM7_MAINIO_BOOTMODE:
250 value = (uint32_t)bootmode & 0x07;
252 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
253 case FM7_MAINIO_BOOTRAM_RW:
254 value = (boot_ram_write) ? 0xffffffff : 0x00000000;
258 case FM7_MAINIO_WINDOW_ENABLED:
259 value = (window_enabled) ? 0xffffffff : 0x00000000;
261 case FM7_MAINIO_WINDOW_FAST:
262 value = (window_fast) ? 0xffffffff : 0x00000000;
264 case FM7_MAINIO_FASTMMR_ENABLED:
265 value = (mmr_fast) ? 0xffffffff : 0x00000000;
267 case FM7_MAINIO_MMR_ENABLED:
268 value = (mmr_enabled) ? 0xffffffff : 0x00000000;
270 case FM7_MAINIO_MMR_EXTENDED:
271 value = (mmr_extend) ? 0xffffffff : 0x00000000;
273 case FM7_MAINIO_MEM_REFRESH_FAST:
274 value = (refresh_fast) ? 0xffffffff : 0x00000000;
277 #if defined(_FM77AV_VARIANTS)
278 case FM7_MAINIO_INITROM_ENABLED:
279 value = (initiator_enabled) ? 0xffffffff: 0x00000000;
281 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
282 case FM7_MAINIO_EXTROM:
283 value = (extrom_bank) ? 0xffffffff: 0x00000000;
286 case FM7_MAINIO_EXTBANK:
287 value = extcard_bank & 0x3f;
288 value |= (dictram_enabled) ? 0x80 : 0;
289 value |= (dictrom_enabled) ? 0x40 : 0;
297 void FM7_MAINMEM::write_signal(int sigid, uint32_t data, uint32_t mask)
299 bool flag = ((data & mask) != 0);
301 case SIG_FM7_SUB_HALT:
304 case FM7_MAINIO_IS_BASICROM:
307 case FM7_MAINIO_PUSH_FD0F:
308 basicrom_fd0f = flag;
310 case FM7_MAINIO_CLOCKMODE:
312 setclock(clockmode ? 0 : 1);
314 case FM7_MAINIO_BOOTMODE:
315 bootmode = data & 0x07;
317 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
318 case FM7_MAINIO_BOOTRAM_RW:
319 boot_ram_write = flag;
322 #ifdef _FM77AV_VARIANTS
323 case FM7_MAINIO_INITROM_ENABLED:
324 initiator_enabled = flag;
326 case FM7_MAINIO_EXTBANK:
327 extcard_bank = data & 0x3f;
328 dictram_enabled = ((data & 0x80) != 0) ? true : false;
329 dictrom_enabled = ((data & 0x40) != 0) ? true : false;
331 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
332 case FM7_MAINIO_EXTROM:
338 case FM7_MAINIO_WINDOW_ENABLED:
339 window_enabled = flag;
340 setclock(config.cpu_type);
342 case FM7_MAINIO_WINDOW_FAST:
344 setclock(config.cpu_type);
346 case FM7_MAINIO_FASTMMR_ENABLED:
348 setclock(config.cpu_type);
350 case FM7_MAINIO_MMR_ENABLED:
352 setclock(config.cpu_type);
354 case FM7_MAINIO_MMR_EXTENDED:
357 case FM7_MAINIO_MEM_REFRESH_FAST:
359 setclock(config.cpu_type);
365 uint32_t FM7_MAINMEM::read_io8(uint32_t addr)
367 return mainio->read_io8(addr);
370 void FM7_MAINMEM::write_io8(uint32_t addr, uint32_t data)
372 return mainio->write_io8(addr, data);
375 uint32_t FM7_MAINMEM::read_dma_data8(uint32_t addr)
379 val = this->read_data8_main(addr & 0xffff, true);
382 return this->read_data8(addr & 0xffff);
386 uint32_t FM7_MAINMEM::read_dma_io8(uint32_t addr)
390 val = this->read_data8_main(addr & 0xffff, true);
393 return this->read_data8(addr & 0xffff);
397 uint32_t FM7_MAINMEM::read_data8(uint32_t addr)
400 if(addr >= FM7_MAINIO_WINDOW_OFFSET) {
402 case FM7_MAINIO_WINDOW_OFFSET:
403 return (uint32_t)window_offset;
405 case FM7_MAINIO_MMR_SEGMENT:
406 return (uint32_t)mmr_segment;
409 if((addr >= FM7_MAINIO_MMR_BANK) && (addr < (FM7_MAINIO_MMR_BANK + 0x80))){
410 return mmr_map_data[addr - FM7_MAINIO_MMR_BANK];
417 return read_data8_main(addr, false);
420 void FM7_MAINMEM::write_dma_data8(uint32_t addr, uint32_t data)
423 write_data8_main(addr & 0xffff, data, true);
425 write_data8(addr & 0xffff, data);
429 void FM7_MAINMEM::write_dma_io8(uint32_t addr, uint32_t data)
432 write_data8_main(addr & 0xffff, data, true);
434 write_data8(addr & 0xffff, data);
438 void FM7_MAINMEM::write_data8(uint32_t addr, uint32_t data)
441 if(addr >= FM7_MAINIO_WINDOW_OFFSET) {
443 case FM7_MAINIO_WINDOW_OFFSET:
444 window_offset = data;
446 case FM7_MAINIO_MMR_SEGMENT:
448 mmr_segment = data & 0x07;
450 mmr_segment = data & 0x03;
454 if((addr >= FM7_MAINIO_MMR_BANK) && (addr < (FM7_MAINIO_MMR_BANK + 0x80))){
455 mmr_map_data[addr - FM7_MAINIO_MMR_BANK] = (uint8_t)data;
456 update_mmr_jumptable(addr - FM7_MAINIO_MMR_BANK);
463 write_data8_main(addr, data, false);
466 // Read / Write data(s) as big endian.
467 uint32_t FM7_MAINMEM::read_data16(uint32_t addr)
472 hi = read_data8(addr) & 0xff;
473 lo = read_data8(addr + 1) & 0xff;
479 uint32_t FM7_MAINMEM::read_data32(uint32_t addr)
481 uint32_t ah, a2, a3, al;
484 ah = read_data8(addr) & 0xff;
485 a2 = read_data8(addr + 1) & 0xff;
486 a3 = read_data8(addr + 2) & 0xff;
487 al = read_data8(addr + 3) & 0xff;
489 val = ah * (65536 * 256) + a2 * 65536 + a3 * 256 + al;
493 void FM7_MAINMEM::write_data16(uint32_t addr, uint32_t data)
497 write_data8(addr + 1, d & 0xff);
499 write_data8(addr + 0, d & 0xff);
502 void FM7_MAINMEM::write_data32(uint32_t addr, uint32_t data)
506 write_data8(addr + 3, d & 0xff);
508 write_data8(addr + 2, d & 0xff);
510 write_data8(addr + 1, d & 0xff);
512 write_data8(addr + 0, d & 0xff);
516 void FM7_MAINMEM::update_config()
518 setclock(config.cpu_type);
521 #define STATE_VERSION 7
523 #include "../../statesub.h"
525 void FM7_MAINMEM::decl_state(void)
527 enter_decl_state(STATE_VERSION);
529 DECL_STATE_ENTRY_BOOL(ioaccess_wait);
530 DECL_STATE_ENTRY_INT32(waitfactor);
531 DECL_STATE_ENTRY_INT32(waitcount);
532 DECL_STATE_ENTRY_BOOL(sub_halted);
534 DECL_STATE_ENTRY_BOOL(diag_load_basicrom);
535 DECL_STATE_ENTRY_BOOL(diag_load_bootrom_bas);
536 DECL_STATE_ENTRY_BOOL(diag_load_bootrom_dos);
537 DECL_STATE_ENTRY_BOOL(diag_load_bootrom_mmr);
538 DECL_STATE_ENTRY_BOOL(diag_load_bootrom_bubble);
539 DECL_STATE_ENTRY_BOOL(diag_load_bootrom_bubble_128k);
540 DECL_STATE_ENTRY_BOOL(diag_load_bootrom_sfd8);
541 DECL_STATE_ENTRY_BOOL(diag_load_bootrom_2hd);
543 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_omote, sizeof(fm7_mainmem_omote));
544 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_ura, sizeof(fm7_mainmem_ura));
545 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_basicrom, sizeof(fm7_mainmem_basicrom));
546 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_bioswork, sizeof(fm7_mainmem_bioswork));
547 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_bootrom_vector, sizeof(fm7_mainmem_bootrom_vector));
548 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_reset_vector, sizeof(fm7_mainmem_reset_vector));
550 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_null, sizeof(fm7_mainmem_null));
552 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
553 DECL_STATE_ENTRY_1D_ARRAY(fm7_bootram, sizeof(fm7_bootram));
555 #if defined(_FM77_VARIANTS) || defined(_FM8)
556 for(int i = 0; i < 8; i++) DECL_STATE_ENTRY_1D_ARRAY_MEMBER(fm7_bootroms[i], 0x200, i);
557 #elif defined(_FM7) || defined(_FMNEW7)
558 for(int i = 0; i < 4; i++) DECL_STATE_ENTRY_1D_ARRAY_MEMBER(fm7_bootroms[i], 0x200, i);
562 DECL_STATE_ENTRY_BOOL(diag_load_sm11_14);
563 DECL_STATE_ENTRY_BOOL(diag_load_sm11_15);
564 #elif defined(_FM77_VARIANTS)
565 DECL_STATE_ENTRY_BOOL(diag_load_wb11_12);
566 #elif defined(_FM7) || defined(_FMNEW7)
567 DECL_STATE_ENTRY_BOOL(diag_load_tl11_11);
568 # if defined(_FMNEW7)
569 DECL_STATE_ENTRY_BOOL(diag_load_tl11_12);
571 #elif defined(_FM77AV_VARIANTS)
572 DECL_STATE_ENTRY_BOOL(dictrom_connected);
573 DECL_STATE_ENTRY_BOOL(use_page2_extram);
575 DECL_STATE_ENTRY_BOOL(diag_load_initrom);
576 DECL_STATE_ENTRY_BOOL(diag_load_dictrom);
577 DECL_STATE_ENTRY_BOOL(diag_load_learndata);
578 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_initrom, sizeof(fm7_mainmem_initrom));
579 DECL_STATE_ENTRY_1D_ARRAY(fm77av_hidden_bootmmr, sizeof(fm77av_hidden_bootmmr));
581 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_mmrbank_0, sizeof(fm7_mainmem_mmrbank_0));
582 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_mmrbank_2, sizeof(fm7_mainmem_mmrbank_2));
584 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
585 DECL_STATE_ENTRY_BOOL(diag_load_extrarom);
586 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_extrarom, sizeof(fm7_mainmem_extrarom));
588 # if defined(CAPABLE_DICTROM)
589 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_dictrom, sizeof(fm7_mainmem_dictrom));
590 DECL_STATE_ENTRY_1D_ARRAY(fm7_mainmem_learndata, sizeof(fm7_mainmem_learndata));
595 DECL_STATE_ENTRY_BOOL(extram_connected);
596 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
597 defined(_FM77_VARIANTS)
598 DECL_STATE_ENTRY_INT32(extram_pages);
599 DECL_STATE_ENTRY_VARARRAY_VAR(fm7_mainmem_extram, extram_size);
600 # if defined(_FM77_VARIANTS)
601 DECL_STATE_ENTRY_1D_ARRAY(fm77_shadowram, sizeof(fm77_shadowram));
607 DECL_STATE_ENTRY_BOOL(is_basicrom);
608 DECL_STATE_ENTRY_BOOL(clockmode);
609 DECL_STATE_ENTRY_BOOL(basicrom_fd0f);
610 DECL_STATE_ENTRY_UINT32(bootmode);
611 #if defined(_FM77AV_VARIANTS)
612 DECL_STATE_ENTRY_UINT32(extcard_bank);
613 DECL_STATE_ENTRY_BOOL(extrom_bank);
614 DECL_STATE_ENTRY_BOOL(initiator_enabled);
615 DECL_STATE_ENTRY_BOOL(dictrom_enabled);
616 DECL_STATE_ENTRY_BOOL(dictram_enabled);
618 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
619 DECL_STATE_ENTRY_BOOL(boot_ram_write);
622 DECL_STATE_ENTRY_BOOL(window_enabled);
623 DECL_STATE_ENTRY_BOOL(mmr_enabled);
624 DECL_STATE_ENTRY_BOOL(mmr_fast);
625 DECL_STATE_ENTRY_BOOL(mmr_extend);
627 DECL_STATE_ENTRY_UINT16(window_offset);
628 DECL_STATE_ENTRY_BOOL(window_fast);
629 DECL_STATE_ENTRY_BOOL(refresh_fast);
630 DECL_STATE_ENTRY_UINT8(mmr_segment);
631 DECL_STATE_ENTRY_1D_ARRAY(mmr_map_data, sizeof(mmr_map_data));
634 DECL_STATE_ENTRY_UINT32(mem_waitfactor); // OK?
635 DECL_STATE_ENTRY_UINT32(mem_waitcount); // OK?
637 DECL_STATE_ENTRY_UINT32(cpu_clocks); // OK?
642 void FM7_MAINMEM::save_state(FILEIO *state_fio)
644 if(state_entry != NULL) {
645 state_entry->save_state(state_fio);
648 # if defined(_FM77_VARIANTS)
649 if(extram_pages > 3) extram_pages = 3;
650 # elif defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
651 if(extram_pages > 12) extram_pages = 12;
654 //extram_size = extram_pages * 0x10000;
657 bool FM7_MAINMEM::load_state(FILEIO *state_fio)
660 if(state_entry != NULL) {
661 mb = state_entry->load_state(state_fio);
662 this->out_debug_log(_T("Load State: MAINIO: id=%d stat=%s\n"), this_device_id, (mb) ? _T("OK") : _T("NG"));
663 if(!mb) return false;
666 # if defined(_FM77_VARIANTS)
667 if(extram_pages > 3) extram_pages = 3;
668 # elif defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
669 if(extram_pages > 12) extram_pages = 12;
672 //extram_size = extram_pages * 0x10000;
674 update_all_mmr_jumptable();