home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / bios.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  27.0 KB  |  1,159 lines

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