OSDN Git Service

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