OSDN Git Service

[VM][PC9801][MEMBUS] Split update_bios() to functions.
[csp-qt/common_source_project-fm7.git] / source / src / vm / v99x8.cpp
1 #define USE_CMDTIME
2
3 // from "v99x8.c" of Zodiac
4
5 /*
6  * Copyright (c) 2000-2002 SASAKI Shunsuke (eruchan@users.sourceforge.net).
7  * Copyright (c) 2001-2002 The Zodiac project.
8  * All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  */
24
25 //#include "../../config.h"
26
27 #include <string.h>
28
29 //#include "../zodiac.h"
30 #include "v99x8.h"
31 v99x8_t v99x8;
32
33 //#ifdef USE_CMDTIME
34 void cmdtime_set(int m);
35 void cmdtime_chk(void);
36 static int cmdtime_t;
37 static int cmdtime_m;
38 //#endif
39 static int latch1;
40 static int latch2;
41
42 // from "md.h.in" of Zodiac
43 #if defined(_MSC_VER)
44 #       define __inline__ __forceinline
45 #elif defined(_MWERKS_)
46 #       define __inline__ inline
47 #elif !defined(__GNUC__)
48 #       define __inline__
49 #endif
50
51 #define MD_LITTLE
52
53 //#include "z80.h"      /* XXX interrupt */
54 #define Z80_NOINT 0xffff
55 #define Z80_INT 0x0038
56 //#define Z80_NMI 0x0066
57
58 #define MD_BPP 32
59 #define md_maprgb15(R,G,B) RGB_COLOR(((R) << 3), ((G) << 3), ((B) << 3))
60 #define md_video_pixbytes(n) (n*32/8)
61 #define md_refresh_sync() (TRUE)
62 #define md_video_defaultopt() (0)
63 int md_video_pitch(void);       // the length of a row of pixels in bytes
64 uint8_t *md_video_lockline(int x, int y, int w, int h);
65 void md_video_unlockline(void) {}
66 void md_video_update(int n, /*md_video_rect_t*/void *rp);
67 void md_video_fill(int x, int y, int w, int h, uint32_t c);
68 typedef uint32_t md_pixel_t;
69
70 // from "md_depend.h" of Zodiac
71 typedef struct
72 {
73         int width, height;
74         int bpp;
75         int option;
76 }       md_video_mode_t;
77 //typedef       SDL_Rect md_video_rect_t;
78 //typedef       SDL_Surface md_video_surface_t;
79 typedef struct
80 {
81         //md_video_surface_t *screen;
82         int w, h;                                       /* \97v\8b\81\82µ\82½\83T\83C\83Y */
83 }       md_video_t;
84
85
86 static int vram_addr;
87 static int vram_page;
88
89 static bool f_out3;
90 static bool f_mode;
91 bool f_scr;
92
93
94 extern void v99x8_command(int m);       /* v99x8_internal.h ?? */
95 extern void v99x8_cputovdp(int m);
96
97
98 #define XXX_V99X8_ID 0
99
100
101 /*
102 0: 000, 10 xx TMS 
103 1: 000, 00 xx TMS 
104 2: 001, 00 xx TMS 
105 3: 000, 01 xx TMS 
106
107 x: 010, 10 xx     
108 4: 010, 00 xx     
109 5: 011, 00 xx     1 
110 6: 100, 00 xx     2 
111 7: 101, 00 xx I   1 
112 8: 111, 00 xx I   0 
113
114 a: 111, 00 11     0
115 c: 111, 00 01     0
116 */
117
118
119 /*
120 normal, sc7/8
121
122 00000h: 00000h
123 00001h: 10000h
124 00002h: 00001h
125 00003h: 10000h
126 0fffeh: 07fffh
127 0ffffh: 17fffh
128 10000h: 08000h
129 10001h: 08001h
130
131 */
132
133 static void v99x8_interleave(void)
134 {
135 #if 0
136         static uint8_t *vram = NULL;
137         uint8_t *p;
138         size_t size;
139
140         size = v99x8.pages * 0x4000;
141
142         if (vram == NULL)
143                 vram = (uint8_t *)malloc(size);
144
145         p = vram;
146         vram = v99x8.vram;
147         v99x8.vram = p;
148
149         if (v99x8.mode.f_interleave)
150         {
151                 int a, b, c;
152
153                 a = 0;
154                 b = size / 2;
155                 c = 0;
156
157                 while (c < (int)size)
158                 {
159                         v99x8.vram[c]     = vram[a++];
160                         v99x8.vram[c + 1] = vram[b++];
161                         c += 2;
162                 }
163         } else
164         {
165                 int a, b, c;
166
167                 a = 0;
168                 b = size / 2;
169                 c = 0;
170
171                 while (c < (int)size)
172                 {
173                         v99x8.vram[a++] = vram[c];
174                         v99x8.vram[b++] = vram[c + 1];
175                         c += 2;
176                 }
177         }
178 #endif
179 }
180
181 static void v99x8_mode_set(int n)
182 {
183         v99x8_screen_mode_t mode[] =
184         {
185                 {TRUE, FALSE, 0, 0},  /* V99X8_SCREEN_0 */
186                 {TRUE, FALSE, 0, 0},  /* V99X8_SCREEN_1 */
187                 {TRUE, FALSE, 0, 0},  /* V99X8_SCREEN_2 */
188                 {TRUE, FALSE, 0, 0},  /* V99X8_SCREEN_3 */
189
190                 {FALSE, FALSE, 0, 0}, /* V99X8_SCREEN_4 */
191                 {FALSE, FALSE, 256, 1}, /* V99X8_SCREEN_5 */
192                 {FALSE, FALSE, 512, 2}, /* V99X8_SCREEN_6 */
193                 {FALSE, TRUE, 512, 1},  /* V99X8_SCREEN_7 */
194
195                 {FALSE, TRUE, 256, 0},  /* V99X8_SCREEN_8 */
196                 {FALSE, FALSE, 0, 0}, /* V99X8_SCREEN_X */
197                 {FALSE, TRUE, 256, 0},  /* V99X8_SCREEN_A */
198                 {FALSE, TRUE, 256, 0}   /* V99X8_SCREEN_C */
199         };
200
201         if (n != V99X8_SCREEN_8 || (v99x8.ctrl[25] & 0x08) != 0x08)
202                 v99x8.scr = n;
203         else
204         {
205                 if ((v99x8.ctrl[25] & 0x10) == 0x10)
206                         v99x8.scr = V99X8_SCREEN_A;
207                 else
208                         v99x8.scr = V99X8_SCREEN_C;
209         }
210
211         memcpy(&v99x8.mode, &mode[v99x8.scr], sizeof(v99x8_screen_mode_t));
212 }
213
214 static void v99x8_update(void)
215 {
216         int mapping[] =
217         {
218                 V99X8_SCREEN_1, V99X8_SCREEN_2, V99X8_SCREEN_4, V99X8_SCREEN_5,
219                 V99X8_SCREEN_6, V99X8_SCREEN_7, V99X8_SCREEN_IGN, V99X8_SCREEN_8,
220                 V99X8_SCREEN_3, V99X8_SCREEN_IGN, V99X8_SCREEN_IGN, V99X8_SCREEN_IGN,
221                 V99X8_SCREEN_IGN, V99X8_SCREEN_IGN, V99X8_SCREEN_IGN, V99X8_SCREEN_IGN,
222                 V99X8_SCREEN_0, V99X8_SCREEN_IGN, V99X8_SCREEN_X
223         };
224
225         bool f;
226         int a;
227
228         if (!f_mode)
229                 return;
230
231         f = v99x8.mode.f_interleave;
232
233         a = ((v99x8.ctrl[0] & 0x0e) >> 1) | (v99x8.ctrl[1] & 0x18);
234         if (a >= sizeof(mapping) / sizeof(*mapping) || 
235             mapping[a] == V99X8_SCREEN_IGN)
236         {
237                 return;
238         }
239
240         v99x8_mode_set(mapping[a]);
241
242         if (f != v99x8.mode.f_interleave)
243                 v99x8_interleave();
244
245         f_mode = FALSE;
246 }
247
248
249 static void v99x8_ctrl_init(void)
250 {
251         memset(v99x8.ctrl, 0, sizeof(v99x8.ctrl));
252 }
253
254 void v99x8_ctrl(int n, uint8_t m)
255 {
256 /* printf ("v99x8_ctrl %2d <= %02x\n", n, m); */
257
258         if (n >= V99X8_NREG)
259         {
260                 n = V99X8_NREG - 1;
261         }
262
263         switch(n)
264         {
265         case 0:
266                 if (((m ^ v99x8.ctrl[0]) & 0x0e) != 0)
267                 {
268                         f_mode = TRUE;
269                         f_scr = TRUE;
270                 }
271                 break;
272
273         case 1:
274                 if (((m ^ v99x8.ctrl[1]) & 0x18) != 0)
275                 {
276                         f_mode = TRUE;
277                         f_scr = TRUE;
278                 }
279                 break;
280
281         case 2:
282         case 3:
283         case 4:
284         case 10:
285                 f_scr = TRUE;
286                 break;
287
288         case 7:
289                 v99x8.col_fg = m >> 4;
290                 v99x8.col_bg = m & 0x0f;
291                 break;
292
293         case 14:
294                 m &= v99x8.pages - 1;
295                 vram_page = (int)m << 14;
296                 break;
297
298         case 15:
299                 if (m >= V99X8_NSTAT)
300                         m = V99X8_NSTAT - 1;
301                 break;
302
303         case 16:
304                 m &= 0x0f;
305                 break;
306
307         case 17:
308                 f_out3 = !(m & 0x80);
309                 m &= 0x3f;
310                 break;
311
312     case 44: 
313         v99x8_update();
314                 v99x8_cputovdp(m);
315         break;
316     case 46: 
317         v99x8_update();
318                 v99x8_command(m);
319         break;
320
321     /* XXX
322
323     */
324     case 6:
325         m &= 0x3f;
326         break;
327
328     case 11:
329         m &= 0x03;
330         break;
331         }
332
333         v99x8.ctrl[n] = m;
334 }
335
336
337 static void vram_incaddr(void)
338 {
339         vram_addr = (vram_addr + 1) & 0x3fff;
340         if (vram_addr == 0 && !v99x8.mode.f_tms)
341                 v99x8_ctrl(14, v99x8.ctrl[14] + 1);
342 }
343
344 uint8_t vram_read(int addr)
345 {
346         return v99x8.vram[addr];
347 }
348
349 void vram_write(int addr, uint8_t n)
350 {
351         v99x8.vram[addr] = n;
352 }
353
354
355 uint8_t v99x8_in_0(void)        /* VRAM read */
356 {
357         int n;
358
359         v99x8_update();
360
361         n = vram_read(vram_addr + vram_page);
362         vram_incaddr();
363         return n;
364 }
365
366 void v99x8_out_0(uint8_t n)     /* VRAM write */
367 {
368         v99x8_update();
369
370         vram_write(vram_addr + vram_page, n);
371         vram_incaddr();
372 }
373
374 uint8_t v99x8_in_1(void)        /* status in */
375 {
376         int n;
377 #if 0
378         int a, b;
379 #endif
380
381         v99x8_update();
382
383         n = v99x8.status[v99x8.ctrl[15]];
384
385 /*
386 if (z80.ivec!=Z80_NOINT)
387         {
388 printf("* IFF:%d H:%d V:%d\n", z80.IFF&1, (v99x8.ctrl[0]&0x10), (v99x8.ctrl[1]&0x20));
389         }
390         z80_intreq(Z80_NOINT);
391         VKey=1;
392 */
393
394         switch(v99x8.ctrl[15])
395         {
396         case 0:
397                 v99x8.status[0] &= ~0xa0;
398                 break;
399         case 1:
400                 v99x8.status[1] &= ~0x01;
401                 break;
402         case 7:
403 /*              v99x8.status[7] = v99x8.ctrl[44] = v99x8_vdptocpu(); */
404                 break;
405
406         case 2:
407 #if 0
408                 context_timelock();
409                 a = context.hz / 60 / 262;
410                 b = (context.time_cycle % a) * 100 / a;
411                 context_timeunlock();
412
413                 if (b > 73)
414                         n |= 0x20;
415 //              else
416 #endif
417 //                      n &= ~0x20;
418                 break;
419         }
420
421         return n;
422 }
423
424 void    v99x8_out_1(uint8_t n)  /* ctrl out */
425 {
426         //static int latch = -1;
427
428         if (latch1 == -1)
429         {
430                 latch1 = n;
431         } else
432         {
433                 if (n & 0x80)
434                 {
435                         if ((n & 0x40) == 0)
436                                 v99x8_ctrl(n & 0x3f, latch1);
437                 } else
438                 {
439 /* ??? read/write \82Ì\8bæ\95Ê */
440                         vram_addr = ((int)(n & 0x3f) << 8) + latch1;
441                 }
442                 latch1 = -1;
443         }
444 }
445
446 void v99x8_out_2(uint8_t n)     /* palette out */
447 {
448         //static int latch = -1;
449
450         if (latch2 == -1)
451         {
452                 latch2 = n;
453         } else
454         {
455                 int a;
456
457                 a = v99x8.ctrl[16];
458                 v99x8_pallete_set(a, (latch2 & 0x70) >> 4, n & 0x07, latch2 & 0x07);
459                 v99x8_ctrl(16, a + 1);
460
461                 latch2 = -1;
462         }
463 }
464
465 void v99x8_out_3(uint8_t n)     /* ctrl out */
466 {
467         if (v99x8.ctrl[17] != 17)
468                 v99x8_ctrl(v99x8.ctrl[17], n);
469
470         if (f_out3)
471                 v99x8_ctrl(17, v99x8.ctrl[17] + 1);
472 }
473
474
475 static void v99x8_status_init(void)
476 {
477         memset(v99x8.status, 0, sizeof(v99x8.status));
478         v99x8.status[0] = 0x9f;
479         v99x8.status[1] = XXX_V99X8_ID << 1;
480         v99x8.status[2] = 0xac;
481 }
482
483 static void v99x8_vram_init(void)
484 {
485         //v99x8.vram = (uint8_t *)malloc(v99x8.pages * 0x4000);
486         memset(v99x8.vram, 0xff, v99x8.pages * 0x4000);
487 }
488
489 void v99x8_init(void)
490 {
491 /* ---- */
492
493         vram_addr = 0;
494         vram_page = 0;
495         f_out3 = FALSE;
496         f_scr = TRUE;
497         f_mode = FALSE;
498
499
500 /* ---- */
501
502         v99x8.scanline = 0;
503         v99x8.n_scanlines = 262;
504         v99x8.pages = 8;
505
506         v99x8_ctrl_init();
507         v99x8_status_init();
508
509 /*      v99x8.f_zoom = FALSE; */
510
511         v99x8_vram_init();
512
513         v99x8_mode_set(V99X8_SCREEN_1);
514
515         v99x8.col_fg = 0;
516         v99x8.col_bg = 0;
517
518         v99x8_refresh_init();
519 }
520
521 static bool flag_frame = FALSE;
522
523 int V99X8::hsync(int v/*void*/)
524 {
525         int a, line;
526
527         v99x8.scanline = v;     // is this OK???
528         v99x8.status[2] ^= 0x20;
529
530         if (v99x8.scanline < 226)
531         {
532                 if (flag_frame)
533                 {
534                         if (0 == v99x8.scanline) v99x8_refresh_clear(); // added by umaiboux
535                         line = v99x8.scanline + (((v99x8.ctrl[18] >> 4) + 8) & 0x0f) - 8 - 7;
536                         if (v99x8.ctrl[9] & 0x80)
537                                 a = 212;
538                         else
539                                 a = 192, line -= 10;
540
541                         if (v99x8.ctrl[1] & 0x40 && line >= 0 && line < a)
542                         {
543                                 v99x8_update();
544
545                                 switch(v99x8.scr)
546                                 {
547                                 case V99X8_SCREEN_0: v99x8_refresh_sc0(line, 1); break;
548                                 case V99X8_SCREEN_1: v99x8_refresh_sc1(line, 1); break;
549                                 case V99X8_SCREEN_2: v99x8_refresh_sc4(line, 1); break;
550                                 case V99X8_SCREEN_3: v99x8_refresh_sc3(line, 1); break;
551                                 case V99X8_SCREEN_4: v99x8_refresh_sc4(line, 1); break;
552                                 case V99X8_SCREEN_5: v99x8_refresh_sc5(line, 1); break;
553                                 case V99X8_SCREEN_6: v99x8_refresh_sc6(line, 1); break;
554                                 case V99X8_SCREEN_7: v99x8_refresh_sc7(line, 1); break;
555                                 case V99X8_SCREEN_8: v99x8_refresh_sc8(line, 1); break;
556                                 case V99X8_SCREEN_A: v99x8_refresh_scc(line, 1); break;
557                                 case V99X8_SCREEN_C: v99x8_refresh_scc(line, 1); break;
558                                 case V99X8_SCREEN_X: v99x8_refresh_scx(line, 1); break;
559                                 }
560                         }
561                 }
562
563                 if (((v99x8.scanline + v99x8.ctrl[23] 
564                     - ((v99x8.ctrl[9] & 0x80) ? 8 : 18)) & 0xff) == v99x8.ctrl[19])
565                 {
566                         if (v99x8.ctrl[0] & 0x10)
567                         {
568                                 v99x8.status[1] |= 0x01; /* H-sync */
569                                 z80_intreq(Z80_INT);
570                         }
571                 } else
572                 {
573                         if (!(v99x8.ctrl[0] & 0x10))
574                                 v99x8.status[1] &= ~0x01;   /* ?? H-sync off*/
575                 }
576         } else
577         {
578                 switch(v99x8.scanline)
579                 {
580                 case 234:
581                         if (flag_frame)
582                                 v99x8_refresh_screen();
583
584                         flag_frame = md_refresh_sync();
585
586                         v99x8.status[2] |= 0x40;    /* VBlank on */
587
588                         v99x8.status[1] &= ~0x01;   /* ?? H-sync off*/
589                         z80_intreq(Z80_NOINT);      /* ?? H-sync \82ð clear */
590
591 /* XXX sprite check */
592                         break;
593
594                 case 237:
595 /*                      v99x8.status[1] &= ~0x01; */  /* ?? H-sync off*/
596                         if (v99x8.ctrl[1] & 0x20)
597                         {
598                                 v99x8.status[0] |= 0x80;    /* V-sync int */
599                                 z80_intreq(Z80_INT);
600                         }
601                         break;
602
603                 case 261:
604                         v99x8.status[2] &= ~0x40;   /* VBlank off */
605                         v99x8.status[0] &= ~0x40;   /* 5sprit off */
606                         v99x8.status[0] &= ~0x80;   /* Vsync off */
607                         z80_intreq(Z80_NOINT);      /* ?? V-sync \82ð clear */
608
609                         /*if (flag_frame)
610                                 v99x8_refresh_clear();*/ // deleted by umaiboux
611                 }
612
613
614 /* NTSC timing
615
616   3/  3: sync signal
617  13/ 13: top erase
618  26/ 16: top border
619 192/212: line
620  25/ 15: bottom border
621
622   3/  3: bottom erase
623
624 */
625         }
626         return v99x8.scanline = (v99x8.scanline + 1) % v99x8.n_scanlines;
627 }
628
629
630
631 // from "v99x8_command.c" of Zodiac
632
633 /*
634  * Copyright (c) 2000-2002 SASAKI Shunsuke (eruchan@users.sourceforge.net).
635  * Copyright (c) 2001-2002 The Zodiac project.
636  * All rights reserved.
637  *
638  * This program is free software; you can redistribute it and/or modify
639  * it under the terms of the GNU General Public License as published by
640  * the Free Software Foundation; either version 2 of the License, or
641  * (at your option) any later version.
642  *
643  * This program is distributed in the hope that it will be useful,
644  * but WITHOUT ANY WARRANTY; without even the implied warranty of
645  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
646  * GNU General Public License for more details.
647  *
648  * You should have received a copy of the GNU General Public License
649  * along with this program; if not, write to the Free Software
650  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
651  */
652
653 //#include "../../config.h"
654
655 //#include <string.h>
656 #include <stdlib.h>
657
658 //#include "../zodiac.h"
659 #include "v99x8.h"
660
661 /* #define YAN_V99X8_TEST 1 */  /* XXX */
662
663 typedef struct
664 {
665         int xbytes;
666         int xmask, xshift;
667         int ymask, yshift;
668
669         int sx, sy, dx, dy, nx, ny;
670         int lop;
671
672         uint8_t *src, *dst;
673 } vcom_t;
674
675 vcom_t vcom;
676
677 typedef struct
678 {
679         int sx, sy, ex, ey;
680         int x, y;
681         int xsize;
682 } r44_t;
683
684 static r44_t r44;
685
686 #if 1   /* XXX */
687 typedef struct
688 {
689         int npix;
690         int xmask;
691         int mask;
692         int pmask[4];
693         int lshift[4];
694         int rshift[4];
695 } pixmask_t;
696
697 static pixmask_t pixmasks[4] = {
698         {2, 0x01, 0x0f, {0x0f, 0xf0, 0x0f, 0xf0}, {4, 0, 4, 0}, {4, 0, 4, 0}},
699         {4, 0x03, 0x03, {0x3f, 0xcf, 0xf3, 0xfc}, {6, 4, 2, 0}, {6, 4, 2, 0}},
700         {2, 0x01, 0x0f, {0x0f, 0xf0, 0x0f, 0xf0}, {4, 0, 4, 0}, {4, 0, 4, 0}},
701         {1, 0x00, 0xff, {0x00, 0x00, 0x00, 0x00}, {0, 0, 0, 0}, {0, 0, 0, 0}}
702 };
703
704 static pixmask_t pixmask;
705 #endif
706
707 static int getshift(int n)
708 {
709         int i;
710
711         for (i = 0; n & (1 << i); i++)
712                 ;
713         return i;
714 }
715
716 #define vcom_getsx() vcom.sx = (v99x8.ctrl[32] + (v99x8.ctrl[33] << 8)) & vcom.xmask
717 #define vcom_getsy() vcom.sy = (v99x8.ctrl[34] + (v99x8.ctrl[35] << 8)) & vcom.ymask
718 #define vcom_getdx() vcom.dx = (v99x8.ctrl[36] + (v99x8.ctrl[37] << 8)) & vcom.xmask
719 #define vcom_getdy() vcom.dy = (v99x8.ctrl[38] + (v99x8.ctrl[39] << 8)) & vcom.ymask
720 #define vcom_getnx() vcom.nx = ((v99x8.ctrl[40] + (v99x8.ctrl[41] << 8) - 1) & 511) + 1
721 #define vcom_getny() vcom.ny = ((v99x8.ctrl[42] + (v99x8.ctrl[43] << 8) - 1) & 1023) + 1
722
723 static void vcom_lpset(int x, int y, int clr);
724 static uint8_t vcom_point(int x, int y);
725
726 static void vcom_set(int base, int n)
727 {
728         v99x8.ctrl[base]     = n & 0xff;
729         v99x8.ctrl[base + 1] = n >> 8;
730 }
731
732 #define vcom_setsy(n) vcom_set(34, n)
733 #define vcom_setdy(n) vcom_set(38, n)
734 #define vcom_setny(n) vcom_set(42, n)
735
736 #define vcom_vram(x, y) (&v99x8.vram[((x) >> vcom.xshift) + ((y) << vcom.yshift)])
737
738 static int vcom_chksum(uint8_t *d, int n)
739 {
740         uint8_t *p;
741         int sum = 0;
742
743         p = d;
744         while(n--) {
745                 sum += *p;
746                 p++;
747         }
748         return sum;
749 }
750
751 #define vcom_dtcopy(d, s, nbytes) { \
752         uint8_t *p1, *p2;             \
753         int n;                      \
754         p1 = (s);                   \
755         p2 = (d);                   \
756         n = (nbytes);               \
757         while(n--)                  \
758                 *p2++ = *p1++;      \
759 }
760
761 static int vcom_canonaddr(void)
762 {
763         int ny;
764
765         if (v99x8.ctrl[45] & 0x04)  /* Direction to left */
766         {
767                 vcom.sx -= vcom.nx;
768                 vcom.dx -= vcom.nx;
769         }
770         vcom.sx = max(vcom.sx, 0);
771         vcom.nx = min(vcom.nx, vcom.xmask + 1 - vcom.sx);
772         vcom.dx = max(vcom.dx, 0);
773         vcom.nx = min(vcom.nx, vcom.xmask + 1 - vcom.dx);
774
775         ny = vcom.ny;
776         if ((v99x8.ctrl[45] & 0x08) == 0)   /* Direction to down */
777         {
778                 ny = min(ny, vcom.ymask + 1 - vcom.sy);
779                 ny = min(ny, vcom.ymask + 1 - vcom.dy);
780         } else
781         {
782                 ny = min(ny, vcom.sy + 1);
783                 ny = min(ny, vcom.dy + 1);
784                 ny = 0 - ny;
785         }
786
787 /* printf("can %d->%d *(%d,%d)\n", vcom.sx, vcom.dx, vcom.nx, ny); */
788
789         vcom.src = vcom_vram(vcom.sx, vcom.sy);
790         vcom.dst = vcom_vram(vcom.dx, vcom.dy);
791         vcom.nx >>= vcom.xshift;
792
793         return ny;
794 }
795
796 static void vcom_hcopy(uint8_t *dst, uint8_t *src, int nx, int ny)
797 {
798         if (ny < 0)
799         {
800                 while (ny++ < 0)
801                 {
802 /* printf("sum1: %d\n", vcom_chksum(src, nx)); */
803                         /* memmove(dst, src, nx); */
804                         vcom_dtcopy(dst, src, nx);
805 /* printf("sum2: %d\n", vcom_chksum(dst, nx)); */
806                         src -= vcom.xbytes;
807                         dst -= vcom.xbytes;
808                 }
809         } else
810         {
811                 while (ny--)
812                 {
813 /* printf("sum1: %d\n", vcom_chksum(src, nx)); */
814                         /* memmove(dst, src, nx); */
815                         vcom_dtcopy(dst, src, nx);
816 /* printf("sum2: %d\n", vcom_chksum(dst, nx)); */
817                         src += vcom.xbytes;
818                         dst += vcom.xbytes;
819                 }
820         }
821 }
822
823 static void ymmm(void)
824 {
825         int n;
826
827         vcom_getdx();
828         vcom_getsy();
829         vcom.sx = vcom.dx;
830         vcom_getdy();
831         vcom.nx = 512;
832         vcom_getny();
833
834 /* printf("ymmm: (%d,%d) %d*%d\n", vcom.sx, vcom.sy, vcom.dy, vcom.ny); */
835         n = vcom_canonaddr();
836         vcom_hcopy(vcom.dst, vcom.src, vcom.nx, n);
837
838         vcom_setsy(vcom.sy + n);
839         vcom_setdy(vcom.dy + n);
840
841         if (vcom.ny != abs(n))
842                 vcom_setny(vcom.ny - abs(n));
843 }
844
845 static void hmmm(void)
846 {
847         int n;
848
849         vcom_getsx();
850         vcom_getsy();
851         vcom_getdx();
852         vcom_getdy();
853         vcom_getnx();
854         vcom_getny();
855
856 /* printf("hmmm: (%d,%d)->(%d,%d) *(%d,%d)\n", vcom.sx, vcom.sy, vcom.dx, vcom.dy, vcom.nx, vcom.ny); */
857         n = vcom_canonaddr();
858         vcom_hcopy(vcom.dst, vcom.src, vcom.nx, n);
859
860         vcom_setsy(vcom.sy + n);
861         vcom_setdy(vcom.dy + n);
862
863         if (vcom.ny != abs(n))
864                 vcom_setny(vcom.ny - abs(n));
865 }
866
867 static void hmmv(void)
868 {
869         int n, ny, clr;
870
871         vcom.sx = 0;
872         vcom.sy = 0;
873         vcom_getdx();
874         vcom_getdy();
875         vcom_getnx();
876         vcom_getny();
877         clr = v99x8.ctrl[44];
878
879         ny = n = vcom_canonaddr();
880         if (n < 0)
881         {
882                 while (ny++ < 0)
883                 {
884                         memset(vcom.dst, clr, vcom.nx);
885                         vcom.dst -= vcom.xbytes;
886                 }
887         } else
888         {
889                 while (ny--)
890                 {
891                         memset(vcom.dst, clr, vcom.nx);
892                         vcom.dst += vcom.xbytes;
893                 }
894         }
895
896         vcom_setsy(vcom.sy + n);
897         vcom_setdy(vcom.dy + n);
898
899         if (vcom.ny != abs(n))
900                 vcom_setny(vcom.ny - abs(n));
901 }
902
903 #define vcom_lset(dc, sc)                           \
904 switch(vcom.lop)                                    \
905 {                                                   \
906         case 0x0: (dc)  = (sc); break;                  \
907         case 0x1: (dc) &= (sc); break;                  \
908         case 0x2: (dc) |= (sc); break;                  \
909         case 0x3: (dc) ^= (sc); break;                  \
910         case 0x4: (dc) =~ (sc); break;                  \
911         case 0x8: if ((sc) != 0) (dc)  = (sc); break;   \
912         case 0x9: if ((sc) != 0) (dc) &= (sc); break;   \
913         case 0xa: if ((sc) != 0) (dc) |= (sc); break;   \
914         case 0xb: if ((sc) != 0) (dc) ^= (sc); break;   \
915         case 0xc: if ((sc) != 0) (dc) =~ (sc); break;   \
916 }
917
918 /*
919         dc =  sc;
920         dc &= sc;
921         dc |= sc;
922         dc ^= sc;
923         dc =  ~sc;
924 */
925
926 static void vcom_lmove(uint8_t *dst, uint8_t *src, int n)
927 {
928 #if 0
929         if (v99x8.ctrl[45] & 0x04)  /* Direction to left */
930 #endif
931
932         while(n>0)
933         {
934                 vcom_lset(*dst, *src);
935                 ++dst, ++src;
936                 --n;
937         }
938 }
939
940 static void vcom_lcopy(uint8_t *dst, uint8_t *src, int nx, int ny)
941 {
942         if (ny < 0)
943         {
944                 while (ny++ < 0)
945                 {
946                         vcom_lmove(dst, src, nx);
947                         src -= vcom.xbytes;
948                         dst -= vcom.xbytes;
949                 }
950         } else
951         {
952                 while (ny--)
953                 {
954                         vcom_lmove(dst, src, nx);
955                         src += vcom.xbytes;
956                         dst += vcom.xbytes;
957                 }
958         }
959 }
960
961 /* 
962   XXX
963         \82±\82ê\82Í\82 \82­\82Ü\82Å\82»\82Ì\8fê\82µ\82Ì\82¬\82È\82à\82Ì\81B
964         memo:
965                 src\82Ì\83f\81[\83^\82ðbuf\82É\83o\83C\83g\83R\83s\81[\82µ\81Adst\82Ì\90æ\93ª\82\90\82\89\82\98\82\85\82\8c\88Ê\92u\82É\82 \82¤\82æ\82¤\82É\83r\83b\83g\83V\83t\83g\82µ\81A
966                 \90æ\92[\82Æ\8fI\92[\82Ì\83f\81[\83^\82ðdst\82Æ\8d\87\90¬\82µ\82Ä\81A\82»\82ê\82ðdst\82Ölogop\82ð\8dl\97\82µ\82Â\82Â\81A\83o\83C\83g\83R\83s
967                 \81[\82·\82ê\82Î\82¢\82¢\82Ì\82©\81H
968
969                 \82Å\81ASCREEN8\82Ì\8e\9e\82â\81Asrc\82Ædst\82Ìpixel\88Ê\92u\82ª\93¯\82\82È\82ç\81A\83V\83t\83g\8f\88\97\9d\82ð\82µ\82È\82¢\82æ\82¤
970                 \82É\82·\82é\81A\82Æ\81B
971
972                 \83R\83X\83g\82Í\82©\82©\82é\82¯\82Ç\81A1pix\82¸\82Â\82¿\82Ü\82¿\82Ü\83R\83s\81[\82·\82é\82æ\82è\82©\82Í\91¬\82»\82¤\82È\8bC\82ª\82·\82é\81B
973
974                 \82»\82Ì\8fê\8d\87 vcom_lset \82É\82à\8eè\92¼\82µ\82ª\95K\97v\82É\82È\82é\82Æ(T\95t\82«\98_\97\9d\89\89\8eZ\95\94\95ª)\81B
975                 \82¾\82¯\82Ç memmove \82Ì\8c\8f\82Ì\82æ\82¤\82É\81A\88ê\92Ubuf\82É\83Z\81[\83u\82·\82é\82Æ\81AVRAM\89ó\82µ\82¿\82á\82¤\82©\82à\81B
976
977                 \82Æ\82·\82é\82Æ\81c\89º\82Ý\82½\82¢\82É\82¿\82Ü\82¿\82Ü\83R\83s\81[\82µ\82Ä\82­\82µ\82©\82È\82¢\82Ì\82©\82È\82\9f\81c
978 */
979 #ifdef YAN_V99X8_TEST
980 static void vcom_lbcopy(int sx, int sy, int dx, int dy, int nx, int ny)
981 {
982         int osx, odx, onx;
983
984         nx <<= vcom.xshift;
985         osx = sx;
986         odx = dx;
987         onx = nx;
988
989         if (ny < 0)
990         {
991                 while (ny++ < 0)
992                 {
993                         while (nx-- > -1)
994                         {
995                                 vcom_lpset(dx, dy, (int)vcom_point(sx, sy));
996                                 sx++;
997                                 dx++;
998                         }
999                         sy--;
1000                         dy--;
1001                         sx = osx;
1002                         dx = odx;
1003                         nx = onx;
1004                 }
1005         } else
1006         {
1007                 while (ny--)
1008                 {
1009                         while (nx-- > -1)
1010                         {
1011                                 vcom_lpset(dx, dy, (int)vcom_point(sx, sy));
1012                                 sx++;
1013                                 dx++;
1014                         }
1015                         sy++;
1016                         dy++;
1017                         sx = osx;
1018                         dx = odx;
1019                         nx = onx;
1020                 }
1021         }
1022 }
1023 #endif /* YAN_V99X8_TEST */
1024
1025
1026 void vcom_lputc(int m)  /* XXX \8d\95û\8cü\81A\8fã\95û\8cü\82Ì\83e\83X\83g\82Í\82µ\82Ä\82Ü\82¹\82ñ */
1027 {
1028         uint8_t *dst;
1029         int dot;
1030
1031         dst = vcom_vram(r44.x, r44.y);
1032
1033 #if 1   /* XXX */
1034         {
1035                 int pixn;
1036
1037                 m &= pixmask.mask;
1038                 pixn = r44.x & pixmask.xmask;
1039                 dot = (*dst >> ((1 - pixn) * pixmask.npix)) & pixmask.mask;
1040                 vcom_lset(dot, m);
1041                 *dst = (*dst & pixmask.pmask[pixn]) | (dot << pixmask.lshift[pixn]);
1042         }
1043 #else
1044         switch (v99x8.scr)
1045         {
1046         case V99X8_SCREEN_5:
1047         case V99X8_SCREEN_7:
1048                 m &= 0x0f;
1049                 dot = (*dst >> ((1 - (r44.x & 1)) * 4)) & 0x0f;
1050                 vcom_lset(dot, m);
1051                 if ((r44.x & 1) == 0)
1052                         *dst = (*dst & 0x0f) | (dot << 4);
1053                 else
1054                         *dst = (*dst & 0xf0) | dot;
1055                 break;
1056
1057         case V99X8_SCREEN_6:
1058                 m &= 0x03;
1059                 dot = (*dst >> ((1 - (r44.x & 3)) * 2)) & 0x03;
1060                 vcom_lset(dot, m);
1061                 switch (r44.x & 0x03)
1062                 {
1063                 case 0:
1064                         *dst = (*dst & 0x3f) | (dot << 6);
1065                         break;
1066                 case 1:
1067                         *dst = (*dst & 0xcf) | (dot << 4);
1068                         break;
1069                 case 2:
1070                         *dst = (*dst & 0xf3) | (dot << 2);
1071                         break;
1072                 case 3:
1073                         *dst = (*dst & 0xfc) | dot;
1074                 }
1075                 break;
1076
1077         case V99X8_SCREEN_8:
1078                 vcom_lset(*dst, m & 0xff);
1079                 break;
1080
1081         }
1082 #endif
1083
1084         if (r44.sx <= r44.ex)
1085         {
1086                 if (++r44.x >= r44.ex)
1087                 {
1088                         r44.x = r44.sx;
1089                         if (r44.sy < r44.ey)
1090                         {
1091                                 if (++r44.y >= r44.ey)
1092                                         v99x8.status[2] &= ~0x01;
1093                         } else
1094                         {
1095                                 if (--r44.y < r44.ey)
1096                                         v99x8.status[2] &= ~0x01;
1097                         }
1098                 }
1099         } else
1100         {
1101                 if (--r44.x < r44.ex)
1102                 {
1103                         r44.x = r44.sx;
1104                         if (r44.sy <= r44.ey)
1105                         {
1106                                 if (++r44.y > r44.ey)
1107                                         v99x8.status[2] &= ~0x01;
1108                         } else
1109                         {
1110                                 if (--r44.y < r44.ey)
1111                                         v99x8.status[2] &= ~0x01;
1112                         }
1113                 }
1114         }
1115 }
1116
1117
1118 void vcom_hputc(int m) /* XXX \8d\95û\8cü\81A\8fã\95û\8cü\82Ì\83e\83X\83g\82Í\82µ\82Ä\82Ü\82¹\82ñ */
1119 {
1120         *vcom_vram(r44.x, r44.y) = m;
1121
1122         if (r44.sx <= r44.ex)
1123         {
1124                 r44.x += 1 << vcom.xshift;
1125
1126                 if (r44.x >= r44.ex)
1127                 {
1128                         r44.x = r44.sx;
1129                         if (r44.sy <= r44.ey)
1130                         {
1131                                 if ((++r44.y) >= r44.ey)
1132                                         v99x8.status[2] &= ~0x01;
1133                         } else
1134                         {
1135                                 if ((--r44.y) <= r44.ey)
1136                                         v99x8.status[2] &= ~0x01;
1137                         }
1138                 }
1139         } else
1140         {
1141                 r44.x -= 1 << vcom.xshift;
1142
1143                 if (r44.x <= r44.ex)
1144                 {
1145                         r44.x = r44.sx;
1146                         if (r44.sy <= r44.ey)
1147                         {
1148                                 if ((++r44.y) >= r44.ey)
1149                                         v99x8.status[2] &= ~0x01;
1150                         } else
1151                         {
1152                                 if ((--r44.y) <= r44.ey)
1153                                         v99x8.status[2] &= ~0x01;
1154                         }
1155                 }
1156         }
1157 }
1158
1159
1160 void v99x8_cputovdp(int m)
1161 {
1162         if ((v99x8.status[2] & 0x01) == 0)
1163                 return;
1164
1165         switch(v99x8.ctrl[46] >> 4)
1166         {
1167         case 0xb:
1168                 vcom_lputc(m);
1169                 break;
1170         case 0xf:
1171                 vcom_hputc(m);
1172                 break;
1173         }
1174 }
1175
1176 static void lmmc(void)
1177 {
1178         vcom_getdx();
1179         vcom_getdy();
1180         vcom_getnx();
1181         vcom_getny();
1182
1183
1184         r44.sx = r44.x = vcom.dx;
1185         r44.sy = r44.y = vcom.dy;
1186         r44.ex = vcom.dx + vcom.nx;
1187         r44.ey = vcom.dy + vcom.ny;
1188
1189         vcom_lputc(v99x8.ctrl[44]);
1190 }
1191
1192
1193 static void lmcm(void);
1194
1195 static void stop(void);
1196
1197
1198 static void vcom_lpset(int x,int y, int clr)
1199 {
1200         uint8_t *dst;
1201         int src_dot, dst_dot;
1202
1203         dst = vcom_vram(x, y);
1204
1205 #if 1   /* XXX */
1206         {
1207                 int pixn;
1208
1209                 pixn = x & pixmask.xmask;
1210                 src_dot = clr & pixmask.mask;
1211                 dst_dot = (*dst >> pixmask.rshift[pixn]) & pixmask.mask;
1212                 vcom_lset(dst_dot, src_dot);
1213                 *dst = (*dst & pixmask.pmask[pixn]) | (dst_dot << pixmask.lshift[pixn]);
1214         }
1215 #else
1216         switch(v99x8.scr)
1217         {
1218         case V99X8_SCREEN_5:
1219         case V99X8_SCREEN_7:
1220                 src_dot = clr & 0x0f;
1221                 dst_dot = (*dst >> ((1 - (x & 1)) * 4)) & 0x0f;
1222                 vcom_lset(dst_dot, src_dot);
1223                 if ((x & 1) == 0)
1224                         *dst = (*dst & 0x0f) | (dst_dot << 4);
1225                 else
1226                         *dst = (*dst & 0xf0) | dst_dot;
1227                 break;
1228
1229         case V99X8_SCREEN_6:
1230                 src_dot = clr & 0x03;
1231                 dst_dot = (*dst >> ((1 - (r44.x & 3)) * 2)) & 0x03;
1232                 vcom_lset(dst_dot, src_dot);
1233                 switch(x & 0x03)
1234                 {
1235                 case 0:
1236                         *dst = (*dst & 0x3f) | (src_dot << 6);
1237                         break;
1238                 case 1:
1239                         *dst = (*dst & 0xcf) | (src_dot << 4);
1240                         break;
1241                 case 2:
1242                         *dst = (*dst & 0xf3) | (src_dot << 2);
1243                         break;
1244                 case 3:
1245                         *dst = (*dst & 0xfc) | src_dot;
1246                 }
1247                 break;
1248
1249         case V99X8_SCREEN_8:
1250                 vcom_lset(*dst, clr & 0xff);
1251                 break;
1252         }
1253 #endif
1254 }
1255
1256
1257 static void line(void)
1258 {
1259         int i, j, x, y;
1260         int maj, min;
1261
1262         vcom_getdx();
1263         vcom_getdy();
1264         maj = (v99x8.ctrl[40] + (v99x8.ctrl[41] << 8)) & 1023;
1265         min = (v99x8.ctrl[42] + (v99x8.ctrl[43] << 8)) & 511;
1266
1267         /* XXX */
1268         maj = (maj == 0) ? (1) : (maj);
1269
1270         for (i = 0; i <= maj; i++)
1271         {
1272                 j = (i * min) / maj;
1273                 if (v99x8.ctrl[45] & 0x01)
1274                 {
1275                         y = vcom.dy + ((v99x8.ctrl[45] & 0x08) ? -i : i);
1276                         x = vcom.dx + ((v99x8.ctrl[45] & 0x04) ? -j : j);
1277                 } else
1278                 {
1279                         x = vcom.dx + ((v99x8.ctrl[45] & 0x04) ? -i : i);
1280                         y = vcom.dy + ((v99x8.ctrl[45] & 0x08) ? -j : j);
1281                 }
1282                 vcom_lpset(x, y, v99x8.ctrl[44]);
1283         }
1284 }
1285
1286 static uint8_t vcom_point(int x, int y)
1287 {
1288         uint8_t clr = *vcom_vram(x, y);
1289
1290 #if 1   /* XXX */
1291         {
1292                 int pixn;
1293
1294                 pixn = x & pixmask.xmask;
1295                 clr = (clr >> pixmask.rshift[pixn]) & pixmask.mask;
1296         }
1297 #else
1298         switch (v99x8.scr)
1299         {
1300         case V99X8_SCREEN_5:
1301         case V99X8_SCREEN_7:
1302                 clr = (clr >> (4 * (x & 1))) & 0x0F;
1303                 break;
1304         case V99X8_SCREEN_6:
1305                 clr = (clr >> (2 * (x & 3))) & 0x03;
1306                 break;
1307         }
1308 #endif
1309
1310         return clr;
1311 }
1312
1313 static void srch(void)
1314 {
1315         int i;
1316
1317         vcom_getsx();
1318         vcom_getsy();
1319
1320         i = 0;
1321         v99x8.status[2] &= ~0x10;
1322         while ((0 <= (vcom.sx + i)) && ((vcom.sx + i) <= vcom.xmask))
1323         {
1324                 uint8_t clr = vcom_point(vcom.sx + i, vcom.sy);
1325                 if (v99x8.ctrl[45] & 0x02)
1326                 {
1327                         if (clr != v99x8.ctrl[44])
1328                         {
1329                                 v99x8.status[2] |= 0x10;
1330                                 break;
1331                         }
1332                 } else
1333                 {
1334                         if (clr == v99x8.ctrl[44])
1335                         {
1336                                 v99x8.status[2] |= 0x10;
1337                                 break;
1338                         }
1339                 }
1340                 i = (v99x8.ctrl[45] & 0x04) ? (i - 1) : (i + 1);
1341         }
1342
1343         if (v99x8.status[2] & 0x10)
1344         {
1345                 v99x8.status[8] = (vcom.sx + i) & 0xff;
1346                 v99x8.status[9] = (((vcom.sx + i) >> 8) & 0x03) | 0xfc;
1347         }
1348 }
1349
1350
1351 static void pset(void)
1352 {
1353         vcom_getdx();
1354         vcom_getdy();
1355         vcom_lpset(vcom.dx, vcom.dy, v99x8.ctrl[44]);
1356 }
1357
1358
1359 static void point(void)
1360 {
1361         vcom_getsx();
1362         vcom_getsy();
1363         v99x8.status[7] = vcom_point(vcom.sx, vcom.sy);
1364 }
1365
1366 static void hmmc(void)
1367 {
1368         vcom_getdx();
1369         vcom_getdy();
1370         vcom_getnx();
1371         vcom_getny();
1372
1373
1374         r44.sx = r44.x = vcom.dx & ~1;
1375         r44.sy = r44.y = vcom.dy;
1376         r44.ex = (vcom.dx + vcom.nx) & ~1;
1377         r44.ey = vcom.dy + vcom.ny;
1378         r44.xsize = vcom.nx & ~1;
1379
1380         vcom_hputc(v99x8.ctrl[44]);
1381 }
1382
1383 static void lmmm(void)
1384 {
1385         int n;
1386
1387         vcom_getsx();
1388         vcom_getsy();
1389         vcom_getdx();
1390         vcom_getdy();
1391         vcom_getnx();
1392         vcom_getny();
1393
1394 /* printf("hmmm: (%d,%d)->(%d,%d) *(%d,%d)\n", vcom.sx, vcom.sy, vcom.dx, vcom.dy, vcom.nx, vcom.ny); */
1395         n = vcom_canonaddr();
1396 #if YAN_V99X8_TEST      /* XXX */
1397         vcom_lbcopy(vcom.sx, vcom.sy, vcom.dx, vcom.dy, vcom.nx, n);
1398 #else
1399         vcom_lcopy(vcom.dst, vcom.src, vcom.nx, n);
1400 #endif
1401         vcom_setsy(vcom.sy + n);
1402         vcom_setdy(vcom.dy + n);
1403
1404         if (vcom.ny != abs(n))
1405                 vcom_setny(vcom.ny - abs(n));
1406 }
1407
1408
1409 static void lmmm_(void);
1410
1411
1412 static void vcom_lfill(uint8_t *p, int clr, int n)
1413 {
1414         if (n == 0)     /* \83o\83C\83g\90\94\92P\88Ê\82Å\8f\88\97\9d\82ð\82¨\82±\82È\82¤\82½\82ß */
1415                 n = 1;      /* 1dot\82ª\96³\8e\8b\82³\82ê\82Ä\82µ\82Ü\82¤\91Î\89\9e */
1416
1417         switch(vcom.lop)
1418         {
1419         case 0x8:
1420                 if (clr == 0)
1421                         break;
1422         case 0x0:
1423                 while (n-- > 0)
1424                         *p++ = clr;
1425                 break;
1426
1427         case 0x9:
1428                 if (clr == 0)
1429                         break;
1430         case 0x1:
1431                 while (n-- > 0)
1432                         *p++ &= clr;
1433                 break;
1434
1435         case 0xa:
1436                 if (clr == 0)
1437                         break;
1438         case 0x2:
1439                 while (n-- > 0)
1440                         *p++ |= clr;
1441                 break;
1442
1443         case 0xb:
1444                 if (clr == 0)
1445                         break;
1446         case 0x3:
1447                 while (n-- > 0)
1448                         *p++ ^= clr;
1449                 break;
1450
1451         case 0xc:
1452                 if (clr == 0)
1453                         break;
1454         case 0x4:
1455                 while (n-- > 0)
1456                         *p++ = ~clr;
1457                 break;
1458         }
1459
1460 }
1461
1462 static void lmmv(void)   /* XXX byte \92P\88Ê\82Å\8f\88\97\9d\82µ\82Ä\82é\82Ì\82Í\8eè\94²\82«(^^; */
1463 {
1464         int n, ny, clr;
1465
1466         vcom.sx = 0;
1467         vcom.sy = 0;
1468         vcom_getdx();
1469         vcom_getdy();
1470         vcom_getnx();
1471         vcom_getny();
1472         clr = v99x8.ctrl[44];
1473         switch (vcom.xshift)
1474         {
1475         case 2:
1476                 clr |= clr << 2;
1477         case 1:
1478                 clr |= clr << 4;
1479         }
1480
1481         ny = n = vcom_canonaddr();
1482         if (n < 0)
1483         {
1484                 while (ny++ < 0)
1485                 {
1486                         vcom_lfill(vcom.dst, clr, vcom.nx);
1487                         vcom.dst -= vcom.xbytes;
1488                 }
1489         } else
1490         {
1491                 while (ny--)
1492                 {
1493                         vcom_lfill(vcom.dst, clr, vcom.nx);
1494                         vcom.dst += vcom.xbytes;
1495                 }
1496         }
1497
1498         vcom_setsy(vcom.sy + n);
1499         vcom_setdy(vcom.dy + n);
1500
1501         if (vcom.ny != abs(n))
1502                 vcom_setny(vcom.ny - abs(n));
1503 }
1504
1505
1506 static void lmmv_(void);
1507
1508
1509 void v99x8_command(int m)
1510 {
1511         if (v99x8.mode.xsize == 0) /* XXX */
1512                 return;
1513
1514         vcom.xbytes = v99x8.mode.xsize >> v99x8.mode.xshift;
1515         vcom.xmask  = v99x8.mode.xsize - 1;
1516         vcom.xshift = v99x8.mode.xshift;
1517
1518         vcom.ymask  = v99x8.pages * 0x4000 / vcom.xbytes - 1;
1519         vcom.yshift = getshift(vcom.xbytes - 1);
1520
1521 #if 1   /* XXX */
1522         pixmask = pixmasks[(v99x8.scr - V99X8_SCREEN_5) & 0x03];
1523 #endif
1524
1525         v99x8.status[2] |= 0x01;
1526 #ifdef USE_CMDTIME
1527         cmdtime_set(m);
1528 #endif
1529
1530
1531         vcom.lop = m & 0xf;
1532
1533         switch(m >> 4)
1534         {
1535         case 0xf:       hmmc(); break;
1536         case 0xe:       ymmm(); break;
1537         case 0xd:       hmmm(); break;
1538         case 0xc:       hmmv(); break;
1539         case 0xb:       lmmc(); break;
1540         case 0xa:       lmcm(); break;
1541         case 0x9:       lmmm_(); break;
1542         case 0x8:       lmmv_(); break;
1543         case 0x7:       line(); break;
1544         case 0x6:       srch(); break;
1545         case 0x5:       pset(); break;
1546         case 0x4:       point(); break;
1547         case 0x0:       stop(); break;
1548         }
1549
1550         v99x8.ctrl[46] &= 0x0f;
1551 #ifdef USE_CMDTIME
1552         if (((m >> 4) != 0xb) && ((m >> 4) != 0xf) && (0 == cmdtime_t)) v99x8.status[2] &= ~0x01;
1553         //cmdtime_chk();
1554 #else
1555         if ((m >> 4) != 0xb && (m >> 4) != 0xf)
1556                 v99x8.status[2] &= ~0x01;
1557 #endif
1558 }
1559
1560 // from "v99x8_refresh.c" of Zodiac
1561
1562 /*
1563  * Copyright (c) 2000-2002 SASAKI Shunsuke (eruchan@users.sourceforge.net).
1564  * Copyright (c) 2001-2002 The Zodiac project.
1565  * All rights reserved.
1566  *
1567  * This program is free software; you can redistribute it and/or modify
1568  * it under the terms of the GNU General Public License as published by
1569  * the Free Software Foundation; either version 2 of the License, or
1570  * (at your option) any later version.
1571  *
1572  * This program is distributed in the hope that it will be useful,
1573  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1574  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1575  * GNU General Public License for more details.
1576  *
1577  * You should have received a copy of the GNU General Public License
1578  * along with this program; if not, write to the Free Software
1579  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1580  */
1581
1582 //#include "../../config.h"
1583
1584 #include <stdlib.h>
1585 //#include <string.h>
1586
1587 //#include "../zodiac.h"
1588 #include "v99x8.h"
1589
1590 extern bool f_scr;
1591
1592
1593 #ifdef MD_LITTLE
1594 #       define UINT32_FROM16(n1, n2) ((n2) << 16 | (n1))
1595 #       define UINT8_FROM4(n1, n2) ((n1) << 4 | (n2))
1596 #else
1597 #       define  UINT32_FROM16(n1, n2)   ((n1) << 16 | (n2))
1598 #       define  UINT8_FROM4(n1, n2)     ((n2) << 4 | (n1))
1599 #endif
1600
1601
1602 typedef struct
1603 {
1604         int width, height;
1605         int bpp;
1606
1607 } v99x8_refresh_t;
1608
1609 static v99x8_refresh_t v99x8_refresh;
1610
1611
1612   /* pallete */
1613
1614 typedef struct
1615 {
1616         bool flag;
1617         uint8_t r, g, b;
1618         uint32_t color;
1619 } v99x8_pallete_t;
1620
1621 static v99x8_pallete_t pal[16 + 1];
1622 static uint32_t pal_8[256];
1623 static uint32_t pal_m[256];
1624
1625 static bool f_pal;
1626
1627
1628 void v99x8_pallete_set(uint8_t n, uint8_t r, uint8_t g, uint8_t b)
1629 {
1630         if (n == 0)
1631                 n = 16;
1632
1633         pal[n].r = r * 31 / 7;
1634         pal[n].g = g * 31 / 7;
1635         pal[n].b = b * 31 / 7;
1636         pal[n].flag = TRUE;
1637
1638         f_pal = TRUE;
1639 }
1640
1641 static int col_bg = 0;
1642
1643 static void v99x8_pallete_update(void)
1644 {
1645         int a;
1646         int i, j;
1647
1648         if (f_pal)
1649                 for (i = 1; i < 17; ++i)
1650                         if (pal[i].flag)
1651                                 pal[i].color = md_maprgb15(pal[i].r, pal[i].g, pal[i].b);
1652
1653         a = (v99x8.col_bg == 0 || (v99x8.ctrl[8] & 0x20)) ? 16 : v99x8.col_bg;
1654         if (col_bg != a || pal[a].flag)
1655         {
1656                 f_pal = TRUE;
1657                 col_bg = a;
1658                 memcpy(&pal[0], &pal[a], sizeof(v99x8_pallete_t));
1659                 pal[0].flag = TRUE;
1660         }
1661
1662         if (!f_pal)
1663                 return;
1664
1665         if (!v99x8.f_zoom)
1666         {
1667                 for (i = 0; i < 16; ++i)
1668                 {
1669                         for (j = 0; j < 16; ++j)
1670                         {
1671                                 if (!pal[i].flag && !pal[j].flag)
1672                                         continue;
1673
1674                                 a = UINT8_FROM4(i, j);
1675
1676                                 if (i == j)
1677                                 {
1678                                         pal_m[a] = pal[i].color;
1679                                 } else
1680                                 {
1681                                         pal_m[a] = md_maprgb15((pal[i].r >> 1) + (pal[j].r >> 1),
1682                                                                (pal[i].g >> 1) + (pal[j].g >> 1),
1683                                                                (pal[i].b >> 1) + (pal[j].b >> 1));
1684                                 }
1685                         }
1686                 }
1687         }
1688         f_pal = FALSE;
1689         for (i = 0; i < 17; ++i)
1690                 pal[i].flag = FALSE;
1691 }
1692
1693 static void v99x8_pallete_init(void)
1694 {
1695         static const uint8_t inipal[16][3] =
1696         {
1697                 {0, 0, 0}, {0, 0, 0}, {1, 6, 1}, {3, 7, 3}, 
1698                 {1, 1, 7}, {2, 3, 7}, {5, 1, 1}, {2, 6, 7}, 
1699                 {7, 1, 1}, {7, 3, 3}, {6, 6, 1}, {6, 6, 4}, 
1700                 {1, 4, 1}, {6, 2, 5}, {5, 5, 5}, {7, 7, 7}
1701         };
1702
1703         uint32_t pal_black;
1704         int i;
1705
1706         memset(pal, 0, sizeof(pal));
1707
1708         pal_black = md_maprgb15(0, 0, 0);
1709         for (i = 0; i < 256; ++i)
1710         {
1711                      /* GGGRRRBB */
1712                 /* i & 0x1c, (i >> 3) & 0x1c, (i & 3) << 3); */
1713                 pal_8[i] = md_maprgb15((i & 0x1c) * 31 / (7 << 2),
1714                                        (i & 0xe0) * 31 / (7 << 5),
1715                                        (i & 3) * 31 / 3);
1716                 pal_m[i] = pal_black;
1717         }
1718
1719         for(i = 0; i < 16; i++)
1720                 v99x8_pallete_set(i, inipal[i][0], inipal[i][1], inipal[i][2]);
1721 }
1722
1723
1724
1725
1726 #define V99X8_WIDTH  (256 + 15)
1727 #define V99X8_HEIGHT (212 + 15)
1728
1729
1730 static uint8_t tbl_yjk_b[32 * 64 * 64], tbl_yjk_rg[62 + 32];
1731 static uint8_t blackbuf[256];      /* sprite \94ñ\95\\8e¦\97p\83o\83b\83t\83@ */
1732
1733
1734 void v99x8_refresh_init(void)
1735 {
1736         int i;
1737         md_video_mode_t mode;
1738
1739         v99x8_refresh.width  = V99X8_WIDTH;
1740         v99x8_refresh.height = V99X8_HEIGHT;
1741
1742         if (v99x8.f_zoom)
1743         {
1744                 v99x8_refresh.width *= 2;
1745                 v99x8_refresh.height *= 2;
1746         }
1747
1748         mode.width  = v99x8_refresh.width;
1749         mode.height = v99x8_refresh.height;
1750
1751 #ifdef  MD_BPP
1752         mode.bpp = v99x8_refresh.bpp = MD_BPP;
1753 #else
1754         mode.bpp = v99x8_refresh.bpp = 16;
1755 #endif
1756
1757         mode.option     = md_video_defaultopt();
1758
1759 #if 0
1760         md_video_fixmode(&mode);
1761         if (!md_video_setmode(v99x8_refresh.width, v99x8_refresh.height, &mode, NULL))
1762                 exit(EXIT_FAILURE);
1763
1764         v99x8_refresh.bpp = md_video_bpp();
1765 #endif
1766
1767         v99x8_pallete_init();
1768
1769         for (i = 0; i < 32; ++i)
1770         {
1771                 int     n;
1772
1773                 int     j;
1774                 for (j = 0; j < 64; ++j)
1775                 {
1776                         int     k;
1777                         for (k = 0; k < 64; ++k)
1778                         {
1779                                 n = (i * 5 - ((j & 0x20) ? j - 64 : j) * 2
1780                                      - ((k & 0x20) ? k - 64 : k)) >> 2;
1781                                 if (n > 31)
1782                                         n = 31;
1783                                 if (n < 0)
1784                                         n = 0;
1785
1786                                 tbl_yjk_b[(((j + 32) & 63) << 11)
1787                                     + (((k + 32) & 63) << 5) + i] = n;
1788                         }
1789                 }
1790
1791                 tbl_yjk_rg[i] = 0;
1792                 tbl_yjk_rg[i + 32] = i;
1793                 tbl_yjk_rg[i + 64] = 31;
1794         }
1795
1796 /*
1797 y5:k3 (low)
1798 y5:k3 (high)
1799 y5:j3 
1800 y5:j3 
1801
1802 r: y + j
1803 g: y + k
1804 b: (5Y + 2J + K) >> 2
1805 */
1806         memset(blackbuf, 0, sizeof(blackbuf));
1807 }
1808
1809 void V99X8::v99x8_refresh_screen(void)
1810 {
1811         md_video_update(0, NULL);
1812 }
1813
1814 void V99X8::v99x8_refresh_clear(void)
1815 {
1816         md_video_fill(0, 0, v99x8_refresh.width, v99x8_refresh.height, pal[v99x8.col_bg].color);
1817 }
1818
1819 uint8_t *V99X8::v99x8_refresh_start(int x, int w, int h)
1820 {
1821         int a;
1822
1823         v99x8_pallete_update();
1824
1825         a = v99x8.f_zoom ? 2 : 1;
1826
1827         return md_video_lockline((((7 - v99x8.ctrl[18]) & 0x0f) + x) * a
1828                                  , v99x8.scanline * a
1829                                  , w * a, h * a);
1830 }
1831
1832 static __inline__ void v99x8_refresh_stop(void)
1833 {
1834         md_video_unlockline();
1835 }
1836
1837
1838 #ifdef MD_BPP
1839
1840 #       if MD_BPP != 2
1841
1842 #               define pixel_put(pb, n, px) *((md_pixel_t *)(pb) + (n)) = (px)
1843
1844 #       else
1845
1846 /*
1847
1848 #               ifdef MD_LITTLE
1849 #                       define pixel_put(pb, n, px) *((uint8_t *)(pb) + (n) / 4)  \
1850                                                       |= (px) << ((3 - (n)) * 2)
1851 #               else
1852 #                       define pixel_put(pb, n, px) *((uint8_t *)(pb) + (n) / 4)  \
1853                                                       |= (px) << ((n) * 2)
1854 #               endif
1855
1856 */
1857
1858 #       endif
1859
1860 #else
1861 static __inline__ void pixel_put(void *pb, int n, uint32_t p1)
1862 {
1863         uint8_t *p;
1864         int mask, pix2bpp;
1865
1866         switch (v99x8_refresh.bpp)
1867         {
1868         case 16:
1869                 *((uint16_t *)pb + n) = p1;
1870                 break;
1871         case 8:
1872                 *((uint8_t *)pb + n) = p1;
1873                 break;
1874         case 32:
1875                 *((uint32_t *)pb + n) = p1;
1876                 break;
1877         case 2:
1878                 p = (uint8_t *)pb + (n >> 2);
1879 #ifdef MD_LITTLE
1880                 mask = 0xc0 >> ((n & 3) * 2);
1881                 pix2bpp = p1 << (6 - ((n & 3) * 2));
1882 #else
1883                 mask = 0x03 << ((n & 3) * 2);
1884                 pix2bpp = p1 << ((n & 3) * 2);
1885
1886 #endif
1887                 *p = (*p & ~mask) | (pix2bpp & mask);
1888                 break;
1889
1890 /* XXX 2bpp \91Î\89\9e\95û\96@
1891  *
1892  *  1. \82Ü\82¸\91Î\89\9e\82·\82é 2bit \82ð & \82Å 0 \83N\83\8a\83A\82·\82é
1893  *  2. \8e\9f\82É\81A2bit \82ð | \82Å\89Á\82¦\82é
1894  *
1895  * \82Æ\82¢\82¤\8eè\8f\87\82ª\95K\97v\81B\91Î\89\9e\82Í\8cã\93ú\82É\82Ä.... --\82k
1896  */
1897
1898         }
1899 }
1900 #endif
1901
1902
1903
1904
1905 static uint8_t sbuf[32 + 256 + 16];
1906
1907 typedef struct
1908 {
1909         uint8_t y;
1910         uint8_t x;
1911         uint8_t n;
1912         uint8_t a;
1913 } v99x8_sprite_t;
1914
1915
1916
1917 static uint8_t *v99x8_refresh_sprite1(uint8_t y)
1918 {
1919         v99x8_sprite_t *ptr_a;
1920         int n, size;
1921         int i;
1922         uint8_t a, c, *ptr_g, *ptr_s, *tbl_sp;
1923         bool cf;
1924
1925 /*      if (v99x8.ctrl[8] & 0x02)
1926                 return blackbuf; */
1927
1928 /*      tbl_sp = &v99x8.vram[(int)v99x8.ctrl[6] << 11]; */
1929         tbl_sp = v99x8.vram + ((int)v99x8.ctrl[6] << 11);
1930
1931         memset(sbuf + 32, 0, 256);
1932
1933         size = (v99x8.ctrl[1] & 0x02) ? 16 : 8;
1934 /*      if (SpritesMAG)
1935                 h *= 2; */
1936
1937         n = 0;
1938         cf = FALSE;
1939         ptr_a = (v99x8_sprite_t *)(v99x8.vram + ((int)v99x8.ctrl[11] << 15)
1940                                                   + ((int)v99x8.ctrl[5] << 7));
1941
1942         for (i = 0 ;; ++i, ++ptr_a)
1943         {
1944                 if (i >= 32 || n >= 4 || ptr_a->y == 208)
1945                         break;
1946
1947                 a = (uint8_t)(ptr_a->y - v99x8.ctrl[23]); /* a>256-h? a-=256 */
1948                 if (a >=y || a + size < y)
1949                         continue;
1950
1951                 ++n;
1952                 a = y - (a + 1);
1953
1954                 c = ptr_a->a;
1955                 ptr_s = sbuf + ptr_a->x + ((c & 0x80) ? 0 : 32);
1956                 ptr_g = tbl_sp + a
1957                 + (((v99x8.ctrl[1] & 0x02) ? ptr_a->n & 0xfc : ptr_a->n) << 3);
1958
1959 /*              cf = TRUE; */
1960                 c &= 0x0f;
1961
1962                 if (ptr_s[0] == 0 && (*ptr_g & 0x80))   ptr_s[0] = c;
1963                 if (ptr_s[1] == 0 && (*ptr_g & 0x40))   ptr_s[1] = c;
1964                 if (ptr_s[2] == 0 && (*ptr_g & 0x20))   ptr_s[2] = c;
1965                 if (ptr_s[3] == 0 && (*ptr_g & 0x10))   ptr_s[3] = c;
1966                 if (ptr_s[4] == 0 && (*ptr_g & 0x08))   ptr_s[4] = c;
1967                 if (ptr_s[5] == 0 && (*ptr_g & 0x04))   ptr_s[5] = c;
1968                 if (ptr_s[6] == 0 && (*ptr_g & 0x02))   ptr_s[6] = c;
1969                 if (ptr_s[7] == 0 && (*ptr_g & 0x01))   ptr_s[7] = c;
1970
1971                 if (!(v99x8.ctrl[1] & 0x02))
1972                         continue;
1973
1974                 ptr_s += 8;
1975                 ptr_g += 16;
1976
1977                 if (ptr_s[0] == 0 && (*ptr_g & 0x80))   ptr_s[0] = c;
1978                 if (ptr_s[1] == 0 && (*ptr_g & 0x40))   ptr_s[1] = c;
1979                 if (ptr_s[2] == 0 && (*ptr_g & 0x20))   ptr_s[2] = c;
1980                 if (ptr_s[3] == 0 && (*ptr_g & 0x10))   ptr_s[3] = c;
1981                 if (ptr_s[4] == 0 && (*ptr_g & 0x08))   ptr_s[4] = c;
1982                 if (ptr_s[5] == 0 && (*ptr_g & 0x04))   ptr_s[5] = c;
1983                 if (ptr_s[6] == 0 && (*ptr_g & 0x02))   ptr_s[6] = c;
1984                 if (ptr_s[7] == 0 && (*ptr_g & 0x01))   ptr_s[7] = c;
1985         }
1986         return sbuf + 32;
1987 }
1988
1989
1990 static uint8_t *v99x8_refresh_sprite2(uint8_t y)
1991 {
1992         v99x8_sprite_t *ptr_a;
1993         int n, size;
1994         int i;
1995         uint8_t a, c, *ptr_g, *ptr_c, *ptr_s, *tbl_sp;
1996         bool cf;
1997
1998         if (v99x8.ctrl[8] & 0x02)
1999                 return blackbuf;
2000
2001         tbl_sp = v99x8.vram + ((int)v99x8.ctrl[6] << 11);
2002
2003         memset(sbuf + 32, 0, 256);
2004
2005         size = (v99x8.ctrl[1] & 0x02) ? 16 : 8;
2006 /*      if (SpritesMAG)
2007                 h *= 2; */
2008
2009         n = 0;
2010         cf = FALSE;
2011
2012         ptr_c = v99x8.vram + ((int)v99x8.ctrl[11] << 15)
2013                                + ((int)(v99x8.ctrl[5] & 0xf8) << 7);
2014         ptr_a = (v99x8_sprite_t *)(ptr_c + 0x200);
2015
2016         for (i = 0 ;; ++i, ++ptr_a, ptr_c += 16)
2017         {
2018                 if (i >= 32 || n >= 8 || ptr_a->y == 216)
2019                         break;
2020
2021                 a = (uint8_t)(ptr_a->y - v99x8.ctrl[23]); /* a>256-h? a-=256 */
2022                 if (a >= y || a + size < y)
2023                         continue;
2024
2025                 ++n;
2026                 a = y - (a + 1);
2027
2028                 c = ptr_c[a];
2029                 ptr_s = sbuf + ptr_a->x + ((c & 0x80) ? 0 : 32);
2030                 ptr_g = tbl_sp + a
2031                         + (((v99x8.ctrl[1] & 0x02) ? ptr_a->n & 0xfc : ptr_a->n) << 3);
2032
2033                 if ((c & 0x40) == 0)
2034                 {
2035                         cf = TRUE;
2036                         c &= 0x0f;
2037
2038                         if (ptr_s[0] == 0 && (*ptr_g & 0x80))   ptr_s[0] = c;
2039                         if (ptr_s[1] == 0 && (*ptr_g & 0x40))   ptr_s[1] = c;
2040                         if (ptr_s[2] == 0 && (*ptr_g & 0x20))   ptr_s[2] = c;
2041                         if (ptr_s[3] == 0 && (*ptr_g & 0x10))   ptr_s[3] = c;
2042                         if (ptr_s[4] == 0 && (*ptr_g & 0x08))   ptr_s[4] = c;
2043                         if (ptr_s[5] == 0 && (*ptr_g & 0x04))   ptr_s[5] = c;
2044                         if (ptr_s[6] == 0 && (*ptr_g & 0x02))   ptr_s[6] = c;
2045                         if (ptr_s[7] == 0 && (*ptr_g & 0x01))   ptr_s[7] = c;
2046
2047                         if (!(v99x8.ctrl[1] & 0x02))
2048                                 continue;
2049
2050                         ptr_s += 8; ptr_g += 16;
2051                         if (ptr_s[0] == 0 && (*ptr_g & 0x80))   ptr_s[0] = c;
2052                         if (ptr_s[1] == 0 && (*ptr_g & 0x40))   ptr_s[1] = c;
2053                         if (ptr_s[2] == 0 && (*ptr_g & 0x20))   ptr_s[2] = c;
2054                         if (ptr_s[3] == 0 && (*ptr_g & 0x10))   ptr_s[3] = c;
2055                         if (ptr_s[4] == 0 && (*ptr_g & 0x08))   ptr_s[4] = c;
2056                         if (ptr_s[5] == 0 && (*ptr_g & 0x04))   ptr_s[5] = c;
2057                         if (ptr_s[6] == 0 && (*ptr_g & 0x02))   ptr_s[6] = c;
2058                         if (ptr_s[7] == 0 && (*ptr_g & 0x01))   ptr_s[7] = c;
2059                 } else
2060                 {
2061                         if (!cf)
2062                                 continue;
2063
2064                         c &= 0x0f;
2065                         if (*ptr_g & 0x80)      ptr_s[0] |= c;
2066                         if (*ptr_g & 0x40)      ptr_s[1] |= c;
2067                         if (*ptr_g & 0x20)      ptr_s[2] |= c;
2068                         if (*ptr_g & 0x10)      ptr_s[3] |= c;
2069                         if (*ptr_g & 0x08)      ptr_s[4] |= c;
2070                         if (*ptr_g & 0x04)      ptr_s[5] |= c;
2071                         if (*ptr_g & 0x02)      ptr_s[6] |= c;
2072                         if (*ptr_g & 0x01)      ptr_s[7] |= c;
2073
2074                         if (!(v99x8.ctrl[1] & 0x02))
2075                                 continue;
2076
2077                         ptr_s += 8; ptr_g += 16;
2078                         if (*ptr_g & 0x80)      ptr_s[0] |= c;
2079                         if (*ptr_g & 0x40)      ptr_s[1] |= c;
2080                         if (*ptr_g & 0x20)      ptr_s[2] |= c;
2081                         if (*ptr_g & 0x10)      ptr_s[3] |= c;
2082                         if (*ptr_g & 0x08)      ptr_s[4] |= c;
2083                         if (*ptr_g & 0x04)      ptr_s[5] |= c;
2084                         if (*ptr_g & 0x02)      ptr_s[6] |= c;
2085                         if (*ptr_g & 0x01)      ptr_s[7] |= c;
2086                 }
2087         }
2088         return sbuf + 32;
2089 }
2090
2091
2092
2093 void V99X8::v99x8_refresh_sc0(int y, int h)
2094 {
2095         uint8_t *pbuf;
2096         uint32_t fg, bg;
2097         int pp;
2098
2099
2100         if (f_scr)
2101         {
2102                 v99x8.tbl_pg = v99x8.vram + (((int)v99x8.ctrl[4] & 0x3f) << 11);
2103                 v99x8.tbl_pn = v99x8.vram + (((int)v99x8.ctrl[2] & 0x7f) << 10);
2104                 f_scr = FALSE;
2105         }
2106
2107         pbuf = v99x8_refresh_start(8, 240, h);
2108         pp = md_video_pitch() - md_video_pixbytes(240);
2109
2110         fg = pal[v99x8.col_fg].color;
2111         bg = pal[v99x8.col_bg].color;
2112
2113         while(h-- > 0)
2114         {
2115                 int i;
2116                 uint8_t *T,*G;
2117
2118                 T = v99x8.tbl_pn + (y >> 3) * 40;
2119                 G = v99x8.tbl_pg + (y & 0x07);
2120                 ++y;
2121
2122                 for (i = 0; i < 40; ++i)
2123                 {
2124                         uint8_t a;
2125
2126                         a = G[(int)*T++ << 3];
2127                         if  (v99x8.f_zoom)
2128                         {
2129                                 pixel_put(pbuf, 0, (a & 0x80)? fg : bg);
2130                                 pixel_put(pbuf, 1, (a & 0x80)? fg : bg);
2131                                 pixel_put(pbuf, 2, (a & 0x40)? fg : bg);
2132                                 pixel_put(pbuf, 3, (a & 0x40)? fg : bg);
2133                                 pixel_put(pbuf, 4, (a & 0x20)? fg : bg);
2134                                 pixel_put(pbuf, 5, (a & 0x20)? fg : bg);
2135                                 pixel_put(pbuf, 6, (a & 0x10)? fg : bg);
2136                                 pixel_put(pbuf, 7, (a & 0x10)? fg : bg);
2137                                 pixel_put(pbuf, 8, (a & 0x08)? fg : bg);
2138                                 pixel_put(pbuf, 9, (a & 0x08)? fg : bg);
2139                                 pixel_put(pbuf, 10, (a & 0x04)? fg : bg);
2140                                 pixel_put(pbuf, 11, (a & 0x04)? fg : bg);
2141                                 pbuf += md_video_pixbytes(12);
2142                         } else
2143                         {
2144                                 pixel_put(pbuf, 0, (a & 0x80)? fg : bg);
2145                                 pixel_put(pbuf, 1, (a & 0x40)? fg : bg);
2146                                 pixel_put(pbuf, 2, (a & 0x20)? fg : bg);
2147                                 pixel_put(pbuf, 3, (a & 0x10)? fg : bg);
2148                                 pixel_put(pbuf, 4, (a & 0x08)? fg : bg);
2149                                 pixel_put(pbuf, 5, (a & 0x04)? fg : bg);
2150                                 pbuf += md_video_pixbytes(6);
2151                         }
2152                 }
2153                 pbuf += pp;
2154         }
2155
2156         v99x8_refresh_stop();
2157 }
2158
2159 void V99X8::v99x8_refresh_sc1(int y, int h)
2160 {
2161         uint8_t *T,*G;
2162         int i, n;
2163         int pp;
2164         uint8_t *pbuf, *sp;
2165
2166         if (f_scr)
2167         {
2168                 v99x8.tbl_pg = v99x8.vram + (((int)v99x8.ctrl[4] & 0x3f) << 11);
2169                 v99x8.tbl_pn = v99x8.vram + (((int)v99x8.ctrl[2] & 0x7f) << 10);
2170                 v99x8.tbl_cl = v99x8.vram + (((int)v99x8.ctrl[10] & 0x07) << 14)
2171                                           + ((int)v99x8.ctrl[3] << 6);
2172                 f_scr = FALSE;
2173         }
2174
2175         pbuf = v99x8_refresh_start(0, 256, h);
2176         pp = md_video_pitch() - md_video_pixbytes(256);
2177
2178         while (h-- > 0)
2179         {
2180                 n = v99x8.ctrl[23] + y;
2181                 G = v99x8.tbl_pg + (n & 0x07);
2182                 T = v99x8.tbl_pn + ((n & 0xF8) << 2);
2183                 sp = v99x8_refresh_sprite1(y++);
2184
2185                 for(i = 0; i < 32; ++i)
2186                 {
2187                         uint8_t a;
2188                         uint8_t n;
2189                         uint32_t fg, bg;
2190
2191                         n = v99x8.tbl_cl[*T >> 3];
2192                         fg = pal[n >> 4].color;
2193                         bg = pal[n & 0x0f].color;
2194
2195                         a = G[(int)*T++ << 3];
2196                         if  (v99x8.f_zoom)
2197                         {
2198                                 pixel_put(pbuf, 0, sp[0] ? pal[sp[0]].color : (a & 0x80) ? fg : bg);
2199                                 pixel_put(pbuf, 1, sp[0] ? pal[sp[0]].color : (a & 0x80) ? fg : bg);
2200                                 pixel_put(pbuf, 2, sp[1] ? pal[sp[1]].color : (a & 0x40) ? fg : bg);
2201                                 pixel_put(pbuf, 3, sp[1] ? pal[sp[1]].color : (a & 0x40) ? fg : bg);
2202                                 pixel_put(pbuf, 4, sp[2] ? pal[sp[2]].color : (a & 0x20) ? fg : bg);
2203                                 pixel_put(pbuf, 5, sp[2] ? pal[sp[2]].color : (a & 0x20) ? fg : bg);
2204                                 pixel_put(pbuf, 6, sp[3] ? pal[sp[3]].color : (a & 0x10) ? fg : bg);
2205                                 pixel_put(pbuf, 7, sp[3] ? pal[sp[3]].color : (a & 0x10) ? fg : bg);
2206                                 pixel_put(pbuf, 8, sp[4] ? pal[sp[4]].color : (a & 0x08) ? fg : bg);
2207                                 pixel_put(pbuf, 9, sp[4] ? pal[sp[4]].color : (a & 0x08) ? fg : bg);
2208                                 pixel_put(pbuf, 10, sp[5] ? pal[sp[5]].color : (a & 0x04) ? fg : bg);
2209                                 pixel_put(pbuf, 11, sp[5] ? pal[sp[5]].color : (a & 0x04) ? fg : bg);
2210                                 pixel_put(pbuf, 12, sp[6] ? pal[sp[6]].color : (a & 0x02) ? fg : bg);
2211                                 pixel_put(pbuf, 13, sp[6] ? pal[sp[6]].color : (a & 0x02) ? fg : bg);
2212                                 pixel_put(pbuf, 14, sp[7] ? pal[sp[7]].color : (a & 0x01) ? fg : bg);
2213                                 pixel_put(pbuf, 15, sp[7] ? pal[sp[7]].color : (a & 0x01) ? fg : bg);
2214                                 pbuf += md_video_pixbytes(16);
2215                                 sp += 8;
2216                         } else
2217                         {
2218                                 pixel_put(pbuf, 0, sp[0] ? pal[sp[0]].color : (a & 0x80) ? fg : bg);
2219                                 pixel_put(pbuf, 1, sp[1] ? pal[sp[1]].color : (a & 0x40) ? fg : bg);
2220                                 pixel_put(pbuf, 2, sp[2] ? pal[sp[2]].color : (a & 0x20) ? fg : bg);
2221                                 pixel_put(pbuf, 3, sp[3] ? pal[sp[3]].color : (a & 0x10) ? fg : bg);
2222                                 pixel_put(pbuf, 4, sp[4] ? pal[sp[4]].color : (a & 0x08) ? fg : bg);
2223                                 pixel_put(pbuf, 5, sp[5] ? pal[sp[5]].color : (a & 0x04) ? fg : bg);
2224                                 pixel_put(pbuf, 6, sp[6] ? pal[sp[6]].color : (a & 0x02) ? fg : bg);
2225                                 pixel_put(pbuf, 7, sp[7] ? pal[sp[7]].color : (a & 0x01) ? fg : bg);
2226
2227                                 pbuf += md_video_pixbytes(8);
2228                                 sp += 8;
2229                         }
2230                 }
2231                 pbuf += pp;
2232         }
2233
2234         v99x8_refresh_stop();
2235 }
2236
2237 void V99X8::v99x8_refresh_sc4(int y, int h)
2238 {
2239         int i;
2240         int n;
2241         uint8_t *T, *PGT, *CLT;
2242         int pp;
2243         uint8_t *pbuf, *sp;
2244
2245         if (f_scr)
2246         {
2247                 v99x8.tbl_pg = v99x8.vram + (((int)v99x8.ctrl[4] & 0x3c) << 11);
2248                 v99x8.tbl_pn = v99x8.vram + (((int)v99x8.ctrl[2] & 0x7f) << 10);
2249                 v99x8.tbl_cl = v99x8.vram + (((int)v99x8.ctrl[10] & 0x07) << 14)
2250                                           + (((int)v99x8.ctrl[3] & 0x80) << 6);
2251                 f_scr = FALSE;
2252         }
2253
2254
2255         pbuf = v99x8_refresh_start(0, 256, h);
2256         pp = md_video_pitch() - md_video_pixbytes(256);
2257
2258         while (h-- > 0)
2259         {
2260                 n = v99x8.ctrl[23] + y;
2261                 T = v99x8.tbl_pn + ((n & 0xf8) << 2);
2262
2263                 n = ((n & 0xc0) << 5) + (n & 0x07);
2264                 PGT = v99x8.tbl_pg + n;
2265                 CLT = v99x8.tbl_cl + n;
2266
2267                 if (v99x8.scr == V99X8_SCREEN_2)
2268                         sp = v99x8_refresh_sprite1(y++);
2269                 else
2270                         sp = v99x8_refresh_sprite2(y++);
2271
2272                 for (i = 0; i < 32; ++i)
2273                 {
2274                         uint8_t a;
2275                         uint8_t n;
2276                         uint32_t fg, bg;
2277
2278                         n = CLT[*T << 3];
2279                         fg = pal[n >> 4].color;
2280                         bg = pal[n & 0x0f].color;
2281
2282                         a = PGT[(int)*T++ << 3];
2283
2284                         if  (v99x8.f_zoom)
2285                         {
2286                                 pixel_put(pbuf, 0, sp[0] ? pal[sp[0]].color : (a & 0x80) ? fg : bg);
2287                                 pixel_put(pbuf, 1, sp[0] ? pal[sp[0]].color : (a & 0x80) ? fg : bg);
2288                                 pixel_put(pbuf, 2, sp[1] ? pal[sp[1]].color : (a & 0x40) ? fg : bg);
2289                                 pixel_put(pbuf, 3, sp[1] ? pal[sp[1]].color : (a & 0x40) ? fg : bg);
2290                                 pixel_put(pbuf, 4, sp[2] ? pal[sp[2]].color : (a & 0x20) ? fg : bg);
2291                                 pixel_put(pbuf, 5, sp[2] ? pal[sp[2]].color : (a & 0x20) ? fg : bg);
2292                                 pixel_put(pbuf, 6, sp[3] ? pal[sp[3]].color : (a & 0x10) ? fg : bg);
2293                                 pixel_put(pbuf, 7, sp[3] ? pal[sp[3]].color : (a & 0x10) ? fg : bg);
2294                                 pixel_put(pbuf, 8, sp[4] ? pal[sp[4]].color : (a & 0x08) ? fg : bg);
2295                                 pixel_put(pbuf, 9, sp[4] ? pal[sp[4]].color : (a & 0x08) ? fg : bg);
2296                                 pixel_put(pbuf, 10, sp[5] ? pal[sp[5]].color : (a & 0x04) ? fg : bg);
2297                                 pixel_put(pbuf, 11, sp[5] ? pal[sp[5]].color : (a & 0x04) ? fg : bg);
2298                                 pixel_put(pbuf, 12, sp[6] ? pal[sp[6]].color : (a & 0x02) ? fg : bg);
2299                                 pixel_put(pbuf, 13, sp[6] ? pal[sp[6]].color : (a & 0x02) ? fg : bg);
2300                                 pixel_put(pbuf, 14, sp[7] ? pal[sp[7]].color : (a & 0x01) ? fg : bg);
2301                                 pixel_put(pbuf, 15, sp[7] ? pal[sp[7]].color : (a & 0x01) ? fg : bg);
2302                                 pbuf += md_video_pixbytes(16); sp += 8;
2303                         } else
2304                         {
2305                                 pixel_put(pbuf, 0, sp[0] ? pal[sp[0]].color : (a & 0x80)? fg : bg);
2306                                 pixel_put(pbuf, 1, sp[1] ? pal[sp[1]].color : (a & 0x40)? fg : bg);
2307                                 pixel_put(pbuf, 2, sp[2] ? pal[sp[2]].color : (a & 0x20)? fg : bg);
2308                                 pixel_put(pbuf, 3, sp[3] ? pal[sp[3]].color : (a & 0x10)? fg : bg);
2309                                 pixel_put(pbuf, 4, sp[4] ? pal[sp[4]].color : (a & 0x08)? fg : bg);
2310                                 pixel_put(pbuf, 5, sp[5] ? pal[sp[5]].color : (a & 0x04)? fg : bg);
2311                                 pixel_put(pbuf, 6, sp[6] ? pal[sp[6]].color : (a & 0x02)? fg : bg);
2312                                 pixel_put(pbuf, 7, sp[7] ? pal[sp[7]].color : (a & 0x01)? fg : bg);
2313
2314                                 pbuf += md_video_pixbytes(8); sp += 8;
2315                         }
2316                 }
2317                 pbuf += pp;
2318         }
2319
2320         v99x8_refresh_stop();
2321 }
2322
2323 void V99X8::v99x8_refresh_sc5(int y, int h)
2324 {
2325         int i;
2326         uint8_t *T;
2327         int pp;
2328         uint8_t *pbuf, *sp;
2329
2330         if (f_scr)
2331         {
2332                 v99x8.tbl_pn = v99x8.vram + (((int)v99x8.ctrl[2] & 0x60) << 10);
2333                 f_scr = FALSE;
2334         }
2335
2336         pbuf = v99x8_refresh_start(0, 256, h);
2337         pp = md_video_pitch() - md_video_pixbytes(256);
2338
2339         T = v99x8.tbl_pn + (((y + v99x8.ctrl[23]) & 0xff) << 7);
2340
2341         while(h-- > 0)
2342         {
2343                 sp = v99x8_refresh_sprite2(y++);
2344                 for (i = 0; i < 32; ++i)
2345                 {
2346                         if  (v99x8.f_zoom)
2347                         {
2348                                 pixel_put(pbuf, 0, pal[sp[0] ? sp[0] : T[0] >> 4].color);
2349                                 pixel_put(pbuf, 1, pal[sp[0] ? sp[0] : T[0] >> 4].color);
2350                                 pixel_put(pbuf, 2, pal[sp[1] ? sp[1] : T[0] & 0x0f].color);
2351                                 pixel_put(pbuf, 3, pal[sp[1] ? sp[1] : T[0] & 0x0f].color);
2352                                 pixel_put(pbuf, 4, pal[sp[2] ? sp[2] : T[1] >> 4].color);
2353                                 pixel_put(pbuf, 5, pal[sp[2] ? sp[2] : T[1] >> 4].color);
2354                                 pixel_put(pbuf, 6, pal[sp[3] ? sp[3] : T[1] & 0x0f].color);
2355                                 pixel_put(pbuf, 7, pal[sp[3] ? sp[3] : T[1] & 0x0f].color);
2356                                 pixel_put(pbuf, 8, pal[sp[4] ? sp[4] : T[2] >> 4].color);
2357                                 pixel_put(pbuf, 9, pal[sp[4] ? sp[4] : T[2] >> 4].color);
2358                                 pixel_put(pbuf, 10, pal[sp[5] ? sp[5] : T[2] & 0x0f].color);
2359                                 pixel_put(pbuf, 11, pal[sp[5] ? sp[5] : T[2] & 0x0f].color);
2360                                 pixel_put(pbuf, 12, pal[sp[6] ? sp[6] : T[3] >> 4].color);
2361                                 pixel_put(pbuf, 13, pal[sp[6] ? sp[6] : T[3] >> 4].color);
2362                                 pixel_put(pbuf, 14, pal[sp[7] ? sp[7] : T[3] & 0x0f].color);
2363                                 pixel_put(pbuf, 15, pal[sp[7] ? sp[7] : T[3] & 0x0f].color);
2364
2365                                 pbuf += md_video_pixbytes(16); T += 4; sp += 8;
2366                         } else {
2367                                 pixel_put(pbuf, 0, pal[sp[0] ? sp[0] : T[0] >> 4].color);
2368                                 pixel_put(pbuf, 1, pal[sp[1] ? sp[1] : T[0] & 0x0f].color);
2369                                 pixel_put(pbuf, 2, pal[sp[2] ? sp[2] : T[1] >> 4].color);
2370                                 pixel_put(pbuf, 3, pal[sp[3] ? sp[3] : T[1] & 0x0f].color);
2371                                 pixel_put(pbuf, 4, pal[sp[4] ? sp[4] : T[2] >> 4].color);
2372                                 pixel_put(pbuf, 5, pal[sp[5] ? sp[5] : T[2] & 0x0f].color);
2373                                 pixel_put(pbuf, 6, pal[sp[6] ? sp[6] : T[3] >> 4].color);
2374                                 pixel_put(pbuf, 7, pal[sp[7] ? sp[7] : T[3] & 0x0f].color);
2375
2376                                 pbuf += md_video_pixbytes(8); T += 4; sp += 8;
2377                         }
2378                 }
2379                 pbuf += pp;
2380         }
2381
2382         v99x8_refresh_stop();
2383 }
2384
2385 void    V99X8::v99x8_refresh_sc6(int y, int h)
2386 {
2387         int i;
2388         uint8_t *T;
2389         int pp;
2390         uint8_t *pbuf, *sp;
2391
2392         if (f_scr)
2393         {
2394                 v99x8.tbl_pn = v99x8.vram + (((int)v99x8.ctrl[2] & 0x60) << 10);
2395                 f_scr = FALSE;
2396         }
2397
2398
2399         pbuf = v99x8_refresh_start(0, 256, h);
2400         pp = md_video_pitch() - md_video_pixbytes(256);
2401
2402         T = v99x8.tbl_pn + (((y + v99x8.ctrl[23]) & 0xff) << 7);
2403
2404         while(h-- > 0)
2405         {
2406                 sp = v99x8_refresh_sprite2(y++);
2407                 for(i = 0; i < 32; ++i)
2408                 {
2409                         if  (v99x8.f_zoom)
2410                         {
2411                                 pixel_put(pbuf, 0, pal[sp[0] ? sp[0] : T[0] >> 6].color);
2412                                 pixel_put(pbuf, 1, pal[sp[0] ? sp[0] : (T[0] >> 4) & 3].color);
2413                                 pixel_put(pbuf, 2, pal[sp[1] ? sp[1] : (T[0] >> 2) & 3].color);
2414                                 pixel_put(pbuf, 3, pal[sp[1] ? sp[1] : T[0] & 3].color);
2415                                 pixel_put(pbuf, 4, pal[sp[2] ? sp[2] : T[1] >> 6].color);
2416                                 pixel_put(pbuf, 5, pal[sp[2] ? sp[2] : (T[1] >> 4) & 3].color);
2417                                 pixel_put(pbuf, 6, pal[sp[3] ? sp[3] : (T[1] >> 2) & 3].color);
2418                                 pixel_put(pbuf, 7, pal[sp[3] ? sp[3] : T[1] & 3].color);
2419                                 pixel_put(pbuf, 8, pal[sp[4] ? sp[4] : T[2] >> 6].color);
2420                                 pixel_put(pbuf, 9, pal[sp[4] ? sp[4] : (T[2] >> 4) & 3].color);
2421                                 pixel_put(pbuf, 10, pal[sp[5] ? sp[5] : (T[2] >> 2) & 3].color);
2422                                 pixel_put(pbuf, 11, pal[sp[5] ? sp[5] : T[2] & 3].color);
2423                                 pixel_put(pbuf, 12, pal[sp[6] ? sp[6] : T[3] >> 6].color);
2424                                 pixel_put(pbuf, 13, pal[sp[6] ? sp[6] : (T[3] >> 4) & 3].color);
2425                                 pixel_put(pbuf, 14, pal[sp[7] ? sp[7] : (T[3] >> 2) & 3].color);
2426                                 pixel_put(pbuf, 15, pal[sp[7] ? sp[7] : T[3] & 3].color);
2427                                 pbuf += md_video_pixbytes(16); T += 4; sp += 8;
2428                         } else
2429                         {
2430                                 pixel_put(pbuf, 0, sp[0] ? pal[sp[0]].color : pal_m[(T[0] >> 6) | (T[0] & 0x30)]);
2431                                 pixel_put(pbuf, 1, sp[1] ? pal[sp[1]].color : pal_m[((T[0] & 0x0c) << 2) | (T[0] & 0x03)]);
2432                                 pixel_put(pbuf, 2, sp[2] ? pal[sp[2]].color : pal_m[(T[1] >> 6) | (T[1] & 0x30)]);
2433                                 pixel_put(pbuf, 3, sp[3] ? pal[sp[3]].color : pal_m[((T[1] & 0x0c) << 2) | (T[1] & 0x03)]);
2434                                 pixel_put(pbuf, 4, sp[4] ? pal[sp[4]].color : pal_m[(T[2] >> 6) | (T[2] & 0x30)]);
2435                                 pixel_put(pbuf, 5, sp[5] ? pal[sp[5]].color : pal_m[((T[2] & 0x0c) << 2) | (T[2] & 0x03)]);
2436                                 pixel_put(pbuf, 6, sp[6] ? pal[sp[6]].color : pal_m[(T[3] >> 6) | (T[3] & 0x30)]);
2437                                 pixel_put(pbuf, 7, sp[7] ? pal[sp[7]].color : pal_m[((T[3] & 0x0c) << 2) | (T[3] & 0x03)]);
2438                                 pbuf += md_video_pixbytes(8); T += 4; sp += 8;
2439                         }
2440                 }
2441                 pbuf += pp;
2442         }
2443
2444         v99x8_refresh_stop();
2445 }
2446
2447 void V99X8::v99x8_refresh_sc7(int y, int h)
2448 {
2449         uint8_t *pbuf, *sp;
2450         uint8_t *T;
2451         int pp;
2452         int i;
2453
2454         if (f_scr)
2455         {
2456                 v99x8.tbl_pn = v99x8.vram + (((int)v99x8.ctrl[2] & 0x20) << 11);
2457                 f_scr = FALSE;
2458         }
2459
2460         pbuf = v99x8_refresh_start(0, 256, h);
2461         pp = md_video_pitch() - md_video_pixbytes(256);
2462
2463 /* printf("%d/%d %d  %d\n", y, v99x8.ctrl[23], (y+v99x8.ctrl[23])&0xff, v99x8.ctrl[19]+1); */
2464         T = v99x8.tbl_pn + (((y + v99x8.ctrl[23]) & 0xff) << 8);
2465
2466         while(h-- > 0)
2467         {
2468                 sp = v99x8_refresh_sprite2(y);
2469                 {
2470                         for (i = 0; i < 32; ++i)
2471                         {
2472                         if  (v99x8.f_zoom)
2473                                 {
2474                                         pixel_put(pbuf, 0, pal[sp[0] ? sp[0] : T[0] >> 4].color);
2475                                         pixel_put(pbuf, 1, pal[sp[0] ? sp[0] : T[0] & 0x0f].color);
2476                                         pixel_put(pbuf, 2, pal[sp[1] ? sp[1] : T[1] >> 4].color);
2477                                         pixel_put(pbuf, 3, pal[sp[1] ? sp[1] : T[1] & 0x0f].color);
2478                                         pixel_put(pbuf, 4, pal[sp[2] ? sp[2] : T[2] >> 4].color);
2479                                         pixel_put(pbuf, 5, pal[sp[2] ? sp[2] : T[2] & 0x0f].color);
2480                                         pixel_put(pbuf, 6, pal[sp[3] ? sp[3] : T[3] >> 4].color);
2481                                         pixel_put(pbuf, 7, pal[sp[3] ? sp[3] : T[3] & 0x0f].color);
2482                                         pixel_put(pbuf, 8, pal[sp[4] ? sp[4] : T[4] >> 4].color);
2483                                         pixel_put(pbuf, 9, pal[sp[4] ? sp[4] : T[4] & 0x0f].color);
2484                                         pixel_put(pbuf, 10, pal[sp[5] ? sp[5] : T[5] >> 4].color);
2485                                         pixel_put(pbuf, 11, pal[sp[5] ? sp[5] : T[5] & 0x0f].color);
2486                                         pixel_put(pbuf, 12, pal[sp[6] ? sp[6] : T[6] >> 4].color);
2487                                         pixel_put(pbuf, 13, pal[sp[6] ? sp[6] : T[6] & 0x0f].color);
2488                                         pixel_put(pbuf, 14, pal[sp[7] ? sp[7] : T[7] >> 4].color);
2489                                         pixel_put(pbuf, 15, pal[sp[7] ? sp[7] : T[7] & 0x0f].color);
2490                                         pbuf += md_video_pixbytes(16); T += 8; sp += 8;
2491                                 } else
2492                                 {
2493                                         pixel_put(pbuf,0, sp[0]? pal[sp[0]].color : pal_m[T[0]]);
2494                                         pixel_put(pbuf,1, sp[1]? pal[sp[1]].color : pal_m[T[1]]);
2495                                         pixel_put(pbuf,2, sp[2]? pal[sp[2]].color : pal_m[T[2]]);
2496                                         pixel_put(pbuf,3, sp[3]? pal[sp[3]].color : pal_m[T[3]]);
2497                                         pixel_put(pbuf,4, sp[4]? pal[sp[4]].color : pal_m[T[4]]);
2498                                         pixel_put(pbuf,5, sp[5]? pal[sp[5]].color : pal_m[T[5]]);
2499                                         pixel_put(pbuf,6, sp[6]? pal[sp[6]].color : pal_m[T[6]]);
2500                                         pixel_put(pbuf,7, sp[7]? pal[sp[7]].color : pal_m[T[7]]);
2501
2502                                         pbuf += md_video_pixbytes(8); T += 8; sp += 8;
2503                                 }
2504                         }
2505                 }
2506                 ++y;
2507                 pbuf += pp;
2508         }
2509
2510         v99x8_refresh_stop();
2511 }
2512
2513 void V99X8::v99x8_refresh_sc8(int y, int h)
2514 {
2515         uint8_t *pbuf, *sp;
2516         uint8_t *T;
2517         int pp;
2518         int i;
2519         uint8_t sc8spr[16] =
2520         {
2521                 0x00,0x02,0x10,0x12,0x80,0x82,0x90,0x92,
2522                 0x49,0x4B,0x59,0x5B,0xC9,0xCB,0xD9,0xDB
2523         };
2524
2525         if (f_scr)
2526         {
2527                 v99x8.tbl_pn = v99x8.vram + (((int)v99x8.ctrl[2] & 0x20) << 11);
2528                 f_scr = FALSE;
2529         }
2530
2531         pbuf = v99x8_refresh_start(0, 256, h);
2532         pp = md_video_pitch() - md_video_pixbytes(256);
2533
2534         T = v99x8.tbl_pn + (((y + v99x8.ctrl[23]) & 0xff) << 8);
2535
2536         while(h-- > 0)
2537         {
2538                 sp = v99x8_refresh_sprite2(y);
2539                 {
2540                         for (i = 0; i < 32; ++i)
2541                         {
2542                                 if  (v99x8.f_zoom)
2543                                 {
2544                                         pixel_put(pbuf, 0, pal_8[sp[0] ? sc8spr[sp[0]] : T[0]]);
2545                                         pixel_put(pbuf, 1, pal_8[sp[0] ? sc8spr[sp[0]] : T[0]]);
2546                                         pixel_put(pbuf, 2, pal_8[sp[1] ? sc8spr[sp[1]] : T[1]]);
2547                                         pixel_put(pbuf, 3, pal_8[sp[1] ? sc8spr[sp[1]] : T[1]]);
2548                                         pixel_put(pbuf, 4, pal_8[sp[2] ? sc8spr[sp[2]] : T[2]]);
2549                                         pixel_put(pbuf, 5, pal_8[sp[2] ? sc8spr[sp[2]] : T[2]]);
2550                                         pixel_put(pbuf, 6, pal_8[sp[3] ? sc8spr[sp[3]] : T[3]]);
2551                                         pixel_put(pbuf, 7, pal_8[sp[3] ? sc8spr[sp[3]] : T[3]]);
2552                                         pixel_put(pbuf, 8, pal_8[sp[4] ? sc8spr[sp[4]] : T[4]]);
2553                                         pixel_put(pbuf, 9, pal_8[sp[4] ? sc8spr[sp[4]] : T[4]]);
2554                                         pixel_put(pbuf, 10, pal_8[sp[5] ? sc8spr[sp[5]] : T[5]]);
2555                                         pixel_put(pbuf, 11, pal_8[sp[5] ? sc8spr[sp[5]] : T[5]]);
2556                                         pixel_put(pbuf, 12, pal_8[sp[6] ? sc8spr[sp[6]] : T[6]]);
2557                                         pixel_put(pbuf, 13, pal_8[sp[6] ? sc8spr[sp[6]] : T[6]]);
2558                                         pixel_put(pbuf, 14, pal_8[sp[7] ? sc8spr[sp[7]] : T[7]]);
2559                                         pixel_put(pbuf, 15, pal_8[sp[7] ? sc8spr[sp[7]] : T[7]]);
2560                                         pbuf += md_video_pixbytes(16); T += 8; sp += 8;
2561                                 } else
2562                                 {
2563                                         pixel_put(pbuf,0, pal_8[sp[0] ? sc8spr[sp[0]] : T[0]]);
2564                                         pixel_put(pbuf,1, pal_8[sp[1] ? sc8spr[sp[1]] : T[1]]);
2565                                         pixel_put(pbuf,2, pal_8[sp[2] ? sc8spr[sp[2]] : T[2]]);
2566                                         pixel_put(pbuf,3, pal_8[sp[3] ? sc8spr[sp[3]] : T[3]]);
2567                                         pixel_put(pbuf,4, pal_8[sp[4] ? sc8spr[sp[4]] : T[4]]);
2568                                         pixel_put(pbuf,5, pal_8[sp[5] ? sc8spr[sp[5]] : T[5]]);
2569                                         pixel_put(pbuf,6, pal_8[sp[6] ? sc8spr[sp[6]] : T[6]]);
2570                                         pixel_put(pbuf,7, pal_8[sp[7] ? sc8spr[sp[7]] : T[7]]);
2571                                         pbuf += md_video_pixbytes(8); T += 8; sp += 8;
2572                                 }
2573                         }
2574                 }
2575                 ++y;
2576                 pbuf += pp;
2577         }
2578
2579         v99x8_refresh_stop();
2580 }
2581
2582 static __inline__ uint32_t v99x8_refresh_MapYJK(int n, int j, int k, int jk)
2583 {
2584         return md_maprgb15(tbl_yjk_rg[n + j], tbl_yjk_rg[n + k], tbl_yjk_b [n + jk]);
2585 }
2586
2587
2588 void V99X8::v99x8_refresh_scc(int y, int h)
2589 {
2590         uint8_t *pbuf, *sp;
2591         uint8_t *T;
2592         int pp;
2593         int i;
2594         uint8_t sc8spr[16] =
2595         {
2596                 0x00, 0x02, 0x10, 0x12, 0x80, 0x82, 0x90, 0x92,
2597                 0x49, 0x4B, 0x59, 0x5B, 0xC9, 0xCB, 0xD9, 0xDB
2598         };
2599
2600         if (f_scr)
2601         {
2602                 v99x8.tbl_pn = v99x8.vram + (((int)v99x8.ctrl[2] & 0x20) << 11);
2603                 f_scr = FALSE;
2604         }
2605
2606         pbuf = v99x8_refresh_start(0, 256, h);
2607         pp = md_video_pitch() - md_video_pixbytes(256);
2608
2609         T = v99x8.tbl_pn + (((y + v99x8.ctrl[23]) & 0xff) << 8);
2610
2611         while(h-- > 0)
2612         {
2613                 sp = v99x8_refresh_sprite2(y);
2614                 for (i = 0; i < 64; ++i)
2615                 {
2616                         int yjk_k, yjk_j, yjk_jk;
2617
2618                         yjk_k = (((T[0] & 7) | ((T[1] & 7) << 3)) + 32) & 0x3f;
2619                         yjk_j = (((T[2] & 7) | ((T[3] & 7) << 3)) + 32) & 0x3f;
2620
2621                         yjk_jk = (yjk_j << 11) + (yjk_k << 5);
2622
2623                         pixel_put(pbuf, 0, sp[0] ? pal_8[sc8spr[sp[0]]] : v99x8_refresh_MapYJK(T[0] >> 3, yjk_j, yjk_k, yjk_jk));
2624                         pixel_put(pbuf, 1, sp[1] ? pal_8[sc8spr[sp[1]]] : v99x8_refresh_MapYJK(T[1] >> 3, yjk_j, yjk_k, yjk_jk));
2625                         pixel_put(pbuf, 2, sp[2] ? pal_8[sc8spr[sp[2]]] : v99x8_refresh_MapYJK(T[2] >> 3, yjk_j, yjk_k, yjk_jk));
2626                         pixel_put(pbuf, 3, sp[3] ? pal_8[sc8spr[sp[3]]] : v99x8_refresh_MapYJK(T[3] >> 3, yjk_j, yjk_k, yjk_jk));
2627
2628                         pbuf += md_video_pixbytes(4); T += 4; sp += 4;
2629                 }
2630                 ++y;
2631                 pbuf += pp;
2632         }
2633
2634         v99x8_refresh_stop();
2635 }
2636
2637 void    V99X8::v99x8_refresh_sc2(int y, int h)  {;}
2638 void    V99X8::v99x8_refresh_sc3(int y, int h)  {;}
2639 void    V99X8::v99x8_refresh_sca(int y, int h)  {;} /* sc10/sc11 */
2640 void    V99X8::v99x8_refresh_scx(int y, int h)
2641 {
2642         uint8_t *pbuf;
2643         int pp;
2644         uint32_t fg, bg, m[4];
2645
2646         if (f_scr)
2647         {
2648                 v99x8.tbl_pg = v99x8.vram + (((int)v99x8.ctrl[4] & 0x3f) << 11);
2649                 v99x8.tbl_pn = v99x8.vram + (((int)v99x8.ctrl[2] & 0x7c) << 10);
2650                 v99x8.tbl_cl = v99x8.vram + (((int)v99x8.ctrl[10] & 0x07) << 14)
2651                                           + (((int)v99x8.ctrl[3] & 0xf8) << 6);
2652                 f_scr = FALSE;
2653         }
2654
2655         pbuf = v99x8_refresh_start(8, 240, h);
2656         pp = md_video_pitch() - md_video_pixbytes(240);
2657
2658         fg = pal[v99x8.col_fg].color;
2659         bg = pal[v99x8.col_bg].color;
2660         m[0] = pal_m[(v99x8.col_bg << 4) | v99x8.col_bg];
2661         m[1] = pal_m[(v99x8.col_bg << 4) | v99x8.col_fg];
2662         m[2] = pal_m[(v99x8.col_fg << 4) | v99x8.col_bg];
2663         m[3] = pal_m[(v99x8.col_fg << 4) | v99x8.col_fg];
2664
2665         while(h-- > 0)
2666         {
2667                 int i;
2668                 uint8_t *T,*G;
2669
2670                 T = v99x8.tbl_pn + (y >> 3) * 80;
2671                 G = v99x8.tbl_pg + (y & 0x07);
2672                 ++y;
2673
2674                 for (i = 0; i < 80; ++i)
2675                 {
2676                         uint8_t a;
2677
2678                         a = G[(int)*T++ << 3];
2679                         if  (v99x8.f_zoom)
2680                         {
2681                                 pixel_put(pbuf, 0, (a & 0x80) ? fg : bg);
2682                                 pixel_put(pbuf, 1, (a & 0x40) ? fg : bg);
2683                                 pixel_put(pbuf, 2, (a & 0x20) ? fg : bg);
2684                                 pixel_put(pbuf, 3, (a & 0x10) ? fg : bg);
2685                                 pixel_put(pbuf, 4, (a & 0x08) ? fg : bg);
2686                                 pixel_put(pbuf, 5, (a & 0x04) ? fg : bg);
2687                                 pbuf += md_video_pixbytes(6);
2688                         } else
2689                         {
2690                                 pixel_put(pbuf, 0, m[a >> 6]);
2691                                 pixel_put(pbuf, 1, m[(a >> 4)& 0x03]);
2692                                 pixel_put(pbuf, 2, m[(a >> 2)& 0x03]);
2693
2694                                 pbuf += md_video_pixbytes(3);
2695                         }
2696                 }
2697                 pbuf += pp;
2698         }
2699
2700         v99x8_refresh_stop();
2701 }
2702
2703
2704
2705
2706
2707 /*
2708         Skelton for retropc emulator
2709
2710         Origin : Zodiac
2711         Author : umaiboux
2712         Date   : 2014.12.xx -
2713
2714         [ V99x8 ]
2715 */
2716
2717 void V99X8::initialize()
2718 {
2719         DEVICE::initialize();
2720         _SCREEN_WIDTH = osd->get_feature_int_value(_T("SCREEN_WIDTH"));
2721         _SCREEN_HEIGHT = osd->get_feature_int_value(_T("SCREEN_HEIGHT"));
2722         //_use_cmdtime = osd->check_feature(_T("USE_CMDTIME"));
2723
2724         screen = (scrntype_t *)malloc(_SCREEN_WIDTH * _SCREEN_HEIGHT * sizeof(scrntype_t));
2725         // register event
2726         register_vline_event(this);
2727
2728         v99x8.vram = this->vram;
2729         v99x8.f_zoom = TRUE;
2730         //v99x8_init();
2731 }
2732
2733 void V99X8::release()
2734 {
2735         if(screen != NULL) free(screen);
2736 }
2737
2738
2739 void V99X8::reset()
2740 {
2741         v99x8_init();
2742 #ifdef USE_CMDTIME
2743                 cmdtime_t = 0;
2744                 cmdtime_m = 0;
2745 #endif
2746         latch1 = -1;
2747         latch2 = -1;
2748 }
2749
2750 void V99X8::write_io8(uint32_t addr, uint32_t data)
2751 {
2752         data &= 0xFF;
2753         switch (addr & 3) {
2754         case 0:
2755                 v99x8_out_0(data);
2756                 break;
2757         case 1:
2758                 v99x8_out_1(data);
2759                 break;
2760         case 2:
2761                 v99x8_out_2(data);
2762                 break;
2763         default:
2764                 v99x8_out_3(data);
2765                 break;
2766         }
2767 }
2768
2769 uint32_t V99X8::read_io8(uint32_t addr)
2770 {
2771         uint8_t data;
2772         switch (addr & 1) {
2773         case 0:
2774                 data = v99x8_in_0();
2775                 break;
2776         default:
2777                 data = v99x8_in_1();
2778                 break;
2779         }
2780         return data;
2781 }
2782
2783 void V99X8::draw_screen()
2784 {
2785         if(emu->now_waiting_in_debugger) {
2786                 // store regs
2787                 v99x8_t tmp_v99x8 = v99x8;
2788                 bool tmp_intstat = intstat;
2789                 
2790                 // drive vlines
2791                 for(int v = /*get_cur_vline() + 1*/0; v < get_lines_per_frame(); v++) {
2792                         event_vline(v, 0);
2793                 }
2794                 
2795                 // restore regs
2796                 v99x8 = tmp_v99x8;
2797                 intstat = tmp_intstat;
2798         }
2799         md_video_update(0, NULL);
2800 }
2801
2802 void V99X8::event_vline(int v, int clock)
2803 {
2804 #ifdef USE_CMDTIME
2805         cmdtime_chk();
2806 #endif
2807         hsync(v);
2808 }
2809
2810 void V99X8::set_intstat(bool val)
2811 {
2812         if(val != intstat) {
2813                 if(!emu->now_waiting_in_debugger) {
2814                         write_signals(&outputs_irq, val ? 0xffffffff : 0);
2815                 }
2816                 intstat = val;
2817         }
2818 }
2819
2820 void V99X8::z80_intreq(int a)
2821 {
2822         set_intstat(a != Z80_NOINT);
2823 }
2824
2825 int V99X8::md_video_pitch(void)
2826 {
2827         return _SCREEN_WIDTH*4;
2828 }
2829
2830 uint8_t *V99X8::md_video_lockline(int x, int y, int w, int h)
2831 {
2832         return (uint8_t*)(screen+y*_SCREEN_WIDTH+x);
2833 #if 0
2834         if (SDL_MUSTLOCK(video.screen))
2835                 SDL_LockSurface(video.screen); /* \96ß\82è\92l\83`\83F\83b\83N\81H */
2836
2837         return (Uint8_t *)video.screen->pixels
2838                + video.screen->format->BytesPerPixel * (video.w + x)
2839                + video.screen->pitch * (y + video.h);
2840 #endif
2841 }
2842
2843 void V99X8::md_video_update(int n, /*md_video_rect_t*/void *rp)
2844 {
2845         if (rp == NULL) {
2846                 scrntype_t *dst;
2847                 int y = 0;
2848                 int h = _SCREEN_HEIGHT;
2849                 for(;h>0; h-=2) {
2850                         if((dst = emu->get_screen_buffer(y)) != NULL) {
2851                                 memcpy(dst, screen+y*_SCREEN_WIDTH, _SCREEN_WIDTH*4);
2852                         }
2853                         if((dst = emu->get_screen_buffer(y + 1)) != NULL) {
2854                                 memcpy(dst, screen+y*_SCREEN_WIDTH, _SCREEN_WIDTH*4);
2855                         }
2856                         y+=2;
2857                 }
2858         }
2859         else {
2860                 ;
2861         }
2862 }
2863
2864 void V99X8::md_video_fill(int x, int y, int w, int h, uint32_t c)
2865 {
2866         int w2;
2867         for(;h>0; h--) {
2868                 scrntype_t *p = screen+y*_SCREEN_WIDTH+x;
2869                 for(w2=w;w2>0; w2--) {
2870                         *p++ = c;
2871                 }
2872                 y++;
2873         }
2874 }
2875
2876 static void lmcm(void)
2877 {
2878         ;
2879 }
2880
2881
2882 static void stop(void)
2883 {
2884 #ifdef USE_CMDTIME
2885                 cmdtime_t = 0;
2886                 v99x8.status[2] &= ~0x01;
2887 #endif
2888 }
2889
2890
2891 static void vcom_lfill_(int dx, int dy, int nx, int clr)
2892 {
2893         if (v99x8.ctrl[45] & 0x04) { /* Direction to left */
2894                 // Todo?: if (dx-nx<MIN_OF_X) xxx;
2895                 for (;nx>0;nx--,dx--) vcom_lpset(dx, dy, clr);
2896         }
2897         else {
2898                 // Todo?: if (dx+nx>MAX_OF_X) xxx;
2899                 for (;nx>0;nx--,dx++) vcom_lpset(dx, dy, clr);
2900         }
2901 }
2902
2903 static void lmmv_(void)
2904 {
2905         int clr;
2906
2907         vcom.sx = 0;
2908         vcom.sy = 0;
2909         vcom_getdx();
2910         vcom_getdy();
2911         vcom_getnx();
2912         vcom_getny();
2913         clr = v99x8.ctrl[44];
2914
2915         if ((v99x8.ctrl[45] & 0x08) == 0) {  /* Direction to down */
2916                 int ny = vcom.ny, dy = vcom.dy;
2917                 // Todo?: if (dy+ny>MAX_OF_Y) xxx;
2918                 for (;ny>0;ny--,dy++) vcom_lfill_(vcom.dx, dy, vcom.nx, clr);
2919                 vcom_setdy(vcom.dy + vcom.ny);
2920         }
2921         else {
2922                 int ny = vcom.ny, dy = vcom.dy;
2923                 // Todo?: if (dy-ny<MIN_OF_Y) xxx;
2924                 for (;ny>0;ny--,dy--) vcom_lfill_(vcom.dx, dy, vcom.nx, clr);
2925                 vcom_setdy(vcom.dy - vcom.ny);
2926         }
2927
2928         //vcom_setdy(vcom.dy + n);
2929
2930         //if (vcom.ny != abs(n))
2931         //      vcom_setny(vcom.ny - abs(n));
2932         vcom_setny(0);
2933 }
2934
2935
2936 static void vcom_lcopy_(int sx, int sy, int dx, int dy, int nx)
2937 {
2938         if (v99x8.ctrl[45] & 0x04) { /* Direction to left */
2939                 // Todo?: if (dx-nx<MIN_OF_X) xxx;
2940                 // Todo?: if (sx-nx<MIN_OF_X) xxx;
2941                 for (;nx>0;nx--,dx--, sx--) vcom_lpset(dx, dy, vcom_point(sx, sy));
2942         }
2943         else {
2944                 // Todo?: if (dx+nx>MAX_OF_X) xxx;
2945                 // Todo?: if (sx+nx>MAX_OF_X) xxx;
2946                 if (dx+nx>vcom.xmask+1) {
2947                         nx=vcom.xmask-dx+1;
2948                 }
2949                 if (sx+nx>vcom.xmask+1) {
2950                         nx=vcom.xmask-sx+1;
2951                 }
2952                 for (;nx>0;nx--,dx++, sx++) vcom_lpset(dx, dy, vcom_point(sx, sy));
2953         }
2954 }
2955
2956
2957 static void lmmm_(void)
2958 {
2959         vcom_getsx();
2960         vcom_getsy();
2961         vcom_getdx();
2962         vcom_getdy();
2963         vcom_getnx();
2964         vcom_getny();
2965
2966         if ((v99x8.ctrl[45] & 0x08) == 0) {  /* Direction to down */
2967                 int ny = vcom.ny, dy = vcom.dy, sy = vcom.sy;
2968                 // Todo?: if (dy+ny>MAX_OF_Y) xxx;
2969                 // Todo?: if (sy+ny>MAX_OF_Y) xxx;
2970                 for (;ny>0;ny--,dy++,sy++) vcom_lcopy_(vcom.sx, sy, vcom.dx, dy, vcom.nx);
2971                 vcom_setsy(vcom.sy + vcom.ny);
2972                 vcom_setdy(vcom.dy + vcom.ny);
2973         }
2974         else {
2975                 int ny = vcom.ny, dy = vcom.dy, sy = vcom.sy;
2976                 // Todo?: if (dy-ny<MIN_OF_Y) xxx;
2977                 // Todo?: if (sy-ny<MIN_OF_Y) xxx;
2978                 for (;ny>0;ny--,dy--,sy--) vcom_lcopy_(vcom.sx, sy, vcom.dx, dy, vcom.nx);
2979                 vcom_setsy(vcom.sy - vcom.ny);
2980                 vcom_setdy(vcom.dy - vcom.ny);
2981         }
2982
2983         //vcom_setsy(vcom.sy + n);
2984         //vcom_setdy(vcom.dy + n);
2985
2986         //if (vcom.ny != abs(n))
2987         //      vcom_setny(vcom.ny - abs(n));
2988         vcom_setny(0);
2989 }
2990
2991
2992 void cmdtime_set(int m)
2993 {
2994 #ifdef USE_CMDTIME
2995         cmdtime_m = m>>4;
2996         cmdtime_t = 0;
2997
2998         /* provisional data */
2999         /*
3000         if ((v99x8.ctrl[8] & 0x02) == 0) && ((v99x8.ctrl[1] & 0x40) != 0)
3001         YMMM 4.83 microseconds/byte
3002         HMMM 5.85 microseconds/byte
3003         HMMV 3.05 microseconds/byte
3004         LMMM 6.87 microseconds/dot
3005         LMMV 5.91 microseconds/dot
3006         */
3007         switch(m >> 4)
3008         {
3009         case 0xe:       /* ymmm */ vcom_getdx();vcom_getny();cmdtime_t=483*(v99x8.ctrl[45] & 0x04?vcom.dx:v99x8.mode.xsize-vcom.dx)*vcom.ny/pixmask.npix; break;
3010         case 0xd:       /* hmmm */ vcom_getnx();vcom_getny();cmdtime_t=585*vcom.nx*vcom.ny/pixmask.npix; break;
3011         case 0xc:       /* hmmv */ vcom_getnx();vcom_getny();cmdtime_t=305*vcom.nx*vcom.ny/pixmask.npix; break;
3012         case 0x9:       /* lmmm */ vcom_getnx();vcom_getny();cmdtime_t=687*vcom.nx*vcom.ny; break;
3013         case 0x8:       /* lmmv */ vcom_getnx();vcom_getny();cmdtime_t=591*vcom.nx*vcom.ny; break;
3014         }
3015         //cmdtime_t = cmdtime_t*60*262/1000000/100;
3016         cmdtime_t = cmdtime_t/6361;
3017         if (cmdtime_t<0) cmdtime_t=0;
3018 #endif
3019 }
3020
3021 void cmdtime_chk(void)
3022 {
3023 #ifdef USE_CMDTIME
3024         if (cmdtime_t) {
3025                 cmdtime_t--;
3026                 if (0 == cmdtime_t) v99x8.status[2] &= ~0x01;
3027         }
3028 #endif
3029 }
3030
3031
3032 #define STATE_VERSION   1
3033
3034 bool V99X8::process_state(FILEIO* state_fio, bool loading)
3035 {
3036         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
3037                 return false;
3038         }
3039         if(!state_fio->StateCheckInt32(this_device_id)) {
3040                 return false;
3041         }
3042 #ifdef USE_CMDTIME
3043         state_fio->StateValue(cmdtime_t);
3044         state_fio->StateValue(cmdtime_m);
3045 #endif
3046         state_fio->StateValue(latch1);
3047         state_fio->StateValue(latch2);
3048         state_fio->StateValue(vram_addr);
3049         state_fio->StateValue(vram_page);
3050         state_fio->StateValue(f_out3);
3051         state_fio->StateValue(f_mode);
3052         state_fio->StateValue(flag_frame);
3053         //state_fio->StateArray(&vcom, sizeof(vcom), 1); // vcom contains uint8_t*.Pointer of 64bit is sizeof(uint64_t).
3054         {
3055                 state_fio->StateValue(vcom.xbytes);
3056                 state_fio->StateValue(vcom.xmask);
3057                 state_fio->StateValue(vcom.ymask);
3058                 state_fio->StateValue(vcom.xshift);
3059                 state_fio->StateValue(vcom.yshift);
3060                 
3061                 state_fio->StateValue(vcom.sx);
3062                 state_fio->StateValue(vcom.sy);
3063                 state_fio->StateValue(vcom.dx);
3064                 state_fio->StateValue(vcom.dy);
3065                 state_fio->StateValue(vcom.nx);
3066                 state_fio->StateValue(vcom.ny);
3067         }
3068         if(loading) {
3069                 uintptr_t p = (uintptr_t)vram;
3070                 vcom.src = (uint8_t*)(p + state_fio->FgetInt32_LE());
3071                 vcom.dst = (uint8_t*)(p + state_fio->FgetInt32_LE());
3072         } else {
3073                 uintptr_t _v, _s, _d;
3074                 _v = (uintptr_t)vram;
3075                 _s = (uintptr_t)(vcom.src);
3076                 _d = (uintptr_t)(vcom.dst);
3077                 state_fio->FputInt32_LE((int)(_s - _v));
3078                 state_fio->FputInt32_LE((int)(_d - _v));
3079         }
3080
3081         state_fio->StateArray(&r44, sizeof(r44), 1); // All of this are Int32
3082         state_fio->StateArray(&pixmask, sizeof(pixmask), 1); // All of this are Int32
3083         state_fio->StateArray(&v99x8_refresh, sizeof(v99x8_refresh), 1);// All of this are Int32
3084         //state_fio->StateArray(pal, sizeof(pal), 1);
3085         for(int i = 0; i < array_length(pal); i++) {
3086                 state_fio->StateValue(pai[i].flag);
3087                 state_fio->StateValue(pai[i].r);
3088                 state_fio->StateValue(pai[i].g);
3089                 state_fio->StateValue(pai[i].b);
3090                 state_fio->StateValue(pai[i].color);
3091         }
3092                 
3093         state_fio->StateArray(pal_8, sizeof(pal_8), 1);
3094         state_fio->StateArray(pal_m, sizeof(pal_m), 1);
3095         state_fio->StateValue(col_bg);
3096         state_fio->StateArray(tbl_yjk_b, sizeof(tbl_yjk_b), 1);
3097         state_fio->StateArray(tbl_yjk_rg, sizeof(tbl_yjk_rg), 1);
3098         state_fio->StateArray(blackbuf, sizeof(blackbuf), 1);
3099         state_fio->StateArray(sbuf, sizeof(sbuf), 1);
3100         state_fio->StateArray(vram, sizeof(vram), 1);
3101         state_fio->StateValue(intstat);
3102         // Q: Do not save "v99x8_t v99x8"? 20181014 K.O
3103         
3104         // post process
3105         if(loading) {
3106                 v99x8.vram = vram;
3107                 f_scr = true;
3108         }
3109         return true;
3110 }