workaround a problem with the harmattan gcc
[drnoksnes] / c4emu.cpp
1 /*******************************************************************************
2   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  
4   (c) Copyright 1996 - 2003 Gary Henderson (gary.henderson@ntlworld.com) and
5                             Jerremy Koot (jkoot@snes9x.com)
6
7   (c) Copyright 2002 - 2003 Matthew Kendora and
8                             Brad Jorsch (anomie@users.sourceforge.net)
9  
10
11                       
12   C4 x86 assembler and some C emulation code
13   (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com),
14                             _Demo_ (_demo_@zsnes.com), and
15                             Nach (n-a-c-h@users.sourceforge.net)
16                                           
17   C4 C++ code
18   (c) Copyright 2003 Brad Jorsch
19
20   DSP-1 emulator code
21   (c) Copyright 1998 - 2003 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson,
22                             John Weidman (jweidman@slip.net),
23                             neviksti (neviksti@hotmail.com), and
24                             Kris Bleakley (stinkfish@bigpond.com)
25  
26   DSP-2 emulator code
27   (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and
28                      Lord Nightmare (lord_nightmare@users.sourceforge.net
29
30   OBC1 emulator code
31   (c) Copyright 2001 - 2003 zsKnight, pagefault (pagefault@zsnes.com)
32   Ported from x86 assembler to C by sanmaiwashi
33
34   SPC7110 and RTC C++ emulator code
35   (c) Copyright 2002 Matthew Kendora with research by
36                      zsKnight, John Weidman, and Dark Force
37
38   S-RTC C emulator code
39   (c) Copyright 2001 John Weidman
40   
41   Super FX x86 assembler emulator code 
42   (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault 
43
44   Super FX C emulator code 
45   (c) Copyright 1997 - 1999 Ivar and Gary Henderson.
46
47
48
49  
50   Specific ports contains the works of other authors. See headers in
51   individual files.
52  
53   Snes9x homepage: http://www.snes9x.com
54  
55   Permission to use, copy, modify and distribute Snes9x in both binary and
56   source form, for non-commercial purposes, is hereby granted without fee,
57   providing that this license information and copyright notice appear with
58   all copies and any derived work.
59  
60   This software is provided 'as-is', without any express or implied
61   warranty. In no event shall the authors be held liable for any damages
62   arising from the use of this software.
63  
64   Snes9x is freeware for PERSONAL USE only. Commercial users should
65   seek permission of the copyright holders first. Commercial use includes
66   charging money for Snes9x or software derived from Snes9x.
67  
68   The copyright holders request that bug fixes and improvements to the code
69   should be forwarded to them so everyone can benefit from the modifications
70   in future versions.
71  
72   Super NES and Super Nintendo Entertainment System are trademarks of
73   Nintendo Co., Limited and its subsidiary companies.
74 *******************************************************************************/
75
76 #ifndef __GP32__
77 #ifdef HAVE_CONFIG_H
78         #include <config.h>
79 #endif
80 #endif
81
82 #include <math.h>
83 #include "snes9x.h"
84 #include "sar.h"
85 #include "memmap.h"
86 #include "ppu.h"
87 #include "c4.h"
88
89 void S9xInitC4 ()
90 {
91     // Stupid zsnes code, we can't do the logical thing without breaking
92     // savestates
93 //    Memory.C4RAM = &Memory.FillRAM [0x6000];
94     memset(Memory.C4RAM, 0, 0x2000);
95 }
96
97 uint8 S9xGetC4 (uint16 Address)
98 {
99 #ifdef DEBUGGER
100     if(Settings.BGLayering) printf("%02x from %04x\n", Memory.C4RAM[Address-0x6000], Address);
101 #endif
102     if(Address==0x7f5e) return 0;
103     return (Memory.C4RAM [Address-0x6000]);
104 }
105
106 static uint8 C4TestPattern [12 * 4] =
107 {
108     0x00, 0x00, 0x00, 0xff,
109     0xff, 0xff, 0x00, 0xff,
110     0x00, 0x00, 0x00, 0xff,
111     0xff, 0xff, 0x00, 0x00,
112     0xff, 0xff, 0x00, 0x00,
113     0x80, 0xff, 0xff, 0x7f,
114     0x00, 0x80, 0x00, 0xff,
115     0x7f, 0x00, 0xff, 0x7f,
116     0xff, 0x7f, 0xff, 0xff,
117     0x00, 0x00, 0x01, 0xff,
118     0xff, 0xfe, 0x00, 0x01,
119     0x00, 0xff, 0xfe, 0x00
120 };
121
122
123 static void C4ConvOAM(void){
124     uint8 *OAMptr=Memory.C4RAM+(Memory.C4RAM[0x626]<<2);
125     for(uint8 *i=Memory.C4RAM+0x1fd; i>OAMptr; i-=4){
126         // Clear OAM-to-be
127         *i=0xe0;
128     }
129
130     uint16 globalX, globalY;
131     uint8 *OAMptr2;
132     int16 SprX, SprY;
133     uint8 SprName, SprAttr;
134     uint8 SprCount;
135     
136     globalX=READ_WORD(Memory.C4RAM+0x0621);
137     globalY=READ_WORD(Memory.C4RAM+0x0623);
138     OAMptr2=Memory.C4RAM+0x200+(Memory.C4RAM[0x626]>>2);
139
140 #ifdef DEBUGGER
141     if(Memory.C4RAM[0x625]!=0) printf("$6625=%02x, expected 00\n", Memory.C4RAM[0x625]);
142     if((Memory.C4RAM[0x626]>>2)!=Memory.C4RAM[0x629]) printf("$6629=%02x, expected %02x\n", Memory.C4RAM[0x629], (Memory.C4RAM[0x626]>>2));
143     if(((uint16)Memory.C4RAM[0x626]<<2)!=READ_WORD(Memory.C4RAM+0x627)) printf("$6627=%04x, expected %04x\n", READ_WORD(Memory.C4RAM+0x627), ((uint16)Memory.C4RAM[0x626]<<2));
144 #endif
145
146     if(Memory.C4RAM[0x0620]!=0){
147         SprCount=128-Memory.C4RAM[0x626];
148         uint8 offset=(Memory.C4RAM[0x626]&3)*2;
149         uint8 *srcptr=Memory.C4RAM+0x220;
150         for(int i=Memory.C4RAM[0x0620]; i>0 && SprCount>0; i--, srcptr+=16){
151             SprX=READ_WORD(srcptr)-globalX;
152             SprY=READ_WORD(srcptr+2)-globalY;
153             SprName=srcptr[5];
154             SprAttr=srcptr[4] | srcptr[0x06]; // XXX: mask bits?
155
156                 uint8 *sprptr=S9xGetMemPointer(READ_3WORD(srcptr+7));
157                 if(*sprptr!=0){
158                     int16 X, Y;
159                     for(int SprCnt=*sprptr++; SprCnt>0 && SprCount>0; SprCnt--, sprptr+=4){
160                         X=(int8)sprptr[1];
161                         if(SprAttr&0x40){ // flip X
162                             X=-X-((sprptr[0]&0x20)?16:8);
163                         }
164                         X+=SprX;
165                         if(X>=-16 && X<=272){
166                             Y=(int8)sprptr[2];
167                             if(SprAttr&0x80){
168                                 Y=-Y-((sprptr[0]&0x20)?16:8);
169                             }
170                             Y+=SprY;
171                             if(Y>=-16 && Y<=224){
172                                 OAMptr[0]=X&0xff;
173                                 OAMptr[1]=(uint8)Y;
174                                 OAMptr[2]=SprName+sprptr[3];
175                                 OAMptr[3]=SprAttr^(sprptr[0]&0xc0); // XXX: Carry from SprName addition?
176                                 *OAMptr2 &= ~(3<<offset);
177                                 if(X&0x100) *OAMptr2 |= 1<<offset;
178                                 if(sprptr[0]&0x20) *OAMptr2 |= 2<<offset;
179                                 OAMptr+=4;
180                                 SprCount--;
181                                 offset=(offset+2)&6;
182                                 if(offset==0) OAMptr2++;
183                             }
184                         }
185                     }
186                 } else if(SprCount>0){
187                     OAMptr[0]=(uint8)SprX;
188                     OAMptr[1]=(uint8)SprY;
189                     OAMptr[2]=SprName;
190                     OAMptr[3]=SprAttr;
191                     *OAMptr2 &= ~(3<<offset);
192                     if(SprX&0x100) *OAMptr2 |= 3<<offset;
193                     else *OAMptr2 |= 2<<offset;
194                     OAMptr+=4;
195                     SprCount--;
196                     offset=(offset+2)&6;
197                     if(offset==0) OAMptr2++;
198                 }
199             }
200         }
201     // XXX: Copy to OAM? I doubt it.
202 }
203
204 static void C4DoScaleRotate(int row_padding){
205     int16 A, B, C, D;
206
207     // Calculate matrix
208     int32 XScale=READ_WORD(Memory.C4RAM+0x1f8f);
209     if(XScale&0x8000) XScale=0x7fff;
210     int32 YScale=READ_WORD(Memory.C4RAM+0x1f92);
211     if(YScale&0x8000) YScale=0x7fff;
212
213     if(READ_WORD(Memory.C4RAM+0x1f80)==0)
214         { // no rotation
215         // XXX: only do this for C and D?
216         // XXX: and then only when YScale is 0x1000?
217         A=(int16)XScale;
218                 B=0;
219         C=0;
220                 D=(int16)YScale;
221     }
222         else if(READ_WORD(Memory.C4RAM+0x1f80)==128){ // 90 degree rotation
223         // XXX: Really do this?
224         A=0;
225                 B=(int16)(-YScale);
226         C=(int16)XScale;
227                 D=0;
228     } else if(READ_WORD(Memory.C4RAM+0x1f80)==256){ // 180 degree rotation
229         // XXX: Really do this?
230         A=(int16)(-XScale);
231                 B=0;
232         C=0;
233                 D=(int16)(-YScale);
234     } else if(READ_WORD(Memory.C4RAM+0x1f80)==384){ // 270 degree rotation
235         // XXX: Really do this?
236         A=0;
237                 B=(int16)YScale;
238         C=(int16)(-XScale);
239                 D=0;
240     } else {
241         A=(int16)SAR(C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*XScale, 15);
242         B=(int16)(-SAR(C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*YScale, 15));
243         C=(int16)SAR(C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*XScale, 15);
244         D=(int16)SAR(C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*YScale, 15);
245     }
246
247     // Calculate Pixel Resolution
248     uint8 w=Memory.C4RAM[0x1f89]&~7;
249     uint8 h=Memory.C4RAM[0x1f8c]&~7;
250
251 //    printf("%dx%d XScale=%04x YScale=%04x angle=%03x\n", w, h, XScale, YScale, READ_WORD(Memory.C4RAM+0x1f80)&0x1ff);
252 //    printf("Matrix: [%10g %10g]  [%04x %04x]\n", A/4096.0, B/4096.0, A&0xffff, B&0xffff);
253 //    printf("        [%10g %10g]  [%04x %04x]\n", C/4096.0, D/4096.0, C&0xffff, D&0xffff);
254
255     // Clear the output RAM
256     memset(Memory.C4RAM, 0, (w+row_padding/4)*h/2);
257
258     int32 Cx=(int16)READ_WORD(Memory.C4RAM+0x1f83);
259     int32 Cy=(int16)READ_WORD(Memory.C4RAM+0x1f86);
260
261 #ifdef DEBUGGER
262     if(Memory.C4RAM[0x1f97]!=0) printf("$7f97=%02x, expected 00\n", Memory.C4RAM[0x1f97]);
263     if((Cx&~1)!=w/2 || (Cy&~1)!=h/2) printf("Center is not middle of image! (%d, %d) != (%d, %d)\n", Cx, Cy, w/2, h/2);
264 #endif
265
266     // Calculate start position (i.e. (Ox, Oy) = (0, 0))
267     // The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in
268     // the function. We do Cx*A etc normally because the matrix parameters
269     // already have the fractional parts.
270     int32 LineX=(Cx<<12) - Cx*A - Cx*B;
271     int32 LineY=(Cy<<12) - Cy*C - Cy*D;
272     
273     // Start loop
274     uint32 X, Y;
275     uint8 byte;
276     int outidx=0;
277     uint8 bit=0x80;
278     for(int y=0; y<h; y++){
279         X=LineX;
280         Y=LineY;
281         for(int x=0; x<w; x++){
282             if((X>>12)>=w || (Y>>12)>=h){
283                 byte=0;
284             } else {
285                 uint32 addr=(Y>>12)*w+(X>>12);
286                 byte=Memory.C4RAM[0x600+(addr>>1)];
287                 if(addr&1) byte>>=4;
288             }
289
290             // De-bitplanify
291             if(byte&1) Memory.C4RAM[outidx]|=bit;
292             if(byte&2) Memory.C4RAM[outidx+1]|=bit;
293             if(byte&4) Memory.C4RAM[outidx+16]|=bit;
294             if(byte&8) Memory.C4RAM[outidx+17]|=bit;
295
296             bit>>=1;
297             if(bit==0){
298                 bit=0x80;
299                 outidx+=32;
300             }
301             
302             X+=A; // Add 1 to output x => add an A and a C
303             Y+=C;
304         }
305         outidx+=2+row_padding;
306         if(outidx&0x10){
307             outidx&=~0x10;
308         } else {
309             outidx-=w*4+row_padding;
310         }
311         LineX+=B; // Add 1 to output y => add a B and a D
312         LineY+=D;
313     }
314 }
315
316 static void C4DrawLine(int32 X1, int32 Y1, int16 Z1,
317                        int32 X2, int32 Y2, int16 Z2, uint8 Color){
318     // Transform coordinates
319     C4WFXVal=(short)X1;
320     C4WFYVal=(short)Y1;
321     C4WFZVal=Z1;
322     C4WFScale=Memory.C4RAM[0x1f90];
323     C4WFX2Val=Memory.C4RAM[0x1f86];
324     C4WFY2Val=Memory.C4RAM[0x1f87];
325     C4WFDist=Memory.C4RAM[0x1f88];
326     C4TransfWireFrame2();
327     X1=(C4WFXVal+48)<<8;
328     Y1=(C4WFYVal+48)<<8;
329
330     C4WFXVal=(short)X2;
331     C4WFYVal=(short)Y2;
332     C4WFZVal=Z2;
333     C4TransfWireFrame2();
334     X2=(C4WFXVal+48)<<8;
335     Y2=(C4WFYVal+48)<<8;
336
337     // get line info
338     C4WFXVal=(short)(X1>>8);
339     C4WFYVal=(short)(Y1>>8);
340     C4WFX2Val=(short)(X2>>8);
341     C4WFY2Val=(short)(Y2>>8);
342     C4CalcWireFrame();
343     X2=(int16)C4WFXVal;
344     Y2=(int16)C4WFYVal;
345
346     // render line
347     for(int i=C4WFDist?C4WFDist:1; i>0; i--)
348         { //.loop
349         if(X1>0xff && Y1>0xff && X1<0x6000 && Y1<0x6000)
350                 {
351             uint16 addr=((X1&~0x7ff) + (Y1&~0x7ff)*12 + (Y1&0x700))>>7;
352             addr=(((Y1>>8)>>3)<<8)-(((Y1>>8)>>3)<<6)+(((X1>>8)>>3)<<4)+((Y1>>8)&7)*2;
353             uint8 bit=0x80>>((X1>>8)&7);
354             Memory.C4RAM[addr+0x300]&=~bit;
355             Memory.C4RAM[addr+0x301]&=~bit;
356             if(Color&1) Memory.C4RAM[addr+0x300]|=bit;
357             if(Color&2) Memory.C4RAM[addr+0x301]|=bit;
358         }
359         X1+=X2;
360         Y1+=Y2;
361     }
362 }
363
364 static void C4DrawWireFrame(void)
365 {
366     uint8 *line=S9xGetMemPointer(READ_3WORD(Memory.C4RAM+0x1f80));
367     uint8 *point1, *point2;
368     int16 X1, Y1, Z1;
369     int16 X2, Y2, Z2;
370     uint8 Color;
371
372 #ifdef DEBUGGER
373     if(READ_3WORD(Memory.C4RAM+0x1f8f)&0xff00ff) printf("wireframe: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM+0x1f8f));
374     if(READ_3WORD(Memory.C4RAM+0x1fa4)!=0x001000) printf("wireframe: Unexpected value in $7fa4: %06x\n", READ_3WORD(Memory.C4RAM+0x1fa4));
375 #endif
376
377     for(int i=Memory.C4RAM[0x0295]; i>0; i--, line+=5){
378         if(line[0]==0xff && line[1]==0xff){
379             uint8 *tmp=line-5;
380             while(line[2]==0xff && line[3]==0xff) tmp-=5;
381             point1=S9xGetMemPointer((Memory.C4RAM[0x1f82]<<16) | (tmp[2]<<8) | tmp[3]);
382         } else {
383             point1=S9xGetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[0]<<8) | line[1]);
384         }
385         point2=S9xGetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[2]<<8) | line[3]);
386
387         X1=(point1[0]<<8) | point1[1];
388         Y1=(point1[2]<<8) | point1[3];
389         Z1=(point1[4]<<8) | point1[5];
390         X2=(point2[0]<<8) | point2[1];
391         Y2=(point2[2]<<8) | point2[3];
392         Z2=(point2[4]<<8) | point2[5];
393         Color=line[4];
394         C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
395 }
396 }
397
398 static void C4TransformLines(void){
399     C4WFX2Val=Memory.C4RAM[0x1f83];
400     C4WFY2Val=Memory.C4RAM[0x1f86];
401     C4WFDist=Memory.C4RAM[0x1f89];
402     C4WFScale=Memory.C4RAM[0x1f8c];
403
404 #ifdef DEBUGGER
405     if(Memory.C4RAM[0x1f8a]!=0x90) printf("lines: $7f8a = %02x, expected 90\n", READ_WORD(Memory.C4RAM+0x1f8a));
406 #endif
407
408     // transform vertices
409     uint8 *ptr=Memory.C4RAM;
410         {
411                 for(int i=READ_WORD(Memory.C4RAM+0x1f80); i>0; i--, ptr+=0x10)
412 {
413                         C4WFXVal=READ_WORD(ptr+1);
414                 C4WFYVal=READ_WORD(ptr+5);
415                     C4WFZVal=READ_WORD(ptr+9);
416                         C4TransfWireFrame();
417
418                 // displace
419                     WRITE_WORD(ptr+1, C4WFXVal+0x80);
420                         WRITE_WORD(ptr+5, C4WFYVal+0x50);
421                 }
422         }
423     WRITE_WORD(Memory.C4RAM+0x600, 23);
424     WRITE_WORD(Memory.C4RAM+0x602, 0x60);
425     WRITE_WORD(Memory.C4RAM+0x605, 0x40);
426     WRITE_WORD(Memory.C4RAM+0x600+8, 23);
427     WRITE_WORD(Memory.C4RAM+0x602+8, 0x60);
428     WRITE_WORD(Memory.C4RAM+0x605+8, 0x40);
429
430     ptr=Memory.C4RAM+0xb02;
431     uint8 *ptr2=Memory.C4RAM;
432         {
433             for(int i=READ_WORD(Memory.C4RAM+0xb00); i>0; i--, ptr+=2, ptr2+=8)
434                 {
435                     C4WFXVal=READ_WORD(Memory.C4RAM+(ptr[0]<<4)+1);
436                         C4WFYVal=READ_WORD(Memory.C4RAM+(ptr[0]<<4)+5);
437                         C4WFX2Val=READ_WORD(Memory.C4RAM+(ptr[1]<<4)+1);
438                         C4WFY2Val=READ_WORD(Memory.C4RAM+(ptr[1]<<4)+5);
439                         C4CalcWireFrame();
440                         WRITE_WORD(ptr2+0x600, C4WFDist?C4WFDist:1);
441                         WRITE_WORD(ptr2+0x602, C4WFXVal);
442                         WRITE_WORD(ptr2+0x605, C4WFYVal);
443                 }
444     }
445 }
446 static void C4BitPlaneWave(){
447     static uint16 bmpdata[]={
448         0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, 0x000E,
449         0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020A, 0x020C, 0x020E,
450         0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E,
451         0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060A, 0x060C, 0x060E,
452         0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080A, 0x080C, 0x080E
453     };
454
455     uint8 *dst=Memory.C4RAM;
456     uint32 waveptr=Memory.C4RAM[0x1f83];
457     uint16 mask1=0xc0c0;
458     uint16 mask2=0x3f3f;
459
460 #ifdef DEBUGGER
461     if(READ_3WORD(Memory.C4RAM+0x1f80) != Memory.C4RAM[waveptr+0xb00]) printf("$7f80=%06x, expected %02x\n", READ_3WORD(Memory.C4RAM+0x1f80), Memory.C4RAM[waveptr+0xb00]);
462 #endif
463
464     for(int j=0; j<0x10; j++){
465         do {
466             int16 height=-((int8)Memory.C4RAM[waveptr+0xb00])-16;
467             for(int i=0; i<40; i++){
468                 uint16 tmp=READ_WORD(dst+bmpdata[i]) & mask2;
469                 if(height>=0){
470                     if(height<8){
471                         tmp|=mask1&READ_WORD(Memory.C4RAM+0xa00+height*2);
472                     } else {
473                         tmp|=mask1&0xff00;
474                     }
475                 }
476                 WRITE_WORD(dst+bmpdata[i], tmp);
477                 height++;
478             }
479             waveptr=(waveptr+1)&0x7f;
480             mask1=(mask1>>2)|(mask1<<6);
481             mask2=(mask2>>2)|(mask2<<6);
482         } while(mask1!=0xc0c0);
483         dst+=16;
484
485         do {
486             int16 height=-((int8)Memory.C4RAM[waveptr+0xb00])-16;
487             for(int i=0; i<40; i++){
488                 uint16 tmp=READ_WORD(dst+bmpdata[i]) & mask2;
489                 if(height>=0){
490                     if(height<8){
491                         tmp|=mask1&READ_WORD(Memory.C4RAM+0xa10+height*2);
492                     } else {
493                         tmp|=mask1&0xff00;
494                     }
495                 }
496                 WRITE_WORD(dst+bmpdata[i], tmp);
497                 height++;
498             }
499             waveptr=(waveptr+1)&0x7f;
500             mask1=(mask1>>2)|(mask1<<6);
501             mask2=(mask2>>2)|(mask2<<6);
502         } while(mask1!=0xc0c0);
503         dst+=16;
504     }
505 }
506
507 static void C4SprDisintegrate()
508 {
509     uint8 width, height;
510     uint32 StartX, StartY;
511     uint8 *src;
512     int32 scaleX, scaleY;
513     int32 Cx, Cy;
514
515     width=Memory.C4RAM[0x1f89];
516     height=Memory.C4RAM[0x1f8c];
517     Cx=(int16)READ_WORD(Memory.C4RAM+0x1f80);
518     Cy=(int16)READ_WORD(Memory.C4RAM+0x1f83);
519
520 #ifdef DEBUGGER
521     if((Cx&~1)!=width/2 || (Cy&~1)!=height/2) printf("Center is not middle of image for disintegrate! (%d, %d) != (%d, %d)\n", Cx, Cy, width/2, height/2);
522 #endif
523     
524     scaleX=(int16)READ_WORD(Memory.C4RAM+0x1f86);
525     scaleY=(int16)READ_WORD(Memory.C4RAM+0x1f8f);
526     StartX=-Cx*scaleX+(Cx<<8);
527     StartY=-Cy*scaleY+(Cy<<8);
528     src=Memory.C4RAM+0x600;
529
530     memset(Memory.C4RAM, 0, width*height/2);
531     
532     for(uint32 y=StartY, i=0; i<height; i++, y+=scaleY)
533         {
534         for(uint32 x=StartX, j=0; j<width; j++, x+=scaleX)
535                 {
536             if((x>>8)<width && (y>>8)<height && (y>>8)*width+(x>>8)<0x2000)
537                         {
538                 uint8 pixel=(j&1)?(*src>>4):*src;
539                 int idx=(y>>11)*width*4+(x>>11)*32+((y>>8)&7)*2;
540                 uint8 mask=0x80>>((x>>8)&7);
541                 if(pixel&1) Memory.C4RAM[idx]|=mask;
542                 if(pixel&2) Memory.C4RAM[idx+1]|=mask;
543                 if(pixel&4) Memory.C4RAM[idx+16]|=mask;
544                 if(pixel&8) Memory.C4RAM[idx+17]|=mask;
545             }
546             if(j&1) src++;
547         }
548     }
549 }
550
551 static void S9xC4ProcessSprites()
552 {
553     switch(Memory.C4RAM[0x1f4d])
554         {
555       case 0x00: // Build OAM
556 #ifdef DEBUGGER
557 //        printf("00 00 Build OAM!\n");
558 #endif
559         C4ConvOAM();
560         break;
561
562       case 0x03: // Scale/Rotate
563 #ifdef DEBUGGER
564 //        printf("00 03 Scale/Rotate!\n");
565 #endif
566         C4DoScaleRotate(0);
567         break;
568
569       case 0x05: // Transform Lines
570 #ifdef DEBUGGER
571 //        printf("00 05 Transform Lines!\n");
572 #endif
573         C4TransformLines();
574         break;
575
576       case 0x07: // Scale/Rotate
577 #ifdef DEBUGGER
578 //        printf("00 07 Scale/Rotate!\n");
579 #endif
580         C4DoScaleRotate(64);
581         break;
582
583       case 0x08: // Draw wireframe
584 #ifdef DEBUGGER
585 //        printf("00 08 Draw wireframe!\n");
586 #endif
587         C4DrawWireFrame();
588         break;
589
590       case 0x0b: // Disintegrate
591 #ifdef DEBUGGER
592         printf("00 0b Disintegrate!\n");
593 #endif
594         C4SprDisintegrate();
595         break;
596
597       case 0x0c: // Wave
598 #ifdef DEBUGGER
599 //        printf("00 0b Wave!\n");
600 #endif
601         C4BitPlaneWave();
602         break;
603         
604       default:
605 #ifdef DEBUGGER
606         printf ("Unknown C4 sprite command (%02x)\n", Memory.C4RAM [0x1f4d]);
607 #endif
608         break;
609     }
610 }
611
612 void S9xSetC4 (uint8 byte, uint16 Address)
613 {
614     int i;
615
616 #ifdef DEBUGGER
617     if(Settings.BGLayering) printf("%02x to %04x\n", byte, Address);
618 #endif
619     Memory.C4RAM [Address-0x6000] = byte;
620     if (Address == 0x7f4f)
621     {
622         if(Memory.C4RAM[0x1f4d]==0x0e && byte<0x40 && (byte&3)==0)
623                 {
624 #ifdef DEBUGGER
625             printf("Test command %02x 0e used!\n", byte);
626 #endif
627             Memory.C4RAM[0x1f80]=byte>>2;
628         }
629                 else
630                 {
631         switch (byte)
632         {
633         case 0x00: // Sprite
634                 S9xC4ProcessSprites();
635                 break;
636
637               case 0x01: // Draw wireframe
638 #ifdef DEBUGGER
639                 //printf("01 Draw wireframe used!\n");
640                 if(Memory.C4RAM[0x1f4d]!=8) printf("$7f4d=%02x, expected 08 for command 01 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
641 #endif
642                 memset(Memory.C4RAM+0x300, 0, 16*12*3*4);
643                 C4DrawWireFrame();
644                 break;
645
646               case 0x05: // Propulsion (?)
647 #ifdef DEBUGGER
648                 printf("05 Propulsion (?)!\n");
649                 if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 05 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
650 #endif
651         {
652                     int32 tmp=0x10000;
653                     if(READ_WORD(Memory.C4RAM+0x1f83)){
654                         tmp=SAR((tmp/READ_WORD(Memory.C4RAM+0x1f83))*READ_WORD(Memory.C4RAM+0x1f81), 8);
655                     }
656                     WRITE_WORD(Memory.C4RAM+0x1f80, (uint16)tmp);
657                 }
658                 break;
659
660               case 0x0d: // Set vector length
661 #ifdef DEBUGGER
662                 printf("0d Set vector length!\n");
663                 if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 0d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
664 #endif
665                 C41FXVal=READ_WORD(Memory.C4RAM+0x1f80);
666                 C41FYVal=READ_WORD(Memory.C4RAM+0x1f83);
667                 C41FDistVal=READ_WORD(Memory.C4RAM+0x1f86);
668                 C4Op0D();
669                 WRITE_WORD(Memory.C4RAM+0x1f89, C41FXVal);
670                 WRITE_WORD(Memory.C4RAM+0x1f8c, C41FYVal);
671                 break;
672
673               case 0x10: // Polar to rectangluar
674 #ifdef DEBUGGER
675 //                printf("10 Polar->Rect!\n");
676                 if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 10 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
677 #endif
678             {
679                     int32 tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 16);
680                     WRITE_3WORD(Memory.C4RAM+0x1f86, tmp);
681                     tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 16);
682                     WRITE_3WORD(Memory.C4RAM+0x1f89, (tmp-SAR(tmp, 6)));
683                 }
684                 break;
685
686               case 0x13: // Polar to rectangluar
687 #ifdef DEBUGGER
688 //                printf("13 Polar->Rect!\n");
689                 if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 13 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
690 #endif
691                 {
692                     int32 tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 8);
693                     WRITE_3WORD(Memory.C4RAM+0x1f86, tmp);
694                     tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 8);
695                     WRITE_3WORD(Memory.C4RAM+0x1f89, tmp);
696                 }
697                 break;
698
699               case 0x15: // Pythagorean
700 #ifdef DEBUGGER
701                 printf("15 Pythagorean!\n");
702                 if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 15 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
703 #endif
704                 C41FXVal=READ_WORD(Memory.C4RAM+0x1f80);
705                 C41FYVal=READ_WORD(Memory.C4RAM+0x1f83);
706                 C41FDist=(int16)sqrt((double)C41FXVal*C41FXVal + (double)C41FYVal*C41FYVal);
707                 WRITE_WORD(Memory.C4RAM+0x1f80, C41FDist);
708                 break;
709
710               case 0x1f: // atan
711 #ifdef DEBUGGER
712 //                printf("1f atan!\n");
713                 if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 1f %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
714 #endif
715                 C41FXVal=READ_WORD(Memory.C4RAM+0x1f80);
716                 C41FYVal=READ_WORD(Memory.C4RAM+0x1f83);
717                 C4Op1F();
718                 WRITE_WORD(Memory.C4RAM+0x1f86, C41FAngleRes);
719                 break;
720
721               case 0x22: // Trapezoid
722                 {
723 #ifdef DEBUGGER
724 //                   printf("22 Trapezoid!\n");
725                     if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 22 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
726 #endif
727                     int16 angle1=READ_WORD(Memory.C4RAM+0x1f8c)&0x1ff;
728                     int16 angle2=READ_WORD(Memory.C4RAM+0x1f8f)&0x1ff;
729 #ifdef DEBUGGER
730                     if(C4CosTable[angle1]==0) fprintf(stderr, "22 Trapezoid: Invalid tangent! angle1=%d\n", angle1);
731                     if(C4CosTable[angle2]==0) fprintf(stderr, "22 Trapezoid: Invalid tangent! angle2=%d\n", angle2);
732 #endif
733                     int32 tan1=(C4CosTable[angle1]!=0)?((((int32)C4SinTable[angle1])<<16)/C4CosTable[angle1]):0x80000000;
734                     int32 tan2=(C4CosTable[angle2]!=0)?((((int32)C4SinTable[angle2])<<16)/C4CosTable[angle2]):0x80000000;
735                     int16 y = READ_WORD(Memory.C4RAM+0x1f83) - READ_WORD(Memory.C4RAM+0x1f89);
736                     int16 left, right;
737                     for(int j=0; j<225; j++)
738                     {
739                         if(y>=0)
740                         {
741                             left = SAR((int32)tan1*y, 16) -
742                                 READ_WORD(Memory.C4RAM+0x1f80) + 
743                                 READ_WORD(Memory.C4RAM+0x1f86);
744                             right = SAR((int32)tan2*y, 16) -
745                                 READ_WORD(Memory.C4RAM+0x1f80) + 
746                                 READ_WORD(Memory.C4RAM+0x1f86) +
747                                 READ_WORD(Memory.C4RAM+0x1f93);
748
749                             if(left<0 && right<0){
750                                 left=1;
751                                 right=0;
752                             } else if(left<0){
753                                 left=0;
754                             } else if(right<0){
755                                 right=0;
756                             }
757                             if(left>255 && right>255){
758                                 left=255;
759                                 right=254;
760                             } else if(left>255){
761                                 left=255;
762                             } else if(right>255){
763                                 right=255;
764                             }
765                         }
766                         else
767                         {
768                             left=1;
769                             right=0;
770                         }
771                         Memory.C4RAM[j+0x800] = (uint8)left;
772                         Memory.C4RAM[j+0x900] = (uint8)right;
773                         y++;
774                     }
775             }
776             break;
777
778               case 0x25: // Multiply
779 #ifdef DEBUGGER
780                 printf("25 Multiply!\n");
781                 if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 25 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
782 #endif
783                 { 
784                     int32 foo=READ_3WORD(Memory.C4RAM+0x1f80);
785                     int32 bar=READ_3WORD(Memory.C4RAM+0x1f83);
786                     foo*=bar;
787                     WRITE_3WORD(Memory.C4RAM+0x1f80, foo);
788         }
789             break;
790
791               case 0x2d: // Transform Coords
792 #ifdef DEBUGGER
793 //                printf("2d Transform Coords!\n");
794                 if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 2d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
795                 if(READ_3WORD(Memory.C4RAM+0x1f8f)&0xff00ff) printf("2d transform coords: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM+0x1f8f));
796                 if(READ_3WORD(Memory.C4RAM+0x1f8c)!=0x001000) printf("0d transform coords: Unexpected value in $7f8c: %06x\n", READ_3WORD(Memory.C4RAM+0x1f8c));
797 #endif
798                 C4WFXVal=READ_WORD(Memory.C4RAM+0x1f81);
799                 C4WFYVal=READ_WORD(Memory.C4RAM+0x1f84);
800                 C4WFZVal=READ_WORD(Memory.C4RAM+0x1f87);
801                 C4WFX2Val=Memory.C4RAM[0x1f89];
802                 C4WFY2Val=Memory.C4RAM[0x1f8a];
803                 C4WFDist=Memory.C4RAM[0x1f8b];
804                 C4WFScale=READ_WORD(Memory.C4RAM+0x1f90);
805                 C4TransfWireFrame2();
806                 WRITE_WORD(Memory.C4RAM+0x1f80, C4WFXVal);
807                 WRITE_WORD(Memory.C4RAM+0x1f83, C4WFYVal);
808                 break;
809
810               case 0x40: // Sum
811 #ifdef DEBUGGER
812                 printf("40 Sum!\n");
813                 if(Memory.C4RAM[0x1f4d]!=0x0e) printf("$7f4d=%02x, expected 0e for command 40 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
814 #endif
815                 {
816                     uint16 sum=0;
817                     for(int i=0; i<0x800; sum+=Memory.C4RAM[i++]);
818                     WRITE_WORD(Memory.C4RAM+0x1f80, sum);
819                 }
820                 break;
821
822               case 0x54: // Square
823 #ifdef DEBUGGER
824                 printf("54 Square!\n");
825                 if(Memory.C4RAM[0x1f4d]!=0x0e) printf("$7f4d=%02x, expected 0e for command 54 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
826 #endif
827                 {
828                     int64 a=SAR((int64)READ_3WORD(Memory.C4RAM+0x1f80)<<40, 40);
829                                 //      printf("%08X%08X\n", (uint32)(a>>32), (uint32)(a&0xFFFFFFFF));
830                     a*=a;
831                                 //      printf("%08X%08X\n", (uint32)(a>>32), (uint32)(a&0xFFFFFFFF));
832                     WRITE_3WORD(Memory.C4RAM+0x1f83, a);
833                     WRITE_3WORD(Memory.C4RAM+0x1f86, (a>>24));
834                 }
835                 break;
836
837         case 0x5c: // Immediate Reg
838 #ifdef DEBUGGER
839                 printf("5c Immediate Reg!\n");
840                 if(Memory.C4RAM[0x1f4d]!=0x0e) printf("$7f4d=%02x, expected 0e for command 5c %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
841 #endif
842             for (i = 0; i < 12 * 4; i++)
843                 Memory.C4RAM [i] = C4TestPattern [i];
844             break;
845
846         case 0x89: // Immediate ROM
847 #ifdef DEBUGGER
848                 printf("89 Immediate ROM!\n");
849                 if(Memory.C4RAM[0x1f4d]!=0x0e) printf("$7f4d=%02x, expected 0e for command 89 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
850 #endif
851                 Memory.C4RAM [0x1f80] = 0x36;
852                 Memory.C4RAM [0x1f81] = 0x43;
853                 Memory.C4RAM [0x1f82] = 0x05;
854             break;
855
856         default:
857 #ifdef DEBUGGER
858             printf ("Unknown C4 command (%02x)\n", byte);
859 #endif
860             break;
861         }
862     }
863     } else if (Address == 0x7f47) {
864 #ifdef DEBUGGER
865 //        printf("C4 load memory %06x => %04x, %04x bytes\n", READ_3WORD(Memory.C4RAM+0x1f40), READ_WORD(Memory.C4RAM+0x1f45), READ_WORD(Memory.C4RAM+0x1f43));
866         if(byte != 0) printf("C4 load: non-0 written to $7f47! Wrote %02x\n", byte);
867         if(READ_WORD(Memory.C4RAM+0x1f45) < 0x6000 || (READ_WORD(Memory.C4RAM+0x1f45) + READ_WORD(Memory.C4RAM+0x1f43)) > 0x6c00) printf("C4 load: Dest unusual! It's %04x\n", READ_WORD(Memory.C4RAM+0x1f45));
868 #endif
869         memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff), 
870                 S9xGetMemPointer(READ_3WORD(Memory.C4RAM+0x1f40)),
871                 READ_WORD(Memory.C4RAM+0x1f43));
872 }
873 }
874
875 int16 C4SinTable[512] = {
876             0,    402,    804,   1206,   1607,   2009,   2410,   2811,
877       3211,   3611,   4011,   4409,   4808,   5205,   5602,   5997,
878       6392,   6786,   7179,   7571,   7961,   8351,   8739,   9126,
879       9512,   9896,  10278,  10659,  11039,  11416,  11793,  12167,
880      12539,  12910,  13278,  13645,  14010,  14372,  14732,  15090,
881      15446,  15800,  16151,  16499,  16846,  17189,  17530,  17869,
882      18204,  18537,  18868,  19195,  19519,  19841,  20159,  20475,
883      20787,  21097,  21403,  21706,  22005,  22301,  22594,  22884,
884      23170,  23453,  23732,  24007,  24279,  24547,  24812,  25073,
885      25330,  25583,  25832,  26077,  26319,  26557,  26790,  27020,
886      27245,  27466,  27684,  27897,  28106,  28310,  28511,  28707,
887      28898,  29086,  29269,  29447,  29621,  29791,  29956,  30117,
888      30273,  30425,  30572,  30714,  30852,  30985,  31114,  31237,
889      31357,  31471,  31581,  31685,  31785,  31881,  31971,  32057,
890      32138,  32214,  32285,  32351,  32413,  32469,  32521,  32568,
891      32610,  32647,  32679,  32706,  32728,  32745,  32758,  32765,
892      32767,  32765,  32758,  32745,  32728,  32706,  32679,  32647,
893      32610,  32568,  32521,  32469,  32413,  32351,  32285,  32214,
894      32138,  32057,  31971,  31881,  31785,  31685,  31581,  31471,
895      31357,  31237,  31114,  30985,  30852,  30714,  30572,  30425,
896      30273,  30117,  29956,  29791,  29621,  29447,  29269,  29086,
897      28898,  28707,  28511,  28310,  28106,  27897,  27684,  27466,
898      27245,  27020,  26790,  26557,  26319,  26077,  25832,  25583,
899      25330,  25073,  24812,  24547,  24279,  24007,  23732,  23453,
900      23170,  22884,  22594,  22301,  22005,  21706,  21403,  21097,
901      20787,  20475,  20159,  19841,  19519,  19195,  18868,  18537,
902      18204,  17869,  17530,  17189,  16846,  16499,  16151,  15800,
903      15446,  15090,  14732,  14372,  14010,  13645,  13278,  12910,
904      12539,  12167,  11793,  11416,  11039,  10659,  10278,   9896,
905       9512,   9126,   8739,   8351,   7961,   7571,   7179,   6786,
906       6392,   5997,   5602,   5205,   4808,   4409,   4011,   3611,
907       3211,   2811,   2410,   2009,   1607,   1206,    804,    402,
908          0,   -402,   -804,  -1206,  -1607,  -2009,  -2410,  -2811,
909      -3211,  -3611,  -4011,  -4409,  -4808,  -5205,  -5602,  -5997,
910      -6392,  -6786,  -7179,  -7571,  -7961,  -8351,  -8739,  -9126,
911      -9512,  -9896, -10278, -10659, -11039, -11416, -11793, -12167,
912     -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
913     -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
914     -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
915     -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
916     -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
917     -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
918     -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
919     -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
920     -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
921     -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
922     -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
923     -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
924     -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
925     -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
926     -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
927     -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
928     -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
929     -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
930     -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
931     -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
932     -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
933     -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
934     -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
935     -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
936     -12539, -12167, -11793, -11416, -11039, -10659, -10278,  -9896,
937      -9512,  -9126,  -8739,  -8351,  -7961,  -7571,  -7179,  -6786,
938      -6392,  -5997,  -5602,  -5205,  -4808,  -4409,  -4011,  -3611,
939      -3211,  -2811,  -2410,  -2009,  -1607,  -1206,   -804,   -402
940 };
941
942 int16 C4CosTable[512] = {
943              32767,  32765,  32758,  32745,  32728,  32706,  32679,  32647,
944      32610,  32568,  32521,  32469,  32413,  32351,  32285,  32214,
945      32138,  32057,  31971,  31881,  31785,  31685,  31581,  31471,
946      31357,  31237,  31114,  30985,  30852,  30714,  30572,  30425,
947      30273,  30117,  29956,  29791,  29621,  29447,  29269,  29086,
948      28898,  28707,  28511,  28310,  28106,  27897,  27684,  27466,
949      27245,  27020,  26790,  26557,  26319,  26077,  25832,  25583,
950      25330,  25073,  24812,  24547,  24279,  24007,  23732,  23453,
951      23170,  22884,  22594,  22301,  22005,  21706,  21403,  21097,
952      20787,  20475,  20159,  19841,  19519,  19195,  18868,  18537,
953      18204,  17869,  17530,  17189,  16846,  16499,  16151,  15800,
954      15446,  15090,  14732,  14372,  14010,  13645,  13278,  12910,
955      12539,  12167,  11793,  11416,  11039,  10659,  10278,   9896,
956       9512,   9126,   8739,   8351,   7961,   7571,   7179,   6786,
957       6392,   5997,   5602,   5205,   4808,   4409,   4011,   3611,
958       3211,   2811,   2410,   2009,   1607,   1206,    804,    402,
959          0,   -402,   -804,  -1206,  -1607,  -2009,  -2410,  -2811,
960      -3211,  -3611,  -4011,  -4409,  -4808,  -5205,  -5602,  -5997,
961      -6392,  -6786,  -7179,  -7571,  -7961,  -8351,  -8739,  -9126,
962      -9512,  -9896, -10278, -10659, -11039, -11416, -11793, -12167,
963     -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
964     -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
965     -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
966     -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
967     -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
968     -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
969     -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
970     -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
971     -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
972     -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
973     -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
974     -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
975     -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
976     -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
977     -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
978     -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
979     -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
980     -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
981     -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
982     -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
983     -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
984     -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
985     -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
986     -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
987     -12539, -12167, -11793, -11416, -11039, -10659, -10278,  -9896,
988          -9512,  -9126,  -8739,  -8351,  -7961,  -7571,  -7179,  -6786,
989      -6392,  -5997,  -5602,  -5205,  -4808,  -4409,  -4011,  -3611,
990      -3211,  -2811,  -2410,  -2009,  -1607,  -1206,   -804,   -402,
991          0,    402,    804,   1206,   1607,   2009,   2410,   2811,
992       3211,   3611,   4011,   4409,   4808,   5205,   5602,   5997,
993       6392,   6786,   7179,   7571,   7961,   8351,   8739,   9126,
994       9512,   9896,  10278,  10659,  11039,  11416,  11793,  12167,
995      12539,  12910,  13278,  13645,  14010,  14372,  14732,  15090,
996      15446,  15800,  16151,  16499,  16846,  17189,  17530,  17869,
997      18204,  18537,  18868,  19195,  19519,  19841,  20159,  20475,
998      20787,  21097,  21403,  21706,  22005,  22301,  22594,  22884,
999      23170,  23453,  23732,  24007,  24279,  24547,  24812,  25073,
1000      25330,  25583,  25832,  26077,  26319,  26557,  26790,  27020,
1001      27245,  27466,  27684,  27897,  28106,  28310,  28511,  28707,
1002      28898,  29086,  29269,  29447,  29621,  29791,  29956,  30117,
1003      30273,  30425,  30572,  30714,  30852,  30985,  31114,  31237,
1004      31357,  31471,  31581,  31685,  31785,  31881,  31971,  32057,
1005      32138,  32214,  32285,  32351,  32413,  32469,  32521,  32568,
1006      32610,  32647,  32679,  32706,  32728,  32745,  32758,  32765
1007 };