annotate src/gba/bios.cpp @ 92:1ff2c546f5ad

added tick(), which allows one to step through each opcode of gameboy
author Robert McIntyre <rlm@mit.edu>
date Sun, 11 Mar 2012 19:07:31 -0500
parents f9f4f1b99eed
children
rev   line source
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