OSDN Git Service

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