OSDN Git Service

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