OSDN Git Service

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