OSDN Git Service

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