OSDN Git Service

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