OSDN Git Service

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