OSDN Git Service

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