OSDN Git Service

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