OSDN Git Service

[VM][General] *Important* Separate some devices to DLL; libCSPcommon_vm .
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / display.cpp
1 /*
2  * Common source code project -> FM-7 -> Display
3  * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
4  * History:
5  *  Feb 10, 2015 : Initial.
6  */
7
8 #include "vm.h"
9 #include "emu.h"
10 #include "../../fileio.h"
11 #include "fm7_display.h"
12 #if defined(_FM77AV_VARIANTS)
13 # include "mb61vh010.h"
14 #endif
15
16 DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
17 {
18         p_vm = parent_vm;
19         p_emu = parent_emu;
20         ins_led = NULL;
21         kana_led = NULL;
22         caps_led = NULL;
23 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
24         kanjiclass1 = NULL;
25         kanjiclass2 = NULL;
26 #elif defined(_FM77_VARIANTS)
27         kanjiclass1 = NULL;
28 #endif
29 #if defined(_FM77AV_VARIANTS)
30         alu = NULL;
31 #endif
32         mainio = NULL;
33         subcpu = NULL;
34         keyboard = NULL;
35         for(int i = 0; i < 256; i++) {
36                 uint16_t n = (uint16_t)i;
37                 for(int j = 0; j < 8; j++) {
38                         bit_trans_table_0[i][j] = n & 0x80;
39                         bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
40                         bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
41                         bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
42 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
43                         bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
44                         bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
45 #endif                  
46                         n <<= 1;
47                 }
48         }
49         displine = 0;
50         active_page = 0;
51         set_device_name(_T("DISPLAY SUBSYSTEM"));
52 }
53
54 DISPLAY::~DISPLAY()
55 {
56
57 }
58
59 void DISPLAY::reset_cpuonly()
60 {
61         int i;
62         double usec;
63         keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
64         mainio->write_signal(SIG_FM7_SUB_HALT, 0x00, 0xff);
65         sub_busy = true;
66         
67         palette_changed = true;
68         multimode_accessmask = 0;
69         multimode_dispmask = 0;
70         firq_mask = false;
71         //cancel_request = false;
72         switch(config.cpu_type){
73                 case 0:
74                         clock_fast = true;
75                         break;
76                 case 1:
77                         clock_fast = false;
78                         break;
79         }
80         enter_display();
81    
82         offset_point = 0;
83         for(i = 0; i < 2; i++) {
84                 offset_changed[i] = true;
85                 tmp_offset_point[i].d = 0;
86         }
87
88         vram_wrote_shadow = true;
89         for(i = 0; i < 411; i++) vram_wrote_table[i] = true;
90         for(i = 0; i < 411; i++) vram_draw_table[i] = true;
91         displine = 0;
92         active_page = 0;
93         
94 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
95         vsync = true;
96         vblank = true;
97         hblank = false;
98         vblank_count = 0;
99         
100         if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
101         if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
102         if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
103         if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
104         hblank_event_id = -1;
105         hdisp_event_id = -1;
106         vsync_event_id = -1;
107         vstart_event_id = -1;
108         if(display_mode == DISPLAY_MODE_8_400L) {
109                 usec = 0.33 * 1000.0; 
110         } else {
111                 usec = 0.51 * 1000.0;
112         }
113         //usec = 16.0;
114         register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
115         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
116         mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
117 #endif
118 #if defined(_FM77AV_VARIANTS)
119         offset_77av = false;
120         offset_point_bank1 = 0;
121         display_page = 0;
122         display_page_bak = 0;
123         
124         subcpu_resetreq = false;
125         subrom_bank_using = subrom_bank;
126    
127         nmi_enable = true;
128         use_alu = false;
129
130 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
131         vram_bank = 0;
132         vram_display_block = 0;
133         vram_active_block = 0;
134         
135 #  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
136         window_low = 0;
137         window_high = 0;
138         window_xbegin = 0;
139         window_xend = 0;
140         window_opened = false;
141 #  endif        
142 # endif
143         
144         alu->reset();
145 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
146         alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
147         alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
148         alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
149 # else
150         alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
151         alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
152         alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
153 # endif
154         alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
155         alu->write_signal(SIG_ALU_PLANES, 3, 3);
156         
157 #endif
158         for(i = 0; i < 8; i++) set_dpalette(i, i);
159         do_firq(!firq_mask && key_firq_req);
160
161 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
162         kanjisub = false;
163         kanjiaddr.d = 0x00000000;
164 # if defined(_FM77L4)
165         mode400line = false;
166         stat_400linecard = false;
167 # endif 
168 #endif
169         vram_wrote = true;
170         clr_count = 0;
171         frame_skip_count = 3;
172 }
173
174
175 void DISPLAY::reset()
176 {
177         int i;
178         memset(io_w_latch, 0xff, sizeof(io_w_latch));
179         halt_flag = false;
180         vram_accessflag = true;
181         display_mode = DISPLAY_MODE_8_200L;
182         crt_flag = true;
183         screen_update_flag = true;
184         crt_flag_bak = true;
185         
186         cancel_request = false;
187 #if defined(_FM77AV_VARIANTS)
188         mode320 = false;
189         apalette_index.d = 0;
190         for(i = 0; i < 4096; i++) {
191                 analog_palette_r[i] = i & 0x0f0;
192                 analog_palette_g[i] = (i & 0xf00) >> 4;
193                 analog_palette_b[i] = (i & 0x00f) << 4;
194                 calc_apalette(i);
195         }
196         subrom_bank = 0;
197         cgrom_bank = 0;
198 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
199         monitor_ram = false;
200         ram_protect = true;
201         
202         mode400line = false;
203         mode256k = false;
204 # endif
205 #elif defined(_FM77L4)
206         mode400line = false;
207 #endif
208         emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
209         is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
210         key_firq_req = false;   //firq_mask = true;
211         firq_mask = false;
212         reset_cpuonly();
213         
214 #if defined(_FM77AV_VARIANTS)
215         power_on_reset = false;
216         for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
217         nmi_enable = true;
218 #else
219 # if defined(_FM8)
220         for(i = 0; i < 8; i++) set_dpalette(i, i);
221         multimode_accessmask = 0x00;
222         multimode_dispmask = 0x00;
223 # endif
224 #endif  
225         //enter_display();
226         
227         if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
228         register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
229         subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
230         subcpu->reset();
231 }
232
233 void DISPLAY::update_config()
234 {
235         vram_wrote = true;
236 #if !defined(_FM8)
237         is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
238 #endif  
239         enter_display();
240 }
241
242 /*
243  * Vram accessing functions moved to vram.cpp .
244  */
245
246 void DISPLAY::do_irq(bool flag)
247 {
248         subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
249 }
250
251 void DISPLAY::do_firq(bool flag)
252 {
253         subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
254 }
255
256 void DISPLAY::do_nmi(bool flag)
257 {
258 #if defined(_FM77AV_VARIANTS)
259         if(!nmi_enable) flag = false;
260 #endif
261         subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
262 }
263
264 void DISPLAY::set_multimode(uint8_t val)
265 {
266 #if !defined(_FM8)      
267         multimode_accessmask = val & 0x07;
268         multimode_dispmask = (val & 0x70) >> 4;
269         vram_wrote = true;
270 # if defined(_FM77AV_VARIANTS)
271         alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
272 # endif
273 #endif  
274 }
275
276 uint8_t DISPLAY::get_multimode(void)
277 {
278 #if defined(_FM8)
279         return 0xff;
280 #else
281         uint8_t val;
282         val = multimode_accessmask & 0x07;
283         val |= ((multimode_dispmask << 4) & 0x70);
284         val |= 0x80;
285         return val;
286 #endif  
287 }
288
289 uint8_t DISPLAY::get_cpuaccessmask(void)
290 {
291         return multimode_accessmask & 0x07;
292 }
293
294 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
295 {
296         scrntype_t r, g, b;
297         addr &= 7;
298         dpalette_data[addr] = val | 0xf8; //0b11111000;
299         b =  ((val & 0x01) != 0x00)? 255 : 0x00;
300         r =  ((val & 0x02) != 0x00)? 255 : 0x00;
301         g =  ((val & 0x04) != 0x00)? 255 : 0x00;
302         
303         dpalette_pixel[addr] = RGB_COLOR(r, g, b);
304         palette_changed = true;
305 }
306
307 uint8_t DISPLAY::get_dpalette(uint32_t addr)
308 {
309 #if defined(_FM8)
310         return 0xff;
311 #else
312         uint8_t data;
313         addr = addr & 7;
314         
315         data = dpalette_data[addr];
316         return data;
317 #endif
318 }
319
320 void DISPLAY::halt_subcpu(void)
321 {
322         subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
323 }
324
325 void DISPLAY::go_subcpu(void)
326 {
327         subcpu->write_signal(SIG_CPU_BUSREQ, 0x00, 0x01);
328 }
329
330 void DISPLAY::enter_display(void)
331 {
332         uint32_t subclock;
333         if(clock_fast) {
334                 subclock = SUBCLOCK_NORMAL;
335         } else {
336                 subclock = SUBCLOCK_SLOW;
337         }
338         if(!is_cyclesteal && vram_accessflag) {
339                 subclock = subclock / 3;
340         }
341         if(prev_clock != subclock) p_vm->set_cpu_clock(subcpu, subclock);
342         prev_clock = subclock;
343 }
344
345 void DISPLAY::leave_display(void)
346 {
347 }
348
349 void DISPLAY::halt_subsystem(void)
350 {
351         halt_flag = false;
352         halt_subcpu();
353 }
354
355 void DISPLAY::restart_subsystem(void)
356 {
357         halt_flag = false;
358 #if defined(_FM77AV_VARIANTS)
359         if(subcpu_resetreq) {
360                 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
361                 reset_cpuonly();
362                 power_on_reset = true;
363                 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
364                 subcpu->reset();
365                 do_firq(!firq_mask && key_firq_req);
366         }
367 #endif
368         go_subcpu();
369 }
370
371 //SUB:D408:R
372 void DISPLAY::set_crtflag(void)
373 {
374         crt_flag = true;
375         vram_wrote = true;
376 }
377
378 //SUB:D408:W
379 void DISPLAY::reset_crtflag(void)
380 {
381         crt_flag = false;
382         vram_wrote = true;
383 }
384
385 //SUB:D402:R
386 uint8_t DISPLAY::acknowledge_irq(void)
387 {
388         cancel_request = false;
389         do_irq(false);
390         return 0xff;
391 }
392
393 //SUB:D403:R
394 uint8_t DISPLAY::beep(void)
395 {
396         mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
397         return 0xff; // True?
398 }
399
400
401 // SUB:D404 : R 
402 uint8_t DISPLAY::attention_irq(void)
403 {
404         mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
405         return 0xff;
406 }
407
408 // SUB:D405:W
409 void DISPLAY::set_cyclesteal(uint8_t val)
410 {
411 #if !defined(_FM8)
412 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)       
413         vram_wrote = true;
414         val &= 0x01;
415         if(val == 0) {
416                 is_cyclesteal = true;
417         } else {
418                 is_cyclesteal = false;
419         }
420         enter_display();
421 # endif 
422 #endif
423 }
424
425 //SUB:D409:R
426 uint8_t DISPLAY::set_vramaccess(void)
427 {
428         vram_accessflag = true;
429         return 0xff;
430 }
431
432 //SUB:D409:W
433 void DISPLAY::reset_vramaccess(void)
434 {
435         vram_accessflag = false;
436 }
437
438 //SUB:D40A:R
439 uint8_t DISPLAY::reset_subbusy(void)
440 {
441         sub_busy = false;
442         return 0xff;
443 }
444
445 //SUB:D40A:W
446 void DISPLAY::set_subbusy(void)
447 {
448         sub_busy = true;
449 }
450
451
452 #if defined(_FM77AV_VARIANTS)
453 // D410
454 void DISPLAY::alu_write_cmdreg(uint32_t val)
455 {
456         alu->write_data8(ALU_CMDREG, val);
457         if((val & 0x80) != 0) {
458                 use_alu = true;
459         } else {
460                 use_alu = false;
461         }
462 }
463
464 // D411
465 void DISPLAY::alu_write_logical_color(uint8_t val)
466 {
467         uint32_t data = (uint32_t)val;
468         alu->write_data8(ALU_LOGICAL_COLOR, data);
469 }
470
471 // D412
472 void DISPLAY::alu_write_mask_reg(uint8_t val)
473 {
474         uint32_t data = (uint32_t)val;
475         alu->write_data8(ALU_WRITE_MASKREG, data);
476 }
477
478 // D413 - D41A
479 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
480 {
481         uint32_t data = (uint32_t)val;
482         addr = addr & 7;
483         alu->write_data8(ALU_CMPDATA_REG + addr, data);
484 }
485
486 // D41B
487 void DISPLAY::alu_write_disable_reg(uint8_t val)
488 {
489         uint32_t data = (uint32_t)val;
490         alu->write_data8(ALU_BANK_DISABLE, data);
491 }
492
493 // D41C - D41F
494 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
495 {
496         uint32_t data = (uint32_t)val;
497         switch(addr & 3) {
498                 case 0: // $D41C
499                         alu->write_data8(ALU_TILEPAINT_B, data);
500                         break;
501                 case 1: // $D41D
502                         alu->write_data8(ALU_TILEPAINT_R, data);
503                         break;
504                 case 2: // $D41E
505                         alu->write_data8(ALU_TILEPAINT_G, data);
506                         break;
507                 case 3: // xxxx
508                         //alu->write_data8(ALU_TILEPAINT_L, 0xff);
509                         break;
510         }
511 }
512
513 // D420
514 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
515 {
516         alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
517 }
518  
519 // D421
520 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
521 {
522         alu->write_data8(ALU_OFFSET_REG_LO, val);
523 }
524
525 // D422
526 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
527 {
528         alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
529 }
530
531 // D423
532 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
533 {
534         alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
535 }
536
537 // D424-D42B
538 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
539 {
540         uint32_t data = (uint32_t)val;
541         switch(addr) {
542                 case 0:  
543                         alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03); 
544                         break;
545                 case 1:  
546                         alu->write_data8(ALU_LINEPOS_START_X_LOW, data); 
547                         break;
548                 case 2:  
549                         alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01); 
550                         break;
551                 case 3:  
552                         alu->write_data8(ALU_LINEPOS_START_Y_LOW, data); 
553                         break;
554                 case 4:  
555                         alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03); 
556                         break;
557                 case 5:  
558                         alu->write_data8(ALU_LINEPOS_END_X_LOW, data); 
559                         break;
560                 case 6:  
561                         alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01); 
562                         break;
563                 case 7:  
564                         alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
565                         break;
566         }
567 }
568
569 //SUB:D430:R
570 uint8_t DISPLAY::get_miscreg(void)
571 {
572         uint8_t ret;
573
574         ret = 0x6a;
575         if(!hblank) ret |= 0x80;
576         if(vsync) ret |= 0x04;
577         if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
578         if(power_on_reset) ret |= 0x01;
579         return ret;
580 }
581
582 //SUB:D430:W
583 void DISPLAY::set_miscreg(uint8_t val)
584 {
585         int old_display_page = display_page;
586
587         nmi_enable = ((val & 0x80) == 0) ? true : false;
588         if(!nmi_enable) do_nmi(false);
589
590         if((val & 0x40) == 0) {
591                 display_page = 0;
592         } else {
593                 display_page = 1;
594         }
595         if(display_page != old_display_page) {
596                         vram_wrote = true;
597         }
598         active_page = ((val & 0x20) == 0) ? 0 : 1;
599         if((val & 0x04) == 0) {
600                 offset_77av = false;
601         } else {
602                 offset_77av = true;
603         }
604         cgrom_bank = val & 0x03;
605 }
606
607 // Main: FD13
608 void DISPLAY::set_monitor_bank(uint8_t var)
609 {
610 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
611         if((var & 0x04) != 0){
612                 monitor_ram = true;
613         } else {
614                 monitor_ram = false;
615         }
616 # endif
617         subrom_bank = var & 0x03;
618         vram_wrote = true;
619         if(!halt_flag) {
620                 subcpu_resetreq = false;
621                 power_on_reset = true;
622                 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
623                 reset_cpuonly();
624                 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
625                 subcpu->reset();
626                 do_firq(!firq_mask && key_firq_req);
627         } else {
628                 subcpu_resetreq = true;
629         }
630 }
631
632
633 // FD30
634 void DISPLAY::set_apalette_index_hi(uint8_t val)
635 {
636         apalette_index.b.h = val & 0x0f;
637 }
638
639 // FD31
640 void DISPLAY::set_apalette_index_lo(uint8_t val)
641 {
642         apalette_index.b.l = val;
643 }
644
645 void DISPLAY::calc_apalette(uint16_t idx)
646 {
647         uint8_t r, g, b;
648         idx = idx & 4095;
649         g = analog_palette_g[idx];
650         r = analog_palette_r[idx];
651         b = analog_palette_b[idx];
652         if(g != 0) g |= 0x0f; 
653         if(r != 0) r |= 0x0f; 
654         if(b != 0) b |= 0x0f; 
655         analog_palette_pixel[idx] = RGB_COLOR(r, g, b);
656 }
657
658 // FD32
659 void DISPLAY::set_apalette_b(uint8_t val)
660 {
661         uint16_t index;
662         uint8_t tmp;
663         index = apalette_index.w.l;
664         tmp = (val & 0x0f) << 4;
665         if(analog_palette_b[index] != tmp) {
666                 analog_palette_b[index] = tmp;
667                 calc_apalette(index);
668                 palette_changed = true;
669         }
670 }
671
672 // FD33
673 void DISPLAY::set_apalette_r(uint8_t val)
674 {
675         uint16_t index;
676         uint8_t tmp;
677         index = apalette_index.w.l;
678         tmp = (val & 0x0f) << 4;
679         if(analog_palette_r[index] != tmp) {
680                 analog_palette_r[index] = tmp;
681                 calc_apalette(index);
682                 palette_changed = true;
683         }
684 }
685
686 // FD34
687 void DISPLAY::set_apalette_g(uint8_t val)
688 {
689         uint16_t index;
690         uint8_t tmp;
691         index = apalette_index.w.l;
692         tmp = (val & 0x0f) << 4;
693         if(analog_palette_g[index] != tmp) {
694                 analog_palette_g[index] = tmp;
695                 calc_apalette(index);
696                 palette_changed = true;
697         }
698 }
699
700 #endif // _FM77AV_VARIANTS
701
702
703 void DISPLAY::copy_vram_blank_area(void)
704 {
705 }
706
707
708 void DISPLAY::copy_vram_per_line(void)
709 {
710         uint32_t src_offset;
711         uint32_t yoff_d1;
712         uint32_t yoff_d2;
713         uint32_t yoff_d;
714         uint32_t poff = 0;
715         uint32_t src_base;
716         int pages = 1;
717         uint32_t src_offset_d1;
718         uint32_t src_offset_d2;
719         uint32_t src_offset_d;
720         uint32_t bytes_d1;
721         uint32_t bytes_d2;
722         uint32_t bytes_d;
723         int i, j, k;
724         //int dline = (int)displine - 1;
725         int dline = (int)displine;
726
727         if(dline < 0) return;
728         if(display_mode == DISPLAY_MODE_8_400L) {
729                 if(dline >= 400) return;
730         } else {
731                 if(dline >= 200) return;
732         }
733 #if defined(_FM77AV_VARIANTS)
734         yoff_d1 = offset_point;
735         yoff_d2 = offset_point_bank1;
736         if(display_mode == DISPLAY_MODE_4096) {
737                 src_offset = dline * 40;
738 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
739                 pages = 2;
740 #endif
741                 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
742                 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
743                 for(k = 0; k < pages; k++) {
744                         for(i = 0; i < 3; i++) {
745                                 for(j = 0; j < 2; j++) {
746                                         src_base = i * 0x4000 + j * 0x2000;
747                                         if(bytes_d1 < 40) {
748                                                 memcpy(&gvram_shadow[src_offset + src_base + poff],
749                                                            &gvram[((src_offset + yoff_d1) & 0x1fff) + src_base + poff],
750                                                            bytes_d1);
751                                                 memcpy(&gvram_shadow[src_offset + bytes_d1 + src_base + poff],
752                                                            &gvram[src_base + poff],
753                                                            40 - bytes_d1);
754                                         } else {
755                                                 memcpy(&gvram_shadow[src_offset + src_base + poff],
756                                                            &gvram[((src_offset + yoff_d1) & 0x1fff) + src_base + poff],
757                                                            40);
758                                         }
759                                         src_base = i * 0x4000 + j * 0x2000 + 0xc000;
760                                         if(bytes_d2 < 40) {
761                                                 memcpy(&gvram_shadow[src_offset + src_base + poff],
762                                                            &gvram[((src_offset + yoff_d2) & 0x1fff) + src_base + poff],
763                                                            bytes_d2);
764                                                 memcpy(&gvram_shadow[src_offset + bytes_d2 + src_base + poff],
765                                                            &gvram[src_base + poff],
766                                                            40 - bytes_d2);
767                                         } else {
768                                                 memcpy(&gvram_shadow[src_offset + src_base + poff],
769                                                            &gvram[((src_offset + yoff_d2) & 0x1fff) + src_base + poff],
770                                                            40);
771                                         }
772                                 }
773                         }
774                         poff += 0x18000;
775                 }
776                 vram_draw_table[dline] = true;
777                 vram_wrote_table[dline] = false;
778         }
779 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
780         else if(display_mode == DISPLAY_MODE_256k) {
781                 src_offset = dline * 40;
782                 
783 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
784                 pages = 4;
785 #elif defined(_FM77AV40)
786                 pages = 3;
787 #else
788                 pages = 0;
789 #endif
790                 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
791                 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
792                 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
793                 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
794                 for(k = 0; k < pages; k++) {
795                         for(i = 0; i < 3; i++) {
796                                 for(j = 0; j < 2; j++) {
797                                         if((k & 1) == 0) {
798                                                 src_base = i * 0x4000 + j * 0x2000 + k *  0xc000;
799                                                 src_offset_d = src_offset_d1;
800                                                 bytes_d = bytes_d1;
801                                         } else {
802                                                 src_base = i * 0x4000 + j * 0x2000 + k *  0xc000;
803                                                 src_offset_d = src_offset_d2;
804                                                 bytes_d = bytes_d2;
805                                         }                                               
806                                         if(bytes_d < 40) {
807                                                 memcpy(&gvram_shadow[src_offset + src_base],
808                                                            &gvram[src_offset_d + src_base],
809                                                            bytes_d);
810                                                 memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
811                                                            &gvram[src_base],
812                                                            40 - bytes_d);
813                                         } else {
814                                                 memcpy(&gvram_shadow[src_offset + src_base],
815                                                            &gvram[src_offset_d + src_base],
816                                                            40);
817                                         }
818                                 }
819                         }
820                 }
821                 vram_draw_table[dline] = true;
822                 vram_wrote_table[dline] = false;
823         }
824         else if(display_mode == DISPLAY_MODE_8_400L) {
825                 src_offset = dline * 80;
826 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
827                 pages = 2;
828 # elif defined(_FM77AV40)
829                 pages = 1;
830 #endif
831                 if(display_page_bak == 1) { // Is this dirty?
832                         yoff_d = yoff_d2;
833                 } else {
834                         yoff_d = yoff_d1;
835                 }
836                 yoff_d = (yoff_d << 1) & 0x7fff;
837                 src_offset_d = (src_offset + yoff_d) & 0x7fff;
838                 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
839                 for(i = 0; i < pages; i++) {
840                         for(j = 0; j < 3; j++) {
841                                 src_base = i * 0x18000 + j * 0x8000;
842                                 if(bytes_d < 80) {
843                                         memcpy(&gvram_shadow[src_offset + src_base],
844                                                    &gvram[src_offset_d + src_base],
845                                                    bytes_d);
846                                         memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
847                                                    &gvram[src_base],
848                                                    80 - bytes_d);
849                                 } else {
850                                         memcpy(&gvram_shadow[src_offset + src_base + poff],
851                                                    &gvram[src_offset_d + src_base],
852                                                    80);
853                                 }
854                         }
855                 }
856                 vram_draw_table[dline] = true;
857                 vram_wrote_table[dline] = false;
858         }
859 #endif  
860         else { // 200line
861                 src_offset = dline * 80;
862 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
863                 pages = 4;
864 #elif defined(_FM77AV40)
865                 pages = 3;
866 #elif defined(_FM77AV_VARIANTS)
867                 pages = 2;
868 #else
869                 pages = 1;
870 #endif
871                 poff = 0;
872                 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
873                 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
874                 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
875                 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
876                 for(i = 0; i < pages; i++) {
877                         for(j = 0; j < 3; j++) {
878                                 src_base = j * 0x4000;
879                                 if((i & 1) == 0) {
880                                         src_offset_d = src_offset_d1;
881                                         bytes_d = bytes_d1;
882                                 } else {
883                                         src_offset_d = src_offset_d2;
884                                         bytes_d = bytes_d2;
885                                 }
886                                 if(bytes_d < 80) {
887                                         memcpy(&gvram_shadow[src_offset + src_base + poff],
888                                                    &gvram[src_offset_d + src_base + poff],
889                                                    bytes_d);
890                                         memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
891                                                    &gvram[src_base + poff],
892                                                    80 - bytes_d);
893                                 } else {
894                                         memcpy(&gvram_shadow[src_offset + src_base + poff],
895                                                    &gvram[src_offset_d + src_base + poff],
896                                                    80);
897                                 }
898                         }
899                         poff += 0xc000;
900                 }
901                 vram_draw_table[dline] = true;
902                 vram_wrote_table[dline] = false;
903         }
904 #else // FM-8/7/77
905         { // 200line
906                 src_offset = dline * 80;
907                 pages = 1;
908                 poff = 0;
909                 yoff_d = offset_point;
910                 src_offset_d = (src_offset + yoff_d) & 0x3fff;
911                 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
912                 for(j = 0; j < 3; j++) {
913                         src_base = j * 0x4000;
914                         if(bytes_d < 80) {
915                                 memcpy(&gvram_shadow[src_offset + src_base + poff],
916                                            &gvram[src_offset_d + src_base + poff],
917                                            bytes_d);
918                                 memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
919                                            &gvram[src_base + poff],
920                                            80 - bytes_d);
921                         } else {
922                                 memcpy(&gvram_shadow[src_offset + src_base + poff],
923                                            &gvram[src_offset_d + src_base + poff],
924                                            80);
925                         }
926                 }
927                 vram_draw_table[dline] = true;
928                 vram_wrote_table[dline] = false;
929         }
930
931 #endif
932 }
933
934 void DISPLAY::copy_vram_all()
935 {
936 #if defined(_FM77AV_VARIANTS)   
937         uint32_t yoff_d1 = offset_point;
938         uint32_t yoff_d2 = offset_point_bank1;
939         uint32_t src_offset_1, src_offset_2;
940         uint32_t poff = 0;
941         if(display_mode == DISPLAY_MODE_4096) {
942 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
943                 int pages = 2;
944 #else
945                 int pages = 1;
946 #endif
947                 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
948                 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
949                 for(int k = 0; k < pages; k++) {
950                         for(int i = 0; i < 3; i++) {
951                                 for(int j = 0; j < 2; j++) {
952                                         src_offset_1 = i * 0x4000 + j * 0x2000;
953                                         src_offset_2 = src_offset_1 + 0xc000;
954                                         memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
955                                         memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
956                                         memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
957                                         memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
958                                 }
959                         }
960                         poff += 0x18000;
961                 }
962         }
963 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
964         else if(display_mode == DISPLAY_MODE_256k) {
965                 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
966                 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
967                 for(int i = 0; i < 3; i++) {
968                         for(int j = 0; j < 2; j++) {
969                                 src_offset_1 = i * 0x4000 + j * 0x2000;
970                                 src_offset_2 = src_offset_1 + 0xc000;
971                                 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
972                                 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
973                                 memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
974                                 memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
975                         }
976                 }
977                 poff += 0x18000;
978                 for(int i = 0; i < 3; i++) {
979                         for(int j = 0; j < 2; j++) {
980                                 src_offset_1 = i * 0x4000 + j * 0x2000;
981                                 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
982                                 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
983                         }
984                 }
985         } else if(display_mode == DISPLAY_MODE_8_400L) {
986 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
987                 int pages = 2;
988 #else
989                 int pages = 1;
990 #endif
991                 uint32_t yoff_d;
992                 uint32_t bytes_d;
993                 
994                 if(display_page_bak == 1) { // Is this dirty?
995                         yoff_d = yoff_d2;
996                 } else {
997                         yoff_d = yoff_d1;
998                 }
999                 yoff_d = (yoff_d << 1) & 0x7fff;
1000                 bytes_d = 0x8000 - yoff_d;
1001                 for(int k = 0; k < pages; k++) {
1002                         for(int i = 0; i < 3; i++) {
1003                                 src_offset_1 = i * 0x8000;
1004                                 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + yoff_d + poff], bytes_d);
1005                                 memcpy(&gvram_shadow[src_offset_1 + bytes_d + poff], &gvram[src_offset_1 + poff], 0x8000 - bytes_d);
1006                         }
1007                         poff += 0x18000;
1008                 }
1009         }
1010 #endif  
1011     else { // 200line
1012 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1013                 int pages = 4;
1014 #elif defined(_FM77AV40)
1015                 int pages = 3;
1016 #else
1017                 int pages = 2;
1018 #endif
1019                 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1020                 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1021                 uint32_t yoff_d, bytes_d;
1022                 for(int k = 0; k < pages; k++) {
1023                         yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1024                         bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1025                         for(int j = 0; j < 3; j++) {
1026                                 src_offset_1 = k * 0xc000 + j * 0x4000;
1027                                 memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1028                                 memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1029                         }
1030                 }
1031         }
1032 #else // FM-8/7/77
1033     { // 200line
1034                 uint32_t yoff_d = offset_point & 0x3fff;
1035                 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1036                 uint32_t src_offset_1;
1037                 for(int j = 0; j < 3; j++) {
1038                         src_offset_1 = j * 0x4000;
1039                         memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1040                         memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1041                 }
1042         }
1043 #endif
1044 }
1045                 
1046 // Timing values from XM7 . Thanks Ryu.
1047 void DISPLAY::event_callback(int event_id, int err)
1048 {
1049         double usec;
1050         bool f;
1051         switch(event_id) {
1052                 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1053 #if defined(_FM77AV_VARIANTS)
1054                         if(nmi_enable) {
1055                                 do_nmi(true);
1056                         } else {
1057                                 //do_nmi(false);
1058                         }
1059 #else
1060                         do_nmi(true);
1061 #endif
1062                         break;
1063                 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1064                         do_nmi(false);
1065                         break;
1066 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1067                 case EVENT_FM7SUB_HDISP:
1068                         hblank = false;
1069                         f = false;
1070                         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1071                         if(display_mode == DISPLAY_MODE_8_400L) {
1072                                 usec = 30.0;
1073                                 if(displine < 400) f = true;
1074                         } else {
1075                                 usec = 39.5;
1076                                 if(displine < 200) f = true;
1077                         }
1078                         if(f) {
1079                                 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1080                                         if(vram_wrote_table[displine] || vram_wrote) copy_vram_per_line();
1081                                 }
1082                                 register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hblank_event_id); // NEXT CYCLE_
1083                                 vsync = false;
1084                                 vblank = false;
1085                                 enter_display();
1086                         }
1087                         f = false;
1088                         break;
1089                 case EVENT_FM7SUB_HBLANK:
1090                         hblank = true;
1091                         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1092                         f = false;
1093                         if(display_mode == DISPLAY_MODE_8_400L) {
1094                                 if((displine < 400)) f = true;
1095                         } else {
1096                                 if((displine < 200)) f = true;
1097                         }
1098                         if(f) {
1099                                 if(display_mode == DISPLAY_MODE_8_400L) {
1100                                         usec = 11.0;
1101                                 } else {
1102                                         usec = 24.0;
1103                                 }
1104                                 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1105                         }
1106                         displine++;
1107                         break;
1108                 case EVENT_FM7SUB_VSTART: // Call first.
1109                         vblank = true;
1110                         vsync = false;
1111                         hblank = false;
1112                         displine = 0;
1113                         display_page_bak = display_page;
1114                         
1115                         // Parameter from XM7/VM/display.c , thanks, Ryu.
1116                         mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1117                         mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
1118                         if(vblank_count != 0) {
1119                                 if(display_mode == DISPLAY_MODE_8_400L) {
1120                                         usec = (0.98 + 16.4) * 1000.0;
1121                                 } else {
1122                                         usec = (1.91 + 12.7) * 1000.0;
1123                                 }
1124                                 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1125
1126                                 if(display_mode == DISPLAY_MODE_8_400L) {
1127                                         usec = 930.0; // 939.0
1128                                 } else {
1129                                         usec = 1840.0; // 1846.5
1130                                 }
1131                                 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1132                                 vblank_count = 0;
1133                                 return;
1134                         } else {
1135                                 if(display_mode == DISPLAY_MODE_8_400L) {
1136                                         usec = 0.34 * 1000.0;
1137                                 } else {
1138                                         usec = 1.52 * 1000.0;
1139                                 }
1140                                 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1141                                 vblank_count++;
1142                                 //break;
1143                         }
1144                         break;
1145         case EVENT_FM7SUB_VSYNC:
1146                 vblank = true;
1147                 hblank = false;
1148                 vsync = true;
1149                 displine = 0;
1150                 if(display_mode == DISPLAY_MODE_8_400L) {
1151                         usec = 0.33 * 1000.0; 
1152                 } else {
1153                         usec = 0.51 * 1000.0;
1154                 }
1155                 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
1156                 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1157                 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1158                 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1159                         bool ff = false;
1160                         if(!vram_wrote) {
1161                                 int lines = 200;
1162                                 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1163                                 for(int yy = 0; yy < lines; yy++) {
1164                                         if(vram_wrote_table[yy]) {
1165                                                 vram_wrote_table[yy] = false;
1166                                                 ff = true;
1167                                         }
1168                                 }
1169                         } else {
1170                                 ff = true;
1171                         }
1172                         if(ff) {
1173                                 for(int yy = 0; yy < 400; yy++) vram_draw_table[yy] = true;
1174                                 copy_vram_all();
1175                                 vram_wrote_shadow = true;
1176                                 screen_update_flag = true;
1177                         }
1178                 } else {
1179                         if(vram_wrote) {
1180                                 for(int yy = 0; yy < 400; yy++) {
1181                                         if(!vram_draw_table[yy]) {
1182                                                 displine = yy;
1183                                                 copy_vram_per_line();
1184                                         }
1185                                 }
1186                                 displine = 0;
1187                         }
1188                         for(int yy = 0; yy < 400; yy++) {
1189                                 if(vram_draw_table[yy]) {
1190                                         vram_wrote_shadow = true;
1191                                         screen_update_flag = true;
1192                                         break;
1193                                 }
1194                         }
1195                 }
1196                 vram_wrote = false;
1197                 break;
1198 #endif                  
1199         case EVENT_FM7SUB_CLR_BUSY:
1200                 set_subbusy();
1201                 break;
1202         case EVENT_FM7SUB_CLR_CRTFLAG:
1203                 reset_crtflag();
1204                 break;
1205         }
1206 }
1207
1208 void DISPLAY::event_frame()
1209 {
1210 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1211         int yy;
1212         bool f = false;
1213
1214         if(vram_wrote) {
1215                 for(yy = 0; yy < 400; yy++) {
1216                         if(!vram_draw_table[yy]) {
1217                                 displine = yy;
1218                                 copy_vram_per_line();
1219                         }
1220                 }
1221         }
1222         {
1223                 for(yy = 0; yy < 400; yy++) {
1224                         if(vram_draw_table[yy]) {
1225                                 f = true;
1226                                 break;
1227                         }
1228                 }
1229                 if(f) {
1230                         screen_update_flag = true;
1231                         vram_wrote_shadow = true;
1232                 }
1233         }
1234         vram_wrote = false;
1235         displine = 0;
1236         enter_display();
1237 #endif  
1238 }
1239
1240 void DISPLAY::event_vline(int v, int clock)
1241 {
1242 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1243 //      if((v >= 200) || (v < 0)) return;
1244         displine = v;
1245         if(vram_wrote_table[displine] || vram_wrote) {
1246                 copy_vram_per_line();
1247         }               
1248         enter_display();
1249 #endif  
1250 }
1251
1252
1253 uint32_t DISPLAY::read_signal(int id)
1254 {
1255         uint32_t retval = 0;
1256         switch(id) {
1257                 case SIG_FM7_SUB_HALT:
1258                 case SIG_DISPLAY_HALT:
1259                         retval = (halt_flag) ? 0xffffffff : 0;
1260                         break;
1261                 case SIG_DISPLAY_BUSY:
1262                         retval =  (sub_busy) ? 0x80 : 0;
1263                         break;
1264                 case SIG_DISPLAY_MULTIPAGE:
1265                         retval =  multimode_accessmask;
1266                         break;
1267                 case SIG_DISPLAY_PLANES:
1268                         retval = 3;
1269                         break;
1270 #if defined(_FM77AV_VARIANTS)
1271                 case SIG_DISPLAY_VSYNC:
1272                         retval = (vsync) ? 0x01 : 0x00;
1273                         break;
1274                 case SIG_DISPLAY_DISPLAY:
1275                         retval = (!hblank) ? 0x02: 0x00;
1276                         break;
1277                 case SIG_FM7_SUB_BANK: // Main: FD13
1278                         retval = subrom_bank & 0x03;
1279 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1280                         if(monitor_ram) retval |= 0x04;
1281 #endif
1282                         break;
1283 #endif                  
1284 #if defined(_FM77AV_VARIANTS)
1285                 case SIG_DISPLAY_MODE320:
1286                         retval = (mode320) ? 0x40: 0x00;
1287                         break;
1288 #endif
1289                 case SIG_DISPLAY_Y_HEIGHT:
1290 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1291                         retval = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1292 #else
1293                         retval = 200;
1294 #endif            
1295                         break;
1296                 case SIG_DISPLAY_X_WIDTH:
1297 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1298                         retval = (mode320 || mode256k) ? 320 : 640;
1299 #elif defined(_FM77AV_VARIANTS)
1300                         retval = (mode320) ? 320 : 640;
1301 #else
1302                         retval = 640;
1303 #endif            
1304                         break;
1305                 default:
1306                         break;
1307         }
1308         return retval;
1309 }
1310
1311 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1312 {
1313         bool flag = ((data & mask) != 0);
1314         int y;
1315         switch(id) {
1316                 case SIG_FM7_SUB_HALT:
1317                         if(flag) {
1318                                 sub_busy = true;
1319                         }
1320                         halt_flag = flag;
1321                         //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1322                         break;
1323                 case SIG_DISPLAY_HALT:
1324                         if(flag) {
1325                                 halt_subsystem();
1326                         } else {
1327                                 restart_subsystem();
1328                         }
1329                         break;
1330                 case SIG_FM7_SUB_CANCEL:
1331                         if(flag) {
1332                                 cancel_request = true;
1333                                 do_irq(true);
1334                         }
1335                         break;
1336                 case SIG_DISPLAY_CLOCK:
1337                         clock_fast = flag;
1338                         enter_display();
1339                         break;
1340 #if defined(_FM77AV_VARIANTS)
1341                 case SIG_FM7_SUB_BANK: // Main: FD13
1342                         set_monitor_bank(data & 0xff);
1343                         break;
1344 #endif                  
1345                 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1346 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1347                         //printf("Wrote $FD04: %02x\n", data);
1348                         {
1349                                 int oldmode = display_mode;
1350                                 int mode;
1351                                 kanjisub = ((data & 0x20) == 0) ? true : false;
1352                                 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1353                                 mode400line = ((data & 0x08) == 0) ? true : false;
1354                                 ram_protect = ((data & 0x04) == 0) ? true : false;
1355                                 if(mode400line && !mode320) {
1356                                         display_mode = DISPLAY_MODE_8_400L;
1357                                 } else if(mode256k) {
1358                                         display_mode = DISPLAY_MODE_256k;
1359                                 } else {
1360                                         display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1361                                 }
1362                                 if(oldmode != display_mode) {
1363                                         scrntype_t *pp;
1364                                         if(mode320 || mode256k) {
1365                                                 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1366                                                 for(y = 0; y < 200; y++) {
1367                                                         pp = emu->get_screen_buffer(y);
1368                                                         if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1369                                                 }
1370                                         } else if(display_mode == DISPLAY_MODE_8_400L) {
1371                                                 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1372                                                 for(y = 0; y < 400; y++) {
1373                                                         pp = emu->get_screen_buffer(y);
1374                                                         if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1375                                                 }
1376                                         } else {
1377                                                 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1378                                                 for(y = 0; y < 200; y++) {
1379                                                         pp = emu->get_screen_buffer(y);
1380                                                         if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1381                                                 }
1382                                         }
1383                                         vram_wrote = true;
1384                                         alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 :  80, 0xffff);
1385                                         alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1386                                         alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1387                                         frame_skip_count = 3;
1388                                 }
1389                         }
1390 #elif defined(_FM77_VARIANTS)
1391                         {
1392                                 int oldmode = display_mode;
1393                                 kanjisub = ((data & 0x20) == 0) ? true : false;
1394 # if defined(_FM77L4)                           
1395                                 stat_400linecard = ((data & 0x20) != 0) ? true : false;
1396                                 mode400line = ((data & 0x08) != 0) ? false : true;
1397                                 if(mode400line && stat_400linecard) {
1398                                         display_mode = DISPLAY_MODE_8_400L_TEXT;
1399                                 } else if(stat_400linecard) {
1400                                         display_mode = DISPLAY_MODE_8_200L_TEXT;
1401                                 } else {
1402                                         display_mode = DISPLAY_MODE_8_200L;
1403                                 }
1404 # endif                         
1405                         }                       
1406 #endif
1407                         break;
1408 #if defined(_FM77AV_VARIANTS)
1409                 case SIG_DISPLAY_MODE320: // FD12 bit 6
1410 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1411                         {
1412                                 //printf("Wrote $FD12: %02x\n", data);
1413                                 int oldmode = display_mode;
1414                                 mode320 = flag;
1415                                 if(!mode320 && !mode256k) {
1416                                         //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
1417                                         display_mode = DISPLAY_MODE_8_200L;
1418                                 } else {
1419                                         display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
1420                                 }
1421                                 if(oldmode != display_mode) {
1422                                         scrntype_t *pp;
1423                                         if(mode320 || mode256k) {
1424                                                 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1425                                                 for(y = 0; y < 200; y++) {
1426                                                         pp = emu->get_screen_buffer(y);
1427                                                         if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1428                                                 }
1429                                         } else { // 200 lines, 8 colors.
1430                                                 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1431                                                 for(y = 0; y < 200; y++) {
1432                                                         pp = emu->get_screen_buffer(y);
1433                                                         if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1434                                                 }
1435                                         }
1436                                         vram_wrote = true;
1437                                         alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 :  80, 0xffff);
1438                                         alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1439                                         alu->write_signal(SIG_ALU_400LINE, 0x00, 0xff);
1440                                         //frame_skip_count = 3;
1441                                 }
1442                         }
1443 # else
1444                         mode320 = flag;
1445                         {
1446                 
1447                                 if(mode320) {
1448                                         emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1449                                         for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
1450                                 } else {
1451                                         emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1452                                         for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1453                                 }
1454                         }
1455                         display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1456                         alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 :  80, 0xffff);
1457                         alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1458                         alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1459                         vram_wrote = true;
1460 # endif
1461 #endif                  
1462                         break;
1463                 case SIG_DISPLAY_MULTIPAGE:
1464                         set_multimode(data);
1465                         break;
1466                 case SIG_FM7_SUB_KEY_MASK:
1467                         if(firq_mask == flag) {
1468                                 do_firq(!flag && key_firq_req);
1469                         }
1470                         firq_mask = !flag;
1471                         break;
1472                 case SIG_FM7_SUB_KEY_FIRQ:
1473                         do_firq(flag & !(firq_mask));
1474                         key_firq_req = flag;
1475                         break;
1476                 case SIG_FM7_SUB_USE_CLR:
1477                         if(flag) {
1478                                 clr_count = data & 0x03;
1479                         } else {
1480                                 clr_count = 0;
1481                         }
1482                         break;
1483                 default:
1484                         break;
1485         }
1486 }
1487    
1488 /*
1489  * Vram accessing functions moved to vram.cpp .
1490  */
1491
1492 uint8_t DISPLAY::read_mmio(uint32_t addr)
1493 {
1494         uint32_t retval = 0xff;
1495         uint32_t raddr; 
1496         if(addr < 0xd400) return 0xff;
1497         
1498 #if !defined(_FM77AV_VARIANTS)
1499         raddr = (addr - 0xd400) & 0x000f;
1500 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1501         raddr = (addr - 0xd400) & 0x003f;
1502 #else // FM77AV40EX || FM77AV40SX
1503         raddr = (addr - 0xd400) & 0x00ff;
1504 #endif
1505         switch(raddr) {
1506                 case 0x00: // Read keyboard
1507                         retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1508                         break;
1509                 case 0x01: // Read keyboard
1510                         retval = keyboard->read_data8(0x01) & 0xff;
1511                         break;
1512                 case 0x02: // Acknowledge
1513                         acknowledge_irq();
1514                         break;
1515                 case 0x03:
1516                         beep();
1517                         break;
1518                 case 0x04:
1519                         attention_irq();
1520                         break;
1521 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1522      defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1523                 case 0x06:
1524                         if(!kanjisub) return 0xff;
1525 # if !defined(_FM77_VARIANTS)
1526                         if(kanji_level2) {
1527                                 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1528                         }
1529 # endif
1530                         if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1531                         break;
1532                 case 0x07:
1533                         if(!kanjisub) return 0xff;
1534 # if !defined(_FM77_VARIANTS)
1535                         if(kanji_level2) {
1536                                 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1537                         }
1538 # endif
1539                         if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1540                         break;
1541 #endif
1542                 case 0x08:
1543                         set_crtflag();
1544                         break;
1545                 case 0x09:
1546                         retval = set_vramaccess();
1547                         break;
1548                 case 0x0a:
1549                         reset_subbusy();
1550                         break;
1551                 case 0x0d:
1552                         keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1553                         break;
1554 #if defined(_FM77AV_VARIANTS)
1555                 // ALU
1556                 case 0x10:
1557                         retval = alu->read_data8(ALU_CMDREG);
1558                         break;
1559                 case 0x11:
1560                         retval = alu->read_data8(ALU_LOGICAL_COLOR);
1561                         break;
1562                 case 0x12:
1563                         retval = alu->read_data8(ALU_WRITE_MASKREG);
1564                         break;
1565                 case 0x13:
1566                         retval = alu->read_data8(ALU_CMP_STATUS_REG);
1567                         break;
1568                 case 0x1b:
1569                         retval = alu->read_data8(ALU_BANK_DISABLE);
1570                         break;
1571 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1572                 case 0x2f: // VRAM BANK
1573                         retval = 0xfc | (vram_bank & 0x03);
1574                         break;
1575 # endif                 
1576                 // MISC
1577                 case 0x30:
1578                         retval = get_miscreg();
1579                         break;
1580                 // KEY ENCODER.
1581                 case 0x31:
1582                         retval = keyboard->read_data8(0x31);
1583                         break;
1584                 case 0x32:
1585                         retval = keyboard->read_data8(0x32);
1586                         break;
1587 #endif                          
1588                 default:
1589                         break;
1590         }
1591         return (uint8_t)retval;
1592 }
1593
1594 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
1595 {
1596         uint32_t offset;
1597         uint32_t page_offset = 0;
1598         uint32_t page_mask = 0x3fff;
1599         uint32_t color = (addr >> 14) & 0x03;
1600         uint32_t pagemod;
1601         
1602 #if defined(_FM77AV_VARIANTS)
1603         if (active_page != 0) {
1604                 offset = offset_point_bank1;
1605         } else {
1606                 offset = offset_point;
1607         }
1608 #else
1609         offset = offset_point;
1610 #endif
1611                 
1612 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1613 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1614                 if(vram_active_block != 0) page_offset = 0x18000;
1615 # endif         
1616                 if(display_mode == DISPLAY_MODE_8_400L) {
1617                         if(addr >= 0x8000) return 0xff;
1618                         color = vram_bank & 0x03;
1619                         if(color > 2) color = 0;
1620                         offset <<= 1;
1621                         pagemod = 0x8000 * color;
1622                         return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1623                 } else {
1624                         if(mode256k) {
1625 #if defined(_FM77AV40)
1626                                 if(vram_bank < 3) {
1627                                         page_offset = 0xc000 * (vram_bank & 0x03);
1628                                 } else {
1629                                         page_offset = 0; // right?
1630                                 }
1631 #else                   
1632                                 page_offset = 0xc000 * (vram_bank & 0x03);
1633 #endif                  
1634                                 page_mask = 0x1fff;
1635                                 pagemod = addr & 0xe000;
1636                         } else {
1637                                 if(mode320) {
1638                                         page_mask = 0x1fff;
1639                                         pagemod = addr & 0xe000;
1640                                 } else {
1641                                         pagemod = addr & 0xc000;
1642                                 }
1643                                 if(active_page != 0) {
1644                                         page_offset += 0xc000;
1645                                 }
1646                         }                               
1647                         return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1648                 }
1649 #elif defined(_FM77AV_VARIANTS)
1650                 {               
1651                         if(active_page != 0) {
1652                                 page_offset += 0xc000;
1653                         }
1654                         if(mode320) {
1655                                 page_mask = 0x1fff;
1656                                 pagemod = addr & 0xe000;
1657                         } else {
1658                                 pagemod = addr & 0xc000;
1659                         }
1660                         return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1661                 }
1662 #elif defined(_FM77L4) //_FM77L4
1663                 {
1664                         if(display_mode == DISPLAY_MODE_8_400L) {
1665                                 return (uint32_t)read_vram_l4_400l(addr, offset);
1666                         } else {
1667                                 pagemod = addr & 0xc000;
1668                                 return gvram[((addr + offset) & 0x3fff) | pagemod];
1669                         }
1670                         return 0xff;
1671                 }
1672 #else // Others (77/7/8)
1673                 pagemod = addr & 0xc000;
1674                 return gvram[((addr + offset) & 0x3fff) | pagemod];
1675 #endif
1676 }
1677
1678 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
1679 {
1680         uint32_t raddr = addr & 0xffff;
1681         uint32_t color;
1682         if(addr < 0xc000) {
1683 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1684                 if(display_mode == DISPLAY_MODE_8_400L) {
1685                         color = vram_bank & 0x03;
1686                         if(color > 2) color = 0;
1687                 } else
1688 # endif
1689                 {
1690                         color = (addr >> 14) & 0x03;
1691                 }
1692 #if !defined(_FM8)              
1693                 if((multimode_accessmask & (1 << color)) != 0) return;
1694 #endif          
1695                 return write_vram_data8(raddr, (uint8_t)data);
1696         } else {
1697                 return write_data8_main(raddr, (uint8_t)data);
1698         }
1699 }
1700
1701
1702 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
1703 {
1704         uint32_t offset;
1705         uint32_t page_offset = 0;
1706         uint32_t page_mask = 0x3fff;
1707         uint32_t color = (addr >> 14) & 0x03;
1708         uint32_t pagemod;
1709         uint8_t tdata;
1710         
1711 #if defined(_FM77AV_VARIANTS)
1712         if (active_page != 0) {
1713                 offset = offset_point_bank1;
1714         } else {
1715                 offset = offset_point;
1716         }
1717 #else
1718         offset = offset_point;
1719 #endif
1720
1721 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1722 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1723                 if(vram_active_block != 0) page_offset = 0x18000;
1724 # endif         
1725                 if(display_mode == DISPLAY_MODE_8_400L) {
1726                         if(addr >= 0x8000) {
1727                                 return;
1728                         }
1729                         color = vram_bank & 0x03;
1730                         if(color > 2) color = 0;
1731                         offset <<= 1;
1732                         pagemod = 0x8000 * color;
1733                         // Reduce data transfer.
1734                         tdata = gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];                    
1735                         if(tdata != data) {
1736                                 gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
1737                                 vram_wrote_table[(addr & 0x7fff) / 80] = true;
1738                         }
1739                 } else  if(display_mode == DISPLAY_MODE_256k) {
1740 #if defined(_FM77AV40)
1741                         if(vram_bank < 3) {
1742                                 page_offset = 0xc000 * (vram_bank & 0x03);
1743                         } else {
1744                                 page_offset = 0; // right?
1745                         }
1746 #else                   
1747                         page_offset = 0xc000 * (vram_bank & 0x03);
1748 #endif                  
1749                         page_mask = 0x1fff;
1750                         pagemod = addr & 0xe000;
1751                         tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1752                         if(tdata != data) {
1753                                 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1754                                 vram_wrote_table[(addr & page_mask) / 40] = true;
1755                         }
1756                         return;
1757                 } else if(display_mode == DISPLAY_MODE_4096) {
1758                         if(active_page != 0) {
1759                                 page_offset += 0xc000;
1760                         }
1761                         page_mask = 0x1fff;
1762                         pagemod = addr & 0xe000;
1763                         tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1764                         if(tdata != data) {
1765                                 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1766                                 vram_wrote_table[(addr & page_mask) / 40] = true;
1767                         }
1768                 } else { // 200line
1769                         if(active_page != 0) {
1770                                 page_offset += 0xc000;
1771                         }
1772                         page_mask = 0x3fff;
1773                         pagemod = addr & 0xc000;
1774                         tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1775                         if(tdata != data) {
1776                                 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1777                                 vram_wrote_table[(addr & page_mask) / 80] = true;
1778                         }
1779                 }                               
1780 #elif defined(_FM77AV_VARIANTS)
1781                 if(display_mode == DISPLAY_MODE_4096) {
1782                         if(active_page != 0) {
1783                                 page_offset = 0xc000;
1784                         }
1785                         page_mask = 0x1fff;
1786                         pagemod = addr & 0xe000;
1787                         tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1788                         if(tdata != data) {
1789                                 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1790                                 vram_wrote_table[(addr & page_mask) / 40] = true;
1791                         }
1792                 } else { // 200line
1793                         if(active_page != 0) {
1794                                 page_offset = 0xc000;
1795                         }
1796                         page_mask = 0x3fff;
1797                         pagemod = addr & 0xc000;
1798                         tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1799                         if(tdata != data) {
1800                                 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1801                                 vram_wrote_table[(addr & page_mask) / 80] = true;
1802                         }
1803                 }
1804 #elif defined(_FM77L4) //_FM77L4
1805                 {
1806                         if(display_mode == DISPLAY_MODE_8_400L) {
1807                                 write_vram_l4_400l(addr, data, offset);
1808                         } else {
1809                                 pagemod = addr & 0xc000;
1810                                 tdata = gvram[((addr + offset) & 0x3fff) | pagemod];
1811                                 if(data != tdata) {
1812                                         gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1813                                         vram_wrote_table[(addr & 0x3fff) / 80] = true;
1814                                 }
1815                         }
1816                 }
1817 #else // Others (77/7/8)
1818                 pagemod = addr & 0xc000;
1819                 tdata = gvram[((addr + offset) & 0x3fff) | pagemod];
1820                 if(tdata != data) {
1821                         gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1822                         vram_wrote_table[(addr & 0x3fff) / 80] = true;
1823                 }
1824 #endif
1825 }
1826
1827 uint32_t DISPLAY::read_data8_main(uint32_t addr)
1828 {
1829         uint32_t raddr;
1830         if(addr < 0xc000) return 0xff;
1831         if(addr < 0xd000) { 
1832                 raddr = addr - 0xc000;
1833 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1834                 if(monitor_ram) {
1835                         if(console_ram_bank >= 1) {
1836                                 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
1837                         }
1838                 }
1839 #endif
1840                 return console_ram[raddr];
1841         } else if(addr < 0xd380) {
1842                 raddr = addr - 0xd000;
1843                 return work_ram[raddr];
1844         } else if(addr < 0xd400) {
1845                 raddr = addr - 0xd380;
1846                 return shared_ram[raddr];
1847         } else  if(addr < 0xd800) {
1848 #if defined(_FM77AV_VARIANTS)
1849                 if(addr >= 0xd500) {
1850                         return submem_hidden[addr - 0xd500];
1851                 }
1852 #endif     
1853                 return read_mmio(addr);
1854         } else if(addr < 0x10000) {
1855 #if !defined(_FM77AV_VARIANTS)
1856                 return subsys_c[addr - 0xd800];
1857 #else
1858                 if(addr < 0xe000) {
1859 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1860                         if(monitor_ram) {
1861                                 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
1862                         }
1863 #endif          
1864                         return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
1865                 } else if(addr < 0x10000) {
1866 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1867                         if(monitor_ram) {
1868                                 return subsys_ram[addr - 0xe000];
1869                         }
1870 #endif          
1871                         switch(subrom_bank_using & 3) {
1872                         case 0: // SUBSYS_C
1873                                 return subsys_c[addr - 0xd800];
1874                                 break;
1875                         case 1:
1876                                 return subsys_a[addr - 0xe000];
1877                                 break;
1878                         case 2:
1879                                 return subsys_b[addr - 0xe000];
1880                                 break;
1881                         default:
1882                                 return subsys_cg[addr - 0xe000];
1883                                 break;
1884                         }
1885                 }
1886 #endif
1887         }
1888         return 0xff;
1889 }
1890
1891 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
1892 {
1893         uint32_t raddr = addr & 0xffff;
1894         uint32_t color;
1895         if(addr < 0xc000) {
1896 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1897                 if(display_mode == DISPLAY_MODE_8_400L) {
1898                         color = vram_bank & 0x03;
1899                         if(color > 2) color = 0;
1900                 } else
1901 # endif
1902                 {
1903                         color = (addr >> 14) & 0x03;
1904                 }
1905 # if !defined(_FM8)             
1906                 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1907 # endif         
1908                 return read_vram_data8(raddr);
1909         } else {
1910                 return read_data8_main(raddr);
1911         }
1912 }
1913
1914
1915 uint32_t DISPLAY::read_data8(uint32_t addr)
1916 {
1917         uint32_t raddr = addr;
1918         uint32_t offset;
1919         uint32_t color = (addr & 0x0c000) >> 14;
1920         if(addr < 0xc000) {
1921 #if defined(_FM77AV_VARIANTS)
1922                 if(use_alu) {
1923                         alu->read_data8(addr + ALU_WRITE_PROXY);
1924                 }
1925 #endif
1926 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1927                 if(display_mode == DISPLAY_MODE_8_400L) {
1928                         color = vram_bank & 0x03;
1929                         if(color > 2) color = 0;
1930                 } else {
1931                         color = (addr >> 14) & 0x03;
1932                 }
1933 # endif
1934 # if !defined(_FM8)             
1935                 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1936 # endif         
1937                 return read_vram_data8(addr);
1938         } else if(addr < 0x10000) {
1939                 return read_data8_main(addr);
1940         }
1941 #if !defined(_FM8)      
1942         else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
1943                 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
1944         }
1945 #endif  
1946 #if defined(_FM77AV_VARIANTS)
1947         // ACCESS VIA ALU.
1948         else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
1949                 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
1950 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)         
1951                 if(display_mode == DISPLAY_MODE_8_400L) {
1952                         uint32_t page_offset = 0;
1953 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1954                         if(vram_active_block != 0) page_offset = 0x18000;
1955 # endif         
1956                         color = (addr & 0x18000) >> 15;
1957                         if(color > 2) color = 0;
1958                         
1959                         if (active_page != 0) {
1960                                 offset = offset_point_bank1 << 1;
1961                         } else {
1962                                 offset = offset_point << 1;
1963                         }
1964                         if(color > 2) color = 0;
1965                         uint32_t pagemod = 0x8000 * color;
1966                         return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1967                 }
1968 # endif         
1969                 return read_vram_data8(addr);
1970         }
1971 #endif
1972         return 0xff;
1973 }       
1974
1975 /*
1976  * Vram accessing functions moved to vram.cpp .
1977  */
1978
1979 void DISPLAY::write_mmio(uint32_t addr, uint32_t data)
1980 {
1981         uint8_t rval = 0;
1982         pair_t tmpvar;
1983         if(addr < 0xd400) return;
1984         
1985 #if !defined(_FM77AV_VARIANTS)
1986         addr = (addr - 0xd400) & 0x000f;
1987 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1988         addr = (addr - 0xd400) & 0x003f;
1989 #else // FM77AV40EX || FM77AV40SX
1990         addr = (addr - 0xd400) & 0x00ff;
1991 #endif
1992         io_w_latch[addr] = (uint8_t)data;
1993         switch(addr) {
1994 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
1995                 // FM77 SPECIFIED
1996                 case 0x05:
1997                         set_cyclesteal((uint8_t)data);
1998                         break;
1999 #endif
2000 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2001      defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2002                 // KANJI
2003                 case 0x06:
2004                         if(!kanjisub) return;
2005                         kanjiaddr.w.h = 0x0000;
2006                         kanjiaddr.b.h = (uint8_t) data;
2007                         break;
2008                 case 0x07:
2009                         if(!kanjisub) return;
2010                         kanjiaddr.w.h = 0x0000;
2011                         kanjiaddr.b.l = (uint8_t)data;
2012                         break;
2013 #endif                  
2014                 // CRT OFF
2015                 case 0x08:
2016                         reset_crtflag();
2017                         break;
2018                 // VRAM ACCESS
2019                 case 0x09:
2020                         reset_vramaccess();
2021                         break;
2022                 // BUSY
2023                 case 0x0a:
2024                         if(clr_count <= 0) {
2025                                 set_subbusy();
2026                         } else { // Read once when using clr_foo() to set busy flag.
2027                                 double usec;
2028                                 if(clock_fast) {
2029                                         usec = (1000.0 * 1000.0) / 2000000.0;
2030                                 } else {
2031                                         usec = (1000.0 * 1000.0) / 999000.0;
2032                                 }
2033                                 if(!is_cyclesteal && vram_accessflag)  usec = usec * 3.0;
2034                                 usec = (double)clr_count * usec;
2035                                 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
2036                                 reset_subbusy();
2037                                 clr_count = 0;
2038                         }
2039                         break;
2040                 // LED
2041                 case 0x0d:
2042                         keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2043                         break;
2044                 // OFFSET
2045                 case 0x0e:
2046                 case 0x0f:
2047                         rval = (uint8_t)data;
2048                         if(offset_changed[active_page]) {
2049 #if defined(_FM77AV_VARIANTS)
2050                                 if(active_page != 0) {
2051                                         tmp_offset_point[active_page].d = offset_point_bank1;
2052                                 } else {
2053                                         tmp_offset_point[active_page].d = offset_point;
2054                                 }
2055 #else
2056                                 tmp_offset_point[active_page].d = offset_point;
2057 #endif
2058                         }
2059                         tmp_offset_point[active_page].w.h = 0x0000;
2060                         if(addr == 0x0e) {
2061                                 tmp_offset_point[active_page].b.h = rval;
2062                         } else {
2063                                 tmp_offset_point[active_page].b.l = rval;
2064                         }
2065                         offset_changed[active_page] = !offset_changed[active_page];
2066                         if(offset_changed[active_page]) {
2067                                 vram_wrote = true;
2068 #if defined(_FM77AV_VARIANTS)
2069                                 if(active_page != 0) {
2070                                         if(offset_77av) {
2071                                                 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2072                                         } else {
2073                                                 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2074                                         }                                  
2075                                 } else {
2076                                         if(offset_77av) {
2077                                                 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2078                                         } else {
2079                                                 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2080                                         }                                  
2081                                 }
2082 #else
2083                                 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2084 #endif                             
2085                         }
2086                         break;
2087 #if defined(_FM77AV_VARIANTS)
2088                 // ALU
2089                 case 0x10:
2090                         alu_write_cmdreg(data);
2091                         break;
2092                 case 0x11:
2093                         alu_write_logical_color(data);
2094                         break;
2095                 case 0x12:
2096                         alu_write_mask_reg(data);
2097                         break;
2098                 case 0x1b:
2099                         alu_write_disable_reg(data);
2100                         break;
2101                 case 0x20:
2102                         alu_write_offsetreg_hi(data);
2103                         break;
2104                 case 0x21:
2105                         alu_write_offsetreg_lo(data);
2106                         break;
2107                 case 0x22:
2108                         alu_write_linepattern_hi(data);
2109                         break;
2110                 case 0x23:
2111                         alu_write_linepattern_lo(data);
2112                         break;
2113 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2114                 case 0x2e: //
2115                         console_ram_bank = (data & 0x18) >> 3;
2116                         if(console_ram_bank > 2) console_ram_bank = 0;
2117                         cgram_bank = data & 0x07;
2118                         kanji_level2 = ((data & 0x80) == 0) ? false : true;
2119                         break;
2120                 case 0x2f: // VRAM BANK
2121                         vram_bank = data &  0x03;
2122                         if(vram_bank > 2) vram_bank = 0;
2123                         vram_wrote = true;
2124                         break;
2125 # endif                 
2126                 // MISC
2127                 case 0x30:
2128                         set_miscreg(data);
2129                         break;
2130                 // KEYBOARD ENCODER
2131                 case 0x31:
2132                         keyboard->write_data8(0x31, data);
2133                         break;
2134 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2135                 case 0x33: //
2136                         vram_active_block = data & 0x01;
2137                         if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2138                         vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2139                         break;
2140                         // Window
2141                 case 0x38: //
2142                 case 0x39: //
2143                         tmpvar.d = window_xbegin * 8;
2144                         tmpvar.w.h = 0;
2145                         if(addr == 0x38) {
2146                                 tmpvar.b.h = data & 0x03;
2147                         } else {
2148                                 tmpvar.b.l = data & 0xf8;
2149                         }
2150                         if(mode320 || mode256k) {
2151                            if(tmpvar.d > 320) tmpvar.d = 320;
2152                         } else {
2153                            if(tmpvar.d > 640) tmpvar.d = 640;
2154                         }
2155                         window_xbegin = tmpvar.d / 8;
2156                         vram_wrote = true;
2157                         break;
2158                 case 0x3a: //
2159                 case 0x3b: //
2160                         tmpvar.d = window_xend * 8;
2161                         tmpvar.w.h = 0;
2162                         if(addr == 0x3a) {
2163                                 tmpvar.b.h = data & 0x03;
2164                         } else {
2165                                 tmpvar.b.l = data & 0xf8;
2166                         }
2167                         if(mode320 || mode256k) {
2168                            if(tmpvar.d > 320) tmpvar.d = 320;
2169                         } else {
2170                            if(tmpvar.d > 640) tmpvar.d = 640;
2171                         }
2172                         window_xend = tmpvar.d / 8;
2173                         vram_wrote = true;
2174                         break;
2175                 case 0x3c: //
2176                 case 0x3d: //
2177                         tmpvar.d = window_low;
2178                         tmpvar.w.h = 0;
2179                         if(addr == 0x3c) {
2180                                 tmpvar.b.h = data & 0x03;
2181                         } else {
2182                                 tmpvar.b.l = data & 0xff;
2183                         }
2184                         if(display_mode == DISPLAY_MODE_8_400L) {
2185                                 if(tmpvar.d > 400) tmpvar.d = 400;
2186                         } else {
2187                                 tmpvar.d <<= 1;
2188                                 if(tmpvar.d > 400) tmpvar.d = 400;
2189                         }
2190                         window_low = tmpvar.d;
2191                         vram_wrote = true;
2192                         break;
2193                 case 0x3e: //
2194                 case 0x3f: //
2195                         tmpvar.d = window_high;
2196                         tmpvar.w.h = 0;
2197                         if(addr == 0x3e) {
2198                                 tmpvar.b.h = data & 0x03;
2199                         } else {
2200                                 tmpvar.b.l = data & 0xff;
2201                         }
2202                         if(display_mode == DISPLAY_MODE_8_400L) {
2203                                 if(tmpvar.d > 400) tmpvar.d = 400;
2204                         } else {
2205                                 tmpvar.d <<= 1;
2206                                 if(tmpvar.d > 400) tmpvar.d = 400;
2207                         }
2208                         window_high = tmpvar.d;
2209                         vram_wrote = true;
2210                         break;
2211 # endif
2212 #endif                          
2213                 default:
2214 #if defined(_FM77AV_VARIANTS)
2215                         //ALU
2216                         if((addr >= 0x13) && (addr <= 0x1a)) {
2217                                 alu_write_cmpdata_reg(addr - 0x13, data);
2218                         } else if((addr >= 0x1c) && (addr <= 0x1e)) {
2219                                 alu_write_tilepaint_data(addr, data);
2220                         } else if((addr >= 0x24) && (addr <= 0x2b)) {
2221                                 alu_write_line_position(addr - 0x24, data);
2222                         }
2223 #endif                          
2224                         break;
2225         }
2226 }
2227
2228 void DISPLAY::write_data8_main(uint32_t addr, uint8_t data)
2229 {
2230         uint32_t offset;
2231         uint32_t raddr;
2232         uint32_t page_offset = 0x0000;
2233
2234         if(addr < 0xc000) return;
2235         
2236         if(addr < 0xd000) { 
2237                 raddr = addr - 0xc000;
2238 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2239                 if(monitor_ram) {
2240                         if(console_ram_bank >= 1) {
2241                                 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
2242                                 return;
2243                         }
2244                 }
2245 #endif
2246                 console_ram[raddr] = data;
2247                 return;
2248         } else if(addr < 0xd380) {
2249                 raddr = addr - 0xd000;
2250                 work_ram[raddr] = data;
2251                 return;
2252         } else if(addr < 0xd400) {
2253                 raddr = addr - 0xd380;
2254                 shared_ram[raddr] = data;
2255                 return;
2256         } else if(addr < 0xd800) {
2257 #if defined(_FM77AV_VARIANTS)
2258                 if(addr >= 0xd500) {
2259                         submem_hidden[addr - 0xd500] = data;
2260                         return;
2261                 }
2262 #endif
2263                 write_mmio(addr, data);
2264                 return;
2265         } else if(addr < 0x10000) {
2266 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2267                 if(ram_protect) return;
2268                 if(monitor_ram) {
2269                         if(addr < 0xe000) {
2270                                 submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)] = data; //FIXME
2271                         } else {
2272                                 subsys_ram[addr - 0xe000] = data;
2273                         }
2274                 }
2275 #endif          
2276                 return;
2277         }
2278 }
2279
2280 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
2281 {
2282         uint32_t offset;
2283         uint32_t raddr;
2284         uint32_t page_offset = 0x0000;
2285         uint8_t val8 = data & 0xff;
2286         uint32_t pagemod;
2287         uint32_t color = (addr & 0xc000) >> 14;
2288         uint8_t tdata;
2289
2290         if(addr < 0xc000) {
2291 #if defined(_FM77AV_VARIANTS)
2292                 if(use_alu) {
2293                         alu->read_data8(addr + ALU_WRITE_PROXY);
2294                         return;
2295                 }
2296 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2297                 if(display_mode == DISPLAY_MODE_8_400L) {
2298                         color = vram_bank & 0x03;
2299                         if(color > 2) color = 0;
2300                 }
2301 # endif
2302 #endif
2303 #if !defined(_FM8)
2304                 if((multimode_accessmask & (1 << color)) != 0) return;
2305 #endif          
2306                 write_vram_data8(addr, val8);
2307                 return;
2308         } else if(addr < 0x10000) {
2309                 write_data8_main(addr, val8);
2310                 return;
2311         }
2312 #if !defined(_FM8)      
2313         else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2314                 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
2315                 return;
2316         }
2317 #endif  
2318 #if defined(_FM77AV_VARIANTS)
2319         // ANALOG PALETTE
2320         else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
2321                 set_apalette_r(val8);
2322                 return;
2323         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2324                 set_apalette_g(val8);
2325                 return;
2326         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2327                 set_apalette_b(val8);
2328                 return;
2329         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2330                 set_apalette_index_hi(val8);
2331                 return;
2332         } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2333                 set_apalette_index_lo(val8);
2334                 return;
2335         }
2336         // ACCESS VIA ALU.
2337         else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2338                 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS; 
2339 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2340                 if(display_mode == DISPLAY_MODE_8_400L) {
2341                         color = (addr & 0x18000) >> 15;
2342                         if(color > 2) color = 0;
2343                         page_offset = 0;
2344 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2345                         if(vram_active_block != 0) page_offset = 0x18000;
2346 # endif         
2347                         if(color > 2) color = 0;
2348                         if (active_page != 0) {
2349                                 offset = offset_point_bank1 << 1;
2350                         } else {
2351                                 offset = offset_point << 1;
2352                         }
2353                         pagemod = 0x8000 * color;
2354                         tdata = gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
2355                         if(tdata != (uint8_t)data) {
2356                                 gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
2357                                 vram_wrote_table[(addr & 0x7fff) / 80] = true;
2358                         }
2359                         return;
2360                 }
2361                 write_vram_data8(addr, data);
2362 # else
2363                 write_vram_data8(addr, data);
2364 # endif
2365                 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2366         }
2367 #endif
2368         return;
2369 }       
2370
2371
2372 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
2373 {
2374         FILEIO fio;
2375         uint32_t blocks;
2376         const _TCHAR *s;
2377   
2378         if((name == NULL) || (ptr == NULL))  return 0;
2379         s = create_local_path(name);
2380         if(s == NULL) return 0;
2381   
2382         if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2383         blocks = fio.Fread(ptr, size, 1);
2384         fio.Fclose();
2385
2386         return blocks * size;
2387 }
2388
2389
2390 void DISPLAY::initialize()
2391 {
2392         int i;
2393
2394         screen_update_flag = true;
2395         memset(gvram, 0x00, sizeof(gvram));
2396         vram_wrote_shadow = false;
2397         memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2398         for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
2399         for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2400
2401         memset(console_ram, 0x00, sizeof(console_ram));
2402         memset(work_ram, 0x00, sizeof(work_ram));
2403         memset(shared_ram, 0x00, sizeof(shared_ram));
2404         memset(subsys_c, 0xff, sizeof(subsys_c));
2405    
2406         diag_load_subrom_c = false;
2407 #if defined(_FM8)       
2408         if(read_bios(_T("SUBSYS_8.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2409         this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2410 #else
2411         if(read_bios(_T("SUBSYS_C.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2412         this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2413 #endif
2414 #if defined(_FM77AV_VARIANTS)
2415         memset(subsys_a, 0xff, sizeof(subsys_a));
2416         memset(subsys_b, 0xff, sizeof(subsys_b));
2417         memset(subsys_cg, 0xff, sizeof(subsys_cg));
2418         memset(submem_hidden, 0x00, sizeof(submem_hidden));
2419    
2420         diag_load_subrom_a = false;
2421         if(read_bios(_T("SUBSYS_A.ROM"), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2422         this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
2423
2424         diag_load_subrom_b = false;
2425         if(read_bios(_T("SUBSYS_B.ROM"), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2426         this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
2427
2428         diag_load_subrom_cg = false;
2429         if(read_bios(_T("SUBSYSCG.ROM"), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2430         this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
2431 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2432     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2433         memset(subsys_ram, 0x00, sizeof(subsys_ram));
2434         memset(submem_cgram, 0x00, sizeof(submem_cgram));
2435         memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2436         ram_protect = true;
2437 # endif
2438 #endif
2439 #if defined(_FM77AV_VARIANTS)
2440         mode320 = false;
2441         apalette_index.d = 0;
2442         for(i = 0; i < 4096; i++) {
2443                 analog_palette_r[i] = i & 0x0f0;
2444                 analog_palette_g[i] = (i & 0xf00) >> 4;
2445                 analog_palette_b[i] = (i & 0x00f) << 4;
2446                 calc_apalette(i);
2447         }
2448 #endif
2449 #if defined(_FM77AV_VARIANTS)
2450         hblank_event_id = -1;
2451         hdisp_event_id = -1;
2452         vsync_event_id = -1;
2453         vstart_event_id = -1;
2454 #endif
2455 #if defined(_FM8)
2456         clock_fast = false;
2457 #else
2458         clock_fast = true;
2459 #endif
2460 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
2461         is_cyclesteal = true;
2462 #else
2463         is_cyclesteal = false;
2464 #endif  
2465 //      emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2466         emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2467         enter_display();
2468         nmi_event_id = -1;
2469         firq_mask = false;
2470         key_firq_req = false;   //firq_mask = true;
2471         frame_skip_count = 3;
2472         emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2473         palette_changed = true;
2474 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
2475         //register_vline_event(this);
2476         //register_frame_event(this);
2477 #endif  
2478         
2479 }
2480
2481 void DISPLAY::release()
2482 {
2483 }
2484
2485 #define STATE_VERSION 7
2486 void DISPLAY::save_state(FILEIO *state_fio)
2487 {
2488         state_fio->FputUint32_BE(STATE_VERSION);
2489         state_fio->FputInt32_BE(this_device_id);
2490         this->out_debug_log("Save State: DISPLAY : id=%d ver=%d\n", this_device_id, STATE_VERSION);
2491
2492         {
2493                 int i;
2494                 state_fio->FputInt32_BE(clr_count);
2495                 state_fio->FputBool(halt_flag);
2496                 state_fio->FputInt32_BE(active_page);
2497                 state_fio->FputBool(sub_busy);
2498                 state_fio->FputBool(crt_flag);
2499                 state_fio->FputBool(vram_wrote);
2500                 state_fio->FputBool(is_cyclesteal);
2501                 
2502                 state_fio->FputBool(clock_fast);
2503                 
2504 #if defined(_FM77AV_VARIANTS)
2505                 state_fio->FputBool(subcpu_resetreq);
2506                 state_fio->FputBool(power_on_reset);
2507 #endif  
2508                 state_fio->FputBool(cancel_request);
2509                 state_fio->FputBool(key_firq_req);
2510
2511                 state_fio->FputInt32_BE(display_mode);
2512                 state_fio->FputUint32_BE(prev_clock);
2513
2514 #if !defined(_FM8)      
2515                 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
2516                 state_fio->FputUint8(multimode_accessmask);
2517                 state_fio->FputUint8(multimode_dispmask);
2518 #endif          
2519                 state_fio->FputUint32_BE(offset_point);
2520 #if defined(_FM77AV_VARIANTS)
2521                 state_fio->FputUint32_BE(offset_point_bank1);
2522 #endif          
2523                 for(i = 0; i < 2; i++) {
2524                         state_fio->FputUint32_BE(tmp_offset_point[i].d);
2525                         state_fio->FputBool(offset_changed[i]);
2526                 }
2527                 state_fio->FputBool(offset_77av);
2528                 state_fio->FputBool(diag_load_subrom_c);
2529                 
2530         
2531                 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
2532                 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
2533                 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
2534                 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
2535                 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
2536                 state_fio->Fwrite(gvram, sizeof(gvram), 1);
2537                 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
2538         
2539 #if defined(_FM77_VARIANTS)
2540                 state_fio->FputBool(kanjisub);
2541                 state_fio->FputUint16_BE(kanjiaddr.w.l);
2542 # if defined(_FM77L4)
2543                 state_fio->FputBool(mode400line);
2544                 state_fio->FputBool(stat_400linecard);
2545 # endif
2546 #elif defined(_FM77AV_VARIANTS)
2547                 state_fio->FputBool(kanjisub);
2548                 state_fio->FputUint16_BE(kanjiaddr.w.l);
2549
2550                 state_fio->FputBool(vblank);
2551                 state_fio->FputBool(vsync);
2552                 state_fio->FputBool(hblank);
2553                 state_fio->FputInt32_BE(vblank_count);
2554                 
2555                 state_fio->FputBool(mode320);
2556                 state_fio->FputInt8(display_page);
2557                 state_fio->FputInt8(display_page_bak);
2558                 state_fio->FputInt32_BE(cgrom_bank);
2559 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2560     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2561                 state_fio->FputInt32_BE(vram_bank);
2562 #endif  
2563         
2564                 state_fio->FputUint32_BE(displine);
2565                 state_fio->FputUint8(subrom_bank);
2566                 state_fio->FputUint8(subrom_bank_using);
2567         
2568                 state_fio->FputBool(nmi_enable);
2569                 state_fio->FputBool(use_alu);
2570                 
2571                 state_fio->FputUint8(apalette_index.b.l);
2572                 state_fio->FputUint8(apalette_index.b.h);
2573                 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
2574                 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
2575                 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
2576                 
2577
2578                 state_fio->FputBool(diag_load_subrom_a);
2579                 state_fio->FputBool(diag_load_subrom_b);
2580                 state_fio->FputBool(diag_load_subrom_cg);
2581         
2582                 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
2583                 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
2584                 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
2585                 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
2586 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2587                 state_fio->FputBool(mode400line);
2588                 state_fio->FputBool(mode256k);
2589                 
2590                 state_fio->FputBool(monitor_ram);
2591 #  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2592                 state_fio->FputUint16_BE(window_low);
2593                 state_fio->FputUint16_BE(window_high);
2594                 state_fio->FputUint16_BE(window_xbegin);
2595                 state_fio->FputUint16_BE(window_xend);
2596                 state_fio->FputBool(window_opened);
2597 #  endif        
2598                 state_fio->FputBool(kanji_level2);
2599
2600                 state_fio->FputUint8(vram_active_block);
2601                 state_fio->FputUint8(vram_display_block);
2602                 state_fio->FputUint8(console_ram_bank);
2603                 state_fio->FputBool(ram_protect);
2604                 
2605                 state_fio->FputUint32_BE(cgram_bank);
2606                 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
2607                 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
2608                 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
2609 # endif
2610 #endif
2611         }
2612         // V2
2613         {
2614                 state_fio->FputInt32_BE(nmi_event_id);
2615 #if defined(_FM77AV_VARIANTS)
2616                 state_fio->FputInt32_BE(hblank_event_id);
2617                 state_fio->FputInt32_BE(hdisp_event_id);
2618                 state_fio->FputInt32_BE(vsync_event_id);
2619                 state_fio->FputInt32_BE(vstart_event_id);
2620 #endif
2621                 state_fio->FputBool(firq_mask);
2622                 state_fio->FputBool(vram_accessflag);
2623                 state_fio->FputUint32_BE(frame_skip_count);
2624         }                       
2625 }
2626
2627 bool DISPLAY::load_state(FILEIO *state_fio)
2628 {
2629
2630         uint32_t version = state_fio->FgetUint32_BE();
2631         if(this_device_id != state_fio->FgetInt32_BE()) {
2632                 return false;
2633         }
2634         this->out_debug_log("Load State: DISPLAY : id=%d ver=%d\n", this_device_id, version);
2635    
2636         if(version >= 1) {
2637                 int addr;
2638                 int i;
2639                 clr_count = state_fio->FgetInt32_BE();
2640                 halt_flag = state_fio->FgetBool();
2641                 active_page = state_fio->FgetInt32_BE();
2642                 sub_busy = state_fio->FgetBool();
2643                 crt_flag = state_fio->FgetBool();
2644                 vram_wrote = state_fio->FgetBool();
2645                 crt_flag_bak = true;
2646                 for(i = 0; i < 411; i++) vram_wrote_table[i] = true;
2647                 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
2648                 is_cyclesteal = state_fio->FgetBool();
2649         
2650                 clock_fast = state_fio->FgetBool();
2651
2652 #if defined(_FM77AV_VARIANTS)
2653                 subcpu_resetreq = state_fio->FgetBool();
2654                 power_on_reset = state_fio->FgetBool();
2655 #endif          
2656                 cancel_request = state_fio->FgetBool();
2657                 key_firq_req = state_fio->FgetBool();
2658
2659                 display_mode = state_fio->FgetInt32_BE();
2660                 prev_clock = state_fio->FgetUint32_BE();
2661         
2662 #if defined(_FM8)
2663                 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
2664 #else
2665                 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
2666                 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
2667                 multimode_accessmask = state_fio->FgetUint8();
2668                 multimode_dispmask = state_fio->FgetUint8();
2669 #endif
2670                 offset_point = state_fio->FgetUint32_BE();
2671 #if defined(_FM77AV_VARIANTS)
2672                 offset_point_bank1     = state_fio->FgetUint32_BE();
2673 #endif          
2674                 for(i = 0; i < 2; i++) {
2675                         tmp_offset_point[i].d = state_fio->FgetUint32_BE();
2676                         offset_changed[i] = state_fio->FgetBool();
2677                 }
2678                 offset_77av = state_fio->FgetBool();
2679                 diag_load_subrom_c = state_fio->FgetBool();
2680                 
2681                 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
2682                 state_fio->Fread(console_ram, sizeof(console_ram), 1);
2683                 state_fio->Fread(work_ram, sizeof(work_ram), 1);
2684                 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
2685                 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
2686                 state_fio->Fread(gvram, sizeof(gvram), 1);
2687                 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
2688 #if defined(_FM77_VARIANTS)
2689                 kanjisub = state_fio->FgetBool();
2690                 kanjiaddr.d = 0;
2691                 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2692 # if defined(_FM77L4)           
2693                 mode400line = state_fio->FgetBool();
2694                 stat_400linecard = state_fio->FgetBool();
2695 # endif         
2696 #elif defined(_FM77AV_VARIANTS)
2697                 kanjisub = state_fio->FgetBool();
2698                 kanjiaddr.d = 0;
2699                 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2700                 
2701                 vblank = state_fio->FgetBool();
2702                 vsync = state_fio->FgetBool();
2703                 hblank = state_fio->FgetBool();
2704                 vblank_count = state_fio->FgetInt32_BE();
2705
2706                 mode320 = state_fio->FgetBool();
2707                 display_page = state_fio->FgetInt8();
2708                 display_page_bak = state_fio->FgetInt8();
2709                 cgrom_bank = state_fio->FgetInt32_BE();
2710 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2711     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2712                 vram_bank = state_fio->FgetInt32_BE();
2713 #endif          
2714                 screen_update_flag = true;
2715                 displine = state_fio->FgetUint32_BE();
2716                 subrom_bank = state_fio->FgetUint8();
2717                 subrom_bank_using = state_fio->FgetUint8();
2718         
2719                 nmi_enable = state_fio->FgetBool();
2720                 use_alu = state_fio->FgetBool();
2721
2722                 apalette_index.b.l = state_fio->FgetUint8();
2723                 apalette_index.b.h = state_fio->FgetUint8();
2724         
2725                 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
2726                 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
2727                 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
2728                 for(i = 0; i < 4096; i++) calc_apalette(i);
2729                 
2730                 diag_load_subrom_a = state_fio->FgetBool();
2731                 diag_load_subrom_b = state_fio->FgetBool();
2732                 diag_load_subrom_cg = state_fio->FgetBool();
2733         
2734                 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
2735                 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
2736                 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
2737                 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
2738            
2739 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2740                 mode400line = state_fio->FgetBool();
2741                 mode256k = state_fio->FgetBool();
2742
2743                 monitor_ram = state_fio->FgetBool();
2744 #  if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2745                 window_low = state_fio->FgetUint16_BE();
2746                 window_high = state_fio->FgetUint16_BE();
2747                 window_xbegin = state_fio->FgetUint16_BE();
2748                 window_xend = state_fio->FgetUint16_BE();
2749                 window_opened = state_fio->FgetBool();
2750 # endif 
2751                 kanji_level2 = state_fio->FgetBool();
2752                 
2753                 vram_active_block = state_fio->FgetUint8();
2754                 vram_display_block = state_fio->FgetUint8();
2755                 console_ram_bank = state_fio->FgetUint8();
2756                 ram_protect = state_fio->FgetBool();
2757
2758                 cgram_bank = state_fio->FgetUint32_BE();
2759                 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
2760                 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
2761                 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
2762 # endif
2763 #endif
2764                 palette_changed = true;
2765                 vram_wrote_shadow = true; // Force Draw
2766                 this->draw_screen();
2767                 if(version == 1) return true;
2768         }
2769         if(version >= 2) {      //V2
2770                 nmi_event_id = state_fio->FgetInt32_BE();
2771 #if defined(_FM77AV_VARIANTS)
2772                 hblank_event_id = state_fio->FgetInt32_BE();
2773                 hdisp_event_id = state_fio->FgetInt32_BE();
2774                 vsync_event_id = state_fio->FgetInt32_BE();
2775                 vstart_event_id = state_fio->FgetInt32_BE();
2776 #endif
2777                 firq_mask = state_fio->FgetBool();
2778                 vram_accessflag = state_fio->FgetBool();
2779                 frame_skip_count = state_fio->FgetUint32_BE();
2780         }                       
2781         if(version == STATE_VERSION) return true;
2782         return false;
2783 }
2784
2785