OSDN Git Service

13561c01bf97d6219e5dbdd2bae83a0abb3ff475
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / fm7_mainmem.cpp
1 /*
2  * Main memory without MMR for FM-7 [FM7_MAINMEM]
3  *  Author: K.Ohta
4  *  Date  : 2015.01.01-
5  *
6  */
7
8 #include "fm7_mainmem.h"
9
10
11 void FM7_MAINMEM::reset()
12 {
13         waitfactor = 0;
14         waitcount = 0;
15         ioaccess_wait = false;
16         sub_halted = (display->read_signal(SIG_DISPLAY_HALT) == 0) ? false : true;
17         //sub_halted = false;
18         memset(fm7_mainmem_bootrom_vector, 0x00, 0x10); // Clear without vector
19 #if defined(_FM77AV_VARIANTS)
20         memset(fm7_bootram, 0x00, 0x1f0);
21         initiator_enabled = true;
22         boot_ram_write = true;
23 #elif defined(_FM77_VARIANTS)
24         boot_ram_write = false;
25 #endif  
26         bootmode = config.boot_mode & 3;
27 #if defined(HAS_MMR)
28         if((config.dipswitch & FM7_DIPSW_EXTRAM) != 0) {
29                 extram_connected = true;
30         } else {
31                 extram_connected = false;
32         }
33 #endif
34 #if defined(_FM77AV_VARIANTS)
35         if(dictrom_connected) {
36                 use_page2_extram = true;
37         } else {
38                 use_page2_extram = ((config.dipswitch & FM7_DIPSW_EXTRAM_AV) != 0) ? true : false;
39         }
40 #endif   
41 #ifdef HAS_MMR
42         mmr_extend = false;
43         mmr_segment = 0;
44         window_offset = 0;
45         mmr_enabled = false;
46         mmr_fast = false;
47         window_enabled = false;
48         window_fast = false;
49         refresh_fast = false;
50 #endif
51         if((bootmode & 0x03) == 0) { // IF BASIC BOOT THEN ROM
52                 basicrom_fd0f = true;
53         } else { // ELSE RAM
54                 basicrom_fd0f = false;
55         }
56         clockmode = (config.cpu_type == 0) ? true : false;
57         is_basicrom = ((bootmode & 0x03) == 0) ? true : false;
58         maincpu->reset();
59 }
60
61 void FM7_MAINMEM::setclock(int mode)
62 {
63         uint32 clock = MAINCLOCK_SLOW;
64         if(mode == 1) { // SLOW
65                 clock = MAINCLOCK_SLOW; // Temporally
66 #if defined(HAS_MMR)            
67                 if(!mmr_fast && !window_fast) {
68                         if(refresh_fast) {
69                                 if(mmr_enabled || window_enabled) {
70                                         clock = (uint32)((double)clock * 1.089);
71                                 } else {
72                                         clock = (uint32)((double)clock * 1.086);
73                                 }                                       
74                         }
75                 }
76 #endif          
77         } else {
78 #if defined(HAS_MMR)
79                 if(window_enabled) {
80                         if(window_fast) {
81                                 clock = MAINCLOCK_FAST_MMR;
82                         } else {
83                                 clock = MAINCLOCK_MMR;
84                         }
85                 } else if(mmr_enabled) {
86                         if(mmr_fast) {
87                                 clock = MAINCLOCK_FAST_MMR;
88                         } else {
89                                 clock = MAINCLOCK_MMR;
90                         }
91                 } else {
92                         clock = MAINCLOCK_NORMAL;
93                 }
94                 if(!mmr_fast && !window_fast) {
95                         if(refresh_fast) {
96                                 if(mmr_enabled || window_enabled) {
97                                         clock = (uint32)((double)clock * 1.089);
98                                 } else {
99                                         clock = (uint32)((double)clock * 1.086);
100                                 }                                       
101                         }
102                 }
103 #else
104                 clock = MAINCLOCK_NORMAL;
105 #endif                          
106         }
107         p_vm->set_cpu_clock(this->maincpu, clock);
108 }
109                 
110
111 void FM7_MAINMEM::wait()
112 {
113         int waitfactor; // If MMR of TWR enabled, factor = 3.
114                             // If memory, factor = 2?
115         if(!clockmode) return; // SLOW
116 #ifdef HAS_MMR
117     //if(!mmr_fast && !window_fast && (window_enabled || mmr_enabled)) waitfactor = 2;
118         if(!ioaccess_wait) {
119                 waitfactor = 2;
120                 ioaccess_wait = true;
121         } else { // Not MMR, TWR or enabled FAST MMR mode
122                 waitfactor = 3; // If(MMR or TWR) and NOT FAST MMR factor = 3, else factor = 2
123                 if(mmr_fast) waitfactor = 2;
124                 ioaccess_wait = false;
125         } 
126 #else
127         waitfactor = 2;
128 #endif    
129         if(waitfactor <= 0) return;
130         waitcount++;
131         if(waitcount >= waitfactor) {
132                 if(maincpu != NULL) maincpu->set_extra_clock(1);
133                 waitcount = 0;
134         }
135 }
136
137
138 int FM7_MAINMEM::window_convert(uint32 addr, uint32 *realaddr)
139 {
140         uint32 raddr = addr;
141 #ifdef HAS_MMR
142         if((addr < 0x8000) && (addr >= 0x7c00)) {
143                 raddr = ((window_offset * 256) + addr) & 0x0ffff; 
144                 *realaddr = raddr;
145 #ifdef _FM77AV_VARIANTS
146                 //printf("TWR hit %04x -> %04x\n", addr, raddr);
147                 return FM7_MAINMEM_AV_PAGE0; // 0x00000 - 0x0ffff
148 #else // FM77(L4 or others)
149                 *realaddr |= 0x20000;
150                 return FM7_MAINMEM_EXTRAM; // 0x20000 - 0x2ffff
151 #endif
152         }
153         // Window not hit.
154 #endif
155         return -1;
156 }
157
158
159 int FM7_MAINMEM::check_extrom(uint32 raddr, uint32 *realaddr)
160 {
161 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
162         if(extrom_bank) { // Extra ROM selected.
163                 uint32 dbank = extcard_bank & 0x3f;
164                 if(dbank < 0x20) { // KANJI
165                         if((dbank == 0x07) || (dbank == 0x06)) {
166                                 // NOT KANJI AS IS.Thanks Ryu.
167                                 *realaddr = raddr & 0x01;
168                                 return FM7_MAINMEM_KANJI_DUMMYADDR;
169                         }
170                         *realaddr = (dbank << 12) | raddr;
171                         return FM7_MAINMEM_KANJI_LEVEL1;
172                 } else if(dbank < 0x2c) {
173                         raddr = ((dbank << 12) - 0x20000) | raddr;
174                         *realaddr = raddr;
175                         return FM7_MAINMEM_77AV40_EXTRAROM;
176                 } else if(dbank < 0x30) {
177                         *realaddr = 0;
178                         return FM7_MAINMEM_NULL;
179                 } else {
180                         raddr = ((dbank << 12) - 0x30000) | raddr;
181                         if((raddr >= 0x8000)  && (raddr < 0xfc00)) {
182                                 *realaddr = raddr - 0x8000;
183                                 return FM7_MAINMEM_BASICROM;
184                         } else if((raddr >= 0xfe00) && (raddr < 0xffe0)) {
185                                 *realaddr = raddr - 0xfe00;
186                                 return FM7_MAINMEM_BOOTROM_MMR;
187                         } else if(raddr >= 0xfffe) {
188                                 *realaddr = raddr - 0xfffe;
189                                 return FM7_MAINMEM_RESET_VECTOR;
190                         }
191                         //*realaddr = raddr + 0x10000;
192                         //return FM7_MAINMEM_77AV40_EXTRAROM;
193                         *realaddr = 0;
194                         return FM7_MAINMEM_NULL;
195                 }
196         }
197 #endif  
198         return -1;
199 }
200    
201
202 int FM7_MAINMEM::mmr_convert(uint32 addr, uint32 *realaddr, bool write_state, bool dmamode)
203 {
204         uint32  raddr = addr & 0x0fff;
205         uint32  mmr_bank;
206         uint32  major_bank;
207         uint8 segment;
208    
209 #ifdef HAS_MMR
210         if(dmamode) {
211                 segment = 0x00;
212         } else {
213                 segment = mmr_segment;
214         }
215         if(addr >= 0xfc00) return -1;
216         if(!mmr_extend) {
217                 mmr_bank = mmr_map_data[(addr >> 12) & 0x000f | ((segment & 0x03) << 4)] & 0x003f;
218         } else {
219                 mmr_bank = mmr_map_data[(addr >> 12) & 0x000f | ((segment & 0x07) << 4)] & 0x007f;
220         }               
221         // Reallocated by MMR
222         // Bank 3x : Standard memories.
223         if((mmr_bank < 0x3f) && (mmr_bank >= 0x30)) {
224                 raddr = ((mmr_bank << 12) | raddr) & 0xffff;
225                 return nonmmr_convert(raddr, realaddr);
226         }
227 # ifdef _FM77AV_VARIANTS
228         else if(mmr_bank == 0x3f) {
229                 if((raddr >= 0xd80) && (raddr <= 0xd97)) { // MMR AREA
230                         *realaddr = 0;
231                         return FM7_MAINMEM_NULL;
232                 } else {
233                         raddr = raddr | 0xf000;
234                         return nonmmr_convert(raddr, realaddr); // Access I/O, Bootrom, even via MMR.
235                 }
236         }
237 # elif defined(_FM77_VARIANTS)
238         else if(mmr_bank == 0x3f) {
239                 if((raddr >= 0xc00) && (raddr < 0xe00)) {
240                         if(is_basicrom) {
241                                 *realaddr = 0;
242                                 return FM7_MAINMEM_ZERO;
243                         } else {
244                                 *realaddr = raddr - 0xc00;
245                                 return FM7_MAINMEM_SHADOWRAM;
246                         }
247                 } else if(raddr >= 0xe00) {
248                         *realaddr = addr - 0x0e00;
249                         if(is_basicrom) {
250                                 if(diag_load_bootrom_mmr) {
251                                         return FM7_MAINMEM_BOOTROM_MMR;
252                                 } else {
253                                         return FM7_MAINMEM_BOOTROM_BAS;
254                                 }
255                         } else {
256                                 return FM7_MAINMEM_BOOTROM_RAM;
257                         }
258                 } else {
259                         raddr = raddr | 0xf000;
260                         return nonmmr_convert(raddr, realaddr); // Access I/O, Bootrom, even via MMR.
261                 } 
262         }
263 # endif
264         major_bank = (mmr_bank >> 4) & 0x0f;
265     
266 # ifdef _FM77AV_VARIANTS
267         if(major_bank == 0x0) { // PAGE 0
268                 *realaddr = ((mmr_bank << 12) | raddr) & 0x0ffff;
269                 return FM7_MAINMEM_AV_PAGE0;
270         } else if(major_bank == 0x1) { // PAGE 1                
271                 *realaddr = ((mmr_bank << 12) | raddr) & 0x0ffff;
272                 return FM7_MAINMEM_AV_DIRECTACCESS;
273         } else  if(major_bank == 0x2) { // PAGE 2
274                 if((mmr_bank == 0x2e) && (!write_state)) {
275                         int banknum = check_extrom(raddr, realaddr);
276                         if(banknum >= 0) {
277                                 return banknum;
278                         } else {
279 #  if defined(CAPABLE_DICTROM)
280                                 if(dictrom_connected && dictrom_enabled) { // Dictionary ROM
281                                         uint32 dbank = extcard_bank & 0x3f;
282                                         *realaddr = raddr | (dbank << 12);
283                                         return FM7_MAINMEM_DICTROM;
284                                 }
285 #  else
286                                         *realaddr = 0;
287                                         return FM7_MAINMEM_NULL;
288 #  endif                           
289                         }
290                 }
291 #  if defined(CAPABLE_DICTROM)
292                 switch(mmr_bank) {
293                 case 0x28:
294                 case 0x29: // Backuped RAM
295                         if(dictrom_connected && dictram_enabled){ // Battery backuped RAM
296                                 raddr = (((uint32)mmr_bank & 0x01) << 12) | raddr;
297                                 raddr =  raddr & 0x1fff;
298                                 *realaddr = raddr;
299                                 return FM7_MAINMEM_BACKUPED_RAM;
300                         }
301                         break;
302                 }
303                 *realaddr = (raddr | (mmr_bank << 12)) & 0x0ffff;
304                 return FM7_MAINMEM_AV_PAGE2;
305 #  else
306                 if(use_page2_extram) {
307                         *realaddr = ((mmr_bank << 12) | raddr) & 0x0ffff;
308                         return FM7_MAINMEM_AV_PAGE2;
309                 } else {
310                         *realaddr = 0;
311                         return FM7_MAINMEM_NULL;
312                 }
313 #  endif
314         }
315 # endif
316         
317 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
318         else if(extram_connected && mmr_extend) { // PAGE 4-
319                 if((major_bank >= (extram_pages + 4)) || (fm7_mainmem_extram == NULL) ) {
320                         *realaddr = 0;
321                         return FM7_MAINMEM_NULL; // $FF
322                 } else {
323                         raddr = ((uint32)(mmr_bank - 0x40) << 12) | raddr;
324                         *realaddr = raddr;
325                         return FM7_MAINMEM_EXTRAM;
326                 }
327         } else {
328                 *realaddr = 0;
329                 return FM7_MAINMEM_NULL;
330         }
331 # elif defined(_FM77_VARIANTS)
332         if(extram_connected) { // PAGE 4-
333                 if((major_bank > (extram_pages - 1)) || (major_bank >= 3)) {
334                         *realaddr = 0;
335                         return FM7_MAINMEM_NULL; // $FF
336                 } else {
337                         raddr = ((uint32)mmr_bank << 12) | raddr;
338                         *realaddr = raddr;
339                         return FM7_MAINMEM_EXTRAM;
340                 }
341         } else {
342                 *realaddr = 0;
343                 return FM7_MAINMEM_NULL; // $FF
344         }
345 # else // _FM77AV_VARIANTS
346         if(major_bank > 3) {
347                 *realaddr = 0;
348                 return FM7_MAINMEM_NULL; // $FF
349         }
350 # endif
351 #endif // HAS_MMR
352         *realaddr = 0;
353         return -1;
354 }
355
356 int FM7_MAINMEM::nonmmr_convert(uint32 addr, uint32 *realaddr)
357 {
358         addr &= 0x0ffff;
359 #ifdef _FM77AV_VARIANTS
360         if(initiator_enabled) {
361                 if((addr >= 0x6000) && (addr < 0x8000)) {
362                     //printf("HIT %02x\n", read_table[FM7_MAINMEM_INITROM].memory[addr - 0x6000]);
363                         *realaddr = addr - 0x6000;
364                         return FM7_MAINMEM_INITROM;
365                 }
366                 if(addr >= 0xfffe) {
367                   //printf("HIT %02x\n", read_table[FM7_MAINMEM_INITROM].memory[addr - 0xe000]);
368                         *realaddr = addr - 0xe000;
369                         return FM7_MAINMEM_INITROM;
370                 }
371         }
372 #endif  
373
374         uint32 addr_major, addr_minor;
375         addr_major = (addr >> 12) & 0x0f;
376
377         switch (addr_major) {
378         case 0x00:
379         case 0x01:
380         case 0x02:
381         case 0x03:
382         case 0x04:
383         case 0x05:
384         case 0x06:
385         case 0x07:
386                 *realaddr = addr;
387                 return FM7_MAINMEM_OMOTE;
388                 break;
389         case 0x08:
390         case 0x09:
391         case 0x0a:
392         case 0x0b:
393         case 0x0c:
394         case 0x0d:
395         case 0x0e:
396                 *realaddr = addr - 0x8000;
397                 if (basicrom_fd0f) {
398                         return FM7_MAINMEM_BASICROM;
399                 }
400                 return FM7_MAINMEM_URA;
401                 break;
402         case 0x0f:
403                 addr_minor = (addr >> 8) & 0x0f;
404                 switch (addr_minor){
405                 case 0x00:
406                 case 0x01:
407                 case 0x02:
408                 case 0x03:
409                 case 0x04:
410                 case 0x05:
411                 case 0x06:
412                 case 0x07:
413                 case 0x08:
414                 case 0x09:
415                 case 0x0a:
416                 case 0x0b:
417                         *realaddr = addr - 0x8000;
418                         if (basicrom_fd0f) {
419                                 return FM7_MAINMEM_BASICROM;
420                         }
421                         return FM7_MAINMEM_URA;
422                         break;
423                 case 0x0c:
424                         if (addr < 0xfc80) {
425                                 *realaddr = addr - 0xfc00;
426                                 return FM7_MAINMEM_BIOSWORK;
427                         }
428                         else {
429                                 *realaddr = addr - 0xfc80;
430                                 return FM7_MAINMEM_SHAREDRAM;
431                         }
432                         break;
433                 case 0x0d:
434                         wait();
435                         *realaddr = addr - 0xfd00;
436                         return FM7_MAINMEM_MMIO;
437                         break;
438                 default:
439                         if (addr < 0xffe0){
440                                 wait();
441                                 *realaddr = addr - 0xfe00;
442 #if defined(_FM77AV_VARIANTS)
443                                 return FM7_MAINMEM_BOOTROM_RAM;
444 #else
445                                 switch(bootmode) {
446                                 case 0:
447                                         return FM7_MAINMEM_BOOTROM_BAS;
448                                         break;
449                                 case 1:
450                                         //printf("BOOT_DOS ADDR=%04x\n", addr);
451                                         return FM7_MAINMEM_BOOTROM_DOS;
452                                         break;
453                                 case 2:
454                                         return FM7_MAINMEM_BOOTROM_MMR;
455                                         break;
456                                 case 3:
457                                         return FM7_MAINMEM_BOOTROM_EXTRA;
458                                         break;
459 # if defined(_FM77_VARIANTS)
460                                 case 4:
461                                         return FM7_MAINMEM_BOOTROM_RAM;
462                                         break;
463 # endif                         
464                                 default:
465                                         return FM7_MAINMEM_BOOTROM_BAS; // Really?
466                                         break;
467                                 }
468 #endif
469                         }
470                         else if (addr < 0xfffe) { // VECTOR
471                                 *realaddr = addr - 0xffe0;
472                                 return FM7_MAINMEM_VECTOR;
473                         }
474 #if defined(_FM77AV_VARIANTS)
475                         else if(addr < 0x10000) {
476                                 wait();
477                                 *realaddr = addr - 0xfe00;
478                                 return FM7_MAINMEM_BOOTROM_RAM;
479                         }
480 #else
481                         else if (addr < 0x10000) {
482                                 *realaddr = addr - 0xfffe;
483                                 return FM7_MAINMEM_RESET_VECTOR;
484                         }
485 #endif                  
486                         break;
487                 }
488                 break;
489         }
490         emu->out_debug_log("Main: Over run ADDR = %08x", addr);
491         *realaddr = addr;
492         return FM7_MAINMEM_NULL;
493 }
494      
495 int FM7_MAINMEM::getbank(uint32 addr, uint32 *realaddr, bool write_state, bool dmamode)
496 {
497         if(realaddr == NULL) return FM7_MAINMEM_NULL; // Not effect.
498 #ifdef HAS_MMR
499         if(window_enabled) {
500                 int stat;
501                 uint32 raddr;
502                 stat = window_convert(addr, &raddr);
503                 //if(stat >= 0) printf("WINDOW CONVERT: %04x to %04x, bank = %02x\n", addr, raddr, stat);
504                 if(stat >= 0) {
505                         *realaddr = raddr;
506                         return stat;
507                 }
508         }
509         if(mmr_enabled) {
510                 int stat;
511                 uint32 raddr;
512                 stat = mmr_convert(addr, &raddr, write_state, dmamode);
513                 if(stat >= 0) {
514                   //printf("MMR CONVERT: %04x to %05x, bank = %02x\n", addr, raddr, stat);
515                         *realaddr = raddr;
516                         return stat;
517                 }
518         }
519 #endif
520         addr = addr & 0xffff;
521         // NOT MMR.
522         return nonmmr_convert(addr, realaddr);
523 }
524
525 uint32 FM7_MAINMEM::read_signal(int sigid)
526 {
527         uint32 value = 0x00000000;
528         switch(sigid) {
529         case FM7_MAINIO_PUSH_FD0F:
530                 value = (basicrom_fd0f) ? 0xffffffff : 0x00000000;
531                 break;
532         case FM7_MAINIO_IS_BASICROM:
533                 value = (is_basicrom) ? 0xffffffff : 0x00000000;
534                 break;
535         case FM7_MAINIO_CLOCKMODE:
536                 value = (clockmode) ? 0xffffffff : 0x00000000;
537                 break;
538         case FM7_MAINIO_BOOTMODE:
539                 value = (uint32)bootmode & 0x07;
540                 break;
541 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
542         case FM7_MAINIO_BOOTRAM_RW:
543                 value = (boot_ram_write) ? 0xffffffff : 0x00000000;
544                 break;
545 #endif                  
546 #ifdef HAS_MMR                  
547         case FM7_MAINIO_WINDOW_ENABLED:
548                 value = (window_enabled) ? 0xffffffff : 0x00000000;
549                 break;
550         case FM7_MAINIO_WINDOW_FAST:
551                 value = (window_fast) ? 0xffffffff : 0x00000000;
552                 break;
553         case FM7_MAINIO_FASTMMR_ENABLED:
554                 value = (mmr_fast) ? 0xffffffff : 0x00000000;
555                 break;
556         case FM7_MAINIO_MMR_ENABLED:
557                 value = (mmr_enabled) ? 0xffffffff : 0x00000000;
558                 break;
559         case FM7_MAINIO_MMR_EXTENDED:
560                 value = (mmr_extend) ? 0xffffffff : 0x00000000;
561                 break;
562         case FM7_MAINMEM_REFRESH_FAST:
563                 value = (refresh_fast) ? 0xffffffff : 0x00000000;
564                 break;
565 #endif                  
566 #if defined(_FM77AV_VARIANTS)
567         case FM7_MAINIO_INITROM_ENABLED:
568                 value = (initiator_enabled) ? 0xffffffff: 0x00000000;
569                 break;
570 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)          
571         case FM7_MAINIO_EXTROM:
572                 value = (extrom_bank) ? 0xffffffff: 0x00000000;
573                 break;
574 # endif    
575         case FM7_MAINIO_EXTBANK:
576                 value = extcard_bank & 0x3f;
577                 value |= (dictram_enabled) ? 0x80 : 0;
578                 value |= (dictrom_enabled) ? 0x40 : 0;
579                 break;
580 #endif
581         }
582         return value;
583 }
584
585
586 void FM7_MAINMEM::write_signal(int sigid, uint32 data, uint32 mask)
587 {
588         bool flag = ((data & mask) != 0);
589         switch(sigid) {
590                 case SIG_FM7_SUB_HALT:
591                         sub_halted = flag;
592                         break;
593                 case FM7_MAINIO_IS_BASICROM:
594                         is_basicrom = flag;
595                         break;
596                 case FM7_MAINIO_PUSH_FD0F:
597                         basicrom_fd0f = flag;
598                         break;
599                 case FM7_MAINIO_CLOCKMODE:
600                         clockmode = flag;
601                         break;
602                 case FM7_MAINIO_BOOTMODE:
603                         bootmode = data & 0x07;
604                         break;
605 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
606                 case FM7_MAINIO_BOOTRAM_RW:
607                         boot_ram_write = flag;
608                         break;
609 #endif                  
610 #ifdef _FM77AV_VARIANTS
611                 case FM7_MAINIO_INITROM_ENABLED:
612                         initiator_enabled = flag;
613                         break;
614                 case FM7_MAINIO_EXTBANK:
615                         extcard_bank = data & 0x3f;
616                         dictram_enabled = ((data & 0x80) != 0) ? true : false;
617                         dictrom_enabled = ((data & 0x40) != 0) ? true : false;
618                         break;
619 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)          
620                 case FM7_MAINIO_EXTROM:
621                         extrom_bank = flag;
622                         break;
623 # endif    
624 #endif                  
625 #ifdef HAS_MMR                  
626                 case FM7_MAINIO_WINDOW_ENABLED:
627                         window_enabled = flag;
628                         setclock(config.cpu_type);
629                         break;
630                 case FM7_MAINIO_WINDOW_FAST:
631                         window_fast = flag;
632                         setclock(config.cpu_type);
633                         break;
634                 case FM7_MAINIO_FASTMMR_ENABLED:
635                         mmr_fast = flag;
636                         setclock(config.cpu_type);
637                         break;
638                 case FM7_MAINIO_MMR_ENABLED:
639                         mmr_enabled = flag;
640                         setclock(config.cpu_type);
641                         break;
642                 case FM7_MAINIO_MMR_EXTENDED:
643                         mmr_extend = flag;
644                         break;
645                 case FM7_MAINMEM_REFRESH_FAST:
646                         refresh_fast = flag;
647                         setclock(config.cpu_type);
648                         break;
649 #endif                  
650         }
651 }
652
653
654 uint32 FM7_MAINMEM::read_dma_data8(uint32 addr)
655 {
656 #if defined(HAS_MMR)    
657         uint32 val;
658         val = this->read_data8_main(addr & 0xffff, true);
659         return val;
660 #else
661         return this->read_data8(addr & 0xffff);
662 #endif  
663 }
664
665 uint32 FM7_MAINMEM::read_dma_io8(uint32 addr)
666 {
667 #if defined(HAS_MMR)    
668         uint32 val;
669         val = this->read_data8_main(addr & 0xffff, true);
670         return val;
671 #else
672         return this->read_data8(addr & 0xffff);
673 #endif  
674 }
675
676
677 uint32 FM7_MAINMEM::read_data8_main(uint32 addr, bool dmamode)
678 {
679         uint32 realaddr;
680         int bank;
681         
682         bank = getbank(addr, &realaddr, false, dmamode);
683         if(bank < 0) {
684                 emu->out_debug_log("Illegal BANK: ADDR = %04x", addr);
685                 return 0xff; // Illegal
686         }
687         if(bank == FM7_MAINMEM_SHAREDRAM) {
688                 if(!sub_halted) return 0xff; // Not halt
689                 return display->read_data8(realaddr  + 0xd380); // Okay?
690         } else if(bank == FM7_MAINMEM_NULL) {
691                 return 0xff;
692         }
693 #if defined(_FM77AV_VARIANTS)
694         else if(bank == FM7_MAINMEM_AV_DIRECTACCESS) {
695                 if(!sub_halted) return 0xff; // Not halt
696                 if(dmamode) {
697                         return display->read_dma_data8(realaddr); // Okay?
698                 } else {
699                         return display->read_data8(realaddr); // Okay?
700                 }
701         } else if(bank == FM7_MAINMEM_KANJI_DUMMYADDR) {
702                 return (realaddr & 0x01);
703         }
704 #endif  
705 #if defined(CAPABLE_DICTROM)
706         else if(bank == FM7_MAINMEM_KANJI_LEVEL1) {
707                 return kanjiclass1->read_data8(KANJIROM_DIRECTADDR + realaddr);
708         }
709 #endif
710         else if(read_table[bank].dev != NULL) {
711                 return read_table[bank].dev->read_data8(realaddr);
712         } else if(read_table[bank].memory != NULL) {
713                 return read_table[bank].memory[realaddr];
714         }
715         return 0xff; // Dummy
716 }       
717
718 uint32 FM7_MAINMEM::read_data8(uint32 addr)
719 {
720         uint32 realaddr;
721         int bank;
722
723 #if defined(HAS_MMR)   
724         if(addr >= FM7_MAINIO_WINDOW_OFFSET) {
725                 switch(addr) {
726                 case FM7_MAINIO_WINDOW_OFFSET:
727                         return (uint32)window_offset;
728                         break;
729                 case FM7_MAINIO_MMR_SEGMENT:
730                         return (uint32)mmr_segment;
731                         break;
732                 default:
733                         if((addr >= FM7_MAINIO_MMR_BANK) && (addr < (FM7_MAINIO_MMR_BANK + 0x80))){
734                                 return mmr_map_data[addr - FM7_MAINIO_MMR_BANK];
735                         }
736                         break;
737                 }
738                 return 0xff;
739         }
740 #endif   
741         return this->read_data8_main(addr, false);
742 }
743
744 void FM7_MAINMEM::write_dma_data8(uint32 addr, uint32 data)
745 {
746 #if defined(HAS_MMR)
747         this->write_data8_main(addr & 0xffff, data, true);
748 #else
749         this->write_data8(addr & 0xffff, data);
750 #endif  
751 }
752
753 void FM7_MAINMEM::write_dma_io8(uint32 addr, uint32 data)
754 {
755 #if defined(HAS_MMR)
756         this->write_data8_main(addr & 0xffff, data, true);
757 #else
758         this->write_data8(addr & 0xffff, data);
759 #endif  
760 }
761
762 void FM7_MAINMEM::write_data8_main(uint32 addr, uint32 data, bool dmamode)
763 {
764         uint32 realaddr;
765         int bank;
766         bank = getbank(addr, &realaddr, true, dmamode);
767         if(bank < 0) {
768                 emu->out_debug_log("Illegal BANK: ADDR = %04x", addr);
769                 return; // Illegal
770         }
771         if(bank == FM7_MAINMEM_SHAREDRAM) {
772                 if(!sub_halted) return; // Not halt
773                 display->write_data8(realaddr + 0xd380, data); // Okay?
774                 return;
775         } else if(bank == FM7_MAINMEM_NULL) {
776                 return;
777         }
778 #if defined(_FM7) || defined(_FMNEW7)
779         else if(bank == FM7_MAINMEM_BASICROM) {
780                 bank = FM7_MAINMEM_URA; // FM-7/NEW7 write to ura-ram even enabled basic-rom. 
781         }
782 #endif   
783    
784 #if defined(_FM77AV_VARIANTS)
785         else if(bank == FM7_MAINMEM_AV_DIRECTACCESS) {
786                 if(!sub_halted) return; // Not halt
787                 if(dmamode) {
788                         display->write_dma_data8(realaddr, data); // Okay?
789                 } else {
790                         display->write_data8(realaddr, data); // Okay?
791                 }
792                 return;
793         }
794 #endif
795 #if defined(HAS_MMR)    
796         else if(bank == FM7_MAINMEM_BOOTROM_RAM) {
797                 if(!boot_ram_write) return;
798         }
799 #endif
800         if(write_table[bank].dev != NULL) {
801                 write_table[bank].dev->write_data8(realaddr, data);
802         } else if(write_table[bank].memory != NULL) {
803                 write_table[bank].memory[realaddr] = (uint8)data;
804         }
805 }
806
807 void FM7_MAINMEM::write_data8(uint32 addr, uint32 data)
808 {
809         uint32 realaddr;
810         int bank;
811 #if defined(HAS_MMR)   
812         if(addr >= FM7_MAINIO_WINDOW_OFFSET) {
813                 switch(addr) {
814                 case FM7_MAINIO_WINDOW_OFFSET:
815                         window_offset = data;
816                         break;
817                 case FM7_MAINIO_MMR_SEGMENT:
818                         if(mmr_extend) {
819                                 mmr_segment = data & 0x07;
820                         } else {
821                                 mmr_segment = data & 0x03;
822                         }
823                         break;
824                 default:
825                         if((addr >= FM7_MAINIO_MMR_BANK) && (addr < (FM7_MAINIO_MMR_BANK + 0x80))){
826                                 mmr_map_data[addr - FM7_MAINIO_MMR_BANK] = (uint8)data;
827                         }
828                         break;
829                 }
830                 return;
831         }
832 #endif
833         write_data8_main(addr, data, false);
834 }
835
836 // Read / Write data(s) as big endian.
837 uint32 FM7_MAINMEM::read_data16(uint32 addr)
838 {
839         uint32 hi, lo;
840         uint32 val;
841    
842         hi = read_data8(addr) & 0xff;
843         lo = read_data8(addr + 1) & 0xff;
844    
845         val = hi * 256 + lo;
846         return val;
847 }
848
849 uint32 FM7_MAINMEM::read_data32(uint32 addr)
850 {
851         uint32 ah, a2, a3, al;
852         uint32 val;
853    
854         ah = read_data8(addr) & 0xff;
855         a2 = read_data8(addr + 1) & 0xff;
856         a3 = read_data8(addr + 2) & 0xff;
857         al = read_data8(addr + 3) & 0xff;
858    
859         val = ah * (65536 * 256) + a2 * 65536 + a3 * 256 + al;
860         return val;
861 }
862
863 void FM7_MAINMEM::write_data16(uint32 addr, uint32 data)
864 {
865         uint32 d = data;
866    
867         write_data8(addr + 1, d & 0xff);
868         d = d / 256;
869         write_data8(addr + 0, d & 0xff);
870 }
871
872 void FM7_MAINMEM::write_data32(uint32 addr, uint32 data)
873 {
874         uint32 d = data;
875    
876         write_data8(addr + 3, d & 0xff);
877         d = d / 256;
878         write_data8(addr + 2, d & 0xff);
879         d = d / 256;
880         write_data8(addr + 1, d & 0xff);
881         d = d / 256;
882         write_data8(addr + 0, d & 0xff);
883 }
884
885
886 bool FM7_MAINMEM::get_loadstat_basicrom(void)
887 {
888         return diag_load_basicrom;
889 }
890
891 bool FM7_MAINMEM::get_loadstat_bootrom_bas(void)
892 {
893         return diag_load_bootrom_bas;
894 }
895
896 bool FM7_MAINMEM::get_loadstat_bootrom_dos(void)
897 {
898         return diag_load_bootrom_dos;
899 }
900
901 uint32 FM7_MAINMEM::read_bios(const char *name, uint8 *ptr, uint32 size)
902 {
903         FILEIO fio;
904         uint32 blocks;
905         const _TCHAR *s;
906   
907         if((name == NULL) || (ptr == NULL))  return 0;
908         s = create_local_path((const _TCHAR *)name);
909         if(s == NULL) return 0;
910   
911         if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
912         blocks = fio.Fread(ptr, size, 1);
913         fio.Fclose();
914
915         return blocks * size;
916 }
917
918 uint32 FM7_MAINMEM::write_bios(const char *name, uint8 *ptr, uint32 size)
919 {
920         FILEIO fio;
921         uint32 blocks;
922         const _TCHAR *s;
923   
924         if((name == NULL) || (ptr == NULL))  return 0;
925         s = create_local_path((const _TCHAR *)name);
926         if(s == NULL) return 0;
927   
928         fio.Fopen(s, FILEIO_WRITE_BINARY);
929         blocks = fio.Fwrite(ptr, size, 1);
930         fio.Fclose();
931
932         return blocks * size;
933 }
934
935 void FM7_MAINMEM::update_config()
936 {
937         setclock(config.cpu_type);
938 }
939
940 FM7_MAINMEM::FM7_MAINMEM(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
941 {
942         p_vm = parent_vm;
943         p_emu = parent_emu;
944 #if !defined(_FM77AV_VARIANTS)
945         for(int i = 0; i < 4; i++) fm7_bootroms[i] = (uint8 *)malloc(0x200);
946 #endif  
947         mainio = NULL;
948         display = NULL;
949         maincpu = NULL;
950 #if defined(CAPABLE_DICTROM)
951         kanjiclass1 = NULL;
952 #endif  
953 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)  || \
954         defined(_FM77_VARIANTS)
955         fm7_mainmem_extram = NULL;
956 #endif
957         // Initialize table
958         memset(read_table, 0x00, sizeof(read_table));
959         memset(write_table, 0x00, sizeof(write_table));
960 }
961
962 FM7_MAINMEM::~FM7_MAINMEM()
963 {
964 }
965
966 void FM7_MAINMEM::initialize(void)
967 {
968         int i;
969         diag_load_basicrom = false;
970         diag_load_bootrom_bas = false;
971         diag_load_bootrom_dos = false;
972         diag_load_bootrom_mmr = false;
973
974
975 #if defined(_FM77AV_VARIANTS)
976         dictrom_connected = false;
977 #endif
978 #ifdef HAS_MMR  
979         for(i = 0x00; i < 0x80; i++) {
980                 mmr_map_data[i] = 0;
981         }
982         mmr_segment = 0;
983         window_offset = 0;
984         mmr_enabled = false;
985         mmr_fast = false;
986         window_enabled = false;
987 #endif  
988 #ifdef _FM77AV_VARIANTS
989         extcard_bank = 0;
990         extrom_bank = false;
991         dictrom_enabled = false;
992         dictram_enabled = false;
993         
994         initiator_enabled = true;
995         boot_ram_write = true;
996 #endif  
997         bootmode = config.boot_mode & 3;
998         basicrom_fd0f = false;
999         is_basicrom = ((bootmode & 0x03) == 0) ? true : false;
1000    
1001         // $0000-$7FFF
1002         i = FM7_MAINMEM_OMOTE;
1003         memset(fm7_mainmem_omote, 0x00, 0x8000 * sizeof(uint8));
1004         read_table[i].memory = fm7_mainmem_omote;
1005         write_table[i].memory = fm7_mainmem_omote;
1006
1007         // $8000-$FBFF
1008         i = FM7_MAINMEM_URA;
1009         memset(fm7_mainmem_ura, 0x00, 0x7c00 * sizeof(uint8));
1010         read_table[i].memory = fm7_mainmem_ura;
1011         write_table[i].memory = fm7_mainmem_ura;
1012         
1013         i = FM7_MAINMEM_VECTOR;
1014         memset(fm7_mainmem_bootrom_vector, 0x00, 0x1e);
1015         read_table[i].memory = fm7_mainmem_bootrom_vector;
1016         write_table[i].memory = fm7_mainmem_bootrom_vector;
1017         
1018         
1019 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
1020         defined(_FM77_VARIANTS)
1021         extram_pages = FM77_EXRAM_BANKS;
1022 #if defined(_FM77_VARIANTS)
1023         if(extram_pages > 3) extram_pages = 3;
1024 #else
1025         if(extram_pages > 12) extram_pages = 12;
1026 #endif 
1027         if(extram_pages > 0) {
1028                 i = FM7_MAINMEM_EXTRAM;
1029                 fm7_mainmem_extram = (uint8 *)malloc(extram_pages * 0x10000);
1030                 if(fm7_mainmem_extram != NULL) {
1031                         memset(fm7_mainmem_extram, 0x00, extram_pages * 0x10000);
1032                         read_table[i].memory = fm7_mainmem_extram;
1033                         write_table[i].memory = fm7_mainmem_extram;
1034                 }
1035         }
1036 #endif  
1037
1038 #if defined(_FM77_VARIANTS)
1039         memset(fm77_shadowram, 0x00, 0x200);
1040         read_table[FM7_MAINMEM_SHADOWRAM].memory = fm77_shadowram;
1041         write_table[FM7_MAINMEM_SHADOWRAM].memory = fm77_shadowram;
1042 #endif
1043 #if !defined(_FM77AV_VARIANTS)  
1044         for(i = FM7_MAINMEM_BOOTROM_BAS; i <= FM7_MAINMEM_BOOTROM_EXTRA; i++) {
1045                  memset(fm7_bootroms[i - FM7_MAINMEM_BOOTROM_BAS], 0xff, 0x200);
1046                  read_table[i].memory = fm7_bootroms[i - FM7_MAINMEM_BOOTROM_BAS];
1047         }
1048 #endif  
1049 #if defined(_FM8)
1050         if(read_bios("BOOT_BAS8.ROM", fm7_bootroms[0], 0x200) >= 0x1e0) {
1051                 diag_load_bootrom_bas = true;
1052         } else {
1053                 diag_load_bootrom_bas = false;
1054         }
1055         if(read_bios("BOOT_DOS8.ROM", fm7_bootroms[1], 0x200) >= 0x1e0) {
1056                 diag_load_bootrom_dos = true;
1057         } else {
1058                 diag_load_bootrom_dos = false;
1059         }
1060         diag_load_bootrom_mmr = false;
1061 # elif defined(_FM7) || defined(_FMNEW7) || defined(_FM77_VARIANTS)
1062         if(read_bios("BOOT_BAS.ROM", fm7_bootroms[0], 0x200) >= 0x1e0) {
1063                 diag_load_bootrom_bas = true;
1064         } else {
1065                 diag_load_bootrom_bas = false;
1066         }
1067         if(read_bios("BOOT_DOS.ROM", fm7_bootroms[1], 0x200) >= 0x1e0) {
1068                 diag_load_bootrom_dos = true;
1069         } else {
1070                 diag_load_bootrom_dos = false;
1071         }
1072 #  if defined(_FM77_VARIANTS)
1073         if(read_bios("BOOT_MMR.ROM", fm7_bootroms[2], 0x200) >= 0x1e0) {
1074                 diag_load_bootrom_mmr = true;
1075         } else {
1076                 diag_load_bootrom_mmr = false;
1077         }
1078    
1079         i = FM7_MAINMEM_BOOTROM_RAM;
1080         memset(fm7_bootram, 0x00, 0x200 * sizeof(uint8)); // RAM
1081         read_table[i].memory = fm7_bootram;
1082         write_table[i].memory = fm7_bootram;
1083 #  else
1084        // FM-7/8
1085         diag_load_bootrom_mmr = false;
1086 #  endif
1087 # elif defined(_FM77AV_VARIANTS)
1088         i = FM7_MAINMEM_AV_PAGE0;
1089         memset(fm7_mainmem_mmrbank_0, 0x00, 0x10000 * sizeof(uint8));
1090         read_table[i].memory = fm7_mainmem_mmrbank_0;
1091         write_table[i].memory = fm7_mainmem_mmrbank_0;
1092         
1093         i = FM7_MAINMEM_AV_PAGE2;
1094         memset(fm7_mainmem_mmrbank_2, 0x00, 0x10000 * sizeof(uint8));
1095         read_table[i].memory = fm7_mainmem_mmrbank_2;
1096         write_table[i].memory = fm7_mainmem_mmrbank_2;
1097         
1098         i = FM7_MAINMEM_INITROM;
1099         diag_load_initrom = false;
1100         memset(fm7_mainmem_initrom, 0xff, 0x2000 * sizeof(uint8));
1101         read_table[i].memory = fm7_mainmem_initrom;
1102
1103         if(read_bios("INITIATE.ROM", read_table[i].memory, 0x2000) >= 0x2000) diag_load_initrom = true;
1104         emu->out_debug_log("77AV INITIATOR ROM READING : %s", diag_load_initrom ? "OK" : "NG");
1105
1106         read_table[FM7_MAINMEM_BOOTROM_BAS].memory = NULL; // Not connected.
1107         read_table[FM7_MAINMEM_BOOTROM_DOS].memory = NULL; // Not connected.
1108         read_table[FM7_MAINMEM_BOOTROM_MMR].memory = NULL; // Not connected.
1109         
1110         if(read_bios("BOOT_MMR.ROM", fm77av_hidden_bootmmr, 0x200) < 0x1e0) {
1111                 memcpy(fm77av_hidden_bootmmr, &fm7_mainmem_initrom[0x1a00], 0x200);
1112         }
1113         read_table[FM7_MAINMEM_BOOTROM_MMR].memory = fm77av_hidden_bootmmr; // Not connected.
1114         fm77av_hidden_bootmmr[0x1fe] = 0xfe;
1115         fm77av_hidden_bootmmr[0x1fe] = 0x00;
1116         
1117         i = FM7_MAINMEM_BOOTROM_RAM;
1118         memset(fm7_bootram, 0x00, 0x200 * sizeof(uint8)); // RAM
1119         read_table[i].memory = fm7_bootram;
1120         write_table[i].memory = fm7_bootram;
1121         
1122         if(diag_load_initrom) diag_load_bootrom_bas = true;
1123         if(diag_load_initrom) diag_load_bootrom_dos = true;
1124         
1125         if((config.boot_mode & 0x03) == 0) {
1126                 memcpy(fm7_bootram, &fm7_mainmem_initrom[0x1800], 0x1e0 * sizeof(uint8));
1127         } else {
1128                 memcpy(fm7_bootram, &fm7_mainmem_initrom[0x1a00], 0x1e0 * sizeof(uint8));
1129         }
1130         fm7_bootram[0x1fe] = 0xfe; // Set reset vector.
1131         fm7_bootram[0x1ff] = 0x00; //
1132         // FM-7
1133 #endif
1134         emu->out_debug_log("BOOT ROM (basic mode) READING : %s", diag_load_bootrom_bas ? "OK" : "NG");
1135         emu->out_debug_log("BOOT ROM (DOS   mode) READING : %s", diag_load_bootrom_dos ? "OK" : "NG");
1136 #if defined(_FM77_VARIANTS)
1137         emu->out_debug_log("BOOT ROM (MMR   mode) READING : %s", diag_load_bootrom_mmr ? "OK" : "NG");
1138 #endif
1139
1140
1141 #if !defined(_FM77AV_VARIANTS)
1142         for(i = 0; i <= 3; i++) {
1143                 uint8 *p = fm7_bootroms[i];
1144                 p[0x1fe] = 0xfe; // Set reset vector.
1145                 p[0x1ff] = 0x00; //
1146         }
1147         
1148 #endif  
1149         i = FM7_MAINMEM_RESET_VECTOR;
1150         fm7_mainmem_reset_vector[0] = 0xfe;
1151         fm7_mainmem_reset_vector[1] = 0x00;
1152    
1153         read_table[i].memory = fm7_mainmem_reset_vector;
1154    
1155         i = FM7_MAINMEM_BASICROM;
1156         memset(fm7_mainmem_basicrom, 0xff, 0x7c00 * sizeof(uint8));
1157
1158         read_table[i].memory = fm7_mainmem_basicrom;
1159 #if !defined(_FM8)
1160         if(read_bios("FBASIC302.ROM", fm7_mainmem_basicrom, 0x7c00) == 0x7c00) {
1161                 diag_load_basicrom = true;
1162         } else if(read_bios("FBASIC300.ROM", fm7_mainmem_basicrom, 0x7c00) == 0x7c00) {
1163                 diag_load_basicrom = true;
1164         } else if(read_bios("FBASIC30.ROM", fm7_mainmem_basicrom, 0x7c00) == 0x7c00) {
1165                 diag_load_basicrom = true;
1166         }
1167    
1168 #else // FM8
1169         if(read_bios("FBASIC10.ROM", fm7_mainmem_basicrom, 0x7c00) == 0x7c00) diag_load_basicrom = true;
1170 #endif  
1171         emu->out_debug_log("BASIC ROM READING : %s", diag_load_basicrom ? "OK" : "NG");
1172    
1173         i = FM7_MAINMEM_BIOSWORK;
1174         memset(fm7_mainmem_bioswork, 0x00, 0x80 * sizeof(uint8));
1175         read_table[i].memory = fm7_mainmem_bioswork;
1176         write_table[i].memory = fm7_mainmem_bioswork;
1177 #if defined(CAPABLE_DICTROM)
1178         diag_load_dictrom = false;
1179         i = FM7_MAINMEM_DICTROM;
1180         memset(fm7_mainmem_dictrom, 0xff, 0x40000 * sizeof(uint8));
1181         read_table[i].memory = fm7_mainmem_dictrom;
1182         if(read_bios("DICROM.ROM", fm7_mainmem_dictrom, 0x40000) == 0x40000) diag_load_dictrom = true;
1183         emu->out_debug_log("DICTIONARY ROM READING : %s", diag_load_dictrom ? "OK" : "NG");
1184         dictrom_connected = diag_load_dictrom;
1185         
1186         i = FM7_MAINMEM_BACKUPED_RAM;
1187         diag_load_learndata = false;
1188         memset(fm7_mainmem_learndata, 0x00, 0x2000 * sizeof(uint8));
1189         read_table[i].memory = fm7_mainmem_learndata;
1190         write_table[i].memory = fm7_mainmem_learndata;
1191         if(read_bios("USERDIC.DAT", read_table[i].memory, 0x2000) == 0x2000) diag_load_learndata = true;
1192         emu->out_debug_log("DICTIONARY BACKUPED RAM READING : %s", diag_load_learndata ? "OK" : "NG");
1193         if(!diag_load_learndata) write_bios("USERDIC.DAT", fm7_mainmem_learndata, 0x2000);
1194 #endif
1195         
1196         i = FM7_MAINMEM_77AV40_EXTRAROM;
1197 #if defined(_FM77AV40SX) || defined(_FM77AV40EX)
1198         diag_load_extrarom = false;
1199         memset(fm7_mainmem_extrarom, 0xff, sizeof(fm7_mainmem_extrarom));
1200         read_table[i].memory = fm7_mainmem_extrarom;
1201         if(read_bios("EXTSUB.ROM", read_table[i].memory, 0xc000) == 0xc000) diag_load_extrarom = true;
1202         emu->out_debug_log("AV40SX/EX EXTRA ROM READING : %s", diag_load_extrarom ? "OK" : "NG");
1203 #endif
1204 }
1205
1206 void FM7_MAINMEM::release()
1207 {
1208 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
1209          defined(_FM77_VARIANTS)
1210         if(fm7_mainmem_extram != NULL) free(fm7_mainmem_extram);
1211 #endif  
1212 #if !defined(_FM77AV_VARIANTS)
1213         int i;
1214         for(i = 0; i < 4; i++) {
1215                 if(fm7_bootroms[i] != NULL) free(fm7_bootroms[i]);
1216                 fm7_bootroms[i] = NULL;
1217         }
1218 #endif
1219 #if defined(CAPABLE_DICTROM)
1220         write_bios("USERDIC.DAT", fm7_mainmem_learndata, 0x2000);
1221 #endif
1222 //      MEMORY::release();
1223 }
1224
1225 #define STATE_VERSION 2
1226 void FM7_MAINMEM::save_state(FILEIO *state_fio)
1227 {
1228         state_fio->FputUint32_BE(STATE_VERSION);
1229         state_fio->FputInt32_BE(this_device_id);
1230
1231         // V1
1232         state_fio->FputBool(ioaccess_wait);
1233         state_fio->FputInt32_BE(waitfactor);
1234         state_fio->FputInt32_BE(waitcount);
1235
1236         state_fio->FputBool(sub_halted);
1237         
1238         state_fio->FputBool(diag_load_basicrom);
1239         state_fio->FputBool(diag_load_bootrom_bas);
1240         state_fio->FputBool(diag_load_bootrom_dos);
1241         state_fio->FputBool(diag_load_bootrom_mmr);
1242         state_fio->Fwrite(fm7_mainmem_omote, sizeof(fm7_mainmem_omote), 1);
1243         state_fio->Fwrite(fm7_mainmem_ura, sizeof(fm7_mainmem_ura), 1);
1244         state_fio->Fwrite(fm7_mainmem_basicrom, sizeof(fm7_mainmem_basicrom), 1);
1245         state_fio->Fwrite(fm7_mainmem_bioswork, sizeof(fm7_mainmem_bioswork), 1);
1246         state_fio->Fwrite(fm7_mainmem_bootrom_vector, sizeof(fm7_mainmem_bootrom_vector), 1);
1247         state_fio->Fwrite(fm7_mainmem_reset_vector, sizeof(fm7_mainmem_reset_vector), 1);
1248         
1249         state_fio->Fwrite(fm7_mainmem_null, sizeof(fm7_mainmem_null), 1);
1250 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
1251         state_fio->Fwrite(fm7_bootram, sizeof(fm7_bootram), 1);
1252 #endif  
1253 #if !defined(_FM77AV_VARIANTS)
1254         int addr;
1255         for(addr = 0; addr < 4; addr++) state_fio->Fwrite(fm7_bootroms[addr], sizeof(0x200), 1);
1256 #endif  
1257 #ifdef _FM77AV_VARIANTS
1258         state_fio->FputBool(dictrom_connected);
1259         state_fio->FputBool(use_page2_extram);
1260         
1261         state_fio->FputBool(diag_load_initrom);
1262         state_fio->FputBool(diag_load_dictrom);
1263         state_fio->FputBool(diag_load_learndata);
1264         state_fio->Fwrite(fm7_mainmem_initrom, sizeof(fm7_mainmem_initrom), 1);
1265         state_fio->Fwrite(fm77av_hidden_bootmmr, sizeof(fm77av_hidden_bootmmr), 1);
1266         
1267         state_fio->Fwrite(fm7_mainmem_mmrbank_0, sizeof(fm7_mainmem_mmrbank_0), 1);
1268         state_fio->Fwrite(fm7_mainmem_mmrbank_2, sizeof(fm7_mainmem_mmrbank_2), 1);
1269         
1270 # if defined(_FM77AV40SX) || defined(_FM77AV40EX)
1271         state_fio->FputBool(diag_load_extrarom);
1272         state_fio->Fwrite(fm7_mainmem_extrarom, sizeof(fm7_mainmem_extrarom), 1);
1273 # endif
1274 # if defined(CAPABLE_DICTROM)
1275         state_fio->Fwrite(fm7_mainmem_dictrom, sizeof(fm7_mainmem_dictrom), 1);
1276         state_fio->Fwrite(fm7_mainmem_learndata, sizeof(fm7_mainmem_learndata), 1);
1277 # endif
1278 #endif
1279         
1280 #ifdef HAS_MMR
1281         state_fio->FputBool(extram_connected);
1282 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
1283          defined(_FM77_VARIANTS)
1284         int pages;
1285         state_fio->FputInt32_BE(extram_pages);
1286         pages = extram_pages;
1287 #  if defined(_FM77_VARIANTS)
1288         if(pages > 3) pages = 3;
1289 #  else
1290         if(pages > 12) pages = 12;
1291 #  endif        
1292         if(pages > 0) state_fio->Fwrite(fm7_mainmem_extram, pages * 0x10000, 1);
1293 #  if defined(_FM77_VARIANTS)
1294         state_fio->Fwrite(fm77_shadowram, sizeof(fm77_shadowram), 1);
1295 #  endif
1296 # endif
1297 #endif
1298         
1299         { // V2;
1300                 state_fio->FputBool(is_basicrom);
1301                 state_fio->FputBool(clockmode);
1302                 state_fio->FputBool(basicrom_fd0f);
1303                 state_fio->FputUint32_BE(bootmode);
1304 #if defined(_FM77AV_VARIANTS)
1305                 state_fio->FputUint32_BE(extcard_bank);
1306                 state_fio->FputBool(extrom_bank);
1307                 state_fio->FputBool(initiator_enabled);
1308                 state_fio->FputBool(dictrom_enabled);
1309                 state_fio->FputBool(dictram_enabled);
1310 #endif
1311 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
1312                 state_fio->FputBool(boot_ram_write);
1313 #endif          
1314 #if defined(HAS_MMR)
1315                 state_fio->FputBool(window_enabled);
1316                 state_fio->FputBool(mmr_enabled);
1317                 state_fio->FputBool(mmr_fast);
1318                 state_fio->FputBool(mmr_extend);
1319                 
1320                 state_fio->FputUint16_BE(window_offset);
1321                 state_fio->FputBool(window_fast);
1322                 state_fio->FputBool(refresh_fast);
1323                 state_fio->FputUint8(mmr_segment);
1324                 state_fio->Fwrite(mmr_map_data, sizeof(mmr_map_data), 1);
1325 #endif
1326         }
1327 }
1328
1329 bool FM7_MAINMEM::load_state(FILEIO *state_fio)
1330 {
1331         uint32 version;
1332         version = state_fio->FgetUint32_BE();
1333         if(this_device_id != state_fio->FgetInt32_BE()) return false;
1334         if(version >= 1) {
1335                 // V1
1336                 ioaccess_wait = state_fio->FgetBool();
1337                 waitfactor = state_fio->FgetInt32_BE();
1338                 waitcount = state_fio->FgetInt32_BE();
1339
1340                 sub_halted = state_fio->FgetBool();
1341         
1342                 diag_load_basicrom = state_fio->FgetBool();
1343                 diag_load_bootrom_bas = state_fio->FgetBool();
1344                 diag_load_bootrom_dos = state_fio->FgetBool();
1345                 diag_load_bootrom_mmr = state_fio->FgetBool();
1346                 
1347                 state_fio->Fread(fm7_mainmem_omote, sizeof(fm7_mainmem_omote), 1);
1348                 state_fio->Fread(fm7_mainmem_ura, sizeof(fm7_mainmem_ura), 1);
1349                 state_fio->Fread(fm7_mainmem_basicrom, sizeof(fm7_mainmem_basicrom), 1);
1350                 state_fio->Fread(fm7_mainmem_bioswork, sizeof(fm7_mainmem_bioswork), 1);
1351                 state_fio->Fread(fm7_mainmem_bootrom_vector, sizeof(fm7_mainmem_bootrom_vector), 1);
1352                 state_fio->Fread(fm7_mainmem_reset_vector, sizeof(fm7_mainmem_reset_vector), 1);
1353         
1354                 state_fio->Fread(fm7_mainmem_null, sizeof(fm7_mainmem_null), 1);
1355 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
1356                 state_fio->Fread(fm7_bootram, sizeof(fm7_bootram), 1);
1357 #endif  
1358 #if !defined(_FM77AV_VARIANTS)
1359                 int addr;
1360                 for(addr = 0; addr < 4; addr++) state_fio->Fread(fm7_bootroms[addr], sizeof(0x200), 1);
1361 #endif  
1362 #ifdef _FM77AV_VARIANTS
1363                 dictrom_connected = state_fio->FgetBool();
1364                 use_page2_extram = state_fio->FgetBool();
1365         
1366                 diag_load_initrom = state_fio->FgetBool();
1367                 diag_load_dictrom = state_fio->FgetBool();
1368                 diag_load_learndata = state_fio->FgetBool();
1369                 state_fio->Fread(fm7_mainmem_initrom, sizeof(fm7_mainmem_initrom), 1);
1370                 state_fio->Fread(fm77av_hidden_bootmmr, sizeof(fm77av_hidden_bootmmr), 1);
1371                 
1372                 state_fio->Fread(fm7_mainmem_mmrbank_0, sizeof(fm7_mainmem_mmrbank_0), 1);
1373                 state_fio->Fread(fm7_mainmem_mmrbank_2, sizeof(fm7_mainmem_mmrbank_2), 1);
1374         
1375 # if defined(_FM77AV40SX) || defined(_FM77AV40EX)
1376                 diag_load_extrarom = state_fio->FgetBool();
1377                 state_fio->Fread(fm7_mainmem_extrarom, sizeof(fm7_mainmem_extrarom), 1);
1378 # endif         
1379 # if defined(CAPABLE_DICTROM)
1380                 state_fio->Fread(fm7_mainmem_dictrom, sizeof(fm7_mainmem_dictrom), 1);
1381                 state_fio->Fread(fm7_mainmem_learndata, sizeof(fm7_mainmem_learndata), 1);
1382 # endif
1383 #endif
1384         
1385 #ifdef HAS_MMR
1386                 extram_connected = state_fio->FgetBool();
1387 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
1388          defined(_FM77_VARIANTS)
1389                 int pages;
1390                 extram_pages = state_fio->FgetInt32_BE();
1391                 pages = extram_pages;
1392 #  if defined(_FM77_VARIANTS)
1393                 if(pages > 3) pages = 3;
1394 #  else
1395                 if(pages > 12) pages = 12;
1396 #  endif        
1397                 if(pages > 0) state_fio->Fread(fm7_mainmem_extram, pages * 0x10000, 1);
1398 #  if defined(_FM77_VARIANTS)
1399                 state_fio->Fread(fm77_shadowram, sizeof(fm77_shadowram), 1);
1400 #  endif
1401 # endif
1402 #endif
1403                 if(version == 1) return true;
1404         }
1405         if(version >= 2) { // V2;
1406                 is_basicrom = state_fio->FgetBool();
1407                 clockmode = state_fio->FgetBool();
1408                 basicrom_fd0f = state_fio->FgetBool();
1409                 bootmode = state_fio->FgetUint32_BE();
1410 #if defined(_FM77AV_VARIANTS)
1411                 extcard_bank = state_fio->FgetUint32_BE();
1412                 extrom_bank = state_fio->FgetBool();
1413                 initiator_enabled = state_fio->FgetBool();
1414                 dictrom_enabled = state_fio->FgetBool();
1415                 dictram_enabled = state_fio->FgetBool();
1416 #endif
1417 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
1418                 boot_ram_write = state_fio->FgetBool();
1419 #endif          
1420 #if defined(HAS_MMR)
1421                 window_enabled = state_fio->FgetBool();
1422                 mmr_enabled = state_fio->FgetBool();
1423                 mmr_fast = state_fio->FgetBool();
1424                 mmr_extend = state_fio->FgetBool();
1425                 
1426                 window_offset = state_fio->FgetUint16_BE();
1427                 window_fast = state_fio->FgetBool();
1428                 refresh_fast = state_fio->FgetBool();
1429                 mmr_segment = state_fio->FgetUint8();
1430                 state_fio->Fread(mmr_map_data, sizeof(mmr_map_data), 1);
1431 #endif
1432         }
1433         return true;
1434 }