OSDN Git Service

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