workaround a problem with the harmattan gcc
[drnoksnes] / seta010.cpp
1 /*******************************************************************************
2   Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  
4   (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and
5                             Jerremy Koot (jkoot@snes9x.com)
6
7   (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net)
8
9   (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net),
10                             funkyass (funkyass@spam.shaw.ca),
11                             Joel Yliluoma (http://iki.fi/bisqwit/)
12                             Kris Bleakley (codeviolation@hotmail.com),
13                             Matthew Kendora,
14                             Nach (n-a-c-h@users.sourceforge.net),
15                             Peter Bortas (peter@bortas.org) and
16                             zones (kasumitokoduck@yahoo.com)
17
18   C4 x86 assembler and some C emulation code
19   (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com),
20                             _Demo_ (_demo_@zsnes.com), and Nach
21
22   C4 C++ code
23   (c) Copyright 2003 Brad Jorsch
24
25   DSP-1 emulator code
26   (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson,
27                             John Weidman, neviksti (neviksti@hotmail.com),
28                             Kris Bleakley, Andreas Naive
29
30   DSP-2 emulator code
31   (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and
32                      Lord Nightmare (lord_nightmare@users.sourceforge.net
33
34   OBC1 emulator code
35   (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and
36                             Kris Bleakley
37   Ported from x86 assembler to C by sanmaiwashi
38
39   SPC7110 and RTC C++ emulator code
40   (c) Copyright 2002 Matthew Kendora with research by
41                      zsKnight, John Weidman, and Dark Force
42
43   S-DD1 C emulator code
44   (c) Copyright 2003 Brad Jorsch with research by
45                      Andreas Naive and John Weidman
46  
47   S-RTC C emulator code
48   (c) Copyright 2001 John Weidman
49   
50   ST010 C++ emulator code
51   (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora
52
53   Super FX x86 assembler emulator code 
54   (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault 
55
56   Super FX C emulator code 
57   (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman
58
59
60   SH assembler code partly based on x86 assembler code
61   (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) 
62
63  
64   Specific ports contains the works of other authors. See headers in
65   individual files.
66  
67   Snes9x homepage: http://www.snes9x.com
68  
69   Permission to use, copy, modify and distribute Snes9x in both binary and
70   source form, for non-commercial purposes, is hereby granted without fee,
71   providing that this license information and copyright notice appear with
72   all copies and any derived work.
73  
74   This software is provided 'as-is', without any express or implied
75   warranty. In no event shall the authors be held liable for any damages
76   arising from the use of this software.
77  
78   Snes9x is freeware for PERSONAL USE only. Commercial users should
79   seek permission of the copyright holders first. Commercial use includes
80   charging money for Snes9x or software derived from Snes9x.
81  
82   The copyright holders request that bug fixes and improvements to the code
83   should be forwarded to them so everyone can benefit from the modifications
84   in future versions.
85  
86   Super NES and Super Nintendo Entertainment System are trademarks of
87   Nintendo Co., Limited and its subsidiary companies.
88 *******************************************************************************/
89 //#include "port.h"
90 #include "memmap.h"
91 #include "seta.h"
92
93 // Mode 7 scaling constants for all raster lines
94 const int16 ST010_M7Scale[176] = {
95         0x0380,  0x0325,  0x02da,  0x029c,  0x0268,  0x023b,  0x0215,  0x01f3,
96         0x01d5,  0x01bb,  0x01a3,  0x018e,  0x017b,  0x016a,  0x015a,  0x014b,
97         0x013e,  0x0132,  0x0126,  0x011c,  0x0112,  0x0109,  0x0100,  0x00f8,
98         0x00f0,  0x00e9,  0x00e3,  0x00dc,  0x00d6,  0x00d1,  0x00cb,  0x00c6,
99         0x00c1,  0x00bd,  0x00b8,  0x00b4,  0x00b0,  0x00ac,  0x00a8,  0x00a5,
100         0x00a2,  0x009e,  0x009b,  0x0098,  0x0095,  0x0093,  0x0090,  0x008d,
101         0x008b,  0x0088,  0x0086,  0x0084,  0x0082,  0x0080,  0x007e,  0x007c,
102         0x007a,  0x0078,  0x0076,  0x0074,  0x0073,  0x0071,  0x006f,  0x006e,
103         0x006c,  0x006b,  0x0069,  0x0068,  0x0067,  0x0065,  0x0064,  0x0063,
104         0x0062,  0x0060,  0x005f,  0x005e,  0x005d,  0x005c,  0x005b,  0x005a,
105         0x0059,  0x0058,  0x0057,  0x0056,  0x0055,  0x0054,  0x0053,  0x0052,
106         0x0051,  0x0051,  0x0050,  0x004f,  0x004e,  0x004d,  0x004d,  0x004c,
107         0x004b,  0x004b,  0x004a,  0x0049,  0x0048,  0x0048,  0x0047,  0x0047,
108         0x0046,  0x0045,  0x0045,  0x0044,  0x0044,  0x0043,  0x0042,  0x0042,
109         0x0041,  0x0041,  0x0040,  0x0040,  0x003f,  0x003f,  0x003e,  0x003e,
110         0x003d,  0x003d,  0x003c,  0x003c,  0x003b,  0x003b,  0x003a,  0x003a,
111         0x003a,  0x0039,  0x0039,  0x0038,  0x0038,  0x0038,  0x0037,  0x0037,
112         0x0036,  0x0036,  0x0036,  0x0035,  0x0035,  0x0035,  0x0034,  0x0034,
113         0x0034,  0x0033,  0x0033,  0x0033,  0x0032,  0x0032,  0x0032,  0x0031,
114         0x0031,  0x0031,  0x0030,  0x0030,  0x0030,  0x0030,  0x002f,  0x002f,
115         0x002f,  0x002e,  0x002e,  0x002e,  0x002e,  0x002d,  0x002d,  0x002d,
116         0x002d,  0x002c,  0x002c,  0x002c,  0x002c,  0x002b,  0x002b,  0x002b
117 };
118
119 // H-DMA hack
120 bool seta_hack;
121
122 //temporary Op04 requirement
123 #include <math.h>
124
125 #ifndef PI
126 #define PI 3.1415926535897932384626433832795
127 #endif
128
129 ST010_Regs ST010;
130
131 uint8 S9xGetST010(uint32 Address)
132 {
133         if(!(Address&0x80000))
134                 return 0x80;
135
136         if((Address&0xFFF)==0x20)
137                 return ST010.op_reg;
138         if ((Address&0xFFF)==0x21)
139                 return ST010.execute;
140         return Memory.SRAM[Address&CPU.Memory_SRAMMask];
141 }
142
143 const int16 ST010_SinTable[256] = {
144          0x0000,  0x0324,  0x0648,  0x096a,  0x0c8c,  0x0fab,  0x12c8,  0x15e2,
145          0x18f9,  0x1c0b,  0x1f1a,  0x2223,  0x2528,  0x2826,  0x2b1f,  0x2e11,
146          0x30fb,  0x33df,  0x36ba,  0x398c,  0x3c56,  0x3f17,  0x41ce,  0x447a,
147          0x471c,  0x49b4,  0x4c3f,  0x4ebf,  0x5133,  0x539b,  0x55f5,  0x5842,
148          0x5a82,  0x5cb3,  0x5ed7,  0x60eb,  0x62f1,  0x64e8,  0x66cf,  0x68a6,
149          0x6a6d,  0x6c23,  0x6dc9,  0x6f5e,  0x70e2,  0x7254,  0x73b5,  0x7504,
150          0x7641,  0x776b,  0x7884,  0x7989,  0x7a7c,  0x7b5c,  0x7c29,  0x7ce3,
151          0x7d89,  0x7e1d,  0x7e9c,  0x7f09,  0x7f61,  0x7fa6,  0x7fd8,  0x7ff5,
152          0x7fff,  0x7ff5,  0x7fd8,  0x7fa6,  0x7f61,  0x7f09,  0x7e9c,  0x7e1d,
153          0x7d89,  0x7ce3,  0x7c29,  0x7b5c,  0x7a7c,  0x7989,  0x7884,  0x776b,
154          0x7641,  0x7504,  0x73b5,  0x7254,  0x70e2,  0x6f5e,  0x6dc9,  0x6c23,
155          0x6a6d,  0x68a6,  0x66cf,  0x64e8,  0x62f1,  0x60eb,  0x5ed7,  0x5cb3,
156          0x5a82,  0x5842,  0x55f5,  0x539b,  0x5133,  0x4ebf,  0x4c3f,  0x49b4,
157          0x471c,  0x447a,  0x41ce,  0x3f17,  0x3c56,  0x398c,  0x36ba,  0x33df,
158          0x30fb,  0x2e11,  0x2b1f,  0x2826,  0x2528,  0x2223,  0x1f1a,  0x1c0b,
159          0x18f8,  0x15e2,  0x12c8,  0x0fab,  0x0c8c,  0x096a,  0x0648,  0x0324,
160          0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2,
161         -0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11,
162         -0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a,
163         -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842,
164         -0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6,
165         -0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504,
166         -0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3,
167         -0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5,
168         -0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d,
169         -0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b,
170         -0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23,
171         -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3,
172         -0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3,
173         -0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de,
174         -0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b,
175         -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324};
176
177 const unsigned char ST010_ArcTan[32][32] = {
178         { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
179           0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80},
180         { 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
181           0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf},
182         { 0x80, 0x93, 0xa0, 0xa8, 0xad, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb,
183           0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd},
184         { 0x80, 0x8d, 0x98, 0xa0, 0xa6, 0xaa, 0xad, 0xb0, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8,
185           0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc},
186         { 0x80, 0x8a, 0x93, 0x9a, 0xa0, 0xa5, 0xa8, 0xab, 0xad, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5,
187           0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb},
188         { 0x80, 0x88, 0x90, 0x96, 0x9b, 0xa0, 0xa4, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
189           0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9},
190         { 0x80, 0x87, 0x8d, 0x93, 0x98, 0x9c, 0xa0, 0xa3, 0xa6, 0xa8, 0xaa, 0xac, 0xad, 0xae, 0xb0, 0xb0,
191           0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8},
192         { 0x80, 0x86, 0x8b, 0x90, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae,
193           0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7},
194         { 0x80, 0x85, 0x8a, 0x8f, 0x93, 0x97, 0x9a, 0x9d, 0xa0, 0xa2, 0xa5, 0xa6, 0xa8, 0xaa, 0xab, 0xac,
195           0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5},
196         { 0x80, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x98, 0x9b, 0x9e, 0xa0, 0xa0, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa,
197           0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4},
198         { 0x80, 0x84, 0x88, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9b, 0x9e, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa8,
199           0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3},
200         { 0x80, 0x84, 0x87, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, 0xa6,
201           0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2},
202         { 0x80, 0x83, 0x87, 0x8a, 0x8d, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5,
203           0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1},
204         { 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa2, 0xa3,
205           0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0},
206         { 0x80, 0x83, 0x86, 0x89, 0x8b, 0x8e, 0x90, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1,
207           0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf},
208         { 0x80, 0x83, 0x85, 0x88, 0x8b, 0x8d, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa0,
209           0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae},
210         { 0x80, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9a, 0x9c, 0x9d, 0x9f,
211           0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad},
212         { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9d,
213           0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac},
214         { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9c,
215           0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab},
216         { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x9a, 0x9b,
217           0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa},
218         { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x99, 0x9a,
219           0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9},
220         { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8f, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99,
221           0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8},
222         { 0x80, 0x82, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98,
223           0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7},
224         { 0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98,
225           0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6},
226         { 0x80, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x96, 0x97,
227           0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5},
228         { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x94, 0x95, 0x96,
229           0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4},
230         { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95,
231           0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4},
232         { 0x80, 0x82, 0x83, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95,
233           0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3},
234         { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94,
235           0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2},
236         { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
237           0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1},
238         { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93,
239           0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1},
240         { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
241           0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0}};
242
243 short ST010_Sin(short Theta)
244 {
245         return ST010_SinTable[(Theta >> 8) & 0xff];
246 }
247
248 short ST010_Cos(short Theta)
249 {
250         return ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff];
251 }
252
253 void ST010_OP01(short x0, short y0, short &x1, short &y1, short &Quadrant, short &Theta)
254 {
255         if ((x0 < 0) && (y0 < 0))
256         {       
257                 x1 = -x0;
258                 y1 = -y0;
259                 Quadrant = -0x8000;
260         }
261         else if (x0 < 0)
262         {
263                 x1 = y0;
264                 y1 = -x0;
265                 Quadrant = -0x4000;
266         }
267         else if (y0 < 0)
268         {
269                 x1 = -y0;
270                 y1 = x0;
271                 Quadrant = 0x4000;
272         }
273         else
274         {
275                 x1 = x0;
276                 y1 = y0;        
277                 Quadrant = 0x0000;
278         }
279
280         while ((x1 > 0x1f) || (y1 > 0x1f))
281         {
282                 if (x1 > 1) x1 >>= 1;
283                 if (y1 > 1) y1 >>= 1;
284         }
285
286         if (y1 == 0) Quadrant += 0x4000;
287
288         Theta = (ST010_ArcTan[y1][x1] << 8) ^ Quadrant;
289 }
290
291 void ST010_Scale(short Multiplier, short X0, short Y0, int &X1, int &Y1)
292 {
293         X1 = X0 * Multiplier << 1;
294         Y1 = Y0 * Multiplier << 1;
295 }
296
297 void ST010_Multiply(short Multiplicand, short Multiplier, int &Product)
298 {
299         Product = Multiplicand * Multiplier << 1;
300 }
301
302 void ST010_Rotate(short Theta, short X0, short Y0, short &X1, short &Y1)
303 {
304         X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15);
305         Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15);
306 }
307
308 void SETA_Distance(short Y0, short X0, short &Distance)
309 {
310         if (X0 < 0) X0 = -X0;
311         if (Y0 < 0) Y0 = -Y0;
312         Distance = ((X0 * 0x7af0) + 0x4000) >> 15;
313 }
314
315 void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) 
316 {
317         bool Sorted;
318         uint16 Temp;
319
320         if (Positions > 1)
321                 do {
322                         Sorted = true;
323                         for (int i = 0; i < Positions - 1; i++)
324                                 if (Places[i] < Places[i + 1]) 
325                                 {
326                                         Temp = Places[i + 1];
327                                         Places[i + 1] = Places[i];
328                                         Places[i] = Temp;
329
330                                         Temp = Drivers[i + 1];
331                                         Drivers[i + 1] = Drivers[i];
332                                         Drivers[i] = Temp;
333
334                                         Sorted = false;
335                                 }
336                         Positions--;
337                 } while (!Sorted);
338 }
339
340 #define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset]
341
342 void S9xSetST010(uint32 Address, uint8 Byte)
343 {
344         if(!(Address&0x80000))
345         {
346                 ST010.control_enable=TRUE;
347                 return;
348         }
349         //printf("Write %06X:%02X\n", Address, Byte);
350
351         if((Address &0xFFF) ==0x20 && ST010.control_enable)
352                 ST010.op_reg=Byte;
353         if((Address &0xFFF) ==0x21 && ST010.control_enable)
354                 ST010.execute=Byte;
355         else Memory.SRAM[Address&CPU.Memory_SRAMMask]=Byte;
356
357         if(ST010.execute&0x80)
358         {
359                 switch(ST010.op_reg)
360                 {
361                 // Sorts Driver Placements
362                 //
363                 // Input
364                 //   0x0024-0x0025 : Positions
365                 //   0x0040-0x007f : Places
366                 //   0x0080-0x00ff : Drivers
367                 // Output
368                 //   0x0040-0x007f : Places
369                 //   0x0080-0x00ff : Drivers
370                 //
371                 case 0x02:
372                         {
373 #ifdef FAST_LSB_WORD_ACCESS
374                                 ST010_SortDrivers(*(short*)&SRAM[0x0024], (uint16*) (SRAM + 0x0040), (uint16*) (SRAM + 0x0080));
375 #else
376                                 uint16 Places[32];
377                                 uint16 Positions = ST010_WORD(0x0024);
378                                 int Pos, Offset;
379
380                                 Offset = 0;
381
382                                 for (Pos = 0; Pos < Positions; Pos++) 
383                                 {
384                                         Places[Pos] = ST010_WORD(0x0040 + Offset);
385                                         Offset += 2;
386                                 }
387
388                                 ST010_SortDrivers(Positions, Places, (uint16*) (SRAM + 0x0080));
389
390                                 Offset = 0;
391
392                                 for (Pos = 0; Pos < Positions; Pos++)
393                                 {
394                                         SRAM[0x0040 + Offset]=(uint8)(Places[Pos]);
395                                         SRAM[0x0041 + Offset]=(uint8)(Places[Pos] >> 8);
396                                         Offset += 2;
397                                 }
398 #endif                  
399                                 break;
400                                 
401                         }
402
403                 // Two Dimensional Coordinate Scale
404                 //
405                 // Input
406                 //   0x0000-0x0001 : X0 (signed)
407                 //   0x0002-0x0003 : Y0 (signed)
408                 //   0x0004-0x0005 : Multiplier (signed)
409                 // Output
410                 //   0x0010-0x0013 : X1 (signed)
411                 //   0x0014-0x0017 : Y1 (signed)
412                 //
413                 case 0x03:
414                         {
415 #ifdef FAST_LSB_WORD_ACCESS
416                                 ST010_Scale(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002],
417                                         (int&) Memory.SRAM[0x0010], (int&) Memory.SRAM[0x0014]);
418 #else
419                                 int x1, y1;
420
421                                 ST010_Scale(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1);
422
423                                 Memory.SRAM[0x0010]=(uint8)(x1);
424                                 Memory.SRAM[0x0011]=(uint8)(x1 >> 8);
425                                 Memory.SRAM[0x0012]=(uint8)(x1 >> 16);
426                                 Memory.SRAM[0x0013]=(uint8)(x1 >> 24);
427                                 Memory.SRAM[0x0014]=(uint8)(y1);
428                                 Memory.SRAM[0x0015]=(uint8)(y1 >> 8);
429                                 Memory.SRAM[0x0016]=(uint8)(y1 >> 16);
430                                 Memory.SRAM[0x0017]=(uint8)(y1 >> 24);
431 #endif
432                                 break;
433                         }
434
435                 // 16-bit Multiplication
436                 //
437                 // Input
438                 //   0x0000-0x0001 : Multiplcand (signed)
439                 //   0x0002-0x0003 : Multiplier (signed)
440                 // Output
441                 //   0x0010-0x0013 : Product (signed)
442                 //
443                 case 0x06:
444                         {
445 #ifdef FAST_LSB_WORD_ACCESS
446                                 ST010_Multiply(*(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], (int&) Memory.SRAM[0x0010]);
447 #else
448                                 int Product;
449
450                                 ST010_Multiply(ST010_WORD(0x0000), ST010_WORD(0x0002), Product);
451
452                                 Memory.SRAM[0x0010]=(uint8)(Product);
453                                 Memory.SRAM[0x0011]=(uint8)(Product >> 8);
454                                 Memory.SRAM[0x0012]=(uint8)(Product >> 16);
455                                 Memory.SRAM[0x0013]=(uint8)(Product >> 24);
456 #endif
457                                 break;
458                         }
459
460                 // Mode 7 Raster Data Calculation
461                 //
462                 // Input
463                 //   0x0000-0x0001 : Angle (signed)
464                 // Output
465                 //   0x00f0-0x024f : Mode 7 Matrix A
466                 //   0x0250-0x03af : Mode 7 Matrix B
467                 //   0x03b0-0x050f : Mode 7 Matrix C
468                 //   0x0510-0x066f : Mode 7 Matrix D
469                 //
470                 case 0x07:
471                         {
472                                 int16 data;
473                                 int32 offset = 0;
474                                 int16 Theta = ST010_WORD(0x0000);
475
476                                 for (int32 line = 0; line < 176; line++)
477                                 {
478                                         // Calculate Mode 7 Matrix A/D data
479                                         data = ST010_M7Scale[line] * ST010_Cos(Theta) >> 15;
480                                 
481                                         Memory.SRAM[0x00f0 + offset]=(uint8)(data);
482                                         Memory.SRAM[0x00f1 + offset]=(uint8)(data >> 8);
483                                         Memory.SRAM[0x0510 + offset]=(uint8)(data);
484                                         Memory.SRAM[0x0511 + offset]=(uint8)(data >> 8); 
485
486                                         // Calculate Mode 7 Matrix B/C data
487                                         data = ST010_M7Scale[line] * ST010_Sin(Theta) >> 15;  
488
489                                         Memory.SRAM[0x0250 + offset]=(uint8)(data);
490                                         Memory.SRAM[0x0251 + offset]=(uint8)(data >> 8);
491                 
492                                         if (data) data = ~data;
493                                  
494                                         Memory.SRAM[0x03b0 + offset]=(uint8)(data);
495                                         Memory.SRAM[0x03b1 + offset]=(uint8)(data >> 8);
496                 
497                                         offset += 2;
498                                 }
499
500                                 // Shift Angle for use with Lookup table
501                                 Memory.SRAM[0x00] = Memory.SRAM[0x01];
502                                 Memory.SRAM[0x01] = 0x00;
503
504                                 break;
505                         }
506
507                 // Two dimensional Coordinate Rotation
508                 //
509                 // Input
510                 //   0x0000-0x0001 : X0 (signed)
511                 //   0x0002-0x0003 : Y0 (signed)
512                 //   0x0004-0x0005 : Angle (signed)
513                 // Output
514                 //   0x0010-0x0011 : X1 (signed)
515                 //   0x0012-0x0013 : Y1 (signed)
516                 //
517                 case 0x08:
518                         {
519 #ifdef FAST_LSB_WORD_ACCESS
520                                 ST010_Rotate(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002],
521                                         (short&) Memory.SRAM[0x0010], (short&) Memory.SRAM[0x0012]);
522 #else
523                                 short x1, y1;
524
525                                 ST010_Rotate(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1);
526
527                                 Memory.SRAM[0x0010]=(uint8)(x1);
528                                 Memory.SRAM[0x0011]=(uint8)(x1 >> 8);
529                                 Memory.SRAM[0x0012]=(uint8)(y1);
530                                 Memory.SRAM[0x0013]=(uint8)(y1 >> 8);
531 #endif
532                                 break;
533                         }
534
535                 // Input
536                 //   0x0000-0x0001 : DX (signed)
537                 //   0x0002-0x0003 : DY (signed)
538                 // Output
539                 //   0x0010-0x0011 : Angle (signed)
540                 //
541                 case 0x01:
542                         {
543                                 Memory.SRAM[0x0006] = Memory.SRAM[0x0002];
544                                 Memory.SRAM[0x0007] = Memory.SRAM[0x0003];
545
546 #ifdef FAST_LSB_WORD_ACCESS
547                                 ST010_OP01(*(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002],
548                                         (short&) Memory.SRAM[0x0000], (short&) Memory.SRAM[0x0002],
549                                         (short&) Memory.SRAM[0x0004], (short&) Memory.SRAM[0x0010]);
550 #else
551                                 short x1, y1, Quadrant, Theta;
552
553                                 ST010_OP01(ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1, Quadrant, Theta);
554
555                                 Memory.SRAM[0x0000]=(uint8)(x1);
556                                 Memory.SRAM[0x0001]=(uint8)(x1 >> 8);
557                                 Memory.SRAM[0x0002]=(uint8)(y1);
558                                 Memory.SRAM[0x0003]=(uint8)(y1 >> 8);
559                                 Memory.SRAM[0x0004]=(uint8)(Quadrant);
560                                 Memory.SRAM[0x0005]=(uint8)(Quadrant >> 8);
561                                 Memory.SRAM[0x0010]=(uint8)(Theta);
562                                 Memory.SRAM[0x0011]=(uint8)(Theta >> 8);
563 #endif
564                                 break;
565                 }
566
567                 // calculate the vector length of (x,y)
568                 case 0x04:
569                         {
570                                 int16 square, x,y;
571 #ifdef FAST_LSB_WORD_ACCESS
572                                 x=*((int16*)Memory.SRAM);
573                                 y=*((int16*)&Memory.SRAM[2]);
574 #else
575                                 x=Memory.SRAM[0]|(Memory.SRAM[1]<<8);
576                                 y=Memory.SRAM[2]|(Memory.SRAM[3]<<8);
577 #endif
578                                 square=(int16)sqrt((double)(y*y+x*x));
579                                 //SETA_Distance( x,y,square );
580
581 #ifdef FAST_LSB_WORD_ACCESS
582                                 *((int16*)&Memory.SRAM[0x10])=square;
583 #else
584                                 Memory.SRAM[0x10]=(uint8)(square);
585                                 Memory.SRAM[0x11]=(uint8)(square>>8);
586 #endif
587                                 break;
588                         }
589
590                 // calculate AI orientation based on specific guidelines
591                 case 0x05:
592                         {
593                                 int dx,dy;
594                                 int16 a1,b1,c1;
595                                 uint16 o1;
596
597                                 bool wrap=false;
598
599                                 // target (x,y) coordinates
600                                 int16 ypos_max = ST010_WORD(0x00C0);
601                                 int16 xpos_max = ST010_WORD(0x00C2);
602
603                                 // current coordinates and direction
604                                 int32 ypos = SRAM[0xC4]|(SRAM[0xC5]<<8)|(SRAM[0xC6]<<16)|(SRAM[0xC7]<<24);
605                                 int32 xpos = SRAM[0xC8]|(SRAM[0xC9]<<8)|(SRAM[0xCA]<<16)|(SRAM[0xCB]<<24);
606                                 uint16 rot = SRAM[0xCC]|(SRAM[0xCD]<<8);
607
608                                 // physics
609                                 uint16 speed = ST010_WORD(0x00D4);
610                                 uint16 accel = ST010_WORD(0x00D6);
611                                 uint16 speed_max = ST010_WORD(0x00D8);
612
613                                 // special condition acknowledgment
614                                 int16 system = ST010_WORD(0x00DA);
615                                 int16 flags = ST010_WORD(0x00DC);
616
617                                 // new target coordinates
618                                 int16 ypos_new = ST010_WORD(0x00DE);
619                                 int16 xpos_new = ST010_WORD(0x00E0);
620
621                                 // mask upper bit
622                                 xpos_new &= 0x7FFF;
623
624                                 // get the current distance
625                                 dx = xpos_max-(xpos>>16);
626                                 dy = ypos_max-(ypos>>16);
627
628                                 // quirk: clear and move in9
629                                 SRAM[0xD2]=0xFF;
630                                 SRAM[0xD3]=0xFF;
631                                 SRAM[0xDA]=0;
632                                 SRAM[0xDB]=0;
633
634                                 // grab the target angle
635                                 ST010_OP01(dy,dx,a1,b1,c1,(int16 &)o1);
636
637                                 // check for wrapping
638                                 //if((o1<0x6000 && rot>0xA000) ||
639                                         // (rot<0x6000 && o1>0xA000))
640                                 //if(o1<rot)
641                                 if(abs(o1-rot)>0x8000)
642                                 {
643                                         o1+=0x8000;
644                                         rot+=0x8000;
645                                         wrap=true;
646                                 }
647                                 //o1=0x0000;
648                                 //rot=0xFF00;
649
650                                 uint16 old_speed;
651
652                                 old_speed = speed;
653
654                                 // special case
655                                 if(abs(o1-rot)==0x8000)
656                                 {
657                                         speed = 0x100;
658                                 }
659                                 // slow down for sharp curves
660                                 else if(abs(o1-rot)>=0x1000)
661                                 {
662                                         uint32 slow = abs(o1-rot);
663                                         slow >>= 4;     // scaling
664                                         speed -= slow;
665                                 }
666                                 // otherwise accelerate
667                                 else
668                                 {
669                                         speed += accel;
670                                         if(speed > speed_max)
671                                         {
672                                                 // clip speed
673                                                 speed = speed_max;
674                                         }
675                                 }
676
677                                 // prevent negative/positive overflow
678                                 if(abs(old_speed-speed)>0x8000) {
679                                         if(old_speed<speed) speed=0;
680                                         else speed=0xff00;
681                                 }
682
683                                 // adjust direction by so many degrees
684                                 // be careful of negative adjustments
685                                 if( (o1>rot && (o1-rot)>0x80) ||
686                                                 (o1<rot && (rot-o1)>=0x80) )
687                                 {
688                                         if(o1<rot) rot-=0x280;
689                                         else if(o1>rot) rot+=0x280;
690                                 }
691
692                                 // turn off wrapping
693                                 if(wrap) rot-=0x8000;
694
695                                 // now check the distances (store for later)
696                                 dx = (xpos_max<<16)-xpos;
697                                 dy = (ypos_max<<16)-ypos;
698                                 dx>>=16;
699                                 dy>>=16;
700
701                                 // if we're in so many units of the target, signal it
702                                 if( ( system && (dy<=6 && dy>=-8) && (dx<=126 && dx>=-128)) ||
703                                                 (!system && (dx<=6 && dx>=-8) && (dy<=126 && dy>=-128)) )
704                                 {
705                                         // announce our new destination and flag it
706                                         xpos_max = xpos_new&0x7FFF;
707                                         ypos_max = ypos_new;
708                                         flags |= 0x08;
709                                 }
710
711                                 // update position
712                                 xpos -= (ST010_Cos(rot) * 0x400 >> 15) * (speed >> 8) << 1;
713                                 ypos -= (ST010_Sin(rot) * 0x400 >> 15) * (speed >> 8) << 1;
714
715                                 // quirk: mask upper byte
716                                 xpos &= 0x1FFFFFFF;
717                                 ypos &= 0x1FFFFFFF;
718
719                                 SRAM[0x00C0]=(uint8)(ypos_max);
720                                 SRAM[0x00C1]=(uint8)(ypos_max >> 8);
721                                 SRAM[0x00C2]=(uint8)(xpos_max);
722                                 SRAM[0x00C3]=(uint8)(xpos_max >> 8);
723                                 SRAM[0x00C4]=(uint8)(ypos);
724                                 SRAM[0x00C5]=(uint8)(ypos >> 8);
725                                 SRAM[0x00C6]=(uint8)(ypos >> 16);
726                                 SRAM[0x00C7]=(uint8)(ypos >> 24);
727                                 SRAM[0x00C8]=(uint8)(xpos);
728                                 SRAM[0x00C9]=(uint8)(xpos >> 8);
729                                 SRAM[0x00CA]=(uint8)(xpos >> 16);
730                                 SRAM[0x00CB]=(uint8)(xpos >> 24);
731                                 SRAM[0x00CC]=(uint8)(rot);
732                                 SRAM[0x00CD]=(uint8)(rot >> 8);
733                                 SRAM[0x00D4]=(uint8)(speed);
734                                 SRAM[0x00D5]=(uint8)(speed >> 8);
735                                 SRAM[0x00DC]=(uint8)(flags);
736                                 SRAM[0x00DD]=(uint8)(flags >> 8);
737
738                                 break;
739                         }
740
741                 default:
742                         printf("Unknown Op\n");
743                         break;
744                 }
745
746                 // lower signal: op processed
747                 ST010.op_reg=0;
748                 ST010.execute=0;
749         }
750 }
751