OSDN Git Service

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