rlm@1
|
1 #include <cmath>
|
rlm@1
|
2 #include <cstdlib>
|
rlm@1
|
3 #include <cstring>
|
rlm@1
|
4
|
rlm@1
|
5 #include "bios.h"
|
rlm@1
|
6 #include "../common/System.h"
|
rlm@1
|
7 #include "GBA.h"
|
rlm@1
|
8 #include "GBACheats.h" // FIXME: SDL build requires this
|
rlm@1
|
9 #include "GBAinline.h"
|
rlm@1
|
10 #include "GBAGlobals.h"
|
rlm@1
|
11
|
rlm@1
|
12 s16 sineTable[256] = {
|
rlm@1
|
13 (s16)0x0000, (s16)0x0192, (s16)0x0323, (s16)0x04B5, (s16)0x0645, (s16)0x07D5, (s16)0x0964, (s16)0x0AF1,
|
rlm@1
|
14 (s16)0x0C7C, (s16)0x0E05, (s16)0x0F8C, (s16)0x1111, (s16)0x1294, (s16)0x1413, (s16)0x158F, (s16)0x1708,
|
rlm@1
|
15 (s16)0x187D, (s16)0x19EF, (s16)0x1B5D, (s16)0x1CC6, (s16)0x1E2B, (s16)0x1F8B, (s16)0x20E7, (s16)0x223D,
|
rlm@1
|
16 (s16)0x238E, (s16)0x24DA, (s16)0x261F, (s16)0x275F, (s16)0x2899, (s16)0x29CD, (s16)0x2AFA, (s16)0x2C21,
|
rlm@1
|
17 (s16)0x2D41, (s16)0x2E5A, (s16)0x2F6B, (s16)0x3076, (s16)0x3179, (s16)0x3274, (s16)0x3367, (s16)0x3453,
|
rlm@1
|
18 (s16)0x3536, (s16)0x3612, (s16)0x36E5, (s16)0x37AF, (s16)0x3871, (s16)0x392A, (s16)0x39DA, (s16)0x3A82,
|
rlm@1
|
19 (s16)0x3B20, (s16)0x3BB6, (s16)0x3C42, (s16)0x3CC5, (s16)0x3D3E, (s16)0x3DAE, (s16)0x3E14, (s16)0x3E71,
|
rlm@1
|
20 (s16)0x3EC5, (s16)0x3F0E, (s16)0x3F4E, (s16)0x3F84, (s16)0x3FB1, (s16)0x3FD3, (s16)0x3FEC, (s16)0x3FFB,
|
rlm@1
|
21 (s16)0x4000, (s16)0x3FFB, (s16)0x3FEC, (s16)0x3FD3, (s16)0x3FB1, (s16)0x3F84, (s16)0x3F4E, (s16)0x3F0E,
|
rlm@1
|
22 (s16)0x3EC5, (s16)0x3E71, (s16)0x3E14, (s16)0x3DAE, (s16)0x3D3E, (s16)0x3CC5, (s16)0x3C42, (s16)0x3BB6,
|
rlm@1
|
23 (s16)0x3B20, (s16)0x3A82, (s16)0x39DA, (s16)0x392A, (s16)0x3871, (s16)0x37AF, (s16)0x36E5, (s16)0x3612,
|
rlm@1
|
24 (s16)0x3536, (s16)0x3453, (s16)0x3367, (s16)0x3274, (s16)0x3179, (s16)0x3076, (s16)0x2F6B, (s16)0x2E5A,
|
rlm@1
|
25 (s16)0x2D41, (s16)0x2C21, (s16)0x2AFA, (s16)0x29CD, (s16)0x2899, (s16)0x275F, (s16)0x261F, (s16)0x24DA,
|
rlm@1
|
26 (s16)0x238E, (s16)0x223D, (s16)0x20E7, (s16)0x1F8B, (s16)0x1E2B, (s16)0x1CC6, (s16)0x1B5D, (s16)0x19EF,
|
rlm@1
|
27 (s16)0x187D, (s16)0x1708, (s16)0x158F, (s16)0x1413, (s16)0x1294, (s16)0x1111, (s16)0x0F8C, (s16)0x0E05,
|
rlm@1
|
28 (s16)0x0C7C, (s16)0x0AF1, (s16)0x0964, (s16)0x07D5, (s16)0x0645, (s16)0x04B5, (s16)0x0323, (s16)0x0192,
|
rlm@1
|
29 (s16)0x0000, (s16)0xFE6E, (s16)0xFCDD, (s16)0xFB4B, (s16)0xF9BB, (s16)0xF82B, (s16)0xF69C, (s16)0xF50F,
|
rlm@1
|
30 (s16)0xF384, (s16)0xF1FB, (s16)0xF074, (s16)0xEEEF, (s16)0xED6C, (s16)0xEBED, (s16)0xEA71, (s16)0xE8F8,
|
rlm@1
|
31 (s16)0xE783, (s16)0xE611, (s16)0xE4A3, (s16)0xE33A, (s16)0xE1D5, (s16)0xE075, (s16)0xDF19, (s16)0xDDC3,
|
rlm@1
|
32 (s16)0xDC72, (s16)0xDB26, (s16)0xD9E1, (s16)0xD8A1, (s16)0xD767, (s16)0xD633, (s16)0xD506, (s16)0xD3DF,
|
rlm@1
|
33 (s16)0xD2BF, (s16)0xD1A6, (s16)0xD095, (s16)0xCF8A, (s16)0xCE87, (s16)0xCD8C, (s16)0xCC99, (s16)0xCBAD,
|
rlm@1
|
34 (s16)0xCACA, (s16)0xC9EE, (s16)0xC91B, (s16)0xC851, (s16)0xC78F, (s16)0xC6D6, (s16)0xC626, (s16)0xC57E,
|
rlm@1
|
35 (s16)0xC4E0, (s16)0xC44A, (s16)0xC3BE, (s16)0xC33B, (s16)0xC2C2, (s16)0xC252, (s16)0xC1EC, (s16)0xC18F,
|
rlm@1
|
36 (s16)0xC13B, (s16)0xC0F2, (s16)0xC0B2, (s16)0xC07C, (s16)0xC04F, (s16)0xC02D, (s16)0xC014, (s16)0xC005,
|
rlm@1
|
37 (s16)0xC000, (s16)0xC005, (s16)0xC014, (s16)0xC02D, (s16)0xC04F, (s16)0xC07C, (s16)0xC0B2, (s16)0xC0F2,
|
rlm@1
|
38 (s16)0xC13B, (s16)0xC18F, (s16)0xC1EC, (s16)0xC252, (s16)0xC2C2, (s16)0xC33B, (s16)0xC3BE, (s16)0xC44A,
|
rlm@1
|
39 (s16)0xC4E0, (s16)0xC57E, (s16)0xC626, (s16)0xC6D6, (s16)0xC78F, (s16)0xC851, (s16)0xC91B, (s16)0xC9EE,
|
rlm@1
|
40 (s16)0xCACA, (s16)0xCBAD, (s16)0xCC99, (s16)0xCD8C, (s16)0xCE87, (s16)0xCF8A, (s16)0xD095, (s16)0xD1A6,
|
rlm@1
|
41 (s16)0xD2BF, (s16)0xD3DF, (s16)0xD506, (s16)0xD633, (s16)0xD767, (s16)0xD8A1, (s16)0xD9E1, (s16)0xDB26,
|
rlm@1
|
42 (s16)0xDC72, (s16)0xDDC3, (s16)0xDF19, (s16)0xE075, (s16)0xE1D5, (s16)0xE33A, (s16)0xE4A3, (s16)0xE611,
|
rlm@1
|
43 (s16)0xE783, (s16)0xE8F8, (s16)0xEA71, (s16)0xEBED, (s16)0xED6C, (s16)0xEEEF, (s16)0xF074, (s16)0xF1FB,
|
rlm@1
|
44 (s16)0xF384, (s16)0xF50F, (s16)0xF69C, (s16)0xF82B, (s16)0xF9BB, (s16)0xFB4B, (s16)0xFCDD, (s16)0xFE6E
|
rlm@1
|
45 };
|
rlm@1
|
46
|
rlm@1
|
47 void BIOS_ArcTan()
|
rlm@1
|
48 {
|
rlm@1
|
49 #ifdef GBA_LOGGING
|
rlm@1
|
50 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
51 {
|
rlm@1
|
52 log("ArcTan: %08x (VCOUNT=%2d)\n",
|
rlm@1
|
53 reg[0].I,
|
rlm@1
|
54 VCOUNT);
|
rlm@1
|
55 }
|
rlm@1
|
56 #endif
|
rlm@1
|
57
|
rlm@1
|
58 s32 a = -((s32)(reg[0].I * reg[0].I)) >> 14;
|
rlm@1
|
59 s32 b = ((0xA9 * a) >> 14) + 0x390;
|
rlm@1
|
60 b = ((b * a) >> 14) + 0x91C;
|
rlm@1
|
61 b = ((b * a) >> 14) + 0xFB6;
|
rlm@1
|
62 b = ((b * a) >> 14) + 0x16AA;
|
rlm@1
|
63 b = ((b * a) >> 14) + 0x2081;
|
rlm@1
|
64 b = ((b * a) >> 14) + 0x3651;
|
rlm@1
|
65 b = ((b * a) >> 14) + 0xA2F9;
|
rlm@1
|
66 reg[0].I = (reg[0].I * b) >> 16;
|
rlm@1
|
67
|
rlm@1
|
68 #ifdef GBA_LOGGING
|
rlm@1
|
69 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
70 {
|
rlm@1
|
71 log("ArcTan: return=%08x\n",
|
rlm@1
|
72 reg[0].I);
|
rlm@1
|
73 }
|
rlm@1
|
74 #endif
|
rlm@1
|
75 }
|
rlm@1
|
76
|
rlm@1
|
77 void BIOS_ArcTan2()
|
rlm@1
|
78 {
|
rlm@1
|
79 #ifdef GBA_LOGGING
|
rlm@1
|
80 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
81 {
|
rlm@1
|
82 log("ArcTan2: %08x,%08x (VCOUNT=%2d)\n",
|
rlm@1
|
83 reg[0].I,
|
rlm@1
|
84 reg[1].I,
|
rlm@1
|
85 VCOUNT);
|
rlm@1
|
86 }
|
rlm@1
|
87 #endif
|
rlm@1
|
88
|
rlm@1
|
89 s16 x = reg[0].I;
|
rlm@1
|
90 s16 y = reg[1].I;
|
rlm@1
|
91
|
rlm@1
|
92 if (y == 0)
|
rlm@1
|
93 {
|
rlm@1
|
94 reg[0].I = 0x8000 & x;
|
rlm@1
|
95 reg[3].I = 0x170;
|
rlm@1
|
96 }
|
rlm@1
|
97 else
|
rlm@1
|
98 {
|
rlm@1
|
99 if (x == 0)
|
rlm@1
|
100 {
|
rlm@1
|
101 reg[0].I = (0x8000 & y) + 0x4000;
|
rlm@1
|
102 reg[3].I = 0x170;
|
rlm@1
|
103 }
|
rlm@1
|
104 else
|
rlm@1
|
105 {
|
rlm@1
|
106 if (abs(x) > abs(y))
|
rlm@1
|
107 {
|
rlm@1
|
108 reg[1].I = x;
|
rlm@1
|
109 reg[0].I = y << 14;
|
rlm@1
|
110 BIOS_Div();
|
rlm@1
|
111 BIOS_ArcTan();
|
rlm@1
|
112 if (x < 0)
|
rlm@1
|
113 reg[0].I = 0x8000 + reg[0].I;
|
rlm@1
|
114 else
|
rlm@1
|
115 reg[0].I = ((y & 0x8000) << 1) + reg[0].I;
|
rlm@1
|
116 reg[3].I = 0x170;
|
rlm@1
|
117 }
|
rlm@1
|
118 else
|
rlm@1
|
119 {
|
rlm@1
|
120 reg[0].I = x << 14;
|
rlm@1
|
121 BIOS_Div();
|
rlm@1
|
122 BIOS_ArcTan();
|
rlm@1
|
123 reg[0].I = (0x4000 + (y & 0x8000)) - reg[0].I;
|
rlm@1
|
124 reg[3].I = 0x170;
|
rlm@1
|
125 }
|
rlm@1
|
126 }
|
rlm@1
|
127 }
|
rlm@1
|
128
|
rlm@1
|
129 #ifdef GBA_LOGGING
|
rlm@1
|
130 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
131 {
|
rlm@1
|
132 log("ArcTan2: return=%08x\n",
|
rlm@1
|
133 reg[0].I);
|
rlm@1
|
134 }
|
rlm@1
|
135 #endif
|
rlm@1
|
136 }
|
rlm@1
|
137
|
rlm@1
|
138 void BIOS_BitUnPack()
|
rlm@1
|
139 {
|
rlm@1
|
140 #ifdef GBA_LOGGING
|
rlm@1
|
141 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
142 {
|
rlm@1
|
143 log("BitUnPack: %08x,%08x,%08x (VCOUNT=%2d)\n",
|
rlm@1
|
144 reg[0].I,
|
rlm@1
|
145 reg[1].I,
|
rlm@1
|
146 reg[2].I,
|
rlm@1
|
147 VCOUNT);
|
rlm@1
|
148 }
|
rlm@1
|
149 #endif
|
rlm@1
|
150
|
rlm@1
|
151 u32 source = reg[0].I;
|
rlm@1
|
152 u32 dest = reg[1].I;
|
rlm@1
|
153 u32 header = reg[2].I;
|
rlm@1
|
154
|
rlm@1
|
155 int len = CPUReadHalfWord(header);
|
rlm@1
|
156 // check address
|
rlm@1
|
157 int bits = CPUReadByte(header+2);
|
rlm@1
|
158 int revbits = 8 - bits;
|
rlm@1
|
159 // u32 value = 0;
|
rlm@1
|
160 u32 base = CPUReadMemory(header+4);
|
rlm@1
|
161 bool addBase = (base & 0x80000000) ? true : false;
|
rlm@1
|
162 base &= 0x7fffffff;
|
rlm@1
|
163 int dataSize = CPUReadByte(header+3);
|
rlm@1
|
164
|
rlm@1
|
165 int data = 0;
|
rlm@1
|
166 int bitwritecount = 0;
|
rlm@1
|
167 while (1)
|
rlm@1
|
168 {
|
rlm@1
|
169 len -= 1;
|
rlm@1
|
170 if (len < 0)
|
rlm@1
|
171 break;
|
rlm@1
|
172 int mask = 0xff >> revbits;
|
rlm@1
|
173 u8 b = CPUReadByte(source);
|
rlm@1
|
174 source++;
|
rlm@1
|
175 int bitcount = 0;
|
rlm@1
|
176 while (1)
|
rlm@1
|
177 {
|
rlm@1
|
178 if (bitcount >= 8)
|
rlm@1
|
179 break;
|
rlm@1
|
180 u32 d = b & mask;
|
rlm@1
|
181 u32 temp = d >> bitcount;
|
rlm@1
|
182 if (!temp && addBase)
|
rlm@1
|
183 {
|
rlm@1
|
184 temp += base;
|
rlm@1
|
185 }
|
rlm@1
|
186 data |= temp << bitwritecount;
|
rlm@1
|
187 bitwritecount += dataSize;
|
rlm@1
|
188 if (bitwritecount >= 32)
|
rlm@1
|
189 {
|
rlm@1
|
190 CPUWriteMemory(dest, data);
|
rlm@1
|
191 dest += 4;
|
rlm@1
|
192 data = 0;
|
rlm@1
|
193 bitwritecount = 0;
|
rlm@1
|
194 }
|
rlm@1
|
195 mask <<= bits;
|
rlm@1
|
196 bitcount += bits;
|
rlm@1
|
197 }
|
rlm@1
|
198 }
|
rlm@1
|
199 }
|
rlm@1
|
200
|
rlm@1
|
201 void BIOS_BgAffineSet()
|
rlm@1
|
202 {
|
rlm@1
|
203 #ifdef GBA_LOGGING
|
rlm@1
|
204 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
205 {
|
rlm@1
|
206 log("BgAffineSet: %08x,%08x,%08x (VCOUNT=%2d)\n",
|
rlm@1
|
207 reg[0].I,
|
rlm@1
|
208 reg[1].I,
|
rlm@1
|
209 reg[2].I,
|
rlm@1
|
210 VCOUNT);
|
rlm@1
|
211 }
|
rlm@1
|
212 #endif
|
rlm@1
|
213
|
rlm@1
|
214 u32 src = reg[0].I;
|
rlm@1
|
215 u32 dest = reg[1].I;
|
rlm@1
|
216 int num = reg[2].I;
|
rlm@1
|
217
|
rlm@1
|
218 for (int i = 0; i < num; i++)
|
rlm@1
|
219 {
|
rlm@1
|
220 s32 cx = CPUReadMemory(src);
|
rlm@1
|
221 src += 4;
|
rlm@1
|
222 s32 cy = CPUReadMemory(src);
|
rlm@1
|
223 src += 4;
|
rlm@1
|
224 s16 dispx = CPUReadHalfWord(src);
|
rlm@1
|
225 src += 2;
|
rlm@1
|
226 s16 dispy = CPUReadHalfWord(src);
|
rlm@1
|
227 src += 2;
|
rlm@1
|
228 s16 rx = CPUReadHalfWord(src);
|
rlm@1
|
229 src += 2;
|
rlm@1
|
230 s16 ry = CPUReadHalfWord(src);
|
rlm@1
|
231 src += 2;
|
rlm@1
|
232 u16 theta = CPUReadHalfWord(src)>>8;
|
rlm@1
|
233 src += 4; // keep structure alignment
|
rlm@1
|
234 s32 a = (s32)sineTable[(theta+0x40)&255];
|
rlm@1
|
235 s32 b = (s32)sineTable[theta];
|
rlm@1
|
236
|
rlm@1
|
237 s16 dx = (s16)((rx * a)>>14);
|
rlm@1
|
238 s16 dmx = (s16)((rx * b)>>14);
|
rlm@1
|
239 s16 dy = (s16)((ry * b)>>14);
|
rlm@1
|
240 s16 dmy = (s16)((ry * a)>>14);
|
rlm@1
|
241
|
rlm@1
|
242 CPUWriteHalfWord(dest, dx);
|
rlm@1
|
243 dest += 2;
|
rlm@1
|
244 CPUWriteHalfWord(dest, -dmx);
|
rlm@1
|
245 dest += 2;
|
rlm@1
|
246 CPUWriteHalfWord(dest, dy);
|
rlm@1
|
247 dest += 2;
|
rlm@1
|
248 CPUWriteHalfWord(dest, dmy);
|
rlm@1
|
249 dest += 2;
|
rlm@1
|
250
|
rlm@1
|
251 s32 startx = cx - dx * dispx + dmx * dispy;
|
rlm@1
|
252 s32 starty = cy - dy * dispx - dmy * dispy;
|
rlm@1
|
253
|
rlm@1
|
254 CPUWriteMemory(dest, startx);
|
rlm@1
|
255 dest += 4;
|
rlm@1
|
256 CPUWriteMemory(dest, starty);
|
rlm@1
|
257 dest += 4;
|
rlm@1
|
258 }
|
rlm@1
|
259 }
|
rlm@1
|
260
|
rlm@1
|
261 void BIOS_CpuSet()
|
rlm@1
|
262 {
|
rlm@1
|
263 #ifdef GBA_LOGGING
|
rlm@1
|
264 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
265 {
|
rlm@1
|
266 log("CpuSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
|
rlm@1
|
267 reg[2].I, VCOUNT);
|
rlm@1
|
268 }
|
rlm@1
|
269 #endif
|
rlm@1
|
270
|
rlm@1
|
271 u32 source = reg[0].I;
|
rlm@1
|
272 u32 dest = reg[1].I;
|
rlm@1
|
273 u32 cnt = reg[2].I;
|
rlm@1
|
274
|
rlm@1
|
275 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
276 ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0)
|
rlm@1
|
277 return;
|
rlm@1
|
278
|
rlm@1
|
279 int count = cnt & 0x1FFFFF;
|
rlm@1
|
280
|
rlm@1
|
281 // 32-bit ?
|
rlm@1
|
282 if ((cnt >> 26) & 1)
|
rlm@1
|
283 {
|
rlm@1
|
284 // needed for 32-bit mode!
|
rlm@1
|
285 source &= 0xFFFFFFFC;
|
rlm@1
|
286 dest &= 0xFFFFFFFC;
|
rlm@1
|
287 // fill ?
|
rlm@1
|
288 if ((cnt >> 24) & 1)
|
rlm@1
|
289 {
|
rlm@1
|
290 u32 value = CPUReadMemory(source);
|
rlm@1
|
291 while (count)
|
rlm@1
|
292 {
|
rlm@1
|
293 CPUWriteMemory(dest, value);
|
rlm@1
|
294 dest += 4;
|
rlm@1
|
295 count--;
|
rlm@1
|
296 }
|
rlm@1
|
297 }
|
rlm@1
|
298 else
|
rlm@1
|
299 {
|
rlm@1
|
300 // copy
|
rlm@1
|
301 while (count)
|
rlm@1
|
302 {
|
rlm@1
|
303 CPUWriteMemory(dest, CPUReadMemory(source));
|
rlm@1
|
304 source += 4;
|
rlm@1
|
305 dest += 4;
|
rlm@1
|
306 count--;
|
rlm@1
|
307 }
|
rlm@1
|
308 }
|
rlm@1
|
309 }
|
rlm@1
|
310 else
|
rlm@1
|
311 {
|
rlm@1
|
312 // 16-bit fill?
|
rlm@1
|
313 if ((cnt >> 24) & 1)
|
rlm@1
|
314 {
|
rlm@1
|
315 u16 value = CPUReadHalfWord(source);
|
rlm@1
|
316 while (count)
|
rlm@1
|
317 {
|
rlm@1
|
318 CPUWriteHalfWord(dest, value);
|
rlm@1
|
319 dest += 2;
|
rlm@1
|
320 count--;
|
rlm@1
|
321 }
|
rlm@1
|
322 }
|
rlm@1
|
323 else
|
rlm@1
|
324 {
|
rlm@1
|
325 // copy
|
rlm@1
|
326 while (count)
|
rlm@1
|
327 {
|
rlm@1
|
328 CPUWriteHalfWord(dest, CPUReadHalfWord(source));
|
rlm@1
|
329 source += 2;
|
rlm@1
|
330 dest += 2;
|
rlm@1
|
331 count--;
|
rlm@1
|
332 }
|
rlm@1
|
333 }
|
rlm@1
|
334 }
|
rlm@1
|
335 }
|
rlm@1
|
336
|
rlm@1
|
337 void BIOS_CpuFastSet()
|
rlm@1
|
338 {
|
rlm@1
|
339 #ifdef GBA_LOGGING
|
rlm@1
|
340 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
341 {
|
rlm@1
|
342 log("CpuFastSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
|
rlm@1
|
343 reg[2].I, VCOUNT);
|
rlm@1
|
344 }
|
rlm@1
|
345 #endif
|
rlm@1
|
346
|
rlm@1
|
347 u32 source = reg[0].I;
|
rlm@1
|
348 u32 dest = reg[1].I;
|
rlm@1
|
349 u32 cnt = reg[2].I;
|
rlm@1
|
350
|
rlm@1
|
351 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
352 ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0)
|
rlm@1
|
353 return;
|
rlm@1
|
354
|
rlm@1
|
355 // needed for 32-bit mode!
|
rlm@1
|
356 source &= 0xFFFFFFFC;
|
rlm@1
|
357 dest &= 0xFFFFFFFC;
|
rlm@1
|
358
|
rlm@1
|
359 int count = cnt & 0x1FFFFF;
|
rlm@1
|
360
|
rlm@1
|
361 // fill?
|
rlm@1
|
362 if ((cnt >> 24) & 1)
|
rlm@1
|
363 {
|
rlm@1
|
364 while (count > 0)
|
rlm@1
|
365 {
|
rlm@1
|
366 // BIOS always transfers 32 bytes at a time
|
rlm@1
|
367 u32 value = CPUReadMemory(source);
|
rlm@1
|
368 for (int i = 0; i < 8; i++)
|
rlm@1
|
369 {
|
rlm@1
|
370 CPUWriteMemory(dest, value);
|
rlm@1
|
371 dest += 4;
|
rlm@1
|
372 }
|
rlm@1
|
373 count -= 8;
|
rlm@1
|
374 }
|
rlm@1
|
375 }
|
rlm@1
|
376 else
|
rlm@1
|
377 {
|
rlm@1
|
378 // copy
|
rlm@1
|
379 while (count > 0)
|
rlm@1
|
380 {
|
rlm@1
|
381 // BIOS always transfers 32 bytes at a time
|
rlm@1
|
382 for (int i = 0; i < 8; i++)
|
rlm@1
|
383 {
|
rlm@1
|
384 CPUWriteMemory(dest, CPUReadMemory(source));
|
rlm@1
|
385 source += 4;
|
rlm@1
|
386 dest += 4;
|
rlm@1
|
387 }
|
rlm@1
|
388 count -= 8;
|
rlm@1
|
389 }
|
rlm@1
|
390 }
|
rlm@1
|
391 }
|
rlm@1
|
392
|
rlm@1
|
393 void BIOS_Diff8bitUnFilterWram()
|
rlm@1
|
394 {
|
rlm@1
|
395 #ifdef GBA_LOGGING
|
rlm@1
|
396 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
397 {
|
rlm@1
|
398 log("Diff8bitUnFilterWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
|
rlm@1
|
399 reg[1].I, VCOUNT);
|
rlm@1
|
400 }
|
rlm@1
|
401 #endif
|
rlm@1
|
402
|
rlm@1
|
403 u32 source = reg[0].I;
|
rlm@1
|
404 u32 dest = reg[1].I;
|
rlm@1
|
405
|
rlm@1
|
406 u32 header = CPUReadMemory(source);
|
rlm@1
|
407 source += 4;
|
rlm@1
|
408
|
rlm@1
|
409 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
410 ((source + ((header >> 8) & 0x1fffff) & 0xe000000) == 0))
|
rlm@1
|
411 return;
|
rlm@1
|
412
|
rlm@1
|
413 int len = header >> 8;
|
rlm@1
|
414
|
rlm@1
|
415 u8 data = CPUReadByte(source++);
|
rlm@1
|
416 CPUWriteByte(dest++, data);
|
rlm@1
|
417 len--;
|
rlm@1
|
418
|
rlm@1
|
419 while (len > 0)
|
rlm@1
|
420 {
|
rlm@1
|
421 u8 diff = CPUReadByte(source++);
|
rlm@1
|
422 data += diff;
|
rlm@1
|
423 CPUWriteByte(dest++, data);
|
rlm@1
|
424 len--;
|
rlm@1
|
425 }
|
rlm@1
|
426 }
|
rlm@1
|
427
|
rlm@1
|
428 void BIOS_Diff8bitUnFilterVram()
|
rlm@1
|
429 {
|
rlm@1
|
430 #ifdef GBA_LOGGING
|
rlm@1
|
431 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
432 {
|
rlm@1
|
433 log("Diff8bitUnFilterVram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
|
rlm@1
|
434 reg[1].I, VCOUNT);
|
rlm@1
|
435 }
|
rlm@1
|
436 #endif
|
rlm@1
|
437
|
rlm@1
|
438 u32 source = reg[0].I;
|
rlm@1
|
439 u32 dest = reg[1].I;
|
rlm@1
|
440
|
rlm@1
|
441 u32 header = CPUReadMemory(source);
|
rlm@1
|
442 source += 4;
|
rlm@1
|
443
|
rlm@1
|
444 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
445 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
|
rlm@1
|
446 return;
|
rlm@1
|
447
|
rlm@1
|
448 int len = header >> 8;
|
rlm@1
|
449
|
rlm@1
|
450 u8 data = CPUReadByte(source++);
|
rlm@1
|
451 u16 writeData = data;
|
rlm@1
|
452 int shift = 8;
|
rlm@1
|
453 int bytes = 1;
|
rlm@1
|
454
|
rlm@1
|
455 while (len >= 2)
|
rlm@1
|
456 {
|
rlm@1
|
457 u8 diff = CPUReadByte(source++);
|
rlm@1
|
458 data += diff;
|
rlm@1
|
459 writeData |= (data << shift);
|
rlm@1
|
460 bytes++;
|
rlm@1
|
461 shift += 8;
|
rlm@1
|
462 if (bytes == 2)
|
rlm@1
|
463 {
|
rlm@1
|
464 CPUWriteHalfWord(dest, writeData);
|
rlm@1
|
465 dest += 2;
|
rlm@1
|
466 len -= 2;
|
rlm@1
|
467 bytes = 0;
|
rlm@1
|
468 writeData = 0;
|
rlm@1
|
469 shift = 0;
|
rlm@1
|
470 }
|
rlm@1
|
471 }
|
rlm@1
|
472 }
|
rlm@1
|
473
|
rlm@1
|
474 void BIOS_Diff16bitUnFilter()
|
rlm@1
|
475 {
|
rlm@1
|
476 #ifdef GBA_LOGGING
|
rlm@1
|
477 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
478 {
|
rlm@1
|
479 log("Diff16bitUnFilter: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
|
rlm@1
|
480 reg[1].I, VCOUNT);
|
rlm@1
|
481 }
|
rlm@1
|
482 #endif
|
rlm@1
|
483
|
rlm@1
|
484 u32 source = reg[0].I;
|
rlm@1
|
485 u32 dest = reg[1].I;
|
rlm@1
|
486
|
rlm@1
|
487 u32 header = CPUReadMemory(source);
|
rlm@1
|
488 source += 4;
|
rlm@1
|
489
|
rlm@1
|
490 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
491 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
|
rlm@1
|
492 return;
|
rlm@1
|
493
|
rlm@1
|
494 int len = header >> 8;
|
rlm@1
|
495
|
rlm@1
|
496 u16 data = CPUReadHalfWord(source);
|
rlm@1
|
497 source += 2;
|
rlm@1
|
498 CPUWriteHalfWord(dest, data);
|
rlm@1
|
499 dest += 2;
|
rlm@1
|
500 len -= 2;
|
rlm@1
|
501
|
rlm@1
|
502 while (len >= 2)
|
rlm@1
|
503 {
|
rlm@1
|
504 u16 diff = CPUReadHalfWord(source);
|
rlm@1
|
505 source += 2;
|
rlm@1
|
506 data += diff;
|
rlm@1
|
507 CPUWriteHalfWord(dest, data);
|
rlm@1
|
508 dest += 2;
|
rlm@1
|
509 len -= 2;
|
rlm@1
|
510 }
|
rlm@1
|
511 }
|
rlm@1
|
512
|
rlm@1
|
513 void BIOS_Div()
|
rlm@1
|
514 {
|
rlm@1
|
515 #ifdef GBA_LOGGING
|
rlm@1
|
516 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
517 {
|
rlm@1
|
518 log("Div: 0x%08x,0x%08x (VCOUNT=%d)\n",
|
rlm@1
|
519 reg[0].I,
|
rlm@1
|
520 reg[1].I,
|
rlm@1
|
521 VCOUNT);
|
rlm@1
|
522 }
|
rlm@1
|
523 #endif
|
rlm@1
|
524
|
rlm@1
|
525 int number = reg[0].I;
|
rlm@1
|
526 int denom = reg[1].I;
|
rlm@1
|
527
|
rlm@1
|
528 if (denom != 0)
|
rlm@1
|
529 {
|
rlm@1
|
530 reg[0].I = number / denom;
|
rlm@1
|
531 reg[1].I = number % denom;
|
rlm@1
|
532 s32 temp = (s32)reg[0].I;
|
rlm@1
|
533 reg[3].I = temp < 0 ? (u32)-temp : (u32)temp;
|
rlm@1
|
534 }
|
rlm@1
|
535 #ifdef GBA_LOGGING
|
rlm@1
|
536 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
537 {
|
rlm@1
|
538 log("Div: return=0x%08x,0x%08x,0x%08x\n",
|
rlm@1
|
539 reg[0].I,
|
rlm@1
|
540 reg[1].I,
|
rlm@1
|
541 reg[3].I);
|
rlm@1
|
542 }
|
rlm@1
|
543 #endif
|
rlm@1
|
544 }
|
rlm@1
|
545
|
rlm@1
|
546 void BIOS_DivARM()
|
rlm@1
|
547 {
|
rlm@1
|
548 #ifdef GBA_LOGGING
|
rlm@1
|
549 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
550 {
|
rlm@1
|
551 log("DivARM: 0x%08x, (VCOUNT=%d)\n",
|
rlm@1
|
552 reg[0].I,
|
rlm@1
|
553 VCOUNT);
|
rlm@1
|
554 }
|
rlm@1
|
555 #endif
|
rlm@1
|
556
|
rlm@1
|
557 u32 temp = reg[0].I;
|
rlm@1
|
558 reg[0].I = reg[1].I;
|
rlm@1
|
559 reg[1].I = temp;
|
rlm@1
|
560 BIOS_Div();
|
rlm@1
|
561 }
|
rlm@1
|
562
|
rlm@1
|
563 void BIOS_HuffUnComp()
|
rlm@1
|
564 {
|
rlm@1
|
565 #ifdef GBA_LOGGING
|
rlm@1
|
566 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
567 {
|
rlm@1
|
568 log("HuffUnComp: 0x%08x,0x%08x (VCOUNT=%d)\n",
|
rlm@1
|
569 reg[0].I,
|
rlm@1
|
570 reg[1].I,
|
rlm@1
|
571 VCOUNT);
|
rlm@1
|
572 }
|
rlm@1
|
573 #endif
|
rlm@1
|
574
|
rlm@1
|
575 u32 source = reg[0].I;
|
rlm@1
|
576 u32 dest = reg[1].I;
|
rlm@1
|
577
|
rlm@1
|
578 u32 header = CPUReadMemory(source);
|
rlm@1
|
579 source += 4;
|
rlm@1
|
580
|
rlm@1
|
581 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
582 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
|
rlm@1
|
583 return;
|
rlm@1
|
584
|
rlm@1
|
585 u8 treeSize = CPUReadByte(source++);
|
rlm@1
|
586
|
rlm@1
|
587 u32 treeStart = source;
|
rlm@1
|
588
|
rlm@1
|
589 source += (treeSize<<1) + 1;
|
rlm@1
|
590
|
rlm@1
|
591 int len = header >> 8;
|
rlm@1
|
592
|
rlm@1
|
593 u32 mask = 0x80000000;
|
rlm@1
|
594 u32 data = CPUReadMemory(source);
|
rlm@1
|
595 source += 4;
|
rlm@1
|
596
|
rlm@1
|
597 int pos = 0;
|
rlm@1
|
598 u8 rootNode = CPUReadByte(treeStart);
|
rlm@1
|
599 u8 currentNode = rootNode;
|
rlm@1
|
600 bool writeData = false;
|
rlm@1
|
601 int byteShift = 0;
|
rlm@1
|
602 int byteCount = 0;
|
rlm@1
|
603 u32 writeValue = 0;
|
rlm@1
|
604
|
rlm@1
|
605 if ((header & 0x0F) == 8)
|
rlm@1
|
606 {
|
rlm@1
|
607 while (len > 0)
|
rlm@1
|
608 {
|
rlm@1
|
609 // take left
|
rlm@1
|
610 if (pos == 0)
|
rlm@1
|
611 pos++;
|
rlm@1
|
612 else
|
rlm@1
|
613 pos += (((currentNode & 0x3F)+1)<<1);
|
rlm@1
|
614
|
rlm@1
|
615 if (data & mask)
|
rlm@1
|
616 {
|
rlm@1
|
617 // right
|
rlm@1
|
618 if (currentNode & 0x40)
|
rlm@1
|
619 writeData = true;
|
rlm@1
|
620 currentNode = CPUReadByte(treeStart+pos+1);
|
rlm@1
|
621 }
|
rlm@1
|
622 else
|
rlm@1
|
623 {
|
rlm@1
|
624 // left
|
rlm@1
|
625 if (currentNode & 0x80)
|
rlm@1
|
626 writeData = true;
|
rlm@1
|
627 currentNode = CPUReadByte(treeStart+pos);
|
rlm@1
|
628 }
|
rlm@1
|
629
|
rlm@1
|
630 if (writeData)
|
rlm@1
|
631 {
|
rlm@1
|
632 writeValue |= (currentNode << byteShift);
|
rlm@1
|
633 byteCount++;
|
rlm@1
|
634 byteShift += 8;
|
rlm@1
|
635
|
rlm@1
|
636 pos = 0;
|
rlm@1
|
637 currentNode = rootNode;
|
rlm@1
|
638 writeData = false;
|
rlm@1
|
639
|
rlm@1
|
640 if (byteCount == 4)
|
rlm@1
|
641 {
|
rlm@1
|
642 byteCount = 0;
|
rlm@1
|
643 byteShift = 0;
|
rlm@1
|
644 CPUWriteMemory(dest, writeValue);
|
rlm@1
|
645 writeValue = 0;
|
rlm@1
|
646 dest += 4;
|
rlm@1
|
647 len -= 4;
|
rlm@1
|
648 }
|
rlm@1
|
649 }
|
rlm@1
|
650 mask >>= 1;
|
rlm@1
|
651 if (mask == 0)
|
rlm@1
|
652 {
|
rlm@1
|
653 mask = 0x80000000;
|
rlm@1
|
654 data = CPUReadMemory(source);
|
rlm@1
|
655 source += 4;
|
rlm@1
|
656 }
|
rlm@1
|
657 }
|
rlm@1
|
658 }
|
rlm@1
|
659 else
|
rlm@1
|
660 {
|
rlm@1
|
661 int halfLen = 0;
|
rlm@1
|
662 int value = 0;
|
rlm@1
|
663 while (len > 0)
|
rlm@1
|
664 {
|
rlm@1
|
665 // take left
|
rlm@1
|
666 if (pos == 0)
|
rlm@1
|
667 pos++;
|
rlm@1
|
668 else
|
rlm@1
|
669 pos += (((currentNode & 0x3F)+1)<<1);
|
rlm@1
|
670
|
rlm@1
|
671 if ((data & mask))
|
rlm@1
|
672 {
|
rlm@1
|
673 // right
|
rlm@1
|
674 if (currentNode & 0x40)
|
rlm@1
|
675 writeData = true;
|
rlm@1
|
676 currentNode = CPUReadByte(treeStart+pos+1);
|
rlm@1
|
677 }
|
rlm@1
|
678 else
|
rlm@1
|
679 {
|
rlm@1
|
680 // left
|
rlm@1
|
681 if (currentNode & 0x80)
|
rlm@1
|
682 writeData = true;
|
rlm@1
|
683 currentNode = CPUReadByte(treeStart+pos);
|
rlm@1
|
684 }
|
rlm@1
|
685
|
rlm@1
|
686 if (writeData)
|
rlm@1
|
687 {
|
rlm@1
|
688 if (halfLen == 0)
|
rlm@1
|
689 value |= currentNode;
|
rlm@1
|
690 else
|
rlm@1
|
691 value |= (currentNode<<4);
|
rlm@1
|
692
|
rlm@1
|
693 halfLen += 4;
|
rlm@1
|
694 if (halfLen == 8)
|
rlm@1
|
695 {
|
rlm@1
|
696 writeValue |= (value << byteShift);
|
rlm@1
|
697 byteCount++;
|
rlm@1
|
698 byteShift += 8;
|
rlm@1
|
699
|
rlm@1
|
700 halfLen = 0;
|
rlm@1
|
701 value = 0;
|
rlm@1
|
702
|
rlm@1
|
703 if (byteCount == 4)
|
rlm@1
|
704 {
|
rlm@1
|
705 byteCount = 0;
|
rlm@1
|
706 byteShift = 0;
|
rlm@1
|
707 CPUWriteMemory(dest, writeValue);
|
rlm@1
|
708 dest += 4;
|
rlm@1
|
709 writeValue = 0;
|
rlm@1
|
710 len -= 4;
|
rlm@1
|
711 }
|
rlm@1
|
712 }
|
rlm@1
|
713 pos = 0;
|
rlm@1
|
714 currentNode = rootNode;
|
rlm@1
|
715 writeData = false;
|
rlm@1
|
716 }
|
rlm@1
|
717 mask >>= 1;
|
rlm@1
|
718 if (mask == 0)
|
rlm@1
|
719 {
|
rlm@1
|
720 mask = 0x80000000;
|
rlm@1
|
721 data = CPUReadMemory(source);
|
rlm@1
|
722 source += 4;
|
rlm@1
|
723 }
|
rlm@1
|
724 }
|
rlm@1
|
725 }
|
rlm@1
|
726 }
|
rlm@1
|
727
|
rlm@1
|
728 void BIOS_LZ77UnCompVram()
|
rlm@1
|
729 {
|
rlm@1
|
730 #ifdef GBA_LOGGING
|
rlm@1
|
731 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
732 {
|
rlm@1
|
733 log("LZ77UnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n",
|
rlm@1
|
734 reg[0].I,
|
rlm@1
|
735 reg[1].I,
|
rlm@1
|
736 VCOUNT);
|
rlm@1
|
737 }
|
rlm@1
|
738 #endif
|
rlm@1
|
739
|
rlm@1
|
740 u32 source = reg[0].I;
|
rlm@1
|
741 u32 dest = reg[1].I;
|
rlm@1
|
742
|
rlm@1
|
743 u32 header = CPUReadMemory(source);
|
rlm@1
|
744 source += 4;
|
rlm@1
|
745
|
rlm@1
|
746 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
747 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
|
rlm@1
|
748 return;
|
rlm@1
|
749
|
rlm@1
|
750 int byteCount = 0;
|
rlm@1
|
751 int byteShift = 0;
|
rlm@1
|
752 u32 writeValue = 0;
|
rlm@1
|
753
|
rlm@1
|
754 int len = header >> 8;
|
rlm@1
|
755
|
rlm@1
|
756 while (len > 0)
|
rlm@1
|
757 {
|
rlm@1
|
758 u8 d = CPUReadByte(source++);
|
rlm@1
|
759
|
rlm@1
|
760 if (d)
|
rlm@1
|
761 {
|
rlm@1
|
762 for (int i = 0; i < 8; i++)
|
rlm@1
|
763 {
|
rlm@1
|
764 if (d & 0x80)
|
rlm@1
|
765 {
|
rlm@1
|
766 u16 data = CPUReadByte(source++) << 8;
|
rlm@1
|
767 data |= CPUReadByte(source++);
|
rlm@1
|
768 int length = (data >> 12) + 3;
|
rlm@1
|
769 int offset = (data & 0x0FFF);
|
rlm@1
|
770 u32 windowOffset = dest + byteCount - offset - 1;
|
rlm@1
|
771 for (int i = 0; i < length; i++)
|
rlm@1
|
772 {
|
rlm@1
|
773 writeValue |= (CPUReadByte(windowOffset++) << byteShift);
|
rlm@1
|
774 byteShift += 8;
|
rlm@1
|
775 byteCount++;
|
rlm@1
|
776
|
rlm@1
|
777 if (byteCount == 2)
|
rlm@1
|
778 {
|
rlm@1
|
779 CPUWriteHalfWord(dest, writeValue);
|
rlm@1
|
780 dest += 2;
|
rlm@1
|
781 byteCount = 0;
|
rlm@1
|
782 byteShift = 0;
|
rlm@1
|
783 writeValue = 0;
|
rlm@1
|
784 }
|
rlm@1
|
785 len--;
|
rlm@1
|
786 if (len == 0)
|
rlm@1
|
787 return;
|
rlm@1
|
788 }
|
rlm@1
|
789 }
|
rlm@1
|
790 else
|
rlm@1
|
791 {
|
rlm@1
|
792 writeValue |= (CPUReadByte(source++) << byteShift);
|
rlm@1
|
793 byteShift += 8;
|
rlm@1
|
794 byteCount++;
|
rlm@1
|
795 if (byteCount == 2)
|
rlm@1
|
796 {
|
rlm@1
|
797 CPUWriteHalfWord(dest, writeValue);
|
rlm@1
|
798 dest += 2;
|
rlm@1
|
799 byteCount = 0;
|
rlm@1
|
800 byteShift = 0;
|
rlm@1
|
801 writeValue = 0;
|
rlm@1
|
802 }
|
rlm@1
|
803 len--;
|
rlm@1
|
804 if (len == 0)
|
rlm@1
|
805 return;
|
rlm@1
|
806 }
|
rlm@1
|
807 d <<= 1;
|
rlm@1
|
808 }
|
rlm@1
|
809 }
|
rlm@1
|
810 else
|
rlm@1
|
811 {
|
rlm@1
|
812 for (int i = 0; i < 8; i++)
|
rlm@1
|
813 {
|
rlm@1
|
814 writeValue |= (CPUReadByte(source++) << byteShift);
|
rlm@1
|
815 byteShift += 8;
|
rlm@1
|
816 byteCount++;
|
rlm@1
|
817 if (byteCount == 2)
|
rlm@1
|
818 {
|
rlm@1
|
819 CPUWriteHalfWord(dest, writeValue);
|
rlm@1
|
820 dest += 2;
|
rlm@1
|
821 byteShift = 0;
|
rlm@1
|
822 byteCount = 0;
|
rlm@1
|
823 writeValue = 0;
|
rlm@1
|
824 }
|
rlm@1
|
825 len--;
|
rlm@1
|
826 if (len == 0)
|
rlm@1
|
827 return;
|
rlm@1
|
828 }
|
rlm@1
|
829 }
|
rlm@1
|
830 }
|
rlm@1
|
831 }
|
rlm@1
|
832
|
rlm@1
|
833 void BIOS_LZ77UnCompWram()
|
rlm@1
|
834 {
|
rlm@1
|
835 #ifdef GBA_LOGGING
|
rlm@1
|
836 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
837 {
|
rlm@1
|
838 log("LZ77UnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
|
rlm@1
|
839 VCOUNT);
|
rlm@1
|
840 }
|
rlm@1
|
841 #endif
|
rlm@1
|
842
|
rlm@1
|
843 u32 source = reg[0].I;
|
rlm@1
|
844 u32 dest = reg[1].I;
|
rlm@1
|
845
|
rlm@1
|
846 u32 header = CPUReadMemory(source);
|
rlm@1
|
847 source += 4;
|
rlm@1
|
848
|
rlm@1
|
849 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
850 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
|
rlm@1
|
851 return;
|
rlm@1
|
852
|
rlm@1
|
853 int len = header >> 8;
|
rlm@1
|
854
|
rlm@1
|
855 while (len > 0)
|
rlm@1
|
856 {
|
rlm@1
|
857 u8 d = CPUReadByte(source++);
|
rlm@1
|
858
|
rlm@1
|
859 if (d)
|
rlm@1
|
860 {
|
rlm@1
|
861 for (int i = 0; i < 8; i++)
|
rlm@1
|
862 {
|
rlm@1
|
863 if (d & 0x80)
|
rlm@1
|
864 {
|
rlm@1
|
865 u16 data = CPUReadByte(source++) << 8;
|
rlm@1
|
866 data |= CPUReadByte(source++);
|
rlm@1
|
867 int length = (data >> 12) + 3;
|
rlm@1
|
868 int offset = (data & 0x0FFF);
|
rlm@1
|
869 u32 windowOffset = dest - offset - 1;
|
rlm@1
|
870 for (int i = 0; i < length; i++)
|
rlm@1
|
871 {
|
rlm@1
|
872 CPUWriteByte(dest++, CPUReadByte(windowOffset++));
|
rlm@1
|
873 len--;
|
rlm@1
|
874 if (len == 0)
|
rlm@1
|
875 return;
|
rlm@1
|
876 }
|
rlm@1
|
877 }
|
rlm@1
|
878 else
|
rlm@1
|
879 {
|
rlm@1
|
880 CPUWriteByte(dest++, CPUReadByte(source++));
|
rlm@1
|
881 len--;
|
rlm@1
|
882 if (len == 0)
|
rlm@1
|
883 return;
|
rlm@1
|
884 }
|
rlm@1
|
885 d <<= 1;
|
rlm@1
|
886 }
|
rlm@1
|
887 }
|
rlm@1
|
888 else
|
rlm@1
|
889 {
|
rlm@1
|
890 for (int i = 0; i < 8; i++)
|
rlm@1
|
891 {
|
rlm@1
|
892 CPUWriteByte(dest++, CPUReadByte(source++));
|
rlm@1
|
893 len--;
|
rlm@1
|
894 if (len == 0)
|
rlm@1
|
895 return;
|
rlm@1
|
896 }
|
rlm@1
|
897 }
|
rlm@1
|
898 }
|
rlm@1
|
899 }
|
rlm@1
|
900
|
rlm@1
|
901 void BIOS_ObjAffineSet()
|
rlm@1
|
902 {
|
rlm@1
|
903 #ifdef GBA_LOGGING
|
rlm@1
|
904 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
905 {
|
rlm@1
|
906 log("ObjAffineSet: 0x%08x,0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n",
|
rlm@1
|
907 reg[0].I,
|
rlm@1
|
908 reg[1].I,
|
rlm@1
|
909 reg[2].I,
|
rlm@1
|
910 reg[3].I,
|
rlm@1
|
911 VCOUNT);
|
rlm@1
|
912 }
|
rlm@1
|
913 #endif
|
rlm@1
|
914
|
rlm@1
|
915 u32 src = reg[0].I;
|
rlm@1
|
916 u32 dest = reg[1].I;
|
rlm@1
|
917 int num = reg[2].I;
|
rlm@1
|
918 int offset = reg[3].I;
|
rlm@1
|
919
|
rlm@1
|
920 for (int i = 0; i < num; i++)
|
rlm@1
|
921 {
|
rlm@1
|
922 s16 rx = CPUReadHalfWord(src);
|
rlm@1
|
923 src += 2;
|
rlm@1
|
924 s16 ry = CPUReadHalfWord(src);
|
rlm@1
|
925 src += 2;
|
rlm@1
|
926 u16 theta = CPUReadHalfWord(src)>>8;
|
rlm@1
|
927 src += 4; // keep structure alignment
|
rlm@1
|
928
|
rlm@1
|
929 s32 a = (s32)sineTable[(theta+0x40)&255];
|
rlm@1
|
930 s32 b = (s32)sineTable[theta];
|
rlm@1
|
931
|
rlm@1
|
932 s16 dx = (s16)((rx * a)>>14);
|
rlm@1
|
933 s16 dmx = (s16)((rx * b)>>14);
|
rlm@1
|
934 s16 dy = (s16)((ry * b)>>14);
|
rlm@1
|
935 s16 dmy = (s16)((ry * a)>>14);
|
rlm@1
|
936
|
rlm@1
|
937 CPUWriteHalfWord(dest, dx);
|
rlm@1
|
938 dest += offset;
|
rlm@1
|
939 CPUWriteHalfWord(dest, -dmx);
|
rlm@1
|
940 dest += offset;
|
rlm@1
|
941 CPUWriteHalfWord(dest, dy);
|
rlm@1
|
942 dest += offset;
|
rlm@1
|
943 CPUWriteHalfWord(dest, dmy);
|
rlm@1
|
944 dest += offset;
|
rlm@1
|
945 }
|
rlm@1
|
946 }
|
rlm@1
|
947
|
rlm@1
|
948 void BIOS_RegisterRamReset(u32 flags)
|
rlm@1
|
949 {
|
rlm@1
|
950 // no need to trace here. this is only called directly from GBA.cpp
|
rlm@1
|
951 // to emulate bios initialization
|
rlm@1
|
952
|
rlm@1
|
953 if (flags)
|
rlm@1
|
954 {
|
rlm@1
|
955 if (flags & 0x01)
|
rlm@1
|
956 {
|
rlm@1
|
957 // clear work RAM
|
rlm@1
|
958 memset(workRAM, 0, 0x40000);
|
rlm@1
|
959 }
|
rlm@1
|
960 if (flags & 0x02)
|
rlm@1
|
961 {
|
rlm@1
|
962 // clear internal RAM
|
rlm@1
|
963 memset(internalRAM, 0, 0x7e00); // don't clear 0x7e00-0x7fff
|
rlm@1
|
964 }
|
rlm@1
|
965 if (flags & 0x04)
|
rlm@1
|
966 {
|
rlm@1
|
967 // clear palette RAM
|
rlm@1
|
968 memset(paletteRAM, 0, 0x400);
|
rlm@1
|
969 }
|
rlm@1
|
970 if (flags & 0x08)
|
rlm@1
|
971 {
|
rlm@1
|
972 // clear VRAM
|
rlm@1
|
973 memset(vram, 0, 0x18000);
|
rlm@1
|
974 }
|
rlm@1
|
975 if (flags & 0x10)
|
rlm@1
|
976 {
|
rlm@1
|
977 // clean OAM
|
rlm@1
|
978 memset(oam, 0, 0x400);
|
rlm@1
|
979 }
|
rlm@1
|
980
|
rlm@1
|
981 if (flags & 0x80)
|
rlm@1
|
982 {
|
rlm@1
|
983 int i;
|
rlm@1
|
984 for (i = 0; i < 8; i++)
|
rlm@1
|
985 CPUUpdateRegister(0x200+i*2, 0);
|
rlm@1
|
986
|
rlm@1
|
987 CPUUpdateRegister(0x202, 0xFFFF);
|
rlm@1
|
988
|
rlm@1
|
989 for (i = 0; i < 8; i++)
|
rlm@1
|
990 CPUUpdateRegister(0x4+i*2, 0);
|
rlm@1
|
991
|
rlm@1
|
992 for (i = 0; i < 16; i++)
|
rlm@1
|
993 CPUUpdateRegister(0x20+i*2, 0);
|
rlm@1
|
994
|
rlm@1
|
995 for (i = 0; i < 24; i++)
|
rlm@1
|
996 CPUUpdateRegister(0xb0+i*2, 0);
|
rlm@1
|
997
|
rlm@1
|
998 CPUUpdateRegister(0x130, 0);
|
rlm@1
|
999 CPUUpdateRegister(0x20, 0x100);
|
rlm@1
|
1000 CPUUpdateRegister(0x30, 0x100);
|
rlm@1
|
1001 CPUUpdateRegister(0x26, 0x100);
|
rlm@1
|
1002 CPUUpdateRegister(0x36, 0x100);
|
rlm@1
|
1003 }
|
rlm@1
|
1004
|
rlm@1
|
1005 if (flags & 0x20)
|
rlm@1
|
1006 {
|
rlm@1
|
1007 int i;
|
rlm@1
|
1008 for (i = 0; i < 8; i++)
|
rlm@1
|
1009 CPUUpdateRegister(0x110+i*2, 0);
|
rlm@1
|
1010 CPUUpdateRegister(0x134, 0x8000);
|
rlm@1
|
1011 for (i = 0; i < 7; i++)
|
rlm@1
|
1012 CPUUpdateRegister(0x140+i*2, 0);
|
rlm@1
|
1013 }
|
rlm@1
|
1014
|
rlm@1
|
1015 if (flags & 0x40)
|
rlm@1
|
1016 {
|
rlm@1
|
1017 int i;
|
rlm@1
|
1018 CPUWriteByte(0x4000084, 0);
|
rlm@1
|
1019 CPUWriteByte(0x4000084, 0x80);
|
rlm@1
|
1020 CPUWriteMemory(0x4000080, 0x880e0000);
|
rlm@1
|
1021 CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff);
|
rlm@1
|
1022 CPUWriteByte(0x4000070, 0x70);
|
rlm@1
|
1023 for (i = 0; i < 8; i++)
|
rlm@1
|
1024 CPUUpdateRegister(0x90+i*2, 0);
|
rlm@1
|
1025 CPUWriteByte(0x4000070, 0);
|
rlm@1
|
1026 for (i = 0; i < 8; i++)
|
rlm@1
|
1027 CPUUpdateRegister(0x90+i*2, 0);
|
rlm@1
|
1028 CPUWriteByte(0x4000084, 0);
|
rlm@1
|
1029 }
|
rlm@1
|
1030 }
|
rlm@1
|
1031 }
|
rlm@1
|
1032
|
rlm@1
|
1033 void BIOS_RegisterRamReset()
|
rlm@1
|
1034 {
|
rlm@1
|
1035 #ifdef GBA_LOGGING
|
rlm@1
|
1036 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
1037 {
|
rlm@1
|
1038 log("RegisterRamReset: 0x%08x (VCOUNT=%d)\n",
|
rlm@1
|
1039 reg[0].I,
|
rlm@1
|
1040 VCOUNT);
|
rlm@1
|
1041 }
|
rlm@1
|
1042 #endif
|
rlm@1
|
1043
|
rlm@1
|
1044 BIOS_RegisterRamReset(reg[0].I);
|
rlm@1
|
1045 }
|
rlm@1
|
1046
|
rlm@1
|
1047 void BIOS_RLUnCompVram()
|
rlm@1
|
1048 {
|
rlm@1
|
1049 #ifdef GBA_LOGGING
|
rlm@1
|
1050 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
1051 {
|
rlm@1
|
1052 log("RLUnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n",
|
rlm@1
|
1053 reg[0].I,
|
rlm@1
|
1054 reg[1].I,
|
rlm@1
|
1055 VCOUNT);
|
rlm@1
|
1056 }
|
rlm@1
|
1057 #endif
|
rlm@1
|
1058
|
rlm@1
|
1059 u32 source = reg[0].I;
|
rlm@1
|
1060 u32 dest = reg[1].I;
|
rlm@1
|
1061
|
rlm@1
|
1062 u32 header = CPUReadMemory(source);
|
rlm@1
|
1063 source += 4;
|
rlm@1
|
1064
|
rlm@1
|
1065 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
1066 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
|
rlm@1
|
1067 return;
|
rlm@1
|
1068
|
rlm@1
|
1069 int len = header >> 8;
|
rlm@1
|
1070 int byteCount = 0;
|
rlm@1
|
1071 int byteShift = 0;
|
rlm@1
|
1072 u32 writeValue = 0;
|
rlm@1
|
1073
|
rlm@1
|
1074 while (len > 0)
|
rlm@1
|
1075 {
|
rlm@1
|
1076 u8 d = CPUReadByte(source++);
|
rlm@1
|
1077 int l = d & 0x7F;
|
rlm@1
|
1078 if (d & 0x80)
|
rlm@1
|
1079 {
|
rlm@1
|
1080 u8 data = CPUReadByte(source++);
|
rlm@1
|
1081 l += 3;
|
rlm@1
|
1082 for (int i = 0; i < l; i++)
|
rlm@1
|
1083 {
|
rlm@1
|
1084 writeValue |= (data << byteShift);
|
rlm@1
|
1085 byteShift += 8;
|
rlm@1
|
1086 byteCount++;
|
rlm@1
|
1087
|
rlm@1
|
1088 if (byteCount == 2)
|
rlm@1
|
1089 {
|
rlm@1
|
1090 CPUWriteHalfWord(dest, writeValue);
|
rlm@1
|
1091 dest += 2;
|
rlm@1
|
1092 byteCount = 0;
|
rlm@1
|
1093 byteShift = 0;
|
rlm@1
|
1094 writeValue = 0;
|
rlm@1
|
1095 }
|
rlm@1
|
1096 len--;
|
rlm@1
|
1097 if (len == 0)
|
rlm@1
|
1098 return;
|
rlm@1
|
1099 }
|
rlm@1
|
1100 }
|
rlm@1
|
1101 else
|
rlm@1
|
1102 {
|
rlm@1
|
1103 l++;
|
rlm@1
|
1104 for (int i = 0; i < l; i++)
|
rlm@1
|
1105 {
|
rlm@1
|
1106 writeValue |= (CPUReadByte(source++) << byteShift);
|
rlm@1
|
1107 byteShift += 8;
|
rlm@1
|
1108 byteCount++;
|
rlm@1
|
1109 if (byteCount == 2)
|
rlm@1
|
1110 {
|
rlm@1
|
1111 CPUWriteHalfWord(dest, writeValue);
|
rlm@1
|
1112 dest += 2;
|
rlm@1
|
1113 byteCount = 0;
|
rlm@1
|
1114 byteShift = 0;
|
rlm@1
|
1115 writeValue = 0;
|
rlm@1
|
1116 }
|
rlm@1
|
1117 len--;
|
rlm@1
|
1118 if (len == 0)
|
rlm@1
|
1119 return;
|
rlm@1
|
1120 }
|
rlm@1
|
1121 }
|
rlm@1
|
1122 }
|
rlm@1
|
1123 }
|
rlm@1
|
1124
|
rlm@1
|
1125 void BIOS_RLUnCompWram()
|
rlm@1
|
1126 {
|
rlm@1
|
1127 #ifdef GBA_LOGGING
|
rlm@1
|
1128 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
1129 {
|
rlm@1
|
1130 log("RLUnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n",
|
rlm@1
|
1131 reg[0].I,
|
rlm@1
|
1132 reg[1].I,
|
rlm@1
|
1133 VCOUNT);
|
rlm@1
|
1134 }
|
rlm@1
|
1135 #endif
|
rlm@1
|
1136
|
rlm@1
|
1137 u32 source = reg[0].I;
|
rlm@1
|
1138 u32 dest = reg[1].I;
|
rlm@1
|
1139
|
rlm@1
|
1140 u32 header = CPUReadMemory(source);
|
rlm@1
|
1141 source += 4;
|
rlm@1
|
1142
|
rlm@1
|
1143 if (((source & 0xe000000) == 0) ||
|
rlm@1
|
1144 ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
|
rlm@1
|
1145 return;
|
rlm@1
|
1146
|
rlm@1
|
1147 int len = header >> 8;
|
rlm@1
|
1148
|
rlm@1
|
1149 while (len > 0)
|
rlm@1
|
1150 {
|
rlm@1
|
1151 u8 d = CPUReadByte(source++);
|
rlm@1
|
1152 int l = d & 0x7F;
|
rlm@1
|
1153 if (d & 0x80)
|
rlm@1
|
1154 {
|
rlm@1
|
1155 u8 data = CPUReadByte(source++);
|
rlm@1
|
1156 l += 3;
|
rlm@1
|
1157 for (int i = 0; i < l; i++)
|
rlm@1
|
1158 {
|
rlm@1
|
1159 CPUWriteByte(dest++, data);
|
rlm@1
|
1160 len--;
|
rlm@1
|
1161 if (len == 0)
|
rlm@1
|
1162 return;
|
rlm@1
|
1163 }
|
rlm@1
|
1164 }
|
rlm@1
|
1165 else
|
rlm@1
|
1166 {
|
rlm@1
|
1167 l++;
|
rlm@1
|
1168 for (int i = 0; i < l; i++)
|
rlm@1
|
1169 {
|
rlm@1
|
1170 CPUWriteByte(dest++, CPUReadByte(source++));
|
rlm@1
|
1171 len--;
|
rlm@1
|
1172 if (len == 0)
|
rlm@1
|
1173 return;
|
rlm@1
|
1174 }
|
rlm@1
|
1175 }
|
rlm@1
|
1176 }
|
rlm@1
|
1177 }
|
rlm@1
|
1178
|
rlm@1
|
1179 void BIOS_SoftReset()
|
rlm@1
|
1180 {
|
rlm@1
|
1181 #ifdef GBA_LOGGING
|
rlm@1
|
1182 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
1183 {
|
rlm@1
|
1184 log("SoftReset: (VCOUNT=%d)\n", VCOUNT);
|
rlm@1
|
1185 }
|
rlm@1
|
1186 #endif
|
rlm@1
|
1187
|
rlm@1
|
1188 armState = true;
|
rlm@1
|
1189 armMode = 0x1F;
|
rlm@1
|
1190 armIrqEnable = false;
|
rlm@1
|
1191 C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
|
rlm@1
|
1192 reg[13].I = 0x03007F00;
|
rlm@1
|
1193 reg[14].I = 0x00000000;
|
rlm@1
|
1194 reg[16].I = 0x00000000;
|
rlm@1
|
1195 reg[R13_IRQ].I = 0x03007FA0;
|
rlm@1
|
1196 reg[R14_IRQ].I = 0x00000000;
|
rlm@1
|
1197 reg[SPSR_IRQ].I = 0x00000000;
|
rlm@1
|
1198 reg[R13_SVC].I = 0x03007FE0;
|
rlm@1
|
1199 reg[R14_SVC].I = 0x00000000;
|
rlm@1
|
1200 reg[SPSR_SVC].I = 0x00000000;
|
rlm@1
|
1201 u8 b = internalRAM[0x7ffa];
|
rlm@1
|
1202
|
rlm@1
|
1203 memset(&internalRAM[0x7e00], 0, 0x200);
|
rlm@1
|
1204
|
rlm@1
|
1205 if (b)
|
rlm@1
|
1206 {
|
rlm@1
|
1207 armNextPC = 0x02000000;
|
rlm@1
|
1208 reg[15].I = 0x02000004;
|
rlm@1
|
1209 }
|
rlm@1
|
1210 else
|
rlm@1
|
1211 {
|
rlm@1
|
1212 armNextPC = 0x08000000;
|
rlm@1
|
1213 reg[15].I = 0x08000004;
|
rlm@1
|
1214 }
|
rlm@1
|
1215 }
|
rlm@1
|
1216
|
rlm@1
|
1217 void BIOS_Sqrt()
|
rlm@1
|
1218 {
|
rlm@1
|
1219 #ifdef GBA_LOGGING
|
rlm@1
|
1220 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
1221 {
|
rlm@1
|
1222 log("Sqrt: %08x (VCOUNT=%2d)\n",
|
rlm@1
|
1223 reg[0].I,
|
rlm@1
|
1224 VCOUNT);
|
rlm@1
|
1225 }
|
rlm@1
|
1226 #endif
|
rlm@1
|
1227 reg[0].I = (u32)sqrt((double)reg[0].I);
|
rlm@1
|
1228 #ifdef GBA_LOGGING
|
rlm@1
|
1229 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
1230 {
|
rlm@1
|
1231 log("Sqrt: return=%08x\n",
|
rlm@1
|
1232 reg[0].I);
|
rlm@1
|
1233 }
|
rlm@1
|
1234 #endif
|
rlm@1
|
1235 }
|
rlm@1
|
1236
|
rlm@1
|
1237 void BIOS_MidiKey2Freq()
|
rlm@1
|
1238 {
|
rlm@1
|
1239 #ifdef GBA_LOGGING
|
rlm@1
|
1240 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
1241 {
|
rlm@1
|
1242 log("MidiKey2Freq: WaveData=%08x mk=%08x fp=%08x\n",
|
rlm@1
|
1243 reg[0].I,
|
rlm@1
|
1244 reg[1].I,
|
rlm@1
|
1245 reg[2].I);
|
rlm@1
|
1246 }
|
rlm@1
|
1247 #endif
|
rlm@1
|
1248 int freq = CPUReadMemory(reg[0].I+4);
|
rlm@1
|
1249 double tmp;
|
rlm@1
|
1250 tmp = ((double)(180 - reg[1].I)) - ((double)reg[2].I / 256.f);
|
rlm@1
|
1251 tmp = pow((double)2.f, tmp / 12.f);
|
rlm@1
|
1252 reg[0].I = (int)((double)freq / tmp);
|
rlm@1
|
1253
|
rlm@1
|
1254 #ifdef GBA_LOGGING
|
rlm@1
|
1255 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
1256 {
|
rlm@1
|
1257 log("MidiKey2Freq: return %08x\n",
|
rlm@1
|
1258 reg[0].I);
|
rlm@1
|
1259 }
|
rlm@1
|
1260 #endif
|
rlm@1
|
1261 }
|
rlm@1
|
1262
|
rlm@1
|
1263 void BIOS_SndDriverJmpTableCopy()
|
rlm@1
|
1264 {
|
rlm@1
|
1265 #ifdef GBA_LOGGING
|
rlm@1
|
1266 if (systemVerbose & VERBOSE_SWI)
|
rlm@1
|
1267 {
|
rlm@1
|
1268 log("SndDriverJmpTableCopy: dest=%08x\n",
|
rlm@1
|
1269 reg[0].I);
|
rlm@1
|
1270 }
|
rlm@1
|
1271 #endif
|
rlm@1
|
1272 for (int i = 0; i < 0x24; i++)
|
rlm@1
|
1273 {
|
rlm@1
|
1274 CPUWriteMemory(reg[0].I, 0x9c);
|
rlm@1
|
1275 reg[0].I += 4;
|
rlm@1
|
1276 }
|
rlm@1
|
1277 }
|
rlm@1
|
1278
|