initial import
[picodrive.git] / platform / linux / fakedasm.c
1 // This is part of Pico Library
2
3 // (c) Copyright 2004 Dave, All rights reserved.
4 // (c) Copyright 2006 notaz, All rights reserved.
5 // Free for non-commercial use.
6
7 // For commercial use, separate licencing terms must be obtained.
8
9
10 #include "../../Pico/PicoInt.h"
11 #undef blockcpy
12
13 extern unsigned short DefOutBuff[320*2];
14 extern unsigned char  HighCol[8+320+8];
15 extern char HighSprZ[320+8+8]; // Z-buffer for accurate sprites and shadow/hilight mode
16                         // (if bit 7 == 0, sh caused by tile; if bit 6 == 0 pixel must be shadowed, else hilighted, if bit5 == 1)
17 // lsb->msb: moved sprites, all window tiles don't use same priority, accurate sprites (copied from PicoOpt), interlace
18 //           dirty sprites, sonic mode
19 extern int rendstatus;
20 extern int Scanline; // Scanline
21
22
23 struct TileStrip
24 {
25   int nametab; // Position in VRAM of name table (for this tile line)
26   int line;    // Line number in pixels 0x000-0x3ff within the virtual tilemap 
27   int hscroll; // Horizontal scroll value in pixels for the line
28   int xmask;   // X-Mask (0x1f - 0x7f) for horizontal wraparound in the tilemap
29   int *hc;     // cache for high tile codes and their positions
30   int cells;   // cells (tiles) to draw (32 col mode doesn't need to update whole 320)
31 };
32
33 // utility
34 void *blockcpy(void *dst, const void *src, size_t n)
35 {
36         return memcpy(dst, src, n);
37 }
38
39 void blockcpy_or(void *dst, void *src, size_t n, int pat)
40 {
41   unsigned char *pd = dst, *ps = src;
42   for (; n; n--)
43     *pd++ = (unsigned char) (*ps++ | pat);
44 }
45
46
47 static int TileNorm(int sx,int addr,int pal)
48 {
49   unsigned char *pd = HighCol+sx;
50   unsigned int pack=0; unsigned int t=0;
51
52   pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
53   if (pack)
54   {
55     t=pack&0x0000f000; if (t) pd[0]=(unsigned char)(pal|(t>>12));
56     t=pack&0x00000f00; if (t) pd[1]=(unsigned char)(pal|(t>> 8));
57     t=pack&0x000000f0; if (t) pd[2]=(unsigned char)(pal|(t>> 4));
58     t=pack&0x0000000f; if (t) pd[3]=(unsigned char)(pal|(t    ));
59     t=pack&0xf0000000; if (t) pd[4]=(unsigned char)(pal|(t>>28));
60     t=pack&0x0f000000; if (t) pd[5]=(unsigned char)(pal|(t>>24));
61     t=pack&0x00f00000; if (t) pd[6]=(unsigned char)(pal|(t>>20));
62     t=pack&0x000f0000; if (t) pd[7]=(unsigned char)(pal|(t>>16));
63     return 0;
64   }
65
66   return 1; // Tile blank
67 }
68
69 static int TileFlip(int sx,int addr,int pal)
70 {
71   unsigned char *pd = HighCol+sx;
72   unsigned int pack=0; unsigned int t=0;
73
74   pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
75   if (pack)
76   {
77     t=pack&0x000f0000; if (t) pd[0]=(unsigned char)(pal|(t>>16));
78     t=pack&0x00f00000; if (t) pd[1]=(unsigned char)(pal|(t>>20));
79     t=pack&0x0f000000; if (t) pd[2]=(unsigned char)(pal|(t>>24));
80     t=pack&0xf0000000; if (t) pd[3]=(unsigned char)(pal|(t>>28));
81     t=pack&0x0000000f; if (t) pd[4]=(unsigned char)(pal|(t    ));
82     t=pack&0x000000f0; if (t) pd[5]=(unsigned char)(pal|(t>> 4));
83     t=pack&0x00000f00; if (t) pd[6]=(unsigned char)(pal|(t>> 8));
84     t=pack&0x0000f000; if (t) pd[7]=(unsigned char)(pal|(t>>12));
85     return 0;
86   }
87   return 1; // Tile blank
88 }
89
90
91 // tile renderers for hacky operator sprite support
92 #define sh_pix(x) \
93   if(!t); \
94   else if(t==0xe) pd[x]=(unsigned char)((pd[x]&0x3f)|0x80); /* hilight */ \
95   else if(t==0xf) pd[x]=(unsigned char)((pd[x]&0x3f)|0xc0); /* shadow  */ \
96   else pd[x]=(unsigned char)(pal|t);
97
98 static int TileNormSH(int sx,int addr,int pal)
99 {
100   unsigned int pack=0; unsigned int t=0;
101   unsigned char *pd = HighCol+sx;
102
103   pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
104   if (pack)
105   {
106     t=(pack&0x0000f000)>>12; sh_pix(0);
107     t=(pack&0x00000f00)>> 8; sh_pix(1);
108     t=(pack&0x000000f0)>> 4; sh_pix(2);
109     t=(pack&0x0000000f)    ; sh_pix(3);
110     t=(pack&0xf0000000)>>28; sh_pix(4);
111     t=(pack&0x0f000000)>>24; sh_pix(5);
112     t=(pack&0x00f00000)>>20; sh_pix(6);
113     t=(pack&0x000f0000)>>16; sh_pix(7);
114     return 0;
115   }
116
117   return 1; // Tile blank
118 }
119
120 static int TileFlipSH(int sx,int addr,int pal)
121 {
122   unsigned int pack=0; unsigned int t=0;
123   unsigned char *pd = HighCol+sx;
124
125   pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
126   if (pack)
127   {
128     t=(pack&0x000f0000)>>16; sh_pix(0);
129     t=(pack&0x00f00000)>>20; sh_pix(1);
130     t=(pack&0x0f000000)>>24; sh_pix(2);
131     t=(pack&0xf0000000)>>28; sh_pix(3);
132     t=(pack&0x0000000f)    ; sh_pix(4);
133     t=(pack&0x000000f0)>> 4; sh_pix(5);
134     t=(pack&0x00000f00)>> 8; sh_pix(6);
135     t=(pack&0x0000f000)>>12; sh_pix(7);
136     return 0;
137   }
138   return 1; // Tile blank
139 }
140
141
142 // --------------------------------------------
143
144 static void DrawStrip(struct TileStrip *ts, int sh)
145 {
146   int tilex=0,dx=0,ty=0,code=0,addr=0,cells;
147   int oldcode=-1,blank=-1; // The tile we know is blank
148   int pal=0;
149
150   // Draw tiles across screen:
151   tilex=(-ts->hscroll)>>3;
152   ty=(ts->line&7)<<1; // Y-Offset into tile
153   dx=((ts->hscroll-1)&7)+1;
154   cells = ts->cells;
155   if(dx != 8) cells++; // have hscroll, need to draw 1 cell more
156
157   for (; cells; dx+=8,tilex++,cells--)
158   {
159     int zero=0;
160
161     code=Pico.vram[ts->nametab+(tilex&ts->xmask)];
162     if (code==blank) continue;
163     if (code>>15) { // high priority tile
164       int cval = code | (dx<<16) | (ty<<25);
165       if(code&0x1000) cval^=7<<26;
166       *ts->hc++ = cval; // cache it
167       continue;
168     }
169
170     if (code!=oldcode) {
171       oldcode = code;
172       // Get tile address/2:
173       addr=(code&0x7ff)<<4;
174       addr+=ty;
175       if (code&0x1000) addr^=0xe; // Y-flip
176
177 //      pal=Pico.cram+((code>>9)&0x30);
178       pal=((code>>9)&0x30)|(sh<<6);
179     }
180
181     if (code&0x0800) zero=TileFlip(dx,addr,pal);
182     else             zero=TileNorm(dx,addr,pal);
183
184     if (zero) blank=code; // We know this tile is blank now
185   }
186
187   // terminate the cache list
188   *ts->hc = 0;
189 }
190
191 static void DrawStripVSRam(struct TileStrip *ts, int plane)
192 {
193   int tilex=0,dx=0,ty=0,code=0,addr=0,cell=0,nametabadd=0;
194   int oldcode=-1,blank=-1; // The tile we know is blank
195   int pal=0,scan=Scanline;
196
197   // Draw tiles across screen:
198   tilex=(-ts->hscroll)>>3;
199   dx=((ts->hscroll-1)&7)+1;
200   if(dx != 8) {
201     int vscroll, line;
202     cell--; // have hscroll, start with negative cell
203     // also calculate intial VS stuff
204     vscroll=Pico.vsram[plane];
205
206     // Find the line in the name table
207     line=(vscroll+scan)&ts->line&0xffff; // ts->line is really ymask ..
208     nametabadd=(line>>3)<<(ts->line>>24);    // .. and shift[width]
209     ty=(line&7)<<1; // Y-Offset into tile
210   }
211
212   for (; cell < ts->cells; dx+=8,tilex++,cell++)
213   {
214     int zero=0;
215
216     if((cell&1)==0) {
217       int line,vscroll;
218       vscroll=Pico.vsram[plane+(cell&~1)];
219
220       // Find the line in the name table
221       line=(vscroll+scan)&ts->line&0xffff; // ts->line is really ymask ..
222       nametabadd=(line>>3)<<(ts->line>>24);    // .. and shift[width]
223       ty=(line&7)<<1; // Y-Offset into tile
224     }
225
226     code=Pico.vram[ts->nametab+nametabadd+(tilex&ts->xmask)];
227     if (code==blank) continue;
228     if (code>>15) { // high priority tile
229       int cval = code | (dx<<16) | (ty<<25);
230       if(code&0x1000) cval^=7<<26;
231       *ts->hc++ = cval; // cache it
232       continue;
233     }
234
235     if (code!=oldcode) {
236       oldcode = code;
237       // Get tile address/2:
238       addr=(code&0x7ff)<<4;
239       if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip
240
241 //      pal=Pico.cram+((code>>9)&0x30);
242       pal=((code>>9)&0x30);
243     }
244
245     if (code&0x0800) zero=TileFlip(dx,addr,pal);
246     else             zero=TileNorm(dx,addr,pal);
247
248     if (zero) blank=code; // We know this tile is blank now
249   }
250
251   // terminate the cache list
252   *ts->hc = 0;
253 }
254
255 static void DrawStripInterlace(struct TileStrip *ts)
256 {
257   int tilex=0,dx=0,ty=0,code=0,addr=0,cells;
258   int oldcode=-1,blank=-1; // The tile we know is blank
259   int pal=0;
260
261   // Draw tiles across screen:
262   tilex=(-ts->hscroll)>>3;
263   ty=(ts->line&15)<<1; // Y-Offset into tile
264   dx=((ts->hscroll-1)&7)+1;
265   cells = ts->cells;
266   if(dx != 8) cells++; // have hscroll, need to draw 1 cell more
267
268   for (; cells; dx+=8,tilex++,cells--)
269   {
270     int zero=0;
271
272     code=Pico.vram[ts->nametab+(tilex&ts->xmask)];
273     if (code==blank) continue;
274     if (code>>15) { // high priority tile
275       int cval = (code&0xfc00) | (dx<<16) | (ty<<25);
276       cval|=(code&0x3ff)<<1;
277       if(code&0x1000) cval^=0xf<<26;
278       *ts->hc++ = cval; // cache it
279       continue;
280     }
281
282     if (code!=oldcode) {
283       oldcode = code;
284       // Get tile address/2:
285       addr=(code&0x7ff)<<5;
286       if (code&0x1000) addr+=30-ty; else addr+=ty; // Y-flip
287
288 //      pal=Pico.cram+((code>>9)&0x30);
289       pal=((code>>9)&0x30);
290     }
291
292     if (code&0x0800) zero=TileFlip(dx,addr,pal);
293     else             zero=TileNorm(dx,addr,pal);
294
295     if (zero) blank=code; // We know this tile is blank now
296   }
297
298   // terminate the cache list
299   *ts->hc = 0;
300 }
301
302 // --------------------------------------------
303
304 void DrawLayer(int plane, int *hcache, int maxcells, int sh)
305 {
306   struct PicoVideo *pvid=&Pico.video;
307   const char shift[4]={5,6,5,7}; // 32,64 or 128 sized tilemaps (2 is invalid)
308   struct TileStrip ts;
309   int width, height, ymask;
310   int vscroll, htab;
311
312   ts.hc=hcache;
313   ts.cells=maxcells;
314
315   // Work out the TileStrip to draw
316
317   // Work out the name table size: 32 64 or 128 tiles (0-3)
318   width=pvid->reg[16];
319   height=(width>>4)&3; width&=3;
320
321   ts.xmask=(1<<shift[width])-1; // X Mask in tiles (0x1f-0x7f)
322   ymask=(height<<8)|0xff;       // Y Mask in pixels
323   if(width == 1)   ymask&=0x1ff;
324   else if(width>1) ymask =0x0ff;
325
326   // Find name table:
327   if (plane==0) ts.nametab=(pvid->reg[2]&0x38)<< 9; // A
328   else          ts.nametab=(pvid->reg[4]&0x07)<<12; // B
329
330   htab=pvid->reg[13]<<9; // Horizontal scroll table address
331   if ( pvid->reg[11]&2)     htab+=Scanline<<1; // Offset by line
332   if ((pvid->reg[11]&1)==0) htab&=~0xf; // Offset by tile
333   htab+=plane; // A or B
334
335   // Get horizontal scroll value, will be masked later
336   ts.hscroll=Pico.vram[htab&0x7fff];
337
338   if((pvid->reg[12]&6) == 6) {
339     // interlace mode 2
340     vscroll=Pico.vsram[plane]; // Get vertical scroll value
341
342     // Find the line in the name table
343     ts.line=(vscroll+(Scanline<<1))&((ymask<<1)|1);
344     ts.nametab+=(ts.line>>4)<<shift[width];
345
346     DrawStripInterlace(&ts);
347   } else if( pvid->reg[11]&4) {
348     // shit, we have 2-cell column based vscroll
349     // luckily this doesn't happen too often
350     ts.line=ymask|(shift[width]<<24); // save some stuff instead of line
351     DrawStripVSRam(&ts, plane);
352   } else {
353     vscroll=Pico.vsram[plane]; // Get vertical scroll value
354
355     // Find the line in the name table
356     ts.line=(vscroll+Scanline)&ymask;
357     ts.nametab+=(ts.line>>3)<<shift[width];
358
359     DrawStrip(&ts, sh);
360   }
361 }
362
363
364 // --------------------------------------------
365
366 // tstart & tend are tile pair numbers
367 void DrawWindow(int tstart, int tend, int prio, int sh) // int *hcache
368 {
369   struct PicoVideo *pvid=&Pico.video;
370   int tilex=0,ty=0,nametab,code=0;
371   int blank=-1; // The tile we know is blank
372
373   // Find name table line:
374   if (pvid->reg[12]&1)
375   {
376     nametab=(pvid->reg[3]&0x3c)<<9; // 40-cell mode
377     nametab+=(Scanline>>3)<<6;
378   }
379   else
380   {
381     nametab=(pvid->reg[3]&0x3e)<<9; // 32-cell mode
382     nametab+=(Scanline>>3)<<5;
383   }
384
385   tilex=tstart<<1;
386   tend<<=1;
387
388   ty=(Scanline&7)<<1; // Y-Offset into tile
389
390   if(!(rendstatus&2)) {
391     // check the first tile code
392     code=Pico.vram[nametab+tilex];
393     // if the whole window uses same priority (what is often the case), we may be able to skip this field
394     if((code>>15) != prio) return;
395   }
396
397   // Draw tiles across screen:
398   for (; tilex < tend; tilex++)
399   {
400     int addr=0,zero=0;
401     int pal;
402
403     code=Pico.vram[nametab+tilex];
404     if(code==blank) continue;
405     if((code>>15) != prio) {
406       rendstatus|=2;
407       continue;
408     }
409
410     pal=((code>>9)&0x30);
411
412     if(sh) {
413       int tmp, *zb = (int *)(HighCol+8+(tilex<<3));
414       if(prio) {
415         tmp = *zb;
416         if(!(tmp&0x00000080)) tmp&=~0x000000c0; if(!(tmp&0x00008000)) tmp&=~0x0000c000;
417         if(!(tmp&0x00800000)) tmp&=~0x00c00000; if(!(tmp&0x80000000)) tmp&=~0xc0000000;
418         *zb++=tmp; tmp = *zb;
419         if(!(tmp&0x00000080)) tmp&=~0x000000c0; if(!(tmp&0x00008000)) tmp&=~0x0000c000;
420         if(!(tmp&0x00800000)) tmp&=~0x00c00000; if(!(tmp&0x80000000)) tmp&=~0xc0000000;
421         *zb++=tmp;
422       } else {
423         pal |= 0x40;
424       }
425     }
426
427     // Get tile address/2:
428     addr=(code&0x7ff)<<4;
429     if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip
430
431     if (code&0x0800) zero=TileFlip(8+(tilex<<3),addr,pal);
432     else             zero=TileNorm(8+(tilex<<3),addr,pal);
433
434     if (zero) blank=code; // We know this tile is blank now
435   }
436
437   // terminate the cache list
438   //*hcache = 0;
439 }
440
441 // --------------------------------------------
442
443 void DrawTilesFromCache(int *hc, int sh)
444 {
445   int code, addr, zero, dx;
446   int pal;
447   short blank=-1; // The tile we know is blank
448
449   // *ts->hc++ = code | (dx<<16) | (ty<<25); // cache it
450
451   while((code=*hc++)) {
452     if(!sh && (short)code == blank) continue;
453
454     // Get tile address/2:
455     addr=(code&0x7ff)<<4;
456     addr+=(unsigned int)code>>25; // y offset into tile
457     dx=(code>>16)&0x1ff;
458     if(sh) {
459       unsigned char *zb = HighCol+dx;
460       if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;
461       if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;
462       if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;
463       if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++;
464     }
465
466     pal=((code>>9)&0x30);
467
468     if (code&0x0800) zero=TileFlip(dx,addr,pal);
469     else             zero=TileNorm(dx,addr,pal);
470
471     if(zero) blank=(short)code;
472   }
473 }
474
475 // --------------------------------------------
476
477 // Index + 0  :    hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size
478 // Index + 4  :    xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8
479
480 void DrawSprite(int *sprite, int **hc, int sh)
481 {
482   int width=0,height=0;
483   int row=0,code=0;
484   int pal;
485   int tile=0,delta=0;
486   int sx, sy;
487   int (*fTileFunc)(int sx,int addr,int pal);
488
489   // parse the sprite data
490   sy=sprite[0];
491   code=sprite[1];
492   sx=code>>16; // X
493   width=sy>>28;
494   height=(sy>>24)&7; // Width and height in tiles
495   sy=(sy<<16)>>16; // Y
496
497   row=Scanline-sy; // Row of the sprite we are on
498
499   if (code&0x1000) row=(height<<3)-1-row; // Flip Y
500
501   tile=code&0x7ff; // Tile number
502   tile+=row>>3; // Tile number increases going down
503   delta=height; // Delta to increase tile by going right
504   if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X
505
506   tile<<=4; tile+=(row&7)<<1; // Tile address
507
508   if(code&0x8000) { // high priority - cache it
509     *(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>16)&0xf);
510   } else {
511     delta<<=4; // Delta of address
512     pal=((code>>9)&0x30)|(sh<<6);
513
514     if(sh && (code&0x6000) == 0x6000) {
515       if(code&0x0800) fTileFunc=TileFlipSH;
516       else            fTileFunc=TileNormSH;
517     } else {
518       if(code&0x0800) fTileFunc=TileFlip;
519       else            fTileFunc=TileNorm;
520     }
521
522     for (; width; width--,sx+=8,tile+=delta)
523     {
524       if(sx<=0)   continue;
525       if(sx>=328) break; // Offscreen
526
527       tile&=0x7fff; // Clip tile address
528       fTileFunc(sx,tile,pal);
529     }
530   }
531 }
532
533
534 void DrawSpritesFromCache(int *hc, int sh)
535 {
536   int code, tile, sx, delta, width;
537   int pal;
538   int (*fTileFunc)(int sx,int addr,int pal);
539
540   // *(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>24)&0xf);
541
542   while((code=*hc++)) {
543     pal=(code&0x30);
544     delta=code&0xf;
545     width=delta>>2; delta&=3;
546     width++; delta++; // Width and height in tiles
547     if (code&0x10000) delta=-delta; // Flip X
548     delta<<=4;
549     tile=((unsigned int)code>>17)<<1;
550     sx=(code<<16)>>22; // sx can be negative (start offscreen), so sign extend
551
552     if(sh && pal == 0x30) { //
553       if(code&0x10000) fTileFunc=TileFlipSH;
554       else             fTileFunc=TileNormSH;
555     } else {
556       if(code&0x10000) fTileFunc=TileFlip;
557       else             fTileFunc=TileNorm;
558     }
559
560     for (; width; width--,sx+=8,tile+=delta)
561     {
562       if(sx<=0)   continue;
563       if(sx>=328) break; // Offscreen
564
565       tile&=0x7fff; // Clip tile address
566       fTileFunc(sx,tile,pal);
567     }
568   }
569 }
570
571
572 void BackFill(int reg7, int sh)
573 {
574   unsigned int back=0;
575   unsigned int *pd=NULL,*end=NULL;
576
577   // Start with a blank scanline (background colour):
578   back=reg7&0x3f;
579   back|=sh<<6;
580   back|=back<<8;
581   back|=back<<16;
582
583   pd= (unsigned int *)(HighCol+8);
584   end=(unsigned int *)(HighCol+8+320);
585
586   do { pd[0]=pd[1]=pd[2]=pd[3]=back; pd+=4; } while (pd<end);
587 }
588
589 // --------------------------------------------
590
591 extern unsigned short HighPal[0x100];
592
593 void FinalizeLineBGR444(int sh)
594 {
595   unsigned short *pd=DrawLineDest;
596   unsigned char  *ps=HighCol+8;
597   unsigned short *pal=Pico.cram;
598   int len, i, t;
599
600   if (Pico.video.reg[12]&1) {
601     len = 320;
602   } else {
603     if(!(PicoOpt&0x100)) pd+=32;
604     len = 256;
605   }
606
607   if(sh) {
608     pal=HighPal;
609     if(Pico.m.dirtyPal) {
610       blockcpy(pal, Pico.cram, 0x40*2);
611       // shadowed pixels
612       for(i = 0x3f; i >= 0; i--)
613         pal[0x40|i] = pal[0xc0|i] = (unsigned short)((pal[i]>>1)&0x0777);
614       // hilighted pixels
615       for(i = 0x3f; i >= 0; i--) {
616         t=pal[i]&0xeee;t+=0x444;if(t&0x10)t|=0xe;if(t&0x100)t|=0xe0;if(t&0x1000)t|=0xe00;t&=0xeee;
617         pal[0x80|i]=(unsigned short)t;
618       }
619       Pico.m.dirtyPal = 0;
620     }
621   }
622
623   for(i = 0; i < len; i++)
624     pd[i] = pal[ps[i]];
625 }
626
627
628 void FinalizeLineRGB555(int sh)
629 {
630   unsigned short *pd=DrawLineDest;
631   unsigned char  *ps=HighCol+8;
632   unsigned short *pal=HighPal;
633   int len, i, t, dirtyPal = Pico.m.dirtyPal;
634
635   if(dirtyPal) {
636     unsigned short *ppal=Pico.cram;
637     for(i = 0x3f; i >= 0; i--)
638       pal[i] = (unsigned short) (((ppal[i]&0x00f)<<12)|((ppal[i]&0x0f0)<<3)|((ppal[i]&0xf00)>>7));
639     Pico.m.dirtyPal = 0;
640   }
641
642   if (Pico.video.reg[12]&1) {
643     len = 320;
644   } else {
645     if(!(PicoOpt&0x100)) pd+=32;
646     len = 256;
647   }
648
649   if(sh) {
650     if(dirtyPal) {
651       // shadowed pixels
652       for(i = 0x3f; i >= 0; i--)
653         pal[0x40|i] = pal[0xc0|i] = (unsigned short)((pal[i]>>1)&0x738e);
654       // hilighted pixels
655       for(i = 0x3f; i >= 0; i--) {
656         t=pal[i]&0xe71c;t+=0x4208;if(t&0x20)t|=0x1c;if(t&0x800)t|=0x700;if(t&0x10000)t|=0xe000;t&=0xe71c;
657         pal[0x80|i]=(unsigned short)t;
658       }
659     }
660   }
661
662   for(i = 0; i < len; i++)
663     pd[i] = pal[ps[i]];
664 }
665
666
667