diff -Nru dolphin-emu-2.0+svn5985/Data/User/OpenCL/TextureDecoder.cl dolphin-emu-2.0+svn6107/Data/User/OpenCL/TextureDecoder.cl --- dolphin-emu-2.0+svn5985/Data/User/OpenCL/TextureDecoder.cl 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Data/User/OpenCL/TextureDecoder.cl 2010-08-18 03:25:14.000000000 +0100 @@ -24,9 +24,9 @@ { uchar4 val = vload4(srcOffset, src); uchar8 res; - res.even = (val >> (uchar4)4) & (uchar4)0x0F; - res.odd = val & (uchar4)0x0F; - res |= res << (uchar8)4; + res.even = (val >> 4) & 0x0F; + res.odd = val & 0x0F; + res |= res << 4; vstore8(res, 0, dst + ((y + iy)*width + x)); srcOffset++; } @@ -41,9 +41,9 @@ { uchar4 val = vload4(srcOffset, src); uchar8 res; - res.even = (val >> (uchar4)4) & (uchar4)0x0F; - res.odd = val & (uchar4)0x0F; - res |= res << (uchar8)4; + res.even = (val >> 4) & 0x0F; + res.odd = val & 0x0F; + res |= res << 4; vstore8(upsample(upsample(res,res),upsample(res,res)), 0, dst + ((y + iy)*width + x)); srcOffset++; } @@ -108,8 +108,8 @@ for (int iy = 0; iy < 4; iy++) { val = vload8(srcOffset++, src); - res = upsample(val >> (uchar8)4, val & (uchar8)0xF); - res |= res << (ushort8)4; + res = upsample(val >> 4, val & 0xF); + res |= res << 4; vstore8(res, 0, dst + y*width + x); dst+=width; } @@ -125,10 +125,10 @@ for (int iy = 0; iy < 4; iy++) { val = vload8(srcOffset++, src); - uchar8 a = val >> (uchar8)4; - uchar8 l = val & (uchar8)0xF; + uchar8 a = val >> 4; + uchar8 l = val & 0xF; res = upsample(upsample(a, l), upsample(l,l)); - res |= res << (uint8)4; + res |= res << 4; vstore8(res, 0, dst + y*width + x); dst+=width; } @@ -142,7 +142,7 @@ for (int iy = 0; iy < 4; iy++) { ushort8 val = (ushort8)(vload4(srcOffset, src), vload4(srcOffset + 4, src)); - ushort8 bgra = rotate(val,(ushort8)8).s40516273; + ushort8 bgra = rotate(val,8).s40516273; vstore8(bgra, 0, dst + ((y + iy)*width + x) * 2); srcOffset++; } @@ -175,7 +175,7 @@ dst += width*y + x; for (int iy = 0; iy < 4; iy++) { - vstore4(rotate(vload4(srcOffset++, src),(ushort4)8), 0, dst + iy*width); + vstore4(rotate(vload4(srcOffset++, src),8), 0, dst + iy*width); } } @@ -189,10 +189,10 @@ uchar8 val = vload8(srcOffset++, src); uchar16 res; - res.even.even = bitselect(val.even, val.even >> (uchar4)5, (uchar4)7); - res.odd.even = bitselect((val.odd >> (uchar4)3) | (val.even << (uchar4)5), val.even >> (uchar4)1, (uchar4)3); - res.even.odd = bitselect(val.odd << (uchar4)3, val.odd >> (uchar4)2, (uchar4)7); - res.odd.odd = (uchar4)0xFF; + res.even.even = bitselect(val.even, val.even >> 5, 7); + res.odd.even = bitselect((val.odd >> 3) | (val.even << 5), val.even >> 1, 3); + res.even.odd = bitselect(val.odd << 3, val.odd >> 2, 7); + res.odd.odd = 0xFF; vstore16(res, 0, dst + ((y + iy)*width + x) * 4); } @@ -207,16 +207,16 @@ uchar16 resNoAlpha, resAlpha, choice; #define iterateRGB5A3() \ val = vload8(srcOffset++, src); \ - resNoAlpha.s26AE = val.even << (uchar4)1; \ - resNoAlpha.s159D = val.even << (uchar4)6 | val.odd >> (uchar4)2; \ - resNoAlpha.s048C = val.odd << (uchar4)3; \ - resNoAlpha = bitselect(resNoAlpha, resNoAlpha >> (uchar16)5, (uchar16)0x3); \ - resNoAlpha.s37BF = (uchar4)(0xFF); \ - resAlpha.s26AE = bitselect(val.even << (uchar4)4, val.even, (uchar4)0xF); \ - resAlpha.s159D = bitselect(val.odd, val.odd >> (uchar4)4, (uchar4)0xF); \ - resAlpha.s048C = bitselect(val.odd << (uchar4)4, val.odd, (uchar4)0xF); \ - resAlpha.s37BF = bitselect(val.even << (uchar4)1, val.even >> (uchar4)2, (uchar4)0x1C); \ - resAlpha.s37BF = bitselect(resAlpha.s37BF, val.even >> (uchar4)5, (uchar4)0x3); \ + resNoAlpha.s26AE = val.even << 1; \ + resNoAlpha.s159D = val.even << 6 | val.odd >> 2; \ + resNoAlpha.s048C = val.odd << 3; \ + resNoAlpha = bitselect(resNoAlpha, resNoAlpha >> 5, 0x3); \ + resNoAlpha.s37BF = 0xFF; \ + resAlpha.s26AE = bitselect(val.even << 4, val.even, 0xF); \ + resAlpha.s159D = bitselect(val.odd, val.odd >> 4, 0xF); \ + resAlpha.s048C = bitselect(val.odd << 4, val.odd, 0xF); \ + resAlpha.s37BF = bitselect(val.even << 1, val.even >> 2, 0x1C); \ + resAlpha.s37BF = bitselect(resAlpha.s37BF, val.even >> 5, 0x3); \ choice = (uchar16)((uchar4)(val.even.s0), \ (uchar4)(val.even.s1), \ (uchar4)(val.even.s2), \ @@ -237,16 +237,16 @@ uchar16 resNoAlpha, resAlpha, choice; #define iterateRGB5A3_RGBA() \ val = vload8(srcOffset++, src); \ - resNoAlpha.s048C = val.even << (uchar4)1; \ - resNoAlpha.s159D = val.even << (uchar4)6 | val.odd >> (uchar4)2; \ - resNoAlpha.s26AE = val.odd << (uchar4)3; \ - resNoAlpha = bitselect(resNoAlpha, resNoAlpha >> (uchar16)5, (uchar16)0x3); \ - resNoAlpha.s37BF = (uchar4)(0xFF); \ - resAlpha.s048C = bitselect(val.even << (uchar4)4, val.even, (uchar4)0xF); \ - resAlpha.s159D = bitselect(val.odd, val.odd >> (uchar4)4, (uchar4)0xF); \ - resAlpha.s26AE = bitselect(val.odd << (uchar4)4, val.odd, (uchar4)0xF); \ - resAlpha.s37BF = bitselect(val.even << (uchar4)1, val.even >> (uchar4)2, (uchar4)0x1C); \ - resAlpha.s37BF = bitselect(resAlpha.s37BF, val.even >> (uchar4)5, (uchar4)0x3); \ + resNoAlpha.s048C = val.even << 1; \ + resNoAlpha.s159D = val.even << 6 | val.odd >> 2; \ + resNoAlpha.s26AE = val.odd << 3; \ + resNoAlpha = bitselect(resNoAlpha, resNoAlpha >> 5, 0x3); \ + resNoAlpha.s37BF = 0xFF; \ + resAlpha.s048C = bitselect(val.even << 4, val.even, 0xF); \ + resAlpha.s159D = bitselect(val.odd, val.odd >> 4, 0xF); \ + resAlpha.s26AE = bitselect(val.odd << 4, val.odd, 0xF); \ + resAlpha.s37BF = bitselect(val.even << 1, val.even >> 2, 0x1C); \ + resAlpha.s37BF = bitselect(resAlpha.s37BF, val.even >> 5, 0x3); \ choice = (uchar16)((uchar4)(val.even.s0), \ (uchar4)(val.even.s1), \ (uchar4)(val.even.s2), \ @@ -274,13 +274,13 @@ uchar2 colora565 = (uchar2)(val.s1, val.s3); uchar2 colorb565 = (uchar2)(val.s0, val.s2); - uchar8 color32 = (uchar8)(bitselect(colora565 << (uchar2)3, colora565 >> (uchar2)2, (uchar2)7), - bitselect((colora565 >> (uchar2)3) | (colorb565 << (uchar2)5), colorb565 >> (uchar2)1, (uchar2)3), - bitselect(colorb565, colorb565 >> (uchar2)5, (uchar2)7), + uchar8 color32 = (uchar8)(bitselect(colora565 << 3, colora565 >> 2, 7), + bitselect((colora565 >> 3) | (colorb565 << 5), colorb565 >> 1, 3), + bitselect(colorb565, colorb565 >> 5, 7), (uchar2)0xFF); ushort4 frac2 = convert_ushort4(color32.even) - convert_ushort4(color32.odd); - uchar4 frac = convert_uchar4((frac2 * (ushort4)3) / (ushort4)8); + uchar4 frac = convert_uchar4((frac2 * 3) / 8); ushort4 colorAlpha = upsample((uchar4)(color32.even.s0,color32.even.s1,color32.even.s2,0), rhadd(color32.odd, color32.even)); @@ -320,13 +320,13 @@ uchar2 colora565 = (uchar2)(val.s1, val.s3); uchar2 colorb565 = (uchar2)(val.s0, val.s2); - uchar8 color32 = (uchar8)(bitselect(colorb565, colorb565 >> (uchar2)5, (uchar2)7), - bitselect((colora565 >> (uchar2)3) | (colorb565 << (uchar2)5), colorb565 >> (uchar2)1, (uchar2)3), - bitselect(colora565 << (uchar2)3, colora565 >> (uchar2)2, (uchar2)7), + uchar8 color32 = (uchar8)(bitselect(colorb565, colorb565 >> 5, 7), + bitselect((colora565 >> 3) | (colorb565 << 5), colorb565 >> 1, 3), + bitselect(colora565 << 3, colora565 >> 2, 7), (uchar2)0xFF); ushort4 frac2 = convert_ushort4(color32.even) - convert_ushort4(color32.odd); - uchar4 frac = convert_uchar4((frac2 * (ushort4)3) / (ushort4)8); + uchar4 frac = convert_uchar4((frac2 * 3) / 8); ushort4 colorAlpha = upsample((uchar4)(color32.even.s0,color32.even.s1,color32.even.s2,0), rhadd(color32.odd, color32.even)); diff -Nru dolphin-emu-2.0+svn5985/debian/changelog dolphin-emu-2.0+svn6107/debian/changelog --- dolphin-emu-2.0+svn5985/debian/changelog 2010-08-11 21:23:11.000000000 +0100 +++ dolphin-emu-2.0+svn6107/debian/changelog 2010-08-19 18:27:18.000000000 +0100 @@ -1,14 +1,14 @@ -dolphin-emu (2.0+svn5985-0ubuntu3~lucid) lucid; urgency=low +dolphin-emu (2.0+svn6107-0ubuntu2~lucid) lucid; urgency=low - * Trying to rebuild again + * dummy package rebuild against wxlib in ubuntu-proposed - -- Andrei Dziahel Wed, 11 Aug 2010 23:22:42 +0300 + -- Andrei Dziahel Thu, 19 Aug 2010 20:24:57 +0300 -dolphin-emu (2.0+svn5985-0ubuntu2~lucid) lucid; urgency=low +dolphin-emu (2.0+svn6107-0ubuntu1~lucid) lucid; urgency=low - * Rebuilding to match updated WX Lib + * New SVN Release - -- Andrei Dziahel Wed, 11 Aug 2010 23:04:42 +0300 + -- Glenn Rice Tue, 17 Aug 2010 20:42:59 -0500 dolphin-emu (2.0+svn5985-0ubuntu1~lucid) lucid; urgency=low diff -Nru dolphin-emu-2.0+svn5985/debian/control dolphin-emu-2.0+svn6107/debian/control --- dolphin-emu-2.0+svn5985/debian/control 2010-07-01 19:21:35.000000000 +0100 +++ dolphin-emu-2.0+svn6107/debian/control 2010-08-18 03:27:01.000000000 +0100 @@ -28,7 +28,7 @@ wx2.8-headers, x11proto-xf86vidmode-dev, zlib1g-dev -Standards-Version: 3.8.4 +Standards-Version: 3.9.1 Homepage: http://www.dolphin-emu.com Package: dolphin-emu diff -Nru dolphin-emu-2.0+svn5985/debian/patches/00-set-svn-version dolphin-emu-2.0+svn6107/debian/patches/00-set-svn-version --- dolphin-emu-2.0+svn5985/debian/patches/00-set-svn-version 2010-07-28 02:30:22.000000000 +0100 +++ dolphin-emu-2.0+svn6107/debian/patches/00-set-svn-version 2010-08-18 03:25:42.000000000 +0100 @@ -1,12 +1,13 @@ diff -Naur dolphin-emu.orig/SconsTests/utils.py dolphin-emu/SconsTests/utils.py --- dolphin-emu.orig/SconsTests/utils.py 2010-01-13 12:47:12.509314979 -0600 +++ dolphin-emu/SconsTests/utils.py 2010-01-13 14:41:15.557039942 -0600 -@@ -85,7 +85,7 @@ - def GenerateRevFile(flavour, template, output): +@@ -84,8 +84,7 @@ + def GenerateRevFile(flavour, template, output): try: -- svnrev = os.popen('svnversion .').read().strip().split(':')[0] -+ svnrev = "5985" +- svnrev = os.popen('svnversion ' + os.path.dirname(template)).\ +- read().strip().split(':')[0] ++ svnrev = "6108" except: - svnrev = "" - + svnrev = '' + diff -Nru dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_3B3B30CA.txt dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_3B3B30CA.txt --- dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_3B3B30CA.txt 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_3B3B30CA.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,436 +0,0 @@ -/* -ROM functions used: -0x8000 dsp reset -0x8078 wait for CMBH & 0x8000 -0x807e wait for DMBH & 0x8000 -0x808b dump DRAM/IRAM to mainmem -0x80b5 boot new ucode -0x80bc boot new ucode without ACC clearing by ROM - -For the rest, this ucode is just calling the last few instructions -from huge functions in ROM - some kind of obfuscation? - -0x81f4 - 81f4 b51e mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M - 81f5 9909 asr16'ir $ACC1 : $AR1 - 81f6 1b7f srri @$AR3, $AC1.M - 81f7 812b clr's $ACC0 : @$AR3, $AC1.L -0x8458 - 8458 b51e mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M - 8459 9900 asr16 $ACC1 - 845a 1b7f srri @$AR3, $AC1.M - 845b 812b clr's $ACC0 : @$AR3, $AC1.L -0x8723 - 8723 3300 xorr $AC1.M, $AX1.H - 8724 1adf srrd @$AR2, $AC1.M -0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M -0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -*/ - -0000 0000 nop -0001 0000 nop -0002 0000 nop -0003 0000 nop -0004 0000 nop -0005 0000 nop -0006 0000 nop -0007 0000 nop -0008 0000 nop -0009 0000 nop -000a 0000 nop -000b 0000 nop -000c 0000 nop -000d 0021 halt -000e 02ff rti -000f 0021 halt - -0010 1306 sbset #0x06 -0011 1203 sbclr #0x03 -0012 1204 sbclr #0x04 -0013 1305 sbset #0x05 -0014 0092 00ff lri $CR, #0x00ff -0016 0088 ffff lri $WR0, #0xffff -0018 0089 ffff lri $WR1, #0xffff -001a 008a ffff lri $WR2, #0xffff -001c 008b ffff lri $WR3, #0xffff -001e 8f00 set40 -001f 8b00 m0 -0020 8c00 clr15 -0021 02bf 807e call 0x807e // loop until dsp->cpu mailbox is empty -0023 16fc dcd1 si @DMBH, #0xdcd1 -0025 16fd 0000 si @DMBL, #0x0000 // sendmail 0xdcd10000 -0027 16fb 0001 si @DIRQ, #0x0001 - -// wait for cpu mail == 0xabbaxxxx -0029 02bf 8078 call 0x8078 // wait for cpu mail -002b 24ff lrs $AC0.L, @CMBL -002c 0280 abba cmpi $AC0.M, #0xabba -002e 0294 0029 jnz 0x0029 - -// wait for cpu mail -0030 8e00 set16 -0031 02bf 8078 call 0x8078 - -0033 20ff lrs $AX0.L, @CMBL -0034 0240 0fff andi $AC0.M, #0x0fff -0036 1f5e mrr $AX0.H, $AC0.M -0037 009b 0000 lri $AX1.H, #0x0000 // DSP-dram addr -0039 0099 0020 lri $AX1.L, #0x0020 // length (20 bytes = 10 words, word 9 and 10 are addr where result should DMA'd to in main mem) -003b 0087 0000 lri $IX3, #0x0000 // there will be no ucode/iram upload -003d 0080 0041 lri $AR0, #0x0041 // return addr after dram upload -003f 029f 80bc jmp 0x80bc // DRAM upload !! -// $AX0.H-$AX0.L - CPU(PPC) addr = mail & 0x0fffffff -// upload data from mainmem do dsp dram and jump to 0x41 after that - -0041 02bf 008c call 008c_BigCrazyFunction() // <<------------- main crap is here!!!!!!!!! -0043 02bf 807e call 0x807e // loop until dsp->cpu mailbox is empty - -0045 16fc dcd1 si @DMBH, #0xdcd1 -0047 16fd 0003 si @DMBL, #0x0003 // sendmail 0xdcd10003 (aka... calc is over, result is in main mem now) -0049 16fb 0001 si @DIRQ, #0x0001 -004b 8f00 set40 - -004c 02bf 8078 call 0x8078 -004e 0280 cdd1 cmpi $AC0.M, #0xcdd1 -0050 0294 004c jnz 0x004c - -0052 26ff lrs $AC0.M, @CMBL -0053 0280 0001 cmpi $AC0.M, #0x0001 -0055 0295 005e jz 0x005e // if cpu->dsp mail was 0xcdd10001 -> 005e_PrepareBootUcode() - -0057 0280 0002 cmpi $AC0.M, #0x0002 -0059 0295 8000 jz 0x8000 // if cpu->dsp mail was 0xcdd10002 -> dsp reset ( jmp to irom(0x8000)) - -005b 029f 004c jmp 0x004c // wait for next mail from cpu -005d 0021 halt - -void 005e_PrepareBootUcode() -{ -005e 8e00 set16 -005f 02bf 8078 call 0x8078 // wait for cpu mail -0061 24ff lrs $AC0.L, @CMBL -0062 02bf 8078 call 0x8078 // wait for cpu mail -0064 24ff lrs $AC0.L, @CMBL -0065 02bf 8078 call 0x8078 // wait for cpu mail -0067 24ff lrs $AC0.L, @CMBL -0068 02bf 8078 call 0x8078 // wait for cpu mail -006a 00c5 ffff lr $IX1, @CMBL -006c 0240 0fff andi $AC0.M, #0x0fff -006e 1c9e mrr $IX0, $AC0.M -006f 02bf 8078 call 0x8078 // wait for cpu mail -0071 00c7 ffff lr $IX3, @CMBL -0073 02bf 8078 call 0x8078 // wait for cpu mail -0075 00c6 ffff lr $IX2, @CMBL -0077 02bf 8078 call 0x8078 // wait for cpu mail -0079 00c0 ffff lr $AR0, @CMBL -007b 02bf 8078 call 0x8078 // wait for cpu mail -007d 20ff lrs $AX0.L, @CMBL -007e 0240 0fff andi $AC0.M, #0x0fff -0080 1f5e mrr $AX0.H, $AC0.M -0081 02bf 8078 call 0x8078 // wait for cpu mail -0083 21ff lrs $AX1.L, @CMBL -0084 02bf 8078 call 0x8078 // wait for cpu mail -0086 23ff lrs $AX1.H, @CMBL -0087 1205 sbclr #0x05 -0088 1206 sbclr #0x06 -0089 029f 80b5 jmp 80b5_BootUcode() -008b 0021 halt -} - -// does some crazy stuff with data at dram @0x3/0x5/0x6/0x7 with help of some values from drom :) -// result is @0x22,@0x23 and written back to main memory to dmem-0x08:dmem-0x09 -void 008c_BigCrazyFunction() -{ -008c 8100 clr $ACC0 -008d 0081 0010 lri $AR1, #0x0010 -008f 1020 loopi #0x20 - 0090 1b3e srri @$AR1, $AC0.M -0091 00df 1456 lr $AC1.M, @0x1456 -0093 0340 ffd0 andi $AC1.M, #0xffd0 -0095 8417 clrp'mv : $AX1.L, $AC1.M -0096 0080 0000 lri $AR0, #0x0000 -0098 0086 0000 lri $IX2, #0x0000 -009a 0082 001f lri $AR2, #0x001f -009c 00de 15f6 lr $AC0.M, @0x15f6 -009e 1408 lsl $ACC0, #8 -009f 00df 1766 lr $AC1.M, @0x1766 -00a1 0340 00ff andi $AC1.M, #0x00ff -00a3 1f5f mrr $AX0.H, $AC1.M -00a4 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -00a6 1f1c mrr $AX0.L, $AC0.L -00a7 811e clr'mv $ACC0 : $AX1.H, $AC0.M -00a8 191e lrri $AC0.M, @$AR0 -00a9 1478 lsr $ACC0, #-8 -00aa 1ffc mrr $AC1.M, $AC0.L -00ab 1f5e mrr $AX0.H, $AC0.M -00ac 02bf 8809 call 0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M -00ae 02bf 8723 call 0x8723 - 8723 3300 xorr $AC1.M, $AX1.H - 8724 1adf srrd @$AR2, $AC1.M -00b0 0006 dar $AR2 -00b1 8106 clr'dr $ACC0 : $AR2 -00b2 00de 166c lr $AC0.M, @0x166c -00b4 1404 lsl $ACC0, #4 -00b5 0240 ff00 andi $AC0.M, #0xff00 -00b7 00df 1231 lr $AC1.M, @0x1231 -00b9 1578 lsr $ACC1, #-8 -00ba 0340 00ff andi $AC1.M, #0x00ff -00bc 1f5f mrr $AX0.H, $AC1.M -00bd 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -00bf 1f1c mrr $AX0.L, $AC0.L -00c0 811e clr'mv $ACC0 : $AX1.H, $AC0.M -00c1 191e lrri $AC0.M, @$AR0 -00c2 1478 lsr $ACC0, #-8 -00c3 1ffc mrr $AC1.M, $AC0.L -00c4 1f5e mrr $AX0.H, $AC0.M -00c5 02bf 8809 call 0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M -00c7 02bf 8723 call 0x8723 - 8723 3300 xorr $AC1.M, $AX1.H - 8724 1adf srrd @$AR2, $AC1.M -00c9 8100 clr $ACC0 -00ca 8900 clr $ACC1 -00cb 00d1 0005 lr $AC1.H, @0x0005 -00cd 9900 asr16 $ACC1 -00ce 8200 cmp -00cf 0295 00e5 jz 0x00e5 - -00d1 0291 00f3 jl 0x00f3 - -00d3 0082 0010 lri $AR2, #0x0010 -00d5 0086 0001 lri $IX2, #0x0001 -00d7 00d0 171b lr $AC0.H, @0x171b -00d9 9100 asr16 $ACC0 -00da 7d00 neg $ACC1 -00db 4d00 add $ACC1, $ACC0 -00dc 1501 lsl $ACC1, #1 -00dd 1f5f mrr $AX0.H, $AC1.M -00de 00df 0003 lr $AC1.M, @0x0003 -00e0 1504 lsl $ACC1, #4 -00e1 02bf 8809 call 0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M -00e3 029f 0102 jmp 0x0102 - -: -00e5 0082 0011 lri $AR2, #0x0011 -00e7 00df 0003 lr $AC1.M, @0x0003 -00e9 1501 lsl $ACC1, #1 -00ea 1f5f mrr $AX0.H, $AC1.M -00eb 00de 1043 lr $AC0.M, @0x1043 -00ed 0240 fff0 andi $AC0.M, #0xfff0 -00ef 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -00f1 029f 0102 jmp 0x0102 - -: -00f3 0082 0010 lri $AR2, #0x0010 -00f5 0086 0001 lri $IX2, #0x0001 -00f7 00d0 1285 lr $AC0.H, @0x1285 -00f9 9100 asr16 $ACC0 -00fa 4d00 add $ACC1, $ACC0 -00fb 1501 lsl $ACC1, #1 -00fc 00de 0003 lr $AC0.M, @0x0003 -00fe 1404 lsl $ACC0, #4 -00ff 1f5e mrr $AX0.H, $AC0.M -0100 02bf 8809 call 0x8809 - 8809 392e orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L - 880a 1b5f srri @$AR2, $AC1.M - -: -0102 0083 0013 lri $AR3, #0x0013 -0104 1b7e srri @$AR3, $AC0.M -0105 8923 clr's $ACC1 : @$AR3, $AC0.L -0106 0083 0013 lri $AR3, #0x0013 -0108 00df 0007 lr $AC1.M, @0x0007 -010a 00de 11b8 lr $AC0.M, @0x11b8 -010c 0240 fff0 andi $AC0.M, #0xfff0 -010e 1f5e mrr $AX0.H, $AC0.M -010f 02bf 81f4 call 0x81f4 - 81f4 b51e mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M - 81f5 9909 asr16'ir $ACC1 : $AR1 - 81f6 1b7f srri @$AR3, $AC1.M - 81f7 812b clr's $ACC0 : @$AR3, $AC1.L -0111 f100 lsl16 $ACC1 -0112 02bf 8458 call 0x8458 - 8458 b51e mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M - 8459 9900 asr16 $ACC1 - 845a 1b7f srri @$AR3, $AC1.M - 845b 812b clr's $ACC0 : @$AR3, $AC1.L -0114 8f00 set40 -0115 0082 0015 lri $AR2, #0x0015 -0117 00de 0006 lr $AC0.M, @0x0006 -0119 00da 165b lr $AX0.H, @0x165b -011b 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -011d 14fd asr $ACC0, #-3 -011e 1403 lsl $ACC0, #3 -011f 1b5e srri @$AR2, $AC0.M -0120 1b5c srri @$AR2, $AC0.L -0121 0082 0016 lri $AR2, #0x0016 -0123 00de 1723 lr $AC0.M, @0x1723 -0125 14f4 asr $ACC0, #-12 -0126 00da 166b lr $AX0.H, @0x166b -0128 02bf 88e5 call 0x88e5 - 88e5 387a orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 - 88e6 18dd lrrd $AC1.L, @$AR2 - 88e7 4c05 add'dr $ACC0, $ACC1 : $AR1 - 88e8 1b5e srri @$AR2, $AC0.M - 88e9 1a5c srr @$AR2, $AC0.L -012a b100 tst $ACC0 -012b 0290 012e jge 0x012e - -012d 8100 clr $ACC0 - -: -012e 14fd asr $ACC0, #-3 -012f 8e00 set16 -0130 00df 1491 lr $AC1.M, @0x1491 -0132 0340 d0f0 andi $AC1.M, #0xd0f0 -0134 1cbf mrr $IX1, $AC1.M -0135 00df 1468 lr $AC1.M, @0x1468 -0137 00d1 11fc lr $AC1.H, @0x11fc -0139 157c lsr $ACC1, #-4 -013a 1cdf mrr $IX2, $AC1.M -013b 00d1 11b8 lr $AC1.H, @0x11b8 -013d 9900 asr16 $ACC1 -013e 1418 lsl $ACC0, #24 -013f 1478 lsr $ACC0, #-8 -0140 1f5e mrr $AX0.H, $AC0.M -0141 1ffe mrr $AC1.M, $AC0.M -0142 1f65 mrr $AX1.H, $IX1 -0143 3600 andr $AC0.M, $AX1.H -0144 1402 lsl $ACC0, #2 -0145 1f66 mrr $AX1.H, $IX2 -0146 3700 andr $AC1.M, $AX1.H -0147 1501 lsl $ACC1, #1 -0148 4c00 add $ACC0, $ACC1 -0149 1518 lsl $ACC1, #24 -014a 9900 asr16 $ACC1 -014b 3500 andr $AC1.M, $AX0.H -014c 4c00 add $ACC0, $ACC1 -014d 00df 0012 lr $AC1.M, @0x0012 -014f 3f00 orc $AC1.M, $AC0.M -0150 00ff 0012 sr @0x0012, $AC1.M -0152 1470 lsr $ACC0, #-16 -0153 00df 0011 lr $AC1.M, @0x0011 -0155 3f00 orc $AC1.M, $AC0.M -0156 00ff 0011 sr @0x0011, $AC1.M -0158 1fa5 mrr $AC1.L, $IX1 -0159 1501 lsl $ACC1, #1 -015a 1fe6 mrr $AC1.M, $IX2 -015b f100 lsl16 $ACC1 -015c 15f8 asr $ACC1, #-8 -015d f500 lsr16 $ACC1 -015e 1f5f mrr $AX0.H, $AC1.M -015f 1f7d mrr $AX1.H, $AC1.L -0160 8100 clr $ACC0 -0161 00de 0011 lr $AC0.M, @0x0011 -0163 3400 andr $AC0.M, $AX0.H -0164 8900 clr $ACC1 -0165 00df 0012 lr $AC1.M, @0x0012 -0167 3500 andr $AC1.M, $AX0.H -0168 4c00 add $ACC0, $ACC1 -0169 00df 0012 lr $AC1.M, @0x0012 -016b 1578 lsr $ACC1, #-8 -016c 4c00 add $ACC0, $ACC1 -016d 8900 clr $ACC1 -016e 1ffe mrr $AC1.M, $AC0.M -016f 1508 lsl $ACC1, #8 -0170 3b00 orr $AC1.M, $AX1.H -0171 00de 0011 lr $AC0.M, @0x0011 -0173 3e00 orc $AC0.M, $AC1.M -0174 00df 0012 lr $AC1.M, @0x0012 -0176 3b00 orr $AC1.M, $AX1.H -0177 1cbf mrr $IX1, $AC1.M -0178 00da 15f1 lr $AX0.H, @0x15f1 -017a 3500 andr $AC1.M, $AX0.H -017b 0295 0192 jz 0x0192 -if () { - - 017d 00df 10e2 lr $AC1.M, @0x10e2 - 017f 1508 lsl $ACC1, #8 - 0180 1f5f mrr $AX0.H, $AC1.M - 0181 00df 103b lr $AC1.M, @0x103b - 0183 7900 decm $AC1.M - 0184 3900 orr $AC1.M, $AX0.H - 0185 3080 xorc $AC0.M, $AC1.M - 0186 00fe 0022 sr @0x0022, $AC0.M - 0188 00dc 1229 lr $AC0.L, @0x1229 - 018a 00dd 11f8 lr $AC1.L, @0x11f8 - 018c 5c00 sub $ACC0, $ACC1 - 018d f000 lsl16 $ACC0 - 018e 1fe5 mrr $AC1.M, $IX1 - 018f 3080 xorc $AC0.M, $AC1.M - 0190 029f 01a5 jmp 0x01a5 - -} else { - - 0192 00df 10ca lr $AC1.M, @0x10ca - 0194 1508 lsl $ACC1, #8 - 0195 1f5f mrr $AX0.H, $AC1.M - 0196 00df 1043 lr $AC1.M, @0x1043 - 0198 7500 incm $AC1.M - 0199 3900 orr $AC1.M, $AX0.H - 019a 3080 xorc $AC0.M, $AC1.M - 019b 00fe 0022 sr @0x0022, $AC0.M - 019d 00dc 1259 lr $AC0.L, @0x1259 - 019f 00dd 16fe lr $AC1.L, @0x16fe - 01a1 4c00 add $ACC0, $ACC1 - 01a2 f000 lsl16 $ACC0 - 01a3 1fe5 mrr $AC1.M, $IX1 - 01a4 3080 xorc $AC0.M, $AC1.M -} - -01a5 00fe 0023 sr @0x0023, $AC0.M -// this is where result is written to main memory -// dsp mem 0x20-0x23 (8 bytes) are written back, because only values @22 and @23 were modified result is 32bit -01a7 00da 0008 lr $AX0.H, @0x0008 // cpu addr high -01a9 00d8 0009 lr $AX0.L, @0x0009 // cpu addr low -01ab 009b 0020 lri $AX1.H, #0x0020 // dsp addr -01ad 0099 0008 lri $AX1.L, #0x0008 // length -01af 0087 0000 lri $IX3, #0x0000 // there will be no iram dma -01b1 02bf 808b call 0x808b // dram->cpu <<<--- important!! -01b3 02df ret -} - -01b4 0000 nop -01b5 0000 nop -01b6 0000 nop -01b7 0000 nop -01b8 0000 nop -01b9 0000 nop -01ba 0000 nop -01bb 0000 nop -01bc 0000 nop -01bd 0000 nop -01be 0000 nop -01bf 0000 nop diff -Nru dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_6A696CE7.txt dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_6A696CE7.txt --- dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_6A696CE7.txt 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_6A696CE7.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,3467 +0,0 @@ -// This document was previously called "DSP_UC_AX1.txt" and "Crazy Taxi.txt" -// CR is set to #FF all the time in this ucode, so srs/lrs always operate on hw registers. - -////////////////////////////////////////////////////////////////////////// -// Known addresses in DRAM -Addr Name Description/Notes - -// Buffers -0x0000 Main Right -0x0140 Main Left -0x0280 -0x0400 -0x0540 -0x0680 -0x07c0 -0x0900 -0x0a40 - -0x03c0 update_block Contains pairs to update current PB with - -0x0b80 pb Current pb, length = 0xc0 - -0x0e04 ms_remaining Milliseconds remaining to process for current voice -0x0e05 pUpdate_block Pointer to update_block -0x0e06 pUpdates_this_ms Pointer to number of updates - -// Pointers to buffers -0x0e08 0x0000 See buffers at 0x0000 -0x0e09 0x0140 -0x0e0a 0x0280 -0x0e0b 0x0400 -0x0e0c 0x0540 -0x0e0d 0x0680 -0x0e0e 0x07c0 -0x0e0f 0x0900 -0x0e10 0x0a40 - -// Func pointers -0x0e14 selectedMixCtrl -0x0e15 selectedSRC -0x0e16 selectedCoef Points into DROM - -// ITD -0x0e40 -0x0e41 -0x0e42 -0x0e43 -////////////////////////////////////////////////////////////////////////// - -// Good ol' exception table -0000 0000 nop -0001 0000 nop // 0 Reset falls through, kinda wierd... -0002 029f 0c10 jmp 0x0c10 // 1 Stack U/O flow -0004 029f 0c1f jmp 0x0c1f // 2 -0006 029f 0c3b jmp 0x0c3b // 3 -0008 029f 0c4a jmp 0x0c4a // 4 ? empty -000a 029f 0c50 jmp 0x0c50 // 5 accelerator address overflow -000c 029f 0c82 jmp 0x0c82 // 6 ? empty -000e 029f 0c88 jmp 0x0c88 // 7 ? empty - -// Entry point -void Task_Init() { - // AX operates in this context all the time - // 0010 1302 sbset #0x02 - // 0011 1303 sbset #0x03 - // 0012 1204 sbclr #0x04 - // 0013 1305 sbset #0x05 - // 0014 1306 sbset #0x06 - // 0015 8e00 set16 - // 0016 8c00 clr15 - // 0017 8b00 m0 - // 0018 0092 00ff lri $CR, #0x00ff - - // 001a 8100 clr $ACC0 - // 001b 8900 clr $ACC1 - // 001c 009e 0e80 lri $AC0.M, #0x0e80 - // 001e 00fe 0e1b sr @0x0e1b, $AC0.M - // 0020 8100 clr $ACC0 - // 0021 00fe 0e31 sr @0x0e31, $AC0.M - ACC0 = ACC1 = 0 - *0x0e1b = 0xe80 // Used in Cmd8 - *0x0e31 = 0 - - // Send DSP_INIT mail - // 0023 16fc dcd1 si @DMBH, #0xdcd1 - // 0025 16fd 0000 si @DMBL, #0x0000 - // 0027 16fb 0001 si @DIRQ, #0x0001 - DMB = 0xdcd10000 - // 0029 26fc lrs $AC0.M, @DMBH - // 002a 02a0 8000 andf $AC0.M, #0x8000 - // 002c 029c 0029 jlnz 0x0029 - while (@DMBH & 0x8000 == 0); - - // 002e 029f 0045 jmp 0x0045 - goto GetNextCmdBlock; -} - -void Task_Resume() { - // Ensure sane context - // 0030 1302 sbset #0x02 - // 0031 1303 sbset #0x03 - // 0032 1204 sbclr #0x04 - // 0033 1305 sbset #0x05 - // 0034 1306 sbset #0x06 - // 0035 8e00 set16 - // 0036 8c00 clr15 - // 0037 8b00 m0 - // 0038 0092 00ff lri $CR, #0x00ff - - // Send DSP_RESUME mail - // 003a 16fc dcd1 si @DMBH, #0xdcd1 - // 003c 16fd 0001 si @DMBL, #0x0001 - // 003e 16fb 0001 si @DIRQ, #0x0001 - DMB = 0xdcd10001 - // 0040 26fc lrs $AC0.M, @DMBH - // 0041 02a0 8000 andf $AC0.M, #0x8000 - // 0043 029c 0040 jlnz 0x0040 - while (@DMBH & 0x8000 == 0); - -GetNextCmdBlock: - 0045 8e00 set16 - 0046 8100 clr $ACC0 - 0047 8900 clr $ACC1 - 0048 009f babe lri $AC1.M, #0xbabe - - // Wait for 0xbabexxxx mail from cpu - do { - // 004a 26fe lrs $AC0.M, @CMBH - // 004b 02c0 8000 andcf $AC0.M, #0x8000 - // 004d 029c 004a jlnz 0x004a - while (@CMBH & 0x8000 == 0); - - // 004f 8200 cmp - // 0050 0294 004a jnz 0x004a - } while (@CMBH != 0xbabe); - - // Save the low 16bits of the mail - // 0052 23ff lrs $AX1.H, @CMBL - u16 length = @CMBL - - // Get next mail - // 0053 8100 clr $ACC0 - // 0054 26fe lrs $AC0.M, @CMBH - // 0055 02c0 8000 andcf $AC0.M, #0x8000 - // 0057 029c 0054 jlnz 0x0054 - while (@CMBH & 0x8000 == 0); - - // 0059 27ff lrs $AC1.M, @CMBL - // 005a 0240 7fff andi $AC0.M, #0x7fff - // 005c 2ece srs @DSMAH, $AC0.M - // 005d 2fcf srs @DSMAL, $AC1.M - // 005e 16cd 0c00 si @DSPA, #0x0c00 - // 0060 8100 clr $ACC0 - // 0061 2ec9 srs @DSCR, $AC0.M - // 0062 1ffb mrr $AC1.M, $AX1.H - // 0063 2fcb srs @DSBL, $AC1.M - // DMA in the CmdBlock - static u16* CmdBlockBuf = 0x0c00 - DSMA = (@CMBH & ~0x8000) << 16 | @CMBL - DSPA = CmdBlockBuf - DSCR = 0 // CPU -> DMEM - DSBL = length - - // 0064 02bf 055c call 0x055c - WaitDMA(); - - // Init the CmdBlock pointer - 0066 0080 0c00 lri $AR0, #0x0c00 - -DoNextCommand: - // 0068 8e00 set16 - // 0069 8100 clr $ACC0 - // 006a 8970 clr'l $ACC1 : $AC0.M, @$AR0 - // 006b b100 tst $ACC0 - // 006c 0291 007e jl 0x007e - u16 Cmd = *(CmdBlockBuf++) - if (Cmd < 0) // How could this be possible? 'l is 16bit load... - Die_InvalidCmd(); - - // 006e 0a12 lris $AX0.H, #0x12 - // 006f c100 cmpar $ACC0, $AX0.H - // 0070 0292 007e jg 0x007e - if (Cmd > 0x12) - Die_InvalidCmd(); - - // 0072 009f 0aff lri $AC1.M, #0x0aff - // 0074 4c00 add $ACC0, $ACC1 - // 0075 1c7e mrr $AR3, $AC0.M - // 0076 0213 ilrr $AC0.M, @$AR3 - // 0077 1c7e mrr $AR3, $AC0.M - // 0078 176f jmpr $AR3 - switch (Cmd) { - case 0: Cmd_0(); break; // 0082 - case 1: Cmd_1(); break; // 013e - case 2: Cmd_2(); break; // 01bc - case 3: Cmd_3(); break; // 0248 - case 4: Cmd_4(); break; // 0413 - case 5: Cmd_5(); break; // 0427 - case 6: Cmd_6(); break; // 0165 - case 7: Cmd_7(); break; // 0574 - case 8: Cmd_8(); break; // 0b37 - case 9: Cmd_9(); break; // 015f - case 0xa: Cmd_a(); break; // 0478 - case 0xb: Cmd_b(); break; // 0474 - case 0xc: Cmd_c(); break; // 0476 - case 0xd: Cmd_d(); break; // 01a9 - case 0xe: Cmd_e(); break; // 043b - case 0xf: Cmd_f(); break; // 047a - case 0x10: Cmd_10(); break; // 0bb1 - case 0x11: Cmd_11(); break; // 0175 - } - - // Somehow we've passed the cmd proccessor; DIE!! - // 0079 16fc fbad si @DMBH, #0xfbad - // 007b 16fd 8080 si @DMBL, #0x8080 - DMB = 0xfbad8080 - 007d 0021 halt -} - -// Die and conveniently tell the cpu which cmd was baad -void Die_InvalidCmd() { - 007e 16fc baad si @DMBH, #0xbaad - 0080 2efd srs @DMBL, $AC0.M - 0081 0021 halt -} - -// Executes the same operation 3 times on buffers: (0, 0x0400, 0x07c0) -void Cmd_0() { - // 0082 8100 clr $ACC0 - // 0083 8970 clr'l $ACC1 : $AC0.M, @$AR0 - // 0084 8e78 set16'l : $AC1.M, @$AR0 - u16 maddrh = *(CmdBlockBuf++) - u16 maddrl = *(CmdBlockBuf++) - - // 0085 2ece srs @DSMAH, $AC0.M - // 0086 2fcf srs @DSMAL, $AC1.M - // 0087 009e 0e44 lri $AC0.M, #0x0e44 - // 0089 2ecd srs @DSPA, $AC0.M - // 008a 0e00 lris $AC0.M, #0x00 - // 008b 2ec9 srs @DSCR, $AC0.M - // 008c 009e 0040 lri $AC0.M, #0x0040 - // 008e 2ecb srs @DSBL, $AC0.M - - // DMA 0x0040bytes to DRAM @ 0x0e44 from CPU @ maddr - - 008f 0081 0e44 lri $AR1, #0x0e44 // source - 0091 0082 0000 lri $AR2, #0x0000 // destination - - 0093 009b 009f lri $AX1.H, #0x009f - 0095 009a 0140 lri $AX0.H, #0x0140 // loop length if !ACC0 - - 0097 8100 clr $ACC0 - 0098 8900 clr $ACC1 - - 0099 8f00 set40 - - // 009a 02bf 055c call 0x055c - WaitDMA(); - - 009c 193e lrri $AC0.M, @$AR1 - 009d 193c lrri $AC0.L, @$AR1 - 009e b100 tst $ACC0 - 009f 193f lrri $AC1.M, @$AR1 // added to ACC0 in confusing ways - // 00a0 0294 00a6 jnz 0x00a6 - if (!$ACC0) { - 00a2 005a loop $AX0.H - 00a3 1b5e srri @$AR2, $AC0.M - - // 00a4 029f 00ae jmp 0x00ae - } else { - 00a6 9900 asr16 $ACC1 - 00a7 1b5e srri @$AR2, $AC0.M - 00a8 1b5c srri @$AR2, $AC0.L - 00a9 007b 00ad bloop $AX1.H, 0x00ad - 00ab 4c00 add $ACC0, $ACC1 - 00ac 1b5e srri @$AR2, $AC0.M - 00ad 1b5c srri @$AR2, $AC0.L - - } - - // same code block as above...epic fail? - 00ae 193e lrri $AC0.M, @$AR1 - 00af 193c lrri $AC0.L, @$AR1 - 00b0 b100 tst $ACC0 - 00b1 193f lrri $AC1.M, @$AR1 - // 00b2 0294 00b8 jnz 0x00b8 - if (!$ACC0) { - 00b4 005a loop $AX0.H - 00b5 1b5e srri @$AR2, $AC0.M - - // 00b6 029f 00c0 jmp 0x00c0 - } else { - 00b8 9900 asr16 $ACC1 - 00b9 1b5e srri @$AR2, $AC0.M - 00ba 1b5c srri @$AR2, $AC0.L - 00bb 007b 00bf bloop $AX1.H, 0x00bf - 00bd 4c00 add $ACC0, $ACC1 - 00be 1b5e srri @$AR2, $AC0.M - 00bf 1b5c srri @$AR2, $AC0.L - - } - - // ...and again! wtf - 00c0 193e lrri $AC0.M, @$AR1 - 00c1 193c lrri $AC0.L, @$AR1 - 00c2 b100 tst $ACC0 - 00c3 193f lrri $AC1.M, @$AR1 - // 00c4 0294 00ca jnz 0x00ca - if (!$ACC0) { - 00c6 005a loop $AX0.H - 00c7 1b5e srri @$AR2, $AC0.M - - // 00c8 029f 00d2 jmp 0x00d2 - } else { - 00ca 9900 asr16 $ACC1 - 00cb 1b5e srri @$AR2, $AC0.M - 00cc 1b5c srri @$AR2, $AC0.L - 00cd 007b 00d1 bloop $AX1.H, 0x00d1 - 00cf 4c00 add $ACC0, $ACC1 - 00d0 1b5e srri @$AR2, $AC0.M - 00d1 1b5c srri @$AR2, $AC0.L - - } - - // set to next buffer - 00d2 0082 0400 lri $AR2, #0x0400 - - // same code block, uses tst'l in one place...otherwise the same - 00d4 193e lrri $AC0.M, @$AR1 - 00d5 193c lrri $AC0.L, @$AR1 - 00d6 b179 tst'l $ACC0 : $AC1.M, @$AR1 - // 00d7 0294 00dd jnz 0x00dd - if (!$ACC0) { - 00d9 005a loop $AX0.H - 00da 1b5e srri @$AR2, $AC0.M - // 00db 029f 00e5 jmp 0x00e5 - } else { - 00dd 9900 asr16 $ACC1 - 00de 1b5e srri @$AR2, $AC0.M - 00df 1b5c srri @$AR2, $AC0.L - 00e0 007b 00e4 bloop $AX1.H, 0x00e4 - 00e2 4c00 add $ACC0, $ACC1 - 00e3 1b5e srri @$AR2, $AC0.M - 00e4 1b5c srri @$AR2, $AC0.L - } - - // same code block, using tst'l again...wonder if it actually changes behavior? - 00e5 193e lrri $AC0.M, @$AR1 - 00e6 193c lrri $AC0.L, @$AR1 - 00e7 b179 tst'l $ACC0 : $AC1.M, @$AR1 - // 00e8 0294 00ee jnz 0x00ee - if (!$ACC0) { - 00ea 005a loop $AX0.H - 00eb 1b5e srri @$AR2, $AC0.M - // 00ec 029f 00f6 jmp 0x00f6 - } else { - 00ee 9900 asr16 $ACC1 - 00ef 1b5e srri @$AR2, $AC0.M - 00f0 1b5c srri @$AR2, $AC0.L - 00f1 007b 00f5 bloop $AX1.H, 0x00f5 - 00f3 4c00 add $ACC0, $ACC1 - 00f4 1b5e srri @$AR2, $AC0.M - 00f5 1b5c srri @$AR2, $AC0.L - } - - // see comments above - 00f6 193e lrri $AC0.M, @$AR1 - 00f7 193c lrri $AC0.L, @$AR1 - 00f8 b179 tst'l $ACC0 : $AC1.M, @$AR1 - // 00f9 0294 00ff jnz 0x00ff - if (!$ACC0) { - 00fb 005a loop $AX0.H - 00fc 1b5e srri @$AR2, $AC0.M - // 00fd 029f 0107 jmp 0x0107 - } else { - 00ff 9900 asr16 $ACC1 - 0100 1b5e srri @$AR2, $AC0.M - 0101 1b5c srri @$AR2, $AC0.L - 0102 007b 0106 bloop $AX1.H, 0x0106 - 0104 4c00 add $ACC0, $ACC1 - 0105 1b5e srri @$AR2, $AC0.M - 0106 1b5c srri @$AR2, $AC0.L - } - - // set to next buffer - 0107 0082 07c0 lri $AR2, #0x07c0 - - // see comments above - 0109 193e lrri $AC0.M, @$AR1 - 010a 193c lrri $AC0.L, @$AR1 - 010b b179 tst'l $ACC0 : $AC1.M, @$AR1 - // 010c 0294 0112 jnz 0x0112 - if (!$ACC0) { - 010e 005a loop $AX0.H - 010f 1b5e srri @$AR2, $AC0.M - // 0110 029f 011a jmp 0x011a - } else { - 0112 9900 asr16 $ACC1 - 0113 1b5e srri @$AR2, $AC0.M - 0114 1b5c srri @$AR2, $AC0.L - 0115 007b 0119 bloop $AX1.H, 0x0119 - 0117 4c00 add $ACC0, $ACC1 - 0118 1b5e srri @$AR2, $AC0.M - 0119 1b5c srri @$AR2, $AC0.L - } - - // see comments above - 011a 193e lrri $AC0.M, @$AR1 - 011b 193c lrri $AC0.L, @$AR1 - 011c b179 tst'l $ACC0 : $AC1.M, @$AR1 - // 011d 0294 0123 jnz 0x0123 - if (!$ACC0) { - 011f 005a loop $AX0.H - 0120 1b5e srri @$AR2, $AC0.M - // 0121 029f 012b jmp 0x012b - } else { - 0123 9900 asr16 $ACC1 - 0124 1b5e srri @$AR2, $AC0.M - 0125 1b5c srri @$AR2, $AC0.L - 0126 007b 012a bloop $AX1.H, 0x012a - 0128 4c00 add $ACC0, $ACC1 - 0129 1b5e srri @$AR2, $AC0.M - 012a 1b5c srri @$AR2, $AC0.L - } - - // see comments above - 012b 193e lrri $AC0.M, @$AR1 - 012c 193c lrri $AC0.L, @$AR1 - 012d b179 tst'l $ACC0 : $AC1.M, @$AR1 - // 012e 0294 0134 jnz 0x0134 - if (!$ACC0) { - 0130 005a loop $AX0.H - 0131 1b5e srri @$AR2, $AC0.M - // 0132 029f 013c jmp 0x013c - } else { - 0134 9900 asr16 $ACC1 - 0135 1b5e srri @$AR2, $AC0.M - 0136 1b5c srri @$AR2, $AC0.L - 0137 007b 013b bloop $AX1.H, 0x013b - 0139 4c00 add $ACC0, $ACC1 - 013a 1b5e srri @$AR2, $AC0.M - 013b 1b5c srri @$AR2, $AC0.L - } - - // 013c 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void Cmd_1() { - 013e 0085 ffff lri $IX1, #0xffff // -1 - - // 0140 8150 clr'l $ACC0 : $AX0.H, @$AR0 - // 0141 8940 clr'l $ACC1 : $AX0.L, @$AR0 - // 0142 8e48 set16'l : $AX1.L, @$AR0 - // 0143 00fa 0e17 sr @0x0e17, $AX0.H - // 0145 00f8 0e18 sr @0x0e18, $AX0.L - // 0147 0081 0000 lri $AR1, #0x0000 - // 0149 02bf 04f1 call 0x04f1 - u16 maddrh = *(CmdBlockBuf++) - u16 maddrl = *(CmdBlockBuf++) - u16 unkForMulBuffer1 = *(CmdBlockBuf++) - u16 unkForMulBuffer2 = 0 // a buffer in dram - Unk(maddrh << 16 | maddrl, unkForMulBuffer1, unkForMulBuffer2) - - // 014b 00da 0e17 lr $AX0.H, @0x0e17 - // 014d 00d8 0e18 lr $AX0.L, @0x0e18 - // 014f 8948 clr'l $ACC1 : $AX1.L, @$AR0 - // 0150 0081 0400 lri $AR1, #0x0400 - // 0152 02bf 04f1 call 0x04f1 - unkForMulBuffer1 = *(CmdBlockBuf++) - unkForMulBuffer2 = 0x0400 - Unk(maddrh << 16 | maddrl, unkForMulBuffer1, unkForMulBuffer2) - - // 0154 00da 0e17 lr $AX0.H, @0x0e17 - // 0156 00d8 0e18 lr $AX0.L, @0x0e18 - // 0158 8948 clr'l $ACC1 : $AX1.L, @$AR0 - // 0159 0081 07c0 lri $AR1, #0x07c0 - // 015b 02bf 04f1 call 0x04f1 - unkForMulBuffer1 = *(CmdBlockBuf++) - unkForMulBuffer2 = 0x07c0 - Unk(maddrh << 16 | maddrl, unkForMulBuffer1, unkForMulBuffer2) - - // 015d 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void Cmd_9() { - 015f 0086 07c0 lri $IX2, #0x07c0 // often used buffer in dram - - 0161 02bf 0484 call 0x0484 - - // 0163 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void Cmd_6() { - 0165 8100 clr $ACC0 - 0166 8e00 set16 - - // 0167 191e lrri $AC0.M, @$AR0 - // 0168 191c lrri $AC0.L, @$AR0 - u16 maddrh = *(CmdBlockBuf++) - u16 maddrl = *(CmdBlockBuf++) - - // 0169 2ece srs @DSMAH, $AC0.M - // 016a 2ccf srs @DSMAL, $AC0.L - // 016b 16cd 0000 si @DSPA, #0x0000 - // 016d 16c9 0001 si @DSCR, #0x0001 - // 016f 16cb 0780 si @DSBL, #0x0780 - - // DMA 0x780bytes to CPU @ maddr from DMEM @ 0 - - // 0171 02bf 055c call 0x055c - WaitDMA(); - - // 0173 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void Cmd_11() { - // 0175 8100 clr $ACC0 - // 0176 8970 clr'l $ACC1 : $AC0.M, @$AR0 - // 0177 8e60 set16'l : $AC0.L, @$AR0 - u16 maddrh = *(CmdBlockBuf++) - u16 maddrl = *(CmdBlockBuf++) - - // 0178 2ece srs @DSMAH, $AC0.M - // 0179 2ccf srs @DSMAL, $AC0.L - // 017a 16cd 0e44 si @DSPA, #0x0e44 - // 017c 16c9 0000 si @DSCR, #0x0000 - // 017e 8900 clr $ACC1 - // 017f 0d20 lris $AC1.L, #0x20 - // 0180 2dcb srs @DSBL, $AC1.L - - // DMA 0x20bytes to DRAM @ 0x0e44 from CPU @ maddr - - u16 length_of_0e44 = 0x20 - - // 0181 4c00 add $ACC0, $ACC1 - maddr += length_of_0e44 - - // Save CmdBlockBuf - // 0182 1c80 mrr $IX0, $AR0 - - // 0183 0080 0280 lri $AR0, #0x0280 - // 0185 0081 0000 lri $AR1, #0x0000 - // 0187 0082 0140 lri $AR2, #0x0140 - // 0189 0083 0e44 lri $AR3, #0x0e44 - // 018b 0a00 lris $AX0.H, #0x00 - - // 018c 27c9 lrs $AC1.M, @DSCR - // 018d 03a0 0004 andf $AC1.M, #0x0004 - // 018f 029c 018c jlnz 0x018c - while (@DSCR & 4); - - // 0191 2ece srs @DSMAH, $AC0.M - // 0192 2ccf srs @DSMAL, $AC0.L - // 0193 16cd 0e54 si @DSPA, #0x0e54 - // 0195 16c9 0000 si @DSCR, #0x0000 - // 0197 16cb 0260 si @DSBL, #0x0260 - - // DMA 0x0260bytes to DRAM @ 0x0e54 from CPU @ maddr - - // 0199 009f 00a0 lri $AC1.M, #0x00a0 - // 019b 8f00 set40 - // 019c 007f 01a5 bloop $AC1.M, 0x01a5 - // 019e 197e lrri $AC0.M, @$AR3 - // 019f 1b1a srri @$AR0, $AX0.H - // 01a0 197c lrri $AC0.L, @$AR3 - // 01a1 1b1a srri @$AR0, $AX0.H - // 01a2 1b5e srri @$AR2, $AC0.M - // 01a3 7c22 neg's $ACC0 : @$AR2, $AC0.L - // 01a4 1b3e srri @$AR1, $AC0.M - // 01a5 1b3c srri @$AR1, $AC0.L - - // high reg will only be sign bits, and it's never stored, so we can use s32 here - s32* buffer_source = 0x0e44 - s32* buffer_dest = 0x0140 - s32* buffer_to_zero = 0x0280 - s32* buffer_dest_neg = 0x0000 - for (i = 0x00a0; i > 0; i--) { - s32 thing = *(buffer_source++) - *(buffer_to_zero++) = 0 - *(buffer_dest++) = thing - *(buffer_dest_neg++) = ~thing - } - - // Restore CmdBlockBuf - 01a6 1c04 mrr $AR0, $IX0 - - // 01a7 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -// Interesting, DMAs in new CmdBlock and starts executing it -void Cmd_D() { - // 01a9 8e70 set16'l : $AC0.M, @$AR0 - // 01aa 8960 clr'l $ACC1 : $AC0.L, @$AR0 - u16 maddrh = *(CmdBlockBuf++) - u16 maddrl = *(CmdBlockBuf++) - - // 01ab 191f lrri $AC1.M, @$AR0 - u16 numbytes = *(CmdBlockBuf++) - - // 01ac 2ece srs @DSMAH, $AC0.M - // 01ad 2ccf srs @DSMAL, $AC0.L - // 01ae 16cd 0c00 si @DSPA, #0x0c00 - // 01b0 16c9 0000 si @DSCR, #0x0000 - // 01b2 0503 addis $AC1.M, #0x03 - // 01b3 0340 fff0 andi $AC1.M, #0xfff0 - // 01b5 2fcb srs @DSBL, $AC1.M - - // DMA ((numbytes + 3) & 0xfff0)bytes to DMEM @ 0x0c00 from CPU @ maddr - - // 01b6 02bf 055c call 0x055c - WaitDMA(); - - // 01b8 0080 0c00 lri $AR0, #0x0c00 - CmdBlockBuf = 0x0c00 - - // 01ba 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -// DMAs in a new PB and inits values (itd, func pointers, etc) -// DMAs in new update_block, but doesn't apply it -void Cmd_2() { - 01bc 8100 clr $ACC0 - - // 01bd 8970 clr'l $ACC1 : $AC0.M, @$AR0 - // 01be 8e78 set16'l : $AC1.M, @$AR0 - u16 maddrh = *(CmdBlockBuf++) - u16 maddrl = *(CmdBlockBuf++) - - // 01bf 2ece srs @DSMAH, $AC0.M - // 01c0 2fcf srs @DSMAL, $AC1.M - // 01c1 16cd 0b80 si @DSPA, #0x0b80 - // 01c3 16c9 0000 si @DSCR, #0x0000 - // 01c5 16cb 00c0 si @DSBL, #0x00c0 - - // DMA 0x00c0bytes to DMEM @ 0x0b80 from CPU @ maddr - - // 01c7 0082 0e08 lri $AR2, #0x0e08 - // 01c9 009f 0000 lri $AC1.M, #0x0000 - // 01cb 1b5f srri @$AR2, $AC1.M - // 01cc 009f 0140 lri $AC1.M, #0x0140 - // 01ce 1b5f srri @$AR2, $AC1.M - // 01cf 009f 0280 lri $AC1.M, #0x0280 - // 01d1 1b5f srri @$AR2, $AC1.M - // 01d2 009f 0400 lri $AC1.M, #0x0400 - // 01d4 1b5f srri @$AR2, $AC1.M - // 01d5 009f 0540 lri $AC1.M, #0x0540 - // 01d7 1b5f srri @$AR2, $AC1.M - // 01d8 009f 0680 lri $AC1.M, #0x0680 - // 01da 1b5f srri @$AR2, $AC1.M - // 01db 009f 07c0 lri $AC1.M, #0x07c0 - // 01dd 1b5f srri @$AR2, $AC1.M - // 01de 009f 0900 lri $AC1.M, #0x0900 - // 01e0 1b5f srri @$AR2, $AC1.M - // 01e1 009f 0a40 lri $AC1.M, #0x0a40 - // 01e3 1b5f srri @$AR2, $AC1.M - *0x0e08 = 0x0000 - *0x0e09 = 0x0140 - *0x0e0a = 0x0280 - *0x0e0b = 0x0400 - *0x0e0c = 0x0540 - *0x0e0d = 0x0680 - *0x0e0e = 0x07c0 - *0x0e0f = 0x0900 - *0x0e10 = 0x0a40 - - // 01e4 02bf 055c call 0x055c - WaitDMA(); - - // 01e6 00de 0ba7 lr $AC0.M, @0x0ba7 - // 01e8 00df 0ba8 lr $AC1.M, @0x0ba8 - // 01ea 2ece srs @DSMAH, $AC0.M - // 01eb 2fcf srs @DSMAL, $AC1.M - // 01ec 16cd 03c0 si @DSPA, #0x03c0 - // 01ee 16c9 0000 si @DSCR, #0x0000 - // 01f0 16cb 0080 si @DSBL, #0x0080 - - // DMA 0x80bytes from CPU @ ((pb.update.dataHi << 16) | pb.update.dataLo) to DRAM @ 0x03c0 - - // 01f2 8100 clr $ACC0 - // 01f3 8900 clr $ACC1 - - // 01f4 00de 0b84 lr $AC0.M, @0x0b84 - // 01f6 009f 0b31 lri $AC1.M, #0x0b31 - // 01f8 4c00 add $ACC0, $ACC1 - // 01f9 1c7e mrr $AR3, $AC0.M - // 01fa 0213 ilrr $AC0.M, @$AR3 - // 01fb 00fe 0e15 sr @0x0e15, $AC0.M - *0x0e15 = *(0x0b31 + pb.srcSelect) // func ptr for src - - // 01fd 00de 0b85 lr $AC0.M, @0x0b85 - // 01ff 009f 0b34 lri $AC1.M, #0x0b34 - // 0201 4c00 add $ACC0, $ACC1 - // 0202 1c7e mrr $AR3, $AC0.M - // 0203 0213 ilrr $AC0.M, @$AR3 - // 0204 00fe 0e16 sr @0x0e16, $AC0.M - *0x0e16 = *(0x0b34 + pb.coefSelect) // ptr to coef table - - // 0206 00de 0b86 lr $AC0.M, @0x0b86 - // 0208 009f 0b11 lri $AC1.M, #0x0b11 - // 020a 4c00 add $ACC0, $ACC1 - // 020b 1c7e mrr $AR3, $AC0.M - // 020c 0213 ilrr $AC0.M, @$AR3 - // 020d 00fe 0e14 sr @0x0e14, $AC0.M - *0x0e14 = *(0x0b11 + pb.mixerCtrl) // func ptr for mixer - - // 020f 8100 clr $ACC0 - // 0210 00de 0b9b lr $AC0.M, @0x0b9b - // 0212 b100 tst $ACC0 - // 0213 0295 023a jz 0x023a - if (pb.itd.flag != AX_PB_ITD_OFF) { - // 0215 8900 clr $ACC1 - // 0216 00df 0b9e lr $AC1.M, @0x0b9e - // 0218 0300 0cc0 addi $AC1.M, #0x0cc0 - // 021a 00ff 0e40 sr @0x0e40, $AC1.M - *0x0e40 = 0x0cc0 + pb.itd.shiftL - - // 021c 00df 0b9f lr $AC1.M, @0x0b9f - // 021e 0300 0cc0 addi $AC1.M, #0x0cc0 - // 0220 00ff 0e41 sr @0x0e41, $AC1.M - *0x0e41 = 0x0cc0 + pb.itd.shiftR - - // 0222 009f 0ce0 lri $AC1.M, #0x0ce0 - // 0224 00ff 0e42 sr @0x0e42, $AC1.M - // 0226 00ff 0e43 sr @0x0e43, $AC1.M - *0x0e42 = 0x0ce0 - *0x0e43 = 0x0ce0 - - // 0228 02bf 055c call 0x055c - WaitDMA(); - - // 022a 00de 0b9c lr $AC0.M, @0x0b9c - // 022c 2ece srs @DSMAH, $AC0.M - // 022d 00de 0b9d lr $AC0.M, @0x0b9d - // 022f 2ecf srs @DSMAL, $AC0.M - // 0230 16cd 0cc0 si @DSPA, #0x0cc0 - // 0232 16c9 0000 si @DSCR, #0x0000 - // 0234 16cb 0040 si @DSBL, #0x0040 - - // DMA 0x0040bytes to DMEM @ 0x0cc0 from CPU @ (pb.itd.bufferHi << 16) | pb.itd.bufferLo - - // 0236 02bf 055c call 0x055c - WaitDMA(); - - // 0238 029f 0068 jmp 0x0068 - goto DoNextCommand; - - } else { - - // 023a 009f 0ce0 lri $AC1.M, #0x0ce0 - // 023c 00ff 0e42 sr @0x0e42, $AC1.M - // 023e 00ff 0e40 sr @0x0e40, $AC1.M - // 0240 00ff 0e41 sr @0x0e41, $AC1.M - // 0242 00ff 0e43 sr @0x0e43, $AC1.M - *0x0e42 = 0x0ce0 - *0x0e40 = 0x0ce0 - *0x0e41 = 0x0ce0 - *0x0e43 = 0x0ce0 - - // 0244 02bf 055c call 0x055c - WaitDMA(); - - // 0246 029f 0068 jmp 0x0068 - goto DoNextCommand; - } -} - -// Function calls itself until there are no more linked PBs -void Cmd_3() { - 0248 8e00 set16 - - // Save CmdBlockBuf ptr - 0249 00e0 0e07 sr @0x0e07, $AR0 - - // Processes pb.update.updNum[0] to pb.update.updNum[5] - // Applies specified number of updates for every millisecond of voice frame (5 millisecs) - // first millisec's updates are ignored <- not proven, yet - - // 024b 0080 0ba2 lri $AR0, #0x0ba2 // pb.update.updNum[0] - // 024d 0081 03c0 lri $AR1, #0x03c0 - // 024f 0e05 lris $AC0.M, #0x05 - // 0250 00fe 0e04 sr @0x0e04, $AC0.M // counter to decrement - // 0252 8900 clr $ACC1 - u16* pUpdates_this_ms = 0x0ba2 - u16* pUpdate_block = 0x03c0 - u16 ms_remaining = 5 - -NextMillisecUpd: - // 0253 8150 clr'l $ACC0 : $AX0.H, @$AR0 - // 0254 009f 0b80 lri $AC1.M, #0x0b80 - // 0256 007a 025b bloop $AX0.H, 0x025b - // 0258 193e lrri $AC0.M, @$AR1 - // 0259 4c49 add'l $ACC0, $ACC1 : $AX1.L, @$AR1 - // 025a 1c5e mrr $AR2, $AC0.M - // 025b 1a59 srr @$AR2, $AX1.L // AR2 isn't changed till updates are done - - // Write updates from update_block to pb in dram - for (int i = 0; i < *pUpdates_this_ms; i+=2) { - // Looks like 0x03c0 is a struct of pairs to write into PB - *(0x0b80 + *(pUpdate_block + i)) = *(pUpdate_block + i + 1) - } - pUpdates_this_ms++ - - // 025c 0083 0e05 lri $AR3, #0x0e05 - // 025e 1b61 srri @$AR3, $AR1 - // 025f 1b60 srri @$AR3, $AR0 - *0x0e05 = pUpdate_block - *0x0e06 = pUpdates_this_ms - // They are restored before jmping back to NextMillisecUpd - - // 0260 00de 0b87 lr $AC0.M, @0x0b87 - // 0262 0601 cmpis $AC0.M, #0x01 - // 0263 0295 0267 jz 0x0267 - // 0265 029f 0332 jmp 0x0332 - if (pb.state == AX_PB_STATE_RUN) { - - // 0267 00de 0e42 lr $AC0.M, @0x0e42 - // 0269 00fe 0e1c sr @0x0e1c, $AC0.M - *0x0e1c = *0x0e42 - - // 026b 00c3 0e15 lr $AR3, @0x0e15 - // 026d 177f callr $AR3 - DoSelectedSRC() - - // Volume Envelope Processing - // 026e 8e00 set16 - // 026f 8a00 m2 - // 0270 8100 clr $ACC0 - // 0271 8900 clr $ACC1 - // 0272 00de 0bb3 lr $AC0.M, @0x0bb3 // currentDelta (s16) - // 0274 00df 0bb2 lr $AC1.M, @0x0bb2 // currentVolume (u16) - // 0276 1f1f mrr $AX0.L, $AC1.M - // 0277 4d00 add $ACC1, $ACC0 - // 0278 1481 asl $ACC0, #1 - // 0279 8d1e set15'mv : $AX1.H, $AC0.M // unsigned mulx, - // 027a 1fd8 mrr $AC0.M, $AX0.L - // 027b 0098 8000 lri $AX0.L, #0x8000 - // 027d 0080 0e44 lri $AR0, #0x0e44 - // 027f a830 mulx's $AX0.L, $AX1.H : @$AR0, $AC0.M - // 0280 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0281 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 0282 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0283 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 0284 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0285 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 0286 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0287 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 0288 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0289 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 028a ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 028b ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 028c ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 028d ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 028e ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 028f ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 0290 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0291 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 0292 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0293 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 0294 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0295 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 0296 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0297 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 0298 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 0299 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 029a ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 029b ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 029c ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 029d ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M - // 029e ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M - // 029f 00fe 0bb2 sr @0x0bb2, $AC0.M - - u40 temp1 = pb.ve.currentVolume << 16 - u40 temp2 = (pb.ve.currentVolume + pb.ve.currentDelta) << 16 - *0x0e44 = temp1 >> 16 - *0x0e45 = temp2 >> 16 - - u40 PROD = (u16)0x8000 * (u16)(pb.ve.currentDelta << 1) * 2 - for (u16* i = 0x0e46; i < 0x0e46 + 30; i+=2) { - temp1 += PROD - temp2 += PROD - - *i = temp1 >> 16 - *(i + 1) = temp2 >> 16 - } - temp1 += PROD - pb.ve.currentVolume = temp1 >> 16 - - // 02a1 8f00 set40 - // 02a2 0080 0e44 lri $AR0, #0x0e44 - // 02a4 00c1 0e43 lr $AR1, @0x0e43 - // 02a6 1c61 mrr $AR3, $AR1 - // 02a7 193a lrri $AX0.H, @$AR1 - // 02a8 1918 lrri $AX0.L, @$AR0 - // 02a9 9059 mul'l $AX0.L, $AX0.H : $AX1.H, @$AR1 - // 02aa 1919 lrri $AX1.L, @$AR0 - // 02ab 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02ac 8080 nx'ls : $AX0.L, $AC0.M - // 02ad 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02ae 8091 nx'ls : $AX1.L, $AC1.M - // 02af 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02b0 8080 nx'ls : $AX0.L, $AC0.M - // 02b1 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02b2 8091 nx'ls : $AX1.L, $AC1.M - // 02b3 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02b4 8080 nx'ls : $AX0.L, $AC0.M - // 02b5 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02b6 8091 nx'ls : $AX1.L, $AC1.M - // 02b7 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02b8 8080 nx'ls : $AX0.L, $AC0.M - // 02b9 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02ba 8091 nx'ls : $AX1.L, $AC1.M - // 02bb 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02bc 8080 nx'ls : $AX0.L, $AC0.M - // 02bd 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02be 8091 nx'ls : $AX1.L, $AC1.M - // 02bf 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02c0 8080 nx'ls : $AX0.L, $AC0.M - // 02c1 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02c2 8091 nx'ls : $AX1.L, $AC1.M - // 02c3 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02c4 8080 nx'ls : $AX0.L, $AC0.M - // 02c5 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02c6 8091 nx'ls : $AX1.L, $AC1.M - // 02c7 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02c8 8080 nx'ls : $AX0.L, $AC0.M - // 02c9 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02ca 8091 nx'ls : $AX1.L, $AC1.M - // 02cb 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02cc 8080 nx'ls : $AX0.L, $AC0.M - // 02cd 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02ce 8091 nx'ls : $AX1.L, $AC1.M - // 02cf 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02d0 8080 nx'ls : $AX0.L, $AC0.M - // 02d1 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02d2 8091 nx'ls : $AX1.L, $AC1.M - // 02d3 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02d4 8080 nx'ls : $AX0.L, $AC0.M - // 02d5 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02d6 8091 nx'ls : $AX1.L, $AC1.M - // 02d7 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02d8 8080 nx'ls : $AX0.L, $AC0.M - // 02d9 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02da 8091 nx'ls : $AX1.L, $AC1.M - // 02db 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02dc 8080 nx'ls : $AX0.L, $AC0.M - // 02dd 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02de 8091 nx'ls : $AX1.L, $AC1.M - // 02df 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02e0 8080 nx'ls : $AX0.L, $AC0.M - // 02e1 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02e2 8091 nx'ls : $AX1.L, $AC1.M - // 02e3 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 - // 02e4 8080 nx'ls : $AX0.L, $AC0.M - // 02e5 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 - // 02e6 8091 nx'ls : $AX1.L, $AC1.M - // 02e7 9e00 mulmv $AX1.L, $AX1.H, $ACC0 - // 02e8 6f33 movp's $ACC1 : @$AR3, $AC0.M - // 02e9 1b7f srri @$AR3, $AC1.M - - u16* dst = *0x0e43 - u16* temp1 = 0x0e44 - - for (x = 0; x < 0x20; x++) { - *(dst + x) = ((u16)*(temp1 + x) * (u16)*(dst + x) * 2) >> 16 - } - - // 02ea 00c3 0e14 lr $AR3, @0x0e14 - // 02ec 8f00 set40 - // 02ed 8d00 set15 - // 02ee 8a00 m2 - // 02ef 177f callr $AR3 - // Keep in mind: 40bit, unsigned, *2 - DoSelectedMixer() - - // Note: 40bit, unsigned, *2 not changed till 0x0332 - - // 02f0 8100 clr $ACC0 - // 02f1 00de 0b9b lr $AC0.M, @0x0b9b - // 02f3 b100 tst $ACC0 - // 02f4 0295 032a jz 0x032a - if (pb.itd.flag != AX_PB_ITD_OFF) { - // 02f6 00de 0e42 lr $AC0.M, @0x0e42 - // 02f8 00fe 0e43 sr @0x0e43, $AC0.M - *0x0e43 = *0x0e42 - - // 02fa 8100 clr $ACC0 - // 02fb 8900 clr $ACC1 - // 02fc 00de 0b9e lr $AC0.M, @0x0b9e - // 02fe 00df 0ba0 lr $AC1.M, @0x0ba0 - // 0300 8200 cmp - // 0301 0293 0306 jle 0x0306 - if (pb.itd.shiftL > pb.itd.targetShiftL) { - // 0303 7800 decm $AC0.M - // 0304 029f 0309 jmp 0x0309 - pb.itd.shiftL-- - } else if (pb.itd.shiftL < pb.itd.targetShiftL) { - // 0306 0295 0309 jz 0x0309 - // 0308 7400 incm $AC0.M - pb.itd.shiftL++ - } - // 0309 00fe 0b9e sr @0x0b9e, $AC0.M // Store pb.itd.shiftL - - // 030b 00df 0e43 lr $AC1.M, @0x0e43 - // 030d 05e0 addis $AC1.M, #0xe0 - // 030e 4c00 add $ACC0, $ACC1 - // 030f 00fe 0e40 sr @0x0e40, $AC0.M - *0x0e40 = *0x0e43 - 32 - - // 0311 8100 clr $ACC0 - // 0312 8900 clr $ACC1 - // 0313 00de 0b9f lr $AC0.M, @0x0b9f - // 0315 00df 0ba1 lr $AC1.M, @0x0ba1 - // 0317 8200 cmp - // 0318 0293 031d jle 0x031d - if (pb.itd.shiftR > pb.itd.targetShiftR) { - // 031a 7800 decm $AC0.M - // 031b 029f 0320 jmp 0x0320 - pb.itd.shiftR-- - } else if (pb.itd.shiftR < pb.itd.targetShiftR) { - // 031d 0295 0320 jz 0x0320 - // 031f 7400 incm $AC0.M - pb.itd.shiftR++ - } - // 0320 00fe 0b9f sr @0x0b9f, $AC0.M // Store pb.itd.shiftR - - // 0322 00df 0e43 lr $AC1.M, @0x0e43 - // 0324 05e0 addis $AC1.M, #0xe0 - // 0325 4c00 add $ACC0, $ACC1 - // 0326 00fe 0e41 sr @0x0e41, $AC0.M - *0x0e41 = *0x0e43 - 32 - - 0328 029f 0332 jmp 0x0332 - - } else { // pb.itd.flag == AX_PB_ITD_OFF - - // 032a 00de 0e42 lr $AC0.M, @0x0e42 - // 032c 00fe 0e40 sr @0x0e40, $AC0.M - // 032e 00fe 0e41 sr @0x0e41, $AC0.M - // 0330 00fe 0e43 sr @0x0e43, $AC0.M - *0x0e40 = *0x0e42 - *0x0e41 = *0x0e42 - *0x0e43 = *0x0e42 - } - } - - - // 0332 8100 clr $ACC0 - // 0333 8e00 set16 - // 0334 8400 clrp - // 0335 8900 clr $ACC1 - // 0336 1efe mrr $PROD.M2, $AC0.M - // 0337 0e40 lris $AC0.M, #0x40 - // 0338 1ebe mrr $PROD.M1, $AC0.M - // 0339 0083 0e08 lri $AR3, #0x0e08 - // 033b 1c03 mrr $AR0, $AR3 - // 033c 1ff5 mrr $AC1.M, $PROD.M1 - // 033d 191a lrri $AX0.H, @$AR0 - // 033e f858 addpaxz'l $ACC0, $AX0.H : $AX1.H, @$AR0 - // 033f fba0 addpaxz'ls $ACC1, $AX1.H : $AX0.H, $AC0.M - // 0340 f8b1 addpaxz'ls $ACC0, $AX0.H : $AX1.H, $AC1.M - // 0341 fba0 addpaxz'ls $ACC1, $AX1.H : $AX0.H, $AC0.M - // 0342 f8b1 addpaxz'ls $ACC0, $AX0.H : $AX1.H, $AC1.M - // 0343 fba0 addpaxz'ls $ACC1, $AX1.H : $AX0.H, $AC0.M - // 0344 f8b1 addpaxz'ls $ACC0, $AX0.H : $AX1.H, $AC1.M - // 0345 fba0 addpaxz'ls $ACC1, $AX1.H : $AX0.H, $AC0.M - // 0346 f83b addpaxz's $ACC0, $AX0.H : @$AR3, $AC1.M - // 0347 1b7e srri @$AR3, $AC0.M - - for (u16* i = 0x0e08; i <= 0x0e10; i++) { - *i = (u16)( (0xff00400000 + (u40)(*i << 16)) >> 16 ) - } - - // 0348 0083 0e04 lri $AR3, #0x0e04 - // 034a 8100 clr $ACC0 - // 034b 8973 clr'l $ACC1 : $AC0.M, @$AR3 - // 034c 1961 lrri $AR1, @$AR3 // 0x0e05 - // 034d 1960 lrri $AR0, @$AR3 // 0x0e06 - // 034e 7800 decm $AC0.M - // 034f 00fe 0e04 sr @0x0e04, $AC0.M - // 0351 0294 0253 jnz 0x0253 - ms_remaining-- - if (ms_remaining) - goto NextMillisecUpd - - // 0353 8e00 set16 - // 0354 8100 clr $ACC0 - // 0355 00de 0b9b lr $AC0.M, @0x0b9b - // 0357 b100 tst $ACC0 - // 0358 0295 036a jz 0x036a - if (pb.itd.flag != AX_PB_ITD_OFF) { - - // 035a 00de 0b9c lr $AC0.M, @0x0b9c - // 035c 00dc 0b9d lr $AC0.L, @0x0b9d - // 035e 2ece srs @DSMAH, $AC0.M - // 035f 2ccf srs @DSMAL, $AC0.L - // 0360 8100 clr $ACC0 - // 0361 00de 0e1c lr $AC0.M, @0x0e1c - // 0363 2ecd srs @DSPA, $AC0.M - // 0364 16c9 0001 si @DSCR, #0x0001 - // 0366 16cb 0040 si @DSBL, #0x0040 - - // DMA 0x40bytes from DRAM @ (*0x0e1c) to CPU @ ((pb.itd.bufferHi << 16) | pb.itd.bufferLo) - - // 0368 02bf 055c call 0x055c - WaitDMA(); - } - - // 036a 8100 clr $ACC0 - // 036b 8900 clr $ACC1 - // 036c 00de 0b82 lr $AC0.M, @0x0b82 - // 036e 00df 0b83 lr $AC1.M, @0x0b83 - u16 maddrh = pb.currHi - u16 maddrl = pb.currLo - - // This writes back the whole PB to mram from dsp - // 0370 2ece srs @DSMAH, $AC0.M - // 0371 2fcf srs @DSMAL, $AC1.M - // 0372 16cd 0b80 si @DSPA, #0x0b80 - // 0374 16c9 0001 si @DSCR, #0x0001 - // 0376 16cb 00c0 si @DSBL, #0x00c0 - - // DMA 0xc0bytes from DRAM @ 0x0b80 to CPU @ maddr - - // 0378 02bf 055c call 0x055c - WaitDMA(); - - // 037a 8100 clr $ACC0 - // 037b 00de 0b80 lr $AC0.M, @0x0b80 - // 037d 00dc 0b81 lr $AC0.L, @0x0b81 - // 037f b100 tst $ACC0 - // 0380 0294 0386 jnz 0x0386 - if (((pb.nextHi << 16) | pb.nextLo) == 0) { - // No more PBs! - - // Restore CmdBlockBuf ptr - 0382 00c0 0e07 lr $AR0, @0x0e07 - // 0384 029f 0068 jmp 0x0068 - goto DoNextCommand; - } - - // DMA in the next PB - // From here on out, it's the same as Cmd2, except it calls itself to process the PB it just loaded - - // 0386 2ece srs @DSMAH, $AC0.M - // 0387 2ccf srs @DSMAL, $AC0.L - // 0388 16cd 0b80 si @DSPA, #0x0b80 - // 038a 16c9 0000 si @DSCR, #0x0000 - // 038c 16cb 00c0 si @DSBL, #0x00c0 - - // DMA 0xc0bytes from CPU @ ((pb.nextHi << 16) | pb.nextLo) to DRAM @ 0x0b80 - - // 038e 0082 0e08 lri $AR2, #0x0e08 - // 0390 009f 0000 lri $AC1.M, #0x0000 - // 0392 1b5f srri @$AR2, $AC1.M - // 0393 009f 0140 lri $AC1.M, #0x0140 - // 0395 1b5f srri @$AR2, $AC1.M - // 0396 009f 0280 lri $AC1.M, #0x0280 - // 0398 1b5f srri @$AR2, $AC1.M - // 0399 009f 0400 lri $AC1.M, #0x0400 - // 039b 1b5f srri @$AR2, $AC1.M - // 039c 009f 0540 lri $AC1.M, #0x0540 - // 039e 1b5f srri @$AR2, $AC1.M - // 039f 009f 0680 lri $AC1.M, #0x0680 - // 03a1 1b5f srri @$AR2, $AC1.M - // 03a2 009f 07c0 lri $AC1.M, #0x07c0 - // 03a4 1b5f srri @$AR2, $AC1.M - // 03a5 009f 0900 lri $AC1.M, #0x0900 - // 03a7 1b5f srri @$AR2, $AC1.M - // 03a8 009f 0a40 lri $AC1.M, #0x0a40 - // 03aa 1b5f srri @$AR2, $AC1.M - *0x0e08 = 0x0000 - *0x0e09 = 0x0140 - *0x0e0a = 0x0280 - *0x0e0b = 0x0400 - *0x0e0c = 0x0540 - *0x0e0d = 0x0680 - *0x0e0e = 0x07c0 - *0x0e0f = 0x0900 - *0x0e10 = 0x0a40 - - // 03ab 02bf 055c call 0x055c - WaitDMA(); - - // 03ad 00de 0ba7 lr $AC0.M, @0x0ba7 - // 03af 00df 0ba8 lr $AC1.M, @0x0ba8 - // 03b1 2ece srs @DSMAH, $AC0.M - // 03b2 2fcf srs @DSMAL, $AC1.M - // 03b3 16cd 03c0 si @DSPA, #0x03c0 - // 03b5 16c9 0000 si @DSCR, #0x0000 - // 03b7 16cb 0080 si @DSBL, #0x0080 - - // DMA 0x80bytes from CPU @ ((pb.update.dataHi << 16) | pb.update.dataLo) to DRAM @ 0x03c0 - - // 03b9 8100 clr $ACC0 - // 03ba 8900 clr $ACC1 - - // 03bb 00de 0b84 lr $AC0.M, @0x0b84 - // 03bd 009f 0b31 lri $AC1.M, #0x0b31 - // 03bf 4c00 add $ACC0, $ACC1 - // 03c0 1c7e mrr $AR3, $AC0.M - // 03c1 0213 ilrr $AC0.M, @$AR3 - // 03c2 00fe 0e15 sr @0x0e15, $AC0.M - *0x0e15 = *(0x0b31 + pb.srcSelect) // func ptr for src - - // 03c4 00de 0b85 lr $AC0.M, @0x0b85 - // 03c6 009f 0b34 lri $AC1.M, #0x0b34 - // 03c8 4c00 add $ACC0, $ACC1 - // 03c9 1c7e mrr $AR3, $AC0.M - // 03ca 0213 ilrr $AC0.M, @$AR3 - // 03cb 00fe 0e16 sr @0x0e16, $AC0.M - *0x0e16 = *(0x0b34 + pb.coefSelect) // ptr to coef table - - // 03cd 00de 0b86 lr $AC0.M, @0x0b86 - // 03cf 009f 0b11 lri $AC1.M, #0x0b11 - // 03d1 4c00 add $ACC0, $ACC1 - // 03d2 1c7e mrr $AR3, $AC0.M - // 03d3 0213 ilrr $AC0.M, @$AR3 - // 03d4 00fe 0e14 sr @0x0e14, $AC0.M - *0x0e14 = *(0x0b11 + pb.mixerCtrl) // func ptr for mixer - - // 03d6 8100 clr $ACC0 - // 03d7 00de 0b9b lr $AC0.M, @0x0b9b - // 03d9 b100 tst $ACC0 - // 03da 0295 0403 jz 0x0403 - if (pb.itd.flag != AX_PB_ITD_OFF) { - // 03dc 8900 clr $ACC1 - // 03dd 00df 0b9e lr $AC1.M, @0x0b9e - // 03df 0300 0cc0 addi $AC1.M, #0x0cc0 - // 03e1 00ff 0e40 sr @0x0e40, $AC1.M - *0x0e40 = 0x0cc0 + pb.itd.shiftL - - // 03e3 00df 0b9f lr $AC1.M, @0x0b9f - // 03e5 0300 0cc0 addi $AC1.M, #0x0cc0 - // 03e7 00ff 0e41 sr @0x0e41, $AC1.M - *0x0e41 = 0x0cc0 + pb.itd.shiftR - - // 03e9 009f 0ce0 lri $AC1.M, #0x0ce0 - // 03eb 00ff 0e42 sr @0x0e42, $AC1.M - // 03ed 00ff 0e43 sr @0x0e43, $AC1.M - *0x0e42 = 0x0ce0 - *0x0e43 = 0x0ce0 - - // 03ef 02bf 055c call 0x055c - WaitDMA(); - - // 03f1 00de 0b9c lr $AC0.M, @0x0b9c - // 03f3 2ece srs @DSMAH, $AC0.M - // 03f4 00de 0b9d lr $AC0.M, @0x0b9d - // 03f6 2ecf srs @DSMAL, $AC0.M - // 03f7 16cd 0cc0 si @DSPA, #0x0cc0 - // 03f9 16c9 0000 si @DSCR, #0x0000 - // 03fb 16cb 0040 si @DSBL, #0x0040 - - // DMA 0x0040bytes to DMEM @ 0x0cc0 from CPU @ (pb.itd.bufferHi << 16) | pb.itd.bufferLo - - // 03fd 02bf 055c call 0x055c - WaitDMA(); - - // Restore CmdBlockBuf ptr - 03ff 00c0 0e07 lr $AR0, @0x0e07 - // 0401 029f 0248 jmp 0x0248 - goto Cmd_3() // Calls itself till there are no more PBs linked - - } else { - - // 0403 009f 0ce0 lri $AC1.M, #0x0ce0 - // 0405 00ff 0e42 sr @0x0e42, $AC1.M - // 0407 00ff 0e40 sr @0x0e40, $AC1.M - // 0409 00ff 0e41 sr @0x0e41, $AC1.M - // 040b 00ff 0e43 sr @0x0e43, $AC1.M - *0x0e42 = 0x0ce0 - *0x0e40 = 0x0ce0 - *0x0e41 = 0x0ce0 - *0x0e43 = 0x0ce0 - - // 040d 02bf 055c call 0x055c - WaitDMA(); - - // Restore CmdBlockBuf ptr - 040f 00c0 0e07 lr $AR0, @0x0e07 - // 0411 029f 0248 jmp 0x0248 - goto Cmd_3() // Calls itself till there are no more PBs linked - } -} - -void Cmd_4() { - 0413 8e00 set16 - - 0414 0086 0400 lri $IX2, #0x0400 // buffer in dram - - // 0416 8100 clr $ACC0 - // 0417 8970 clr'l $ACC1 : $AC0.M, @$AR0 - // 0418 191c lrri $AC0.L, @$AR0 - u16 maddrh = *(CmdBlockBuf++) - u16 maddrl = *(CmdBlockBuf++) - - // 0419 2ece srs @DSMAH, $AC0.M - // 041a 2ccf srs @DSMAL, $AC0.L - // 041b 1fc6 mrr $AC0.M, $IX2 - // 041c 2ecd srs @DSPA, $AC0.M - // 041d 16c9 0001 si @DSCR, #0x0001 - // 041f 16cb 0780 si @DSBL, #0x0780 - - // DMA 0x0780bytes from DRAM @ 0x0400 to CPU @ maddr - - // 0421 02bf 055c call 0x055c - WaitDMA(); - - 0423 02bf 0484 call 0x0484 - - // 0425 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void Cmd_5() { - 0427 8e00 set16 - - 0428 0086 07c0 lri $IX2, #0x07c0 - - 042a 8100 clr $ACC0 - 042b 8970 clr'l $ACC1 : $AC0.M, @$AR0 - 042c 191c lrri $AC0.L, @$AR0 - 042d 2ece srs @DSMAH, $AC0.M - 042e 2ccf srs @DSMAL, $AC0.L - 042f 1fc6 mrr $AC0.M, $IX2 - 0430 2ecd srs @DSPA, $AC0.M - 0431 16c9 0001 si @DSCR, #0x0001 - 0433 16cb 0780 si @DSBL, #0x0780 - - // 0435 02bf 055c call 0x055c - WaitDMA(); - - 0437 02bf 0484 call 0x0484 - - // 0439 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void Cmd_E() { - 043b 8c00 clr15 - 043c 8a00 m2 - 043d 8100 clr $ACC0 - 043e 8970 clr'l $ACC1 : $AC0.M, @$AR0 - 043f 191f lrri $AC1.M, @$AR0 - 0440 2ece srs @DSMAH, $AC0.M - 0441 2fcf srs @DSMAL, $AC1.M - 0442 16cd 0280 si @DSPA, #0x0280 - 0444 16c9 0001 si @DSCR, #0x0001 // DMEM -> CPU - 0446 16cb 0280 si @DSBL, #0x0280 - - 0448 8f50 set40'l : $AX0.H, @$AR0 - 0449 8140 clr'l $ACC0 : $AX0.L, @$AR0 - 044a 0081 0400 lri $AR1, #0x0400 - 044c 0083 0000 lri $AR3, #0x0000 - 044e 0082 0140 lri $AR2, #0x0140 - 0450 0099 0080 lri $AX1.L, #0x0080 - - // 0452 02bf 055c call 0x055c - WaitDMA(); - - 0454 1105 046c bloopi #0x05, 0x046c - 0456 1f61 mrr $AX1.H, $AR1 - - 0457 1120 045e bloopi #0x20, 0x045e - 0459 8972 clr'l $ACC1 : $AC0.M, @$AR2 - 045a 195c lrri $AC0.L, @$AR2 - 045b f07b lsl16'l $ACC0 : $AC1.M, @$AR3 - 045c 197d lrri $AC1.L, @$AR3 - 045d f131 lsl16's $ACC1 : @$AR1, $AC0.M - 045e 8139 clr's $ACC0 : @$AR1, $AC1.M - - 045f 8900 clr $ACC1 - 0460 6800 movax $ACC0, $AX0 - 0461 2ece srs @DSMAH, $AC0.M - 0462 2ccf srs @DSMAL, $AC0.L - 0463 1ffb mrr $AC1.M, $AX1.H - 0464 2fcd srs @DSPA, $AC1.M - 0465 0f01 lris $AC1.M, #0x01 - 0466 2fc9 srs @DSCR, $AC1.M - 0467 1ff9 mrr $AC1.M, $AX1.L - 0468 2fcb srs @DSBL, $AC1.M - 0469 7200 addaxl $ACC0, $AX1.L - 046a 1f5e mrr $AX0.H, $AC0.M - 046b 1f1c mrr $AX0.L, $AC0.L - 046c 8100 clr $ACC0 - - // 046d 26c9 lrs $AC0.M, @DSCR - // 046e 02a0 0004 andf $AC0.M, #0x0004 - // 0470 029c 046d jlnz 0x046d - while (@DSCR & 4); - - // 0472 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void UnimplimentedCmd_B() { - // 0474 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void UnimplimentedCmd_C() { - // 0476 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void UnimplimentedCmd_A() { - // 0478 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void Task_Yield() { - // Send DSP_YIELD mail - // 047a 16fc dcd1 si @DMBH, #0xdcd1 - // 047c 16fd 0002 si @DMBL, #0x0002 - DMB = 0xdcd10002 - // 047e 16fb 0001 si @DIRQ, #0x0001 - - 0480 029f 0c91 jmp 0x0c91 -} - - // Unused? - // 0482 029f 0045 jmp 0x0045 - goto GetNextCmdBlock; - -// Called by cmds 4 5 9 -// IX2 is always modified before calling... -void UnkFunc() { - 0484 8e00 set16 - 0485 191f lrri $AC1.M, @$AR0 - 0486 191d lrri $AC1.L, @$AR0 - 0487 1f5f mrr $AX0.H, $AC1.M - 0488 1f1d mrr $AX0.L, $AC1.L - 0489 2fce srs @DSMAH, $AC1.M - 048a 2dcf srs @DSMAL, $AC1.L - 048b 8900 clr $ACC1 - 048c 1fa6 mrr $AC1.L, $IX2 - 048d 2dcd srs @DSPA, $AC1.L - 048e 0e00 lris $AC0.M, #0x00 - 048f 2ec9 srs @DSCR, $AC0.M - 0490 8100 clr $ACC0 - 0491 009c 00c0 lri $AC0.L, #0x00c0 - 0493 2ccb srs @DSBL, $AC0.L - 0494 1ca0 mrr $IX1, $AR0 - 0495 0081 0e44 lri $AR1, #0x0e44 - 0497 4800 addax $ACC0, $AX0 - 0498 1b3e srri @$AR1, $AC0.M - 0499 1b3c srri @$AR1, $AC0.L - 049a 0b00 lris $AX1.H, #0x00 - 049b 0099 0060 lri $AX1.L, #0x0060 - 049d 4b00 addax $ACC1, $AX1 - 049e 1b3d srri @$AR1, $AC1.L - 049f 0081 0e44 lri $AR1, #0x0e44 - 04a1 1c06 mrr $AR0, $IX2 - 04a2 0083 0000 lri $AR3, #0x0000 - 04a4 1c43 mrr $AR2, $AR3 - - 04a5 27c9 lrs $AC1.M, @DSCR - 04a6 03a0 0004 andf $AC1.M, #0x0004 - 04a8 029c 04a5 jlnz 0x04a5 - - 04aa 1109 04da bloopi #0x09, 0x04da - 04ac 8e00 set16 - 04ad 193a lrri $AX0.H, @$AR1 - 04ae 1938 lrri $AX0.L, @$AR1 - 04af 6900 movax $ACC1, $AX0 - 04b0 2fce srs @DSMAH, $AC1.M - 04b1 2dcf srs @DSMAL, $AC1.L - 04b2 8900 clr $ACC1 - 04b3 193d lrri $AC1.L, @$AR1 - 04b4 2dcd srs @DSPA, $AC1.L - 04b5 16c9 0000 si @DSCR, #0x0000 - 04b7 8100 clr $ACC0 - 04b8 009c 00c0 lri $AC0.L, #0x00c0 - 04ba 2ccb srs @DSBL, $AC0.L - 04bb 0081 0e44 lri $AR1, #0x0e44 - 04bd 4800 addax $ACC0, $AX0 - 04be 1b3e srri @$AR1, $AC0.M - 04bf 1b3c srri @$AR1, $AC0.L - 04c0 0b00 lris $AX1.H, #0x00 - 04c1 0960 lris $AX1.L, #0x60 - 04c2 4b00 addax $ACC1, $AX1 - 04c3 1b3d srri @$AR1, $AC1.L - 04c4 0081 0e44 lri $AR1, #0x0e44 - 04c6 8f00 set40 - 04c7 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 04c8 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 04c9 6a00 movax $ACC0, $AX1 - 04ca 4800 addax $ACC0, $AX0 - 04cb 1117 04d4 bloopi #0x17, 0x04d4 - 04cd 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 04ce 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 04cf 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M - 04d0 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L - 04d1 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 04d2 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 04d3 6a3a movax's $ACC0, $AX1.L : @$AR2, $AC1.M - 04d4 482a addax's $ACC0, $AX0.L : @$AR2, $AC1.L - 04d5 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 04d6 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 04d7 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M - 04d8 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L - 04d9 1b5f srri @$AR2, $AC1.M - 04da 1b5d srri @$AR2, $AC1.L - - 04db 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 04dc 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 04dd 6a00 movax $ACC0, $AX1 - 04de 4800 addax $ACC0, $AX0 - - 04df 1117 04e8 bloopi #0x17, 0x04e8 - 04e1 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 04e2 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 04e3 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M - 04e4 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L - 04e5 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 04e6 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 04e7 6a3a movax's $ACC0, $AX1.L : @$AR2, $AC1.M - 04e8 482a addax's $ACC0, $AX0.L : @$AR2, $AC1.L - - 04e9 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 04ea 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 04eb 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M - 04ec 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L - 04ed 1b5f srri @$AR2, $AC1.M - 04ee 1b5d srri @$AR2, $AC1.L - 04ef 1c05 mrr $AR0, $IX1 - 04f0 02df ret -} - -// Only called by Command 1 -// AX0 = maddr -// AX1.L = unkForMulBuffer1 -// AR1 = unkForMulBuffer2 -void Unk(maddr, unkForMulBuffer1, unkForMulBuffer2) { - 04f1 8e00 set16 - - // 04f2 009b 0e44 lri $AX1.H, #0x0e44 - // 04f4 009d 00c0 lri $AC1.L, #0x00c0 - // 04f6 02bf 0541 call 0x0541 - u16 daddr = 0x0e44 - const u16 dma_len = 0x00c0 - DMA_CPUToDMEM(maddr, daddr, dma_len); - - // 04f8 4900 addax $ACC1, $AX0 - // 04f9 00ff 0e1d sr @0x0e1d, $AC1.M - // 04fb 00fd 0e1e sr @0x0e1e, $AC1.L - // 04fd 8900 clr $ACC1 - maddr += dma_len - - // 04fe 02bf 055c call 0x055c - WaitDMA(); - - // 0500 1104 052c bloopi #0x04, 0x052c - for (u8 i = 0; i < 4; i++) { - // 0502 00da 0e1d lr $AX0.H, @0x0e1d // restore - // 0504 00d8 0e1e lr $AX0.L, @0x0e1e // restore - // 0506 009b 0ea4 lri $AX1.H, #0x0ea4 // buffer 2 - // 0508 009d 00c0 lri $AC1.L, #0x00c0 // restore - // 050a 02bf 0541 call 0x0541 - daddr = 0x0ea4 - DMA_CPUToDMEM(maddr, daddr, dma_len); - - // 050c 4900 addax $ACC1, $AX0 - // 050d 00ff 0e1d sr @0x0e1d, $AC1.M // update - // 050f 00fd 0e1e sr @0x0e1e, $AC1.L - maddr += dma_len - - // 0511 0083 0e44 lri $AR3, #0x0e44 - // 0513 02bf 054c call 0x054c - UnknownMulBuffer(0x0e44); - - // 0515 8900 clr $ACC1 - // 0516 00da 0e1d lr $AX0.H, @0x0e1d // restore - // 0518 00d8 0e1e lr $AX0.L, @0x0e1e // restore - // 051a 009b 0e44 lri $AX1.H, #0x0e44 // buffer 1 - // 051c 009d 00c0 lri $AC1.L, #0x00c0 // restore - // 051e 02bf 0541 call 0x0541 - daddr = 0x0e44 - DMA_CPUToDMEM(maddr, daddr, dma_len); - - // 0520 4900 addax $ACC1, $AX0 - // 0521 00ff 0e1d sr @0x0e1d, $AC1.M // update - // 0523 00fd 0e1e sr @0x0e1e, $AC1.L - maddr += dma_len - - // 0525 0083 0ea4 lri $AR3, #0x0ea4 // buffer 2 - // 0527 02bf 054c call 0x054c - UnknownMulBuffer(0x0ea4); - - // 0529 0000 nop - // 052a 0000 nop - // 052b 8e00 set16 // restore - // 052c 8900 clr $ACC1 - } - - // 052d 00da 0e1d lr $AX0.H, @0x0e1d // restore - // 052f 00d8 0e1e lr $AX0.L, @0x0e1e // restore - // 0531 009b 0ea4 lri $AX1.H, #0x0ea4 // buffer 2 - // 0533 009d 00c0 lri $AC1.L, #0x00c0 // restore - // 0535 02bf 0541 call 0x0541 - DMA_CPUToDMEM(maddr, daddr, dma_len); - - // 0537 4900 addax $ACC1, $AX0 - maddr += dma_len - - // 0538 0083 0e44 lri $AR3, #0x0e44 // buffer 1 - // 053a 02bf 054c call 0x054c - UnknownMulBuffer(0x0e44); - - // 053c 0083 0ea4 lri $AR3, #0x0ea4 // buffer 2 - // 053e 02bf 054c call 0x054c - UnknownMulBuffer(0x0ea4); - - 0540 02df ret -} - -// u32 maddr = AX0 -// u16 daddr = AX1.H -// u16 len = AC1.L -// Only transfers from CPU -> DMEM -void DMA_CPUToDMEM() { - 0541 8e00 set16 - 0542 00fa ffce sr @DSMAH, $AX0.H - 0544 00f8 ffcf sr @DSMAL, $AX0.L - 0546 00fb ffcd sr @DSPA, $AX1.H - 0548 16c9 0000 si @DSCR, #0x0000 - 054a 2dcb srs @DSBL, $AC1.L - 054b 02df ret -} - -// IX1 = 0xffff -// AX1.L = unkForMulBuffer1 (next value in cmd block) -// AR1 = unkForMulBuffer2 (0, 0x0400, then 0x07c0) -// AR3 is some buffer, either 0x0e44 or 0x0ea4 -void UnknownMulBuffer() { - 054c 8f00 set40 // Loaded ACx.M values extend to the entire ACC - 054d 8d00 set15 // multiplicands unsigned - 054e 8a00 m2 // mul results doubled - - // 054f 197a lrri $AX0.H, @$AR3 - // 0550 1978 lrri $AX0.L, @$AR3 - AX0.H = *(AR3++) - AX0.L = *(AR3++) - - // 0551 a000 mulx $AX0.L, $AX1.L - // 0552 b600 mulxmv $AX0.H, $AX1.L, $ACC0 - ACC0 = (u16)AX0.L * (u16)unkForMulBuffer1 * 2 - PROD = (u16)AX0.H * (u16)unkForMulBuffer1 * 2 - - // 0553 1130 055a bloopi #0x30, 0x055a - for (int i=0; i<48; i++) { - // 0555 9179 asr16'l $ACC0 : $AC1.M, @$AR1 - ACC0 >>= 16 - AC1.M = *(unkForMulBuffer2++) - - // 0556 4e6d addp'ln $ACC0 : $AC1.L, @$AR1 - ACC0 += PROD - AC1.L = *unkForMulBuffer2 - unkForMulBuffer2 -= 1 - - // 0557 197a lrri $AX0.H, @$AR3 - AX0.H = *(AR3++) - - // 0558 4d43 add'l $ACC1, $ACC0 : $AX0.L, @$AR3 - ACC1 += ACC0 - AX0.L = *(AR3++) - - // 0559 a039 mulx's $AX0.L, $AX1.L : @$AR1, $AC1.M - // 055a b629 mulxmv's $AX0.H, $AX1.L, $ACC0 : @$AR1, $AC1.L - ACC0 = (u16)AX0.L * (u16)unkForMulBuffer1 * 2 - *(unkForMulBuffer2++) = AC1.M - PROD = (u16)AX0.H * (u16)unkForMulBuffer1 * 2 - *(unkForMulBuffer2++) = AC1.L - } - - 055b 02df ret -} - -void WaitDMA() { - // 055c 26c9 lrs $AC0.M, @DSCR - // 055d 02a0 0004 andf $AC0.M, #0x0004 - // 055f 029c 055c jlnz 0x055c - while (@DSCR & 4); - - // 0561 02df ret - return; -} - -// All apparently unused? -void WaitForCPUMailbox() { - 0562 26fe lrs $AC0.M, @CMBH - 0563 02c0 8000 andcf $AC0.M, #0x8000 - 0565 029c 0562 jlnz 0x0562 - 0567 02df ret -} -void WaitForDSPMailbox1() { - 0568 26fc lrs $AC0.M, @DMBH - 0569 02a0 8000 andf $AC0.M, #0x8000 - 056b 029c 0568 jlnz 0x0568 - 056d 02df ret -} -void WaitForDSPMailbox2() { - 056e 26fc lrs $AC0.M, @DMBH - 056f 02a0 8000 andf $AC0.M, #0x8000 - 0571 029c 056e jlnz 0x056e - 0573 02df ret -} - -void Cmd_7() { - // 0574 8100 clr $ACC0 - // 0575 8970 clr'l $ACC1 : $AC0.M, @$AR0 - // 0576 8e60 set16'l : $AC0.L, @$AR0 - u16 maddrh = *(CmdBlockBuf++) - u16 maddrl = *(CmdBlockBuf++) - - // 0577 2ece srs @DSMAH, $AC0.M - // 0578 2ccf srs @DSMAL, $AC0.L - // 0579 16cd 0e44 si @DSPA, #0x0e44 - // 057b 16c9 0000 si @DSCR, #0x0000 - // 057d 8900 clr $ACC1 - // 057e 0d20 lris $AC1.L, #0x20 - u16 dma_len = 32 - - // 057f 2dcb srs @DSBL, $AC1.L - // DMA 32bytes from CPU @ maddr -> DMEM @ 0x0e44 - - // 0580 4c00 add $ACC0, $ACC1 - maddr += dma_len - - // Push CmdBlockBuf ptr - 0581 1c80 mrr $IX0, $AR0 - - // 0582 0080 0280 lri $AR0, #0x0280 - // 0584 0081 0000 lri $AR1, #0x0000 - // 0586 0082 0140 lri $AR2, #0x0140 - // 0588 0083 0e44 lri $AR3, #0x0e44 - u16* unk_buf1 = 0x0280 - u16* unk_buf2 = 0x0000 - u16* unk_buf3 = 0x0140 - u16* dmem_buf = 0x0e44 - - // 058a 0a00 lris $AX0.H, #0x00 - const u16 null = 0 // Guess is that it's faster to use AXx instead of imm value? - - // 058b 27c9 lrs $AC1.M, @DSCR - // 058c 03a0 0004 andf $AC1.M, #0x0004 - // 058e 029c 058b jlnz 0x058b - while (@DSCR & 4); // Wait for DMA completion - - // 0590 2ece srs @DSMAH, $AC0.M - // 0591 2ccf srs @DSMAL, $AC0.L - // 0592 16cd 0e54 si @DSPA, #0x0e54 - // 0594 16c9 0000 si @DSCR, #0x0000 - // 0596 16cb 0260 si @DSBL, #0x0260 - - // DMA 0x0260bytes from CPU @ maddr -> DMEM @ 0x0e54 - // No waiting for DMA - - // 0598 009f 00a0 lri $AC1.M, #0x00a0 - u16 size = 0x00a0 - - // accum loads in the loop are 40bit - // 059a 8f00 set40 - - // 059b 007f 05a4 bloop $AC1.M, 0x05a4 - for (int i = 0; i < size; i++) { - // !!! Doesn't make sense with current understanding of set40 - 059d 197e lrri $AC0.M, @$AR3 - 059e 1b1a srri @$AR0, $AX0.H - 059f 197c lrri $AC0.L, @$AR3 - 05a0 1b1a srri @$AR0, $AX0.H - 05a1 1b5e srri @$AR2, $AC0.M - 05a2 1b5c srri @$AR2, $AC0.L - 05a3 1b3e srri @$AR1, $AC0.M - 05a4 1b3c srri @$AR1, $AC0.L - } - - // Pop CmdBlockBuf ptr - 05a5 1c04 mrr $AR0, $IX0 - - // 05a6 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -# Following 3 funcs are the SRCs to select from, in order - -void SRC_Polyphase() { - // Copy pb's data [pb.addr.format to pb.adpm.yn2] to corresponding hw regs - // 05a8 0082 0bb8 lri $AR2, #0x0bb8 - // 05aa 195e lrri $AC0.M, @$AR2 - // 05ab 2ed1 srs @SampleFormat, $AC0.M - // 05ac 195e lrri $AC0.M, @$AR2 - // 05ad 2ed4 srs @ACSAH, $AC0.M - // 05ae 195e lrri $AC0.M, @$AR2 - // 05af 2ed5 srs @ACSAL, $AC0.M - // 05b0 195e lrri $AC0.M, @$AR2 - // 05b1 2ed6 srs @ACEAH, $AC0.M - // 05b2 195e lrri $AC0.M, @$AR2 - // 05b3 2ed7 srs @ACEAL, $AC0.M - // 05b4 195e lrri $AC0.M, @$AR2 - // 05b5 2ed8 srs @ACCAH, $AC0.M - // 05b6 195e lrri $AC0.M, @$AR2 - // 05b7 2ed9 srs @ACCAL, $AC0.M - // 05b8 195e lrri $AC0.M, @$AR2 - // 05b9 2ea0 srs @COEF_A1_0, $AC0.M - // 05ba 195e lrri $AC0.M, @$AR2 - // 05bb 2ea1 srs @COEF_A2_0, $AC0.M - // 05bc 195e lrri $AC0.M, @$AR2 - // 05bd 2ea2 srs @COEF_A1_1, $AC0.M - // 05be 195e lrri $AC0.M, @$AR2 - // 05bf 2ea3 srs @COEF_A2_1, $AC0.M - // 05c0 195e lrri $AC0.M, @$AR2 - // 05c1 2ea4 srs @COEF_A1_2, $AC0.M - // 05c2 195e lrri $AC0.M, @$AR2 - // 05c3 2ea5 srs @COEF_A2_2, $AC0.M - // 05c4 195e lrri $AC0.M, @$AR2 - // 05c5 2ea6 srs @COEF_A1_3, $AC0.M - // 05c6 195e lrri $AC0.M, @$AR2 - // 05c7 2ea7 srs @COEF_A2_3, $AC0.M - // 05c8 195e lrri $AC0.M, @$AR2 - // 05c9 2ea8 srs @COEF_A1_4, $AC0.M - // 05ca 195e lrri $AC0.M, @$AR2 - // 05cb 2ea9 srs @COEF_A2_4, $AC0.M - // 05cc 195e lrri $AC0.M, @$AR2 - // 05cd 2eaa srs @COEF_A1_5, $AC0.M - // 05ce 195e lrri $AC0.M, @$AR2 - // 05cf 2eab srs @COEF_A2_5, $AC0.M - // 05d0 195e lrri $AC0.M, @$AR2 - // 05d1 2eac srs @COEF_A1_6, $AC0.M - // 05d2 195e lrri $AC0.M, @$AR2 - // 05d3 2ead srs @COEF_A2_6, $AC0.M - // 05d4 195e lrri $AC0.M, @$AR2 - // 05d5 2eae srs @COEF_A1_7, $AC0.M - // 05d6 195e lrri $AC0.M, @$AR2 - // 05d7 2eaf srs @COEF_A2_7, $AC0.M - // 05d8 195e lrri $AC0.M, @$AR2 - // 05d9 2ede srs @GAIN, $AC0.M - // 05da 195e lrri $AC0.M, @$AR2 - // 05db 2eda srs @scale, $AC0.M - // 05dc 195e lrri $AC0.M, @$AR2 - // 05dd 2edb srs @yn1, $AC0.M - // 05de 195e lrri $AC0.M, @$AR2 - // 05df 2edc srs @yn2, $AC0.M - - 05e0 8c00 clr15 - 05e1 8a00 m2 - 05e2 8e00 set16 - 05e3 00d8 0e16 lr $AX0.L, @0x0e16 - 05e5 195b lrri $AX1.H, @$AR2 - 05e6 1959 lrri $AX1.L, @$AR2 - 05e7 8100 clr $ACC0 - 05e8 195c lrri $AC0.L, @$AR2 - 05e9 0080 0e44 lri $AR0, #0x0e44 - 05eb 195f lrri $AC1.M, @$AR2 - 05ec 1b1f srri @$AR0, $AC1.M - 05ed 195f lrri $AC1.M, @$AR2 - 05ee 1b1f srri @$AR0, $AC1.M - 05ef 195f lrri $AC1.M, @$AR2 - 05f0 1b1f srri @$AR0, $AC1.M - 05f1 185f lrr $AC1.M, @$AR2 - 05f2 1b1f srri @$AR0, $AC1.M - 05f3 6b00 movax $ACC1, $AX1 - 05f4 1505 lsl $ACC1, #5 - 05f5 4d00 add $ACC1, $ACC0 - 05f6 157e lsr $ACC1, #-2 - 05f7 1c9f mrr $IX0, $AC1.M - 05f8 1cbd mrr $IX1, $AC1.L - 05f9 05e0 addis $AC1.M, #0xe0 - 05fa 9900 asr16 $ACC1 - 05fb 7d00 neg $ACC1 - 05fc 1cdd mrr $IX2, $AC1.L - 05fd 8900 clr $ACC1 - 05fe 1fa5 mrr $AC1.L, $IX1 - 05ff 1502 lsl $ACC1, #2 - 0600 1cbf mrr $IX1, $AC1.M - 0601 009a 01fc lri $AX0.H, #0x01fc - 0603 009e 0e44 lri $AC0.M, #0x0e44 - 0605 0081 ffdd lri $AR1, #0xffdd - 0607 0083 0d80 lri $AR3, #0x0d80 - 0609 0064 061a bloop $IX0, 0x061a - 060b 1827 lrr $IX3, @$AR1 - 060c 1b07 srri @$AR0, $IX3 - 060d 4a00 addax $ACC0, $AX1 - 060e 1ffc mrr $AC1.M, $AC0.L - 060f 1827 lrr $IX3, @$AR1 - 0610 1b07 srri @$AR0, $IX3 - 0611 1579 lsr $ACC1, #-7 - 0612 3500 andr $AC1.M, $AX0.H - 0613 1827 lrr $IX3, @$AR1 - 0614 1b07 srri @$AR0, $IX3 - 0615 4100 addr $ACC1, $AX0.L - 0616 1b7e srri @$AR3, $AC0.M - 0617 1827 lrr $IX3, @$AR1 - 0618 1b07 srri @$AR0, $IX3 - 0619 1b7f srri @$AR3, $AC1.M - 061a 0000 nop - - 061b 0065 0620 bloop $IX1, 0x0620 - 061d 1827 lrr $IX3, @$AR1 - 061e 1b07 srri @$AR0, $IX3 - 061f 0000 nop - 0620 0000 nop - - 0621 0007 dar $AR3 - 0622 187f lrr $AC1.M, @$AR3 - 0623 0066 0629 bloop $IX2, 0x0629 - 0625 4a3b addax's $ACC0, $AX1.L : @$AR3, $AC1.M - 0626 1ffc mrr $AC1.M, $AC0.L - 0627 1579 lsr $ACC1, #-7 - 0628 3533 andr's $AC1.M, $AX0.H : @$AR3, $AC0.M - 0629 4100 addr $ACC1, $AX0.L - - 062a 1b7f srri @$AR3, $AC1.M - 062b 0004 dar $AR0 - 062c 189f lrrd $AC1.M, @$AR0 - 062d 1adf srrd @$AR2, $AC1.M - 062e 189f lrrd $AC1.M, @$AR0 - 062f 1adf srrd @$AR2, $AC1.M - 0630 189f lrrd $AC1.M, @$AR0 - 0631 1adf srrd @$AR2, $AC1.M - 0632 189f lrrd $AC1.M, @$AR0 - 0633 1adf srrd @$AR2, $AC1.M - 0634 1adc srrd @$AR2, $AC0.L - 0635 0082 0bd2 lri $AR2, #0x0bd2 - 0637 27dc lrs $AC1.M, @yn2 - 0638 1adf srrd @$AR2, $AC1.M - 0639 27db lrs $AC1.M, @yn1 - 063a 1adf srrd @$AR2, $AC1.M - 063b 27da lrs $AC1.M, @scale - 063c 1adf srrd @$AR2, $AC1.M - 063d 0082 0bbe lri $AR2, #0x0bbe - 063f 27d9 lrs $AC1.M, @ACCAL - 0640 1adf srrd @$AR2, $AC1.M - 0641 27d8 lrs $AC1.M, @ACCAH - 0642 1adf srrd @$AR2, $AC1.M - 0643 8f00 set40 - 0644 00c1 0e42 lr $AR1, @0x0e42 - 0646 0082 0d80 lri $AR2, #0x0d80 - 0648 1940 lrri $AR0, @$AR2 - 0649 1943 lrri $AR3, @$AR2 - 064a 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 064b b8c0 mulx'ld $AX0.H, $AX1.H : $AX0.L, $AX1.L, @$AR0 - 064c 111f 0654 bloopi #0x1f, 0x0654 - 064e a6f0 mulxmv'ld $AX0.L, $AX1.L, $ACC0 : $AX0.H, $AX1.H, @$AR0 - 064f bcf0 mulxac'ld $AX0.H, $AX1.H, $ACC0 : $AX0.H, $AX1.H, @$AR0 - 0650 1940 lrri $AR0, @$AR2 - 0651 1943 lrri $AR3, @$AR2 - 0652 bcf0 mulxac'ld $AX0.H, $AX1.H, $ACC0 : $AX0.H, $AX1.H, @$AR0 - 0653 4ec0 addp'ld $ACC0 : $AX0.L, $AX1.L, @$AR0 - 0654 b831 mulx's $AX0.H, $AX1.H : @$AR1, $AC0.M - - 0655 a6f0 mulxmv'ld $AX0.L, $AX1.L, $ACC0 : $AX0.H, $AX1.H, @$AR0 - 0656 bcf0 mulxac'ld $AX0.H, $AX1.H, $ACC0 : $AX0.H, $AX1.H, @$AR0 - 0657 bc00 mulxac $AX0.H, $AX1.H, $ACC0 - 0658 4e00 addp $ACC0 - 0659 1b3e srri @$AR1, $AC0.M - 065a 00e1 0e42 sr @0x0e42, $AR1 - - 065c 02df ret -} - -void SRC_Linear() { - // Copy pb's data [pb.addr.format to pb.adpm.yn2] to corresponding hw regs - // 065d 0082 0bb8 lri $AR2, #0x0bb8 - // 065f 195e lrri $AC0.M, @$AR2 - // 0660 2ed1 srs @SampleFormat, $AC0.M - // 0661 195e lrri $AC0.M, @$AR2 - // 0662 2ed4 srs @ACSAH, $AC0.M - // 0663 195e lrri $AC0.M, @$AR2 - // 0664 2ed5 srs @ACSAL, $AC0.M - // 0665 195e lrri $AC0.M, @$AR2 - // 0666 2ed6 srs @ACEAH, $AC0.M - // 0667 195e lrri $AC0.M, @$AR2 - // 0668 2ed7 srs @ACEAL, $AC0.M - // 0669 195e lrri $AC0.M, @$AR2 - // 066a 2ed8 srs @ACCAH, $AC0.M - // 066b 195e lrri $AC0.M, @$AR2 - // 066c 2ed9 srs @ACCAL, $AC0.M - // 066d 195e lrri $AC0.M, @$AR2 - // 066e 2ea0 srs @COEF_A1_0, $AC0.M - // 066f 195e lrri $AC0.M, @$AR2 - // 0670 2ea1 srs @COEF_A2_0, $AC0.M - // 0671 195e lrri $AC0.M, @$AR2 - // 0672 2ea2 srs @COEF_A1_1, $AC0.M - // 0673 195e lrri $AC0.M, @$AR2 - // 0674 2ea3 srs @COEF_A2_1, $AC0.M - // 0675 195e lrri $AC0.M, @$AR2 - // 0676 2ea4 srs @COEF_A1_2, $AC0.M - // 0677 195e lrri $AC0.M, @$AR2 - // 0678 2ea5 srs @COEF_A2_2, $AC0.M - // 0679 195e lrri $AC0.M, @$AR2 - // 067a 2ea6 srs @COEF_A1_3, $AC0.M - // 067b 195e lrri $AC0.M, @$AR2 - // 067c 2ea7 srs @COEF_A2_3, $AC0.M - // 067d 195e lrri $AC0.M, @$AR2 - // 067e 2ea8 srs @COEF_A1_4, $AC0.M - // 067f 195e lrri $AC0.M, @$AR2 - // 0680 2ea9 srs @COEF_A2_4, $AC0.M - // 0681 195e lrri $AC0.M, @$AR2 - // 0682 2eaa srs @COEF_A1_5, $AC0.M - // 0683 195e lrri $AC0.M, @$AR2 - // 0684 2eab srs @COEF_A2_5, $AC0.M - // 0685 195e lrri $AC0.M, @$AR2 - // 0686 2eac srs @COEF_A1_6, $AC0.M - // 0687 195e lrri $AC0.M, @$AR2 - // 0688 2ead srs @COEF_A2_6, $AC0.M - // 0689 195e lrri $AC0.M, @$AR2 - // 068a 2eae srs @COEF_A1_7, $AC0.M - // 068b 195e lrri $AC0.M, @$AR2 - // 068c 2eaf srs @COEF_A2_7, $AC0.M - // 068d 195e lrri $AC0.M, @$AR2 - // 068e 2ede srs @GAIN, $AC0.M - // 068f 195e lrri $AC0.M, @$AR2 - // 0690 2eda srs @scale, $AC0.M - // 0691 195e lrri $AC0.M, @$AR2 - // 0692 2edb srs @yn1, $AC0.M - // 0693 195e lrri $AC0.M, @$AR2 - // 0694 2edc srs @yn2, $AC0.M - - // 0695 8c00 clr15 // signed mulx - // 0696 8a00 m2 // *2 - // 0697 8e00 set16 // no sign extend - - // 0698 195b lrri $AX1.H, @$AR2 - // 0699 1959 lrri $AX1.L, @$AR2 - // 069a 8100 clr $ACC0 - // 069b 195c lrri $AC0.L, @$AR2 - // 069c 0080 0e44 lri $AR0, #0x0e44 - // 069e 195f lrri $AC1.M, @$AR2 - // 069f 195f lrri $AC1.M, @$AR2 - // 06a0 195f lrri $AC1.M, @$AR2 - // 06a1 1b1f srri @$AR0, $AC1.M - AR0 = 0x0e44 - AX1.H = pb.src.ratioHi - AX1.L = pb.src.ratioLo - AC0.L = pb.src.currentAddressFrac - AC1.M = pb.src.last_samples[2] - - *0x0e44 = pb.src.last_samples[2] - *0x0e45 = pb.src.last_samples[3] - - // 06a2 185f lrr $AC1.M, @$AR2 - // 06a3 1b1f srri @$AR0, $AC1.M - // 06a4 6b00 movax $ACC1, $AX1 - // 06a5 1505 lsl $ACC1, #5 - // 06a6 4d00 add $ACC1, $ACC0 - // 06a7 157e lsr $ACC1, #-2 - // 06a8 1c9f mrr $IX0, $AC1.M - // 06a9 1cbd mrr $IX1, $AC1.L - ACC1 = (pb.src.currentAddressFrac + (pb.src.ratio << 5)) >> 2 - IX0 = ACC1 >> 16 - IX1 = ((ACC1 & 0xffff) & 0xc000) >> 14 - IX2 = ~((ACC1 >> 16) - 32) - AX0.H = 0x01fc - AC0.M = 0x0e45 - AR1 = 0xffdd // DSP_ACCELERATOR - AR3 = 0x0d80 - - // 06aa 05e0 addis $AC1.M, #0xe0 - // 06ab 9900 asr16 $ACC1 - // 06ac 7d00 neg $ACC1 - // 06ad 1cdd mrr $IX2, $AC1.L - // 06ae 8900 clr $ACC1 - // 06af 1fa5 mrr $AC1.L, $IX1 - // 06b0 1502 lsl $ACC1, #2 - // 06b1 1cbf mrr $IX1, $AC1.M - // 06b2 009a 01fc lri $AX0.H, #0x01fc - // 06b4 009e 0e45 lri $AC0.M, #0x0e45 - // 06b6 0081 ffdd lri $AR1, #0xffdd - // 06b8 0083 0d80 lri $AR3, #0x0d80 - // 06ba 0064 06cb bloop $IX0, 0x06cb - // 06bc 1827 lrr $IX3, @$AR1 - // 06bd 1b07 srri @$AR0, $IX3 - // 06be 4a00 addax $ACC0, $AX1 - // 06bf 1b7e srri @$AR3, $AC0.M - // 06c0 1827 lrr $IX3, @$AR1 - // 06c1 1b07 srri @$AR0, $IX3 - // 06c2 1b7c srri @$AR3, $AC0.L - // 06c3 0000 nop - // 06c4 1827 lrr $IX3, @$AR1 - // 06c5 1b07 srri @$AR0, $IX3 - // 06c6 0000 nop - // 06c7 0000 nop - // 06c8 1827 lrr $IX3, @$AR1 - // 06c9 1b07 srri @$AR0, $IX3 - // 06ca 0000 nop - // 06cb 0000 nop - ACCO = (0x0e45 << 16) + pb.src.currentAddressFrac - for (i = 0; i < IX0; i++) { - ACC0 += pb.src.ratio - *(0x0d80++) = ACC0 >> 16 - *(0x0d80++) = ACC0 & 0xffff - *(0x0e46++) = *DSP_ACCELERATOR - *(0x0e46++) = *DSP_ACCELERATOR - *(0x0e46++) = *DSP_ACCELERATOR - *(0x0e46++) = *DSP_ACCELERATOR - } - - // 06cc 0065 06d1 bloop $IX1, 0x06d1 - // 06ce 1827 lrr $IX3, @$AR1 - // 06cf 1b07 srri @$AR0, $IX3 - // 06d0 0000 nop - // 06d1 0000 nop - for (i = 0; i < IX1; i++) { - *(0x0e46++) = *DSP_ACCELERATOR - } - - // 06d2 0066 06d6 bloop $IX2, 0x06d6 - // 06d4 4a00 addax $ACC0, $AX1 - // 06d5 1b7e srri @$AR3, $AC0.M - // 06d6 1b7c srri @$AR3, $AC0.L - for (i = 0; i < IX2; i++) { - ACC0 += pb.src.ratio - *(0x0d80++) = ACC0 >> 16 - *(0x0d80++) = ACC0 & 0xffff - } - - // 06d7 0004 dar $AR0 - // 06d8 189f lrrd $AC1.M, @$AR0 - // 06d9 1adf srrd @$AR2, $AC1.M - // 06da 189f lrrd $AC1.M, @$AR0 - // 06db 1adf srrd @$AR2, $AC1.M - // 06dc 189f lrrd $AC1.M, @$AR0 - // 06dd 1adf srrd @$AR2, $AC1.M - // 06de 189f lrrd $AC1.M, @$AR0 - // 06df 1adf srrd @$AR2, $AC1.M - // 06e0 1adc srrd @$AR2, $AC0.L - *(0x0e46++)-- - pb.src.last_samples[3] = *(0x0e46--) - pb.src.last_samples[2] = *(0x0e46--) - pb.src.last_samples[1] = *(0x0e46--) - pb.src.last_samples[0] = *(0x0e46--) - pb.src.currentAddressFrac = ACC0 & 0xffff - - // 06e1 0082 0bd2 lri $AR2, #0x0bd2 - // 06e3 27dc lrs $AC1.M, @yn2 - // 06e4 1adf srrd @$AR2, $AC1.M - // 06e5 27db lrs $AC1.M, @yn1 - // 06e6 1adf srrd @$AR2, $AC1.M - // 06e7 27da lrs $AC1.M, @scale - // 06e8 1adf srrd @$AR2, $AC1.M - // 06e9 0082 0bbe lri $AR2, #0x0bbe - // 06eb 27d9 lrs $AC1.M, @ACCAL - // 06ec 1adf srrd @$AR2, $AC1.M - // 06ed 27d8 lrs $AC1.M, @ACCAH - // 06ee 1adf srrd @$AR2, $AC1.M - pb.adpm.yn2 = *yn2 - pb.adpm.yn1 = *yn1 - pb.adpm.pred_scale = *scale - pb.addr.currentAddressLo = *ACCAL // Current playback position - pb.addr.currentAddressHi = *ACCAH - - 06ef 8d00 set15 // unsigned mulx - 06f0 8b00 m0 // no *2 - 06f1 8f00 set40 // sign extend - 06f2 00c1 0e42 lr $AR1, @0x0e42 - 06f4 0082 0d80 lri $AR2, #0x0d80 - 06f6 8100 clr $ACC0 - 06f7 1120 0703 bloopi #0x20, 0x0703 - 06f9 8900 clr $ACC1 - 06fa 1940 lrri $AR0, @$AR2 - 06fb 189e lrrd $AC0.M, @$AR0 - 06fc 181b lrr $AX1.H, @$AR0 - 06fd 199a lrrn $AX0.H, @$AR0 - 06fe 5400 subr $ACC0, $AX0.H - 06ff 1f5e mrr $AX0.H, $AC0.M - 0700 1959 lrri $AX1.L, @$AR2 - 0701 b000 mulx $AX0.H, $AX1.L - 0702 fb00 addpaxz $ACC1, $AX1 - 0703 8139 clr's $ACC0 : @$AR1, $AC1.M - - 0704 00e1 0e42 sr @0x0e42, $AR1 - - 0706 02df ret -} - -void SRC_None() { - // Copy pb's data [pb.addr.format to pb.adpm.yn2] to corresponding hw regs - // 0707 0082 0bb8 lri $AR2, #0x0bb8 - // 0709 195e lrri $AC0.M, @$AR2 - // 070a 2ed1 srs @SampleFormat, $AC0.M - // 070b 195e lrri $AC0.M, @$AR2 - // 070c 2ed4 srs @ACSAH, $AC0.M - // 070d 195e lrri $AC0.M, @$AR2 - // 070e 2ed5 srs @ACSAL, $AC0.M - // 070f 195e lrri $AC0.M, @$AR2 - // 0710 2ed6 srs @ACEAH, $AC0.M - // 0711 195e lrri $AC0.M, @$AR2 - // 0712 2ed7 srs @ACEAL, $AC0.M - // 0713 195e lrri $AC0.M, @$AR2 - // 0714 2ed8 srs @ACCAH, $AC0.M - // 0715 195e lrri $AC0.M, @$AR2 - // 0716 2ed9 srs @ACCAL, $AC0.M - // 0717 195e lrri $AC0.M, @$AR2 - // 0718 2ea0 srs @COEF_A1_0, $AC0.M - // 0719 195e lrri $AC0.M, @$AR2 - // 071a 2ea1 srs @COEF_A2_0, $AC0.M - // 071b 195e lrri $AC0.M, @$AR2 - // 071c 2ea2 srs @COEF_A1_1, $AC0.M - // 071d 195e lrri $AC0.M, @$AR2 - // 071e 2ea3 srs @COEF_A2_1, $AC0.M - // 071f 195e lrri $AC0.M, @$AR2 - // 0720 2ea4 srs @COEF_A1_2, $AC0.M - // 0721 195e lrri $AC0.M, @$AR2 - // 0722 2ea5 srs @COEF_A2_2, $AC0.M - // 0723 195e lrri $AC0.M, @$AR2 - // 0724 2ea6 srs @COEF_A1_3, $AC0.M - // 0725 195e lrri $AC0.M, @$AR2 - // 0726 2ea7 srs @COEF_A2_3, $AC0.M - // 0727 195e lrri $AC0.M, @$AR2 - // 0728 2ea8 srs @COEF_A1_4, $AC0.M - // 0729 195e lrri $AC0.M, @$AR2 - // 072a 2ea9 srs @COEF_A2_4, $AC0.M - // 072b 195e lrri $AC0.M, @$AR2 - // 072c 2eaa srs @COEF_A1_5, $AC0.M - // 072d 195e lrri $AC0.M, @$AR2 - // 072e 2eab srs @COEF_A2_5, $AC0.M - // 072f 195e lrri $AC0.M, @$AR2 - // 0730 2eac srs @COEF_A1_6, $AC0.M - // 0731 195e lrri $AC0.M, @$AR2 - // 0732 2ead srs @COEF_A2_6, $AC0.M - // 0733 195e lrri $AC0.M, @$AR2 - // 0734 2eae srs @COEF_A1_7, $AC0.M - // 0735 195e lrri $AC0.M, @$AR2 - // 0736 2eaf srs @COEF_A2_7, $AC0.M - // 0737 195e lrri $AC0.M, @$AR2 - // 0738 2ede srs @GAIN, $AC0.M - // 0739 195e lrri $AC0.M, @$AR2 - // 073a 2eda srs @scale, $AC0.M - // 073b 195e lrri $AC0.M, @$AR2 - // 073c 2edb srs @yn1, $AC0.M - // 073d 195e lrri $AC0.M, @$AR2 - // 073e 2edc srs @yn2, $AC0.M - - // 073f 00c0 0e42 lr $AR0, @0x0e42 - // 0741 0081 ffdd lri $AR1, #0xffdd // DSP_ACCELERATOR - // 0743 1120 0748 bloopi #0x20, 0x0748 - // 0745 1824 lrr $IX0, @$AR1 - // 0746 1b04 srri @$AR0, $IX0 - // 0747 0000 nop - // 0748 0000 nop - // 0749 00e0 0e42 sr @0x0e42, $AR0 - - u16 i = *0x0e42 - for (; i < ((*0x0e42) + 0x20); i++) { - *i = *DSP_ACCELERATOR - } - *0x0e42 = i - - // 074b 0082 0bd9 lri $AR2, #0x0bd9 // pb.src.last_samples[3] - // 074d 0004 dar $AR0 - // 074e 189f lrrd $AC1.M, @$AR0 - // 074f 1adf srrd @$AR2, $AC1.M - // 0750 189f lrrd $AC1.M, @$AR0 - // 0751 1adf srrd @$AR2, $AC1.M - // 0752 189f lrrd $AC1.M, @$AR0 - // 0753 1adf srrd @$AR2, $AC1.M - // 0754 189f lrrd $AC1.M, @$AR0 - // 0755 1adf srrd @$AR2, $AC1.M - // 0756 8900 clr $ACC1 - // 0757 1adc srrd @$AR2, $AC0.L // uhhh assume AC0.L is 0? - i-- // Guess that 0x0e42 points to struct of 1 pointer and 32 values - pb.src.last_samples[3] = *(i--) - pb.src.last_samples[2] = *(i--) - pb.src.last_samples[1] = *(i--) - pb.src.last_samples[0] = *(i--) - pb.src.currentAddressFrac = 0 - - // 0758 27dc lrs $AC1.M, @yn2 - // 0759 00ff 0bd2 sr @0x0bd2, $AC1.M - // 075b 27db lrs $AC1.M, @yn1 - // 075c 00ff 0bd1 sr @0x0bd1, $AC1.M - // 075e 27da lrs $AC1.M, @scale - // 075f 00ff 0bd0 sr @0x0bd0, $AC1.M - // 0761 27d9 lrs $AC1.M, @ACCAL - // 0762 00ff 0bbe sr @0x0bbe, $AC1.M - // 0764 27d8 lrs $AC1.M, @ACCAH - // 0765 00ff 0bbd sr @0x0bbd, $AC1.M - pb.adpm.yn2 = *yn2 - pb.adpm.yn1 = *yn1 - pb.adpm.pred_scale = *scale - pb.addr.currentAddressLo = *ACCAL // Current playback position - pb.addr.currentAddressHi = *ACCAH - - 0767 02df ret -} - - -# From here to the jump tables, all the funcs just wrap calls to mixer(s) in IROM - -void Mixer_0() { - 0768 00c0 0e40 lr $AR0, @0x0e40 - 076a 0081 0b89 lri $AR1, #0x0b89 - 076c 00c2 0e08 lr $AR2, @0x0e08 - 076e 1c62 mrr $AR3, $AR2 - 076f 00c4 0e41 lr $IX0, @0x0e41 - 0771 00c5 0e09 lr $IX1, @0x0e09 - 0773 02bf 80e7 call 0x80e7 - 0775 00f8 0ba9 sr @0x0ba9, $AX0.L - 0777 00fb 0bac sr @0x0bac, $AX1.H - 0779 02df ret -} - -void Mixer_1() { - 077a 00c0 0e40 lr $AR0, @0x0e40 - 077c 0081 0b89 lri $AR1, #0x0b89 - 077e 00c2 0e08 lr $AR2, @0x0e08 - 0780 1c62 mrr $AR3, $AR2 - 0781 00c4 0e41 lr $IX0, @0x0e41 - 0783 00c5 0e09 lr $IX1, @0x0e09 - 0785 02bf 80e7 call 0x80e7 - 0787 00f8 0ba9 sr @0x0ba9, $AX0.L - 0789 00fb 0bac sr @0x0bac, $AX1.H - 078b 00c0 0e40 lr $AR0, @0x0e40 - 078d 0081 0b8d lri $AR1, #0x0b8d - 078f 00c2 0e0b lr $AR2, @0x0e0b - 0791 1c62 mrr $AR3, $AR2 - 0792 00c4 0e41 lr $IX0, @0x0e41 - 0794 00c5 0e0c lr $IX1, @0x0e0c - 0796 02bf 80e7 call 0x80e7 - 0798 00f8 0baa sr @0x0baa, $AX0.L - 079a 00fb 0bad sr @0x0bad, $AX1.H - 079c 02df ret -} - -void Mixer_2() { - 079d 00c0 0e40 lr $AR0, @0x0e40 - 079f 0081 0b89 lri $AR1, #0x0b89 - 07a1 00c2 0e08 lr $AR2, @0x0e08 - 07a3 1c62 mrr $AR3, $AR2 - 07a4 00c4 0e41 lr $IX0, @0x0e41 - 07a6 00c5 0e09 lr $IX1, @0x0e09 - 07a8 02bf 80e7 call 0x80e7 - 07aa 00f8 0ba9 sr @0x0ba9, $AX0.L - 07ac 00fb 0bac sr @0x0bac, $AX1.H - 07ae 00c0 0e40 lr $AR0, @0x0e40 - 07b0 0081 0b91 lri $AR1, #0x0b91 - 07b2 00c2 0e0e lr $AR2, @0x0e0e - 07b4 1c62 mrr $AR3, $AR2 - 07b5 00c4 0e41 lr $IX0, @0x0e41 - 07b7 00c5 0e0f lr $IX1, @0x0e0f - 07b9 02bf 80e7 call 0x80e7 - 07bb 00f8 0bab sr @0x0bab, $AX0.L - 07bd 00fb 0bae sr @0x0bae, $AX1.H - 07bf 02df ret -} - -void Unk() { - 07c0 00c0 0e40 lr $AR0, @0x0e40 - 07c2 0081 0b89 lri $AR1, #0x0b89 - 07c4 00c2 0e08 lr $AR2, @0x0e08 - 07c6 1c62 mrr $AR3, $AR2 - 07c7 00c4 0e41 lr $IX0, @0x0e41 - 07c9 00c5 0e09 lr $IX1, @0x0e09 - 07cb 02bf 80e7 call 0x80e7 - 07cd 00f8 0ba9 sr @0x0ba9, $AX0.L - 07cf 00fb 0bac sr @0x0bac, $AX1.H - 07d1 00c0 0e40 lr $AR0, @0x0e40 - 07d3 0081 0b8d lri $AR1, #0x0b8d - 07d5 00c2 0e0b lr $AR2, @0x0e0b - 07d7 1c62 mrr $AR3, $AR2 - 07d8 00c4 0e41 lr $IX0, @0x0e41 - 07da 00c5 0e0c lr $IX1, @0x0e0c - 07dc 02bf 80e7 call 0x80e7 - 07de 00f8 0baa sr @0x0baa, $AX0.L - 07e0 00fb 0bad sr @0x0bad, $AX1.H - 07e2 00c0 0e40 lr $AR0, @0x0e40 - 07e4 0081 0b91 lri $AR1, #0x0b91 - 07e6 00c2 0e0e lr $AR2, @0x0e0e - 07e8 1c62 mrr $AR3, $AR2 - 07e9 00c4 0e41 lr $IX0, @0x0e41 - 07eb 00c5 0e0f lr $IX1, @0x0e0f - 07ed 02bf 80e7 call 0x80e7 - 07ef 00f8 0bab sr @0x0bab, $AX0.L - 07f1 00fb 0bae sr @0x0bae, $AX1.H - 07f3 02df ret -} - -void Unk() { - 07f4 00c0 0e40 lr $AR0, @0x0e40 - 07f6 0081 0b89 lri $AR1, #0x0b89 - 07f8 00c2 0e08 lr $AR2, @0x0e08 - 07fa 1c62 mrr $AR3, $AR2 - 07fb 00c4 0e41 lr $IX0, @0x0e41 - 07fd 00c5 0e09 lr $IX1, @0x0e09 - 07ff 02bf 80e7 call 0x80e7 - 0801 00f8 0ba9 sr @0x0ba9, $AX0.L - 0803 00fb 0bac sr @0x0bac, $AX1.H - 0805 00c0 0e43 lr $AR0, @0x0e43 - 0807 0081 0b97 lri $AR1, #0x0b97 - 0809 00c2 0e0a lr $AR2, @0x0e0a - 080b 1c62 mrr $AR3, $AR2 - 080c 02bf 81f9 call 0x81f9 - 080e 00f8 0baf sr @0x0baf, $AX0.L - 0810 02df ret -} - -void Unk() { - 0811 00c0 0e40 lr $AR0, @0x0e40 - 0813 0081 0b89 lri $AR1, #0x0b89 - 0815 00c2 0e08 lr $AR2, @0x0e08 - 0817 1c62 mrr $AR3, $AR2 - 0818 00c4 0e41 lr $IX0, @0x0e41 - 081a 00c5 0e09 lr $IX1, @0x0e09 - 081c 02bf 80e7 call 0x80e7 - 081e 00f8 0ba9 sr @0x0ba9, $AX0.L - 0820 00fb 0bac sr @0x0bac, $AX1.H - 0822 00c0 0e40 lr $AR0, @0x0e40 - 0824 0081 0b8d lri $AR1, #0x0b8d - 0826 00c2 0e0b lr $AR2, @0x0e0b - 0828 1c62 mrr $AR3, $AR2 - 0829 00c4 0e41 lr $IX0, @0x0e41 - 082b 00c5 0e0c lr $IX1, @0x0e0c - 082d 02bf 80e7 call 0x80e7 - 082f 00f8 0baa sr @0x0baa, $AX0.L - 0831 00fb 0bad sr @0x0bad, $AX1.H - 0833 00c0 0e43 lr $AR0, @0x0e43 - 0835 0081 0b97 lri $AR1, #0x0b97 - 0837 00c2 0e0a lr $AR2, @0x0e0a - 0839 1c62 mrr $AR3, $AR2 - 083a 1c80 mrr $IX0, $AR0 - 083b 00c5 0e0d lr $IX1, @0x0e0d - 083d 02bf 80e7 call 0x80e7 - 083f 00f8 0baf sr @0x0baf, $AX0.L - 0841 00fb 0bb0 sr @0x0bb0, $AX1.H - 0843 02df ret -} - -void Unk() { - 0844 00c0 0e40 lr $AR0, @0x0e40 - 0846 0081 0b89 lri $AR1, #0x0b89 - 0848 00c2 0e08 lr $AR2, @0x0e08 - 084a 1c62 mrr $AR3, $AR2 - 084b 00c4 0e41 lr $IX0, @0x0e41 - 084d 00c5 0e09 lr $IX1, @0x0e09 - 084f 02bf 80e7 call 0x80e7 - 0851 00f8 0ba9 sr @0x0ba9, $AX0.L - 0853 00fb 0bac sr @0x0bac, $AX1.H - 0855 00c0 0e40 lr $AR0, @0x0e40 - 0857 0081 0b91 lri $AR1, #0x0b91 - 0859 00c2 0e0e lr $AR2, @0x0e0e - 085b 1c62 mrr $AR3, $AR2 - 085c 00c4 0e41 lr $IX0, @0x0e41 - 085e 00c5 0e0f lr $IX1, @0x0e0f - 0860 02bf 80e7 call 0x80e7 - 0862 00f8 0bab sr @0x0bab, $AX0.L - 0864 00fb 0bae sr @0x0bae, $AX1.H - 0866 00c0 0e43 lr $AR0, @0x0e43 - 0868 0081 0b95 lri $AR1, #0x0b95 - 086a 00c2 0e10 lr $AR2, @0x0e10 - 086c 1c62 mrr $AR3, $AR2 - 086d 1c80 mrr $IX0, $AR0 - 086e 00c5 0e0a lr $IX1, @0x0e0a - 0870 02bf 80e7 call 0x80e7 - 0872 00f8 0bb1 sr @0x0bb1, $AX0.L - 0874 00fb 0baf sr @0x0baf, $AX1.H - 0876 02df ret -} - -void Unk() { - 0877 00c0 0e40 lr $AR0, @0x0e40 - 0879 0081 0b89 lri $AR1, #0x0b89 - 087b 00c2 0e08 lr $AR2, @0x0e08 - 087d 1c62 mrr $AR3, $AR2 - 087e 00c4 0e41 lr $IX0, @0x0e41 - 0880 00c5 0e09 lr $IX1, @0x0e09 - 0882 02bf 80e7 call 0x80e7 - 0884 00f8 0ba9 sr @0x0ba9, $AX0.L - 0886 00fb 0bac sr @0x0bac, $AX1.H - 0888 00c0 0e40 lr $AR0, @0x0e40 - 088a 0081 0b8d lri $AR1, #0x0b8d - 088c 00c2 0e0b lr $AR2, @0x0e0b - 088e 1c62 mrr $AR3, $AR2 - 088f 00c4 0e41 lr $IX0, @0x0e41 - 0891 00c5 0e0c lr $IX1, @0x0e0c - 0893 02bf 80e7 call 0x80e7 - 0895 00f8 0baa sr @0x0baa, $AX0.L - 0897 00fb 0bad sr @0x0bad, $AX1.H - 0899 00c0 0e40 lr $AR0, @0x0e40 - 089b 0081 0b91 lri $AR1, #0x0b91 - 089d 00c2 0e0e lr $AR2, @0x0e0e - 089f 1c62 mrr $AR3, $AR2 - 08a0 00c4 0e41 lr $IX0, @0x0e41 - 08a2 00c5 0e0f lr $IX1, @0x0e0f - 08a4 02bf 80e7 call 0x80e7 - 08a6 00f8 0bab sr @0x0bab, $AX0.L - 08a8 00fb 0bae sr @0x0bae, $AX1.H - 08aa 00c0 0e43 lr $AR0, @0x0e43 - 08ac 0081 0b97 lri $AR1, #0x0b97 - 08ae 00c2 0e0a lr $AR2, @0x0e0a - 08b0 1c62 mrr $AR3, $AR2 - 08b1 1c80 mrr $IX0, $AR0 - 08b2 00c5 0e0d lr $IX1, @0x0e0d - 08b4 02bf 80e7 call 0x80e7 - 08b6 00f8 0baf sr @0x0baf, $AX0.L - 08b8 00fb 0bb0 sr @0x0bb0, $AX1.H - 08ba 00c0 0e43 lr $AR0, @0x0e43 - 08bc 0081 0b95 lri $AR1, #0x0b95 - 08be 00c2 0e10 lr $AR2, @0x0e10 - 08c0 1c62 mrr $AR3, $AR2 - 08c1 02bf 81f9 call 0x81f9 - 08c3 00f8 0bb1 sr @0x0bb1, $AX0.L - 08c5 02df ret -} - -void Unk() { - 08c6 00c0 0e40 lr $AR0, @0x0e40 - 08c8 0081 0b89 lri $AR1, #0x0b89 - 08ca 00c2 0e08 lr $AR2, @0x0e08 - 08cc 0083 0e44 lri $AR3, #0x0e44 - 08ce 00c4 0e41 lr $IX0, @0x0e41 - 08d0 00c5 0e09 lr $IX1, @0x0e09 - 08d2 02bf 8282 call 0x8282 - 08d4 00f8 0ba9 sr @0x0ba9, $AX0.L - 08d6 00fb 0bac sr @0x0bac, $AX1.H - 08d8 02df ret -} - -void Unk() { - 08d9 00c0 0e40 lr $AR0, @0x0e40 - 08db 0081 0b89 lri $AR1, #0x0b89 - 08dd 00c2 0e08 lr $AR2, @0x0e08 - 08df 0083 0e44 lri $AR3, #0x0e44 - 08e1 00c4 0e41 lr $IX0, @0x0e41 - 08e3 00c5 0e09 lr $IX1, @0x0e09 - 08e5 02bf 8282 call 0x8282 - 08e7 00f8 0ba9 sr @0x0ba9, $AX0.L - 08e9 00fb 0bac sr @0x0bac, $AX1.H - 08eb 00c0 0e40 lr $AR0, @0x0e40 - 08ed 0081 0b8d lri $AR1, #0x0b8d - 08ef 00c2 0e0b lr $AR2, @0x0e0b - 08f1 0083 0e44 lri $AR3, #0x0e44 - 08f3 00c4 0e41 lr $IX0, @0x0e41 - 08f5 00c5 0e0c lr $IX1, @0x0e0c - 08f7 02bf 8282 call 0x8282 - 08f9 00f8 0baa sr @0x0baa, $AX0.L - 08fb 00fb 0bad sr @0x0bad, $AX1.H - 08fd 02df ret -} - -void Unk() { - 08fe 00c0 0e40 lr $AR0, @0x0e40 - 0900 0081 0b89 lri $AR1, #0x0b89 - 0902 00c2 0e08 lr $AR2, @0x0e08 - 0904 0083 0e44 lri $AR3, #0x0e44 - 0906 00c4 0e41 lr $IX0, @0x0e41 - 0908 00c5 0e09 lr $IX1, @0x0e09 - 090a 02bf 8282 call 0x8282 - 090c 00f8 0ba9 sr @0x0ba9, $AX0.L - 090e 00fb 0bac sr @0x0bac, $AX1.H - 0910 00c0 0e40 lr $AR0, @0x0e40 - 0912 0081 0b91 lri $AR1, #0x0b91 - 0914 00c2 0e0e lr $AR2, @0x0e0e - 0916 0083 0e44 lri $AR3, #0x0e44 - 0918 00c4 0e41 lr $IX0, @0x0e41 - 091a 00c5 0e0f lr $IX1, @0x0e0f - 091c 02bf 8282 call 0x8282 - 091e 00f8 0bab sr @0x0bab, $AX0.L - 0920 00fb 0bae sr @0x0bae, $AX1.H - 0922 02df ret -} - -void Unk() { - 0923 00c0 0e40 lr $AR0, @0x0e40 - 0925 0081 0b89 lri $AR1, #0x0b89 - 0927 00c2 0e08 lr $AR2, @0x0e08 - 0929 0083 0e44 lri $AR3, #0x0e44 - 092b 00c4 0e41 lr $IX0, @0x0e41 - 092d 00c5 0e09 lr $IX1, @0x0e09 - 092f 02bf 8282 call 0x8282 - 0931 00f8 0ba9 sr @0x0ba9, $AX0.L - 0933 00fb 0bac sr @0x0bac, $AX1.H - 0935 00c0 0e40 lr $AR0, @0x0e40 - 0937 0081 0b8d lri $AR1, #0x0b8d - 0939 00c2 0e0b lr $AR2, @0x0e0b - 093b 0083 0e44 lri $AR3, #0x0e44 - 093d 00c4 0e41 lr $IX0, @0x0e41 - 093f 00c5 0e0c lr $IX1, @0x0e0c - 0941 02bf 8282 call 0x8282 - 0943 00f8 0baa sr @0x0baa, $AX0.L - 0945 00fb 0bad sr @0x0bad, $AX1.H - 0947 00c0 0e40 lr $AR0, @0x0e40 - 0949 0081 0b91 lri $AR1, #0x0b91 - 094b 00c2 0e0e lr $AR2, @0x0e0e - 094d 0083 0e44 lri $AR3, #0x0e44 - 094f 00c4 0e41 lr $IX0, @0x0e41 - 0951 00c5 0e0f lr $IX1, @0x0e0f - 0953 02bf 8282 call 0x8282 - 0955 00f8 0bab sr @0x0bab, $AX0.L - 0957 00fb 0bae sr @0x0bae, $AX1.H - 0959 02df ret -} - -void Unk() { - 095a 00c0 0e40 lr $AR0, @0x0e40 - 095c 0081 0b89 lri $AR1, #0x0b89 - 095e 00c2 0e08 lr $AR2, @0x0e08 - 0960 0083 0e44 lri $AR3, #0x0e44 - 0962 00c4 0e41 lr $IX0, @0x0e41 - 0964 00c5 0e09 lr $IX1, @0x0e09 - 0966 02bf 8282 call 0x8282 - 0968 00f8 0ba9 sr @0x0ba9, $AX0.L - 096a 00fb 0bac sr @0x0bac, $AX1.H - 096c 00c0 0e43 lr $AR0, @0x0e43 - 096e 0081 0b97 lri $AR1, #0x0b97 - 0970 00c2 0e0a lr $AR2, @0x0e0a - 0972 0083 0e44 lri $AR3, #0x0e44 - 0974 02bf 845d call 0x845d - 0976 00f8 0baf sr @0x0baf, $AX0.L - 0978 02df ret -} - -void Unk() { - 0979 00c0 0e40 lr $AR0, @0x0e40 - 097b 0081 0b89 lri $AR1, #0x0b89 - 097d 00c2 0e08 lr $AR2, @0x0e08 - 097f 0083 0e44 lri $AR3, #0x0e44 - 0981 00c4 0e41 lr $IX0, @0x0e41 - 0983 00c5 0e09 lr $IX1, @0x0e09 - 0985 02bf 8282 call 0x8282 - 0987 00f8 0ba9 sr @0x0ba9, $AX0.L - 0989 00fb 0bac sr @0x0bac, $AX1.H - 098b 00c0 0e40 lr $AR0, @0x0e40 - 098d 0081 0b8d lri $AR1, #0x0b8d - 098f 00c2 0e0b lr $AR2, @0x0e0b - 0991 0083 0e44 lri $AR3, #0x0e44 - 0993 00c4 0e41 lr $IX0, @0x0e41 - 0995 00c5 0e0c lr $IX1, @0x0e0c - 0997 02bf 8282 call 0x8282 - 0999 00f8 0baa sr @0x0baa, $AX0.L - 099b 00fb 0bad sr @0x0bad, $AX1.H - 099d 00c0 0e43 lr $AR0, @0x0e43 - 099f 0081 0b97 lri $AR1, #0x0b97 - 09a1 00c2 0e0a lr $AR2, @0x0e0a - 09a3 0083 0e44 lri $AR3, #0x0e44 - 09a5 1c80 mrr $IX0, $AR0 - 09a6 00c5 0e0d lr $IX1, @0x0e0d - 09a8 02bf 8282 call 0x8282 - 09aa 00f8 0baf sr @0x0baf, $AX0.L - 09ac 00fb 0bb0 sr @0x0bb0, $AX1.H - 09ae 02df ret -} - -void Unk() { - 09af 00c0 0e40 lr $AR0, @0x0e40 - 09b1 0081 0b89 lri $AR1, #0x0b89 - 09b3 00c2 0e08 lr $AR2, @0x0e08 - 09b5 0083 0e44 lri $AR3, #0x0e44 - 09b7 00c4 0e41 lr $IX0, @0x0e41 - 09b9 00c5 0e09 lr $IX1, @0x0e09 - 09bb 02bf 8282 call 0x8282 - 09bd 00f8 0ba9 sr @0x0ba9, $AX0.L - 09bf 00fb 0bac sr @0x0bac, $AX1.H - 09c1 00c0 0e40 lr $AR0, @0x0e40 - 09c3 0081 0b91 lri $AR1, #0x0b91 - 09c5 00c2 0e0e lr $AR2, @0x0e0e - 09c7 0083 0e44 lri $AR3, #0x0e44 - 09c9 00c4 0e41 lr $IX0, @0x0e41 - 09cb 00c5 0e0f lr $IX1, @0x0e0f - 09cd 02bf 8282 call 0x8282 - 09cf 00f8 0bab sr @0x0bab, $AX0.L - 09d1 00fb 0bae sr @0x0bae, $AX1.H - 09d3 00c0 0e43 lr $AR0, @0x0e43 - 09d5 0081 0b95 lri $AR1, #0x0b95 - 09d7 00c2 0e10 lr $AR2, @0x0e10 - 09d9 0083 0e44 lri $AR3, #0x0e44 - 09db 1c80 mrr $IX0, $AR0 - 09dc 00c5 0e0a lr $IX1, @0x0e0a - 09de 02bf 8282 call 0x8282 - 09e0 00f8 0bb1 sr @0x0bb1, $AX0.L - 09e2 00fb 0baf sr @0x0baf, $AX1.H - 09e4 02df ret -} - -void Unk() { - 09e5 00c0 0e40 lr $AR0, @0x0e40 - 09e7 0081 0b89 lri $AR1, #0x0b89 - 09e9 00c2 0e08 lr $AR2, @0x0e08 - 09eb 0083 0e44 lri $AR3, #0x0e44 - 09ed 00c4 0e41 lr $IX0, @0x0e41 - 09ef 00c5 0e09 lr $IX1, @0x0e09 - 09f1 02bf 8282 call 0x8282 - 09f3 00f8 0ba9 sr @0x0ba9, $AX0.L - 09f5 00fb 0bac sr @0x0bac, $AX1.H - 09f7 00c0 0e40 lr $AR0, @0x0e40 - 09f9 0081 0b8d lri $AR1, #0x0b8d - 09fb 00c2 0e0b lr $AR2, @0x0e0b - 09fd 0083 0e44 lri $AR3, #0x0e44 - 09ff 00c0 0e41 lr $AR0, @0x0e41 - 0a01 00c5 0e0c lr $IX1, @0x0e0c - 0a03 02bf 8282 call 0x8282 - 0a05 00f8 0baa sr @0x0baa, $AX0.L - 0a07 00fb 0bad sr @0x0bad, $AX1.H - 0a09 00c0 0e40 lr $AR0, @0x0e40 - 0a0b 0081 0b91 lri $AR1, #0x0b91 - 0a0d 00c2 0e0e lr $AR2, @0x0e0e - 0a0f 0083 0e44 lri $AR3, #0x0e44 - 0a11 00c4 0e41 lr $IX0, @0x0e41 - 0a13 00c5 0e0f lr $IX1, @0x0e0f - 0a15 02bf 8282 call 0x8282 - 0a17 00f8 0bab sr @0x0bab, $AX0.L - 0a19 00fb 0bae sr @0x0bae, $AX1.H - 0a1b 00c0 0e43 lr $AR0, @0x0e43 - 0a1d 0081 0b97 lri $AR1, #0x0b97 - 0a1f 00c2 0e0a lr $AR2, @0x0e0a - 0a21 0083 0e44 lri $AR3, #0x0e44 - 0a23 1c80 mrr $IX0, $AR0 - 0a24 00c5 0e0d lr $IX1, @0x0e0d - 0a26 02bf 8282 call 0x8282 - 0a28 00f8 0baf sr @0x0baf, $AX0.L - 0a2a 00fb 0bb0 sr @0x0bb0, $AX1.H - 0a2c 00c0 0e43 lr $AR0, @0x0e43 - 0a2e 0081 0b95 lri $AR1, #0x0b95 - 0a30 00c2 0e10 lr $AR2, @0x0e10 - 0a32 0083 0e44 lri $AR3, #0x0e44 - 0a34 02bf 845d call 0x845d - 0a36 00f8 0bb1 sr @0x0bb1, $AX0.L - 0a38 02df ret -} - -void Unk() { - 0a39 00c0 0e40 lr $AR0, @0x0e40 - 0a3b 0081 0b89 lri $AR1, #0x0b89 - 0a3d 00c2 0e08 lr $AR2, @0x0e08 - 0a3f 1c62 mrr $AR3, $AR2 - 0a40 00c4 0e41 lr $IX0, @0x0e41 - 0a42 00c5 0e09 lr $IX1, @0x0e09 - 0a44 02bf 80e7 call 0x80e7 - 0a46 00f8 0ba9 sr @0x0ba9, $AX0.L - 0a48 00fb 0bac sr @0x0bac, $AX1.H - 0a4a 00c0 0e43 lr $AR0, @0x0e43 - 0a4c 0081 0b91 lri $AR1, #0x0b91 - 0a4e 00c2 0e0e lr $AR2, @0x0e0e - 0a50 1c62 mrr $AR3, $AR2 - 0a51 1c80 mrr $IX0, $AR0 - 0a52 00c5 0e0f lr $IX1, @0x0e0f - 0a54 02bf 80e7 call 0x80e7 - 0a56 00f8 0bab sr @0x0bab, $AX0.L - 0a58 00fb 0bae sr @0x0bae, $AX1.H - 0a5a 02df ret -} - -void Unk() { - 0a5b 00c0 0e40 lr $AR0, @0x0e40 - 0a5d 0081 0b89 lri $AR1, #0x0b89 - 0a5f 00c2 0e08 lr $AR2, @0x0e08 - 0a61 1c62 mrr $AR3, $AR2 - 0a62 00c4 0e41 lr $IX0, @0x0e41 - 0a64 00c5 0e09 lr $IX1, @0x0e09 - 0a66 02bf 80e7 call 0x80e7 - 0a68 00f8 0ba9 sr @0x0ba9, $AX0.L - 0a6a 00fb 0bac sr @0x0bac, $AX1.H - 0a6c 00c0 0e43 lr $AR0, @0x0e43 - 0a6e 0081 0b91 lri $AR1, #0x0b91 - 0a70 00c2 0e0e lr $AR2, @0x0e0e - 0a72 1c62 mrr $AR3, $AR2 - 0a73 1c80 mrr $IX0, $AR0 - 0a74 00c5 0e0f lr $IX1, @0x0e0f - 0a76 02bf 80e7 call 0x80e7 - 0a78 00f8 0bab sr @0x0bab, $AX0.L - 0a7a 00fb 0bae sr @0x0bae, $AX1.H - 0a7c 00c0 0e40 lr $AR0, @0x0e40 - 0a7e 0081 0b8d lri $AR1, #0x0b8d - 0a80 00c2 0e0b lr $AR2, @0x0e0b - 0a82 1c62 mrr $AR3, $AR2 - 0a83 00c4 0e41 lr $IX0, @0x0e41 - 0a85 00c5 0e0c lr $IX1, @0x0e0c - 0a87 02bf 80e7 call 0x80e7 - 0a89 00f8 0baa sr @0x0baa, $AX0.L - 0a8b 00fb 0bad sr @0x0bad, $AX1.H - 0a8d 00c0 0e43 lr $AR0, @0x0e43 - 0a8f 0081 0b99 lri $AR1, #0x0b99 - 0a91 00c2 0e0d lr $AR2, @0x0e0d - 0a93 1c62 mrr $AR3, $AR2 - 0a94 02bf 81f9 call 0x81f9 - 0a96 00f8 0bb0 sr @0x0bb0, $AX0.L - 0a98 02df ret -} - -void Unk() { - 0a99 00c0 0e40 lr $AR0, @0x0e40 - 0a9b 0081 0b89 lri $AR1, #0x0b89 - 0a9d 00c2 0e08 lr $AR2, @0x0e08 - 0a9f 0083 0e44 lri $AR3, #0x0e44 - 0aa1 00c4 0e41 lr $IX0, @0x0e41 - 0aa3 00c5 0e09 lr $IX1, @0x0e09 - 0aa5 02bf 8282 call 0x8282 - 0aa7 00f8 0ba9 sr @0x0ba9, $AX0.L - 0aa9 00fb 0bac sr @0x0bac, $AX1.H - 0aab 00c0 0e43 lr $AR0, @0x0e43 - 0aad 0081 0b91 lri $AR1, #0x0b91 - 0aaf 00c2 0e0e lr $AR2, @0x0e0e - 0ab1 0083 0e44 lri $AR3, #0x0e44 - 0ab3 1c80 mrr $IX0, $AR0 - 0ab4 00c5 0e0f lr $IX1, @0x0e0f - 0ab6 02bf 8282 call 0x8282 - 0ab8 00f8 0bab sr @0x0bab, $AX0.L - 0aba 00fb 0bae sr @0x0bae, $AX1.H - 0abc 02df ret -} - -void Unk() { - 0abd 00c0 0e40 lr $AR0, @0x0e40 - 0abf 0081 0b89 lri $AR1, #0x0b89 - 0ac1 00c2 0e08 lr $AR2, @0x0e08 - 0ac3 0083 0e44 lri $AR3, #0x0e44 - 0ac5 00c4 0e41 lr $IX0, @0x0e41 - 0ac7 00c5 0e09 lr $IX1, @0x0e09 - 0ac9 02bf 8282 call 0x8282 - 0acb 00f8 0ba9 sr @0x0ba9, $AX0.L - 0acd 00fb 0bac sr @0x0bac, $AX1.H - 0acf 00c0 0e43 lr $AR0, @0x0e43 - 0ad1 0081 0b91 lri $AR1, #0x0b91 - 0ad3 00c2 0e0e lr $AR2, @0x0e0e - 0ad5 0083 0e44 lri $AR3, #0x0e44 - 0ad7 1c80 mrr $IX0, $AR0 - 0ad8 00c5 0e0f lr $IX1, @0x0e0f - 0ada 02bf 8282 call 0x8282 - 0adc 00f8 0bab sr @0x0bab, $AX0.L - 0ade 00fb 0bae sr @0x0bae, $AX1.H - 0ae0 00c0 0e40 lr $AR0, @0x0e40 - 0ae2 0081 0b8d lri $AR1, #0x0b8d - 0ae4 00c2 0e0b lr $AR2, @0x0e0b - 0ae6 0083 0e44 lri $AR3, #0x0e44 - 0ae8 00c4 0e41 lr $IX0, @0x0e41 - 0aea 00c5 0e0c lr $IX1, @0x0e0c - 0aec 02bf 8282 call 0x8282 - 0aee 00f8 0baa sr @0x0baa, $AX0.L - 0af0 00fb 0bad sr @0x0bad, $AX1.H - 0af2 00c0 0e43 lr $AR0, @0x0e43 - 0af4 0081 0b99 lri $AR1, #0x0b99 - 0af6 00c2 0e0d lr $AR2, @0x0e0d - 0af8 0083 0e44 lri $AR3, #0x0e44 - 0afa 02bf 845d call 0x845d - 0afc 00f8 0bb0 sr @0x0bb0, $AX0.L - 0afe 02df ret -} - -# Jump table for main commands -0aff 0082 // Jump 0 -0b00 013e // Jump 1 -0b01 01bc // Jump 2 -0b02 0248 // Jump 3 -0b03 0413 // Jump 4 -0b04 0427 // Jump 5 -0b05 0165 // Jump 6 -0b06 0574 // Jump 7 -0b07 0b37 // Jump 8 -0b08 015f // Jump 9 -0b09 0478 // Jump a -0b0a 0474 // Jump b -0b0b 0476 // Jump c -0b0c 01a9 // Jump d -0b0d 043b // Jump e -0b0e 047a // Jump f Task_Yield() -0b0f 0bb1 // Jump 10 -0b10 0175 // Jump 11 - -# LUT for pb.mixerCtrl -0b11 0768 // Jump3 0 -0b12 077a // Jump3 1 -0b13 079d // Jump3 2 -0b14 07c0 // Jump3 3 -0b15 07f4 // Jump3 4 -0b16 0811 // Jump3 5 -0b17 0844 // Jump3 6 -0b18 0877 // Jump3 7 -0b19 08c6 // Jump3 8 -0b1a 08d9 // Jump3 9 -0b1b 08fe // Jump3 a -0b1c 0923 // Jump3 b -0b1d 095a // Jump3 c -0b1e 0979 // Jump3 d -0b1f 09af // Jump3 e -0b20 09e5 // Jump3 f - -0b21 0a39 // Jump3 10 -0b22 0a5b // Jump3 11 -0b23 0768 // Jump3 12 -0b24 0768 // Jump3 13 -0b25 0768 // Jump3 14 -0b26 0768 // Jump3 15 -0b27 0768 // Jump3 16 -0b28 0768 // Jump3 17 -0b29 0a99 // Jump3 18 -0b2a 0abd // Jump3 19 -0b2b 0768 // Jump3 1a -0b2c 0768 // Jump3 1b -0b2d 0768 // Jump3 1c -0b2e 0768 // Jump3 1d -0b2f 0768 // Jump3 1e -0b30 0768 // Jump3 1f - -# LUT for pb.srcSelect -0b31 05a8 // Jump4 0 -0b32 065d // Jump4 1 -0b33 0707 // Jump4 2 - -# LUT for pb.coefSelect tables (in drom) -0b34 1000 -0b35 1200 -0b36 1400 - -# End of noise - back to code. - -void Cmd_8() { - 0b37 8e00 set16 - - 0b38 8100 clr $ACC0 - 0b39 8970 clr'l $ACC1 : $AC0.M, @$AR0 - 0b3a 191c lrri $AC0.L, @$AR0 - - 0b3b 2ece srs @DSMAH, $AC0.M - 0b3c 2ccf srs @DSMAL, $AC0.L - 0b3d 16cd 0e80 si @DSPA, #0x0e80 - 0b3f 16c9 0000 si @DSCR, #0x0000 - 0b41 16cb 0100 si @DSBL, #0x0100 - - 0b43 1f7e mrr $AX1.H, $AC0.M - 0b44 1f3c mrr $AX1.L, $AC0.L - - 0b45 8100 clr $ACC0 - - 0b46 26c9 lrs $AC0.M, @DSCR - 0b47 02a0 0004 andf $AC0.M, #0x0004 - 0b49 029c 0b46 jlnz 0x0b46 - - 0b4b 191e lrri $AC0.M, @$AR0 - 0b4c 191c lrri $AC0.L, @$AR0 - 0b4d 2ece srs @DSMAH, $AC0.M - 0b4e 2ccf srs @DSMAL, $AC0.L - 0b4f 16cd 0280 si @DSPA, #0x0280 - 0b51 16c9 0000 si @DSCR, #0x0000 - 0b53 16cb 0280 si @DSBL, #0x0280 - - 0b55 1c80 mrr $IX0, $AR0 - - 0b56 0080 0280 lri $AR0, #0x0280 - 0b58 00c1 0e1b lr $AR1, @0x0e1b - 0b5a 0085 0000 lri $IX1, #0x0000 - 0b5c 0089 007f lri $WR1, #0x007f - 0b5e 0082 0f00 lri $AR2, #0x0f00 - 0b60 0083 16b4 lri $AR3, #0x16b4 - 0b62 1ce3 mrr $IX3, $AR3 - 0b63 8100 clr $ACC0 - - 0b64 26c9 lrs $AC0.M, @DSCR - 0b65 02a0 0004 andf $AC0.M, #0x0004 - 0b67 029c 0b64 jlnz 0x0b64 - - 0b69 8f00 set40 - 0b6a 8a78 m2'l : $AC1.M, @$AR0 - 0b6b 8c68 clr15'l : $AC1.L, @$AR0 - 0b6c f100 lsl16 $ACC1 - 0b6d 1a3f srr @$AR1, $AC1.M - 0b6e 84e3 clrp'ld : $AX0.H, $AX1.L, @$AR3 - 0b6f 107e loopi #0x7e - 0b70 f2e3 madd'ld $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 - 0b71 f2e7 madd'ldn $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 - 0b72 f278 madd'l $AX0.L, $AX0.H : $AC1.M, @$AR0 - 0b73 6e68 movp'l $ACC0 : $AC1.L, @$AR0 - 0b74 f132 lsl16's $ACC1 : @$AR2, $AC0.M - 0b75 1a3f srr @$AR1, $AC1.M - 0b76 119e 0b80 bloopi #0x9e, 0x0b80 - 0b78 1c67 mrr $AR3, $IX3 - 0b79 84e3 clrp'ld : $AX0.H, $AX1.L, @$AR3 - 0b7a 107e loopi #0x7e - 0b7b f2e3 madd'ld $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 - 0b7c f2e7 madd'ldn $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 - 0b7d f278 madd'l $AX0.L, $AX0.H : $AC1.M, @$AR0 - 0b7e 6e68 movp'l $ACC0 : $AC1.L, @$AR0 - 0b7f f132 lsl16's $ACC1 : @$AR2, $AC0.M - 0b80 1a3f srr @$AR1, $AC1.M - - 0b81 1c67 mrr $AR3, $IX3 - 0b82 84e3 clrp'ld : $AX0.H, $AX1.L, @$AR3 - 0b83 107e loopi #0x7e - 0b84 f2e3 madd'ld $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 - 0b85 f2e7 madd'ldn $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 - 0b86 f200 madd $AX0.L, $AX0.H - 0b87 6e00 movp $ACC0 - 0b88 1b5e srri @$AR2, $AC0.M - 0b89 00e1 0e1b sr @0x0e1b, $AR1 - - 0b8b 0080 0280 lri $AR0, #0x0280 - 0b8d 0083 0f00 lri $AR3, #0x0f00 - 0b8f 0081 0000 lri $AR1, #0x0000 - 0b91 0082 0140 lri $AR2, #0x0140 - 0b93 0089 ffff lri $WR1, #0xffff - - 0b95 8900 clr $ACC1 - 0b96 8100 clr $ACC0 - - 0b97 8f00 set40 - - 0b98 11a0 0ba0 bloopi #0xa0, 0x0ba0 - 0b9a 197f lrri $AC1.M, @$AR3 - 0b9b 9930 asr16's $ACC1 : @$AR0, $AC0.M - 0b9c 1b1e srri @$AR0, $AC0.M - 0b9d 1b3f srri @$AR1, $AC1.M - 0b9e 7d29 neg's $ACC1 : @$AR1, $AC1.L - 0b9f 1b5f srri @$AR2, $AC1.M - 0ba0 1b5d srri @$AR2, $AC1.L - - 0ba1 8e00 set16 - - 0ba2 1fdb mrr $AC0.M, $AX1.H - 0ba3 1f99 mrr $AC0.L, $AX1.L - 0ba4 2ece srs @DSMAH, $AC0.M - 0ba5 2ccf srs @DSMAL, $AC0.L - 0ba6 16cd 0e80 si @DSPA, #0x0e80 - 0ba8 16c9 0001 si @DSCR, #0x0001 - 0baa 16cb 0100 si @DSBL, #0x0100 - - // 0bac 02bf 055c call 0x055c - WaitDMA(); - - 0bae 1c04 mrr $AR0, $IX0 - - // 0baf 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -void Cmd_10() { - 0bb1 8e00 set16 - - 0bb2 8100 clr $ACC0 - 0bb3 8970 clr'l $ACC1 : $AC0.M, @$AR0 - 0bb4 191c lrri $AC0.L, @$AR0 - - 0bb5 2ece srs @DSMAH, $AC0.M - 0bb6 2ccf srs @DSMAL, $AC0.L - 0bb7 16cd 07c0 si @DSPA, #0x07c0 - 0bb9 16c9 0001 si @DSCR, #0x0001 - 0bbb 16cb 0500 si @DSBL, #0x0500 - - // 0bbd 02bf 055c call 0x055c - WaitDMA(); - - 0bbf 8100 clr $ACC0 - 0bc0 8970 clr'l $ACC1 : $AC0.M, @$AR0 - 0bc1 191c lrri $AC0.L, @$AR0 - - 0bc2 2ece srs @DSMAH, $AC0.M - 0bc3 2ccf srs @DSMAL, $AC0.L - 0bc4 16cd 07c0 si @DSPA, #0x07c0 - 0bc6 16c9 0000 si @DSCR, #0x0000 - 0bc8 8900 clr $ACC1 - 0bc9 0d20 lris $AC1.L, #0x20 - 0bca 2dcb srs @DSBL, $AC1.L - - 0bcb 4c00 add $ACC0, $ACC1 - - 0bcc 1c80 mrr $IX0, $AR0 - - 0bcd 0080 07c0 lri $AR0, #0x07c0 - 0bcf 0083 0000 lri $AR3, #0x0000 - 0bd1 1c43 mrr $AR2, $AR3 - 0bd2 0a00 lris $AX0.H, #0x00 - - 0bd3 27c9 lrs $AC1.M, @DSCR - 0bd4 03a0 0004 andf $AC1.M, #0x0004 - 0bd6 029c 0bd3 jlnz 0x0bd3 - - 0bd8 2ece srs @DSMAH, $AC0.M - 0bd9 2ccf srs @DSMAL, $AC0.L - 0bda 16cd 07d0 si @DSPA, #0x07d0 - 0bdc 16c9 0000 si @DSCR, #0x0000 - 0bde 16cb 04e0 si @DSBL, #0x04e0 - - 0be0 8f00 set40 - - 0be1 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 0be2 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 0be3 6a00 movax $ACC0, $AX1 - 0be4 4800 addax $ACC0, $AX0 - 0be5 114f 0bee bloopi #0x4f, 0x0bee - 0be7 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 0be8 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 0be9 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M - 0bea 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L - 0beb 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 0bec 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 0bed 6a3a movax's $ACC0, $AX1.L : @$AR2, $AC1.M - 0bee 482a addax's $ACC0, $AX0.L : @$AR2, $AC1.L - - 0bef 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 0bf0 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 0bf1 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M - 0bf2 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L - 0bf3 1b5f srri @$AR2, $AC1.M - 0bf4 1b5d srri @$AR2, $AC1.L - 0bf5 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 0bf6 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 0bf7 6800 movax $ACC0, $AX0 - 0bf8 7c00 neg $ACC0 - 0bf9 4a00 addax $ACC0, $AX1 - 0bfa 114f 0c05 bloopi #0x4f, 0x0c05 - 0bfc 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 0bfd 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 0bfe 6932 movax's $ACC1, $AX0.L : @$AR2, $AC0.M - 0bff 7d00 neg $ACC1 - 0c00 4b22 addax's $ACC1, $AX1.L : @$AR2, $AC0.L - 0c01 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 0c02 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 0c03 683a movax's $ACC0, $AX0.L : @$AR2, $AC1.M - 0c04 7c00 neg $ACC0 - 0c05 4a2a addax's $ACC0, $AX1.L : @$AR2, $AC1.L - - 0c06 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 - 0c07 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 - 0c08 6932 movax's $ACC1, $AX0.L : @$AR2, $AC0.M - 0c09 7d00 neg $ACC1 - 0c0a 4b22 addax's $ACC1, $AX1.L : @$AR2, $AC0.L - 0c0b 1b5f srri @$AR2, $AC1.M - 0c0c 1b5d srri @$AR2, $AC1.L - - 0c0d 1c04 mrr $AR0, $IX0 - - // 0c0e 029f 0068 jmp 0x0068 - goto DoNextCommand; -} - -# Begin interrupt handlers - -// Sends mail with value on top of callstack and rti's -void ResetAndStackUOFlow_Handler() { - 0c10 8e00 set16 - - // 0c11 16fc ecc0 si @DMBH, #0xecc0 - // 0c13 1fcc mrr $AC0.M, $ST0 - // 0c14 1d9e mrr $ST0, $AC0.M - // 0c15 2efd srs @DMBL, $AC0.M - DMB = 0xecc00000 | $ST0 - - // 0c16 26fc lrs $AC0.M, @DMBH - // 0c17 02a0 8000 andf $AC0.M, #0x8000 - // 0c19 029c 0c16 jlnz 0x0c16 - while (@DMBH & 0x8000 == 0); - - // 0c1b 0000 nop - // 0c1c 0000 nop - // 0c1d 0000 nop - // 0c1e 02ff rti - return; -} - -// Saves/Restores whole ACC0, but only modifies AC0.M. strange -void Int2_Handler() { - 0c1f 8e00 set16 - - // Save ACC0 - 0c20 00f0 0e17 sr @0x0e17, $AC0.H - 0c22 00fe 0e18 sr @0x0e18, $AC0.M - 0c24 00fc 0e19 sr @0x0e19, $AC0.L - - // 0c26 1fcc mrr $AC0.M, $ST0 - // 0c27 1d9e mrr $ST0, $AC0.M - // 0c28 16fc feed si @DMBH, #0xfeed - // 0c2a 2efd srs @DMBL, $AC0.M - DMB = 0xfeed0000 | $ST0 - - // 0c2b 26fc lrs $AC0.M, @DMBH - // 0c2c 02a0 8000 andf $AC0.M, #0x8000 - // 0c2e 029c 0c2b jlnz 0x0c2b - while (@DMBH & 0x8000 == 0); - - // Restore ACC0 - 0c30 00d0 0e17 lr $AC0.H, @0x0e17 - 0c32 00de 0e18 lr $AC0.M, @0x0e18 - 0c34 00dc 0e19 lr $AC0.L, @0x0e19 - - // 0c36 0000 nop - // 0c37 0000 nop - // 0c38 0000 nop - // 0c39 0000 nop - // 0c3a 02ff rti - return; -} - -void Int3_Handler() { - 0c3b 8e00 set16 - - // Save AC0.L, AC0.M - 0c3c 1dbc mrr $ST1, $AC0.L - 0c3d 1dbe mrr $ST1, $AC0.M - - // 0c3e 8100 clr $ACC0 - // 0c3f 00de 0bb7 lr $AC0.M, @0x0bb7 - // 0c41 0601 cmpis $AC0.M, #0x01 - // 0c42 0295 0c47 jz 0x0c47 - // 0c44 0e00 lris $AC0.M, #0x00 - // 0c45 00fe 0b87 sr @0x0b87, $AC0.M - if (*0x0bb7 != 1) { // pb.addr != AXPBADDR_LOOP_ON - *0x0b87 = 0; // pb.state = AX_PB_STATE_STOP - } - - // Restore AC0.L, AC0.M - 0c47 1fcd mrr $AC0.M, $ST1 - 0c48 1f8d mrr $AC0.L, $ST1 - - // 0c49 02ff rti - return; -} - -void Int4_Handler() { - // 0c4a 0000 nop - // 0c4b 0000 nop - // 0c4c 0000 nop - // 0c4d 0000 nop - // 0c4e 0000 nop - // 0c4f 02ff rti - return; -} - -void Int5_Handler() { - 0c50 8e00 set16 - - // Save AC0.L, AC0.M - 0c51 1dbc mrr $ST1, $AC0.L - 0c52 1dbe mrr $ST1, $AC0.M - - // 0c53 8100 clr $ACC0 - // 0c54 00de 0bb7 lr $AC0.M, @0x0bb7 - // 0c56 0601 cmpis $AC0.M, #0x01 - // 0c57 0295 0c5f jz 0x0c5f - if (*0x0bb7 != 1) // pb.addr != AXPBADDR_LOOP_ON - { - // 0c59 0e00 lris $AC0.M, #0x00 - // 0c5a 00fe 0b87 sr @0x0b87, $AC0.M - *0x0b87 = 0; // pb.state = AX_PB_STATE_STOP - - // Restore AC0.L, AC0.M - 0c5c 1fcd mrr $AC0.M, $ST1 - 0c5d 1f8d mrr $AC0.L, $ST1 - - // 0c5e 02ff rti - return; - } - - // 0c5f 8100 clr $ACC0 - // 0c60 00de 0b88 lr $AC0.M, @0x0b88 - // 0c62 0601 cmpis $AC0.M, #0x01 - // 0c63 0295 0c71 jz 0x0c71 - if (*0x0b88 != 1) { // pb.type != AX_PB_TYPE_STREAM - - // 0c65 00de 0bda lr $AC0.M, @0x0bda - // 0c67 2eda srs @scale, $AC0.M - // 0c68 00de 0bdb lr $AC0.M, @0x0bdb - // 0c6a 2edb srs @yn1, $AC0.M - // 0c6b 00de 0bdc lr $AC0.M, @0x0bdc - // 0c6d 2edc srs @yn2, $AC0.M - @scale = pb.adpcmLoop.loop_pred_scale - @yn1 = pb.adpcmLoop.loop_yn1 - @yn2 = pb.adpcmLoop.loop_yn2 - - // Restore AC0.L, AC0.M - 0c6e 1fcd mrr $AC0.M, $ST1 - 0c6f 1f8d mrr $AC0.L, $ST1 - - // 0c70 02ff rti - return; - - } else { - - // 0c71 00de 0bda lr $AC0.M, @0x0bda - // 0c73 2eda srs @scale, $AC0.M - // 0c74 26db lrs $AC0.M, @yn1 - // 0c75 2edb srs @yn1, $AC0.M - // 0c76 26dc lrs $AC0.M, @yn2 - // 0c77 2edc srs @yn2, $AC0.M - @scale = pb.adpcmLoop.loop_pred_scale - // refresh @yn1, @yn2....why? - @yn1 = @yn1 - @yn2 = @yn2 - - // Well helllloooo there, padding - // 0c78 8100 clr $ACC0 - // 0c79 00dc 0bdd lr $AC0.L, @0x0bdd - // 0c7b 7600 inc $ACC0 - // 0c7c 00fc 0bdd sr @0x0bdd, $AC0.L - // 0c7e 8100 clr $ACC0 - pb.pad[0]++ - - // Restore AC0.L, AC0.M - 0c7f 1fcd mrr $AC0.M, $ST1 - 0c80 1f8d mrr $AC0.L, $ST1 - - // 0c81 02ff rti - return; - } -} - -void Int6_Handler() { - 0c82 0000 nop - 0c83 0000 nop - 0c84 0000 nop - 0c85 0000 nop - 0c86 0000 nop - 0c87 02ff rti -} - -void Int7_Handler() { - 0c88 0000 nop - 0c89 0000 nop - 0c8a 0000 nop - 0c8b 0000 nop - 0c8c 02ff rti -} - -# End of interrupt handlers - -// Jump table for the next function. -0c8d 0c9f // some kind of soft-reset for the UCode -0c8e 0ca2 // looks like code to dump the UCode memory for debugging -0c8f 0cda // rest the UCode and jump to ROM -0c90 0cdd // normal case to return to the main-loop - -// Called only from Task_Yield() -// Decides what to do next (this cmdblock is done) -void JumpThroughTable2() { - 0c91 8e00 set16 - 0c92 8100 clr $ACC0 - 0c93 8900 clr $ACC1 - - // 0c94 02bf 0ce0 call 0x0ce0 - WaitForCPUMail0(); - - // 0c96 27ff lrs $AC1.M, @CMBL - // 0c97 009e 0c8d lri $AC0.M, #0x0c8d - // 0c99 4c00 add $ACC0, $ACC1 - // 0c9a 1c7e mrr $AR3, $AC0.M - // 0c9b 0313 ilrr $AC1.M, @$AR3 - // 0c9c 1c7f mrr $AR3, $AC1.M - // 0c9d 176f jmpr $AR3 - switch(@CMBL) { - case 0: AX_ResumeTask(); break; - case 1: JumpTable2_1(); break; - case 2: IROM_Reset(); break; - case 3: AX_GetNextCmdBlock(); break; - } - 0c9e 0021 halt -} - -// case 0: -void AX_ResumeTask() { - 0c9f 029f 0030 jmp 0x0030 - 0ca1 0021 halt -} - -// case 1: -// funky...calls the mbox funcs, sometimes prefilling ACx regs... -// Perhaps DMAs some stuff and yields? -// Need to RE the ROM to figure this func out completely -void JumpTable2_1() { - // 0ca2 8100 clr $ACC0 - // 0ca3 8900 clr $ACC1 - // 0ca4 02bf 0ce0 call 0x0ce0 - WaitForCPUMail0(); - - // 0ca6 24ff lrs $AC0.L, @CMBL - // 0ca7 02bf 0ce6 call 0x0ce6 - WaitForCPUMail1(); - - // 0ca9 25ff lrs $AC1.L, @CMBL - // 0caa 02bf 0ce6 call 0x0ce6 - WaitForCPUMail1(); - - 0cac 27ff lrs $AC1.M, @CMBL - 0cad 2ece srs @DSMAH, $AC0.M - 0cae 2ccf srs @DSMAL, $AC0.L - 0caf 16c9 0001 si @DSCR, #0x0001 - 0cb1 2fcd srs @DSPA, $AC1.M - 0cb2 2dcb srs @DSBL, $AC1.L - - // 0cb3 8100 clr $ACC0 - // 0cb4 8900 clr $ACC1 - // 0cb5 02bf 0ce0 call 0x0ce0 - WaitForCPUMail0(); - - 0cb7 24ff lrs $AC0.L, @CMBL - 0cb8 1c9e mrr $IX0, $AC0.M - 0cb9 1cbc mrr $IX1, $AC0.L - 0cba 02bf 0ce6 call 0x0ce6 - WaitForCPUMail1(); - - 0cbc 25ff lrs $AC1.L, @CMBL - 0cbd 02bf 0ce6 call 0x0ce6 - WaitForCPUMail1(); - - 0cbf 27ff lrs $AC1.M, @CMBL - 0cc0 1cdf mrr $IX2, $AC1.M - 0cc1 1cfd mrr $IX3, $AC1.L - - // 0cc2 8100 clr $ACC0 - // 0cc3 02bf 0ce0 call 0x0ce0 - WaitForCPUMail0(); - - 0cc5 26ff lrs $AC0.M, @CMBL - 0cc6 1c1e mrr $AR0, $AC0.M - 0cc7 8900 clr $ACC1 - 0cc8 02bf 0ce6 call 0x0ce6 - WaitForCPUMail1(); - - 0cca 20ff lrs $AX0.L, @CMBL - 0ccb 1f5f mrr $AX0.H, $AC1.M - 0ccc 02bf 0ce0 call 0x0ce0 - WaitForCPUMail0(); - - 0cce 21ff lrs $AX1.L, @CMBL - 0ccf 02bf 0ce0 call 0x0ce0 - WaitForCPUMail0(); - - 0cd1 23ff lrs $AX1.H, @CMBL - - // 0cd2 26c9 lrs $AC0.M, @DSCR - // 0cd3 02a0 0004 andf $AC0.M, #0x0004 - // 0cd5 029c 0cd2 jlnz 0x0cd2 - while (@DSCR & 0x0004 != 0); // Wait for DMA to complete - - // 0cd7 029f 80b5 jmp 0x80b5 - // 0cd9 0021 halt - IROM_ErrorAndDie(); // Not sure...gotta RE the ROM -} - -// case 2: -void IROM_Reset() { - 0cda 029f 8000 jmp 0x8000 - 0cdc 0021 halt -} - -// case 3: -void AX_GetNextCmdBlock() { - // 0cdd 029f 0045 jmp 0x0045 - goto GetNextCmdBlock; - - 0cdf 0021 halt -} - -void WaitForCPUMail0() { - // 0ce0 26fe lrs $AC0.M, @CMBH - // 0ce1 02c0 8000 andcf $AC0.M, #0x8000 - // 0ce3 029c 0ce0 jlnz 0x0ce0 - while (@CMBH & 0x8000 == 0); - // 0ce5 02df ret - return; -} - -void WaitForCPUMail1() { - // 0ce6 27fe lrs $AC1.M, @CMBH - // 0ce7 03c0 8000 andcf $AC1.M, #0x8000 - // 0ce9 029c 0ce6 jlnz 0x0ce6 - while (@CMBH & 0x8000 == 0); - // 0ceb 02df ret - return; -} - -0cec 0000 nop -0ced 0000 nop -0cee 0000 nop -0cef 0000 nop diff -Nru dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_AX_DD7E72D5.txt dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_AX_DD7E72D5.txt --- dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_AX_DD7E72D5.txt 1970-01-01 01:00:00.000000000 +0100 +++ dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_AX_DD7E72D5.txt 2010-08-18 03:25:25.000000000 +0100 @@ -0,0 +1,3467 @@ +// This document was previously called "DSP_UC_AX1.txt" and "Crazy Taxi.txt" +// CR is set to #FF all the time in this ucode, so srs/lrs always operate on hw registers. + +////////////////////////////////////////////////////////////////////////// +// Known addresses in DRAM +Addr Name Description/Notes + +// Buffers +0x0000 Main Right +0x0140 Main Left +0x0280 +0x0400 +0x0540 +0x0680 +0x07c0 +0x0900 +0x0a40 + +0x03c0 update_block Contains pairs to update current PB with + +0x0b80 pb Current pb, length = 0xc0 + +0x0e04 ms_remaining Milliseconds remaining to process for current voice +0x0e05 pUpdate_block Pointer to update_block +0x0e06 pUpdates_this_ms Pointer to number of updates + +// Pointers to buffers +0x0e08 0x0000 See buffers at 0x0000 +0x0e09 0x0140 +0x0e0a 0x0280 +0x0e0b 0x0400 +0x0e0c 0x0540 +0x0e0d 0x0680 +0x0e0e 0x07c0 +0x0e0f 0x0900 +0x0e10 0x0a40 + +// Func pointers +0x0e14 selectedMixCtrl +0x0e15 selectedSRC +0x0e16 selectedCoef Points into DROM + +// ITD +0x0e40 +0x0e41 +0x0e42 +0x0e43 +////////////////////////////////////////////////////////////////////////// + +// Good ol' exception table +0000 0000 nop +0001 0000 nop // 0 Reset falls through, kinda wierd... +0002 029f 0c10 jmp 0x0c10 // 1 Stack U/O flow +0004 029f 0c1f jmp 0x0c1f // 2 +0006 029f 0c3b jmp 0x0c3b // 3 +0008 029f 0c4a jmp 0x0c4a // 4 ? empty +000a 029f 0c50 jmp 0x0c50 // 5 accelerator address overflow +000c 029f 0c82 jmp 0x0c82 // 6 ? empty +000e 029f 0c88 jmp 0x0c88 // 7 ? empty + +// Entry point +void Task_Init() { + // AX operates in this context all the time + // 0010 1302 sbset #0x02 + // 0011 1303 sbset #0x03 + // 0012 1204 sbclr #0x04 + // 0013 1305 sbset #0x05 + // 0014 1306 sbset #0x06 + // 0015 8e00 set16 + // 0016 8c00 clr15 + // 0017 8b00 m0 + // 0018 0092 00ff lri $CR, #0x00ff + + // 001a 8100 clr $ACC0 + // 001b 8900 clr $ACC1 + // 001c 009e 0e80 lri $AC0.M, #0x0e80 + // 001e 00fe 0e1b sr @0x0e1b, $AC0.M + // 0020 8100 clr $ACC0 + // 0021 00fe 0e31 sr @0x0e31, $AC0.M + ACC0 = ACC1 = 0 + *0x0e1b = 0xe80 // Used in Cmd8 + *0x0e31 = 0 + + // Send DSP_INIT mail + // 0023 16fc dcd1 si @DMBH, #0xdcd1 + // 0025 16fd 0000 si @DMBL, #0x0000 + // 0027 16fb 0001 si @DIRQ, #0x0001 + DMB = 0xdcd10000 + // 0029 26fc lrs $AC0.M, @DMBH + // 002a 02a0 8000 andf $AC0.M, #0x8000 + // 002c 029c 0029 jlnz 0x0029 + while (@DMBH & 0x8000 == 0); + + // 002e 029f 0045 jmp 0x0045 + goto GetNextCmdBlock; +} + +void Task_Resume() { + // Ensure sane context + // 0030 1302 sbset #0x02 + // 0031 1303 sbset #0x03 + // 0032 1204 sbclr #0x04 + // 0033 1305 sbset #0x05 + // 0034 1306 sbset #0x06 + // 0035 8e00 set16 + // 0036 8c00 clr15 + // 0037 8b00 m0 + // 0038 0092 00ff lri $CR, #0x00ff + + // Send DSP_RESUME mail + // 003a 16fc dcd1 si @DMBH, #0xdcd1 + // 003c 16fd 0001 si @DMBL, #0x0001 + // 003e 16fb 0001 si @DIRQ, #0x0001 + DMB = 0xdcd10001 + // 0040 26fc lrs $AC0.M, @DMBH + // 0041 02a0 8000 andf $AC0.M, #0x8000 + // 0043 029c 0040 jlnz 0x0040 + while (@DMBH & 0x8000 == 0); + +GetNextCmdBlock: + 0045 8e00 set16 + 0046 8100 clr $ACC0 + 0047 8900 clr $ACC1 + 0048 009f babe lri $AC1.M, #0xbabe + + // Wait for 0xbabexxxx mail from cpu + do { + // 004a 26fe lrs $AC0.M, @CMBH + // 004b 02c0 8000 andcf $AC0.M, #0x8000 + // 004d 029c 004a jlnz 0x004a + while (@CMBH & 0x8000 == 0); + + // 004f 8200 cmp + // 0050 0294 004a jnz 0x004a + } while (@CMBH != 0xbabe); + + // Save the low 16bits of the mail + // 0052 23ff lrs $AX1.H, @CMBL + u16 length = @CMBL + + // Get next mail + // 0053 8100 clr $ACC0 + // 0054 26fe lrs $AC0.M, @CMBH + // 0055 02c0 8000 andcf $AC0.M, #0x8000 + // 0057 029c 0054 jlnz 0x0054 + while (@CMBH & 0x8000 == 0); + + // 0059 27ff lrs $AC1.M, @CMBL + // 005a 0240 7fff andi $AC0.M, #0x7fff + // 005c 2ece srs @DSMAH, $AC0.M + // 005d 2fcf srs @DSMAL, $AC1.M + // 005e 16cd 0c00 si @DSPA, #0x0c00 + // 0060 8100 clr $ACC0 + // 0061 2ec9 srs @DSCR, $AC0.M + // 0062 1ffb mrr $AC1.M, $AX1.H + // 0063 2fcb srs @DSBL, $AC1.M + // DMA in the CmdBlock + static u16* CmdBlockBuf = 0x0c00 + DSMA = (@CMBH & ~0x8000) << 16 | @CMBL + DSPA = CmdBlockBuf + DSCR = 0 // CPU -> DMEM + DSBL = length + + // 0064 02bf 055c call 0x055c + WaitDMA(); + + // Init the CmdBlock pointer + 0066 0080 0c00 lri $AR0, #0x0c00 + +DoNextCommand: + // 0068 8e00 set16 + // 0069 8100 clr $ACC0 + // 006a 8970 clr'l $ACC1 : $AC0.M, @$AR0 + // 006b b100 tst $ACC0 + // 006c 0291 007e jl 0x007e + u16 Cmd = *(CmdBlockBuf++) + if (Cmd < 0) // How could this be possible? 'l is 16bit load... + Die_InvalidCmd(); + + // 006e 0a12 lris $AX0.H, #0x12 + // 006f c100 cmpar $ACC0, $AX0.H + // 0070 0292 007e jg 0x007e + if (Cmd > 0x12) + Die_InvalidCmd(); + + // 0072 009f 0aff lri $AC1.M, #0x0aff + // 0074 4c00 add $ACC0, $ACC1 + // 0075 1c7e mrr $AR3, $AC0.M + // 0076 0213 ilrr $AC0.M, @$AR3 + // 0077 1c7e mrr $AR3, $AC0.M + // 0078 176f jmpr $AR3 + switch (Cmd) { + case 0: Cmd_0(); break; // 0082 + case 1: Cmd_1(); break; // 013e + case 2: Cmd_2(); break; // 01bc + case 3: Cmd_3(); break; // 0248 + case 4: Cmd_4(); break; // 0413 + case 5: Cmd_5(); break; // 0427 + case 6: Cmd_6(); break; // 0165 + case 7: Cmd_7(); break; // 0574 + case 8: Cmd_8(); break; // 0b37 + case 9: Cmd_9(); break; // 015f + case 0xa: Cmd_a(); break; // 0478 + case 0xb: Cmd_b(); break; // 0474 + case 0xc: Cmd_c(); break; // 0476 + case 0xd: Cmd_d(); break; // 01a9 + case 0xe: Cmd_e(); break; // 043b + case 0xf: Cmd_f(); break; // 047a + case 0x10: Cmd_10(); break; // 0bb1 + case 0x11: Cmd_11(); break; // 0175 + } + + // Somehow we've passed the cmd proccessor; DIE!! + // 0079 16fc fbad si @DMBH, #0xfbad + // 007b 16fd 8080 si @DMBL, #0x8080 + DMB = 0xfbad8080 + 007d 0021 halt +} + +// Die and conveniently tell the cpu which cmd was baad +void Die_InvalidCmd() { + 007e 16fc baad si @DMBH, #0xbaad + 0080 2efd srs @DMBL, $AC0.M + 0081 0021 halt +} + +// Executes the same operation 3 times on buffers: (0, 0x0400, 0x07c0) +void Cmd_0() { + // 0082 8100 clr $ACC0 + // 0083 8970 clr'l $ACC1 : $AC0.M, @$AR0 + // 0084 8e78 set16'l : $AC1.M, @$AR0 + u16 maddrh = *(CmdBlockBuf++) + u16 maddrl = *(CmdBlockBuf++) + + // 0085 2ece srs @DSMAH, $AC0.M + // 0086 2fcf srs @DSMAL, $AC1.M + // 0087 009e 0e44 lri $AC0.M, #0x0e44 + // 0089 2ecd srs @DSPA, $AC0.M + // 008a 0e00 lris $AC0.M, #0x00 + // 008b 2ec9 srs @DSCR, $AC0.M + // 008c 009e 0040 lri $AC0.M, #0x0040 + // 008e 2ecb srs @DSBL, $AC0.M + + // DMA 0x0040bytes to DRAM @ 0x0e44 from CPU @ maddr + + 008f 0081 0e44 lri $AR1, #0x0e44 // source + 0091 0082 0000 lri $AR2, #0x0000 // destination + + 0093 009b 009f lri $AX1.H, #0x009f + 0095 009a 0140 lri $AX0.H, #0x0140 // loop length if !ACC0 + + 0097 8100 clr $ACC0 + 0098 8900 clr $ACC1 + + 0099 8f00 set40 + + // 009a 02bf 055c call 0x055c + WaitDMA(); + + 009c 193e lrri $AC0.M, @$AR1 + 009d 193c lrri $AC0.L, @$AR1 + 009e b100 tst $ACC0 + 009f 193f lrri $AC1.M, @$AR1 // added to ACC0 in confusing ways + // 00a0 0294 00a6 jnz 0x00a6 + if (!$ACC0) { + 00a2 005a loop $AX0.H + 00a3 1b5e srri @$AR2, $AC0.M + + // 00a4 029f 00ae jmp 0x00ae + } else { + 00a6 9900 asr16 $ACC1 + 00a7 1b5e srri @$AR2, $AC0.M + 00a8 1b5c srri @$AR2, $AC0.L + 00a9 007b 00ad bloop $AX1.H, 0x00ad + 00ab 4c00 add $ACC0, $ACC1 + 00ac 1b5e srri @$AR2, $AC0.M + 00ad 1b5c srri @$AR2, $AC0.L + + } + + // same code block as above...epic fail? + 00ae 193e lrri $AC0.M, @$AR1 + 00af 193c lrri $AC0.L, @$AR1 + 00b0 b100 tst $ACC0 + 00b1 193f lrri $AC1.M, @$AR1 + // 00b2 0294 00b8 jnz 0x00b8 + if (!$ACC0) { + 00b4 005a loop $AX0.H + 00b5 1b5e srri @$AR2, $AC0.M + + // 00b6 029f 00c0 jmp 0x00c0 + } else { + 00b8 9900 asr16 $ACC1 + 00b9 1b5e srri @$AR2, $AC0.M + 00ba 1b5c srri @$AR2, $AC0.L + 00bb 007b 00bf bloop $AX1.H, 0x00bf + 00bd 4c00 add $ACC0, $ACC1 + 00be 1b5e srri @$AR2, $AC0.M + 00bf 1b5c srri @$AR2, $AC0.L + + } + + // ...and again! wtf + 00c0 193e lrri $AC0.M, @$AR1 + 00c1 193c lrri $AC0.L, @$AR1 + 00c2 b100 tst $ACC0 + 00c3 193f lrri $AC1.M, @$AR1 + // 00c4 0294 00ca jnz 0x00ca + if (!$ACC0) { + 00c6 005a loop $AX0.H + 00c7 1b5e srri @$AR2, $AC0.M + + // 00c8 029f 00d2 jmp 0x00d2 + } else { + 00ca 9900 asr16 $ACC1 + 00cb 1b5e srri @$AR2, $AC0.M + 00cc 1b5c srri @$AR2, $AC0.L + 00cd 007b 00d1 bloop $AX1.H, 0x00d1 + 00cf 4c00 add $ACC0, $ACC1 + 00d0 1b5e srri @$AR2, $AC0.M + 00d1 1b5c srri @$AR2, $AC0.L + + } + + // set to next buffer + 00d2 0082 0400 lri $AR2, #0x0400 + + // same code block, uses tst'l in one place...otherwise the same + 00d4 193e lrri $AC0.M, @$AR1 + 00d5 193c lrri $AC0.L, @$AR1 + 00d6 b179 tst'l $ACC0 : $AC1.M, @$AR1 + // 00d7 0294 00dd jnz 0x00dd + if (!$ACC0) { + 00d9 005a loop $AX0.H + 00da 1b5e srri @$AR2, $AC0.M + // 00db 029f 00e5 jmp 0x00e5 + } else { + 00dd 9900 asr16 $ACC1 + 00de 1b5e srri @$AR2, $AC0.M + 00df 1b5c srri @$AR2, $AC0.L + 00e0 007b 00e4 bloop $AX1.H, 0x00e4 + 00e2 4c00 add $ACC0, $ACC1 + 00e3 1b5e srri @$AR2, $AC0.M + 00e4 1b5c srri @$AR2, $AC0.L + } + + // same code block, using tst'l again...wonder if it actually changes behavior? + 00e5 193e lrri $AC0.M, @$AR1 + 00e6 193c lrri $AC0.L, @$AR1 + 00e7 b179 tst'l $ACC0 : $AC1.M, @$AR1 + // 00e8 0294 00ee jnz 0x00ee + if (!$ACC0) { + 00ea 005a loop $AX0.H + 00eb 1b5e srri @$AR2, $AC0.M + // 00ec 029f 00f6 jmp 0x00f6 + } else { + 00ee 9900 asr16 $ACC1 + 00ef 1b5e srri @$AR2, $AC0.M + 00f0 1b5c srri @$AR2, $AC0.L + 00f1 007b 00f5 bloop $AX1.H, 0x00f5 + 00f3 4c00 add $ACC0, $ACC1 + 00f4 1b5e srri @$AR2, $AC0.M + 00f5 1b5c srri @$AR2, $AC0.L + } + + // see comments above + 00f6 193e lrri $AC0.M, @$AR1 + 00f7 193c lrri $AC0.L, @$AR1 + 00f8 b179 tst'l $ACC0 : $AC1.M, @$AR1 + // 00f9 0294 00ff jnz 0x00ff + if (!$ACC0) { + 00fb 005a loop $AX0.H + 00fc 1b5e srri @$AR2, $AC0.M + // 00fd 029f 0107 jmp 0x0107 + } else { + 00ff 9900 asr16 $ACC1 + 0100 1b5e srri @$AR2, $AC0.M + 0101 1b5c srri @$AR2, $AC0.L + 0102 007b 0106 bloop $AX1.H, 0x0106 + 0104 4c00 add $ACC0, $ACC1 + 0105 1b5e srri @$AR2, $AC0.M + 0106 1b5c srri @$AR2, $AC0.L + } + + // set to next buffer + 0107 0082 07c0 lri $AR2, #0x07c0 + + // see comments above + 0109 193e lrri $AC0.M, @$AR1 + 010a 193c lrri $AC0.L, @$AR1 + 010b b179 tst'l $ACC0 : $AC1.M, @$AR1 + // 010c 0294 0112 jnz 0x0112 + if (!$ACC0) { + 010e 005a loop $AX0.H + 010f 1b5e srri @$AR2, $AC0.M + // 0110 029f 011a jmp 0x011a + } else { + 0112 9900 asr16 $ACC1 + 0113 1b5e srri @$AR2, $AC0.M + 0114 1b5c srri @$AR2, $AC0.L + 0115 007b 0119 bloop $AX1.H, 0x0119 + 0117 4c00 add $ACC0, $ACC1 + 0118 1b5e srri @$AR2, $AC0.M + 0119 1b5c srri @$AR2, $AC0.L + } + + // see comments above + 011a 193e lrri $AC0.M, @$AR1 + 011b 193c lrri $AC0.L, @$AR1 + 011c b179 tst'l $ACC0 : $AC1.M, @$AR1 + // 011d 0294 0123 jnz 0x0123 + if (!$ACC0) { + 011f 005a loop $AX0.H + 0120 1b5e srri @$AR2, $AC0.M + // 0121 029f 012b jmp 0x012b + } else { + 0123 9900 asr16 $ACC1 + 0124 1b5e srri @$AR2, $AC0.M + 0125 1b5c srri @$AR2, $AC0.L + 0126 007b 012a bloop $AX1.H, 0x012a + 0128 4c00 add $ACC0, $ACC1 + 0129 1b5e srri @$AR2, $AC0.M + 012a 1b5c srri @$AR2, $AC0.L + } + + // see comments above + 012b 193e lrri $AC0.M, @$AR1 + 012c 193c lrri $AC0.L, @$AR1 + 012d b179 tst'l $ACC0 : $AC1.M, @$AR1 + // 012e 0294 0134 jnz 0x0134 + if (!$ACC0) { + 0130 005a loop $AX0.H + 0131 1b5e srri @$AR2, $AC0.M + // 0132 029f 013c jmp 0x013c + } else { + 0134 9900 asr16 $ACC1 + 0135 1b5e srri @$AR2, $AC0.M + 0136 1b5c srri @$AR2, $AC0.L + 0137 007b 013b bloop $AX1.H, 0x013b + 0139 4c00 add $ACC0, $ACC1 + 013a 1b5e srri @$AR2, $AC0.M + 013b 1b5c srri @$AR2, $AC0.L + } + + // 013c 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void Cmd_1() { + 013e 0085 ffff lri $IX1, #0xffff // -1 + + // 0140 8150 clr'l $ACC0 : $AX0.H, @$AR0 + // 0141 8940 clr'l $ACC1 : $AX0.L, @$AR0 + // 0142 8e48 set16'l : $AX1.L, @$AR0 + // 0143 00fa 0e17 sr @0x0e17, $AX0.H + // 0145 00f8 0e18 sr @0x0e18, $AX0.L + // 0147 0081 0000 lri $AR1, #0x0000 + // 0149 02bf 04f1 call 0x04f1 + u16 maddrh = *(CmdBlockBuf++) + u16 maddrl = *(CmdBlockBuf++) + u16 unkForMulBuffer1 = *(CmdBlockBuf++) + u16 unkForMulBuffer2 = 0 // a buffer in dram + Unk(maddrh << 16 | maddrl, unkForMulBuffer1, unkForMulBuffer2) + + // 014b 00da 0e17 lr $AX0.H, @0x0e17 + // 014d 00d8 0e18 lr $AX0.L, @0x0e18 + // 014f 8948 clr'l $ACC1 : $AX1.L, @$AR0 + // 0150 0081 0400 lri $AR1, #0x0400 + // 0152 02bf 04f1 call 0x04f1 + unkForMulBuffer1 = *(CmdBlockBuf++) + unkForMulBuffer2 = 0x0400 + Unk(maddrh << 16 | maddrl, unkForMulBuffer1, unkForMulBuffer2) + + // 0154 00da 0e17 lr $AX0.H, @0x0e17 + // 0156 00d8 0e18 lr $AX0.L, @0x0e18 + // 0158 8948 clr'l $ACC1 : $AX1.L, @$AR0 + // 0159 0081 07c0 lri $AR1, #0x07c0 + // 015b 02bf 04f1 call 0x04f1 + unkForMulBuffer1 = *(CmdBlockBuf++) + unkForMulBuffer2 = 0x07c0 + Unk(maddrh << 16 | maddrl, unkForMulBuffer1, unkForMulBuffer2) + + // 015d 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void Cmd_9() { + 015f 0086 07c0 lri $IX2, #0x07c0 // often used buffer in dram + + 0161 02bf 0484 call 0x0484 + + // 0163 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void Cmd_6() { + 0165 8100 clr $ACC0 + 0166 8e00 set16 + + // 0167 191e lrri $AC0.M, @$AR0 + // 0168 191c lrri $AC0.L, @$AR0 + u16 maddrh = *(CmdBlockBuf++) + u16 maddrl = *(CmdBlockBuf++) + + // 0169 2ece srs @DSMAH, $AC0.M + // 016a 2ccf srs @DSMAL, $AC0.L + // 016b 16cd 0000 si @DSPA, #0x0000 + // 016d 16c9 0001 si @DSCR, #0x0001 + // 016f 16cb 0780 si @DSBL, #0x0780 + + // DMA 0x780bytes to CPU @ maddr from DMEM @ 0 + + // 0171 02bf 055c call 0x055c + WaitDMA(); + + // 0173 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void Cmd_11() { + // 0175 8100 clr $ACC0 + // 0176 8970 clr'l $ACC1 : $AC0.M, @$AR0 + // 0177 8e60 set16'l : $AC0.L, @$AR0 + u16 maddrh = *(CmdBlockBuf++) + u16 maddrl = *(CmdBlockBuf++) + + // 0178 2ece srs @DSMAH, $AC0.M + // 0179 2ccf srs @DSMAL, $AC0.L + // 017a 16cd 0e44 si @DSPA, #0x0e44 + // 017c 16c9 0000 si @DSCR, #0x0000 + // 017e 8900 clr $ACC1 + // 017f 0d20 lris $AC1.L, #0x20 + // 0180 2dcb srs @DSBL, $AC1.L + + // DMA 0x20bytes to DRAM @ 0x0e44 from CPU @ maddr + + u16 length_of_0e44 = 0x20 + + // 0181 4c00 add $ACC0, $ACC1 + maddr += length_of_0e44 + + // Save CmdBlockBuf + // 0182 1c80 mrr $IX0, $AR0 + + // 0183 0080 0280 lri $AR0, #0x0280 + // 0185 0081 0000 lri $AR1, #0x0000 + // 0187 0082 0140 lri $AR2, #0x0140 + // 0189 0083 0e44 lri $AR3, #0x0e44 + // 018b 0a00 lris $AX0.H, #0x00 + + // 018c 27c9 lrs $AC1.M, @DSCR + // 018d 03a0 0004 andf $AC1.M, #0x0004 + // 018f 029c 018c jlnz 0x018c + while (@DSCR & 4); + + // 0191 2ece srs @DSMAH, $AC0.M + // 0192 2ccf srs @DSMAL, $AC0.L + // 0193 16cd 0e54 si @DSPA, #0x0e54 + // 0195 16c9 0000 si @DSCR, #0x0000 + // 0197 16cb 0260 si @DSBL, #0x0260 + + // DMA 0x0260bytes to DRAM @ 0x0e54 from CPU @ maddr + + // 0199 009f 00a0 lri $AC1.M, #0x00a0 + // 019b 8f00 set40 + // 019c 007f 01a5 bloop $AC1.M, 0x01a5 + // 019e 197e lrri $AC0.M, @$AR3 + // 019f 1b1a srri @$AR0, $AX0.H + // 01a0 197c lrri $AC0.L, @$AR3 + // 01a1 1b1a srri @$AR0, $AX0.H + // 01a2 1b5e srri @$AR2, $AC0.M + // 01a3 7c22 neg's $ACC0 : @$AR2, $AC0.L + // 01a4 1b3e srri @$AR1, $AC0.M + // 01a5 1b3c srri @$AR1, $AC0.L + + // high reg will only be sign bits, and it's never stored, so we can use s32 here + s32* buffer_source = 0x0e44 + s32* buffer_dest = 0x0140 + s32* buffer_to_zero = 0x0280 + s32* buffer_dest_neg = 0x0000 + for (i = 0x00a0; i > 0; i--) { + s32 thing = *(buffer_source++) + *(buffer_to_zero++) = 0 + *(buffer_dest++) = thing + *(buffer_dest_neg++) = ~thing + } + + // Restore CmdBlockBuf + 01a6 1c04 mrr $AR0, $IX0 + + // 01a7 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +// Interesting, DMAs in new CmdBlock and starts executing it +void Cmd_D() { + // 01a9 8e70 set16'l : $AC0.M, @$AR0 + // 01aa 8960 clr'l $ACC1 : $AC0.L, @$AR0 + u16 maddrh = *(CmdBlockBuf++) + u16 maddrl = *(CmdBlockBuf++) + + // 01ab 191f lrri $AC1.M, @$AR0 + u16 numbytes = *(CmdBlockBuf++) + + // 01ac 2ece srs @DSMAH, $AC0.M + // 01ad 2ccf srs @DSMAL, $AC0.L + // 01ae 16cd 0c00 si @DSPA, #0x0c00 + // 01b0 16c9 0000 si @DSCR, #0x0000 + // 01b2 0503 addis $AC1.M, #0x03 + // 01b3 0340 fff0 andi $AC1.M, #0xfff0 + // 01b5 2fcb srs @DSBL, $AC1.M + + // DMA ((numbytes + 3) & 0xfff0)bytes to DMEM @ 0x0c00 from CPU @ maddr + + // 01b6 02bf 055c call 0x055c + WaitDMA(); + + // 01b8 0080 0c00 lri $AR0, #0x0c00 + CmdBlockBuf = 0x0c00 + + // 01ba 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +// DMAs in a new PB and inits values (itd, func pointers, etc) +// DMAs in new update_block, but doesn't apply it +void Cmd_2() { + 01bc 8100 clr $ACC0 + + // 01bd 8970 clr'l $ACC1 : $AC0.M, @$AR0 + // 01be 8e78 set16'l : $AC1.M, @$AR0 + u16 maddrh = *(CmdBlockBuf++) + u16 maddrl = *(CmdBlockBuf++) + + // 01bf 2ece srs @DSMAH, $AC0.M + // 01c0 2fcf srs @DSMAL, $AC1.M + // 01c1 16cd 0b80 si @DSPA, #0x0b80 + // 01c3 16c9 0000 si @DSCR, #0x0000 + // 01c5 16cb 00c0 si @DSBL, #0x00c0 + + // DMA 0x00c0bytes to DMEM @ 0x0b80 from CPU @ maddr + + // 01c7 0082 0e08 lri $AR2, #0x0e08 + // 01c9 009f 0000 lri $AC1.M, #0x0000 + // 01cb 1b5f srri @$AR2, $AC1.M + // 01cc 009f 0140 lri $AC1.M, #0x0140 + // 01ce 1b5f srri @$AR2, $AC1.M + // 01cf 009f 0280 lri $AC1.M, #0x0280 + // 01d1 1b5f srri @$AR2, $AC1.M + // 01d2 009f 0400 lri $AC1.M, #0x0400 + // 01d4 1b5f srri @$AR2, $AC1.M + // 01d5 009f 0540 lri $AC1.M, #0x0540 + // 01d7 1b5f srri @$AR2, $AC1.M + // 01d8 009f 0680 lri $AC1.M, #0x0680 + // 01da 1b5f srri @$AR2, $AC1.M + // 01db 009f 07c0 lri $AC1.M, #0x07c0 + // 01dd 1b5f srri @$AR2, $AC1.M + // 01de 009f 0900 lri $AC1.M, #0x0900 + // 01e0 1b5f srri @$AR2, $AC1.M + // 01e1 009f 0a40 lri $AC1.M, #0x0a40 + // 01e3 1b5f srri @$AR2, $AC1.M + *0x0e08 = 0x0000 + *0x0e09 = 0x0140 + *0x0e0a = 0x0280 + *0x0e0b = 0x0400 + *0x0e0c = 0x0540 + *0x0e0d = 0x0680 + *0x0e0e = 0x07c0 + *0x0e0f = 0x0900 + *0x0e10 = 0x0a40 + + // 01e4 02bf 055c call 0x055c + WaitDMA(); + + // 01e6 00de 0ba7 lr $AC0.M, @0x0ba7 + // 01e8 00df 0ba8 lr $AC1.M, @0x0ba8 + // 01ea 2ece srs @DSMAH, $AC0.M + // 01eb 2fcf srs @DSMAL, $AC1.M + // 01ec 16cd 03c0 si @DSPA, #0x03c0 + // 01ee 16c9 0000 si @DSCR, #0x0000 + // 01f0 16cb 0080 si @DSBL, #0x0080 + + // DMA 0x80bytes from CPU @ ((pb.update.dataHi << 16) | pb.update.dataLo) to DRAM @ 0x03c0 + + // 01f2 8100 clr $ACC0 + // 01f3 8900 clr $ACC1 + + // 01f4 00de 0b84 lr $AC0.M, @0x0b84 + // 01f6 009f 0b31 lri $AC1.M, #0x0b31 + // 01f8 4c00 add $ACC0, $ACC1 + // 01f9 1c7e mrr $AR3, $AC0.M + // 01fa 0213 ilrr $AC0.M, @$AR3 + // 01fb 00fe 0e15 sr @0x0e15, $AC0.M + *0x0e15 = *(0x0b31 + pb.srcSelect) // func ptr for src + + // 01fd 00de 0b85 lr $AC0.M, @0x0b85 + // 01ff 009f 0b34 lri $AC1.M, #0x0b34 + // 0201 4c00 add $ACC0, $ACC1 + // 0202 1c7e mrr $AR3, $AC0.M + // 0203 0213 ilrr $AC0.M, @$AR3 + // 0204 00fe 0e16 sr @0x0e16, $AC0.M + *0x0e16 = *(0x0b34 + pb.coefSelect) // ptr to coef table + + // 0206 00de 0b86 lr $AC0.M, @0x0b86 + // 0208 009f 0b11 lri $AC1.M, #0x0b11 + // 020a 4c00 add $ACC0, $ACC1 + // 020b 1c7e mrr $AR3, $AC0.M + // 020c 0213 ilrr $AC0.M, @$AR3 + // 020d 00fe 0e14 sr @0x0e14, $AC0.M + *0x0e14 = *(0x0b11 + pb.mixerCtrl) // func ptr for mixer + + // 020f 8100 clr $ACC0 + // 0210 00de 0b9b lr $AC0.M, @0x0b9b + // 0212 b100 tst $ACC0 + // 0213 0295 023a jz 0x023a + if (pb.itd.flag != AX_PB_ITD_OFF) { + // 0215 8900 clr $ACC1 + // 0216 00df 0b9e lr $AC1.M, @0x0b9e + // 0218 0300 0cc0 addi $AC1.M, #0x0cc0 + // 021a 00ff 0e40 sr @0x0e40, $AC1.M + *0x0e40 = 0x0cc0 + pb.itd.shiftL + + // 021c 00df 0b9f lr $AC1.M, @0x0b9f + // 021e 0300 0cc0 addi $AC1.M, #0x0cc0 + // 0220 00ff 0e41 sr @0x0e41, $AC1.M + *0x0e41 = 0x0cc0 + pb.itd.shiftR + + // 0222 009f 0ce0 lri $AC1.M, #0x0ce0 + // 0224 00ff 0e42 sr @0x0e42, $AC1.M + // 0226 00ff 0e43 sr @0x0e43, $AC1.M + *0x0e42 = 0x0ce0 + *0x0e43 = 0x0ce0 + + // 0228 02bf 055c call 0x055c + WaitDMA(); + + // 022a 00de 0b9c lr $AC0.M, @0x0b9c + // 022c 2ece srs @DSMAH, $AC0.M + // 022d 00de 0b9d lr $AC0.M, @0x0b9d + // 022f 2ecf srs @DSMAL, $AC0.M + // 0230 16cd 0cc0 si @DSPA, #0x0cc0 + // 0232 16c9 0000 si @DSCR, #0x0000 + // 0234 16cb 0040 si @DSBL, #0x0040 + + // DMA 0x0040bytes to DMEM @ 0x0cc0 from CPU @ (pb.itd.bufferHi << 16) | pb.itd.bufferLo + + // 0236 02bf 055c call 0x055c + WaitDMA(); + + // 0238 029f 0068 jmp 0x0068 + goto DoNextCommand; + + } else { + + // 023a 009f 0ce0 lri $AC1.M, #0x0ce0 + // 023c 00ff 0e42 sr @0x0e42, $AC1.M + // 023e 00ff 0e40 sr @0x0e40, $AC1.M + // 0240 00ff 0e41 sr @0x0e41, $AC1.M + // 0242 00ff 0e43 sr @0x0e43, $AC1.M + *0x0e42 = 0x0ce0 + *0x0e40 = 0x0ce0 + *0x0e41 = 0x0ce0 + *0x0e43 = 0x0ce0 + + // 0244 02bf 055c call 0x055c + WaitDMA(); + + // 0246 029f 0068 jmp 0x0068 + goto DoNextCommand; + } +} + +// Function calls itself until there are no more linked PBs +void Cmd_3() { + 0248 8e00 set16 + + // Save CmdBlockBuf ptr + 0249 00e0 0e07 sr @0x0e07, $AR0 + + // Processes pb.update.updNum[0] to pb.update.updNum[5] + // Applies specified number of updates for every millisecond of voice frame (5 millisecs) + // first millisec's updates are ignored <- not proven, yet + + // 024b 0080 0ba2 lri $AR0, #0x0ba2 // pb.update.updNum[0] + // 024d 0081 03c0 lri $AR1, #0x03c0 + // 024f 0e05 lris $AC0.M, #0x05 + // 0250 00fe 0e04 sr @0x0e04, $AC0.M // counter to decrement + // 0252 8900 clr $ACC1 + u16* pUpdates_this_ms = 0x0ba2 + u16* pUpdate_block = 0x03c0 + u16 ms_remaining = 5 + +NextMillisecUpd: + // 0253 8150 clr'l $ACC0 : $AX0.H, @$AR0 + // 0254 009f 0b80 lri $AC1.M, #0x0b80 + // 0256 007a 025b bloop $AX0.H, 0x025b + // 0258 193e lrri $AC0.M, @$AR1 + // 0259 4c49 add'l $ACC0, $ACC1 : $AX1.L, @$AR1 + // 025a 1c5e mrr $AR2, $AC0.M + // 025b 1a59 srr @$AR2, $AX1.L // AR2 isn't changed till updates are done + + // Write updates from update_block to pb in dram + for (int i = 0; i < *pUpdates_this_ms; i+=2) { + // Looks like 0x03c0 is a struct of pairs to write into PB + *(0x0b80 + *(pUpdate_block + i)) = *(pUpdate_block + i + 1) + } + pUpdates_this_ms++ + + // 025c 0083 0e05 lri $AR3, #0x0e05 + // 025e 1b61 srri @$AR3, $AR1 + // 025f 1b60 srri @$AR3, $AR0 + *0x0e05 = pUpdate_block + *0x0e06 = pUpdates_this_ms + // They are restored before jmping back to NextMillisecUpd + + // 0260 00de 0b87 lr $AC0.M, @0x0b87 + // 0262 0601 cmpis $AC0.M, #0x01 + // 0263 0295 0267 jz 0x0267 + // 0265 029f 0332 jmp 0x0332 + if (pb.state == AX_PB_STATE_RUN) { + + // 0267 00de 0e42 lr $AC0.M, @0x0e42 + // 0269 00fe 0e1c sr @0x0e1c, $AC0.M + *0x0e1c = *0x0e42 + + // 026b 00c3 0e15 lr $AR3, @0x0e15 + // 026d 177f callr $AR3 + DoSelectedSRC() + + // Volume Envelope Processing + // 026e 8e00 set16 + // 026f 8a00 m2 + // 0270 8100 clr $ACC0 + // 0271 8900 clr $ACC1 + // 0272 00de 0bb3 lr $AC0.M, @0x0bb3 // currentDelta (s16) + // 0274 00df 0bb2 lr $AC1.M, @0x0bb2 // currentVolume (u16) + // 0276 1f1f mrr $AX0.L, $AC1.M + // 0277 4d00 add $ACC1, $ACC0 + // 0278 1481 asl $ACC0, #1 + // 0279 8d1e set15'mv : $AX1.H, $AC0.M // unsigned mulx, + // 027a 1fd8 mrr $AC0.M, $AX0.L + // 027b 0098 8000 lri $AX0.L, #0x8000 + // 027d 0080 0e44 lri $AR0, #0x0e44 + // 027f a830 mulx's $AX0.L, $AX1.H : @$AR0, $AC0.M + // 0280 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0281 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 0282 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0283 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 0284 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0285 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 0286 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0287 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 0288 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0289 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 028a ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 028b ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 028c ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 028d ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 028e ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 028f ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 0290 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0291 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 0292 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0293 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 0294 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0295 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 0296 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0297 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 0298 ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 0299 ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 029a ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 029b ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 029c ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 029d ad30 mulxac's $AX0.L, $AX1.H, $ACC1 : @$AR0, $AC0.M + // 029e ac38 mulxac's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC1.M + // 029f 00fe 0bb2 sr @0x0bb2, $AC0.M + + u40 temp1 = pb.ve.currentVolume << 16 + u40 temp2 = (pb.ve.currentVolume + pb.ve.currentDelta) << 16 + *0x0e44 = temp1 >> 16 + *0x0e45 = temp2 >> 16 + + u40 PROD = (u16)0x8000 * (u16)(pb.ve.currentDelta << 1) * 2 + for (u16* i = 0x0e46; i < 0x0e46 + 30; i+=2) { + temp1 += PROD + temp2 += PROD + + *i = temp1 >> 16 + *(i + 1) = temp2 >> 16 + } + temp1 += PROD + pb.ve.currentVolume = temp1 >> 16 + + // 02a1 8f00 set40 + // 02a2 0080 0e44 lri $AR0, #0x0e44 + // 02a4 00c1 0e43 lr $AR1, @0x0e43 + // 02a6 1c61 mrr $AR3, $AR1 + // 02a7 193a lrri $AX0.H, @$AR1 + // 02a8 1918 lrri $AX0.L, @$AR0 + // 02a9 9059 mul'l $AX0.L, $AX0.H : $AX1.H, @$AR1 + // 02aa 1919 lrri $AX1.L, @$AR0 + // 02ab 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02ac 8080 nx'ls : $AX0.L, $AC0.M + // 02ad 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02ae 8091 nx'ls : $AX1.L, $AC1.M + // 02af 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02b0 8080 nx'ls : $AX0.L, $AC0.M + // 02b1 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02b2 8091 nx'ls : $AX1.L, $AC1.M + // 02b3 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02b4 8080 nx'ls : $AX0.L, $AC0.M + // 02b5 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02b6 8091 nx'ls : $AX1.L, $AC1.M + // 02b7 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02b8 8080 nx'ls : $AX0.L, $AC0.M + // 02b9 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02ba 8091 nx'ls : $AX1.L, $AC1.M + // 02bb 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02bc 8080 nx'ls : $AX0.L, $AC0.M + // 02bd 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02be 8091 nx'ls : $AX1.L, $AC1.M + // 02bf 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02c0 8080 nx'ls : $AX0.L, $AC0.M + // 02c1 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02c2 8091 nx'ls : $AX1.L, $AC1.M + // 02c3 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02c4 8080 nx'ls : $AX0.L, $AC0.M + // 02c5 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02c6 8091 nx'ls : $AX1.L, $AC1.M + // 02c7 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02c8 8080 nx'ls : $AX0.L, $AC0.M + // 02c9 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02ca 8091 nx'ls : $AX1.L, $AC1.M + // 02cb 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02cc 8080 nx'ls : $AX0.L, $AC0.M + // 02cd 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02ce 8091 nx'ls : $AX1.L, $AC1.M + // 02cf 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02d0 8080 nx'ls : $AX0.L, $AC0.M + // 02d1 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02d2 8091 nx'ls : $AX1.L, $AC1.M + // 02d3 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02d4 8080 nx'ls : $AX0.L, $AC0.M + // 02d5 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02d6 8091 nx'ls : $AX1.L, $AC1.M + // 02d7 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02d8 8080 nx'ls : $AX0.L, $AC0.M + // 02d9 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02da 8091 nx'ls : $AX1.L, $AC1.M + // 02db 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02dc 8080 nx'ls : $AX0.L, $AC0.M + // 02dd 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02de 8091 nx'ls : $AX1.L, $AC1.M + // 02df 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02e0 8080 nx'ls : $AX0.L, $AC0.M + // 02e1 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02e2 8091 nx'ls : $AX1.L, $AC1.M + // 02e3 9e51 mulmv'l $AX1.L, $AX1.H, $ACC0 : $AX0.H, @$AR1 + // 02e4 8080 nx'ls : $AX0.L, $AC0.M + // 02e5 9759 mulmv'l $AX0.L, $AX0.H, $ACC1 : $AX1.H, @$AR1 + // 02e6 8091 nx'ls : $AX1.L, $AC1.M + // 02e7 9e00 mulmv $AX1.L, $AX1.H, $ACC0 + // 02e8 6f33 movp's $ACC1 : @$AR3, $AC0.M + // 02e9 1b7f srri @$AR3, $AC1.M + + u16* dst = *0x0e43 + u16* temp1 = 0x0e44 + + for (x = 0; x < 0x20; x++) { + *(dst + x) = ((u16)*(temp1 + x) * (u16)*(dst + x) * 2) >> 16 + } + + // 02ea 00c3 0e14 lr $AR3, @0x0e14 + // 02ec 8f00 set40 + // 02ed 8d00 set15 + // 02ee 8a00 m2 + // 02ef 177f callr $AR3 + // Keep in mind: 40bit, unsigned, *2 + DoSelectedMixer() + + // Note: 40bit, unsigned, *2 not changed till 0x0332 + + // 02f0 8100 clr $ACC0 + // 02f1 00de 0b9b lr $AC0.M, @0x0b9b + // 02f3 b100 tst $ACC0 + // 02f4 0295 032a jz 0x032a + if (pb.itd.flag != AX_PB_ITD_OFF) { + // 02f6 00de 0e42 lr $AC0.M, @0x0e42 + // 02f8 00fe 0e43 sr @0x0e43, $AC0.M + *0x0e43 = *0x0e42 + + // 02fa 8100 clr $ACC0 + // 02fb 8900 clr $ACC1 + // 02fc 00de 0b9e lr $AC0.M, @0x0b9e + // 02fe 00df 0ba0 lr $AC1.M, @0x0ba0 + // 0300 8200 cmp + // 0301 0293 0306 jle 0x0306 + if (pb.itd.shiftL > pb.itd.targetShiftL) { + // 0303 7800 decm $AC0.M + // 0304 029f 0309 jmp 0x0309 + pb.itd.shiftL-- + } else if (pb.itd.shiftL < pb.itd.targetShiftL) { + // 0306 0295 0309 jz 0x0309 + // 0308 7400 incm $AC0.M + pb.itd.shiftL++ + } + // 0309 00fe 0b9e sr @0x0b9e, $AC0.M // Store pb.itd.shiftL + + // 030b 00df 0e43 lr $AC1.M, @0x0e43 + // 030d 05e0 addis $AC1.M, #0xe0 + // 030e 4c00 add $ACC0, $ACC1 + // 030f 00fe 0e40 sr @0x0e40, $AC0.M + *0x0e40 = *0x0e43 - 32 + + // 0311 8100 clr $ACC0 + // 0312 8900 clr $ACC1 + // 0313 00de 0b9f lr $AC0.M, @0x0b9f + // 0315 00df 0ba1 lr $AC1.M, @0x0ba1 + // 0317 8200 cmp + // 0318 0293 031d jle 0x031d + if (pb.itd.shiftR > pb.itd.targetShiftR) { + // 031a 7800 decm $AC0.M + // 031b 029f 0320 jmp 0x0320 + pb.itd.shiftR-- + } else if (pb.itd.shiftR < pb.itd.targetShiftR) { + // 031d 0295 0320 jz 0x0320 + // 031f 7400 incm $AC0.M + pb.itd.shiftR++ + } + // 0320 00fe 0b9f sr @0x0b9f, $AC0.M // Store pb.itd.shiftR + + // 0322 00df 0e43 lr $AC1.M, @0x0e43 + // 0324 05e0 addis $AC1.M, #0xe0 + // 0325 4c00 add $ACC0, $ACC1 + // 0326 00fe 0e41 sr @0x0e41, $AC0.M + *0x0e41 = *0x0e43 - 32 + + 0328 029f 0332 jmp 0x0332 + + } else { // pb.itd.flag == AX_PB_ITD_OFF + + // 032a 00de 0e42 lr $AC0.M, @0x0e42 + // 032c 00fe 0e40 sr @0x0e40, $AC0.M + // 032e 00fe 0e41 sr @0x0e41, $AC0.M + // 0330 00fe 0e43 sr @0x0e43, $AC0.M + *0x0e40 = *0x0e42 + *0x0e41 = *0x0e42 + *0x0e43 = *0x0e42 + } + } + + + // 0332 8100 clr $ACC0 + // 0333 8e00 set16 + // 0334 8400 clrp + // 0335 8900 clr $ACC1 + // 0336 1efe mrr $PROD.M2, $AC0.M + // 0337 0e40 lris $AC0.M, #0x40 + // 0338 1ebe mrr $PROD.M1, $AC0.M + // 0339 0083 0e08 lri $AR3, #0x0e08 + // 033b 1c03 mrr $AR0, $AR3 + // 033c 1ff5 mrr $AC1.M, $PROD.M1 + // 033d 191a lrri $AX0.H, @$AR0 + // 033e f858 addpaxz'l $ACC0, $AX0.H : $AX1.H, @$AR0 + // 033f fba0 addpaxz'ls $ACC1, $AX1.H : $AX0.H, $AC0.M + // 0340 f8b1 addpaxz'ls $ACC0, $AX0.H : $AX1.H, $AC1.M + // 0341 fba0 addpaxz'ls $ACC1, $AX1.H : $AX0.H, $AC0.M + // 0342 f8b1 addpaxz'ls $ACC0, $AX0.H : $AX1.H, $AC1.M + // 0343 fba0 addpaxz'ls $ACC1, $AX1.H : $AX0.H, $AC0.M + // 0344 f8b1 addpaxz'ls $ACC0, $AX0.H : $AX1.H, $AC1.M + // 0345 fba0 addpaxz'ls $ACC1, $AX1.H : $AX0.H, $AC0.M + // 0346 f83b addpaxz's $ACC0, $AX0.H : @$AR3, $AC1.M + // 0347 1b7e srri @$AR3, $AC0.M + + for (u16* i = 0x0e08; i <= 0x0e10; i++) { + *i = (u16)( (0xff00400000 + (u40)(*i << 16)) >> 16 ) + } + + // 0348 0083 0e04 lri $AR3, #0x0e04 + // 034a 8100 clr $ACC0 + // 034b 8973 clr'l $ACC1 : $AC0.M, @$AR3 + // 034c 1961 lrri $AR1, @$AR3 // 0x0e05 + // 034d 1960 lrri $AR0, @$AR3 // 0x0e06 + // 034e 7800 decm $AC0.M + // 034f 00fe 0e04 sr @0x0e04, $AC0.M + // 0351 0294 0253 jnz 0x0253 + ms_remaining-- + if (ms_remaining) + goto NextMillisecUpd + + // 0353 8e00 set16 + // 0354 8100 clr $ACC0 + // 0355 00de 0b9b lr $AC0.M, @0x0b9b + // 0357 b100 tst $ACC0 + // 0358 0295 036a jz 0x036a + if (pb.itd.flag != AX_PB_ITD_OFF) { + + // 035a 00de 0b9c lr $AC0.M, @0x0b9c + // 035c 00dc 0b9d lr $AC0.L, @0x0b9d + // 035e 2ece srs @DSMAH, $AC0.M + // 035f 2ccf srs @DSMAL, $AC0.L + // 0360 8100 clr $ACC0 + // 0361 00de 0e1c lr $AC0.M, @0x0e1c + // 0363 2ecd srs @DSPA, $AC0.M + // 0364 16c9 0001 si @DSCR, #0x0001 + // 0366 16cb 0040 si @DSBL, #0x0040 + + // DMA 0x40bytes from DRAM @ (*0x0e1c) to CPU @ ((pb.itd.bufferHi << 16) | pb.itd.bufferLo) + + // 0368 02bf 055c call 0x055c + WaitDMA(); + } + + // 036a 8100 clr $ACC0 + // 036b 8900 clr $ACC1 + // 036c 00de 0b82 lr $AC0.M, @0x0b82 + // 036e 00df 0b83 lr $AC1.M, @0x0b83 + u16 maddrh = pb.currHi + u16 maddrl = pb.currLo + + // This writes back the whole PB to mram from dsp + // 0370 2ece srs @DSMAH, $AC0.M + // 0371 2fcf srs @DSMAL, $AC1.M + // 0372 16cd 0b80 si @DSPA, #0x0b80 + // 0374 16c9 0001 si @DSCR, #0x0001 + // 0376 16cb 00c0 si @DSBL, #0x00c0 + + // DMA 0xc0bytes from DRAM @ 0x0b80 to CPU @ maddr + + // 0378 02bf 055c call 0x055c + WaitDMA(); + + // 037a 8100 clr $ACC0 + // 037b 00de 0b80 lr $AC0.M, @0x0b80 + // 037d 00dc 0b81 lr $AC0.L, @0x0b81 + // 037f b100 tst $ACC0 + // 0380 0294 0386 jnz 0x0386 + if (((pb.nextHi << 16) | pb.nextLo) == 0) { + // No more PBs! + + // Restore CmdBlockBuf ptr + 0382 00c0 0e07 lr $AR0, @0x0e07 + // 0384 029f 0068 jmp 0x0068 + goto DoNextCommand; + } + + // DMA in the next PB + // From here on out, it's the same as Cmd2, except it calls itself to process the PB it just loaded + + // 0386 2ece srs @DSMAH, $AC0.M + // 0387 2ccf srs @DSMAL, $AC0.L + // 0388 16cd 0b80 si @DSPA, #0x0b80 + // 038a 16c9 0000 si @DSCR, #0x0000 + // 038c 16cb 00c0 si @DSBL, #0x00c0 + + // DMA 0xc0bytes from CPU @ ((pb.nextHi << 16) | pb.nextLo) to DRAM @ 0x0b80 + + // 038e 0082 0e08 lri $AR2, #0x0e08 + // 0390 009f 0000 lri $AC1.M, #0x0000 + // 0392 1b5f srri @$AR2, $AC1.M + // 0393 009f 0140 lri $AC1.M, #0x0140 + // 0395 1b5f srri @$AR2, $AC1.M + // 0396 009f 0280 lri $AC1.M, #0x0280 + // 0398 1b5f srri @$AR2, $AC1.M + // 0399 009f 0400 lri $AC1.M, #0x0400 + // 039b 1b5f srri @$AR2, $AC1.M + // 039c 009f 0540 lri $AC1.M, #0x0540 + // 039e 1b5f srri @$AR2, $AC1.M + // 039f 009f 0680 lri $AC1.M, #0x0680 + // 03a1 1b5f srri @$AR2, $AC1.M + // 03a2 009f 07c0 lri $AC1.M, #0x07c0 + // 03a4 1b5f srri @$AR2, $AC1.M + // 03a5 009f 0900 lri $AC1.M, #0x0900 + // 03a7 1b5f srri @$AR2, $AC1.M + // 03a8 009f 0a40 lri $AC1.M, #0x0a40 + // 03aa 1b5f srri @$AR2, $AC1.M + *0x0e08 = 0x0000 + *0x0e09 = 0x0140 + *0x0e0a = 0x0280 + *0x0e0b = 0x0400 + *0x0e0c = 0x0540 + *0x0e0d = 0x0680 + *0x0e0e = 0x07c0 + *0x0e0f = 0x0900 + *0x0e10 = 0x0a40 + + // 03ab 02bf 055c call 0x055c + WaitDMA(); + + // 03ad 00de 0ba7 lr $AC0.M, @0x0ba7 + // 03af 00df 0ba8 lr $AC1.M, @0x0ba8 + // 03b1 2ece srs @DSMAH, $AC0.M + // 03b2 2fcf srs @DSMAL, $AC1.M + // 03b3 16cd 03c0 si @DSPA, #0x03c0 + // 03b5 16c9 0000 si @DSCR, #0x0000 + // 03b7 16cb 0080 si @DSBL, #0x0080 + + // DMA 0x80bytes from CPU @ ((pb.update.dataHi << 16) | pb.update.dataLo) to DRAM @ 0x03c0 + + // 03b9 8100 clr $ACC0 + // 03ba 8900 clr $ACC1 + + // 03bb 00de 0b84 lr $AC0.M, @0x0b84 + // 03bd 009f 0b31 lri $AC1.M, #0x0b31 + // 03bf 4c00 add $ACC0, $ACC1 + // 03c0 1c7e mrr $AR3, $AC0.M + // 03c1 0213 ilrr $AC0.M, @$AR3 + // 03c2 00fe 0e15 sr @0x0e15, $AC0.M + *0x0e15 = *(0x0b31 + pb.srcSelect) // func ptr for src + + // 03c4 00de 0b85 lr $AC0.M, @0x0b85 + // 03c6 009f 0b34 lri $AC1.M, #0x0b34 + // 03c8 4c00 add $ACC0, $ACC1 + // 03c9 1c7e mrr $AR3, $AC0.M + // 03ca 0213 ilrr $AC0.M, @$AR3 + // 03cb 00fe 0e16 sr @0x0e16, $AC0.M + *0x0e16 = *(0x0b34 + pb.coefSelect) // ptr to coef table + + // 03cd 00de 0b86 lr $AC0.M, @0x0b86 + // 03cf 009f 0b11 lri $AC1.M, #0x0b11 + // 03d1 4c00 add $ACC0, $ACC1 + // 03d2 1c7e mrr $AR3, $AC0.M + // 03d3 0213 ilrr $AC0.M, @$AR3 + // 03d4 00fe 0e14 sr @0x0e14, $AC0.M + *0x0e14 = *(0x0b11 + pb.mixerCtrl) // func ptr for mixer + + // 03d6 8100 clr $ACC0 + // 03d7 00de 0b9b lr $AC0.M, @0x0b9b + // 03d9 b100 tst $ACC0 + // 03da 0295 0403 jz 0x0403 + if (pb.itd.flag != AX_PB_ITD_OFF) { + // 03dc 8900 clr $ACC1 + // 03dd 00df 0b9e lr $AC1.M, @0x0b9e + // 03df 0300 0cc0 addi $AC1.M, #0x0cc0 + // 03e1 00ff 0e40 sr @0x0e40, $AC1.M + *0x0e40 = 0x0cc0 + pb.itd.shiftL + + // 03e3 00df 0b9f lr $AC1.M, @0x0b9f + // 03e5 0300 0cc0 addi $AC1.M, #0x0cc0 + // 03e7 00ff 0e41 sr @0x0e41, $AC1.M + *0x0e41 = 0x0cc0 + pb.itd.shiftR + + // 03e9 009f 0ce0 lri $AC1.M, #0x0ce0 + // 03eb 00ff 0e42 sr @0x0e42, $AC1.M + // 03ed 00ff 0e43 sr @0x0e43, $AC1.M + *0x0e42 = 0x0ce0 + *0x0e43 = 0x0ce0 + + // 03ef 02bf 055c call 0x055c + WaitDMA(); + + // 03f1 00de 0b9c lr $AC0.M, @0x0b9c + // 03f3 2ece srs @DSMAH, $AC0.M + // 03f4 00de 0b9d lr $AC0.M, @0x0b9d + // 03f6 2ecf srs @DSMAL, $AC0.M + // 03f7 16cd 0cc0 si @DSPA, #0x0cc0 + // 03f9 16c9 0000 si @DSCR, #0x0000 + // 03fb 16cb 0040 si @DSBL, #0x0040 + + // DMA 0x0040bytes to DMEM @ 0x0cc0 from CPU @ (pb.itd.bufferHi << 16) | pb.itd.bufferLo + + // 03fd 02bf 055c call 0x055c + WaitDMA(); + + // Restore CmdBlockBuf ptr + 03ff 00c0 0e07 lr $AR0, @0x0e07 + // 0401 029f 0248 jmp 0x0248 + goto Cmd_3() // Calls itself till there are no more PBs linked + + } else { + + // 0403 009f 0ce0 lri $AC1.M, #0x0ce0 + // 0405 00ff 0e42 sr @0x0e42, $AC1.M + // 0407 00ff 0e40 sr @0x0e40, $AC1.M + // 0409 00ff 0e41 sr @0x0e41, $AC1.M + // 040b 00ff 0e43 sr @0x0e43, $AC1.M + *0x0e42 = 0x0ce0 + *0x0e40 = 0x0ce0 + *0x0e41 = 0x0ce0 + *0x0e43 = 0x0ce0 + + // 040d 02bf 055c call 0x055c + WaitDMA(); + + // Restore CmdBlockBuf ptr + 040f 00c0 0e07 lr $AR0, @0x0e07 + // 0411 029f 0248 jmp 0x0248 + goto Cmd_3() // Calls itself till there are no more PBs linked + } +} + +void Cmd_4() { + 0413 8e00 set16 + + 0414 0086 0400 lri $IX2, #0x0400 // buffer in dram + + // 0416 8100 clr $ACC0 + // 0417 8970 clr'l $ACC1 : $AC0.M, @$AR0 + // 0418 191c lrri $AC0.L, @$AR0 + u16 maddrh = *(CmdBlockBuf++) + u16 maddrl = *(CmdBlockBuf++) + + // 0419 2ece srs @DSMAH, $AC0.M + // 041a 2ccf srs @DSMAL, $AC0.L + // 041b 1fc6 mrr $AC0.M, $IX2 + // 041c 2ecd srs @DSPA, $AC0.M + // 041d 16c9 0001 si @DSCR, #0x0001 + // 041f 16cb 0780 si @DSBL, #0x0780 + + // DMA 0x0780bytes from DRAM @ 0x0400 to CPU @ maddr + + // 0421 02bf 055c call 0x055c + WaitDMA(); + + 0423 02bf 0484 call 0x0484 + + // 0425 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void Cmd_5() { + 0427 8e00 set16 + + 0428 0086 07c0 lri $IX2, #0x07c0 + + 042a 8100 clr $ACC0 + 042b 8970 clr'l $ACC1 : $AC0.M, @$AR0 + 042c 191c lrri $AC0.L, @$AR0 + 042d 2ece srs @DSMAH, $AC0.M + 042e 2ccf srs @DSMAL, $AC0.L + 042f 1fc6 mrr $AC0.M, $IX2 + 0430 2ecd srs @DSPA, $AC0.M + 0431 16c9 0001 si @DSCR, #0x0001 + 0433 16cb 0780 si @DSBL, #0x0780 + + // 0435 02bf 055c call 0x055c + WaitDMA(); + + 0437 02bf 0484 call 0x0484 + + // 0439 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void Cmd_E() { + 043b 8c00 clr15 + 043c 8a00 m2 + 043d 8100 clr $ACC0 + 043e 8970 clr'l $ACC1 : $AC0.M, @$AR0 + 043f 191f lrri $AC1.M, @$AR0 + 0440 2ece srs @DSMAH, $AC0.M + 0441 2fcf srs @DSMAL, $AC1.M + 0442 16cd 0280 si @DSPA, #0x0280 + 0444 16c9 0001 si @DSCR, #0x0001 // DMEM -> CPU + 0446 16cb 0280 si @DSBL, #0x0280 + + 0448 8f50 set40'l : $AX0.H, @$AR0 + 0449 8140 clr'l $ACC0 : $AX0.L, @$AR0 + 044a 0081 0400 lri $AR1, #0x0400 + 044c 0083 0000 lri $AR3, #0x0000 + 044e 0082 0140 lri $AR2, #0x0140 + 0450 0099 0080 lri $AX1.L, #0x0080 + + // 0452 02bf 055c call 0x055c + WaitDMA(); + + 0454 1105 046c bloopi #0x05, 0x046c + 0456 1f61 mrr $AX1.H, $AR1 + + 0457 1120 045e bloopi #0x20, 0x045e + 0459 8972 clr'l $ACC1 : $AC0.M, @$AR2 + 045a 195c lrri $AC0.L, @$AR2 + 045b f07b lsl16'l $ACC0 : $AC1.M, @$AR3 + 045c 197d lrri $AC1.L, @$AR3 + 045d f131 lsl16's $ACC1 : @$AR1, $AC0.M + 045e 8139 clr's $ACC0 : @$AR1, $AC1.M + + 045f 8900 clr $ACC1 + 0460 6800 movax $ACC0, $AX0 + 0461 2ece srs @DSMAH, $AC0.M + 0462 2ccf srs @DSMAL, $AC0.L + 0463 1ffb mrr $AC1.M, $AX1.H + 0464 2fcd srs @DSPA, $AC1.M + 0465 0f01 lris $AC1.M, #0x01 + 0466 2fc9 srs @DSCR, $AC1.M + 0467 1ff9 mrr $AC1.M, $AX1.L + 0468 2fcb srs @DSBL, $AC1.M + 0469 7200 addaxl $ACC0, $AX1.L + 046a 1f5e mrr $AX0.H, $AC0.M + 046b 1f1c mrr $AX0.L, $AC0.L + 046c 8100 clr $ACC0 + + // 046d 26c9 lrs $AC0.M, @DSCR + // 046e 02a0 0004 andf $AC0.M, #0x0004 + // 0470 029c 046d jlnz 0x046d + while (@DSCR & 4); + + // 0472 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void UnimplimentedCmd_B() { + // 0474 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void UnimplimentedCmd_C() { + // 0476 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void UnimplimentedCmd_A() { + // 0478 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void Task_Yield() { + // Send DSP_YIELD mail + // 047a 16fc dcd1 si @DMBH, #0xdcd1 + // 047c 16fd 0002 si @DMBL, #0x0002 + DMB = 0xdcd10002 + // 047e 16fb 0001 si @DIRQ, #0x0001 + + 0480 029f 0c91 jmp 0x0c91 +} + + // Unused? + // 0482 029f 0045 jmp 0x0045 + goto GetNextCmdBlock; + +// Called by cmds 4 5 9 +// IX2 is always modified before calling... +void UnkFunc() { + 0484 8e00 set16 + 0485 191f lrri $AC1.M, @$AR0 + 0486 191d lrri $AC1.L, @$AR0 + 0487 1f5f mrr $AX0.H, $AC1.M + 0488 1f1d mrr $AX0.L, $AC1.L + 0489 2fce srs @DSMAH, $AC1.M + 048a 2dcf srs @DSMAL, $AC1.L + 048b 8900 clr $ACC1 + 048c 1fa6 mrr $AC1.L, $IX2 + 048d 2dcd srs @DSPA, $AC1.L + 048e 0e00 lris $AC0.M, #0x00 + 048f 2ec9 srs @DSCR, $AC0.M + 0490 8100 clr $ACC0 + 0491 009c 00c0 lri $AC0.L, #0x00c0 + 0493 2ccb srs @DSBL, $AC0.L + 0494 1ca0 mrr $IX1, $AR0 + 0495 0081 0e44 lri $AR1, #0x0e44 + 0497 4800 addax $ACC0, $AX0 + 0498 1b3e srri @$AR1, $AC0.M + 0499 1b3c srri @$AR1, $AC0.L + 049a 0b00 lris $AX1.H, #0x00 + 049b 0099 0060 lri $AX1.L, #0x0060 + 049d 4b00 addax $ACC1, $AX1 + 049e 1b3d srri @$AR1, $AC1.L + 049f 0081 0e44 lri $AR1, #0x0e44 + 04a1 1c06 mrr $AR0, $IX2 + 04a2 0083 0000 lri $AR3, #0x0000 + 04a4 1c43 mrr $AR2, $AR3 + + 04a5 27c9 lrs $AC1.M, @DSCR + 04a6 03a0 0004 andf $AC1.M, #0x0004 + 04a8 029c 04a5 jlnz 0x04a5 + + 04aa 1109 04da bloopi #0x09, 0x04da + 04ac 8e00 set16 + 04ad 193a lrri $AX0.H, @$AR1 + 04ae 1938 lrri $AX0.L, @$AR1 + 04af 6900 movax $ACC1, $AX0 + 04b0 2fce srs @DSMAH, $AC1.M + 04b1 2dcf srs @DSMAL, $AC1.L + 04b2 8900 clr $ACC1 + 04b3 193d lrri $AC1.L, @$AR1 + 04b4 2dcd srs @DSPA, $AC1.L + 04b5 16c9 0000 si @DSCR, #0x0000 + 04b7 8100 clr $ACC0 + 04b8 009c 00c0 lri $AC0.L, #0x00c0 + 04ba 2ccb srs @DSBL, $AC0.L + 04bb 0081 0e44 lri $AR1, #0x0e44 + 04bd 4800 addax $ACC0, $AX0 + 04be 1b3e srri @$AR1, $AC0.M + 04bf 1b3c srri @$AR1, $AC0.L + 04c0 0b00 lris $AX1.H, #0x00 + 04c1 0960 lris $AX1.L, #0x60 + 04c2 4b00 addax $ACC1, $AX1 + 04c3 1b3d srri @$AR1, $AC1.L + 04c4 0081 0e44 lri $AR1, #0x0e44 + 04c6 8f00 set40 + 04c7 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 04c8 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 04c9 6a00 movax $ACC0, $AX1 + 04ca 4800 addax $ACC0, $AX0 + 04cb 1117 04d4 bloopi #0x17, 0x04d4 + 04cd 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 04ce 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 04cf 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M + 04d0 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L + 04d1 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 04d2 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 04d3 6a3a movax's $ACC0, $AX1.L : @$AR2, $AC1.M + 04d4 482a addax's $ACC0, $AX0.L : @$AR2, $AC1.L + 04d5 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 04d6 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 04d7 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M + 04d8 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L + 04d9 1b5f srri @$AR2, $AC1.M + 04da 1b5d srri @$AR2, $AC1.L + + 04db 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 04dc 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 04dd 6a00 movax $ACC0, $AX1 + 04de 4800 addax $ACC0, $AX0 + + 04df 1117 04e8 bloopi #0x17, 0x04e8 + 04e1 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 04e2 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 04e3 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M + 04e4 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L + 04e5 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 04e6 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 04e7 6a3a movax's $ACC0, $AX1.L : @$AR2, $AC1.M + 04e8 482a addax's $ACC0, $AX0.L : @$AR2, $AC1.L + + 04e9 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 04ea 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 04eb 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M + 04ec 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L + 04ed 1b5f srri @$AR2, $AC1.M + 04ee 1b5d srri @$AR2, $AC1.L + 04ef 1c05 mrr $AR0, $IX1 + 04f0 02df ret +} + +// Only called by Command 1 +// AX0 = maddr +// AX1.L = unkForMulBuffer1 +// AR1 = unkForMulBuffer2 +void Unk(maddr, unkForMulBuffer1, unkForMulBuffer2) { + 04f1 8e00 set16 + + // 04f2 009b 0e44 lri $AX1.H, #0x0e44 + // 04f4 009d 00c0 lri $AC1.L, #0x00c0 + // 04f6 02bf 0541 call 0x0541 + u16 daddr = 0x0e44 + const u16 dma_len = 0x00c0 + DMA_CPUToDMEM(maddr, daddr, dma_len); + + // 04f8 4900 addax $ACC1, $AX0 + // 04f9 00ff 0e1d sr @0x0e1d, $AC1.M + // 04fb 00fd 0e1e sr @0x0e1e, $AC1.L + // 04fd 8900 clr $ACC1 + maddr += dma_len + + // 04fe 02bf 055c call 0x055c + WaitDMA(); + + // 0500 1104 052c bloopi #0x04, 0x052c + for (u8 i = 0; i < 4; i++) { + // 0502 00da 0e1d lr $AX0.H, @0x0e1d // restore + // 0504 00d8 0e1e lr $AX0.L, @0x0e1e // restore + // 0506 009b 0ea4 lri $AX1.H, #0x0ea4 // buffer 2 + // 0508 009d 00c0 lri $AC1.L, #0x00c0 // restore + // 050a 02bf 0541 call 0x0541 + daddr = 0x0ea4 + DMA_CPUToDMEM(maddr, daddr, dma_len); + + // 050c 4900 addax $ACC1, $AX0 + // 050d 00ff 0e1d sr @0x0e1d, $AC1.M // update + // 050f 00fd 0e1e sr @0x0e1e, $AC1.L + maddr += dma_len + + // 0511 0083 0e44 lri $AR3, #0x0e44 + // 0513 02bf 054c call 0x054c + UnknownMulBuffer(0x0e44); + + // 0515 8900 clr $ACC1 + // 0516 00da 0e1d lr $AX0.H, @0x0e1d // restore + // 0518 00d8 0e1e lr $AX0.L, @0x0e1e // restore + // 051a 009b 0e44 lri $AX1.H, #0x0e44 // buffer 1 + // 051c 009d 00c0 lri $AC1.L, #0x00c0 // restore + // 051e 02bf 0541 call 0x0541 + daddr = 0x0e44 + DMA_CPUToDMEM(maddr, daddr, dma_len); + + // 0520 4900 addax $ACC1, $AX0 + // 0521 00ff 0e1d sr @0x0e1d, $AC1.M // update + // 0523 00fd 0e1e sr @0x0e1e, $AC1.L + maddr += dma_len + + // 0525 0083 0ea4 lri $AR3, #0x0ea4 // buffer 2 + // 0527 02bf 054c call 0x054c + UnknownMulBuffer(0x0ea4); + + // 0529 0000 nop + // 052a 0000 nop + // 052b 8e00 set16 // restore + // 052c 8900 clr $ACC1 + } + + // 052d 00da 0e1d lr $AX0.H, @0x0e1d // restore + // 052f 00d8 0e1e lr $AX0.L, @0x0e1e // restore + // 0531 009b 0ea4 lri $AX1.H, #0x0ea4 // buffer 2 + // 0533 009d 00c0 lri $AC1.L, #0x00c0 // restore + // 0535 02bf 0541 call 0x0541 + DMA_CPUToDMEM(maddr, daddr, dma_len); + + // 0537 4900 addax $ACC1, $AX0 + maddr += dma_len + + // 0538 0083 0e44 lri $AR3, #0x0e44 // buffer 1 + // 053a 02bf 054c call 0x054c + UnknownMulBuffer(0x0e44); + + // 053c 0083 0ea4 lri $AR3, #0x0ea4 // buffer 2 + // 053e 02bf 054c call 0x054c + UnknownMulBuffer(0x0ea4); + + 0540 02df ret +} + +// u32 maddr = AX0 +// u16 daddr = AX1.H +// u16 len = AC1.L +// Only transfers from CPU -> DMEM +void DMA_CPUToDMEM() { + 0541 8e00 set16 + 0542 00fa ffce sr @DSMAH, $AX0.H + 0544 00f8 ffcf sr @DSMAL, $AX0.L + 0546 00fb ffcd sr @DSPA, $AX1.H + 0548 16c9 0000 si @DSCR, #0x0000 + 054a 2dcb srs @DSBL, $AC1.L + 054b 02df ret +} + +// IX1 = 0xffff +// AX1.L = unkForMulBuffer1 (next value in cmd block) +// AR1 = unkForMulBuffer2 (0, 0x0400, then 0x07c0) +// AR3 is some buffer, either 0x0e44 or 0x0ea4 +void UnknownMulBuffer() { + 054c 8f00 set40 // Loaded ACx.M values extend to the entire ACC + 054d 8d00 set15 // multiplicands unsigned + 054e 8a00 m2 // mul results doubled + + // 054f 197a lrri $AX0.H, @$AR3 + // 0550 1978 lrri $AX0.L, @$AR3 + AX0.H = *(AR3++) + AX0.L = *(AR3++) + + // 0551 a000 mulx $AX0.L, $AX1.L + // 0552 b600 mulxmv $AX0.H, $AX1.L, $ACC0 + ACC0 = (u16)AX0.L * (u16)unkForMulBuffer1 * 2 + PROD = (u16)AX0.H * (u16)unkForMulBuffer1 * 2 + + // 0553 1130 055a bloopi #0x30, 0x055a + for (int i=0; i<48; i++) { + // 0555 9179 asr16'l $ACC0 : $AC1.M, @$AR1 + ACC0 >>= 16 + AC1.M = *(unkForMulBuffer2++) + + // 0556 4e6d addp'ln $ACC0 : $AC1.L, @$AR1 + ACC0 += PROD + AC1.L = *unkForMulBuffer2 + unkForMulBuffer2 -= 1 + + // 0557 197a lrri $AX0.H, @$AR3 + AX0.H = *(AR3++) + + // 0558 4d43 add'l $ACC1, $ACC0 : $AX0.L, @$AR3 + ACC1 += ACC0 + AX0.L = *(AR3++) + + // 0559 a039 mulx's $AX0.L, $AX1.L : @$AR1, $AC1.M + // 055a b629 mulxmv's $AX0.H, $AX1.L, $ACC0 : @$AR1, $AC1.L + ACC0 = (u16)AX0.L * (u16)unkForMulBuffer1 * 2 + *(unkForMulBuffer2++) = AC1.M + PROD = (u16)AX0.H * (u16)unkForMulBuffer1 * 2 + *(unkForMulBuffer2++) = AC1.L + } + + 055b 02df ret +} + +void WaitDMA() { + // 055c 26c9 lrs $AC0.M, @DSCR + // 055d 02a0 0004 andf $AC0.M, #0x0004 + // 055f 029c 055c jlnz 0x055c + while (@DSCR & 4); + + // 0561 02df ret + return; +} + +// All apparently unused? +void WaitForCPUMailbox() { + 0562 26fe lrs $AC0.M, @CMBH + 0563 02c0 8000 andcf $AC0.M, #0x8000 + 0565 029c 0562 jlnz 0x0562 + 0567 02df ret +} +void WaitForDSPMailbox1() { + 0568 26fc lrs $AC0.M, @DMBH + 0569 02a0 8000 andf $AC0.M, #0x8000 + 056b 029c 0568 jlnz 0x0568 + 056d 02df ret +} +void WaitForDSPMailbox2() { + 056e 26fc lrs $AC0.M, @DMBH + 056f 02a0 8000 andf $AC0.M, #0x8000 + 0571 029c 056e jlnz 0x056e + 0573 02df ret +} + +void Cmd_7() { + // 0574 8100 clr $ACC0 + // 0575 8970 clr'l $ACC1 : $AC0.M, @$AR0 + // 0576 8e60 set16'l : $AC0.L, @$AR0 + u16 maddrh = *(CmdBlockBuf++) + u16 maddrl = *(CmdBlockBuf++) + + // 0577 2ece srs @DSMAH, $AC0.M + // 0578 2ccf srs @DSMAL, $AC0.L + // 0579 16cd 0e44 si @DSPA, #0x0e44 + // 057b 16c9 0000 si @DSCR, #0x0000 + // 057d 8900 clr $ACC1 + // 057e 0d20 lris $AC1.L, #0x20 + u16 dma_len = 32 + + // 057f 2dcb srs @DSBL, $AC1.L + // DMA 32bytes from CPU @ maddr -> DMEM @ 0x0e44 + + // 0580 4c00 add $ACC0, $ACC1 + maddr += dma_len + + // Push CmdBlockBuf ptr + 0581 1c80 mrr $IX0, $AR0 + + // 0582 0080 0280 lri $AR0, #0x0280 + // 0584 0081 0000 lri $AR1, #0x0000 + // 0586 0082 0140 lri $AR2, #0x0140 + // 0588 0083 0e44 lri $AR3, #0x0e44 + u16* unk_buf1 = 0x0280 + u16* unk_buf2 = 0x0000 + u16* unk_buf3 = 0x0140 + u16* dmem_buf = 0x0e44 + + // 058a 0a00 lris $AX0.H, #0x00 + const u16 null = 0 // Guess is that it's faster to use AXx instead of imm value? + + // 058b 27c9 lrs $AC1.M, @DSCR + // 058c 03a0 0004 andf $AC1.M, #0x0004 + // 058e 029c 058b jlnz 0x058b + while (@DSCR & 4); // Wait for DMA completion + + // 0590 2ece srs @DSMAH, $AC0.M + // 0591 2ccf srs @DSMAL, $AC0.L + // 0592 16cd 0e54 si @DSPA, #0x0e54 + // 0594 16c9 0000 si @DSCR, #0x0000 + // 0596 16cb 0260 si @DSBL, #0x0260 + + // DMA 0x0260bytes from CPU @ maddr -> DMEM @ 0x0e54 + // No waiting for DMA + + // 0598 009f 00a0 lri $AC1.M, #0x00a0 + u16 size = 0x00a0 + + // accum loads in the loop are 40bit + // 059a 8f00 set40 + + // 059b 007f 05a4 bloop $AC1.M, 0x05a4 + for (int i = 0; i < size; i++) { + // !!! Doesn't make sense with current understanding of set40 + 059d 197e lrri $AC0.M, @$AR3 + 059e 1b1a srri @$AR0, $AX0.H + 059f 197c lrri $AC0.L, @$AR3 + 05a0 1b1a srri @$AR0, $AX0.H + 05a1 1b5e srri @$AR2, $AC0.M + 05a2 1b5c srri @$AR2, $AC0.L + 05a3 1b3e srri @$AR1, $AC0.M + 05a4 1b3c srri @$AR1, $AC0.L + } + + // Pop CmdBlockBuf ptr + 05a5 1c04 mrr $AR0, $IX0 + + // 05a6 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +# Following 3 funcs are the SRCs to select from, in order + +void SRC_Polyphase() { + // Copy pb's data [pb.addr.format to pb.adpm.yn2] to corresponding hw regs + // 05a8 0082 0bb8 lri $AR2, #0x0bb8 + // 05aa 195e lrri $AC0.M, @$AR2 + // 05ab 2ed1 srs @SampleFormat, $AC0.M + // 05ac 195e lrri $AC0.M, @$AR2 + // 05ad 2ed4 srs @ACSAH, $AC0.M + // 05ae 195e lrri $AC0.M, @$AR2 + // 05af 2ed5 srs @ACSAL, $AC0.M + // 05b0 195e lrri $AC0.M, @$AR2 + // 05b1 2ed6 srs @ACEAH, $AC0.M + // 05b2 195e lrri $AC0.M, @$AR2 + // 05b3 2ed7 srs @ACEAL, $AC0.M + // 05b4 195e lrri $AC0.M, @$AR2 + // 05b5 2ed8 srs @ACCAH, $AC0.M + // 05b6 195e lrri $AC0.M, @$AR2 + // 05b7 2ed9 srs @ACCAL, $AC0.M + // 05b8 195e lrri $AC0.M, @$AR2 + // 05b9 2ea0 srs @COEF_A1_0, $AC0.M + // 05ba 195e lrri $AC0.M, @$AR2 + // 05bb 2ea1 srs @COEF_A2_0, $AC0.M + // 05bc 195e lrri $AC0.M, @$AR2 + // 05bd 2ea2 srs @COEF_A1_1, $AC0.M + // 05be 195e lrri $AC0.M, @$AR2 + // 05bf 2ea3 srs @COEF_A2_1, $AC0.M + // 05c0 195e lrri $AC0.M, @$AR2 + // 05c1 2ea4 srs @COEF_A1_2, $AC0.M + // 05c2 195e lrri $AC0.M, @$AR2 + // 05c3 2ea5 srs @COEF_A2_2, $AC0.M + // 05c4 195e lrri $AC0.M, @$AR2 + // 05c5 2ea6 srs @COEF_A1_3, $AC0.M + // 05c6 195e lrri $AC0.M, @$AR2 + // 05c7 2ea7 srs @COEF_A2_3, $AC0.M + // 05c8 195e lrri $AC0.M, @$AR2 + // 05c9 2ea8 srs @COEF_A1_4, $AC0.M + // 05ca 195e lrri $AC0.M, @$AR2 + // 05cb 2ea9 srs @COEF_A2_4, $AC0.M + // 05cc 195e lrri $AC0.M, @$AR2 + // 05cd 2eaa srs @COEF_A1_5, $AC0.M + // 05ce 195e lrri $AC0.M, @$AR2 + // 05cf 2eab srs @COEF_A2_5, $AC0.M + // 05d0 195e lrri $AC0.M, @$AR2 + // 05d1 2eac srs @COEF_A1_6, $AC0.M + // 05d2 195e lrri $AC0.M, @$AR2 + // 05d3 2ead srs @COEF_A2_6, $AC0.M + // 05d4 195e lrri $AC0.M, @$AR2 + // 05d5 2eae srs @COEF_A1_7, $AC0.M + // 05d6 195e lrri $AC0.M, @$AR2 + // 05d7 2eaf srs @COEF_A2_7, $AC0.M + // 05d8 195e lrri $AC0.M, @$AR2 + // 05d9 2ede srs @GAIN, $AC0.M + // 05da 195e lrri $AC0.M, @$AR2 + // 05db 2eda srs @scale, $AC0.M + // 05dc 195e lrri $AC0.M, @$AR2 + // 05dd 2edb srs @yn1, $AC0.M + // 05de 195e lrri $AC0.M, @$AR2 + // 05df 2edc srs @yn2, $AC0.M + + 05e0 8c00 clr15 + 05e1 8a00 m2 + 05e2 8e00 set16 + 05e3 00d8 0e16 lr $AX0.L, @0x0e16 + 05e5 195b lrri $AX1.H, @$AR2 + 05e6 1959 lrri $AX1.L, @$AR2 + 05e7 8100 clr $ACC0 + 05e8 195c lrri $AC0.L, @$AR2 + 05e9 0080 0e44 lri $AR0, #0x0e44 + 05eb 195f lrri $AC1.M, @$AR2 + 05ec 1b1f srri @$AR0, $AC1.M + 05ed 195f lrri $AC1.M, @$AR2 + 05ee 1b1f srri @$AR0, $AC1.M + 05ef 195f lrri $AC1.M, @$AR2 + 05f0 1b1f srri @$AR0, $AC1.M + 05f1 185f lrr $AC1.M, @$AR2 + 05f2 1b1f srri @$AR0, $AC1.M + 05f3 6b00 movax $ACC1, $AX1 + 05f4 1505 lsl $ACC1, #5 + 05f5 4d00 add $ACC1, $ACC0 + 05f6 157e lsr $ACC1, #-2 + 05f7 1c9f mrr $IX0, $AC1.M + 05f8 1cbd mrr $IX1, $AC1.L + 05f9 05e0 addis $AC1.M, #0xe0 + 05fa 9900 asr16 $ACC1 + 05fb 7d00 neg $ACC1 + 05fc 1cdd mrr $IX2, $AC1.L + 05fd 8900 clr $ACC1 + 05fe 1fa5 mrr $AC1.L, $IX1 + 05ff 1502 lsl $ACC1, #2 + 0600 1cbf mrr $IX1, $AC1.M + 0601 009a 01fc lri $AX0.H, #0x01fc + 0603 009e 0e44 lri $AC0.M, #0x0e44 + 0605 0081 ffdd lri $AR1, #0xffdd + 0607 0083 0d80 lri $AR3, #0x0d80 + 0609 0064 061a bloop $IX0, 0x061a + 060b 1827 lrr $IX3, @$AR1 + 060c 1b07 srri @$AR0, $IX3 + 060d 4a00 addax $ACC0, $AX1 + 060e 1ffc mrr $AC1.M, $AC0.L + 060f 1827 lrr $IX3, @$AR1 + 0610 1b07 srri @$AR0, $IX3 + 0611 1579 lsr $ACC1, #-7 + 0612 3500 andr $AC1.M, $AX0.H + 0613 1827 lrr $IX3, @$AR1 + 0614 1b07 srri @$AR0, $IX3 + 0615 4100 addr $ACC1, $AX0.L + 0616 1b7e srri @$AR3, $AC0.M + 0617 1827 lrr $IX3, @$AR1 + 0618 1b07 srri @$AR0, $IX3 + 0619 1b7f srri @$AR3, $AC1.M + 061a 0000 nop + + 061b 0065 0620 bloop $IX1, 0x0620 + 061d 1827 lrr $IX3, @$AR1 + 061e 1b07 srri @$AR0, $IX3 + 061f 0000 nop + 0620 0000 nop + + 0621 0007 dar $AR3 + 0622 187f lrr $AC1.M, @$AR3 + 0623 0066 0629 bloop $IX2, 0x0629 + 0625 4a3b addax's $ACC0, $AX1.L : @$AR3, $AC1.M + 0626 1ffc mrr $AC1.M, $AC0.L + 0627 1579 lsr $ACC1, #-7 + 0628 3533 andr's $AC1.M, $AX0.H : @$AR3, $AC0.M + 0629 4100 addr $ACC1, $AX0.L + + 062a 1b7f srri @$AR3, $AC1.M + 062b 0004 dar $AR0 + 062c 189f lrrd $AC1.M, @$AR0 + 062d 1adf srrd @$AR2, $AC1.M + 062e 189f lrrd $AC1.M, @$AR0 + 062f 1adf srrd @$AR2, $AC1.M + 0630 189f lrrd $AC1.M, @$AR0 + 0631 1adf srrd @$AR2, $AC1.M + 0632 189f lrrd $AC1.M, @$AR0 + 0633 1adf srrd @$AR2, $AC1.M + 0634 1adc srrd @$AR2, $AC0.L + 0635 0082 0bd2 lri $AR2, #0x0bd2 + 0637 27dc lrs $AC1.M, @yn2 + 0638 1adf srrd @$AR2, $AC1.M + 0639 27db lrs $AC1.M, @yn1 + 063a 1adf srrd @$AR2, $AC1.M + 063b 27da lrs $AC1.M, @scale + 063c 1adf srrd @$AR2, $AC1.M + 063d 0082 0bbe lri $AR2, #0x0bbe + 063f 27d9 lrs $AC1.M, @ACCAL + 0640 1adf srrd @$AR2, $AC1.M + 0641 27d8 lrs $AC1.M, @ACCAH + 0642 1adf srrd @$AR2, $AC1.M + 0643 8f00 set40 + 0644 00c1 0e42 lr $AR1, @0x0e42 + 0646 0082 0d80 lri $AR2, #0x0d80 + 0648 1940 lrri $AR0, @$AR2 + 0649 1943 lrri $AR3, @$AR2 + 064a 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 064b b8c0 mulx'ld $AX0.H, $AX1.H : $AX0.L, $AX1.L, @$AR0 + 064c 111f 0654 bloopi #0x1f, 0x0654 + 064e a6f0 mulxmv'ld $AX0.L, $AX1.L, $ACC0 : $AX0.H, $AX1.H, @$AR0 + 064f bcf0 mulxac'ld $AX0.H, $AX1.H, $ACC0 : $AX0.H, $AX1.H, @$AR0 + 0650 1940 lrri $AR0, @$AR2 + 0651 1943 lrri $AR3, @$AR2 + 0652 bcf0 mulxac'ld $AX0.H, $AX1.H, $ACC0 : $AX0.H, $AX1.H, @$AR0 + 0653 4ec0 addp'ld $ACC0 : $AX0.L, $AX1.L, @$AR0 + 0654 b831 mulx's $AX0.H, $AX1.H : @$AR1, $AC0.M + + 0655 a6f0 mulxmv'ld $AX0.L, $AX1.L, $ACC0 : $AX0.H, $AX1.H, @$AR0 + 0656 bcf0 mulxac'ld $AX0.H, $AX1.H, $ACC0 : $AX0.H, $AX1.H, @$AR0 + 0657 bc00 mulxac $AX0.H, $AX1.H, $ACC0 + 0658 4e00 addp $ACC0 + 0659 1b3e srri @$AR1, $AC0.M + 065a 00e1 0e42 sr @0x0e42, $AR1 + + 065c 02df ret +} + +void SRC_Linear() { + // Copy pb's data [pb.addr.format to pb.adpm.yn2] to corresponding hw regs + // 065d 0082 0bb8 lri $AR2, #0x0bb8 + // 065f 195e lrri $AC0.M, @$AR2 + // 0660 2ed1 srs @SampleFormat, $AC0.M + // 0661 195e lrri $AC0.M, @$AR2 + // 0662 2ed4 srs @ACSAH, $AC0.M + // 0663 195e lrri $AC0.M, @$AR2 + // 0664 2ed5 srs @ACSAL, $AC0.M + // 0665 195e lrri $AC0.M, @$AR2 + // 0666 2ed6 srs @ACEAH, $AC0.M + // 0667 195e lrri $AC0.M, @$AR2 + // 0668 2ed7 srs @ACEAL, $AC0.M + // 0669 195e lrri $AC0.M, @$AR2 + // 066a 2ed8 srs @ACCAH, $AC0.M + // 066b 195e lrri $AC0.M, @$AR2 + // 066c 2ed9 srs @ACCAL, $AC0.M + // 066d 195e lrri $AC0.M, @$AR2 + // 066e 2ea0 srs @COEF_A1_0, $AC0.M + // 066f 195e lrri $AC0.M, @$AR2 + // 0670 2ea1 srs @COEF_A2_0, $AC0.M + // 0671 195e lrri $AC0.M, @$AR2 + // 0672 2ea2 srs @COEF_A1_1, $AC0.M + // 0673 195e lrri $AC0.M, @$AR2 + // 0674 2ea3 srs @COEF_A2_1, $AC0.M + // 0675 195e lrri $AC0.M, @$AR2 + // 0676 2ea4 srs @COEF_A1_2, $AC0.M + // 0677 195e lrri $AC0.M, @$AR2 + // 0678 2ea5 srs @COEF_A2_2, $AC0.M + // 0679 195e lrri $AC0.M, @$AR2 + // 067a 2ea6 srs @COEF_A1_3, $AC0.M + // 067b 195e lrri $AC0.M, @$AR2 + // 067c 2ea7 srs @COEF_A2_3, $AC0.M + // 067d 195e lrri $AC0.M, @$AR2 + // 067e 2ea8 srs @COEF_A1_4, $AC0.M + // 067f 195e lrri $AC0.M, @$AR2 + // 0680 2ea9 srs @COEF_A2_4, $AC0.M + // 0681 195e lrri $AC0.M, @$AR2 + // 0682 2eaa srs @COEF_A1_5, $AC0.M + // 0683 195e lrri $AC0.M, @$AR2 + // 0684 2eab srs @COEF_A2_5, $AC0.M + // 0685 195e lrri $AC0.M, @$AR2 + // 0686 2eac srs @COEF_A1_6, $AC0.M + // 0687 195e lrri $AC0.M, @$AR2 + // 0688 2ead srs @COEF_A2_6, $AC0.M + // 0689 195e lrri $AC0.M, @$AR2 + // 068a 2eae srs @COEF_A1_7, $AC0.M + // 068b 195e lrri $AC0.M, @$AR2 + // 068c 2eaf srs @COEF_A2_7, $AC0.M + // 068d 195e lrri $AC0.M, @$AR2 + // 068e 2ede srs @GAIN, $AC0.M + // 068f 195e lrri $AC0.M, @$AR2 + // 0690 2eda srs @scale, $AC0.M + // 0691 195e lrri $AC0.M, @$AR2 + // 0692 2edb srs @yn1, $AC0.M + // 0693 195e lrri $AC0.M, @$AR2 + // 0694 2edc srs @yn2, $AC0.M + + // 0695 8c00 clr15 // signed mulx + // 0696 8a00 m2 // *2 + // 0697 8e00 set16 // no sign extend + + // 0698 195b lrri $AX1.H, @$AR2 + // 0699 1959 lrri $AX1.L, @$AR2 + // 069a 8100 clr $ACC0 + // 069b 195c lrri $AC0.L, @$AR2 + // 069c 0080 0e44 lri $AR0, #0x0e44 + // 069e 195f lrri $AC1.M, @$AR2 + // 069f 195f lrri $AC1.M, @$AR2 + // 06a0 195f lrri $AC1.M, @$AR2 + // 06a1 1b1f srri @$AR0, $AC1.M + AR0 = 0x0e44 + AX1.H = pb.src.ratioHi + AX1.L = pb.src.ratioLo + AC0.L = pb.src.currentAddressFrac + AC1.M = pb.src.last_samples[2] + + *0x0e44 = pb.src.last_samples[2] + *0x0e45 = pb.src.last_samples[3] + + // 06a2 185f lrr $AC1.M, @$AR2 + // 06a3 1b1f srri @$AR0, $AC1.M + // 06a4 6b00 movax $ACC1, $AX1 + // 06a5 1505 lsl $ACC1, #5 + // 06a6 4d00 add $ACC1, $ACC0 + // 06a7 157e lsr $ACC1, #-2 + // 06a8 1c9f mrr $IX0, $AC1.M + // 06a9 1cbd mrr $IX1, $AC1.L + ACC1 = (pb.src.currentAddressFrac + (pb.src.ratio << 5)) >> 2 + IX0 = ACC1 >> 16 + IX1 = ((ACC1 & 0xffff) & 0xc000) >> 14 + IX2 = ~((ACC1 >> 16) - 32) + AX0.H = 0x01fc + AC0.M = 0x0e45 + AR1 = 0xffdd // DSP_ACCELERATOR + AR3 = 0x0d80 + + // 06aa 05e0 addis $AC1.M, #0xe0 + // 06ab 9900 asr16 $ACC1 + // 06ac 7d00 neg $ACC1 + // 06ad 1cdd mrr $IX2, $AC1.L + // 06ae 8900 clr $ACC1 + // 06af 1fa5 mrr $AC1.L, $IX1 + // 06b0 1502 lsl $ACC1, #2 + // 06b1 1cbf mrr $IX1, $AC1.M + // 06b2 009a 01fc lri $AX0.H, #0x01fc + // 06b4 009e 0e45 lri $AC0.M, #0x0e45 + // 06b6 0081 ffdd lri $AR1, #0xffdd + // 06b8 0083 0d80 lri $AR3, #0x0d80 + // 06ba 0064 06cb bloop $IX0, 0x06cb + // 06bc 1827 lrr $IX3, @$AR1 + // 06bd 1b07 srri @$AR0, $IX3 + // 06be 4a00 addax $ACC0, $AX1 + // 06bf 1b7e srri @$AR3, $AC0.M + // 06c0 1827 lrr $IX3, @$AR1 + // 06c1 1b07 srri @$AR0, $IX3 + // 06c2 1b7c srri @$AR3, $AC0.L + // 06c3 0000 nop + // 06c4 1827 lrr $IX3, @$AR1 + // 06c5 1b07 srri @$AR0, $IX3 + // 06c6 0000 nop + // 06c7 0000 nop + // 06c8 1827 lrr $IX3, @$AR1 + // 06c9 1b07 srri @$AR0, $IX3 + // 06ca 0000 nop + // 06cb 0000 nop + ACCO = (0x0e45 << 16) + pb.src.currentAddressFrac + for (i = 0; i < IX0; i++) { + ACC0 += pb.src.ratio + *(0x0d80++) = ACC0 >> 16 + *(0x0d80++) = ACC0 & 0xffff + *(0x0e46++) = *DSP_ACCELERATOR + *(0x0e46++) = *DSP_ACCELERATOR + *(0x0e46++) = *DSP_ACCELERATOR + *(0x0e46++) = *DSP_ACCELERATOR + } + + // 06cc 0065 06d1 bloop $IX1, 0x06d1 + // 06ce 1827 lrr $IX3, @$AR1 + // 06cf 1b07 srri @$AR0, $IX3 + // 06d0 0000 nop + // 06d1 0000 nop + for (i = 0; i < IX1; i++) { + *(0x0e46++) = *DSP_ACCELERATOR + } + + // 06d2 0066 06d6 bloop $IX2, 0x06d6 + // 06d4 4a00 addax $ACC0, $AX1 + // 06d5 1b7e srri @$AR3, $AC0.M + // 06d6 1b7c srri @$AR3, $AC0.L + for (i = 0; i < IX2; i++) { + ACC0 += pb.src.ratio + *(0x0d80++) = ACC0 >> 16 + *(0x0d80++) = ACC0 & 0xffff + } + + // 06d7 0004 dar $AR0 + // 06d8 189f lrrd $AC1.M, @$AR0 + // 06d9 1adf srrd @$AR2, $AC1.M + // 06da 189f lrrd $AC1.M, @$AR0 + // 06db 1adf srrd @$AR2, $AC1.M + // 06dc 189f lrrd $AC1.M, @$AR0 + // 06dd 1adf srrd @$AR2, $AC1.M + // 06de 189f lrrd $AC1.M, @$AR0 + // 06df 1adf srrd @$AR2, $AC1.M + // 06e0 1adc srrd @$AR2, $AC0.L + *(0x0e46++)-- + pb.src.last_samples[3] = *(0x0e46--) + pb.src.last_samples[2] = *(0x0e46--) + pb.src.last_samples[1] = *(0x0e46--) + pb.src.last_samples[0] = *(0x0e46--) + pb.src.currentAddressFrac = ACC0 & 0xffff + + // 06e1 0082 0bd2 lri $AR2, #0x0bd2 + // 06e3 27dc lrs $AC1.M, @yn2 + // 06e4 1adf srrd @$AR2, $AC1.M + // 06e5 27db lrs $AC1.M, @yn1 + // 06e6 1adf srrd @$AR2, $AC1.M + // 06e7 27da lrs $AC1.M, @scale + // 06e8 1adf srrd @$AR2, $AC1.M + // 06e9 0082 0bbe lri $AR2, #0x0bbe + // 06eb 27d9 lrs $AC1.M, @ACCAL + // 06ec 1adf srrd @$AR2, $AC1.M + // 06ed 27d8 lrs $AC1.M, @ACCAH + // 06ee 1adf srrd @$AR2, $AC1.M + pb.adpm.yn2 = *yn2 + pb.adpm.yn1 = *yn1 + pb.adpm.pred_scale = *scale + pb.addr.currentAddressLo = *ACCAL // Current playback position + pb.addr.currentAddressHi = *ACCAH + + 06ef 8d00 set15 // unsigned mulx + 06f0 8b00 m0 // no *2 + 06f1 8f00 set40 // sign extend + 06f2 00c1 0e42 lr $AR1, @0x0e42 + 06f4 0082 0d80 lri $AR2, #0x0d80 + 06f6 8100 clr $ACC0 + 06f7 1120 0703 bloopi #0x20, 0x0703 + 06f9 8900 clr $ACC1 + 06fa 1940 lrri $AR0, @$AR2 + 06fb 189e lrrd $AC0.M, @$AR0 + 06fc 181b lrr $AX1.H, @$AR0 + 06fd 199a lrrn $AX0.H, @$AR0 + 06fe 5400 subr $ACC0, $AX0.H + 06ff 1f5e mrr $AX0.H, $AC0.M + 0700 1959 lrri $AX1.L, @$AR2 + 0701 b000 mulx $AX0.H, $AX1.L + 0702 fb00 addpaxz $ACC1, $AX1 + 0703 8139 clr's $ACC0 : @$AR1, $AC1.M + + 0704 00e1 0e42 sr @0x0e42, $AR1 + + 0706 02df ret +} + +void SRC_None() { + // Copy pb's data [pb.addr.format to pb.adpm.yn2] to corresponding hw regs + // 0707 0082 0bb8 lri $AR2, #0x0bb8 + // 0709 195e lrri $AC0.M, @$AR2 + // 070a 2ed1 srs @SampleFormat, $AC0.M + // 070b 195e lrri $AC0.M, @$AR2 + // 070c 2ed4 srs @ACSAH, $AC0.M + // 070d 195e lrri $AC0.M, @$AR2 + // 070e 2ed5 srs @ACSAL, $AC0.M + // 070f 195e lrri $AC0.M, @$AR2 + // 0710 2ed6 srs @ACEAH, $AC0.M + // 0711 195e lrri $AC0.M, @$AR2 + // 0712 2ed7 srs @ACEAL, $AC0.M + // 0713 195e lrri $AC0.M, @$AR2 + // 0714 2ed8 srs @ACCAH, $AC0.M + // 0715 195e lrri $AC0.M, @$AR2 + // 0716 2ed9 srs @ACCAL, $AC0.M + // 0717 195e lrri $AC0.M, @$AR2 + // 0718 2ea0 srs @COEF_A1_0, $AC0.M + // 0719 195e lrri $AC0.M, @$AR2 + // 071a 2ea1 srs @COEF_A2_0, $AC0.M + // 071b 195e lrri $AC0.M, @$AR2 + // 071c 2ea2 srs @COEF_A1_1, $AC0.M + // 071d 195e lrri $AC0.M, @$AR2 + // 071e 2ea3 srs @COEF_A2_1, $AC0.M + // 071f 195e lrri $AC0.M, @$AR2 + // 0720 2ea4 srs @COEF_A1_2, $AC0.M + // 0721 195e lrri $AC0.M, @$AR2 + // 0722 2ea5 srs @COEF_A2_2, $AC0.M + // 0723 195e lrri $AC0.M, @$AR2 + // 0724 2ea6 srs @COEF_A1_3, $AC0.M + // 0725 195e lrri $AC0.M, @$AR2 + // 0726 2ea7 srs @COEF_A2_3, $AC0.M + // 0727 195e lrri $AC0.M, @$AR2 + // 0728 2ea8 srs @COEF_A1_4, $AC0.M + // 0729 195e lrri $AC0.M, @$AR2 + // 072a 2ea9 srs @COEF_A2_4, $AC0.M + // 072b 195e lrri $AC0.M, @$AR2 + // 072c 2eaa srs @COEF_A1_5, $AC0.M + // 072d 195e lrri $AC0.M, @$AR2 + // 072e 2eab srs @COEF_A2_5, $AC0.M + // 072f 195e lrri $AC0.M, @$AR2 + // 0730 2eac srs @COEF_A1_6, $AC0.M + // 0731 195e lrri $AC0.M, @$AR2 + // 0732 2ead srs @COEF_A2_6, $AC0.M + // 0733 195e lrri $AC0.M, @$AR2 + // 0734 2eae srs @COEF_A1_7, $AC0.M + // 0735 195e lrri $AC0.M, @$AR2 + // 0736 2eaf srs @COEF_A2_7, $AC0.M + // 0737 195e lrri $AC0.M, @$AR2 + // 0738 2ede srs @GAIN, $AC0.M + // 0739 195e lrri $AC0.M, @$AR2 + // 073a 2eda srs @scale, $AC0.M + // 073b 195e lrri $AC0.M, @$AR2 + // 073c 2edb srs @yn1, $AC0.M + // 073d 195e lrri $AC0.M, @$AR2 + // 073e 2edc srs @yn2, $AC0.M + + // 073f 00c0 0e42 lr $AR0, @0x0e42 + // 0741 0081 ffdd lri $AR1, #0xffdd // DSP_ACCELERATOR + // 0743 1120 0748 bloopi #0x20, 0x0748 + // 0745 1824 lrr $IX0, @$AR1 + // 0746 1b04 srri @$AR0, $IX0 + // 0747 0000 nop + // 0748 0000 nop + // 0749 00e0 0e42 sr @0x0e42, $AR0 + + u16 i = *0x0e42 + for (; i < ((*0x0e42) + 0x20); i++) { + *i = *DSP_ACCELERATOR + } + *0x0e42 = i + + // 074b 0082 0bd9 lri $AR2, #0x0bd9 // pb.src.last_samples[3] + // 074d 0004 dar $AR0 + // 074e 189f lrrd $AC1.M, @$AR0 + // 074f 1adf srrd @$AR2, $AC1.M + // 0750 189f lrrd $AC1.M, @$AR0 + // 0751 1adf srrd @$AR2, $AC1.M + // 0752 189f lrrd $AC1.M, @$AR0 + // 0753 1adf srrd @$AR2, $AC1.M + // 0754 189f lrrd $AC1.M, @$AR0 + // 0755 1adf srrd @$AR2, $AC1.M + // 0756 8900 clr $ACC1 + // 0757 1adc srrd @$AR2, $AC0.L // uhhh assume AC0.L is 0? + i-- // Guess that 0x0e42 points to struct of 1 pointer and 32 values + pb.src.last_samples[3] = *(i--) + pb.src.last_samples[2] = *(i--) + pb.src.last_samples[1] = *(i--) + pb.src.last_samples[0] = *(i--) + pb.src.currentAddressFrac = 0 + + // 0758 27dc lrs $AC1.M, @yn2 + // 0759 00ff 0bd2 sr @0x0bd2, $AC1.M + // 075b 27db lrs $AC1.M, @yn1 + // 075c 00ff 0bd1 sr @0x0bd1, $AC1.M + // 075e 27da lrs $AC1.M, @scale + // 075f 00ff 0bd0 sr @0x0bd0, $AC1.M + // 0761 27d9 lrs $AC1.M, @ACCAL + // 0762 00ff 0bbe sr @0x0bbe, $AC1.M + // 0764 27d8 lrs $AC1.M, @ACCAH + // 0765 00ff 0bbd sr @0x0bbd, $AC1.M + pb.adpm.yn2 = *yn2 + pb.adpm.yn1 = *yn1 + pb.adpm.pred_scale = *scale + pb.addr.currentAddressLo = *ACCAL // Current playback position + pb.addr.currentAddressHi = *ACCAH + + 0767 02df ret +} + + +# From here to the jump tables, all the funcs just wrap calls to mixer(s) in IROM + +void Mixer_0() { + 0768 00c0 0e40 lr $AR0, @0x0e40 + 076a 0081 0b89 lri $AR1, #0x0b89 + 076c 00c2 0e08 lr $AR2, @0x0e08 + 076e 1c62 mrr $AR3, $AR2 + 076f 00c4 0e41 lr $IX0, @0x0e41 + 0771 00c5 0e09 lr $IX1, @0x0e09 + 0773 02bf 80e7 call 0x80e7 + 0775 00f8 0ba9 sr @0x0ba9, $AX0.L + 0777 00fb 0bac sr @0x0bac, $AX1.H + 0779 02df ret +} + +void Mixer_1() { + 077a 00c0 0e40 lr $AR0, @0x0e40 + 077c 0081 0b89 lri $AR1, #0x0b89 + 077e 00c2 0e08 lr $AR2, @0x0e08 + 0780 1c62 mrr $AR3, $AR2 + 0781 00c4 0e41 lr $IX0, @0x0e41 + 0783 00c5 0e09 lr $IX1, @0x0e09 + 0785 02bf 80e7 call 0x80e7 + 0787 00f8 0ba9 sr @0x0ba9, $AX0.L + 0789 00fb 0bac sr @0x0bac, $AX1.H + 078b 00c0 0e40 lr $AR0, @0x0e40 + 078d 0081 0b8d lri $AR1, #0x0b8d + 078f 00c2 0e0b lr $AR2, @0x0e0b + 0791 1c62 mrr $AR3, $AR2 + 0792 00c4 0e41 lr $IX0, @0x0e41 + 0794 00c5 0e0c lr $IX1, @0x0e0c + 0796 02bf 80e7 call 0x80e7 + 0798 00f8 0baa sr @0x0baa, $AX0.L + 079a 00fb 0bad sr @0x0bad, $AX1.H + 079c 02df ret +} + +void Mixer_2() { + 079d 00c0 0e40 lr $AR0, @0x0e40 + 079f 0081 0b89 lri $AR1, #0x0b89 + 07a1 00c2 0e08 lr $AR2, @0x0e08 + 07a3 1c62 mrr $AR3, $AR2 + 07a4 00c4 0e41 lr $IX0, @0x0e41 + 07a6 00c5 0e09 lr $IX1, @0x0e09 + 07a8 02bf 80e7 call 0x80e7 + 07aa 00f8 0ba9 sr @0x0ba9, $AX0.L + 07ac 00fb 0bac sr @0x0bac, $AX1.H + 07ae 00c0 0e40 lr $AR0, @0x0e40 + 07b0 0081 0b91 lri $AR1, #0x0b91 + 07b2 00c2 0e0e lr $AR2, @0x0e0e + 07b4 1c62 mrr $AR3, $AR2 + 07b5 00c4 0e41 lr $IX0, @0x0e41 + 07b7 00c5 0e0f lr $IX1, @0x0e0f + 07b9 02bf 80e7 call 0x80e7 + 07bb 00f8 0bab sr @0x0bab, $AX0.L + 07bd 00fb 0bae sr @0x0bae, $AX1.H + 07bf 02df ret +} + +void Unk() { + 07c0 00c0 0e40 lr $AR0, @0x0e40 + 07c2 0081 0b89 lri $AR1, #0x0b89 + 07c4 00c2 0e08 lr $AR2, @0x0e08 + 07c6 1c62 mrr $AR3, $AR2 + 07c7 00c4 0e41 lr $IX0, @0x0e41 + 07c9 00c5 0e09 lr $IX1, @0x0e09 + 07cb 02bf 80e7 call 0x80e7 + 07cd 00f8 0ba9 sr @0x0ba9, $AX0.L + 07cf 00fb 0bac sr @0x0bac, $AX1.H + 07d1 00c0 0e40 lr $AR0, @0x0e40 + 07d3 0081 0b8d lri $AR1, #0x0b8d + 07d5 00c2 0e0b lr $AR2, @0x0e0b + 07d7 1c62 mrr $AR3, $AR2 + 07d8 00c4 0e41 lr $IX0, @0x0e41 + 07da 00c5 0e0c lr $IX1, @0x0e0c + 07dc 02bf 80e7 call 0x80e7 + 07de 00f8 0baa sr @0x0baa, $AX0.L + 07e0 00fb 0bad sr @0x0bad, $AX1.H + 07e2 00c0 0e40 lr $AR0, @0x0e40 + 07e4 0081 0b91 lri $AR1, #0x0b91 + 07e6 00c2 0e0e lr $AR2, @0x0e0e + 07e8 1c62 mrr $AR3, $AR2 + 07e9 00c4 0e41 lr $IX0, @0x0e41 + 07eb 00c5 0e0f lr $IX1, @0x0e0f + 07ed 02bf 80e7 call 0x80e7 + 07ef 00f8 0bab sr @0x0bab, $AX0.L + 07f1 00fb 0bae sr @0x0bae, $AX1.H + 07f3 02df ret +} + +void Unk() { + 07f4 00c0 0e40 lr $AR0, @0x0e40 + 07f6 0081 0b89 lri $AR1, #0x0b89 + 07f8 00c2 0e08 lr $AR2, @0x0e08 + 07fa 1c62 mrr $AR3, $AR2 + 07fb 00c4 0e41 lr $IX0, @0x0e41 + 07fd 00c5 0e09 lr $IX1, @0x0e09 + 07ff 02bf 80e7 call 0x80e7 + 0801 00f8 0ba9 sr @0x0ba9, $AX0.L + 0803 00fb 0bac sr @0x0bac, $AX1.H + 0805 00c0 0e43 lr $AR0, @0x0e43 + 0807 0081 0b97 lri $AR1, #0x0b97 + 0809 00c2 0e0a lr $AR2, @0x0e0a + 080b 1c62 mrr $AR3, $AR2 + 080c 02bf 81f9 call 0x81f9 + 080e 00f8 0baf sr @0x0baf, $AX0.L + 0810 02df ret +} + +void Unk() { + 0811 00c0 0e40 lr $AR0, @0x0e40 + 0813 0081 0b89 lri $AR1, #0x0b89 + 0815 00c2 0e08 lr $AR2, @0x0e08 + 0817 1c62 mrr $AR3, $AR2 + 0818 00c4 0e41 lr $IX0, @0x0e41 + 081a 00c5 0e09 lr $IX1, @0x0e09 + 081c 02bf 80e7 call 0x80e7 + 081e 00f8 0ba9 sr @0x0ba9, $AX0.L + 0820 00fb 0bac sr @0x0bac, $AX1.H + 0822 00c0 0e40 lr $AR0, @0x0e40 + 0824 0081 0b8d lri $AR1, #0x0b8d + 0826 00c2 0e0b lr $AR2, @0x0e0b + 0828 1c62 mrr $AR3, $AR2 + 0829 00c4 0e41 lr $IX0, @0x0e41 + 082b 00c5 0e0c lr $IX1, @0x0e0c + 082d 02bf 80e7 call 0x80e7 + 082f 00f8 0baa sr @0x0baa, $AX0.L + 0831 00fb 0bad sr @0x0bad, $AX1.H + 0833 00c0 0e43 lr $AR0, @0x0e43 + 0835 0081 0b97 lri $AR1, #0x0b97 + 0837 00c2 0e0a lr $AR2, @0x0e0a + 0839 1c62 mrr $AR3, $AR2 + 083a 1c80 mrr $IX0, $AR0 + 083b 00c5 0e0d lr $IX1, @0x0e0d + 083d 02bf 80e7 call 0x80e7 + 083f 00f8 0baf sr @0x0baf, $AX0.L + 0841 00fb 0bb0 sr @0x0bb0, $AX1.H + 0843 02df ret +} + +void Unk() { + 0844 00c0 0e40 lr $AR0, @0x0e40 + 0846 0081 0b89 lri $AR1, #0x0b89 + 0848 00c2 0e08 lr $AR2, @0x0e08 + 084a 1c62 mrr $AR3, $AR2 + 084b 00c4 0e41 lr $IX0, @0x0e41 + 084d 00c5 0e09 lr $IX1, @0x0e09 + 084f 02bf 80e7 call 0x80e7 + 0851 00f8 0ba9 sr @0x0ba9, $AX0.L + 0853 00fb 0bac sr @0x0bac, $AX1.H + 0855 00c0 0e40 lr $AR0, @0x0e40 + 0857 0081 0b91 lri $AR1, #0x0b91 + 0859 00c2 0e0e lr $AR2, @0x0e0e + 085b 1c62 mrr $AR3, $AR2 + 085c 00c4 0e41 lr $IX0, @0x0e41 + 085e 00c5 0e0f lr $IX1, @0x0e0f + 0860 02bf 80e7 call 0x80e7 + 0862 00f8 0bab sr @0x0bab, $AX0.L + 0864 00fb 0bae sr @0x0bae, $AX1.H + 0866 00c0 0e43 lr $AR0, @0x0e43 + 0868 0081 0b95 lri $AR1, #0x0b95 + 086a 00c2 0e10 lr $AR2, @0x0e10 + 086c 1c62 mrr $AR3, $AR2 + 086d 1c80 mrr $IX0, $AR0 + 086e 00c5 0e0a lr $IX1, @0x0e0a + 0870 02bf 80e7 call 0x80e7 + 0872 00f8 0bb1 sr @0x0bb1, $AX0.L + 0874 00fb 0baf sr @0x0baf, $AX1.H + 0876 02df ret +} + +void Unk() { + 0877 00c0 0e40 lr $AR0, @0x0e40 + 0879 0081 0b89 lri $AR1, #0x0b89 + 087b 00c2 0e08 lr $AR2, @0x0e08 + 087d 1c62 mrr $AR3, $AR2 + 087e 00c4 0e41 lr $IX0, @0x0e41 + 0880 00c5 0e09 lr $IX1, @0x0e09 + 0882 02bf 80e7 call 0x80e7 + 0884 00f8 0ba9 sr @0x0ba9, $AX0.L + 0886 00fb 0bac sr @0x0bac, $AX1.H + 0888 00c0 0e40 lr $AR0, @0x0e40 + 088a 0081 0b8d lri $AR1, #0x0b8d + 088c 00c2 0e0b lr $AR2, @0x0e0b + 088e 1c62 mrr $AR3, $AR2 + 088f 00c4 0e41 lr $IX0, @0x0e41 + 0891 00c5 0e0c lr $IX1, @0x0e0c + 0893 02bf 80e7 call 0x80e7 + 0895 00f8 0baa sr @0x0baa, $AX0.L + 0897 00fb 0bad sr @0x0bad, $AX1.H + 0899 00c0 0e40 lr $AR0, @0x0e40 + 089b 0081 0b91 lri $AR1, #0x0b91 + 089d 00c2 0e0e lr $AR2, @0x0e0e + 089f 1c62 mrr $AR3, $AR2 + 08a0 00c4 0e41 lr $IX0, @0x0e41 + 08a2 00c5 0e0f lr $IX1, @0x0e0f + 08a4 02bf 80e7 call 0x80e7 + 08a6 00f8 0bab sr @0x0bab, $AX0.L + 08a8 00fb 0bae sr @0x0bae, $AX1.H + 08aa 00c0 0e43 lr $AR0, @0x0e43 + 08ac 0081 0b97 lri $AR1, #0x0b97 + 08ae 00c2 0e0a lr $AR2, @0x0e0a + 08b0 1c62 mrr $AR3, $AR2 + 08b1 1c80 mrr $IX0, $AR0 + 08b2 00c5 0e0d lr $IX1, @0x0e0d + 08b4 02bf 80e7 call 0x80e7 + 08b6 00f8 0baf sr @0x0baf, $AX0.L + 08b8 00fb 0bb0 sr @0x0bb0, $AX1.H + 08ba 00c0 0e43 lr $AR0, @0x0e43 + 08bc 0081 0b95 lri $AR1, #0x0b95 + 08be 00c2 0e10 lr $AR2, @0x0e10 + 08c0 1c62 mrr $AR3, $AR2 + 08c1 02bf 81f9 call 0x81f9 + 08c3 00f8 0bb1 sr @0x0bb1, $AX0.L + 08c5 02df ret +} + +void Unk() { + 08c6 00c0 0e40 lr $AR0, @0x0e40 + 08c8 0081 0b89 lri $AR1, #0x0b89 + 08ca 00c2 0e08 lr $AR2, @0x0e08 + 08cc 0083 0e44 lri $AR3, #0x0e44 + 08ce 00c4 0e41 lr $IX0, @0x0e41 + 08d0 00c5 0e09 lr $IX1, @0x0e09 + 08d2 02bf 8282 call 0x8282 + 08d4 00f8 0ba9 sr @0x0ba9, $AX0.L + 08d6 00fb 0bac sr @0x0bac, $AX1.H + 08d8 02df ret +} + +void Unk() { + 08d9 00c0 0e40 lr $AR0, @0x0e40 + 08db 0081 0b89 lri $AR1, #0x0b89 + 08dd 00c2 0e08 lr $AR2, @0x0e08 + 08df 0083 0e44 lri $AR3, #0x0e44 + 08e1 00c4 0e41 lr $IX0, @0x0e41 + 08e3 00c5 0e09 lr $IX1, @0x0e09 + 08e5 02bf 8282 call 0x8282 + 08e7 00f8 0ba9 sr @0x0ba9, $AX0.L + 08e9 00fb 0bac sr @0x0bac, $AX1.H + 08eb 00c0 0e40 lr $AR0, @0x0e40 + 08ed 0081 0b8d lri $AR1, #0x0b8d + 08ef 00c2 0e0b lr $AR2, @0x0e0b + 08f1 0083 0e44 lri $AR3, #0x0e44 + 08f3 00c4 0e41 lr $IX0, @0x0e41 + 08f5 00c5 0e0c lr $IX1, @0x0e0c + 08f7 02bf 8282 call 0x8282 + 08f9 00f8 0baa sr @0x0baa, $AX0.L + 08fb 00fb 0bad sr @0x0bad, $AX1.H + 08fd 02df ret +} + +void Unk() { + 08fe 00c0 0e40 lr $AR0, @0x0e40 + 0900 0081 0b89 lri $AR1, #0x0b89 + 0902 00c2 0e08 lr $AR2, @0x0e08 + 0904 0083 0e44 lri $AR3, #0x0e44 + 0906 00c4 0e41 lr $IX0, @0x0e41 + 0908 00c5 0e09 lr $IX1, @0x0e09 + 090a 02bf 8282 call 0x8282 + 090c 00f8 0ba9 sr @0x0ba9, $AX0.L + 090e 00fb 0bac sr @0x0bac, $AX1.H + 0910 00c0 0e40 lr $AR0, @0x0e40 + 0912 0081 0b91 lri $AR1, #0x0b91 + 0914 00c2 0e0e lr $AR2, @0x0e0e + 0916 0083 0e44 lri $AR3, #0x0e44 + 0918 00c4 0e41 lr $IX0, @0x0e41 + 091a 00c5 0e0f lr $IX1, @0x0e0f + 091c 02bf 8282 call 0x8282 + 091e 00f8 0bab sr @0x0bab, $AX0.L + 0920 00fb 0bae sr @0x0bae, $AX1.H + 0922 02df ret +} + +void Unk() { + 0923 00c0 0e40 lr $AR0, @0x0e40 + 0925 0081 0b89 lri $AR1, #0x0b89 + 0927 00c2 0e08 lr $AR2, @0x0e08 + 0929 0083 0e44 lri $AR3, #0x0e44 + 092b 00c4 0e41 lr $IX0, @0x0e41 + 092d 00c5 0e09 lr $IX1, @0x0e09 + 092f 02bf 8282 call 0x8282 + 0931 00f8 0ba9 sr @0x0ba9, $AX0.L + 0933 00fb 0bac sr @0x0bac, $AX1.H + 0935 00c0 0e40 lr $AR0, @0x0e40 + 0937 0081 0b8d lri $AR1, #0x0b8d + 0939 00c2 0e0b lr $AR2, @0x0e0b + 093b 0083 0e44 lri $AR3, #0x0e44 + 093d 00c4 0e41 lr $IX0, @0x0e41 + 093f 00c5 0e0c lr $IX1, @0x0e0c + 0941 02bf 8282 call 0x8282 + 0943 00f8 0baa sr @0x0baa, $AX0.L + 0945 00fb 0bad sr @0x0bad, $AX1.H + 0947 00c0 0e40 lr $AR0, @0x0e40 + 0949 0081 0b91 lri $AR1, #0x0b91 + 094b 00c2 0e0e lr $AR2, @0x0e0e + 094d 0083 0e44 lri $AR3, #0x0e44 + 094f 00c4 0e41 lr $IX0, @0x0e41 + 0951 00c5 0e0f lr $IX1, @0x0e0f + 0953 02bf 8282 call 0x8282 + 0955 00f8 0bab sr @0x0bab, $AX0.L + 0957 00fb 0bae sr @0x0bae, $AX1.H + 0959 02df ret +} + +void Unk() { + 095a 00c0 0e40 lr $AR0, @0x0e40 + 095c 0081 0b89 lri $AR1, #0x0b89 + 095e 00c2 0e08 lr $AR2, @0x0e08 + 0960 0083 0e44 lri $AR3, #0x0e44 + 0962 00c4 0e41 lr $IX0, @0x0e41 + 0964 00c5 0e09 lr $IX1, @0x0e09 + 0966 02bf 8282 call 0x8282 + 0968 00f8 0ba9 sr @0x0ba9, $AX0.L + 096a 00fb 0bac sr @0x0bac, $AX1.H + 096c 00c0 0e43 lr $AR0, @0x0e43 + 096e 0081 0b97 lri $AR1, #0x0b97 + 0970 00c2 0e0a lr $AR2, @0x0e0a + 0972 0083 0e44 lri $AR3, #0x0e44 + 0974 02bf 845d call 0x845d + 0976 00f8 0baf sr @0x0baf, $AX0.L + 0978 02df ret +} + +void Unk() { + 0979 00c0 0e40 lr $AR0, @0x0e40 + 097b 0081 0b89 lri $AR1, #0x0b89 + 097d 00c2 0e08 lr $AR2, @0x0e08 + 097f 0083 0e44 lri $AR3, #0x0e44 + 0981 00c4 0e41 lr $IX0, @0x0e41 + 0983 00c5 0e09 lr $IX1, @0x0e09 + 0985 02bf 8282 call 0x8282 + 0987 00f8 0ba9 sr @0x0ba9, $AX0.L + 0989 00fb 0bac sr @0x0bac, $AX1.H + 098b 00c0 0e40 lr $AR0, @0x0e40 + 098d 0081 0b8d lri $AR1, #0x0b8d + 098f 00c2 0e0b lr $AR2, @0x0e0b + 0991 0083 0e44 lri $AR3, #0x0e44 + 0993 00c4 0e41 lr $IX0, @0x0e41 + 0995 00c5 0e0c lr $IX1, @0x0e0c + 0997 02bf 8282 call 0x8282 + 0999 00f8 0baa sr @0x0baa, $AX0.L + 099b 00fb 0bad sr @0x0bad, $AX1.H + 099d 00c0 0e43 lr $AR0, @0x0e43 + 099f 0081 0b97 lri $AR1, #0x0b97 + 09a1 00c2 0e0a lr $AR2, @0x0e0a + 09a3 0083 0e44 lri $AR3, #0x0e44 + 09a5 1c80 mrr $IX0, $AR0 + 09a6 00c5 0e0d lr $IX1, @0x0e0d + 09a8 02bf 8282 call 0x8282 + 09aa 00f8 0baf sr @0x0baf, $AX0.L + 09ac 00fb 0bb0 sr @0x0bb0, $AX1.H + 09ae 02df ret +} + +void Unk() { + 09af 00c0 0e40 lr $AR0, @0x0e40 + 09b1 0081 0b89 lri $AR1, #0x0b89 + 09b3 00c2 0e08 lr $AR2, @0x0e08 + 09b5 0083 0e44 lri $AR3, #0x0e44 + 09b7 00c4 0e41 lr $IX0, @0x0e41 + 09b9 00c5 0e09 lr $IX1, @0x0e09 + 09bb 02bf 8282 call 0x8282 + 09bd 00f8 0ba9 sr @0x0ba9, $AX0.L + 09bf 00fb 0bac sr @0x0bac, $AX1.H + 09c1 00c0 0e40 lr $AR0, @0x0e40 + 09c3 0081 0b91 lri $AR1, #0x0b91 + 09c5 00c2 0e0e lr $AR2, @0x0e0e + 09c7 0083 0e44 lri $AR3, #0x0e44 + 09c9 00c4 0e41 lr $IX0, @0x0e41 + 09cb 00c5 0e0f lr $IX1, @0x0e0f + 09cd 02bf 8282 call 0x8282 + 09cf 00f8 0bab sr @0x0bab, $AX0.L + 09d1 00fb 0bae sr @0x0bae, $AX1.H + 09d3 00c0 0e43 lr $AR0, @0x0e43 + 09d5 0081 0b95 lri $AR1, #0x0b95 + 09d7 00c2 0e10 lr $AR2, @0x0e10 + 09d9 0083 0e44 lri $AR3, #0x0e44 + 09db 1c80 mrr $IX0, $AR0 + 09dc 00c5 0e0a lr $IX1, @0x0e0a + 09de 02bf 8282 call 0x8282 + 09e0 00f8 0bb1 sr @0x0bb1, $AX0.L + 09e2 00fb 0baf sr @0x0baf, $AX1.H + 09e4 02df ret +} + +void Unk() { + 09e5 00c0 0e40 lr $AR0, @0x0e40 + 09e7 0081 0b89 lri $AR1, #0x0b89 + 09e9 00c2 0e08 lr $AR2, @0x0e08 + 09eb 0083 0e44 lri $AR3, #0x0e44 + 09ed 00c4 0e41 lr $IX0, @0x0e41 + 09ef 00c5 0e09 lr $IX1, @0x0e09 + 09f1 02bf 8282 call 0x8282 + 09f3 00f8 0ba9 sr @0x0ba9, $AX0.L + 09f5 00fb 0bac sr @0x0bac, $AX1.H + 09f7 00c0 0e40 lr $AR0, @0x0e40 + 09f9 0081 0b8d lri $AR1, #0x0b8d + 09fb 00c2 0e0b lr $AR2, @0x0e0b + 09fd 0083 0e44 lri $AR3, #0x0e44 + 09ff 00c0 0e41 lr $AR0, @0x0e41 + 0a01 00c5 0e0c lr $IX1, @0x0e0c + 0a03 02bf 8282 call 0x8282 + 0a05 00f8 0baa sr @0x0baa, $AX0.L + 0a07 00fb 0bad sr @0x0bad, $AX1.H + 0a09 00c0 0e40 lr $AR0, @0x0e40 + 0a0b 0081 0b91 lri $AR1, #0x0b91 + 0a0d 00c2 0e0e lr $AR2, @0x0e0e + 0a0f 0083 0e44 lri $AR3, #0x0e44 + 0a11 00c4 0e41 lr $IX0, @0x0e41 + 0a13 00c5 0e0f lr $IX1, @0x0e0f + 0a15 02bf 8282 call 0x8282 + 0a17 00f8 0bab sr @0x0bab, $AX0.L + 0a19 00fb 0bae sr @0x0bae, $AX1.H + 0a1b 00c0 0e43 lr $AR0, @0x0e43 + 0a1d 0081 0b97 lri $AR1, #0x0b97 + 0a1f 00c2 0e0a lr $AR2, @0x0e0a + 0a21 0083 0e44 lri $AR3, #0x0e44 + 0a23 1c80 mrr $IX0, $AR0 + 0a24 00c5 0e0d lr $IX1, @0x0e0d + 0a26 02bf 8282 call 0x8282 + 0a28 00f8 0baf sr @0x0baf, $AX0.L + 0a2a 00fb 0bb0 sr @0x0bb0, $AX1.H + 0a2c 00c0 0e43 lr $AR0, @0x0e43 + 0a2e 0081 0b95 lri $AR1, #0x0b95 + 0a30 00c2 0e10 lr $AR2, @0x0e10 + 0a32 0083 0e44 lri $AR3, #0x0e44 + 0a34 02bf 845d call 0x845d + 0a36 00f8 0bb1 sr @0x0bb1, $AX0.L + 0a38 02df ret +} + +void Unk() { + 0a39 00c0 0e40 lr $AR0, @0x0e40 + 0a3b 0081 0b89 lri $AR1, #0x0b89 + 0a3d 00c2 0e08 lr $AR2, @0x0e08 + 0a3f 1c62 mrr $AR3, $AR2 + 0a40 00c4 0e41 lr $IX0, @0x0e41 + 0a42 00c5 0e09 lr $IX1, @0x0e09 + 0a44 02bf 80e7 call 0x80e7 + 0a46 00f8 0ba9 sr @0x0ba9, $AX0.L + 0a48 00fb 0bac sr @0x0bac, $AX1.H + 0a4a 00c0 0e43 lr $AR0, @0x0e43 + 0a4c 0081 0b91 lri $AR1, #0x0b91 + 0a4e 00c2 0e0e lr $AR2, @0x0e0e + 0a50 1c62 mrr $AR3, $AR2 + 0a51 1c80 mrr $IX0, $AR0 + 0a52 00c5 0e0f lr $IX1, @0x0e0f + 0a54 02bf 80e7 call 0x80e7 + 0a56 00f8 0bab sr @0x0bab, $AX0.L + 0a58 00fb 0bae sr @0x0bae, $AX1.H + 0a5a 02df ret +} + +void Unk() { + 0a5b 00c0 0e40 lr $AR0, @0x0e40 + 0a5d 0081 0b89 lri $AR1, #0x0b89 + 0a5f 00c2 0e08 lr $AR2, @0x0e08 + 0a61 1c62 mrr $AR3, $AR2 + 0a62 00c4 0e41 lr $IX0, @0x0e41 + 0a64 00c5 0e09 lr $IX1, @0x0e09 + 0a66 02bf 80e7 call 0x80e7 + 0a68 00f8 0ba9 sr @0x0ba9, $AX0.L + 0a6a 00fb 0bac sr @0x0bac, $AX1.H + 0a6c 00c0 0e43 lr $AR0, @0x0e43 + 0a6e 0081 0b91 lri $AR1, #0x0b91 + 0a70 00c2 0e0e lr $AR2, @0x0e0e + 0a72 1c62 mrr $AR3, $AR2 + 0a73 1c80 mrr $IX0, $AR0 + 0a74 00c5 0e0f lr $IX1, @0x0e0f + 0a76 02bf 80e7 call 0x80e7 + 0a78 00f8 0bab sr @0x0bab, $AX0.L + 0a7a 00fb 0bae sr @0x0bae, $AX1.H + 0a7c 00c0 0e40 lr $AR0, @0x0e40 + 0a7e 0081 0b8d lri $AR1, #0x0b8d + 0a80 00c2 0e0b lr $AR2, @0x0e0b + 0a82 1c62 mrr $AR3, $AR2 + 0a83 00c4 0e41 lr $IX0, @0x0e41 + 0a85 00c5 0e0c lr $IX1, @0x0e0c + 0a87 02bf 80e7 call 0x80e7 + 0a89 00f8 0baa sr @0x0baa, $AX0.L + 0a8b 00fb 0bad sr @0x0bad, $AX1.H + 0a8d 00c0 0e43 lr $AR0, @0x0e43 + 0a8f 0081 0b99 lri $AR1, #0x0b99 + 0a91 00c2 0e0d lr $AR2, @0x0e0d + 0a93 1c62 mrr $AR3, $AR2 + 0a94 02bf 81f9 call 0x81f9 + 0a96 00f8 0bb0 sr @0x0bb0, $AX0.L + 0a98 02df ret +} + +void Unk() { + 0a99 00c0 0e40 lr $AR0, @0x0e40 + 0a9b 0081 0b89 lri $AR1, #0x0b89 + 0a9d 00c2 0e08 lr $AR2, @0x0e08 + 0a9f 0083 0e44 lri $AR3, #0x0e44 + 0aa1 00c4 0e41 lr $IX0, @0x0e41 + 0aa3 00c5 0e09 lr $IX1, @0x0e09 + 0aa5 02bf 8282 call 0x8282 + 0aa7 00f8 0ba9 sr @0x0ba9, $AX0.L + 0aa9 00fb 0bac sr @0x0bac, $AX1.H + 0aab 00c0 0e43 lr $AR0, @0x0e43 + 0aad 0081 0b91 lri $AR1, #0x0b91 + 0aaf 00c2 0e0e lr $AR2, @0x0e0e + 0ab1 0083 0e44 lri $AR3, #0x0e44 + 0ab3 1c80 mrr $IX0, $AR0 + 0ab4 00c5 0e0f lr $IX1, @0x0e0f + 0ab6 02bf 8282 call 0x8282 + 0ab8 00f8 0bab sr @0x0bab, $AX0.L + 0aba 00fb 0bae sr @0x0bae, $AX1.H + 0abc 02df ret +} + +void Unk() { + 0abd 00c0 0e40 lr $AR0, @0x0e40 + 0abf 0081 0b89 lri $AR1, #0x0b89 + 0ac1 00c2 0e08 lr $AR2, @0x0e08 + 0ac3 0083 0e44 lri $AR3, #0x0e44 + 0ac5 00c4 0e41 lr $IX0, @0x0e41 + 0ac7 00c5 0e09 lr $IX1, @0x0e09 + 0ac9 02bf 8282 call 0x8282 + 0acb 00f8 0ba9 sr @0x0ba9, $AX0.L + 0acd 00fb 0bac sr @0x0bac, $AX1.H + 0acf 00c0 0e43 lr $AR0, @0x0e43 + 0ad1 0081 0b91 lri $AR1, #0x0b91 + 0ad3 00c2 0e0e lr $AR2, @0x0e0e + 0ad5 0083 0e44 lri $AR3, #0x0e44 + 0ad7 1c80 mrr $IX0, $AR0 + 0ad8 00c5 0e0f lr $IX1, @0x0e0f + 0ada 02bf 8282 call 0x8282 + 0adc 00f8 0bab sr @0x0bab, $AX0.L + 0ade 00fb 0bae sr @0x0bae, $AX1.H + 0ae0 00c0 0e40 lr $AR0, @0x0e40 + 0ae2 0081 0b8d lri $AR1, #0x0b8d + 0ae4 00c2 0e0b lr $AR2, @0x0e0b + 0ae6 0083 0e44 lri $AR3, #0x0e44 + 0ae8 00c4 0e41 lr $IX0, @0x0e41 + 0aea 00c5 0e0c lr $IX1, @0x0e0c + 0aec 02bf 8282 call 0x8282 + 0aee 00f8 0baa sr @0x0baa, $AX0.L + 0af0 00fb 0bad sr @0x0bad, $AX1.H + 0af2 00c0 0e43 lr $AR0, @0x0e43 + 0af4 0081 0b99 lri $AR1, #0x0b99 + 0af6 00c2 0e0d lr $AR2, @0x0e0d + 0af8 0083 0e44 lri $AR3, #0x0e44 + 0afa 02bf 845d call 0x845d + 0afc 00f8 0bb0 sr @0x0bb0, $AX0.L + 0afe 02df ret +} + +# Jump table for main commands +0aff 0082 // Jump 0 +0b00 013e // Jump 1 +0b01 01bc // Jump 2 +0b02 0248 // Jump 3 +0b03 0413 // Jump 4 +0b04 0427 // Jump 5 +0b05 0165 // Jump 6 +0b06 0574 // Jump 7 +0b07 0b37 // Jump 8 +0b08 015f // Jump 9 +0b09 0478 // Jump a +0b0a 0474 // Jump b +0b0b 0476 // Jump c +0b0c 01a9 // Jump d +0b0d 043b // Jump e +0b0e 047a // Jump f Task_Yield() +0b0f 0bb1 // Jump 10 +0b10 0175 // Jump 11 + +# LUT for pb.mixerCtrl +0b11 0768 // Jump3 0 +0b12 077a // Jump3 1 +0b13 079d // Jump3 2 +0b14 07c0 // Jump3 3 +0b15 07f4 // Jump3 4 +0b16 0811 // Jump3 5 +0b17 0844 // Jump3 6 +0b18 0877 // Jump3 7 +0b19 08c6 // Jump3 8 +0b1a 08d9 // Jump3 9 +0b1b 08fe // Jump3 a +0b1c 0923 // Jump3 b +0b1d 095a // Jump3 c +0b1e 0979 // Jump3 d +0b1f 09af // Jump3 e +0b20 09e5 // Jump3 f + +0b21 0a39 // Jump3 10 +0b22 0a5b // Jump3 11 +0b23 0768 // Jump3 12 +0b24 0768 // Jump3 13 +0b25 0768 // Jump3 14 +0b26 0768 // Jump3 15 +0b27 0768 // Jump3 16 +0b28 0768 // Jump3 17 +0b29 0a99 // Jump3 18 +0b2a 0abd // Jump3 19 +0b2b 0768 // Jump3 1a +0b2c 0768 // Jump3 1b +0b2d 0768 // Jump3 1c +0b2e 0768 // Jump3 1d +0b2f 0768 // Jump3 1e +0b30 0768 // Jump3 1f + +# LUT for pb.srcSelect +0b31 05a8 // Jump4 0 +0b32 065d // Jump4 1 +0b33 0707 // Jump4 2 + +# LUT for pb.coefSelect tables (in drom) +0b34 1000 +0b35 1200 +0b36 1400 + +# End of noise - back to code. + +void Cmd_8() { + 0b37 8e00 set16 + + 0b38 8100 clr $ACC0 + 0b39 8970 clr'l $ACC1 : $AC0.M, @$AR0 + 0b3a 191c lrri $AC0.L, @$AR0 + + 0b3b 2ece srs @DSMAH, $AC0.M + 0b3c 2ccf srs @DSMAL, $AC0.L + 0b3d 16cd 0e80 si @DSPA, #0x0e80 + 0b3f 16c9 0000 si @DSCR, #0x0000 + 0b41 16cb 0100 si @DSBL, #0x0100 + + 0b43 1f7e mrr $AX1.H, $AC0.M + 0b44 1f3c mrr $AX1.L, $AC0.L + + 0b45 8100 clr $ACC0 + + 0b46 26c9 lrs $AC0.M, @DSCR + 0b47 02a0 0004 andf $AC0.M, #0x0004 + 0b49 029c 0b46 jlnz 0x0b46 + + 0b4b 191e lrri $AC0.M, @$AR0 + 0b4c 191c lrri $AC0.L, @$AR0 + 0b4d 2ece srs @DSMAH, $AC0.M + 0b4e 2ccf srs @DSMAL, $AC0.L + 0b4f 16cd 0280 si @DSPA, #0x0280 + 0b51 16c9 0000 si @DSCR, #0x0000 + 0b53 16cb 0280 si @DSBL, #0x0280 + + 0b55 1c80 mrr $IX0, $AR0 + + 0b56 0080 0280 lri $AR0, #0x0280 + 0b58 00c1 0e1b lr $AR1, @0x0e1b + 0b5a 0085 0000 lri $IX1, #0x0000 + 0b5c 0089 007f lri $WR1, #0x007f + 0b5e 0082 0f00 lri $AR2, #0x0f00 + 0b60 0083 16b4 lri $AR3, #0x16b4 + 0b62 1ce3 mrr $IX3, $AR3 + 0b63 8100 clr $ACC0 + + 0b64 26c9 lrs $AC0.M, @DSCR + 0b65 02a0 0004 andf $AC0.M, #0x0004 + 0b67 029c 0b64 jlnz 0x0b64 + + 0b69 8f00 set40 + 0b6a 8a78 m2'l : $AC1.M, @$AR0 + 0b6b 8c68 clr15'l : $AC1.L, @$AR0 + 0b6c f100 lsl16 $ACC1 + 0b6d 1a3f srr @$AR1, $AC1.M + 0b6e 84e3 clrp'ld : $AX0.H, $AX1.L, @$AR3 + 0b6f 107e loopi #0x7e + 0b70 f2e3 madd'ld $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 + 0b71 f2e7 madd'ldn $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 + 0b72 f278 madd'l $AX0.L, $AX0.H : $AC1.M, @$AR0 + 0b73 6e68 movp'l $ACC0 : $AC1.L, @$AR0 + 0b74 f132 lsl16's $ACC1 : @$AR2, $AC0.M + 0b75 1a3f srr @$AR1, $AC1.M + 0b76 119e 0b80 bloopi #0x9e, 0x0b80 + 0b78 1c67 mrr $AR3, $IX3 + 0b79 84e3 clrp'ld : $AX0.H, $AX1.L, @$AR3 + 0b7a 107e loopi #0x7e + 0b7b f2e3 madd'ld $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 + 0b7c f2e7 madd'ldn $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 + 0b7d f278 madd'l $AX0.L, $AX0.H : $AC1.M, @$AR0 + 0b7e 6e68 movp'l $ACC0 : $AC1.L, @$AR0 + 0b7f f132 lsl16's $ACC1 : @$AR2, $AC0.M + 0b80 1a3f srr @$AR1, $AC1.M + + 0b81 1c67 mrr $AR3, $IX3 + 0b82 84e3 clrp'ld : $AX0.H, $AX1.L, @$AR3 + 0b83 107e loopi #0x7e + 0b84 f2e3 madd'ld $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 + 0b85 f2e7 madd'ldn $AX0.L, $AX0.H : $AX0.H, $AX1.L, @$AR3 + 0b86 f200 madd $AX0.L, $AX0.H + 0b87 6e00 movp $ACC0 + 0b88 1b5e srri @$AR2, $AC0.M + 0b89 00e1 0e1b sr @0x0e1b, $AR1 + + 0b8b 0080 0280 lri $AR0, #0x0280 + 0b8d 0083 0f00 lri $AR3, #0x0f00 + 0b8f 0081 0000 lri $AR1, #0x0000 + 0b91 0082 0140 lri $AR2, #0x0140 + 0b93 0089 ffff lri $WR1, #0xffff + + 0b95 8900 clr $ACC1 + 0b96 8100 clr $ACC0 + + 0b97 8f00 set40 + + 0b98 11a0 0ba0 bloopi #0xa0, 0x0ba0 + 0b9a 197f lrri $AC1.M, @$AR3 + 0b9b 9930 asr16's $ACC1 : @$AR0, $AC0.M + 0b9c 1b1e srri @$AR0, $AC0.M + 0b9d 1b3f srri @$AR1, $AC1.M + 0b9e 7d29 neg's $ACC1 : @$AR1, $AC1.L + 0b9f 1b5f srri @$AR2, $AC1.M + 0ba0 1b5d srri @$AR2, $AC1.L + + 0ba1 8e00 set16 + + 0ba2 1fdb mrr $AC0.M, $AX1.H + 0ba3 1f99 mrr $AC0.L, $AX1.L + 0ba4 2ece srs @DSMAH, $AC0.M + 0ba5 2ccf srs @DSMAL, $AC0.L + 0ba6 16cd 0e80 si @DSPA, #0x0e80 + 0ba8 16c9 0001 si @DSCR, #0x0001 + 0baa 16cb 0100 si @DSBL, #0x0100 + + // 0bac 02bf 055c call 0x055c + WaitDMA(); + + 0bae 1c04 mrr $AR0, $IX0 + + // 0baf 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +void Cmd_10() { + 0bb1 8e00 set16 + + 0bb2 8100 clr $ACC0 + 0bb3 8970 clr'l $ACC1 : $AC0.M, @$AR0 + 0bb4 191c lrri $AC0.L, @$AR0 + + 0bb5 2ece srs @DSMAH, $AC0.M + 0bb6 2ccf srs @DSMAL, $AC0.L + 0bb7 16cd 07c0 si @DSPA, #0x07c0 + 0bb9 16c9 0001 si @DSCR, #0x0001 + 0bbb 16cb 0500 si @DSBL, #0x0500 + + // 0bbd 02bf 055c call 0x055c + WaitDMA(); + + 0bbf 8100 clr $ACC0 + 0bc0 8970 clr'l $ACC1 : $AC0.M, @$AR0 + 0bc1 191c lrri $AC0.L, @$AR0 + + 0bc2 2ece srs @DSMAH, $AC0.M + 0bc3 2ccf srs @DSMAL, $AC0.L + 0bc4 16cd 07c0 si @DSPA, #0x07c0 + 0bc6 16c9 0000 si @DSCR, #0x0000 + 0bc8 8900 clr $ACC1 + 0bc9 0d20 lris $AC1.L, #0x20 + 0bca 2dcb srs @DSBL, $AC1.L + + 0bcb 4c00 add $ACC0, $ACC1 + + 0bcc 1c80 mrr $IX0, $AR0 + + 0bcd 0080 07c0 lri $AR0, #0x07c0 + 0bcf 0083 0000 lri $AR3, #0x0000 + 0bd1 1c43 mrr $AR2, $AR3 + 0bd2 0a00 lris $AX0.H, #0x00 + + 0bd3 27c9 lrs $AC1.M, @DSCR + 0bd4 03a0 0004 andf $AC1.M, #0x0004 + 0bd6 029c 0bd3 jlnz 0x0bd3 + + 0bd8 2ece srs @DSMAH, $AC0.M + 0bd9 2ccf srs @DSMAL, $AC0.L + 0bda 16cd 07d0 si @DSPA, #0x07d0 + 0bdc 16c9 0000 si @DSCR, #0x0000 + 0bde 16cb 04e0 si @DSBL, #0x04e0 + + 0be0 8f00 set40 + + 0be1 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 0be2 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 0be3 6a00 movax $ACC0, $AX1 + 0be4 4800 addax $ACC0, $AX0 + 0be5 114f 0bee bloopi #0x4f, 0x0bee + 0be7 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 0be8 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 0be9 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M + 0bea 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L + 0beb 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 0bec 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 0bed 6a3a movax's $ACC0, $AX1.L : @$AR2, $AC1.M + 0bee 482a addax's $ACC0, $AX0.L : @$AR2, $AC1.L + + 0bef 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 0bf0 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 0bf1 6b32 movax's $ACC1, $AX1.L : @$AR2, $AC0.M + 0bf2 4922 addax's $ACC1, $AX0.L : @$AR2, $AC0.L + 0bf3 1b5f srri @$AR2, $AC1.M + 0bf4 1b5d srri @$AR2, $AC1.L + 0bf5 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 0bf6 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 0bf7 6800 movax $ACC0, $AX0 + 0bf8 7c00 neg $ACC0 + 0bf9 4a00 addax $ACC0, $AX1 + 0bfa 114f 0c05 bloopi #0x4f, 0x0c05 + 0bfc 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 0bfd 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 0bfe 6932 movax's $ACC1, $AX0.L : @$AR2, $AC0.M + 0bff 7d00 neg $ACC1 + 0c00 4b22 addax's $ACC1, $AX1.L : @$AR2, $AC0.L + 0c01 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 0c02 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 0c03 683a movax's $ACC0, $AX0.L : @$AR2, $AC1.M + 0c04 7c00 neg $ACC0 + 0c05 4a2a addax's $ACC0, $AX1.L : @$AR2, $AC1.L + + 0c06 80f0 nx'ld : $AX0.H, $AX1.H, @$AR0 + 0c07 80c0 nx'ld : $AX0.L, $AX1.L, @$AR0 + 0c08 6932 movax's $ACC1, $AX0.L : @$AR2, $AC0.M + 0c09 7d00 neg $ACC1 + 0c0a 4b22 addax's $ACC1, $AX1.L : @$AR2, $AC0.L + 0c0b 1b5f srri @$AR2, $AC1.M + 0c0c 1b5d srri @$AR2, $AC1.L + + 0c0d 1c04 mrr $AR0, $IX0 + + // 0c0e 029f 0068 jmp 0x0068 + goto DoNextCommand; +} + +# Begin interrupt handlers + +// Sends mail with value on top of callstack and rti's +void ResetAndStackUOFlow_Handler() { + 0c10 8e00 set16 + + // 0c11 16fc ecc0 si @DMBH, #0xecc0 + // 0c13 1fcc mrr $AC0.M, $ST0 + // 0c14 1d9e mrr $ST0, $AC0.M + // 0c15 2efd srs @DMBL, $AC0.M + DMB = 0xecc00000 | $ST0 + + // 0c16 26fc lrs $AC0.M, @DMBH + // 0c17 02a0 8000 andf $AC0.M, #0x8000 + // 0c19 029c 0c16 jlnz 0x0c16 + while (@DMBH & 0x8000 == 0); + + // 0c1b 0000 nop + // 0c1c 0000 nop + // 0c1d 0000 nop + // 0c1e 02ff rti + return; +} + +// Saves/Restores whole ACC0, but only modifies AC0.M. strange +void Int2_Handler() { + 0c1f 8e00 set16 + + // Save ACC0 + 0c20 00f0 0e17 sr @0x0e17, $AC0.H + 0c22 00fe 0e18 sr @0x0e18, $AC0.M + 0c24 00fc 0e19 sr @0x0e19, $AC0.L + + // 0c26 1fcc mrr $AC0.M, $ST0 + // 0c27 1d9e mrr $ST0, $AC0.M + // 0c28 16fc feed si @DMBH, #0xfeed + // 0c2a 2efd srs @DMBL, $AC0.M + DMB = 0xfeed0000 | $ST0 + + // 0c2b 26fc lrs $AC0.M, @DMBH + // 0c2c 02a0 8000 andf $AC0.M, #0x8000 + // 0c2e 029c 0c2b jlnz 0x0c2b + while (@DMBH & 0x8000 == 0); + + // Restore ACC0 + 0c30 00d0 0e17 lr $AC0.H, @0x0e17 + 0c32 00de 0e18 lr $AC0.M, @0x0e18 + 0c34 00dc 0e19 lr $AC0.L, @0x0e19 + + // 0c36 0000 nop + // 0c37 0000 nop + // 0c38 0000 nop + // 0c39 0000 nop + // 0c3a 02ff rti + return; +} + +void Int3_Handler() { + 0c3b 8e00 set16 + + // Save AC0.L, AC0.M + 0c3c 1dbc mrr $ST1, $AC0.L + 0c3d 1dbe mrr $ST1, $AC0.M + + // 0c3e 8100 clr $ACC0 + // 0c3f 00de 0bb7 lr $AC0.M, @0x0bb7 + // 0c41 0601 cmpis $AC0.M, #0x01 + // 0c42 0295 0c47 jz 0x0c47 + // 0c44 0e00 lris $AC0.M, #0x00 + // 0c45 00fe 0b87 sr @0x0b87, $AC0.M + if (*0x0bb7 != 1) { // pb.addr != AXPBADDR_LOOP_ON + *0x0b87 = 0; // pb.state = AX_PB_STATE_STOP + } + + // Restore AC0.L, AC0.M + 0c47 1fcd mrr $AC0.M, $ST1 + 0c48 1f8d mrr $AC0.L, $ST1 + + // 0c49 02ff rti + return; +} + +void Int4_Handler() { + // 0c4a 0000 nop + // 0c4b 0000 nop + // 0c4c 0000 nop + // 0c4d 0000 nop + // 0c4e 0000 nop + // 0c4f 02ff rti + return; +} + +void Int5_Handler() { + 0c50 8e00 set16 + + // Save AC0.L, AC0.M + 0c51 1dbc mrr $ST1, $AC0.L + 0c52 1dbe mrr $ST1, $AC0.M + + // 0c53 8100 clr $ACC0 + // 0c54 00de 0bb7 lr $AC0.M, @0x0bb7 + // 0c56 0601 cmpis $AC0.M, #0x01 + // 0c57 0295 0c5f jz 0x0c5f + if (*0x0bb7 != 1) // pb.addr != AXPBADDR_LOOP_ON + { + // 0c59 0e00 lris $AC0.M, #0x00 + // 0c5a 00fe 0b87 sr @0x0b87, $AC0.M + *0x0b87 = 0; // pb.state = AX_PB_STATE_STOP + + // Restore AC0.L, AC0.M + 0c5c 1fcd mrr $AC0.M, $ST1 + 0c5d 1f8d mrr $AC0.L, $ST1 + + // 0c5e 02ff rti + return; + } + + // 0c5f 8100 clr $ACC0 + // 0c60 00de 0b88 lr $AC0.M, @0x0b88 + // 0c62 0601 cmpis $AC0.M, #0x01 + // 0c63 0295 0c71 jz 0x0c71 + if (*0x0b88 != 1) { // pb.type != AX_PB_TYPE_STREAM + + // 0c65 00de 0bda lr $AC0.M, @0x0bda + // 0c67 2eda srs @scale, $AC0.M + // 0c68 00de 0bdb lr $AC0.M, @0x0bdb + // 0c6a 2edb srs @yn1, $AC0.M + // 0c6b 00de 0bdc lr $AC0.M, @0x0bdc + // 0c6d 2edc srs @yn2, $AC0.M + @scale = pb.adpcmLoop.loop_pred_scale + @yn1 = pb.adpcmLoop.loop_yn1 + @yn2 = pb.adpcmLoop.loop_yn2 + + // Restore AC0.L, AC0.M + 0c6e 1fcd mrr $AC0.M, $ST1 + 0c6f 1f8d mrr $AC0.L, $ST1 + + // 0c70 02ff rti + return; + + } else { + + // 0c71 00de 0bda lr $AC0.M, @0x0bda + // 0c73 2eda srs @scale, $AC0.M + // 0c74 26db lrs $AC0.M, @yn1 + // 0c75 2edb srs @yn1, $AC0.M + // 0c76 26dc lrs $AC0.M, @yn2 + // 0c77 2edc srs @yn2, $AC0.M + @scale = pb.adpcmLoop.loop_pred_scale + // refresh @yn1, @yn2....why? + @yn1 = @yn1 + @yn2 = @yn2 + + // Well helllloooo there, padding + // 0c78 8100 clr $ACC0 + // 0c79 00dc 0bdd lr $AC0.L, @0x0bdd + // 0c7b 7600 inc $ACC0 + // 0c7c 00fc 0bdd sr @0x0bdd, $AC0.L + // 0c7e 8100 clr $ACC0 + pb.pad[0]++ + + // Restore AC0.L, AC0.M + 0c7f 1fcd mrr $AC0.M, $ST1 + 0c80 1f8d mrr $AC0.L, $ST1 + + // 0c81 02ff rti + return; + } +} + +void Int6_Handler() { + 0c82 0000 nop + 0c83 0000 nop + 0c84 0000 nop + 0c85 0000 nop + 0c86 0000 nop + 0c87 02ff rti +} + +void Int7_Handler() { + 0c88 0000 nop + 0c89 0000 nop + 0c8a 0000 nop + 0c8b 0000 nop + 0c8c 02ff rti +} + +# End of interrupt handlers + +// Jump table for the next function. +0c8d 0c9f // some kind of soft-reset for the UCode +0c8e 0ca2 // looks like code to dump the UCode memory for debugging +0c8f 0cda // rest the UCode and jump to ROM +0c90 0cdd // normal case to return to the main-loop + +// Called only from Task_Yield() +// Decides what to do next (this cmdblock is done) +void JumpThroughTable2() { + 0c91 8e00 set16 + 0c92 8100 clr $ACC0 + 0c93 8900 clr $ACC1 + + // 0c94 02bf 0ce0 call 0x0ce0 + WaitForCPUMail0(); + + // 0c96 27ff lrs $AC1.M, @CMBL + // 0c97 009e 0c8d lri $AC0.M, #0x0c8d + // 0c99 4c00 add $ACC0, $ACC1 + // 0c9a 1c7e mrr $AR3, $AC0.M + // 0c9b 0313 ilrr $AC1.M, @$AR3 + // 0c9c 1c7f mrr $AR3, $AC1.M + // 0c9d 176f jmpr $AR3 + switch(@CMBL) { + case 0: AX_ResumeTask(); break; + case 1: JumpTable2_1(); break; + case 2: IROM_Reset(); break; + case 3: AX_GetNextCmdBlock(); break; + } + 0c9e 0021 halt +} + +// case 0: +void AX_ResumeTask() { + 0c9f 029f 0030 jmp 0x0030 + 0ca1 0021 halt +} + +// case 1: +// funky...calls the mbox funcs, sometimes prefilling ACx regs... +// Perhaps DMAs some stuff and yields? +// Need to RE the ROM to figure this func out completely +void JumpTable2_1() { + // 0ca2 8100 clr $ACC0 + // 0ca3 8900 clr $ACC1 + // 0ca4 02bf 0ce0 call 0x0ce0 + WaitForCPUMail0(); + + // 0ca6 24ff lrs $AC0.L, @CMBL + // 0ca7 02bf 0ce6 call 0x0ce6 + WaitForCPUMail1(); + + // 0ca9 25ff lrs $AC1.L, @CMBL + // 0caa 02bf 0ce6 call 0x0ce6 + WaitForCPUMail1(); + + 0cac 27ff lrs $AC1.M, @CMBL + 0cad 2ece srs @DSMAH, $AC0.M + 0cae 2ccf srs @DSMAL, $AC0.L + 0caf 16c9 0001 si @DSCR, #0x0001 + 0cb1 2fcd srs @DSPA, $AC1.M + 0cb2 2dcb srs @DSBL, $AC1.L + + // 0cb3 8100 clr $ACC0 + // 0cb4 8900 clr $ACC1 + // 0cb5 02bf 0ce0 call 0x0ce0 + WaitForCPUMail0(); + + 0cb7 24ff lrs $AC0.L, @CMBL + 0cb8 1c9e mrr $IX0, $AC0.M + 0cb9 1cbc mrr $IX1, $AC0.L + 0cba 02bf 0ce6 call 0x0ce6 + WaitForCPUMail1(); + + 0cbc 25ff lrs $AC1.L, @CMBL + 0cbd 02bf 0ce6 call 0x0ce6 + WaitForCPUMail1(); + + 0cbf 27ff lrs $AC1.M, @CMBL + 0cc0 1cdf mrr $IX2, $AC1.M + 0cc1 1cfd mrr $IX3, $AC1.L + + // 0cc2 8100 clr $ACC0 + // 0cc3 02bf 0ce0 call 0x0ce0 + WaitForCPUMail0(); + + 0cc5 26ff lrs $AC0.M, @CMBL + 0cc6 1c1e mrr $AR0, $AC0.M + 0cc7 8900 clr $ACC1 + 0cc8 02bf 0ce6 call 0x0ce6 + WaitForCPUMail1(); + + 0cca 20ff lrs $AX0.L, @CMBL + 0ccb 1f5f mrr $AX0.H, $AC1.M + 0ccc 02bf 0ce0 call 0x0ce0 + WaitForCPUMail0(); + + 0cce 21ff lrs $AX1.L, @CMBL + 0ccf 02bf 0ce0 call 0x0ce0 + WaitForCPUMail0(); + + 0cd1 23ff lrs $AX1.H, @CMBL + + // 0cd2 26c9 lrs $AC0.M, @DSCR + // 0cd3 02a0 0004 andf $AC0.M, #0x0004 + // 0cd5 029c 0cd2 jlnz 0x0cd2 + while (@DSCR & 0x0004 != 0); // Wait for DMA to complete + + // 0cd7 029f 80b5 jmp 0x80b5 + // 0cd9 0021 halt + IROM_ErrorAndDie(); // Not sure...gotta RE the ROM +} + +// case 2: +void IROM_Reset() { + 0cda 029f 8000 jmp 0x8000 + 0cdc 0021 halt +} + +// case 3: +void AX_GetNextCmdBlock() { + // 0cdd 029f 0045 jmp 0x0045 + goto GetNextCmdBlock; + + 0cdf 0021 halt +} + +void WaitForCPUMail0() { + // 0ce0 26fe lrs $AC0.M, @CMBH + // 0ce1 02c0 8000 andcf $AC0.M, #0x8000 + // 0ce3 029c 0ce0 jlnz 0x0ce0 + while (@CMBH & 0x8000 == 0); + // 0ce5 02df ret + return; +} + +void WaitForCPUMail1() { + // 0ce6 27fe lrs $AC1.M, @CMBH + // 0ce7 03c0 8000 andcf $AC1.M, #0x8000 + // 0ce9 029c 0ce6 jlnz 0x0ce6 + while (@CMBH & 0x8000 == 0); + // 0ceb 02df ret + return; +} + +0cec 0000 nop +0ced 0000 nop +0cee 0000 nop +0cef 0000 nop diff -Nru dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_GBA.txt dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_GBA.txt --- dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_GBA.txt 1970-01-01 01:00:00.000000000 +0100 +++ dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_GBA.txt 2010-08-18 03:25:25.000000000 +0100 @@ -0,0 +1,498 @@ +/////////////////////////////////////////////////////////////////////////////// +ROM functions used: +0x8000 dsp reset +0x8078 wait for CMBH & 0x8000 +0x807e wait for DMBH & 0x8000 +0x808b dump DRAM/IRAM to mainmem +0x80b5 boot new ucode +0x80bc boot new ucode without ACC clearing by ROM + +For the rest, this ucode is just calling the last few instructions +from huge functions in irom - some kind of obfuscation +Perhaps someone thought the irom would never be dumped? ;p + +Similarly, drom is used pretty extensively as a source of what is intended to +be "mystery" numbers. Usually a word will be fetched, and masked to create a +simple value. No problem! :) + +0x81f4 + mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M + asr16'ir $ACC1 : $AR1 + srri @$AR3, $AC1.M + clr's $ACC0 : @$AR3, $AC1.L +0x8458 + mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M + asr16 $ACC1 + srri @$AR3, $AC1.M + clr's $ACC0 : @$AR3, $AC1.L +0x8723 + xorr $AC1.M, $AX1.H + srrd @$AR2, $AC1.M +0x8809 + orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L + srri @$AR2, $AC1.M +0x88e5 + orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 + lrrd $AC1.L, @$AR2 + add'dr $ACC0, $ACC1 : $AR1 + srri @$AR2, $AC0.M + srr @$AR2, $AC0.L + +struct sec_params_t +{ + u32 key; // from gba + u32 unk1; // normally 2 + u32 unk2; // normally 2 + u32 length; // size of data transferred to gba + u32 dest_addr; // addr to store result in mram + u32 pad[3]; +} + +// exception vector +0000 0000 nop +0001 0000 nop +0002 0000 nop +0003 0000 nop +0004 0000 nop +0005 0000 nop +0006 0000 nop +0007 0000 nop +0008 0000 nop +0009 0000 nop +000a 0000 nop +000b 0000 nop +000c 0000 nop +000d 0021 halt +000e 02ff rti +000f 0021 halt + +// entry point +void 0010_main() +{ +0010 1306 sbset #0x06 +0011 1203 sbclr #0x03 +0012 1204 sbclr #0x04 +0013 1305 sbset #0x05 +0014 0092 00ff lri $CR, #0x00ff +0016 0088 ffff lri $WR0, #0xffff +0018 0089 ffff lri $WR1, #0xffff +001a 008a ffff lri $WR2, #0xffff +001c 008b ffff lri $WR3, #0xffff +001e 8f00 set40 +001f 8b00 m0 +0020 8c00 clr15 +0021 02bf 807e call 0x807e // loop until dsp->cpu mailbox is empty +0023 16fc dcd1 si @DMBH, #0xdcd1 +0025 16fd 0000 si @DMBL, #0x0000 // sendmail 0xdcd10000 +0027 16fb 0001 si @DIRQ, #0x0001 + +// wait for cpu mail == 0xabbaxxxx +0029 02bf 8078 call 0x8078 // wait for cpu mail +002b 24ff lrs $AC0.L, @CMBL +002c 0280 abba cmpi $AC0.M, #0xabba +002e 0294 0029 jnz 0x0029 + +// wait for cpu mail +0030 8e00 set16 +0031 02bf 8078 call 0x8078 + +0033 20ff lrs $AX0.L, @CMBL +0034 0240 0fff andi $AC0.M, #0x0fff +0036 1f5e mrr $AX0.H, $AC0.M +0037 009b 0000 lri $AX1.H, #0x0000 // DSP-dram addr +0039 0099 0020 lri $AX1.L, #0x0020 // length (20 bytes = 10 words, word 9 and 10 are addr where result should DMA'd to in main mem) +003b 0087 0000 lri $IX3, #0x0000 // there will be no ucode/iram upload +003d 0080 0041 lri $AR0, #0x0041 // return addr after dram upload +003f 029f 80bc jmp 0x80bc // DRAM upload !! +// $AX0.H-$AX0.L - CPU(PPC) addr = mail & 0x0fffffff +// upload data from mainmem do dsp dram and jump to 0x41 after that + +0041 02bf 008c call 008c_BigCrazyFunction() +0043 02bf 807e call 0x807e // loop until dsp->cpu mailbox is empty + +0045 16fc dcd1 si @DMBH, #0xdcd1 +0047 16fd 0003 si @DMBL, #0x0003 // sendmail 0xdcd10003 (aka... calc is over, result is in main mem now) +0049 16fb 0001 si @DIRQ, #0x0001 +004b 8f00 set40 + +004c 02bf 8078 call 0x8078 +004e 0280 cdd1 cmpi $AC0.M, #0xcdd1 +0050 0294 004c jnz 0x004c + +0052 26ff lrs $AC0.M, @CMBL +0053 0280 0001 cmpi $AC0.M, #0x0001 +0055 0295 005e jz 0x005e // if cpu->dsp mail was 0xcdd10001 -> 005e_PrepareBootUcode() + +0057 0280 0002 cmpi $AC0.M, #0x0002 +0059 0295 8000 jz 0x8000 // if cpu->dsp mail was 0xcdd10002 -> dsp reset ( jmp to irom(0x8000)) + +005b 029f 004c jmp 0x004c // wait for next mail from cpu +005d 0021 halt +} + +void 005e_PrepareBootUcode() +{ +005e 8e00 set16 +005f 02bf 8078 call 0x8078 +0061 24ff lrs $AC0.L, @CMBL // ??? +0062 02bf 8078 call 0x8078 +0064 24ff lrs $AC0.L, @CMBL // ??? +0065 02bf 8078 call 0x8078 +0067 24ff lrs $AC0.L, @CMBL // ??? +0068 02bf 8078 call 0x8078 +006a 00c5 ffff lr $IX1, @CMBL +006c 0240 0fff andi $AC0.M, #0x0fff +006e 1c9e mrr $IX0, $AC0.M // mram addr for iram +006f 02bf 8078 call 0x8078 +0071 00c7 ffff lr $IX3, @CMBL // iram upload length. upload skipped if 0 +0073 02bf 8078 call 0x8078 +0075 00c6 ffff lr $IX2, @CMBL // iram dest +0077 02bf 8078 call 0x8078 +0079 00c0 ffff lr $AR0, @CMBL // startpc / return addr +007b 02bf 8078 call 0x8078 +007d 20ff lrs $AX0.L, @CMBL +007e 0240 0fff andi $AC0.M, #0x0fff +0080 1f5e mrr $AX0.H, $AC0.M // mram addr for dram +0081 02bf 8078 call 0x8078 +0083 21ff lrs $AX1.L, @CMBL // dram upload length. upload skipped if 0 +0084 02bf 8078 call 0x8078 +0086 23ff lrs $AX1.H, @CMBL // dram dest +0087 1205 sbclr #0x05 +0088 1206 sbclr #0x06 +0089 029f 80b5 jmp 80b5_BootUcode() +008b 0021 halt +} + +// does some crazy stuff with data at dram @0x3/0x5/0x6/0x7 with help of some values from drom :) +// result is @0x22,@0x23 and written back to main memory to dmem-0x08:dmem-0x09 +void 008c_BigCrazyFunction() +{ +// 008c 8100 clr $ACC0 +// 008d 0081 0010 lri $AR1, #0x0010 +// 008f 1020 loopi #0x20 +// 0090 1b3e srri @$AR1, $AC0.M + memset(0x10, 0, 0x20 * sizeof(dsp_word)); + +// 0091 00df 1456 lr $AC1.M, @0x1456 // drom 102f +// 0093 0340 ffd0 andi $AC1.M, #0xffd0 // -> 0x1000 +// 0095 8417 clrp'mv : $AX1.L, $AC1.M // clrp, ax1.l = 0x1000 + IMPORTANT: "confusing" section relies on prod being cleared, and ax1.l == 0x1000 + +// 0096 0080 0000 lri $AR0, #0x0000 +// 0098 0086 0000 lri $IX2, #0x0000 +// 009a 0082 001f lri $AR2, #0x001f +// 009c 00de 15f6 lr $AC0.M, @0x15f6 // drom 7f65 +// 009e 1408 lsl $ACC0, #8 // -> 0x7f_6500 +// 009f 00df 1766 lr $AC1.M, @0x1766 // drom 0273 +// 00a1 0340 00ff andi $AC1.M, #0x00ff // -> 0x73 +// 00a3 1f5f mrr $AX0.H, $AC1.M // ax0.h = 0x73 +// 00a4 02bf 88e5 call 0x88e5 // ar2 = 0x1f, ar1 = 0x30 +// orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // acc0 = 0x7f_6573, ac1.m = 0, ar2 = 0x20 +// lrrd $AC1.L, @$AR2 // ac1.l = 0, ar2 = 0x1f +// add'dr $ACC0, $ACC1 : $AR1 +// srri @$AR2, $AC0.M // *0x1f = 0x6573, ar2 = 0x20 +// srr @$AR2, $AC0.L // *0x20 = 0 +// 00a6 1f1c mrr $AX0.L, $AC0.L // ax0.l = 0 +// 00a7 811e clr'mv $ACC0 : $AX1.H, $AC0.M // acc0 = 0, ax1.h = 0x6573 +// 00a8 191e lrri $AC0.M, @$AR0 // ac0.m = sec_params.key[0], ar1 = 1 +// 00a9 1478 lsr $ACC0, #-8 // acc0 0x00_00.._..00 +// 00aa 1ffc mrr $AC1.M, $AC0.L // ac1.m = sec_params.key[0] & 0x00ff +// 00ab 1f5e mrr $AX0.H, $AC0.M // ax0.h = sec_params.key[0] >> 8 +// 00ac 02bf 8809 call 0x8809 +// orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L // ac1.m |= ax0.h ..tricky tricky :D +// srri @$AR2, $AC1.M // *0x20 = bswap(sec_params.key[0]), ar2 = 0x21 +// 00ae 02bf 8723 call 0x8723 +// xorr $AC1.M, $AX1.H // ac1.m = sec_params.key[0] ^ 0x6573 +// srrd @$AR2, $AC1.M // *0x21 = bswap(sec_params.key[0]) ^ 0x6573, ar2 = 0x20 + // Initialize 0x21 + *0x1f = 0x6573 + *0x20 = bswap(sec_params.key[0]) + *0x21 = bswap(sec_params.key[0]) ^ 0x6573 + +// 00b0 0006 dar $AR2 // ar2 = 0x1f +// 00b1 8106 clr'dr $ACC0 : $AR2 // acc0 = 0, ar2 = 0x1e +// 00b2 00de 166c lr $AC0.M, @0x166c // drom 06f2 +// 00b4 1404 lsl $ACC0, #4 +// 00b5 0240 ff00 andi $AC0.M, #0xff00 // -> 0x6f00 +// 00b7 00df 1231 lr $AC1.M, @0x1231 // drom 64fc +// 00b9 1578 lsr $ACC1, #-8 +// 00ba 0340 00ff andi $AC1.M, #0x00ff // -> 0x64 +// 00bc 1f5f mrr $AX0.H, $AC1.M // ax0.h = 0x64 +// 00bd 02bf 88e5 call 0x88e5 +// orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // ac0.m = 0x6f64, ac1.m = 0, ar2 = 0x1f +// lrrd $AC1.L, @$AR2 // ac1.l = 0x6573, ar2 = 0x1e +// add'dr $ACC0, $ACC1 : $AR1 // acc0 = 0x00_6f64_6573 +// srri @$AR2, $AC0.M // *0x1e = 0x6f64, ar2 = 0x1f +// srr @$AR2, $AC0.L // *0x1f = 0x6573 +// 00bf 1f1c mrr $AX0.L, $AC0.L +// 00c0 811e clr'mv $ACC0 : $AX1.H, $AC0.M // acc0 = 0, ax1.h = 0x6f64 +// 00c1 191e lrri $AC0.M, @$AR0 // ac0.m = sec_params.key[1] +// 00c2 1478 lsr $ACC0, #-8 // acc0 = 0x00_00.._..00 +// 00c3 1ffc mrr $AC1.M, $AC0.L // ac1.m = sec_params.key[1] & 0xff +// 00c4 1f5e mrr $AX0.H, $AC0.M // ax0.h = sec_params.key[1] >> 8 +// 00c5 02bf 8809 call 0x8809 +// orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L // ac1.m |= ax0.h +// srri @$AR2, $AC1.M // *0x1f = bswap(sec_params.key[1]), ar2 = 0x20 +// 00c7 02bf 8723 call 0x8723 +// xorr $AC1.M, $AX1.H +// srrd @$AR2, $AC1.M // *0x20 = bswap(sec_params.key[1]) ^ 0x6f64 + // Initialize 0x20 + *0x1e = 0x6f64 + *0x1f = bswap(sec_params.key[1]) + *0x20 = bswap(sec_params.key[1]) ^ 0x6f64 + + // Initialize 0x11 +// 00c9 8100 clr $ACC0 +// 00ca 8900 clr $ACC1 +// 00cb 00d1 0005 lr $AC1.H, @0x0005 +// 00cd 9900 asr16 $ACC1 // s16 unk2 = (s8)(sec_params.unk2[1]) +// 00ce 8200 cmp +// 00cf 0295 00e5 jz 0x00e5 +// 00d1 0291 00f3 jl 0x00f3 +if (unk2 < 0) { + // 00d3 0082 0010 lri $AR2, #0x0010 + // 00d5 0086 0001 lri $IX2, #0x0001 // 'sn will inc ar2 by 1 + // 00d7 00d0 171b lr $AC0.H, @0x171b // drom ff03 + // 00d9 9100 asr16 $ACC0 // -> 0x00_0003_0000 + // 00da 7d00 neg $ACC1 + // 00db 4d00 add $ACC1, $ACC0 + // 00dc 1501 lsl $ACC1, #1 + // 00dd 1f5f mrr $AX0.H, $AC1.M // ax0.h = ((~unk2 + 3) << 1) & 0xffff + // 00de 00df 0003 lr $AC1.M, @0x0003 // sec_params.unk1[1] + // 00e0 1504 lsl $ACC1, #4 + // 00e1 02bf 8809 call 0x8809 + // orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L // ac1.m = (((~unk2 + 3) << 1) & 0xffff) | (sec_params.unk1[1] << 4), ar2 = 0x11 + // srri @$AR2, $AC1.M + // 00e3 029f 0102 jmp 0x0102 + *0x11 = (((~unk2 + 3) << 1) | (sec_params.unk1[1] << 4)) & 0xffff + +} else if (unk2 == 0) { + // unk2 is unused + // 00e5 0082 0011 lri $AR2, #0x0011 + // 00e7 00df 0003 lr $AC1.M, @0x0003 // sec_params.unk1[1] + // 00e9 1501 lsl $ACC1, #1 + // 00ea 1f5f mrr $AX0.H, $AC1.M // ax0.h = sec_params.unk1[1] << 1 + // 00eb 00de 1043 lr $AC0.M, @0x1043 // drom 0076 + // 00ed 0240 fff0 andi $AC0.M, #0xfff0 // -> 0x70 + // 00ef 02bf 88e5 call 0x88e5 + // orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // ac0.m = (sec_params.unk1[1] << 1) | 0x70, ac1.m = 0, ar2 = 0x12 + // lrrd $AC1.L, @$AR2 // ar2 = 0x11 + // add'dr $ACC0, $ACC1 : $AR1 // acc1 must be 0 + // srri @$AR2, $AC0.M // *0x11 = (sec_params.unk1[1] << 1) | 0x70, ar2 = 0x12 + // srr @$AR2, $AC0.L // *0x12 = 0 // just a side effect, it's already 0 anyways + // 00f1 029f 0102 jmp 0x0102 + *0x11 = ((sec_params.unk1[1] << 1) | 0x70) & 0xffff + +} else if (unk2 > 0) { + // 00f3 0082 0010 lri $AR2, #0x0010 + // 00f5 0086 0001 lri $IX2, #0x0001 // 'sn will inc ar2 by 1 + // 00f7 00d0 1285 lr $AC0.H, @0x1285 // drom 5aff (0xffff because of .h) + // 00f9 9100 asr16 $ACC0 // -> 0xff_ffff_0000 = -1 + // 00fa 4d00 add $ACC1, $ACC0 // ac1.m = unk2 - 1 + // 00fb 1501 lsl $ACC1, #1 // ac1.m <<= 1 ..in the normal case, this makes it 2 again... + // 00fc 00de 0003 lr $AC0.M, @0x0003 // sec_params.unk1[1] + // 00fe 1404 lsl $ACC0, #4 + // 00ff 1f5e mrr $AX0.H, $AC0.M // ax0.h = sec_params.unk1[1] << 4 + // 0100 02bf 8809 call 0x8809 + // orr'sn $AC1.M, $AX0.H : @$AR2, $AC1.L // ac1.m = ((unk2 - 1) << 1) | (sec_params.unk1[1] << 4), ar2 = 0x11 + // srri @$AR2, $AC1.M + *0x11 = (((unk2 - 1) << 1) | (sec_params.unk1[1] << 4)) & 0xffff +} + +// This just clears acc1 +// 0102 0083 0013 lri $AR3, #0x0013 +// 0104 1b7e srri @$AR3, $AC0.M // *0x13 = intermediate from above -> unused +// 0105 8923 clr's $ACC1 : @$AR3, $AC0.L // acc1 = 0, *0x14 = intermediate from above -> unused + +// The "confusion" +// 0106 0083 0013 lri $AR3, #0x0013 +// 0108 00df 0007 lr $AC1.M, @0x0007 // ac1.m = sec_params.length[1] +// 010a 00de 11b8 lr $AC0.M, @0x11b8 // drom 007f +// 010c 0240 fff0 andi $AC0.M, #0xfff0 // -> 0x70 +// 010e 1f5e mrr $AX0.H, $AC0.M // ax0.h = 0x70 +// 010f 02bf 81f4 call 0x81f4 +// mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M// prod = 0x70 * 0x1000 : .m1 = 7 +// asr16'ir $ACC1 : $AR1 // ac1.l = sec_params.length[1], the rest of acc1 must be 0 +// srri @$AR3, $AC1.M // *0x13 = 0, ar3 = 0x14 +// clr's $ACC0 : @$AR3, $AC1.L // acc0 = 0, *0x14 = sec_params.length[1], ar3 = 0x15 +// +// 0111 f100 lsl16 $ACC1 // ac1.m = sec_params.length[1] +// 0112 02bf 8458 call 0x8458 // this is the same routine, just adds 7 and stores to different location +// mulxac'mv $AX0.H, $AX1.L, $ACC1 : $AX1.H, $AC0.M// acc1 += 7 // last prod has 7 in the mid +// asr16 $ACC1 // ac1.l = sec_params.length[1] + 7 +// srri @$AR3, $AC1.M // *0x15 = 0, ar3 = 0x16 +// clr's $ACC0 : @$AR3, $AC1.L // *0x16 = sec_params.length[1] + 7 + *0x13 = 0 + *0x14 = sec_params.length[1] + *0x15 = 0 + *0x16 = sec_params.length[1] + 7 + +// 0114 8f00 set40 // SIGN EXTENSION IN EFFECT!! +// 0115 0082 0015 lri $AR2, #0x0015 +// 0117 00de 0006 lr $AC0.M, @0x0006 // ac0.m = sec_params.length[0] ..always 0? // sign extended +// 0119 00da 165b lr $AX0.H, @0x165b // drom 0000 +// 011b 02bf 88e5 call 0x88e5 +// orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // ac0.m = sec_params.length[0], effectively clears acc1 (*0x15 == 0), ar2 = 0x16 +// lrrd $AC1.L, @$AR2 // ac1.l = sec_params.length[1] + 7, ar2 = 0x15 +// add'dr $ACC0, $ACC1 : $AR1 // ac0.m = sec_params.length[0], ac0.l = sec_params.length[1] + 7 +// srri @$AR2, $AC0.M // *0x15 = sec_params.length[0], ar2 = 0x16 +// srr @$AR2, $AC0.L // *0x16 = sec_params.length[1] + 7 +// 011d 14fd asr $ACC0, #-3 +// 011e 1403 lsl $ACC0, #3 // ((acc0 + 7) & ~7) (round up) // consider .length rounded from here on out +// 011f 1b5e srri @$AR2, $AC0.M // *0x16 = sec_params.length[0], ar2 = 0x17 +// 0120 1b5c srri @$AR2, $AC0.L // *0x17 = sec_params.length[1], ar2 = 0x18 +// 0121 0082 0016 lri $AR2, #0x0016 +// 0123 00de 1723 lr $AC0.M, @0x1723 // drom ffe0 // obviously sign extended +// 0125 14f4 asr $ACC0, #-12 // -> 0xff_ffff_fe00 = -1, -0x200 +// 0126 00da 166b lr $AX0.H, @0x166b // drom 0000 +// 0128 02bf 88e5 call 0x88e5 +// orr'l $AC0.M, $AX0.H : $AC1.M, @$AR2 // ac1.m = sec_params.length[0] // sign extended +// lrrd $AC1.L, @$AR2 // ac1.l = sec_params.length[1] +// add'dr $ACC0, $ACC1 : $AR1 // acc0 = sec_params.length - 0x200 // this is a proper signed operation :) +// srri @$AR2, $AC0.M // *0x16 = sec_params.length - 0x200 HIGH +// srr @$AR2, $AC0.L // *0x17 = sec_params.length - 0x200 LOW + // The above block just does 40bit subtraction...so annoying :p + *0x15 = sec_params.length[0] + *0x16 = sec_params.length - 0x200 HIGH + *0x17 = sec_params.length - 0x200 LOW + +// 012a b100 tst $ACC0 +// 012b 0290 012e jge 0x012e +// 012d 8100 clr $ACC0 +if (acc0 < 0) acc0 = 0 + +// At this point, ACC0 = max40bit(0, sec_params.length - 0x200) + +// 012e 14fd asr $ACC0, #-3 // taken into account at 013f +// 012f 8e00 set16 // back to sanity + +// voodoo +0130 00df 1491 lr $AC1.M, @0x1491 // drom 6a0f +0132 0340 d0f0 andi $AC1.M, #0xd0f0 // -> 0x4000 +0134 1cbf mrr $IX1, $AC1.M // ix1 = 0x4000 +0135 00df 1468 lr $AC1.M, @0x1468 // drom f808 +0137 00d1 11fc lr $AC1.H, @0x11fc // drom 0003 +0139 157c lsr $ACC1, #-4 // -> 0x00_3f80_8000 +013a 1cdf mrr $IX2, $AC1.M // ix2 = 0x3f80 +013b 00d1 11b8 lr $AC1.H, @0x11b8 // drom 007f +013d 9900 asr16 $ACC1 // -> 0x00_007f_3f80 +013e 1418 lsl $ACC0, #24 +013f 1478 lsr $ACC0, #-8 // (((ACC0 >> 3) << 24) >> 8) +same as ((ACC0 >> 3) << 16) & 0x00_ffff_0000 -> ac0.m = (u16)((sec_params.length - 0x200) >> 3) +u16 size = (u16)((sec_params.length - 0x200) >> 3) +0140 1f5e mrr $AX0.H, $AC0.M // ax0.h = size +0141 1ffe mrr $AC1.M, $AC0.M // ac1.m = size +0142 1f65 mrr $AX1.H, $IX1 // ax1.h = 0x4000 +0143 3600 andr $AC0.M, $AX1.H // ac0.m = size & 0x4000 +0144 1402 lsl $ACC0, #2 // acc0 <<= 2 // t = (0x00_size_0000 & 0x00_4000_ffff) << 2 +0145 1f66 mrr $AX1.H, $IX2 // ax1.h = 0x3f80 +0146 3700 andr $AC1.M, $AX1.H // ac1.m = size & 0x3f80 +0147 1501 lsl $ACC1, #1 // acc1 <<= 1 // u = (0x00_size_3f80 & 0x00_3f80_ffff) << 1 +0148 4c00 add $ACC0, $ACC1 // acc0 += acc1 // t += u +0149 1518 lsl $ACC1, #24 +014a 9900 asr16 $ACC1 // signed cast (s16)ac1.l (ends up in ac1.m) +014b 3500 andr $AC1.M, $AX0.H // ac1.m = (s16)u & size +014c 4c00 add $ACC0, $ACC1 // acc0 += acc1 // t += (s16)u & size +014d 00df 0012 lr $AC1.M, @0x0012 +014f 3f00 orc $AC1.M, $AC0.M // ac1.m = acc0 | 0x00_ffff_0000 +0150 00ff 0012 sr @0x0012, $AC1.M // *0x12 = ac1.m +0152 1470 lsr $ACC0, #-16 // // t >>= 16 unsigned +0153 00df 0011 lr $AC1.M, @0x0011 +0155 3f00 orc $AC1.M, $AC0.M +0156 00ff 0011 sr @0x0011, $AC1.M // *0x11 |= previous ac0.h, now at ac0.m <- so ac0.m = unsigned ac0.h +0158 1fa5 mrr $AC1.L, $IX1 // ac1.l = 0x4000 +0159 1501 lsl $ACC1, #1 // ac1.l = 0x8000 +015a 1fe6 mrr $AC1.M, $IX2 // ac1.m = 0x3f80 0x00_3f80_8000 +015b f100 lsl16 $ACC1 // ((acc1 << 16) >> 8) << 16 +015c 15f8 asr $ACC1, #-8 +015d f500 lsr16 $ACC1 // acc1 = 0x00_00ff_8080 +015e 1f5f mrr $AX0.H, $AC1.M // ax0.h = 0xff +015f 1f7d mrr $AX1.H, $AC1.L // ax1.h = 0x8080 +0160 8100 clr $ACC0 +0161 00de 0011 lr $AC0.M, @0x0011 +0163 3400 andr $AC0.M, $AX0.H // ac0.m = *0x11 & 0xff +0164 8900 clr $ACC1 // so it was all to setup ax0.h and ax1.h... +0165 00df 0012 lr $AC1.M, @0x0012 +0167 3500 andr $AC1.M, $AX0.H // ac1.m = *0x12 & 0xff +0168 4c00 add $ACC0, $ACC1 +0169 00df 0012 lr $AC1.M, @0x0012 +016b 1578 lsr $ACC1, #-8 +016c 4c00 add $ACC0, $ACC1 // acc0 = ((*0x11 & 0xff) << 16) + ((*0x12 & 0xff) << 16) + (*0x12 << 8) +016d 8900 clr $ACC1 +016e 1ffe mrr $AC1.M, $AC0.M +016f 1508 lsl $ACC1, #8 +0170 3b00 orr $AC1.M, $AX1.H // ac1.m = (ac0.m << 8) | 0x8080 +0171 00de 0011 lr $AC0.M, @0x0011 +0173 3e00 orc $AC0.M, $AC1.M // final11 = *0x11 | (ac0.m << 8) | 0x8080 +0174 00df 0012 lr $AC1.M, @0x0012 +0176 3b00 orr $AC1.M, $AX1.H +0177 1cbf mrr $IX1, $AC1.M // final12 = *0x12 | 0x8080 + +// write the final values @22 and @23 +// 0178 00da 15f1 lr $AX0.H, @0x15f1 // drom 0200 +// 017a 3500 andr $AC1.M, $AX0.H +// 017b 0295 0192 jz 0x0192 +if (final12 & 0x200 != 0) { + + // 017d 00df 10e2 lr $AC1.M, @0x10e2 // drom 376f + // 017f 1508 lsl $ACC1, #8 // -> 0x37_6f00 + // 0180 1f5f mrr $AX0.H, $AC1.M + // 0181 00df 103b lr $AC1.M, @0x103b // drom 0065 + // 0183 7900 decm $AC1.M // -> 0x64 + // 0184 3900 orr $AC1.M, $AX0.H + // 0185 3080 xorc $AC0.M, $AC1.M + // 0186 00fe 0022 sr @0x0022, $AC0.M // *0x22 = final11 ^ 0x6f64 + // 0188 00dc 1229 lr $AC0.L, @0x1229 // drom 657c + // 018a 00dd 11f8 lr $AC1.L, @0x11f8 // drom 0009 + // 018c 5c00 sub $ACC0, $ACC1 + // 018d f000 lsl16 $ACC0 + // 018e 1fe5 mrr $AC1.M, $IX1 + // 018f 3080 xorc $AC0.M, $AC1.M // *0x23 = final12 ^ 0x6573 + // 0190 029f 01a5 jmp 0x01a5 + *0x22 = final11 ^ 0x6f64 + *0x23 = final12 ^ 0x6573 + +} else { + // 0192 00df 10ca lr $AC1.M, @0x10ca // drom 3461 + // 0194 1508 lsl $ACC1, #8 // -> 0x34_6100 + // 0195 1f5f mrr $AX0.H, $AC1.M + // 0196 00df 1043 lr $AC1.M, @0x1043 // drom 0076 + // 0198 7500 incm $AC1.M // -> 0x77 + // 0199 3900 orr $AC1.M, $AX0.H + // 019a 3080 xorc $AC0.M, $AC1.M + // 019b 00fe 0022 sr @0x0022, $AC0.M // *0x22 = final11 ^ 0x6177 + // 019d 00dc 1259 lr $AC0.L, @0x1259 // drom 6143 + // 019f 00dd 16fe lr $AC1.L, @0x16fe // drom 0008 + // 01a1 4c00 add $ACC0, $ACC1 + // 01a2 f000 lsl16 $ACC0 + // 01a3 1fe5 mrr $AC1.M, $IX1 + // 01a4 3080 xorc $AC0.M, $AC1.M // *0x23 = final12 ^ 0x614b + *0x22 = final11 ^ 0x6177 + *0x23 = final12 ^ 0x614b +} +// 01a5 00fe 0023 sr @0x0023, $AC0.M // taken care of above + +// this is where result is written to main memory +// dsp mem 0x20-0x23 (8 bytes) are written back - only values @22 and @23 were modified, so result is 32bit +01a7 00da 0008 lr $AX0.H, @0x0008 // sec_params.dest_addr[0] +01a9 00d8 0009 lr $AX0.L, @0x0009 // sec_params.dest_addr[1] +01ab 009b 0020 lri $AX1.H, #0x0020 // dsp addr +01ad 0099 0008 lri $AX1.L, #0x0008 // length +01af 0087 0000 lri $IX3, #0x0000 // there will be no iram dma +01b1 02bf 808b call 0x808b // do it! + +01b3 02df ret +} + +01b4 0000 nop +01b5 0000 nop +01b6 0000 nop +01b7 0000 nop +01b8 0000 nop +01b9 0000 nop +01ba 0000 nop +01bb 0000 nop +01bc 0000 nop +01bd 0000 nop +01be 0000 nop +01bf 0000 nop diff -Nru dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_IPL_24B22038.txt dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_IPL_24B22038.txt --- dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_IPL_24B22038.txt 1970-01-01 01:00:00.000000000 +0100 +++ dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_IPL_24B22038.txt 2010-08-18 03:25:25.000000000 +0100 @@ -0,0 +1,1985 @@ +0000 029f 0010 jmp 0x0010 +0002 0000 nop +0003 0000 nop +0004 02ff rti +0005 0000 nop +0006 02ff rti +0007 0000 nop +0008 02ff rti +0009 0000 nop +000a 02ff rti +000b 0000 nop +000c 02ff rti +000d 0000 nop +000e 02ff rti +000f 0000 nop + +// Entry +void 0010_Entry() +{ +0010 1302 sbset #0x02 +0011 1303 sbset #0x03 +0012 1204 sbclr #0x04 +0013 1305 sbset #0x05 +0014 1306 sbset #0x06 +0015 8e00 set16 +0016 8c00 clr15 +0017 8b00 m0 +0018 009e ffff lri $AC0.M, #0xffff +001a 1d1e mrr $WR0, $AC0.M +001b 1d3e mrr $WR1, $AC0.M +001c 1d5e mrr $WR2, $AC0.M +001d 1d7e mrr $WR3, $AC0.M +001e 0092 00ff lri $CR, #0x00ff +0020 8100 clr $ACC0 +0021 009f 1000 lri $AC1.M, #0x1000 +0023 0080 0000 lri $AR0, #0x0000 +0025 005f loop $AC1.M + 0026 1b1e srri @$AR0, $AC0.M // clear dram +0027 26ff lrs $AC0.M, @CMBL +0028 16fc 8888 si @DMBH, #0x8888 +002a 16fd 1111 si @DMBL, #0x1111 // SENDMAIL 0x88881111 +002c 26fc lrs $AC0.M, @DMBH +002d 02a0 8000 andf $AC0.M, #0x8000 +002f 029c 002c jlnz 0x002c +} + +void 0031_MainLoop() +{ +0031 8100 clr $ACC0 +0032 8900 clr $ACC1 +0033 26fe lrs $AC0.M, @CMBH +0034 02c0 8000 andcf $AC0.M, #0x8000 +0036 029c 0031 jlnz 0x0031 // wait for mail +0038 27ff lrs $AC1.M, @CMBL +0039 00ff 0345 sr @0x0345, $AC1.M +003b 1ffe mrr $AC1.M, $AC0.M +003c 0340 00ff andi $AC1.M, #0x00ff +003e 00ff 0344 sr @0x0344, $AC1.M +0040 1479 lsr $ACC0, #-7 +0041 0240 007e andi $AC0.M, #0x007e +0043 0200 0062 addi $AC0.M, #0x0062 +0045 00fe 0343 sr @0x0343, $AC0.M +0047 1c1e mrr $AR0, $AC0.M +0048 170f jmpr $AR0 // jump on CMD? +0049 009e 8000 lri $AC0.M, #0x8000 +004b 00dc 0343 lr $AC0.L, @0x0343 +004d 02bf 005a call 005a_SendMail(AC0.M,AC0.L) // sendmail 0x8000???? +004f 029f 0031 jmp 0x0031 +} + +void 0051_WaitForMailAndStoreIt(DEST $AR0) +{ +0051 26fe lrs $AC0.M, @CMBH +0052 02c0 8000 andcf $AC0.M, #0x8000 +0054 029c 0051 jlnz 0x0051 +0056 24ff lrs $AC0.L, @CMBL +0057 1b1e srri @$AR0, $AC0.M +0058 1b1c srri @$AR0, $AC0.L +0059 02df ret +} + +void 005a_SendMail(AC0.M,AC0.L) +{ +005a 2efc srs @DMBH, $AC0.M +005b 2cfd srs @DMBL, $AC0.L +005c 26fc lrs $AC0.M, @DMBH +005d 02a0 8000 andf $AC0.M, #0x8000 +005f 029c 005c jlnz 0x005c +0061 02df ret +} + +//CMDs +0062 029f 0049 jmp 0x0049 // CMD_0 +0064 029f 02bd jmp 0x02bd // CMD_1 +0066 029f 0470 jmp 0x0470 // CMD_2 +0068 029f 0031 jmp 0x0031 // CMD_3 +006a 029f 00df jmp 0x00df // CMD_4 +006c 029f 00f1 jmp 0x00f1 // CMD_5 +006e 029f 05bb jmp 0x05bb // CMD_6 +0070 029f 056f jmp 0x056f // CMD_7 +0072 029f 05d7 jmp 0x05d7 // CMD_8 +0074 029f 059f jmp 0x059f // CMD_9 +0076 029f 0741 jmp 0x0741 // CMD_A +0078 029f 0618 jmp 0x0618 // CMD_B - jump to IROM area (0x8644) +007a 029f 0203 jmp 0x0203 // CMD_C + +{ +007c 193e lrri $AC0.M, @$AR1 +007d 193c lrri $AC0.L, @$AR1 +007e 2fcd srs @DSPA, $AC1.M +007f 0f00 lris $AC1.M, #0x00 +0080 2fc9 srs @DSCR, $AC1.M // DMEM->CPU +0081 2ece srs @DSMAH, $AC0.M +0082 2ccf srs @DSMAL, $AC0.L +0083 1fe0 mrr $AC1.M, $AR0 +0084 1501 lsl $ACC1, #1 +0085 2fcb srs @DSBL, $AC1.M +0086 02bf 008f call 0x008f +0088 02df ret +} + +{ +0089 193e lrri $AC0.M, @$AR1 +008a 193c lrri $AC0.L, @$AR1 +008b 2fcd srs @DSPA, $AC1.M +008c 0f01 lris $AC1.M, #0x01 +008d 029f 0080 jmp 0x0080 +} + +{ +008f 26c9 lrs $AC0.M, @DSCR +0090 02a0 0004 andf $AC0.M, #0x0004 +0092 029c 008f jlnz 0x008f +0094 02df ret +} + +{ +0095 193e lrri $AC0.M, @$AR1 +0096 193c lrri $AC0.L, @$AR1 +0097 00ff ffcd sr @DSPA, $AC1.M +0099 0f00 lris $AC1.M, #0x00 +009a 00ff ffc9 sr @DSCR, $AC1.M +009c 00fe ffce sr @DSMAH, $AC0.M +009e 00fc ffcf sr @DSMAL, $AC0.L +00a0 1fe0 mrr $AC1.M, $AR0 +00a1 1501 lsl $ACC1, #1 +00a2 00ff ffcb sr @DSBL, $AC1.M +00a4 02df ret +} + +void 00a5_WaitForDMAend() +{ +00a5 00de ffc9 lr $AC0.M, @DSCR +00a7 02a0 0004 andf $AC0.M, #0x0004 +00a9 029c 00a5 jlnz 0x00a5 +00ab 02df ret +} + +void 00ac_AccZeldaTypeRead() +{ +00ac 193e lrri $AC0.M, @$AR1 +00ad 193c lrri $AC0.L, @$AR1 +00ae 0240 7fff andi $AC0.M, #0x7fff +00b0 02bf 00ba call 00ba_AccSetup() +00b2 007a 00b8 bloop $AX0.H, 0x00b8 +00b4 26d3 lrs $AC0.M, @UnkZelda +00b5 1b3e srri @$AR1, $AC0.M +00b6 0000 nop +00b7 0000 nop +00b8 0000 nop +00b9 02df ret +} + +void 00ba_AccSetup() +{ +00ba 1c3f mrr $AR1, $AC1.M +00bb 009f 0005 lri $AC1.M, #0x0005 +00bd 2fd1 srs @SampleFormat, $AC1.M // reads will be u8 +00be 1f5e mrr $AX0.H, $AC0.M +00bf 1f1c mrr $AX0.L, $AC0.L +00c0 2ed4 srs @ACSAH, $AC0.M +00c1 2cd5 srs @ACSAL, $AC0.L +00c2 8900 clr $ACC1 +00c3 1fa0 mrr $AC1.L, $AR0 +00c4 4c00 add $ACC0, $ACC1 +00c5 0200 0030 addi $AC0.M, #0x0030 +00c7 2ed6 srs @ACEAH, $AC0.M +00c8 2cd7 srs @ACEAL, $AC0.L +00c9 1fda mrr $AC0.M, $AX0.H +00ca 1f98 mrr $AC0.L, $AX0.L +00cb 147f lsr $ACC0, #-1 +00cc 2ed8 srs @ACCAH, $AC0.M +00cd 2cd9 srs @ACCAL, $AC0.L +00ce 1f40 mrr $AX0.H, $AR0 +00cf 02df ret +} + +void 00d0_AccZeldaTypeWrite() +{ +00d0 193e lrri $AC0.M, @$AR1 +00d1 193c lrri $AC0.L, @$AR1 +00d2 0260 8000 ori $AC0.M, #0x8000 +00d4 02bf 00ba call 00ba_AccSetup() +00d6 007a 00dd bloop $AX0.H, 0x00dd +{ + 00d8 193e lrri $AC0.M, @$AR1 + 00d9 2ed3 srs @UnkZelda, $AC0.M + 00da 0000 nop + 00db 0000 nop + 00dc 0000 nop + 00dd 0000 nop +} +00de 02df ret +} + +{ +00df 0080 0346 lri $AR0, #0x0346 +00e1 02bf 0051 call 0x0051 +00e3 02bf 0051 call 0x0051 +00e5 0081 0346 lri $AR1, #0x0346 +00e7 00df 0349 lr $AC1.M, @0x0349 +00e9 0340 ffff andi $AC1.M, #0xffff +00eb 00c0 0345 lr $AR0, @0x0345 +00ed 02bf 007c call 0x007c +00ef 029f 0049 jmp 0x0049 +} + +{ +00f1 0080 0346 lri $AR0, #0x0346 +00f3 02bf 0051 call 0x0051 +00f5 02bf 0051 call 0x0051 +00f7 0081 0346 lri $AR1, #0x0346 +00f9 00df 0349 lr $AC1.M, @0x0349 +00fb 0340 ffff andi $AC1.M, #0xffff +00fd 00c0 0345 lr $AR0, @0x0345 +00ff 02bf 0089 call 0x0089 +0101 029f 0049 jmp 0x0049 +} + +{ +0103 0092 00ff lri $CR, #0x00ff +0105 2fd1 srs @SampleFormat, $AC1.M +0106 0340 0003 andi $AC1.M, #0x0003 +0108 1f7f mrr $AX1.H, $AC1.M +0109 1f5e mrr $AX0.H, $AC0.M +010a 1f1c mrr $AX0.L, $AC0.L +010b 0200 0010 addi $AC0.M, #0x0010 +010d 2ed4 srs @ACSAH, $AC0.M +010e 2cd5 srs @ACSAL, $AC0.L +010f 8900 clr $ACC1 +0110 1fa0 mrr $AC1.L, $AR0 +0111 4c00 add $ACC0, $ACC1 +0112 0200 0030 addi $AC0.M, #0x0030 +0114 2ed6 srs @ACEAH, $AC0.M +0115 2cd7 srs @ACEAL, $AC0.L +0116 1fda mrr $AC0.M, $AX0.H +0117 1f98 mrr $AC0.L, $AX0.L +0118 1ffb mrr $AC1.M, $AX1.H +0119 7900 decm $AC1.M +011a 02ca lsrn +011b 2ed8 srs @ACCAH, $AC0.M +011c 2cd9 srs @ACCAL, $AC0.L +011d 02df ret +} + +//DSPLLE errors here!!! readw/writes from 0x3??? +{ +011e 1c23 mrr $AR1, $AR3 +011f 197e lrri $AC0.M, @$AR3 +0120 191b lrri $AX1.H, @$AR0 +0121 d858 mulc'l $AC1.M, $AX1.H : $AX1.H, @$AR0 +0122 1128 0128 bloopi #0x28, 0x0128 +0124 dcd3 mulcac'ld $AC1.M, $AX1.H, $ACC0 : $AX0.L, $AX1.H, @$AR3 +0125 6231 movr's $ACC0, $AX1.L : @$AR1, $AC0.M +0126 dcd3 mulcac'ld $AC1.M, $AX1.H, $ACC0 : $AX0.L, $AX1.H, @$AR3 +0127 6231 movr's $ACC0, $AX1.L : @$AR1, $AC0.M +0128 4900 addax $ACC1, $AX0 +0129 02df ret +} + +{ +012a 8f00 set40 +012b 1c03 mrr $AR0, $AR3 +012c 00db 038e lr $AX1.H, @0x038e +012e 009a 0004 lri $AX0.H, #0x0004 +0130 1978 lrri $AX0.L, @$AR3 +0131 a843 mulx'l $AX0.L, $AX1.H : $AX0.L, @$AR3 +0132 ae00 mulxmv $AX0.L, $AX1.H, $ACC0 +0133 1128 0138 bloopi #0x28, 0x0138 +0135 38c3 asrnrx'l $ACC0, $AX0.H : $AX0.L, @$AR3 +0136 ae30 mulxmv's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC0.M +0137 38c3 asrnrx'l $ACC0, $AX0.H : $AX0.L, @$AR3 +0138 ae30 mulxmv's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC0.M +0139 8e00 set16 +013a 02df ret +} + +{ +013b 00f9 0361 sr @0x0361, $AX1.L +013d 1fc0 mrr $AC0.M, $AR0 +013e 0200 fffc addi $AC0.M, #0xfffc +0140 1c1e mrr $AR0, $AC0.M +0141 1c5e mrr $AR2, $AC0.M +0142 0083 0424 lri $AR3, #0x0424 +0144 197e lrri $AC0.M, @$AR3 +0145 197f lrri $AC1.M, @$AR3 +0146 80a2 nx'sl : $AC0.M, $AX0.H +0147 64a3 movr'sl $ACC0, $AX0.H : $AC1.M, $AX0.H +0148 6530 movr's $ACC1, $AX0.H : @$AR0, $AC0.M +0149 1b1f srri @$AR0, $AC1.M +014a 1c02 mrr $AR0, $AR2 +014b 8100 clr $ACC0 +014c 00de 0402 lr $AC0.M, @0x0402 +014e 00fe 0362 sr @0x0362, $AC0.M +0150 1474 lsr $ACC0, #-12 +0151 1f7e mrr $AX1.H, $AC0.M +0152 1f3c mrr $AX1.L, $AC0.L +0153 8900 clr $ACC1 +0154 00dd 0418 lr $AC1.L, @0x0418 +0156 1504 lsl $ACC1, #4 +0157 0604 cmpis $AC0.M, #0x04 +0158 0290 01b0 jge 0x01b0 +015a 1fdd mrr $AC0.M, $AC1.L +015b 0082 0c00 lri $AR2, #0x0c00 +015d 1050 loopi #0x50 +015e 4b2a addax's $ACC1, $AX1 : @$AR2, $AC1.L +015f 1fbe mrr $AC1.L, $AC0.M +0160 00fe 0360 sr @0x0360, $AC0.M +0162 8900 clr $ACC1 +0163 1fbe mrr $AC1.L, $AC0.M +0164 009a fff8 lri $AX0.H, #0xfff8 +0166 009b 00fc lri $AX1.H, #0x00fc +0168 00d8 0361 lr $AX0.L, @0x0361 +016a 0082 0c00 lri $AR2, #0x0c00 +016c 0083 0c00 lri $AR3, #0x0c00 +016e 195e lrri $AC0.M, @$AR2 +016f 3480 lsrnrx $ACC0, $AX0.H +0170 1128 0175 bloopi #0x28, 0x0175 +0172 367a andr'l $AC0.M, $AX1.H : $AC1.M, @$AR2 +0173 35b3 lsrnrx's $ACC1, $AX0.H : @$AR3, $AC0.M +0174 3772 andr'l $AC1.M, $AX1.H : $AC0.M, @$AR2 +0175 34bb lsrnrx's $ACC0, $AX0.H : @$AR3, $AC1.M +0176 8a00 m2 +0177 0082 0c00 lri $AR2, #0x0c00 +0179 00dd 0418 lr $AC1.L, @0x0418 +017b 1504 lsl $ACC1, #4 +017c 1fe0 mrr $AC1.M, $AR0 +017d 8100 clr $ACC0 +017e 00de 0362 lr $AC0.M, @0x0362 +0180 1474 lsr $ACC0, #-12 +0181 1f7e mrr $AX1.H, $AC0.M +0182 1f3c mrr $AX1.L, $AC0.L +0183 8f00 set40 +0184 1943 lrri $AR3, @$AR2 +0185 4bc3 addax'ld $ACC1, $AX1 : $AX0.L, $AX1.L, @$AR3 +0186 90c3 mul'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 +0187 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 +0188 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 +0189 f200 madd $AX0.L, $AX0.H +018a fe00 movpz $ACC0 +018b 1c1f mrr $AR0, $AC1.M +018c 1943 lrri $AR3, @$AR2 +018d 4bc3 addax'ld $ACC1, $AX1 : $AX0.L, $AX1.L, @$AR3 +018e 90c3 mul'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 +018f 114e 0197 bloopi #0x4e, 0x0197 +0191 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 +0192 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 +0193 f231 madd's $AX0.L, $AX0.H : @$AR1, $AC0.M +0194 1c1f mrr $AR0, $AC1.M +0195 1943 lrri $AR3, @$AR2 +0196 4bc3 addax'ld $ACC1, $AX1 : $AX0.L, $AX1.L, @$AR3 +0197 92c3 mulmvz'ld $AX0.L, $AX0.H, $ACC0 : $AX0.L, $AX1.L, @$AR3 +0198 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 +0199 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 +019a f231 madd's $AX0.L, $AX0.H : @$AR1, $AC0.M +019b fe00 movpz $ACC0 +019c 1b3e srri @$AR1, $AC0.M +019d 8b00 m0 +019e 8e00 set16 +019f 00fe 041b sr @0x041b, $AC0.M +01a1 1c1f mrr $AR0, $AC1.M +01a2 150c lsl $ACC1, #12 +01a3 0340 0fff andi $AC1.M, #0x0fff +01a5 00ff 0418 sr @0x0418, $AC1.M +01a7 0083 0424 lri $AR3, #0x0424 +01a9 191e lrri $AC0.M, @$AR0 +01aa 191f lrri $AC1.M, @$AR0 +01ab 80a0 nx'ls : $AX0.H, $AC0.M +01ac 64a1 movr'ls $ACC0, $AX0.H : $AX0.H, $AC1.M +01ad 6533 movr's $ACC1, $AX0.H : @$AR3, $AC0.M +01ae 1b7f srri @$AR3, $AC1.M +01af 02df ret +} + +{ +01b0 1fe0 mrr $AC1.M, $AR0 +01b1 1c1f mrr $AR0, $AC1.M +01b2 1128 01b9 bloopi #0x28, 0x01b9 +01b4 4b70 addax'l $ACC1, $AX1 : $AC0.M, @$AR0 +01b5 1b3e srri @$AR1, $AC0.M +01b6 1c1f mrr $AR0, $AC1.M +01b7 4b70 addax'l $ACC1, $AX1 : $AC0.M, @$AR0 +01b8 1b3e srri @$AR1, $AC0.M +01b9 1c1f mrr $AR0, $AC1.M +01ba 029f 019f jmp 0x019f +} + +{ +01bc 8a00 m2 +01bd 0088 0007 lri $WR0, #0x0007 +01bf 1150 01cc bloopi #0x50, 0x01cc +{ + 01c1 1c61 mrr $AR3, $AR1 + 01c2 84c3 clrp'ld : $AX0.L, $AX1.L, @$AR3 + 01c3 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 + 01c4 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 + 01c5 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 + 01c6 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 + 01c7 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 + 01c8 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 + 01c9 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 + 01ca f200 madd $AX0.L, $AX0.H + 01cb fe00 movpz $ACC0 + 01cc 1b3e srri @$AR1, $AC0.M +} +01cd 0088 ffff lri $WR0, #0xffff +01cf 8b00 m0 +01d0 02df ret +} + +{ +01d1 0088 0003 lri $WR0, #0x0003 +01d3 0085 0000 lri $IX1, #0x0000 +01d5 0087 0000 lri $IX3, #0x0000 +01d7 1fc2 mrr $AC0.M, $AR2 +01d8 195b lrri $AX1.H, @$AR2 +01d9 1959 lrri $AX1.L, @$AR2 +01da 195f lrri $AC1.M, @$AR2 +01db 195a lrri $AX0.H, @$AR2 +01dc 1c5e mrr $AR2, $AC0.M +01dd 1fda mrr $AC0.M, $AX0.H +01de 1c61 mrr $AR3, $AR1 +01df 8a00 m2 +01e0 8f00 set40 +01e1 191a lrri $AX0.H, @$AR0 +01e2 b850 mulx'l $AX0.H, $AX1.H : $AX0.H, @$AR0 +01e3 e250 maddx'l $AX0.H, $AX1.L : $AX0.H, @$AR0 +01e4 ea50 maddc'l $AC1.M, $AX1.L : $AX0.H, @$AR0 +01e5 e8e8 maddc'ldm $AC0.M, $AX1.L : $AX0.H, $AX1.L, @$AR0 +01e6 b650 mulxmv'l $AX0.H, $AX1.L, $ACC0 : $AX0.H, @$AR0 +01e7 1127 01f2 bloopi #0x27, 0x01f2 +{ + 01e9 e3a8 maddx'lsm $AX0.H, $AX1.H : $AX0.H, $AC0.M + 01ea 197e lrri $AC0.M, @$AR3 + 01eb e850 maddc'l $AC0.M, $AX1.L : $AX0.H, @$AR0 + 01ec eaf8 maddc'ldm $AC1.M, $AX1.L : $AX0.H, $AX1.H, @$AR0 + 01ed bf50 mulxmv'l $AX0.H, $AX1.H, $ACC1 : $AX0.H, @$AR0 + 01ee e2a9 maddx'lsm $AX0.H, $AX1.L : $AX0.H, $AC1.M + 01ef 197f lrri $AC1.M, @$AR3 + 01f0 ea50 maddc'l $AC1.M, $AX1.L : $AX0.H, @$AR0 + 01f1 e8e8 maddc'ldm $AC0.M, $AX1.L : $AX0.H, $AX1.L, @$AR0 + 01f2 b650 mulxmv'l $AX0.H, $AX1.L, $ACC0 : $AX0.H, @$AR0 +} +01f3 e3a8 maddx'lsm $AX0.H, $AX1.H : $AX0.H, $AC0.M +01f4 197e lrri $AC0.M, @$AR3 +01f5 e850 maddc'l $AC0.M, $AX1.L : $AX0.H, @$AR0 +01f6 eaf8 maddc'ldm $AC1.M, $AX1.L : $AX0.H, $AX1.H, @$AR0 +01f7 bf00 mulxmv $AX0.H, $AX1.H, $ACC1 +01f8 1bff srrn @$AR3, $AC1.M +01f9 197f lrri $AC1.M, @$AR3 +01fa 8e00 set16 +01fb 8b00 m0 +01fc 0088 ffff lri $WR0, #0xffff +01fe 1b5b srri @$AR2, $AX1.H +01ff 1b59 srri @$AR2, $AX1.L +0200 1b5f srri @$AR2, $AC1.M +0201 1b5e srri @$AR2, $AC0.M +0202 02df ret +} + +{ +0203 0080 0346 lri $AR0, #0x0346 +0205 02bf 0051 call 0x0051 +0207 02bf 0051 call 0x0051 +0209 0081 0346 lri $AR1, #0x0346 +020b 009f 0580 lri $AC1.M, #0x0580 +020d 0080 0080 lri $AR0, #0x0080 +020f 02bf 007c call 0x007c +0211 0081 0348 lri $AR1, #0x0348 +0213 009f 0c00 lri $AC1.M, #0x0c00 +0215 0080 0080 lri $AR0, #0x0080 +0217 02bf 007c call 0x007c +0219 0080 0c00 lri $AR0, #0x0c00 +021b 0081 0580 lri $AR1, #0x0580 +021d 02bf 01d1 call 0x01d1 +021f 0081 0346 lri $AR1, #0x0346 +0221 009f 0580 lri $AC1.M, #0x0580 +0223 0080 0080 lri $AR0, #0x0080 +0225 02bf 0089 call 0x0089 +0227 0081 0348 lri $AR1, #0x0348 +0229 009f 0c00 lri $AC1.M, #0x0c00 +022b 0080 0080 lri $AR0, #0x0080 +022d 02bf 0089 call 0x0089 +022f 029f 0049 jmp 0x0049 +} + +void 0231_FormatAudioSynths(format AC0.M) +{ +0231 8100 clr $ACC0 +0232 1f5e mrr $AX0.H, $AC0.M +0233 00d8 0402 lr $AX0.L, @0x0402 +0235 00dc 0418 lr $AC0.L, @0x0418 +0237 0080 0520 lri $AR0, #0x0520 +0239 00df 0440 lr $AC1.M, @0x0440 +023b 1501 lsl $ACC1, #1 +023c 0340 007e andi $AC1.M, #0x007e +023e 0300 0246 addi $AC1.M, #0x0246 +0240 1c5f mrr $AR2, $AC1.M +0241 175f callr $AR2 // call 0x0246 +0242 00fc 0418 sr @0x0418, $AC0.L +0244 029f 04e7 jmp 0x04e7 // dummy +0246 029f 0257 jmp 0x0257 // 0x0 - Synth0 +0248 029f 028f jmp 0x028f // 0x1 - Synth1 +024a 029f 0277 jmp 0x0277 // 0x2 - Synth2 +024c 029f 0267 jmp 0x0267 // 0x3 - Synth3 +024e 029f 0292 jmp 0x0292 // 0x4 - Synth4 +0250 029f 0256 jmp 0x0256 // 0x5 - dummy +0252 029f 02b1 jmp 0x02b1 // 0x6 - Synth6 +0254 029f 02ae jmp 0x02ae // 0x7 - Synth7 +0256 02df ret +} + +void 0257_Synth0() +{ +0257 1401 lsl $ACC0, #1 +0258 009b c000 lri $AX1.H, #0xc000 +025a 0099 4000 lri $AX1.L, #0x4000 +025c 1150 0264 bloopi #0x50, 0x0264 +{ + 025e 02c0 0001 andcf $AC0.M, #0x0001 + 0260 027c iflnz + 0261 1b1b srri @$AR0, $AX1.H + 0262 027d iflz + 0263 1b19 srri @$AR0, $AX1.L + 0264 4800 addax $ACC0, $AX0 +} +0265 147f lsr $ACC0, #-1 +0266 02df ret +} + +void 0267_Synth3() +{ +0267 1401 lsl $ACC0, #1 +0268 009b c000 lri $AX1.H, #0xc000 +026a 0099 4000 lri $AX1.L, #0x4000 +026c 1150 0274 bloopi #0x50, 0x0274 +{ + 026e 02c0 0003 andcf $AC0.M, #0x0003 + 0270 027c iflnz + 0271 1b1b srri @$AR0, $AX1.H + 0272 027d iflz + 0273 1b19 srri @$AR0, $AX1.L + 0274 4800 addax $ACC0, $AX0 +} +0275 147f lsr $ACC0, #-1 +0276 02df ret +} + +void 0277_Synth2() +{ +0277 1401 lsl $ACC0, #1 +0278 0081 0ca0 lri $AR1, #0x0ca0 +027a 009b c000 lri $AX1.H, #0xc000 +027c 0099 4000 lri $AX1.L, #0x4000 +027e 8900 clr $ACC1 +027f 0082 0000 lri $AR2, #0x0000 +0281 1150 028c bloopi #0x50, 0x028c +{ + 0283 02c0 0001 andcf $AC0.M, #0x0001 + 0285 027c iflnz + 0286 1b1b srri @$AR0, $AX1.H + 0287 027d iflz + 0288 1b19 srri @$AR0, $AX1.L + 0289 183d lrr $AC1.L, @$AR1 + 028a 4900 addax $ACC1, $AX0 + 028b 1fe2 mrr $AC1.M, $AR2 + 028c 4c39 add's $ACC0, $ACC1 : @$AR1, $AC1.M +} +028d 147f lsr $ACC0, #-1 +028e 02df ret +} + +void 028f_Synth1() +{ +028f 1050 loopi #0x50 + 0290 4820 addax's $ACC0, $AX0 : @$AR0, $AC0.L +0291 02df ret +} + +void 0292_Synth4() +{ +0292 0082 0140 lri $AR2, #0x0140 +0294 008a 003f lri $WR2, #0x003f +0296 0086 0000 lri $IX2, #0x0000 +0298 1406 lsl $ACC0, #6 +0299 8900 clr $ACC1 +029a 1fb8 mrr $AC1.L, $AX0.L +029b 1506 lsl $ACC1, #6 +029c 009b 003f lri $AX1.H, #0x003f +029e 009a 0000 lri $AX0.H, #0x0000 +02a0 3600 andr $AC0.M, $AX1.H +02a1 1cde mrr $IX2, $AC0.M +02a2 001a addarn $AR2, $IX2 +02a3 3400 andr $AC0.M, $AX0.H +02a4 1150 02aa bloopi #0x50, 0x02aa +{ + 02a6 4c00 add $ACC0, $ACC1 + 02a7 364a andr'l $AC0.M, $AX1.H : $AX1.L, @$AR2 + 02a8 1cde mrr $IX2, $AC0.M + 02a9 340e andr'nr $AC0.M, $AX0.H : $AR2 + 02aa 1b19 srri @$AR0, $AX1.L +} +02ab 1fc2 mrr $AC0.M, $AR2 +02ac 147a lsr $ACC0, #-6 +02ad 02df ret +} + +void 02b1_Synth7() +{ +02ae 1050 loopi #0x50 + 02af 1b18 srri @$AR0, $AX0.L +02b0 02df ret +} + +void 02b1_Synth6() +{ +02b1 0083 0000 lri $AR3, #0x0000 +02b3 140f lsl $ACC0, #15 +02b4 4853 addax'l $ACC0, $AX0 : $AX0.H, @$AR3 +02b5 1114 02ba bloopi #0x14, 0x02ba +{ + 02b7 48a2 addax'sl $ACC0, $AX0 : $AC0.M, $AX0.H + 02b8 48a2 addax'sl $ACC0, $AX0 : $AC0.M, $AX0.H + 02b9 48a2 addax'sl $ACC0, $AX0 : $AC0.M, $AX0.H + 02ba 48a2 addax'sl $ACC0, $AX0 : $AC0.M, $AX0.H +} +02bb 146f lsr $ACC0, #-17 +02bc 02df ret +} + +{ +02bd 0080 0380 lri $AR0, #0x0380 +02bf 02bf 0051 call 0x0051 +02c1 02bf 0051 call 0x0051 +02c3 02bf 0051 call 0x0051 +02c5 02bf 0051 call 0x0051 +02c7 0081 0382 lri $AR1, #0x0382 +02c9 009f 0000 lri $AC1.M, #0x0000 +02cb 0080 0200 lri $AR0, #0x0200 +02cd 02bf 007c call 0x007c +02cf 0081 0384 lri $AR1, #0x0384 +02d1 009f 0300 lri $AC1.M, #0x0300 +02d3 0080 0020 lri $AR0, #0x0020 +02d5 02bf 007c call 0x007c +02d7 02bf 0351 call 0x0351 +02d9 00de 0345 lr $AC0.M, @0x0345 +02db 00fe 0342 sr @0x0342, $AC0.M +02dd 029f 0049 jmp 0x0049 +} + +{ +02df 00de 0344 lr $AC0.M, @0x0344 +02e1 1404 lsl $ACC0, #4 +02e2 0200 03a8 addi $AC0.M, #0x03a8 +02e4 1c1e mrr $AR0, $AC0.M +02e5 02bf 0051 call 0x0051 +02e7 02bf 0051 call 0x0051 +02e9 02bf 0051 call 0x0051 +02eb 00de 0345 lr $AC0.M, @0x0345 +02ed 1b1e srri @$AR0, $AC0.M +02ee 00de 0344 lr $AC0.M, @0x0344 +02f0 0200 03a4 addi $AC0.M, #0x03a4 +02f2 1c1e mrr $AR0, $AC0.M +02f3 8100 clr $ACC0 +02f4 1b1e srri @$AR0, $AC0.M +02f5 02df ret +} + +{ +02f6 00de 0344 lr $AC0.M, @0x0344 +02f8 1404 lsl $ACC0, #4 +02f9 0200 03b0 addi $AC0.M, #0x03b0 +02fb 1c1e mrr $AR0, $AC0.M +02fc 02bf 0051 call 0x0051 +02fe 02bf 0051 call 0x0051 +0300 02bf 0051 call 0x0051 +0302 02bf 0051 call 0x0051 +0304 02df ret +} + +{ +0305 0081 034c lri $AR1, #0x034c +0307 009f 0400 lri $AC1.M, #0x0400 +0309 0080 0080 lri $AR0, #0x0080 +030b 02bf 007c call 0x007c +030d 02df ret +} + +{ +030e 0081 034c lri $AR1, #0x034c +0310 009f 0a00 lri $AC1.M, #0x0a00 +0312 0080 0004 lri $AR0, #0x0004 +0314 02bf 00a5 call 00a5_WaitForDMAend() +0316 02bf 007c call 0x007c +0318 0081 034c lri $AR1, #0x034c +031a 009f 0400 lri $AC1.M, #0x0400 +031c 0080 0080 lri $AR0, #0x0080 +031e 02bf 0095 call 0x0095 +0320 02df ret +} + +{ +0321 0081 034c lri $AR1, #0x034c +0323 009f 0400 lri $AC1.M, #0x0400 +0325 0080 0040 lri $AR0, #0x0040 +0327 0081 034c lri $AR1, #0x034c +0329 193e lrri $AC0.M, @$AR1 +032a 193c lrri $AC0.L, @$AR1 +032b 0098 0000 lri $AX0.L, #0x0000 +032d 7000 addaxl $ACC0, $AX0.L +032e 02bf 008b call 0x008b +0330 02df ret +} + +{ +0331 191e lrri $AC0.M, @$AR0 +0332 191a lrri $AX0.H, @$AR0 +0333 005f loop $AC1.M +0334 64a0 movr'ls $ACC0, $AX0.H : $AX0.H, $AC0.M +0335 1b7e srri @$AR3, $AC0.M +0336 1b7a srri @$AR3, $AX0.H +0337 02df ret +} + +{ +0338 191e lrri $AC0.M, @$AR0 +0339 191a lrri $AX0.H, @$AR0 +033a 007f 033f bloop $AC1.M, 0x033f +{ + 033c 32b2 not's $AC0.M : @$AR2, $AC0.M + 033d 65a0 movr'ls $ACC1, $AX0.H : $AX0.H, $AC0.M + 033e 33ba not's $AC1.M : @$AR2, $AC1.M + 033f 64a1 movr'ls $ACC0, $AX0.H : $AX0.H, $AC1.M +} +0340 0000 nop +0341 02df ret +} + +{ +0342 8a00 m2 +0343 157f lsr $ACC1, #-1 +0344 1c20 mrr $AR1, $AR0 +0345 1c03 mrr $AR0, $AR3 +0346 193a lrri $AX0.H, @$AR1 +0347 9051 mul'l $AX0.L, $AX0.H : $AX0.H, @$AR1 +0348 925b mulmvz'l $AX0.L, $AX0.H, $ACC0 : $AX1.H, @$AR3 +0349 007f 034e bloop $AC1.M, 0x034e +{ + 034b 4651 addr'l $ACC0, $AX1.H : $AX0.H, @$AR1 + 034c 92b2 mulmvz'sl $AX0.L, $AX0.H, $ACC0 : $AC0.M, $AX1.H + 034d 4651 addr'l $ACC0, $AX1.H : $AX0.H, @$AR1 + 034e 92b2 mulmvz'sl $AX0.L, $AX0.H, $ACC0 : $AC0.M, $AX1.H +} +034f 8b00 m0 +0350 02df ret +} + +{ +0351 0083 ffa0 lri $AR3, #0xffa0 +0353 0080 0300 lri $AR0, #0x0300 +0355 009f 000e lri $AC1.M, #0x000e +0357 1108 035c bloopi #0x08, 0x035c +{ + 0359 191e lrri $AC0.M, @$AR0 + 035a 1b7e srri @$AR3, $AC0.M + 035b 191e lrri $AC0.M, @$AR0 + 035c 1b7e srri @$AR3, $AC0.M +} +035d 02df ret +} + +{ +035e 0080 0f40 lri $AR0, #0x0f40 +0360 0082 0d00 lri $AR2, #0x0d00 +0362 0083 0d60 lri $AR3, #0x0d60 +0364 009f 0028 lri $AC1.M, #0x0028 +0366 02bf 0338 call 0x0338 +0368 8900 clr $ACC1 +0369 009e 0050 lri $AC0.M, #0x0050 +036b 0080 0ca0 lri $AR0, #0x0ca0 +036d 005e loop $AC0.M + 036e 1b1f srri @$AR0, $AC1.M +036f 0080 0f40 lri $AR0, #0x0f40 +0371 005e loop $AC0.M + 0372 1b1f srri @$AR0, $AC1.M +0373 0080 0fa0 lri $AR0, #0x0fa0 +0375 005e loop $AC0.M + 0376 1b1f srri @$AR0, $AC1.M +0377 02df ret +} + +{ +0378 0080 0dc0 lri $AR0, #0x0dc0 +037a 009e 0180 lri $AC0.M, #0x0180 +037c 8900 clr $ACC1 +037d 005e loop $AC0.M + 037e 1b1f srri @$AR0, $AC1.M +037f 02df ret +} + +{ +0380 00c0 03a0 lr $AR0, @0x03a0 +0382 191a lrri $AX0.H, @$AR0 +0383 00df 03a1 lr $AC1.M, @0x03a1 +0385 009b 00a0 lri $AX1.H, #0x00a0 +0387 0081 0393 lri $AR1, #0x0393 +0389 18bc lrrd $AC0.L, @$AR1 +038a b871 mulx'l $AX0.H, $AX1.H : $AC0.M, @$AR1 +038b bc00 mulxac $AX0.H, $AX1.H, $ACC0 +038c 0080 0050 lri $AR0, #0x0050 +038e 0508 addis $AC1.M, #0x08 +038f 02bf 007e call 0x007e +0391 00de 0390 lr $AC0.M, @0x0390 +0393 02a0 0001 andf $AC0.M, #0x0001 +0395 029d 039f jlz 0x039f +0397 0080 0398 lri $AR0, #0x0398 +0399 009e 0008 lri $AC0.M, #0x0008 +039b 00c1 03a1 lr $AR1, @0x03a1 +039d 02bf 01bc call 0x01bc +039f 009f 0050 lri $AC1.M, #0x0050 +03a1 00c0 03a1 lr $AR0, @0x03a1 +03a3 8100 clr $ACC0 +03a4 00de 0394 lr $AC0.M, @0x0394 +03a6 b100 tst $ACC0 +03a7 0295 03ae jz 0x03ae +03a9 1c7e mrr $AR3, $AC0.M +03aa 00d8 0395 lr $AX0.L, @0x0395 +03ac 02bf 0342 call 0x0342 +03ae 009f 0050 lri $AC1.M, #0x0050 +03b0 00c0 03a1 lr $AR0, @0x03a1 +03b2 8100 clr $ACC0 +03b3 00de 0396 lr $AC0.M, @0x0396 +03b5 b100 tst $ACC0 +03b6 0295 03bd jz 0x03bd +03b8 1c7e mrr $AR3, $AC0.M +03b9 00d8 0397 lr $AX0.L, @0x0397 +03bb 02bf 0342 call 0x0342 +03bd 00de 0390 lr $AC0.M, @0x0390 +03bf 02a0 0002 andf $AC0.M, #0x0002 +03c1 02dd retlz +03c2 0080 0398 lri $AR0, #0x0398 +03c4 009e 0008 lri $AC0.M, #0x0008 +03c6 00c1 03a1 lr $AR1, @0x03a1 +03c8 02bf 01bc call 0x01bc +03ca 02df ret +} + +{ +03cb 009f 0dc0 lri $AC1.M, #0x0dc0 +03cd 00ff 03a1 sr @0x03a1, $AC1.M +03cf 009f 03a8 lri $AC1.M, #0x03a8 +03d1 00ff 03a2 sr @0x03a2, $AC1.M +03d3 009f 03a4 lri $AC1.M, #0x03a4 +03d5 00ff 03a0 sr @0x03a0, $AC1.M +03d7 1104 0400 bloopi #0x04, 0x0400 +{ + 03d9 00c0 03a2 lr $AR0, @0x03a2 + 03db 0083 0390 lri $AR3, #0x0390 + 03dd 009f 000e lri $AC1.M, #0x000e + 03df 02bf 0331 call 0x0331 + 03e1 00da 0390 lr $AX0.H, @0x0390 + 03e3 8600 tstaxh $AX0.H + 03e4 0295 03f1 jz 0x03f1 + 03e6 00df 03a1 lr $AC1.M, @0x03a1 + 03e8 1c7f mrr $AR3, $AC1.M + 03e9 0550 addis $AC1.M, #0x50 + 03ea 1c1f mrr $AR0, $AC1.M + 03eb 009f 0006 lri $AC1.M, #0x0006 + 03ed 02bf 0331 call 0x0331 + 03ef 02bf 0380 call 0x0380 + 03f1 00de 03a2 lr $AC0.M, @0x03a2 + 03f3 0410 addis $AC0.M, #0x10 + 03f4 00fe 03a2 sr @0x03a2, $AC0.M + 03f6 00de 03a1 lr $AC0.M, @0x03a1 + 03f8 0460 addis $AC0.M, #0x60 + 03f9 00fe 03a1 sr @0x03a1, $AC0.M + 03fb 00de 03a0 lr $AC0.M, @0x03a0 + 03fd 7400 incm $AC0.M + 03fe 00fe 03a0 sr @0x03a0, $AC0.M + 0400 0000 nop +} +0401 02df ret +} + +{ +0402 00c0 03a0 lr $AR0, @0x03a0 +0404 181a lrr $AX0.H, @$AR0 +0405 8100 clr $ACC0 +0406 181e lrr $AC0.M, @$AR0 +0407 00db 0391 lr $AX1.H, @0x0391 +0409 7400 incm $AC0.M +040a d100 cmpar $ACC1, $AX0.H +040b 0270 ifge +040c 8100 clr $ACC0 +040d 1b1e srri @$AR0, $AC0.M +040e 00df 03a1 lr $AC1.M, @0x03a1 +0410 009b 00a0 lri $AX1.H, #0x00a0 +0412 0081 0393 lri $AR1, #0x0393 +0414 18bc lrrd $AC0.L, @$AR1 +0415 b871 mulx'l $AX0.H, $AX1.H : $AC0.M, @$AR1 +0416 bc00 mulxac $AX0.H, $AX1.H, $ACC0 +0417 0080 0050 lri $AR0, #0x0050 +0419 02bf 008b call 0x008b +041b 02df ret +} + +{ +041c 009f 0dc0 lri $AC1.M, #0x0dc0 +041e 00ff 03a1 sr @0x03a1, $AC1.M +0420 009f 03a8 lri $AC1.M, #0x03a8 +0422 00ff 03a2 sr @0x03a2, $AC1.M +0424 009f 03a4 lri $AC1.M, #0x03a4 +0426 00ff 03a0 sr @0x03a0, $AC1.M +0428 1104 0448 bloopi #0x04, 0x0448 +{ + 042a 00c0 03a2 lr $AR0, @0x03a2 + 042c 0083 0390 lri $AR3, #0x0390 + 042e 009f 000e lri $AC1.M, #0x000e + 0430 02bf 0331 call 0x0331 + 0432 00da 0390 lr $AX0.H, @0x0390 + 0434 8600 tstaxh $AX0.H + 0435 0295 0439 jz 0x0439 + 0437 02bf 0402 call 0x0402 + 0439 00de 03a2 lr $AC0.M, @0x03a2 + 043b 0410 addis $AC0.M, #0x10 + 043c 00fe 03a2 sr @0x03a2, $AC0.M + 043e 00de 03a1 lr $AC0.M, @0x03a1 + 0440 0460 addis $AC0.M, #0x60 + 0441 00fe 03a1 sr @0x03a1, $AC0.M + 0443 00de 03a0 lr $AC0.M, @0x03a0 + 0445 7400 incm $AC0.M + 0446 00fe 03a0 sr @0x03a0, $AC0.M + 0448 0000 nop +} +0449 02df ret +} + +{ +044a 0081 0386 lri $AR1, #0x0386 +044c 009f 03a8 lri $AC1.M, #0x03a8 +044e 0080 0040 lri $AR0, #0x0040 +0450 02bf 007c call 0x007c +0452 02df ret +} + +{ +0453 191e lrri $AC0.M, @$AR0 +0454 189c lrrd $AC0.L, @$AR0 +0455 4800 addax $ACC0, $AX0 +0456 1b1e srri @$AR0, $AC0.M +0457 1b1c srri @$AR0, $AC0.L +0458 02df ret +0459 8100 clr $ACC0 +045a 26fe lrs $AC0.M, @CMBH +045b 02c0 8000 andcf $AC0.M, #0x8000 +045d 029c 045a jlnz 0x045a +045f 26ff lrs $AC0.M, @CMBL +0460 02df ret +} + +{ +0461 0080 0388 lri $AR0, #0x0388 +0463 0081 0051 lri $AR1, #0x0051 +0465 173f callr $AR1 // call 0x0051 +0466 00de 0344 lr $AC0.M, @0x0344 +0468 00fe 0341 sr @0x0341, $AC0.M +046a 00de 0345 lr $AC0.M, @0x0345 +046c 00fe 038e sr @0x038e, $AC0.M +046e 173f callr $AR1 // call 0x0051 +046f 02df ret +} + +{ +0470 02bf 0461 call 0x0461 +0472 009e 8000 lri $AC0.M, #0x8000 +0474 00dc 0341 lr $AC0.L, @0x0341 +0476 02bf 005a call 005a_SendMail(AC0.M,AC0.L) // 0x8000???? +0478 8100 clr $ACC0 +0479 00fe 0355 sr @0x0355, $AC0.M +047b 02bf 044a call 0x044a +047d 00de 0341 lr $AC0.M, @0x0341 +047f 007e 056c bloop $AC0.M, 0x056c +{ + 0481 02bf 035e call 0x035e + 0483 02bf 03cb call 0x03cb + 0485 02bf 0459 call 0x0459 + 0487 8100 clr $ACC0 + 0488 00fe 0354 sr @0x0354, $AC0.M + 048a 00de 0342 lr $AC0.M, @0x0342 + 048c 007e 0538 bloop $AC0.M, 0x0538 + { + 048e 00d8 0354 lr $AX0.L, @0x0354 + 0490 009a 0100 lri $AX0.H, #0x0100 + 0492 8100 clr $ACC0 + 0493 00de 0380 lr $AC0.M, @0x0380 + 0495 00dc 0381 lr $AC0.L, @0x0381 + 0497 9000 mul $AX0.L, $AX0.H + 0498 9400 mulac $AX0.L, $AX0.H, $ACC0 + 0499 00fe 034c sr @0x034c, $AC0.M + 049b 00fc 034d sr @0x034d, $AC0.L + 049d 02bf 0305 call 0x0305 + 049f 00da 0400 lr $AX0.H, @0x0400 + 04a1 8600 tstaxh $AX0.H + 04a2 0295 0533 jz 0x0533 + 04a4 00da 0401 lr $AX0.H, @0x0401 + 04a6 8600 tstaxh $AX0.H + 04a7 0294 0533 jnz 0x0533 + 04a9 00da 0406 lr $AX0.H, @0x0406 + 04ab 8600 tstaxh $AX0.H + 04ac 0294 0930 jnz 0x0930 + 04ae 8100 clr $ACC0 + 04af 00de 0440 lr $AC0.M, @0x0440 + 04b1 0607 cmpis $AC0.M, #0x07 // format 0x7 or less (Synths) + 04b2 0293 0231 jle 0x0231 + 04b4 0620 cmpis $AC0.M, #0x20 // format 0x20 + 04b5 0295 079e jz 0x079e + 04b7 0621 cmpis $AC0.M, #0x21 // format 0x21 + 04b8 0295 07a7 jz 0x07a7 + 04ba 00d8 0402 lr $AX0.L, @0x0402 + 04bc 8100 clr $ACC0 + 04bd 8900 clr $ACC1 + 04be 00dc 0418 lr $AC0.L, @0x0418 + 04c0 8d00 set15 + 04c1 0099 0050 lri $AX1.L, #0x0050 + 04c3 a000 mulx $AX0.L, $AX1.L + 04c4 a400 mulxac $AX0.L, $AX1.L, $ACC0 + 04c5 1404 lsl $ACC0, #4 + 04c6 8c00 clr15 + 04c7 1ffe mrr $AC1.M, $AC0.M + 04c8 0083 0580 lri $AR3, #0x0580 + 04ca 00da 0441 lr $AX0.H, @0x0441 + 04cc 8600 tstaxh $AX0.H + 04cd 0295 04dd jz 0x04dd + 04cf 00da 0449 lr $AX0.H, @0x0449 + 04d1 8100 clr $ACC0 + 04d2 00de 044b lr $AC0.M, @0x044b + 04d4 3800 orr $AC0.M, $AX0.H + 04d5 0240 000f andi $AC0.M, #0x000f + 04d7 0295 04dd jz 0x04dd + 04d9 02bf 06a6 call 0x06a6 + 04db 029f 04df jmp 0x04df + 04dd 02bf 0837 call 0x0837 + //RAW21-jmp + 04df 0080 0580 lri $AR0, #0x0580 + 04e1 0081 0520 lri $AR1, #0x0520 + 04e3 0099 0000 lri $AX1.L, #0x0000 + 04e5 02bf 013b call 0x013b + //RAW20-jmp + 04e7 0080 0450 lri $AR0, #0x0450 + 04e9 0081 0520 lri $AR1, #0x0520 + 04eb 0082 0428 lri $AR2, #0x0428 + 04ed 0083 0453 lri $AR3, #0x0453 + 04ef 18fa lrrd $AX0.H, @$AR3 + 04f0 8600 tstaxh $AX0.H + 04f1 0294 0501 jnz 0x0501 + 04f3 18fa lrrd $AX0.H, @$AR3 + 04f4 8600 tstaxh $AX0.H + 04f5 0294 0501 jnz 0x0501 + 04f7 18fa lrrd $AX0.H, @$AR3 + 04f8 8600 tstaxh $AX0.H + 04f9 0294 0501 jnz 0x0501 + 04fb 8100 clr $ACC0 + 04fc 18fe lrrd $AC0.M, @$AR3 + 04fd 0280 7fff cmpi $AC0.M, #0x7fff + 04ff 0295 0505 jz 0x0505 + 0501 02bf 01d1 call 0x01d1 + 0503 029f 0505 jmp 0x0505 + 0505 8100 clr $ACC0 + 0506 1c9e mrr $IX0, $AC0.M + 0507 1cde mrr $IX2, $AC0.M + 0508 7400 incm $AC0.M + 0509 1cfe mrr $IX3, $AC0.M + 050a 8f00 set40 + 050b 0086 0002 lri $IX2, #0x0002 + 050d 0082 0408 lri $AR2, #0x0408 + 050f 1104 052f bloopi #0x04, 0x052f + { + 0511 8100 clr $ACC0 + 0512 195e lrri $AC0.M, @$AR2 + 0513 1200 sbclr #0x00 + 0514 b100 tst $ACC0 + 0515 0275 ifz + 0516 1300 sbset #0x00 + 0517 1c7e mrr $AR3, $AC0.M + 0518 195e lrri $AC0.M, @$AR2 + 0519 14fa asr $ACC0, #-6 + 051a 1f5e mrr $AX0.H, $AC0.M + 051b 1f1c mrr $AX0.L, $AC0.L + 051c 185f lrr $AC1.M, @$AR2 + 051d 0080 0520 lri $AR0, #0x0520 + 051f 029d 0523 jlz 0x0523 + 0521 02bf 011e call 0x011e + 0523 1b5f srri @$AR2, $AC1.M + 0524 8100 clr $ACC0 + 0525 185e lrr $AC0.M, @$AR2 + 0526 000e xar $AR2 + //; *** UNKNOWN OPCODE *** + // 0xc/0xd/0xe/0xf is one opcode where last 2 bits define target $AR? reg + // (new value is based on orig $AR? and %WR? reg value = unknown) + 0527 b100 tst $ACC0 + 0528 0274 ifnz + 0529 7800 decm $AC0.M + 052a b100 tst $ACC0 + 052b 8900 clr $ACC1 + 052c 0275 ifz + 052d 1a5f srr @$AR2, $AC1.M + 052e 001a addarn $AR2, $IX2 + 052f 1b5e srri @$AR2, $AC0.M + } + 0530 8e00 set16 + 0531 02bf 0321 call 0x0321 + 0533 00de 0354 lr $AC0.M, @0x0354 + 0535 7400 incm $AC0.M + 0536 00fe 0354 sr @0x0354, $AC0.M + 0538 0000 nop + } + 0539 16fb 0001 si @DIRQ, #0x0001 + 053b 0083 0d00 lri $AR3, #0x0d00 + 053d 02bf 012a call 0x012a + 053f 0081 0388 lri $AR1, #0x0388 + 0541 009f 0d00 lri $AC1.M, #0x0d00 + 0543 0080 0050 lri $AR0, #0x0050 + 0545 02bf 0089 call 0x0089 + 0547 0080 0fa0 lri $AR0, #0x0fa0 + 0549 0083 0d60 lri $AR3, #0x0d60 + 054b 009f 0050 lri $AC1.M, #0x0050 + 054d 0098 8000 lri $AX0.L, #0x8000 + 054f 02bf 0342 call 0x0342 + 0551 0083 0d60 lri $AR3, #0x0d60 + 0553 02bf 012a call 0x012a + 0555 0081 038a lri $AR1, #0x038a + 0557 009f 0d60 lri $AC1.M, #0x0d60 + 0559 0080 0050 lri $AR0, #0x0050 + 055b 02bf 0089 call 0x0089 + 055d 009a 0000 lri $AX0.H, #0x0000 + 055f 0098 00a0 lri $AX0.L, #0x00a0 + 0561 0080 0388 lri $AR0, #0x0388 + 0563 02bf 0453 call 0x0453 + 0565 0080 038a lri $AR0, #0x038a + 0567 02bf 0453 call 0x0453 + 0569 02bf 041c call 0x041c + 056b 0000 nop + 056c 0000 nop +} +056d 029f 0031 jmp 0x0031 +} + +{ +056f 0080 0346 lri $AR0, #0x0346 +0571 02bf 0051 call 0x0051 +0573 02bf 0051 call 0x0051 +0575 0081 0346 lri $AR1, #0x0346 +0577 193e lrri $AC0.M, @$AR1 +0578 193c lrri $AC0.L, @$AR1 +0579 009f 0400 lri $AC1.M, #0x0400 +057b 00c0 0345 lr $AR0, @0x0345 +057d 02bf 007e call 0x007e +057f 0081 0348 lri $AR1, #0x0348 +0581 193e lrri $AC0.M, @$AR1 +0582 193c lrri $AC0.L, @$AR1 +0583 009f 0800 lri $AC1.M, #0x0800 +0585 00c0 0345 lr $AR0, @0x0345 +0587 02bf 007e call 0x007e +0589 0081 0346 lri $AR1, #0x0346 +058b 193e lrri $AC0.M, @$AR1 +058c 193c lrri $AC0.L, @$AR1 +058d 009f 0800 lri $AC1.M, #0x0800 +058f 00c0 0345 lr $AR0, @0x0345 +0591 02bf 008b call 0x008b +0593 0081 0348 lri $AR1, #0x0348 +0595 193e lrri $AC0.M, @$AR1 +0596 193c lrri $AC0.L, @$AR1 +0597 009f 0400 lri $AC1.M, #0x0400 +0599 00c0 0345 lr $AR0, @0x0345 +059b 02bf 008b call 0x008b +059d 029f 0049 jmp 0x0049 +} + +{ +059f 0080 0346 lri $AR0, #0x0346 +05a1 02bf 0051 call 0x0051 +05a3 02bf 0051 call 0x0051 +05a5 0081 0346 lri $AR1, #0x0346 +05a7 193e lrri $AC0.M, @$AR1 +05a8 193c lrri $AC0.L, @$AR1 +05a9 009f 0400 lri $AC1.M, #0x0400 +05ab 00c0 0345 lr $AR0, @0x0345 +05ad 02bf 007e call 0x007e +05af 0081 0348 lri $AR1, #0x0348 +05b1 193e lrri $AC0.M, @$AR1 +05b2 193c lrri $AC0.L, @$AR1 +05b3 009f 0400 lri $AC1.M, #0x0400 +05b5 00c0 0345 lr $AR0, @0x0345 +05b7 02bf 008b call 0x008b +05b9 029f 0049 jmp 0x0049 +} + +{ +05bb 0080 0346 lri $AR0, #0x0346 +05bd 02bf 0051 call 0x0051 +05bf 02bf 0051 call 0x0051 +05c1 0081 0346 lri $AR1, #0x0346 +05c3 193e lrri $AC0.M, @$AR1 +05c4 193c lrri $AC0.L, @$AR1 +05c5 009f 0400 lri $AC1.M, #0x0400 +05c7 00c0 0345 lr $AR0, @0x0345 +05c9 02bf 00ae call 0x00ae +05cb 0081 0348 lri $AR1, #0x0348 +05cd 193e lrri $AC0.M, @$AR1 +05ce 193c lrri $AC0.L, @$AR1 +05cf 009f 0400 lri $AC1.M, #0x0400 +05d1 00c0 0345 lr $AR0, @0x0345 +05d3 02bf 008b call 0x008b +05d5 029f 0049 jmp 0x0049 +} + +{ +05d7 0080 0346 lri $AR0, #0x0346 +05d9 02bf 0051 call 0x0051 +05db 02bf 0051 call 0x0051 +05dd 0081 0346 lri $AR1, #0x0346 +05df 193e lrri $AC0.M, @$AR1 +05e0 193c lrri $AC0.L, @$AR1 +05e1 009f 0400 lri $AC1.M, #0x0400 +05e3 00c0 0344 lr $AR0, @0x0344 +05e5 02bf 007e call 0x007e +05e7 0081 0348 lri $AR1, #0x0348 +05e9 193e lrri $AC0.M, @$AR1 +05ea 193c lrri $AC0.L, @$AR1 +05eb 009f 0800 lri $AC1.M, #0x0800 +05ed 00c0 0344 lr $AR0, @0x0344 +05ef 02bf 007e call 0x007e +05f1 0080 0400 lri $AR0, #0x0400 +05f3 0083 0800 lri $AR3, #0x0800 +05f5 0084 0000 lri $IX0, #0x0000 +05f7 00da 0345 lr $AX0.H, @0x0345 +05f9 00df 0344 lr $AC1.M, @0x0344 +05fb 8f00 set40 +05fc 197b lrri $AX1.H, @$AR3 +05fd b800 mulx $AX0.H, $AX1.H +05fe 197b lrri $AX1.H, @$AR3 +05ff 007f 0604 bloop $AC1.M, 0x0604 +0601 199e lrrn $AC0.M, @$AR0 +0602 bc00 mulxac $AX0.H, $AX1.H, $ACC0 +0603 80b2 nx'sl : $AC0.M, $AX1.H +0604 0000 nop +0605 8e00 set16 +0606 0081 0346 lri $AR1, #0x0346 +0608 193e lrri $AC0.M, @$AR1 +0609 193c lrri $AC0.L, @$AR1 +060a 009f 0400 lri $AC1.M, #0x0400 +060c 00c0 0344 lr $AR0, @0x0344 +060e 02bf 008b call 0x008b +0610 009e 8200 lri $AC0.M, #0x8200 +0612 00dc 0344 lr $AC0.L, @0x0344 +0614 02bf 005a call 005a_SendMail(AC0.M,AC0.L) // 0x8200???? +0616 029f 0031 jmp 0x0031 +} + +{ +0618 0080 0346 lri $AR0, #0x0346 +061a 02bf 0051 call 0x0051 +061c 0081 0346 lri $AR1, #0x0346 +061e 009f 0400 lri $AC1.M, #0x0400 +0620 00c0 0345 lr $AR0, @0x0345 +0622 02bf 007c call 0x007c +0624 02bf 8644 call 0x8644 // iROM!!!! +0626 029f 0049 jmp 0x0049 +} + +{ +0628 009e 0430 lri $AC0.M, #0x0430 +062a 2219 lrs $AX0.H, @0x0019 +062b 4400 addr $ACC0, $AX0.H +062c 1c1e mrr $AR0, $AC0.M +062d 1fda mrr $AC0.M, $AX0.H +062e 3280 not $AC0.M +062f 7400 incm $AC0.M +0630 221a lrs $AX0.H, @0x001a +0631 4400 addr $ACC0, $AX0.H +0632 0090 0000 lri $AC0.H, #0x0000 +0634 029f 0645 jmp 0x0645 +} + +{ +0636 009e 0430 lri $AC0.M, #0x0430 +0638 2219 lrs $AX0.H, @0x0019 +0639 4400 addr $ACC0, $AX0.H +063a 1c1e mrr $AR0, $AC0.M +063b 1fda mrr $AC0.M, $AX0.H +063c 3280 not $AC0.M +063d 7400 incm $AC0.M +063e 221a lrs $AX0.H, @0x001a +063f 4400 addr $ACC0, $AX0.H +0640 0090 0000 lri $AC0.H, #0x0000 +0642 8200 cmp +0643 0270 ifge +0644 1fdf mrr $AC0.M, $AC1.M +0645 1f3e mrr $AX1.L, $AC0.M +0646 02bf 0699 call 0x0699 +0648 261c lrs $AC0.M, @0x001c +0649 241d lrs $AC0.L, @0x001d +064a 7200 addaxl $ACC0, $AX1.L +064b 5300 subr $ACC1, $AX1.L +064c 2e1c srs @0x001c, $AC0.M +064d 2c1d srs @0x001d, $AC0.L +064e 02df ret +} + +{ +064f 8100 clr $ACC0 +0650 221c lrs $AX0.H, @0x001c +0651 201d lrs $AX0.L, @0x001d +0652 4800 addax $ACC0, $AX0 +0653 147c lsr $ACC0, #-4 +0654 2e1e srs @0x001e, $AC0.M +0655 2c1f srs @0x001f, $AC0.L +0656 2340 lrs $AX1.H, @0x0040 +0657 c814 mulc'mv $AC0.M, $AX1.H : $AX1.L, $AC0.L +0658 9e00 mulmv $AX1.L, $AX1.H, $ACC0 +0659 f000 lsl16 $ACC0 +065a 4e00 addp $ACC0 +065b 234c lrs $AX1.H, @0x004c +065c 214d lrs $AX1.L, @0x004d +065d 4a00 addax $ACC0, $AX1 +065e 2e20 srs @0x0020, $AC0.M +065f 2c21 srs @0x0021, $AC0.L +0660 1fd8 mrr $AC0.M, $AX0.L +0661 0240 000f andi $AC0.M, #0x000f +0663 2e19 srs @0x0019, $AC0.M +0664 264a lrs $AC0.M, @0x004a +0665 244b lrs $AC0.L, @0x004b +0666 5800 subax $ACC0, $AX0 +0667 2e22 srs @0x0022, $AC0.M +0668 2c23 srs @0x0023, $AC0.L +0669 02df ret +} + +{ +066a 221e lrs $AX0.H, @0x001e +066b 201f lrs $AX0.L, @0x001f +066c 8100 clr $ACC0 +066d 264a lrs $AC0.M, @0x004a +066e 244b lrs $AC0.L, @0x004b +066f 147c lsr $ACC0, #-4 +0670 5800 subax $ACC0, $AX0 +0671 0295 067a jz 0x067a +0673 02bf 06ec call 0x06ec +0675 0e10 lris $AC0.M, #0x10 +0676 2e1a srs @0x001a, $AC0.M +0677 8100 clr $ACC0 +0678 2e19 srs @0x0019, $AC0.M +0679 02df ret +} + +{ +067a 224a lrs $AX0.H, @0x004a +067b 204b lrs $AX0.L, @0x004b +067c 8100 clr $ACC0 +067d 261c lrs $AC0.M, @0x001c +067e 241d lrs $AC0.L, @0x001d +067f 5800 subax $ACC0, $AX0 +0680 0290 0687 jge 0x0687 +0682 02bf 06ec call 0x06ec +0684 2623 lrs $AC0.M, @0x0023 +0685 029f 0676 jmp 0x0676 +} + +{ +0687 2648 lrs $AC0.M, @0x0048 +0688 2449 lrs $AC0.L, @0x0049 +0689 2e1c srs @0x001c, $AC0.M +068a 2c1d srs @0x001d, $AC0.L +068b 0e10 lris $AC0.M, #0x10 +068c 2e1a srs @0x001a, $AC0.M +068d 02bf 064f call 0x064f +068f 2642 lrs $AC0.M, @0x0042 +0690 2e3f srs @0x003f, $AC0.M +0691 2643 lrs $AC0.M, @0x0043 +0692 2e3e srs @0x003e, $AC0.M +0693 8100 clr $ACC0 +0694 00fe 0362 sr @0x0362, $AC0.M +0696 02bf 06ec call 0x06ec +0698 02df ret +} + +{ +0699 b100 tst $ACC0 +069a 02d5 retz +069b 04fe addis $AC0.M, #0xfe +069c 1f1e mrr $AX0.L, $AC0.M +069d 191e lrri $AC0.M, @$AR0 +069e 0291 06a4 jl 0x06a4 +06a0 191a lrri $AX0.H, @$AR0 +06a1 0058 loop $AX0.L +06a2 64a0 movr'ls $ACC0, $AX0.H : $AX0.H, $AC0.M +06a3 6433 movr's $ACC0, $AX0.H : @$AR3, $AC0.M +06a4 1b7e srri @$AR3, $AC0.M +06a5 02df ret +} + +{ +06a6 0092 0004 lri $CR, #0x0004 +06a8 02bf 064f call 0x064f +06aa 8100 clr $ACC0 +06ab 00fe 0362 sr @0x0362, $AC0.M +06ad 8100 clr $ACC0 +06ae 2622 lrs $AC0.M, @0x0022 +06af 2423 lrs $AC0.L, @0x0023 +06b0 b100 tst $ACC0 +06b1 0294 06c3 jnz 0x06c3 +06b3 02bf 066a call 0x066a +06b5 2219 lrs $AX0.H, @0x0019 +06b6 8600 tstaxh $AX0.H +06b7 0294 06c0 jnz 0x06c0 +06b9 02bf 0636 call 0x0636 +06bb b900 tst $ACC1 +06bc 0295 06e9 jz 0x06e9 +06be 02bf 064f call 0x064f +06c0 8100 clr $ACC0 +06c1 2622 lrs $AC0.M, @0x0022 +06c2 2423 lrs $AC0.L, @0x0023 +06c3 1f1f mrr $AX0.L, $AC1.M +06c4 009a 0000 lri $AX0.H, #0x0000 +06c6 5800 subax $ACC0, $AX0 +06c7 0290 06d6 jge 0x06d6 +06c9 8100 clr $ACC0 +06ca 2619 lrs $AC0.M, @0x0019 +06cb b100 tst $ACC0 +06cc 0294 06d0 jnz 0x06d0 +06ce 02bf 066a call 0x066a +06d0 02bf 0628 call 0x0628 +06d2 02bf 064f call 0x064f +06d4 029f 06ad jmp 0x06ad +} + +{ +06d6 8100 clr $ACC0 +06d7 2619 lrs $AC0.M, @0x0019 +06d8 b100 tst $ACC0 +06d9 0294 06dd jnz 0x06dd +06db 02bf 066a call 0x066a +06dd 02bf 0636 call 0x0636 +06df b900 tst $ACC1 +06e0 0295 06e9 jz 0x06e9 +06e2 02bf 064f call 0x064f +06e4 029f 06d6 jmp 0x06d6 +} + +{ +06e6 8100 clr $ACC0 +06e7 005f loop $AC1.M +06e8 1b7e srri @$AR3, $AC0.M +06e9 0092 00ff lri $CR, #0x00ff +06eb 02df ret +} + +{ +06ec 00ff 0360 sr @0x0360, $AC1.M +06ee 00da 0362 lr $AX0.H, @0x0362 +06f0 8600 tstaxh $AX0.H +06f1 0294 06fe jnz 0x06fe +06f3 0a01 lris $AX0.H, #0x01 +06f4 00fa 0362 sr @0x0362, $AX0.H +06f6 2620 lrs $AC0.M, @0x0020 +06f7 2421 lrs $AC0.L, @0x0021 +06f8 009f 0005 lri $AC1.M, #0x0005 +06fa 02bf 0103 call 0x0103 +06fc 0092 0004 lri $CR, #0x0004 +06fe 0080 ffd3 lri $AR0, #0xffd3 +0700 0084 0000 lri $IX0, #0x0000 +0702 199e lrrn $AC0.M, @$AR0 +0703 1ffe mrr $AC1.M, $AC0.M +0704 1401 lsl $ACC0, #1 +0705 0240 001e andi $AC0.M, #0x001e +0707 0200 0300 addi $AC0.M, #0x0300 +0709 1c3e mrr $AR1, $AC0.M +070a 157c lsr $ACC1, #-4 +070b 0340 000f andi $AC1.M, #0x000f +070d 0a11 lris $AX0.H, #0x11 +070e 5500 subr $ACC1, $AX0.H +070f 009a 00f0 lri $AX0.H, #0x00f0 +0711 009b 000f lri $AX1.H, #0x000f +0713 0082 0370 lri $AR2, #0x0370 +0715 1998 lrrn $AX0.L, @$AR0 +0716 6000 movr $ACC0, $AX0.L +0717 1107 071e bloopi #0x07, 0x071e +{ + 0719 3400 andr $AC0.M, $AX0.H + 071a 1408 lsl $ACC0, #8 + 071b 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M + 071c 3644 andr'ln $AC0.M, $AX1.H : $AX0.L, @$AR0 + 071d 140c lsl $ACC0, #12 + 071e 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M +} +071f 3400 andr $AC0.M, $AX0.H +0720 1408 lsl $ACC0, #8 +0721 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M +0722 3600 andr $AC0.M, $AX1.H +0723 140c lsl $ACC0, #12 +0724 1b5e srri @$AR2, $AC0.M +0725 8f00 set40 +0726 1f7f mrr $AX1.H, $AC1.M +0727 203e lrs $AX0.L, @0x003e +0728 273f lrs $AC1.M, @0x003f +0729 193a lrri $AX0.H, @$AR1 +072a 1939 lrri $AX1.L, @$AR1 +072b 0080 0370 lri $AR0, #0x0370 +072d 0081 0430 lri $AR1, #0x0430 +072f 1c80 mrr $IX0, $AR0 +0730 a000 mulx $AX0.L, $AX1.L +0731 ea70 maddc'l $AC1.M, $AX1.L : $AC0.M, @$AR0 +0732 1108 073b bloopi #0x08, 0x073b +0734 3a93 asrnrx'mv $ACC0, $AX1.H : $AX0.L, $AC1.M +0735 a478 mulxac'l $AX0.L, $AX1.L, $ACC0 : $AC1.M, @$AR0 +0736 1485 asl $ACC0, #5 +0737 e831 maddc's $AC0.M, $AX1.L : @$AR1, $AC0.M +0738 3b92 asrnrx'mv $ACC1, $AX1.H : $AX0.L, $AC0.M +0739 a570 mulxac'l $AX0.L, $AX1.L, $ACC1 : $AC0.M, @$AR0 +073a 1585 asl $ACC1, #5 +073b ea39 maddc's $AC1.M, $AX1.L : @$AR1, $AC1.M +073c 8e00 set16 +073d 8900 clr $ACC1 +073e 00df 0360 lr $AC1.M, @0x0360 +0740 02df ret +} + +{ +0741 0080 0346 lri $AR0, #0x0346 +0743 02bf 0051 call 0x0051 +0745 8100 clr $ACC0 +0746 0080 0430 lri $AR0, #0x0430 +0748 1010 loopi #0x10 + 0749 1b1e srri @$AR0, $AC0.M +074a 00fe 0442 sr @0x0442, $AC0.M +074c 00fe 0443 sr @0x0443, $AC0.M +074e 009c 0000 lri $AC0.L, #0x0000 +0750 00fe 041c sr @0x041c, $AC0.M +0752 00fc 041d sr @0x041d, $AC0.L +0754 009e 0100 lri $AC0.M, #0x0100 +0756 009c f100 lri $AC0.L, #0xf100 +0758 00fe 044e sr @0x044e, $AC0.M +075a 00fc 044f sr @0x044f, $AC0.L +075c 009e 0040 lri $AC0.M, #0x0040 +075e 009c 0000 lri $AC0.L, #0x0000 +0760 00fe 044c sr @0x044c, $AC0.M +0762 00fc 044d sr @0x044d, $AC0.L +0764 009e 0009 lri $AC0.M, #0x0009 +0766 00fe 0440 sr @0x0440, $AC0.M +0768 009e 0010 lri $AC0.M, #0x0010 +076a 00fe 041a sr @0x041a, $AC0.M +076c 009e 0100 lri $AC0.M, #0x0100 +076e 009c f250 lri $AC0.L, #0xf250 +0770 00fe 044a sr @0x044a, $AC0.M +0772 00fc 044b sr @0x044b, $AC0.L +0774 009c 0000 lri $AC0.L, #0x0000 +0776 00fe 0448 sr @0x0448, $AC0.M +0778 00fc 0449 sr @0x0449, $AC0.L +077a 009e 0001 lri $AC0.M, #0x0001 +077c 00fe 0441 sr @0x0441, $AC0.M +077e 8900 clr $ACC1 +077f 00ff 0401 sr @0x0401, $AC1.M +0781 1180 079b bloopi #0x80, 0x079b +{ + 0783 0083 0580 lri $AR3, #0x0580 + 0785 009f 0100 lri $AC1.M, #0x0100 + 0787 02bf 06a6 call 0x06a6 + 0789 0081 0346 lri $AR1, #0x0346 + 078b 193e lrri $AC0.M, @$AR1 + 078c 18bc lrrd $AC0.L, @$AR1 + 078d 009f 0580 lri $AC1.M, #0x0580 + 078f 0080 0100 lri $AR0, #0x0100 + 0791 02bf 008b call 0x008b + 0793 0081 0346 lri $AR1, #0x0346 + 0795 193e lrri $AC0.M, @$AR1 + 0796 18bc lrrd $AC0.L, @$AR1 + 0797 0098 0200 lri $AX0.L, #0x0200 + 0799 7000 addaxl $ACC0, $AX0.L + 079a 1b3e srri @$AR1, $AC0.M + 079b 1abc srrd @$AR1, $AC0.L +} +079c 029f 0049 jmp 0x0049 +} + +void 079e_AudioFormatRAW20() +{ +079e 8900 clr $ACC1 +079f 009f 0050 lri $AC1.M, #0x0050 +07a1 0083 0520 lri $AR3, #0x0520 +07a3 02bf 07b9 call 0x07b9 +07a5 029f 04e7 jmp 0x04e7 +} + +void 07a7_AudioFormatRAW21() +{ +07a7 00d8 0402 lr $AX0.L, @0x0402 +07a9 8100 clr $ACC0 +07aa 8900 clr $ACC1 +07ab 00dc 0418 lr $AC0.L, @0x0418 +07ad 009a 0050 lri $AX0.H, #0x0050 +07af 9000 mul $AX0.L, $AX0.H +07b0 9400 mulac $AX0.L, $AX0.H, $ACC0 +07b1 1404 lsl $ACC0, #4 +07b2 1ffe mrr $AC1.M, $AC0.M +07b3 0083 0580 lri $AR3, #0x0580 +07b5 02bf 07b9 call 0x07b9 +07b7 029f 04df jmp 0x04df +} + +{ +07b9 0092 0004 lri $CR, #0x0004 +07bb 8100 clr $ACC0 +07bc 2622 lrs $AC0.M, @0x0022 +07bd 2423 lrs $AC0.L, @0x0023 +07be 1f1f mrr $AX0.L, $AC1.M +07bf 009a 0000 lri $AX0.H, #0x0000 +07c1 5800 subax $ACC0, $AX0 +07c2 0290 07d9 jge 0x07d9 +07c4 8900 clr $ACC1 +07c5 00c0 0423 lr $AR0, @0x0423 +07c7 02bf 07fe call 0x07fe +07c9 8100 clr $ACC0 +07ca 1fd8 mrr $AC0.M, $AX0.L +07cb 2223 lrs $AX0.H, @0x0023 +07cc 5400 subr $ACC0, $AX0.H +07cd 0007 dar $AR3 +07ce 1979 lrri $AX1.L, @$AR3 +07cf 005e loop $AC0.M +07d0 1b79 srri @$AR3, $AX1.L +07d1 009f 0001 lri $AC1.M, #0x0001 +07d3 2f01 srs @0x0001, $AC1.M +07d4 8900 clr $ACC1 +07d5 2f23 srs @0x0023, $AC1.M +07d6 0092 00ff lri $CR, #0x00ff +07d8 02df ret +} + +{ +07d9 2e22 srs @0x0022, $AC0.M +07da 2c23 srs @0x0023, $AC0.L +07db 8100 clr $ACC0 +07dc 8900 clr $ACC1 +07dd 264a lrs $AC0.M, @0x004a +07de 271c lrs $AC1.M, @0x001c +07df 5c00 sub $ACC0, $ACC1 +07e0 2e1e srs @0x001e, $AC0.M +07e1 5000 subr $ACC0, $AX0.L +07e2 0290 07f8 jge 0x07f8 +07e4 00c0 041e lr $AR0, @0x041e +07e6 02bf 07fe call 0x07fe +07e8 8100 clr $ACC0 +07e9 1fd8 mrr $AC0.M, $AX0.L +07ea 221e lrs $AX0.H, @0x001e +07eb 5400 subr $ACC0, $AX0.H +07ec 1c1e mrr $AR0, $AC0.M +07ed 8100 clr $ACC0 +07ee 2e1c srs @0x001c, $AC0.M +07ef 2648 lrs $AC0.M, @0x0048 +07f0 2449 lrs $AC0.L, @0x0049 +07f1 2e4c srs @0x004c, $AC0.M +07f2 2c4d srs @0x004d, $AC0.L +07f3 02bf 07fe call 0x07fe +07f5 0092 00ff lri $CR, #0x00ff +07f7 02df ret +} + +{ +07f8 1c18 mrr $AR0, $AX0.L +07f9 02bf 07fe call 0x07fe +07fb 0092 00ff lri $CR, #0x00ff +07fd 02df ret +} + +{ +07fe 8100 clr $ACC0 +07ff 1fc0 mrr $AC0.M, $AR0 +0800 b100 tst $ACC0 +0801 02d5 retz +0802 8900 clr $ACC1 +0803 271c lrs $AC1.M, @0x001c +0804 0340 0001 andi $AC1.M, #0x0001 +0806 009b 0000 lri $AX1.H, #0x0000 +0808 1f3f mrr $AX1.L, $AC1.M +0809 264c lrs $AC0.M, @0x004c +080a 244d lrs $AC0.L, @0x004d +080b 8900 clr $ACC1 +080c 251c lrs $AC1.L, @0x001c +080d 1501 lsl $ACC1, #1 +080e 4c00 add $ACC0, $ACC1 +080f 5a00 subax $ACC0, $AX1 +0810 5a00 subax $ACC0, $AX1 +0811 1c20 mrr $AR1, $AR0 +0812 1fe0 mrr $AC1.M, $AR0 +0813 0502 addis $AC1.M, #0x02 +0814 1c1f mrr $AR0, $AC1.M +0815 009f 0a00 lri $AC1.M, #0x0a00 +0817 0092 00ff lri $CR, #0x00ff +0819 02bf 007e call 0x007e +081b 0092 0004 lri $CR, #0x0004 +081d 271c lrs $AC1.M, @0x001c +081e 1f61 mrr $AX1.H, $AR1 +081f 4700 addr $ACC1, $AX1.H +0820 2f1c srs @0x001c, $AC1.M +0821 0080 0a00 lri $AR0, #0x0a00 +0823 8900 clr $ACC1 +0824 1ff9 mrr $AC1.M, $AX1.L +0825 b900 tst $ACC1 +0826 0274 ifnz +0827 0008 iar $AR0 +0828 8900 clr $ACC1 +0829 1fe1 mrr $AC1.M, $AR1 +082a 191e lrri $AC0.M, @$AR0 +082b 0701 cmpis $AC1.M, #0x01 +082c 0293 0835 jle 0x0835 +082e 191a lrri $AX0.H, @$AR0 +082f 05fe addis $AC1.M, #0xfe +0830 005f loop $AC1.M +0831 64a0 movr'ls $ACC0, $AX0.H : $AX0.H, $AC0.M +0832 1b7e srri @$AR3, $AC0.M +0833 1b7a srri @$AR3, $AX0.H +0834 02df ret +} + +{ +0835 1b7e srri @$AR3, $AC0.M +0836 02df ret +} + +{ +0837 0092 0004 lri $CR, #0x0004 +0839 2201 lrs $AX0.H, @0x0001 +083a 8600 tstaxh $AX0.H +083b 0294 0868 jnz 0x0868 +083d 2204 lrs $AX0.H, @0x0004 +083e 8600 tstaxh $AX0.H +083f 02b4 08bc callnz 0x08bc +0841 2219 lrs $AX0.H, @0x0019 +0842 8600 tstaxh $AX0.H +0843 0295 085d jz 0x085d +0845 009e 0430 lri $AC0.M, #0x0430 +0847 4400 addr $ACC0, $AX0.H +0848 1c1e mrr $AR0, $AC0.M +0849 0e10 lris $AC0.M, #0x10 +084a 5400 subr $ACC0, $AX0.H +084b 1f7e mrr $AX1.H, $AC0.M +084c 02bf 0699 call 0x0699 +084e d900 cmpar $ACC1, $AX1.H +084f 0292 085c jg 0x085c +0851 0295 0858 jz 0x0858 +0853 2619 lrs $AC0.M, @0x0019 +0854 4c00 add $ACC0, $ACC1 +0855 2e19 srs @0x0019, $AC0.M +0856 029f 08b9 jmp 0x08b9 + +0858 8100 clr $ACC0 +0859 2e19 srs @0x0019, $AC0.M +085a 029f 08b9 jmp 0x08b9 + +085c 5700 subr $ACC1, $AX1.H +085d 8100 clr $ACC0 +085e 2605 lrs $AC0.M, @0x0005 +085f b100 tst $ACC0 +0860 0295 0879 jz 0x0879 +0862 8100 clr $ACC0 +0863 2e05 srs @0x0005, $AC0.M +0864 2241 lrs $AX0.H, @0x0041 +0865 8600 tstaxh $AX0.H +0866 0294 086f jnz 0x086f +0868 8100 clr $ACC0 +0869 005f loop $AC1.M +086a 1b7e srri @$AR3, $AC0.M +086b 7400 incm $AC0.M +086c 2e01 srs @0x0001, $AC0.M +086d 029f 08b9 jmp 0x08b9 + +086f 2648 lrs $AC0.M, @0x0048 +0870 2449 lrs $AC0.L, @0x0049 +0871 2e1c srs @0x001c, $AC0.M +0872 2c1d srs @0x001d, $AC0.L +0873 02bf 08c1 call 0x08c1 +0875 2642 lrs $AC0.M, @0x0042 +0876 2443 lrs $AC0.L, @0x0043 +0877 2e3f srs @0x003f, $AC0.M +0878 2c3e srs @0x003e, $AC0.L +0879 00ff 0360 sr @0x0360, $AC1.M +087b 2620 lrs $AC0.M, @0x0020 +087c 2421 lrs $AC0.L, @0x0021 +087d 009f 0005 lri $AC1.M, #0x0005 +087f 02bf 0103 call 0x0103 +0881 0092 0004 lri $CR, #0x0004 +0883 8900 clr $ACC1 +0884 00ff 0362 sr @0x0362, $AC1.M +0886 00df 0360 lr $AC1.M, @0x0360 +0888 02bf 08db call 0x08db +088a 8100 clr $ACC0 +088b 00de 0362 lr $AC0.M, @0x0362 +088d 2240 lrs $AX0.H, @0x0040 +088e 4400 addr $ACC0, $AX0.H +088f 00fe 0362 sr @0x0362, $AC0.M +0891 8100 clr $ACC0 +0892 2622 lrs $AC0.M, @0x0022 +0893 2423 lrs $AC0.L, @0x0023 +0894 0a01 lris $AX0.H, #0x01 +0895 0081 0405 lri $AR1, #0x0405 +0897 7a00 dec $ACC0 +0898 b100 tst $ACC0 +0899 0275 ifz +089a 1a3a srr @$AR1, $AX0.H +089b 2e22 srs @0x0022, $AC0.M +089c 2c23 srs @0x0023, $AC0.L +089d 0710 cmpis $AC1.M, #0x10 +089e 0293 08a7 jle 0x08a7 +08a0 05f0 addis $AC1.M, #0xf0 +08a1 2205 lrs $AX0.H, @0x0005 +08a2 8600 tstaxh $AX0.H +08a3 0294 0862 jnz 0x0862 +08a5 029f 0888 jmp 0x0888 +08a7 0275 ifz +08a8 8900 clr $ACC1 +08a9 2f19 srs @0x0019, $AC1.M +08aa 1fc3 mrr $AC0.M, $AR3 +08ab 04f0 addis $AC0.M, #0xf0 +08ac 1c1e mrr $AR0, $AC0.M +08ad 0083 0430 lri $AR3, #0x0430 +08af 0e10 lris $AC0.M, #0x10 +08b0 02bf 0699 call 0x0699 +08b2 2620 lrs $AC0.M, @0x0020 +08b3 2421 lrs $AC0.L, @0x0021 +08b4 00d8 0362 lr $AX0.L, @0x0362 +08b6 7000 addaxl $ACC0, $AX0.L +08b7 2c21 srs @0x0021, $AC0.L +08b8 2e20 srs @0x0020, $AC0.M +08b9 0092 00ff lri $CR, #0x00ff +08bb 02df ret +} + +{ +08bc 8100 clr $ACC0 +08bd 2e1c srs @0x001c, $AC0.M +08be 2e1d srs @0x001d, $AC0.M +08bf 2e3e srs @0x003e, $AC0.M +08c0 2e3f srs @0x003f, $AC0.M +08c1 231c lrs $AX1.H, @0x001c +08c2 211d lrs $AX1.L, @0x001d +08c3 264a lrs $AC0.M, @0x004a +08c4 244b lrs $AC0.L, @0x004b +08c5 5a00 subax $ACC0, $AX1 +08c6 147c lsr $ACC0, #-4 +08c7 2e22 srs @0x0022, $AC0.M +08c8 2c23 srs @0x0023, $AC0.L +08c9 261c lrs $AC0.M, @0x001c +08ca 241d lrs $AC0.L, @0x001d +08cb 147c lsr $ACC0, #-4 +08cc 2240 lrs $AX0.H, @0x0040 +08cd c010 mulc'mv $AC0.M, $AX0.H : $AX0.L, $AC0.L +08ce 9600 mulmv $AX0.L, $AX0.H, $ACC0 +08cf f000 lsl16 $ACC0 +08d0 4e00 addp $ACC0 +08d1 234c lrs $AX1.H, @0x004c +08d2 214d lrs $AX1.L, @0x004d +08d3 4a00 addax $ACC0, $AX1 +08d4 2e20 srs @0x0020, $AC0.M +08d5 2c21 srs @0x0021, $AC0.L +08d6 8100 clr $ACC0 +08d7 2e05 srs @0x0005, $AC0.M +08d8 2e19 srs @0x0019, $AC0.M +08d9 2e04 srs @0x0004, $AC0.M +08da 02df ret +} + +{ +08db 00ff 0360 sr @0x0360, $AC1.M +08dd 0080 ffd3 lri $AR0, #0xffd3 +08df 0084 0000 lri $IX0, #0x0000 +08e1 199e lrrn $AC0.M, @$AR0 +08e2 1ffe mrr $AC1.M, $AC0.M +08e3 1401 lsl $ACC0, #1 +08e4 0240 001e andi $AC0.M, #0x001e +08e6 0200 0300 addi $AC0.M, #0x0300 +08e8 1c3e mrr $AR1, $AC0.M +08e9 157c lsr $ACC1, #-4 +08ea 0340 000f andi $AC1.M, #0x000f +08ec 0a11 lris $AX0.H, #0x11 +08ed 5500 subr $ACC1, $AX0.H +08ee 009a 00f0 lri $AX0.H, #0x00f0 +08f0 009b 000f lri $AX1.H, #0x000f +08f2 0082 0370 lri $AR2, #0x0370 +08f4 1998 lrrn $AX0.L, @$AR0 +08f5 6000 movr $ACC0, $AX0.L +08f6 1107 08fd bloopi #0x07, 0x08fd +{ + 08f8 3400 andr $AC0.M, $AX0.H + 08f9 1408 lsl $ACC0, #8 + 08fa 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M + 08fb 3644 andr'ln $AC0.M, $AX1.H : $AX0.L, @$AR0 + 08fc 140c lsl $ACC0, #12 + 08fd 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M +} +08fe 3400 andr $AC0.M, $AX0.H +08ff 1408 lsl $ACC0, #8 +0900 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M +0901 3600 andr $AC0.M, $AX1.H +0902 140c lsl $ACC0, #12 +0903 1b5e srri @$AR2, $AC0.M +0904 8f00 set40 +0905 1f7f mrr $AX1.H, $AC1.M +0906 203e lrs $AX0.L, @0x003e +0907 273f lrs $AC1.M, @0x003f +0908 193a lrri $AX0.H, @$AR1 +0909 1939 lrri $AX1.L, @$AR1 +090a 0080 0370 lri $AR0, #0x0370 +090c 1c80 mrr $IX0, $AR0 +090d a000 mulx $AX0.L, $AX1.L +090e ea70 maddc'l $AC1.M, $AX1.L : $AC0.M, @$AR0 +090f 3a93 asrnrx'mv $ACC0, $AX1.H : $AX0.L, $AC1.M +0910 a478 mulxac'l $AX0.L, $AX1.L, $ACC0 : $AC1.M, @$AR0 +0911 1485 asl $ACC0, #5 +0912 e833 maddc's $AC0.M, $AX1.L : @$AR3, $AC0.M +0913 3b92 asrnrx'mv $ACC1, $AX1.H : $AX0.L, $AC0.M +0914 a570 mulxac'l $AX0.L, $AX1.L, $ACC1 : $AC0.M, @$AR0 +0915 1585 asl $ACC1, #5 +0916 ea3b maddc's $AC1.M, $AX1.L : @$AR3, $AC1.M +0917 1106 0920 bloopi #0x06, 0x0920 +{ + 0919 3a93 asrnrx'mv $ACC0, $AX1.H : $AX0.L, $AC1.M + 091a a478 mulxac'l $AX0.L, $AX1.L, $ACC0 : $AC1.M, @$AR0 + 091b 1485 asl $ACC0, #5 + 091c e833 maddc's $AC0.M, $AX1.L : @$AR3, $AC0.M + 091d 3b92 asrnrx'mv $ACC1, $AX1.H : $AX0.L, $AC0.M + 091e a570 mulxac'l $AX0.L, $AX1.L, $ACC1 : $AC0.M, @$AR0 + 091f 1585 asl $ACC1, #5 + 0920 ea3b maddc's $AC1.M, $AX1.L : @$AR3, $AC1.M +} +0921 3a93 asrnrx'mv $ACC0, $AX1.H : $AX0.L, $AC1.M +0922 a478 mulxac'l $AX0.L, $AX1.L, $ACC0 : $AC1.M, @$AR0 +0923 1485 asl $ACC0, #5 +0924 e833 maddc's $AC0.M, $AX1.L : @$AR3, $AC0.M +0925 3b92 asrnrx'mv $ACC1, $AX1.H : $AX0.L, $AC0.M +0926 a500 mulxac $AX0.L, $AX1.L, $ACC1 +0927 1585 asl $ACC1, #5 +0928 1b7f srri @$AR3, $AC1.M +0929 2e3e srs @0x003e, $AC0.M +092a 2f3f srs @0x003f, $AC1.M +092b 8e00 set16 +092c 8900 clr $ACC1 +092d 00df 0360 lr $AC1.M, @0x0360 +092f 02df ret +} + +{ +0930 0083 0520 lri $AR3, #0x0520 +0932 00de 041b lr $AC0.M, @0x041b +0934 1050 loopi #0x50 + 0935 1b7e srri @$AR3, $AC0.M +0936 029f 04e7 jmp 0x04e7 +} + +0938 0000 nop +0939 0000 nop +093a 0000 nop +093b 0000 nop +093c 0000 nop +093d 0000 nop +093e 0000 nop +093f 0000 nop diff -Nru dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_IPL_CB22D5C7.txt dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_IPL_CB22D5C7.txt --- dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_IPL_CB22D5C7.txt 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_IPL_CB22D5C7.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,1985 +0,0 @@ -0000 029f 0010 jmp 0x0010 -0002 0000 nop -0003 0000 nop -0004 02ff rti -0005 0000 nop -0006 02ff rti -0007 0000 nop -0008 02ff rti -0009 0000 nop -000a 02ff rti -000b 0000 nop -000c 02ff rti -000d 0000 nop -000e 02ff rti -000f 0000 nop - -// Entry -void 0010_Entry() -{ -0010 1302 sbset #0x02 -0011 1303 sbset #0x03 -0012 1204 sbclr #0x04 -0013 1305 sbset #0x05 -0014 1306 sbset #0x06 -0015 8e00 set16 -0016 8c00 clr15 -0017 8b00 m0 -0018 009e ffff lri $AC0.M, #0xffff -001a 1d1e mrr $WR0, $AC0.M -001b 1d3e mrr $WR1, $AC0.M -001c 1d5e mrr $WR2, $AC0.M -001d 1d7e mrr $WR3, $AC0.M -001e 0092 00ff lri $CR, #0x00ff -0020 8100 clr $ACC0 -0021 009f 1000 lri $AC1.M, #0x1000 -0023 0080 0000 lri $AR0, #0x0000 -0025 005f loop $AC1.M - 0026 1b1e srri @$AR0, $AC0.M // clear dram -0027 26ff lrs $AC0.M, @CMBL -0028 16fc 8888 si @DMBH, #0x8888 -002a 16fd 1111 si @DMBL, #0x1111 // SENDMAIL 0x88881111 -002c 26fc lrs $AC0.M, @DMBH -002d 02a0 8000 andf $AC0.M, #0x8000 -002f 029c 002c jlnz 0x002c -} - -void 0031_MainLoop() -{ -0031 8100 clr $ACC0 -0032 8900 clr $ACC1 -0033 26fe lrs $AC0.M, @CMBH -0034 02c0 8000 andcf $AC0.M, #0x8000 -0036 029c 0031 jlnz 0x0031 // wait for mail -0038 27ff lrs $AC1.M, @CMBL -0039 00ff 0345 sr @0x0345, $AC1.M -003b 1ffe mrr $AC1.M, $AC0.M -003c 0340 00ff andi $AC1.M, #0x00ff -003e 00ff 0344 sr @0x0344, $AC1.M -0040 1479 lsr $ACC0, #-7 -0041 0240 007e andi $AC0.M, #0x007e -0043 0200 0062 addi $AC0.M, #0x0062 -0045 00fe 0343 sr @0x0343, $AC0.M -0047 1c1e mrr $AR0, $AC0.M -0048 170f jmpr $AR0 // jump on CMD? -0049 009e 8000 lri $AC0.M, #0x8000 -004b 00dc 0343 lr $AC0.L, @0x0343 -004d 02bf 005a call 005a_SendMail(AC0.M,AC0.L) // sendmail 0x8000???? -004f 029f 0031 jmp 0x0031 -} - -void 0051_WaitForMailAndStoreIt(DEST $AR0) -{ -0051 26fe lrs $AC0.M, @CMBH -0052 02c0 8000 andcf $AC0.M, #0x8000 -0054 029c 0051 jlnz 0x0051 -0056 24ff lrs $AC0.L, @CMBL -0057 1b1e srri @$AR0, $AC0.M -0058 1b1c srri @$AR0, $AC0.L -0059 02df ret -} - -void 005a_SendMail(AC0.M,AC0.L) -{ -005a 2efc srs @DMBH, $AC0.M -005b 2cfd srs @DMBL, $AC0.L -005c 26fc lrs $AC0.M, @DMBH -005d 02a0 8000 andf $AC0.M, #0x8000 -005f 029c 005c jlnz 0x005c -0061 02df ret -} - -//CMDs -0062 029f 0049 jmp 0x0049 // CMD_0 -0064 029f 02bd jmp 0x02bd // CMD_1 -0066 029f 0470 jmp 0x0470 // CMD_2 -0068 029f 0031 jmp 0x0031 // CMD_3 -006a 029f 00df jmp 0x00df // CMD_4 -006c 029f 00f1 jmp 0x00f1 // CMD_5 -006e 029f 05bb jmp 0x05bb // CMD_6 -0070 029f 056f jmp 0x056f // CMD_7 -0072 029f 05d7 jmp 0x05d7 // CMD_8 -0074 029f 059f jmp 0x059f // CMD_9 -0076 029f 0741 jmp 0x0741 // CMD_A -0078 029f 0618 jmp 0x0618 // CMD_B - jump to IROM area (0x8644) -007a 029f 0203 jmp 0x0203 // CMD_C - -{ -007c 193e lrri $AC0.M, @$AR1 -007d 193c lrri $AC0.L, @$AR1 -007e 2fcd srs @DSPA, $AC1.M -007f 0f00 lris $AC1.M, #0x00 -0080 2fc9 srs @DSCR, $AC1.M // DMEM->CPU -0081 2ece srs @DSMAH, $AC0.M -0082 2ccf srs @DSMAL, $AC0.L -0083 1fe0 mrr $AC1.M, $AR0 -0084 1501 lsl $ACC1, #1 -0085 2fcb srs @DSBL, $AC1.M -0086 02bf 008f call 0x008f -0088 02df ret -} - -{ -0089 193e lrri $AC0.M, @$AR1 -008a 193c lrri $AC0.L, @$AR1 -008b 2fcd srs @DSPA, $AC1.M -008c 0f01 lris $AC1.M, #0x01 -008d 029f 0080 jmp 0x0080 -} - -{ -008f 26c9 lrs $AC0.M, @DSCR -0090 02a0 0004 andf $AC0.M, #0x0004 -0092 029c 008f jlnz 0x008f -0094 02df ret -} - -{ -0095 193e lrri $AC0.M, @$AR1 -0096 193c lrri $AC0.L, @$AR1 -0097 00ff ffcd sr @DSPA, $AC1.M -0099 0f00 lris $AC1.M, #0x00 -009a 00ff ffc9 sr @DSCR, $AC1.M -009c 00fe ffce sr @DSMAH, $AC0.M -009e 00fc ffcf sr @DSMAL, $AC0.L -00a0 1fe0 mrr $AC1.M, $AR0 -00a1 1501 lsl $ACC1, #1 -00a2 00ff ffcb sr @DSBL, $AC1.M -00a4 02df ret -} - -void 00a5_WaitForDMAend() -{ -00a5 00de ffc9 lr $AC0.M, @DSCR -00a7 02a0 0004 andf $AC0.M, #0x0004 -00a9 029c 00a5 jlnz 0x00a5 -00ab 02df ret -} - -void 00ac_AccZeldaTypeRead() -{ -00ac 193e lrri $AC0.M, @$AR1 -00ad 193c lrri $AC0.L, @$AR1 -00ae 0240 7fff andi $AC0.M, #0x7fff -00b0 02bf 00ba call 00ba_AccSetup() -00b2 007a 00b8 bloop $AX0.H, 0x00b8 -00b4 26d3 lrs $AC0.M, @UnkZelda -00b5 1b3e srri @$AR1, $AC0.M -00b6 0000 nop -00b7 0000 nop -00b8 0000 nop -00b9 02df ret -} - -void 00ba_AccSetup() -{ -00ba 1c3f mrr $AR1, $AC1.M -00bb 009f 0005 lri $AC1.M, #0x0005 -00bd 2fd1 srs @SampleFormat, $AC1.M // reads will be u8 -00be 1f5e mrr $AX0.H, $AC0.M -00bf 1f1c mrr $AX0.L, $AC0.L -00c0 2ed4 srs @ACSAH, $AC0.M -00c1 2cd5 srs @ACSAL, $AC0.L -00c2 8900 clr $ACC1 -00c3 1fa0 mrr $AC1.L, $AR0 -00c4 4c00 add $ACC0, $ACC1 -00c5 0200 0030 addi $AC0.M, #0x0030 -00c7 2ed6 srs @ACEAH, $AC0.M -00c8 2cd7 srs @ACEAL, $AC0.L -00c9 1fda mrr $AC0.M, $AX0.H -00ca 1f98 mrr $AC0.L, $AX0.L -00cb 147f lsr $ACC0, #-1 -00cc 2ed8 srs @ACCAH, $AC0.M -00cd 2cd9 srs @ACCAL, $AC0.L -00ce 1f40 mrr $AX0.H, $AR0 -00cf 02df ret -} - -void 00d0_AccZeldaTypeWrite() -{ -00d0 193e lrri $AC0.M, @$AR1 -00d1 193c lrri $AC0.L, @$AR1 -00d2 0260 8000 ori $AC0.M, #0x8000 -00d4 02bf 00ba call 00ba_AccSetup() -00d6 007a 00dd bloop $AX0.H, 0x00dd -{ - 00d8 193e lrri $AC0.M, @$AR1 - 00d9 2ed3 srs @UnkZelda, $AC0.M - 00da 0000 nop - 00db 0000 nop - 00dc 0000 nop - 00dd 0000 nop -} -00de 02df ret -} - -{ -00df 0080 0346 lri $AR0, #0x0346 -00e1 02bf 0051 call 0x0051 -00e3 02bf 0051 call 0x0051 -00e5 0081 0346 lri $AR1, #0x0346 -00e7 00df 0349 lr $AC1.M, @0x0349 -00e9 0340 ffff andi $AC1.M, #0xffff -00eb 00c0 0345 lr $AR0, @0x0345 -00ed 02bf 007c call 0x007c -00ef 029f 0049 jmp 0x0049 -} - -{ -00f1 0080 0346 lri $AR0, #0x0346 -00f3 02bf 0051 call 0x0051 -00f5 02bf 0051 call 0x0051 -00f7 0081 0346 lri $AR1, #0x0346 -00f9 00df 0349 lr $AC1.M, @0x0349 -00fb 0340 ffff andi $AC1.M, #0xffff -00fd 00c0 0345 lr $AR0, @0x0345 -00ff 02bf 0089 call 0x0089 -0101 029f 0049 jmp 0x0049 -} - -{ -0103 0092 00ff lri $CR, #0x00ff -0105 2fd1 srs @SampleFormat, $AC1.M -0106 0340 0003 andi $AC1.M, #0x0003 -0108 1f7f mrr $AX1.H, $AC1.M -0109 1f5e mrr $AX0.H, $AC0.M -010a 1f1c mrr $AX0.L, $AC0.L -010b 0200 0010 addi $AC0.M, #0x0010 -010d 2ed4 srs @ACSAH, $AC0.M -010e 2cd5 srs @ACSAL, $AC0.L -010f 8900 clr $ACC1 -0110 1fa0 mrr $AC1.L, $AR0 -0111 4c00 add $ACC0, $ACC1 -0112 0200 0030 addi $AC0.M, #0x0030 -0114 2ed6 srs @ACEAH, $AC0.M -0115 2cd7 srs @ACEAL, $AC0.L -0116 1fda mrr $AC0.M, $AX0.H -0117 1f98 mrr $AC0.L, $AX0.L -0118 1ffb mrr $AC1.M, $AX1.H -0119 7900 decm $AC1.M -011a 02ca lsrn -011b 2ed8 srs @ACCAH, $AC0.M -011c 2cd9 srs @ACCAL, $AC0.L -011d 02df ret -} - -//DSPLLE errors here!!! readw/writes from 0x3??? -{ -011e 1c23 mrr $AR1, $AR3 -011f 197e lrri $AC0.M, @$AR3 -0120 191b lrri $AX1.H, @$AR0 -0121 d858 mulc'l $AC1.M, $AX1.H : $AX1.H, @$AR0 -0122 1128 0128 bloopi #0x28, 0x0128 -0124 dcd3 mulcac'ld $AC1.M, $AX1.H, $ACC0 : $AX0.L, $AX1.H, @$AR3 -0125 6231 movr's $ACC0, $AX1.L : @$AR1, $AC0.M -0126 dcd3 mulcac'ld $AC1.M, $AX1.H, $ACC0 : $AX0.L, $AX1.H, @$AR3 -0127 6231 movr's $ACC0, $AX1.L : @$AR1, $AC0.M -0128 4900 addax $ACC1, $AX0 -0129 02df ret -} - -{ -012a 8f00 set40 -012b 1c03 mrr $AR0, $AR3 -012c 00db 038e lr $AX1.H, @0x038e -012e 009a 0004 lri $AX0.H, #0x0004 -0130 1978 lrri $AX0.L, @$AR3 -0131 a843 mulx'l $AX0.L, $AX1.H : $AX0.L, @$AR3 -0132 ae00 mulxmv $AX0.L, $AX1.H, $ACC0 -0133 1128 0138 bloopi #0x28, 0x0138 -0135 38c3 asrnrx'l $ACC0, $AX0.H : $AX0.L, @$AR3 -0136 ae30 mulxmv's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC0.M -0137 38c3 asrnrx'l $ACC0, $AX0.H : $AX0.L, @$AR3 -0138 ae30 mulxmv's $AX0.L, $AX1.H, $ACC0 : @$AR0, $AC0.M -0139 8e00 set16 -013a 02df ret -} - -{ -013b 00f9 0361 sr @0x0361, $AX1.L -013d 1fc0 mrr $AC0.M, $AR0 -013e 0200 fffc addi $AC0.M, #0xfffc -0140 1c1e mrr $AR0, $AC0.M -0141 1c5e mrr $AR2, $AC0.M -0142 0083 0424 lri $AR3, #0x0424 -0144 197e lrri $AC0.M, @$AR3 -0145 197f lrri $AC1.M, @$AR3 -0146 80a2 nx'sl : $AC0.M, $AX0.H -0147 64a3 movr'sl $ACC0, $AX0.H : $AC1.M, $AX0.H -0148 6530 movr's $ACC1, $AX0.H : @$AR0, $AC0.M -0149 1b1f srri @$AR0, $AC1.M -014a 1c02 mrr $AR0, $AR2 -014b 8100 clr $ACC0 -014c 00de 0402 lr $AC0.M, @0x0402 -014e 00fe 0362 sr @0x0362, $AC0.M -0150 1474 lsr $ACC0, #-12 -0151 1f7e mrr $AX1.H, $AC0.M -0152 1f3c mrr $AX1.L, $AC0.L -0153 8900 clr $ACC1 -0154 00dd 0418 lr $AC1.L, @0x0418 -0156 1504 lsl $ACC1, #4 -0157 0604 cmpis $AC0.M, #0x04 -0158 0290 01b0 jge 0x01b0 -015a 1fdd mrr $AC0.M, $AC1.L -015b 0082 0c00 lri $AR2, #0x0c00 -015d 1050 loopi #0x50 -015e 4b2a addax's $ACC1, $AX1 : @$AR2, $AC1.L -015f 1fbe mrr $AC1.L, $AC0.M -0160 00fe 0360 sr @0x0360, $AC0.M -0162 8900 clr $ACC1 -0163 1fbe mrr $AC1.L, $AC0.M -0164 009a fff8 lri $AX0.H, #0xfff8 -0166 009b 00fc lri $AX1.H, #0x00fc -0168 00d8 0361 lr $AX0.L, @0x0361 -016a 0082 0c00 lri $AR2, #0x0c00 -016c 0083 0c00 lri $AR3, #0x0c00 -016e 195e lrri $AC0.M, @$AR2 -016f 3480 lsrnrx $ACC0, $AX0.H -0170 1128 0175 bloopi #0x28, 0x0175 -0172 367a andr'l $AC0.M, $AX1.H : $AC1.M, @$AR2 -0173 35b3 lsrnrx's $ACC1, $AX0.H : @$AR3, $AC0.M -0174 3772 andr'l $AC1.M, $AX1.H : $AC0.M, @$AR2 -0175 34bb lsrnrx's $ACC0, $AX0.H : @$AR3, $AC1.M -0176 8a00 m2 -0177 0082 0c00 lri $AR2, #0x0c00 -0179 00dd 0418 lr $AC1.L, @0x0418 -017b 1504 lsl $ACC1, #4 -017c 1fe0 mrr $AC1.M, $AR0 -017d 8100 clr $ACC0 -017e 00de 0362 lr $AC0.M, @0x0362 -0180 1474 lsr $ACC0, #-12 -0181 1f7e mrr $AX1.H, $AC0.M -0182 1f3c mrr $AX1.L, $AC0.L -0183 8f00 set40 -0184 1943 lrri $AR3, @$AR2 -0185 4bc3 addax'ld $ACC1, $AX1 : $AX0.L, $AX1.L, @$AR3 -0186 90c3 mul'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 -0187 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 -0188 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 -0189 f200 madd $AX0.L, $AX0.H -018a fe00 movpz $ACC0 -018b 1c1f mrr $AR0, $AC1.M -018c 1943 lrri $AR3, @$AR2 -018d 4bc3 addax'ld $ACC1, $AX1 : $AX0.L, $AX1.L, @$AR3 -018e 90c3 mul'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 -018f 114e 0197 bloopi #0x4e, 0x0197 -0191 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 -0192 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 -0193 f231 madd's $AX0.L, $AX0.H : @$AR1, $AC0.M -0194 1c1f mrr $AR0, $AC1.M -0195 1943 lrri $AR3, @$AR2 -0196 4bc3 addax'ld $ACC1, $AX1 : $AX0.L, $AX1.L, @$AR3 -0197 92c3 mulmvz'ld $AX0.L, $AX0.H, $ACC0 : $AX0.L, $AX1.L, @$AR3 -0198 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 -0199 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 -019a f231 madd's $AX0.L, $AX0.H : @$AR1, $AC0.M -019b fe00 movpz $ACC0 -019c 1b3e srri @$AR1, $AC0.M -019d 8b00 m0 -019e 8e00 set16 -019f 00fe 041b sr @0x041b, $AC0.M -01a1 1c1f mrr $AR0, $AC1.M -01a2 150c lsl $ACC1, #12 -01a3 0340 0fff andi $AC1.M, #0x0fff -01a5 00ff 0418 sr @0x0418, $AC1.M -01a7 0083 0424 lri $AR3, #0x0424 -01a9 191e lrri $AC0.M, @$AR0 -01aa 191f lrri $AC1.M, @$AR0 -01ab 80a0 nx'ls : $AX0.H, $AC0.M -01ac 64a1 movr'ls $ACC0, $AX0.H : $AX0.H, $AC1.M -01ad 6533 movr's $ACC1, $AX0.H : @$AR3, $AC0.M -01ae 1b7f srri @$AR3, $AC1.M -01af 02df ret -} - -{ -01b0 1fe0 mrr $AC1.M, $AR0 -01b1 1c1f mrr $AR0, $AC1.M -01b2 1128 01b9 bloopi #0x28, 0x01b9 -01b4 4b70 addax'l $ACC1, $AX1 : $AC0.M, @$AR0 -01b5 1b3e srri @$AR1, $AC0.M -01b6 1c1f mrr $AR0, $AC1.M -01b7 4b70 addax'l $ACC1, $AX1 : $AC0.M, @$AR0 -01b8 1b3e srri @$AR1, $AC0.M -01b9 1c1f mrr $AR0, $AC1.M -01ba 029f 019f jmp 0x019f -} - -{ -01bc 8a00 m2 -01bd 0088 0007 lri $WR0, #0x0007 -01bf 1150 01cc bloopi #0x50, 0x01cc -{ - 01c1 1c61 mrr $AR3, $AR1 - 01c2 84c3 clrp'ld : $AX0.L, $AX1.L, @$AR3 - 01c3 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 - 01c4 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 - 01c5 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 - 01c6 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 - 01c7 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 - 01c8 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 - 01c9 f2c3 madd'ld $AX0.L, $AX0.H : $AX0.L, $AX1.L, @$AR3 - 01ca f200 madd $AX0.L, $AX0.H - 01cb fe00 movpz $ACC0 - 01cc 1b3e srri @$AR1, $AC0.M -} -01cd 0088 ffff lri $WR0, #0xffff -01cf 8b00 m0 -01d0 02df ret -} - -{ -01d1 0088 0003 lri $WR0, #0x0003 -01d3 0085 0000 lri $IX1, #0x0000 -01d5 0087 0000 lri $IX3, #0x0000 -01d7 1fc2 mrr $AC0.M, $AR2 -01d8 195b lrri $AX1.H, @$AR2 -01d9 1959 lrri $AX1.L, @$AR2 -01da 195f lrri $AC1.M, @$AR2 -01db 195a lrri $AX0.H, @$AR2 -01dc 1c5e mrr $AR2, $AC0.M -01dd 1fda mrr $AC0.M, $AX0.H -01de 1c61 mrr $AR3, $AR1 -01df 8a00 m2 -01e0 8f00 set40 -01e1 191a lrri $AX0.H, @$AR0 -01e2 b850 mulx'l $AX0.H, $AX1.H : $AX0.H, @$AR0 -01e3 e250 maddx'l $AX0.H, $AX1.L : $AX0.H, @$AR0 -01e4 ea50 maddc'l $AC1.M, $AX1.L : $AX0.H, @$AR0 -01e5 e8e8 maddc'ldm $AC0.M, $AX1.L : $AX0.H, $AX1.L, @$AR0 -01e6 b650 mulxmv'l $AX0.H, $AX1.L, $ACC0 : $AX0.H, @$AR0 -01e7 1127 01f2 bloopi #0x27, 0x01f2 -{ - 01e9 e3a8 maddx'lsm $AX0.H, $AX1.H : $AX0.H, $AC0.M - 01ea 197e lrri $AC0.M, @$AR3 - 01eb e850 maddc'l $AC0.M, $AX1.L : $AX0.H, @$AR0 - 01ec eaf8 maddc'ldm $AC1.M, $AX1.L : $AX0.H, $AX1.H, @$AR0 - 01ed bf50 mulxmv'l $AX0.H, $AX1.H, $ACC1 : $AX0.H, @$AR0 - 01ee e2a9 maddx'lsm $AX0.H, $AX1.L : $AX0.H, $AC1.M - 01ef 197f lrri $AC1.M, @$AR3 - 01f0 ea50 maddc'l $AC1.M, $AX1.L : $AX0.H, @$AR0 - 01f1 e8e8 maddc'ldm $AC0.M, $AX1.L : $AX0.H, $AX1.L, @$AR0 - 01f2 b650 mulxmv'l $AX0.H, $AX1.L, $ACC0 : $AX0.H, @$AR0 -} -01f3 e3a8 maddx'lsm $AX0.H, $AX1.H : $AX0.H, $AC0.M -01f4 197e lrri $AC0.M, @$AR3 -01f5 e850 maddc'l $AC0.M, $AX1.L : $AX0.H, @$AR0 -01f6 eaf8 maddc'ldm $AC1.M, $AX1.L : $AX0.H, $AX1.H, @$AR0 -01f7 bf00 mulxmv $AX0.H, $AX1.H, $ACC1 -01f8 1bff srrn @$AR3, $AC1.M -01f9 197f lrri $AC1.M, @$AR3 -01fa 8e00 set16 -01fb 8b00 m0 -01fc 0088 ffff lri $WR0, #0xffff -01fe 1b5b srri @$AR2, $AX1.H -01ff 1b59 srri @$AR2, $AX1.L -0200 1b5f srri @$AR2, $AC1.M -0201 1b5e srri @$AR2, $AC0.M -0202 02df ret -} - -{ -0203 0080 0346 lri $AR0, #0x0346 -0205 02bf 0051 call 0x0051 -0207 02bf 0051 call 0x0051 -0209 0081 0346 lri $AR1, #0x0346 -020b 009f 0580 lri $AC1.M, #0x0580 -020d 0080 0080 lri $AR0, #0x0080 -020f 02bf 007c call 0x007c -0211 0081 0348 lri $AR1, #0x0348 -0213 009f 0c00 lri $AC1.M, #0x0c00 -0215 0080 0080 lri $AR0, #0x0080 -0217 02bf 007c call 0x007c -0219 0080 0c00 lri $AR0, #0x0c00 -021b 0081 0580 lri $AR1, #0x0580 -021d 02bf 01d1 call 0x01d1 -021f 0081 0346 lri $AR1, #0x0346 -0221 009f 0580 lri $AC1.M, #0x0580 -0223 0080 0080 lri $AR0, #0x0080 -0225 02bf 0089 call 0x0089 -0227 0081 0348 lri $AR1, #0x0348 -0229 009f 0c00 lri $AC1.M, #0x0c00 -022b 0080 0080 lri $AR0, #0x0080 -022d 02bf 0089 call 0x0089 -022f 029f 0049 jmp 0x0049 -} - -void 0231_FormatAudioSynths(format AC0.M) -{ -0231 8100 clr $ACC0 -0232 1f5e mrr $AX0.H, $AC0.M -0233 00d8 0402 lr $AX0.L, @0x0402 -0235 00dc 0418 lr $AC0.L, @0x0418 -0237 0080 0520 lri $AR0, #0x0520 -0239 00df 0440 lr $AC1.M, @0x0440 -023b 1501 lsl $ACC1, #1 -023c 0340 007e andi $AC1.M, #0x007e -023e 0300 0246 addi $AC1.M, #0x0246 -0240 1c5f mrr $AR2, $AC1.M -0241 175f callr $AR2 // call 0x0246 -0242 00fc 0418 sr @0x0418, $AC0.L -0244 029f 04e7 jmp 0x04e7 // dummy -0246 029f 0257 jmp 0x0257 // 0x0 - Synth0 -0248 029f 028f jmp 0x028f // 0x1 - Synth1 -024a 029f 0277 jmp 0x0277 // 0x2 - Synth2 -024c 029f 0267 jmp 0x0267 // 0x3 - Synth3 -024e 029f 0292 jmp 0x0292 // 0x4 - Synth4 -0250 029f 0256 jmp 0x0256 // 0x5 - dummy -0252 029f 02b1 jmp 0x02b1 // 0x6 - Synth6 -0254 029f 02ae jmp 0x02ae // 0x7 - Synth7 -0256 02df ret -} - -void 0257_Synth0() -{ -0257 1401 lsl $ACC0, #1 -0258 009b c000 lri $AX1.H, #0xc000 -025a 0099 4000 lri $AX1.L, #0x4000 -025c 1150 0264 bloopi #0x50, 0x0264 -{ - 025e 02c0 0001 andcf $AC0.M, #0x0001 - 0260 027c iflnz - 0261 1b1b srri @$AR0, $AX1.H - 0262 027d iflz - 0263 1b19 srri @$AR0, $AX1.L - 0264 4800 addax $ACC0, $AX0 -} -0265 147f lsr $ACC0, #-1 -0266 02df ret -} - -void 0267_Synth3() -{ -0267 1401 lsl $ACC0, #1 -0268 009b c000 lri $AX1.H, #0xc000 -026a 0099 4000 lri $AX1.L, #0x4000 -026c 1150 0274 bloopi #0x50, 0x0274 -{ - 026e 02c0 0003 andcf $AC0.M, #0x0003 - 0270 027c iflnz - 0271 1b1b srri @$AR0, $AX1.H - 0272 027d iflz - 0273 1b19 srri @$AR0, $AX1.L - 0274 4800 addax $ACC0, $AX0 -} -0275 147f lsr $ACC0, #-1 -0276 02df ret -} - -void 0277_Synth2() -{ -0277 1401 lsl $ACC0, #1 -0278 0081 0ca0 lri $AR1, #0x0ca0 -027a 009b c000 lri $AX1.H, #0xc000 -027c 0099 4000 lri $AX1.L, #0x4000 -027e 8900 clr $ACC1 -027f 0082 0000 lri $AR2, #0x0000 -0281 1150 028c bloopi #0x50, 0x028c -{ - 0283 02c0 0001 andcf $AC0.M, #0x0001 - 0285 027c iflnz - 0286 1b1b srri @$AR0, $AX1.H - 0287 027d iflz - 0288 1b19 srri @$AR0, $AX1.L - 0289 183d lrr $AC1.L, @$AR1 - 028a 4900 addax $ACC1, $AX0 - 028b 1fe2 mrr $AC1.M, $AR2 - 028c 4c39 add's $ACC0, $ACC1 : @$AR1, $AC1.M -} -028d 147f lsr $ACC0, #-1 -028e 02df ret -} - -void 028f_Synth1() -{ -028f 1050 loopi #0x50 - 0290 4820 addax's $ACC0, $AX0 : @$AR0, $AC0.L -0291 02df ret -} - -void 0292_Synth4() -{ -0292 0082 0140 lri $AR2, #0x0140 -0294 008a 003f lri $WR2, #0x003f -0296 0086 0000 lri $IX2, #0x0000 -0298 1406 lsl $ACC0, #6 -0299 8900 clr $ACC1 -029a 1fb8 mrr $AC1.L, $AX0.L -029b 1506 lsl $ACC1, #6 -029c 009b 003f lri $AX1.H, #0x003f -029e 009a 0000 lri $AX0.H, #0x0000 -02a0 3600 andr $AC0.M, $AX1.H -02a1 1cde mrr $IX2, $AC0.M -02a2 001a addarn $AR2, $IX2 -02a3 3400 andr $AC0.M, $AX0.H -02a4 1150 02aa bloopi #0x50, 0x02aa -{ - 02a6 4c00 add $ACC0, $ACC1 - 02a7 364a andr'l $AC0.M, $AX1.H : $AX1.L, @$AR2 - 02a8 1cde mrr $IX2, $AC0.M - 02a9 340e andr'nr $AC0.M, $AX0.H : $AR2 - 02aa 1b19 srri @$AR0, $AX1.L -} -02ab 1fc2 mrr $AC0.M, $AR2 -02ac 147a lsr $ACC0, #-6 -02ad 02df ret -} - -void 02b1_Synth7() -{ -02ae 1050 loopi #0x50 - 02af 1b18 srri @$AR0, $AX0.L -02b0 02df ret -} - -void 02b1_Synth6() -{ -02b1 0083 0000 lri $AR3, #0x0000 -02b3 140f lsl $ACC0, #15 -02b4 4853 addax'l $ACC0, $AX0 : $AX0.H, @$AR3 -02b5 1114 02ba bloopi #0x14, 0x02ba -{ - 02b7 48a2 addax'sl $ACC0, $AX0 : $AC0.M, $AX0.H - 02b8 48a2 addax'sl $ACC0, $AX0 : $AC0.M, $AX0.H - 02b9 48a2 addax'sl $ACC0, $AX0 : $AC0.M, $AX0.H - 02ba 48a2 addax'sl $ACC0, $AX0 : $AC0.M, $AX0.H -} -02bb 146f lsr $ACC0, #-17 -02bc 02df ret -} - -{ -02bd 0080 0380 lri $AR0, #0x0380 -02bf 02bf 0051 call 0x0051 -02c1 02bf 0051 call 0x0051 -02c3 02bf 0051 call 0x0051 -02c5 02bf 0051 call 0x0051 -02c7 0081 0382 lri $AR1, #0x0382 -02c9 009f 0000 lri $AC1.M, #0x0000 -02cb 0080 0200 lri $AR0, #0x0200 -02cd 02bf 007c call 0x007c -02cf 0081 0384 lri $AR1, #0x0384 -02d1 009f 0300 lri $AC1.M, #0x0300 -02d3 0080 0020 lri $AR0, #0x0020 -02d5 02bf 007c call 0x007c -02d7 02bf 0351 call 0x0351 -02d9 00de 0345 lr $AC0.M, @0x0345 -02db 00fe 0342 sr @0x0342, $AC0.M -02dd 029f 0049 jmp 0x0049 -} - -{ -02df 00de 0344 lr $AC0.M, @0x0344 -02e1 1404 lsl $ACC0, #4 -02e2 0200 03a8 addi $AC0.M, #0x03a8 -02e4 1c1e mrr $AR0, $AC0.M -02e5 02bf 0051 call 0x0051 -02e7 02bf 0051 call 0x0051 -02e9 02bf 0051 call 0x0051 -02eb 00de 0345 lr $AC0.M, @0x0345 -02ed 1b1e srri @$AR0, $AC0.M -02ee 00de 0344 lr $AC0.M, @0x0344 -02f0 0200 03a4 addi $AC0.M, #0x03a4 -02f2 1c1e mrr $AR0, $AC0.M -02f3 8100 clr $ACC0 -02f4 1b1e srri @$AR0, $AC0.M -02f5 02df ret -} - -{ -02f6 00de 0344 lr $AC0.M, @0x0344 -02f8 1404 lsl $ACC0, #4 -02f9 0200 03b0 addi $AC0.M, #0x03b0 -02fb 1c1e mrr $AR0, $AC0.M -02fc 02bf 0051 call 0x0051 -02fe 02bf 0051 call 0x0051 -0300 02bf 0051 call 0x0051 -0302 02bf 0051 call 0x0051 -0304 02df ret -} - -{ -0305 0081 034c lri $AR1, #0x034c -0307 009f 0400 lri $AC1.M, #0x0400 -0309 0080 0080 lri $AR0, #0x0080 -030b 02bf 007c call 0x007c -030d 02df ret -} - -{ -030e 0081 034c lri $AR1, #0x034c -0310 009f 0a00 lri $AC1.M, #0x0a00 -0312 0080 0004 lri $AR0, #0x0004 -0314 02bf 00a5 call 00a5_WaitForDMAend() -0316 02bf 007c call 0x007c -0318 0081 034c lri $AR1, #0x034c -031a 009f 0400 lri $AC1.M, #0x0400 -031c 0080 0080 lri $AR0, #0x0080 -031e 02bf 0095 call 0x0095 -0320 02df ret -} - -{ -0321 0081 034c lri $AR1, #0x034c -0323 009f 0400 lri $AC1.M, #0x0400 -0325 0080 0040 lri $AR0, #0x0040 -0327 0081 034c lri $AR1, #0x034c -0329 193e lrri $AC0.M, @$AR1 -032a 193c lrri $AC0.L, @$AR1 -032b 0098 0000 lri $AX0.L, #0x0000 -032d 7000 addaxl $ACC0, $AX0.L -032e 02bf 008b call 0x008b -0330 02df ret -} - -{ -0331 191e lrri $AC0.M, @$AR0 -0332 191a lrri $AX0.H, @$AR0 -0333 005f loop $AC1.M -0334 64a0 movr'ls $ACC0, $AX0.H : $AX0.H, $AC0.M -0335 1b7e srri @$AR3, $AC0.M -0336 1b7a srri @$AR3, $AX0.H -0337 02df ret -} - -{ -0338 191e lrri $AC0.M, @$AR0 -0339 191a lrri $AX0.H, @$AR0 -033a 007f 033f bloop $AC1.M, 0x033f -{ - 033c 32b2 not's $AC0.M : @$AR2, $AC0.M - 033d 65a0 movr'ls $ACC1, $AX0.H : $AX0.H, $AC0.M - 033e 33ba not's $AC1.M : @$AR2, $AC1.M - 033f 64a1 movr'ls $ACC0, $AX0.H : $AX0.H, $AC1.M -} -0340 0000 nop -0341 02df ret -} - -{ -0342 8a00 m2 -0343 157f lsr $ACC1, #-1 -0344 1c20 mrr $AR1, $AR0 -0345 1c03 mrr $AR0, $AR3 -0346 193a lrri $AX0.H, @$AR1 -0347 9051 mul'l $AX0.L, $AX0.H : $AX0.H, @$AR1 -0348 925b mulmvz'l $AX0.L, $AX0.H, $ACC0 : $AX1.H, @$AR3 -0349 007f 034e bloop $AC1.M, 0x034e -{ - 034b 4651 addr'l $ACC0, $AX1.H : $AX0.H, @$AR1 - 034c 92b2 mulmvz'sl $AX0.L, $AX0.H, $ACC0 : $AC0.M, $AX1.H - 034d 4651 addr'l $ACC0, $AX1.H : $AX0.H, @$AR1 - 034e 92b2 mulmvz'sl $AX0.L, $AX0.H, $ACC0 : $AC0.M, $AX1.H -} -034f 8b00 m0 -0350 02df ret -} - -{ -0351 0083 ffa0 lri $AR3, #0xffa0 -0353 0080 0300 lri $AR0, #0x0300 -0355 009f 000e lri $AC1.M, #0x000e -0357 1108 035c bloopi #0x08, 0x035c -{ - 0359 191e lrri $AC0.M, @$AR0 - 035a 1b7e srri @$AR3, $AC0.M - 035b 191e lrri $AC0.M, @$AR0 - 035c 1b7e srri @$AR3, $AC0.M -} -035d 02df ret -} - -{ -035e 0080 0f40 lri $AR0, #0x0f40 -0360 0082 0d00 lri $AR2, #0x0d00 -0362 0083 0d60 lri $AR3, #0x0d60 -0364 009f 0028 lri $AC1.M, #0x0028 -0366 02bf 0338 call 0x0338 -0368 8900 clr $ACC1 -0369 009e 0050 lri $AC0.M, #0x0050 -036b 0080 0ca0 lri $AR0, #0x0ca0 -036d 005e loop $AC0.M - 036e 1b1f srri @$AR0, $AC1.M -036f 0080 0f40 lri $AR0, #0x0f40 -0371 005e loop $AC0.M - 0372 1b1f srri @$AR0, $AC1.M -0373 0080 0fa0 lri $AR0, #0x0fa0 -0375 005e loop $AC0.M - 0376 1b1f srri @$AR0, $AC1.M -0377 02df ret -} - -{ -0378 0080 0dc0 lri $AR0, #0x0dc0 -037a 009e 0180 lri $AC0.M, #0x0180 -037c 8900 clr $ACC1 -037d 005e loop $AC0.M - 037e 1b1f srri @$AR0, $AC1.M -037f 02df ret -} - -{ -0380 00c0 03a0 lr $AR0, @0x03a0 -0382 191a lrri $AX0.H, @$AR0 -0383 00df 03a1 lr $AC1.M, @0x03a1 -0385 009b 00a0 lri $AX1.H, #0x00a0 -0387 0081 0393 lri $AR1, #0x0393 -0389 18bc lrrd $AC0.L, @$AR1 -038a b871 mulx'l $AX0.H, $AX1.H : $AC0.M, @$AR1 -038b bc00 mulxac $AX0.H, $AX1.H, $ACC0 -038c 0080 0050 lri $AR0, #0x0050 -038e 0508 addis $AC1.M, #0x08 -038f 02bf 007e call 0x007e -0391 00de 0390 lr $AC0.M, @0x0390 -0393 02a0 0001 andf $AC0.M, #0x0001 -0395 029d 039f jlz 0x039f -0397 0080 0398 lri $AR0, #0x0398 -0399 009e 0008 lri $AC0.M, #0x0008 -039b 00c1 03a1 lr $AR1, @0x03a1 -039d 02bf 01bc call 0x01bc -039f 009f 0050 lri $AC1.M, #0x0050 -03a1 00c0 03a1 lr $AR0, @0x03a1 -03a3 8100 clr $ACC0 -03a4 00de 0394 lr $AC0.M, @0x0394 -03a6 b100 tst $ACC0 -03a7 0295 03ae jz 0x03ae -03a9 1c7e mrr $AR3, $AC0.M -03aa 00d8 0395 lr $AX0.L, @0x0395 -03ac 02bf 0342 call 0x0342 -03ae 009f 0050 lri $AC1.M, #0x0050 -03b0 00c0 03a1 lr $AR0, @0x03a1 -03b2 8100 clr $ACC0 -03b3 00de 0396 lr $AC0.M, @0x0396 -03b5 b100 tst $ACC0 -03b6 0295 03bd jz 0x03bd -03b8 1c7e mrr $AR3, $AC0.M -03b9 00d8 0397 lr $AX0.L, @0x0397 -03bb 02bf 0342 call 0x0342 -03bd 00de 0390 lr $AC0.M, @0x0390 -03bf 02a0 0002 andf $AC0.M, #0x0002 -03c1 02dd retlz -03c2 0080 0398 lri $AR0, #0x0398 -03c4 009e 0008 lri $AC0.M, #0x0008 -03c6 00c1 03a1 lr $AR1, @0x03a1 -03c8 02bf 01bc call 0x01bc -03ca 02df ret -} - -{ -03cb 009f 0dc0 lri $AC1.M, #0x0dc0 -03cd 00ff 03a1 sr @0x03a1, $AC1.M -03cf 009f 03a8 lri $AC1.M, #0x03a8 -03d1 00ff 03a2 sr @0x03a2, $AC1.M -03d3 009f 03a4 lri $AC1.M, #0x03a4 -03d5 00ff 03a0 sr @0x03a0, $AC1.M -03d7 1104 0400 bloopi #0x04, 0x0400 -{ - 03d9 00c0 03a2 lr $AR0, @0x03a2 - 03db 0083 0390 lri $AR3, #0x0390 - 03dd 009f 000e lri $AC1.M, #0x000e - 03df 02bf 0331 call 0x0331 - 03e1 00da 0390 lr $AX0.H, @0x0390 - 03e3 8600 tstaxh $AX0.H - 03e4 0295 03f1 jz 0x03f1 - 03e6 00df 03a1 lr $AC1.M, @0x03a1 - 03e8 1c7f mrr $AR3, $AC1.M - 03e9 0550 addis $AC1.M, #0x50 - 03ea 1c1f mrr $AR0, $AC1.M - 03eb 009f 0006 lri $AC1.M, #0x0006 - 03ed 02bf 0331 call 0x0331 - 03ef 02bf 0380 call 0x0380 - 03f1 00de 03a2 lr $AC0.M, @0x03a2 - 03f3 0410 addis $AC0.M, #0x10 - 03f4 00fe 03a2 sr @0x03a2, $AC0.M - 03f6 00de 03a1 lr $AC0.M, @0x03a1 - 03f8 0460 addis $AC0.M, #0x60 - 03f9 00fe 03a1 sr @0x03a1, $AC0.M - 03fb 00de 03a0 lr $AC0.M, @0x03a0 - 03fd 7400 incm $AC0.M - 03fe 00fe 03a0 sr @0x03a0, $AC0.M - 0400 0000 nop -} -0401 02df ret -} - -{ -0402 00c0 03a0 lr $AR0, @0x03a0 -0404 181a lrr $AX0.H, @$AR0 -0405 8100 clr $ACC0 -0406 181e lrr $AC0.M, @$AR0 -0407 00db 0391 lr $AX1.H, @0x0391 -0409 7400 incm $AC0.M -040a d100 cmpar $ACC1, $AX0.H -040b 0270 ifge -040c 8100 clr $ACC0 -040d 1b1e srri @$AR0, $AC0.M -040e 00df 03a1 lr $AC1.M, @0x03a1 -0410 009b 00a0 lri $AX1.H, #0x00a0 -0412 0081 0393 lri $AR1, #0x0393 -0414 18bc lrrd $AC0.L, @$AR1 -0415 b871 mulx'l $AX0.H, $AX1.H : $AC0.M, @$AR1 -0416 bc00 mulxac $AX0.H, $AX1.H, $ACC0 -0417 0080 0050 lri $AR0, #0x0050 -0419 02bf 008b call 0x008b -041b 02df ret -} - -{ -041c 009f 0dc0 lri $AC1.M, #0x0dc0 -041e 00ff 03a1 sr @0x03a1, $AC1.M -0420 009f 03a8 lri $AC1.M, #0x03a8 -0422 00ff 03a2 sr @0x03a2, $AC1.M -0424 009f 03a4 lri $AC1.M, #0x03a4 -0426 00ff 03a0 sr @0x03a0, $AC1.M -0428 1104 0448 bloopi #0x04, 0x0448 -{ - 042a 00c0 03a2 lr $AR0, @0x03a2 - 042c 0083 0390 lri $AR3, #0x0390 - 042e 009f 000e lri $AC1.M, #0x000e - 0430 02bf 0331 call 0x0331 - 0432 00da 0390 lr $AX0.H, @0x0390 - 0434 8600 tstaxh $AX0.H - 0435 0295 0439 jz 0x0439 - 0437 02bf 0402 call 0x0402 - 0439 00de 03a2 lr $AC0.M, @0x03a2 - 043b 0410 addis $AC0.M, #0x10 - 043c 00fe 03a2 sr @0x03a2, $AC0.M - 043e 00de 03a1 lr $AC0.M, @0x03a1 - 0440 0460 addis $AC0.M, #0x60 - 0441 00fe 03a1 sr @0x03a1, $AC0.M - 0443 00de 03a0 lr $AC0.M, @0x03a0 - 0445 7400 incm $AC0.M - 0446 00fe 03a0 sr @0x03a0, $AC0.M - 0448 0000 nop -} -0449 02df ret -} - -{ -044a 0081 0386 lri $AR1, #0x0386 -044c 009f 03a8 lri $AC1.M, #0x03a8 -044e 0080 0040 lri $AR0, #0x0040 -0450 02bf 007c call 0x007c -0452 02df ret -} - -{ -0453 191e lrri $AC0.M, @$AR0 -0454 189c lrrd $AC0.L, @$AR0 -0455 4800 addax $ACC0, $AX0 -0456 1b1e srri @$AR0, $AC0.M -0457 1b1c srri @$AR0, $AC0.L -0458 02df ret -0459 8100 clr $ACC0 -045a 26fe lrs $AC0.M, @CMBH -045b 02c0 8000 andcf $AC0.M, #0x8000 -045d 029c 045a jlnz 0x045a -045f 26ff lrs $AC0.M, @CMBL -0460 02df ret -} - -{ -0461 0080 0388 lri $AR0, #0x0388 -0463 0081 0051 lri $AR1, #0x0051 -0465 173f callr $AR1 // call 0x0051 -0466 00de 0344 lr $AC0.M, @0x0344 -0468 00fe 0341 sr @0x0341, $AC0.M -046a 00de 0345 lr $AC0.M, @0x0345 -046c 00fe 038e sr @0x038e, $AC0.M -046e 173f callr $AR1 // call 0x0051 -046f 02df ret -} - -{ -0470 02bf 0461 call 0x0461 -0472 009e 8000 lri $AC0.M, #0x8000 -0474 00dc 0341 lr $AC0.L, @0x0341 -0476 02bf 005a call 005a_SendMail(AC0.M,AC0.L) // 0x8000???? -0478 8100 clr $ACC0 -0479 00fe 0355 sr @0x0355, $AC0.M -047b 02bf 044a call 0x044a -047d 00de 0341 lr $AC0.M, @0x0341 -047f 007e 056c bloop $AC0.M, 0x056c -{ - 0481 02bf 035e call 0x035e - 0483 02bf 03cb call 0x03cb - 0485 02bf 0459 call 0x0459 - 0487 8100 clr $ACC0 - 0488 00fe 0354 sr @0x0354, $AC0.M - 048a 00de 0342 lr $AC0.M, @0x0342 - 048c 007e 0538 bloop $AC0.M, 0x0538 - { - 048e 00d8 0354 lr $AX0.L, @0x0354 - 0490 009a 0100 lri $AX0.H, #0x0100 - 0492 8100 clr $ACC0 - 0493 00de 0380 lr $AC0.M, @0x0380 - 0495 00dc 0381 lr $AC0.L, @0x0381 - 0497 9000 mul $AX0.L, $AX0.H - 0498 9400 mulac $AX0.L, $AX0.H, $ACC0 - 0499 00fe 034c sr @0x034c, $AC0.M - 049b 00fc 034d sr @0x034d, $AC0.L - 049d 02bf 0305 call 0x0305 - 049f 00da 0400 lr $AX0.H, @0x0400 - 04a1 8600 tstaxh $AX0.H - 04a2 0295 0533 jz 0x0533 - 04a4 00da 0401 lr $AX0.H, @0x0401 - 04a6 8600 tstaxh $AX0.H - 04a7 0294 0533 jnz 0x0533 - 04a9 00da 0406 lr $AX0.H, @0x0406 - 04ab 8600 tstaxh $AX0.H - 04ac 0294 0930 jnz 0x0930 - 04ae 8100 clr $ACC0 - 04af 00de 0440 lr $AC0.M, @0x0440 - 04b1 0607 cmpis $AC0.M, #0x07 // format 0x7 or less (Synths) - 04b2 0293 0231 jle 0x0231 - 04b4 0620 cmpis $AC0.M, #0x20 // format 0x20 - 04b5 0295 079e jz 0x079e - 04b7 0621 cmpis $AC0.M, #0x21 // format 0x21 - 04b8 0295 07a7 jz 0x07a7 - 04ba 00d8 0402 lr $AX0.L, @0x0402 - 04bc 8100 clr $ACC0 - 04bd 8900 clr $ACC1 - 04be 00dc 0418 lr $AC0.L, @0x0418 - 04c0 8d00 set15 - 04c1 0099 0050 lri $AX1.L, #0x0050 - 04c3 a000 mulx $AX0.L, $AX1.L - 04c4 a400 mulxac $AX0.L, $AX1.L, $ACC0 - 04c5 1404 lsl $ACC0, #4 - 04c6 8c00 clr15 - 04c7 1ffe mrr $AC1.M, $AC0.M - 04c8 0083 0580 lri $AR3, #0x0580 - 04ca 00da 0441 lr $AX0.H, @0x0441 - 04cc 8600 tstaxh $AX0.H - 04cd 0295 04dd jz 0x04dd - 04cf 00da 0449 lr $AX0.H, @0x0449 - 04d1 8100 clr $ACC0 - 04d2 00de 044b lr $AC0.M, @0x044b - 04d4 3800 orr $AC0.M, $AX0.H - 04d5 0240 000f andi $AC0.M, #0x000f - 04d7 0295 04dd jz 0x04dd - 04d9 02bf 06a6 call 0x06a6 - 04db 029f 04df jmp 0x04df - 04dd 02bf 0837 call 0x0837 - //RAW21-jmp - 04df 0080 0580 lri $AR0, #0x0580 - 04e1 0081 0520 lri $AR1, #0x0520 - 04e3 0099 0000 lri $AX1.L, #0x0000 - 04e5 02bf 013b call 0x013b - //RAW20-jmp - 04e7 0080 0450 lri $AR0, #0x0450 - 04e9 0081 0520 lri $AR1, #0x0520 - 04eb 0082 0428 lri $AR2, #0x0428 - 04ed 0083 0453 lri $AR3, #0x0453 - 04ef 18fa lrrd $AX0.H, @$AR3 - 04f0 8600 tstaxh $AX0.H - 04f1 0294 0501 jnz 0x0501 - 04f3 18fa lrrd $AX0.H, @$AR3 - 04f4 8600 tstaxh $AX0.H - 04f5 0294 0501 jnz 0x0501 - 04f7 18fa lrrd $AX0.H, @$AR3 - 04f8 8600 tstaxh $AX0.H - 04f9 0294 0501 jnz 0x0501 - 04fb 8100 clr $ACC0 - 04fc 18fe lrrd $AC0.M, @$AR3 - 04fd 0280 7fff cmpi $AC0.M, #0x7fff - 04ff 0295 0505 jz 0x0505 - 0501 02bf 01d1 call 0x01d1 - 0503 029f 0505 jmp 0x0505 - 0505 8100 clr $ACC0 - 0506 1c9e mrr $IX0, $AC0.M - 0507 1cde mrr $IX2, $AC0.M - 0508 7400 incm $AC0.M - 0509 1cfe mrr $IX3, $AC0.M - 050a 8f00 set40 - 050b 0086 0002 lri $IX2, #0x0002 - 050d 0082 0408 lri $AR2, #0x0408 - 050f 1104 052f bloopi #0x04, 0x052f - { - 0511 8100 clr $ACC0 - 0512 195e lrri $AC0.M, @$AR2 - 0513 1200 sbclr #0x00 - 0514 b100 tst $ACC0 - 0515 0275 ifz - 0516 1300 sbset #0x00 - 0517 1c7e mrr $AR3, $AC0.M - 0518 195e lrri $AC0.M, @$AR2 - 0519 14fa asr $ACC0, #-6 - 051a 1f5e mrr $AX0.H, $AC0.M - 051b 1f1c mrr $AX0.L, $AC0.L - 051c 185f lrr $AC1.M, @$AR2 - 051d 0080 0520 lri $AR0, #0x0520 - 051f 029d 0523 jlz 0x0523 - 0521 02bf 011e call 0x011e - 0523 1b5f srri @$AR2, $AC1.M - 0524 8100 clr $ACC0 - 0525 185e lrr $AC0.M, @$AR2 - 0526 000e xar $AR2 - //; *** UNKNOWN OPCODE *** - // 0xc/0xd/0xe/0xf is one opcode where last 2 bits define target $AR? reg - // (new value is based on orig $AR? and %WR? reg value = unknown) - 0527 b100 tst $ACC0 - 0528 0274 ifnz - 0529 7800 decm $AC0.M - 052a b100 tst $ACC0 - 052b 8900 clr $ACC1 - 052c 0275 ifz - 052d 1a5f srr @$AR2, $AC1.M - 052e 001a addarn $AR2, $IX2 - 052f 1b5e srri @$AR2, $AC0.M - } - 0530 8e00 set16 - 0531 02bf 0321 call 0x0321 - 0533 00de 0354 lr $AC0.M, @0x0354 - 0535 7400 incm $AC0.M - 0536 00fe 0354 sr @0x0354, $AC0.M - 0538 0000 nop - } - 0539 16fb 0001 si @DIRQ, #0x0001 - 053b 0083 0d00 lri $AR3, #0x0d00 - 053d 02bf 012a call 0x012a - 053f 0081 0388 lri $AR1, #0x0388 - 0541 009f 0d00 lri $AC1.M, #0x0d00 - 0543 0080 0050 lri $AR0, #0x0050 - 0545 02bf 0089 call 0x0089 - 0547 0080 0fa0 lri $AR0, #0x0fa0 - 0549 0083 0d60 lri $AR3, #0x0d60 - 054b 009f 0050 lri $AC1.M, #0x0050 - 054d 0098 8000 lri $AX0.L, #0x8000 - 054f 02bf 0342 call 0x0342 - 0551 0083 0d60 lri $AR3, #0x0d60 - 0553 02bf 012a call 0x012a - 0555 0081 038a lri $AR1, #0x038a - 0557 009f 0d60 lri $AC1.M, #0x0d60 - 0559 0080 0050 lri $AR0, #0x0050 - 055b 02bf 0089 call 0x0089 - 055d 009a 0000 lri $AX0.H, #0x0000 - 055f 0098 00a0 lri $AX0.L, #0x00a0 - 0561 0080 0388 lri $AR0, #0x0388 - 0563 02bf 0453 call 0x0453 - 0565 0080 038a lri $AR0, #0x038a - 0567 02bf 0453 call 0x0453 - 0569 02bf 041c call 0x041c - 056b 0000 nop - 056c 0000 nop -} -056d 029f 0031 jmp 0x0031 -} - -{ -056f 0080 0346 lri $AR0, #0x0346 -0571 02bf 0051 call 0x0051 -0573 02bf 0051 call 0x0051 -0575 0081 0346 lri $AR1, #0x0346 -0577 193e lrri $AC0.M, @$AR1 -0578 193c lrri $AC0.L, @$AR1 -0579 009f 0400 lri $AC1.M, #0x0400 -057b 00c0 0345 lr $AR0, @0x0345 -057d 02bf 007e call 0x007e -057f 0081 0348 lri $AR1, #0x0348 -0581 193e lrri $AC0.M, @$AR1 -0582 193c lrri $AC0.L, @$AR1 -0583 009f 0800 lri $AC1.M, #0x0800 -0585 00c0 0345 lr $AR0, @0x0345 -0587 02bf 007e call 0x007e -0589 0081 0346 lri $AR1, #0x0346 -058b 193e lrri $AC0.M, @$AR1 -058c 193c lrri $AC0.L, @$AR1 -058d 009f 0800 lri $AC1.M, #0x0800 -058f 00c0 0345 lr $AR0, @0x0345 -0591 02bf 008b call 0x008b -0593 0081 0348 lri $AR1, #0x0348 -0595 193e lrri $AC0.M, @$AR1 -0596 193c lrri $AC0.L, @$AR1 -0597 009f 0400 lri $AC1.M, #0x0400 -0599 00c0 0345 lr $AR0, @0x0345 -059b 02bf 008b call 0x008b -059d 029f 0049 jmp 0x0049 -} - -{ -059f 0080 0346 lri $AR0, #0x0346 -05a1 02bf 0051 call 0x0051 -05a3 02bf 0051 call 0x0051 -05a5 0081 0346 lri $AR1, #0x0346 -05a7 193e lrri $AC0.M, @$AR1 -05a8 193c lrri $AC0.L, @$AR1 -05a9 009f 0400 lri $AC1.M, #0x0400 -05ab 00c0 0345 lr $AR0, @0x0345 -05ad 02bf 007e call 0x007e -05af 0081 0348 lri $AR1, #0x0348 -05b1 193e lrri $AC0.M, @$AR1 -05b2 193c lrri $AC0.L, @$AR1 -05b3 009f 0400 lri $AC1.M, #0x0400 -05b5 00c0 0345 lr $AR0, @0x0345 -05b7 02bf 008b call 0x008b -05b9 029f 0049 jmp 0x0049 -} - -{ -05bb 0080 0346 lri $AR0, #0x0346 -05bd 02bf 0051 call 0x0051 -05bf 02bf 0051 call 0x0051 -05c1 0081 0346 lri $AR1, #0x0346 -05c3 193e lrri $AC0.M, @$AR1 -05c4 193c lrri $AC0.L, @$AR1 -05c5 009f 0400 lri $AC1.M, #0x0400 -05c7 00c0 0345 lr $AR0, @0x0345 -05c9 02bf 00ae call 0x00ae -05cb 0081 0348 lri $AR1, #0x0348 -05cd 193e lrri $AC0.M, @$AR1 -05ce 193c lrri $AC0.L, @$AR1 -05cf 009f 0400 lri $AC1.M, #0x0400 -05d1 00c0 0345 lr $AR0, @0x0345 -05d3 02bf 008b call 0x008b -05d5 029f 0049 jmp 0x0049 -} - -{ -05d7 0080 0346 lri $AR0, #0x0346 -05d9 02bf 0051 call 0x0051 -05db 02bf 0051 call 0x0051 -05dd 0081 0346 lri $AR1, #0x0346 -05df 193e lrri $AC0.M, @$AR1 -05e0 193c lrri $AC0.L, @$AR1 -05e1 009f 0400 lri $AC1.M, #0x0400 -05e3 00c0 0344 lr $AR0, @0x0344 -05e5 02bf 007e call 0x007e -05e7 0081 0348 lri $AR1, #0x0348 -05e9 193e lrri $AC0.M, @$AR1 -05ea 193c lrri $AC0.L, @$AR1 -05eb 009f 0800 lri $AC1.M, #0x0800 -05ed 00c0 0344 lr $AR0, @0x0344 -05ef 02bf 007e call 0x007e -05f1 0080 0400 lri $AR0, #0x0400 -05f3 0083 0800 lri $AR3, #0x0800 -05f5 0084 0000 lri $IX0, #0x0000 -05f7 00da 0345 lr $AX0.H, @0x0345 -05f9 00df 0344 lr $AC1.M, @0x0344 -05fb 8f00 set40 -05fc 197b lrri $AX1.H, @$AR3 -05fd b800 mulx $AX0.H, $AX1.H -05fe 197b lrri $AX1.H, @$AR3 -05ff 007f 0604 bloop $AC1.M, 0x0604 -0601 199e lrrn $AC0.M, @$AR0 -0602 bc00 mulxac $AX0.H, $AX1.H, $ACC0 -0603 80b2 nx'sl : $AC0.M, $AX1.H -0604 0000 nop -0605 8e00 set16 -0606 0081 0346 lri $AR1, #0x0346 -0608 193e lrri $AC0.M, @$AR1 -0609 193c lrri $AC0.L, @$AR1 -060a 009f 0400 lri $AC1.M, #0x0400 -060c 00c0 0344 lr $AR0, @0x0344 -060e 02bf 008b call 0x008b -0610 009e 8200 lri $AC0.M, #0x8200 -0612 00dc 0344 lr $AC0.L, @0x0344 -0614 02bf 005a call 005a_SendMail(AC0.M,AC0.L) // 0x8200???? -0616 029f 0031 jmp 0x0031 -} - -{ -0618 0080 0346 lri $AR0, #0x0346 -061a 02bf 0051 call 0x0051 -061c 0081 0346 lri $AR1, #0x0346 -061e 009f 0400 lri $AC1.M, #0x0400 -0620 00c0 0345 lr $AR0, @0x0345 -0622 02bf 007c call 0x007c -0624 02bf 8644 call 0x8644 // iROM!!!! -0626 029f 0049 jmp 0x0049 -} - -{ -0628 009e 0430 lri $AC0.M, #0x0430 -062a 2219 lrs $AX0.H, @0x0019 -062b 4400 addr $ACC0, $AX0.H -062c 1c1e mrr $AR0, $AC0.M -062d 1fda mrr $AC0.M, $AX0.H -062e 3280 not $AC0.M -062f 7400 incm $AC0.M -0630 221a lrs $AX0.H, @0x001a -0631 4400 addr $ACC0, $AX0.H -0632 0090 0000 lri $AC0.H, #0x0000 -0634 029f 0645 jmp 0x0645 -} - -{ -0636 009e 0430 lri $AC0.M, #0x0430 -0638 2219 lrs $AX0.H, @0x0019 -0639 4400 addr $ACC0, $AX0.H -063a 1c1e mrr $AR0, $AC0.M -063b 1fda mrr $AC0.M, $AX0.H -063c 3280 not $AC0.M -063d 7400 incm $AC0.M -063e 221a lrs $AX0.H, @0x001a -063f 4400 addr $ACC0, $AX0.H -0640 0090 0000 lri $AC0.H, #0x0000 -0642 8200 cmp -0643 0270 ifge -0644 1fdf mrr $AC0.M, $AC1.M -0645 1f3e mrr $AX1.L, $AC0.M -0646 02bf 0699 call 0x0699 -0648 261c lrs $AC0.M, @0x001c -0649 241d lrs $AC0.L, @0x001d -064a 7200 addaxl $ACC0, $AX1.L -064b 5300 subr $ACC1, $AX1.L -064c 2e1c srs @0x001c, $AC0.M -064d 2c1d srs @0x001d, $AC0.L -064e 02df ret -} - -{ -064f 8100 clr $ACC0 -0650 221c lrs $AX0.H, @0x001c -0651 201d lrs $AX0.L, @0x001d -0652 4800 addax $ACC0, $AX0 -0653 147c lsr $ACC0, #-4 -0654 2e1e srs @0x001e, $AC0.M -0655 2c1f srs @0x001f, $AC0.L -0656 2340 lrs $AX1.H, @0x0040 -0657 c814 mulc'mv $AC0.M, $AX1.H : $AX1.L, $AC0.L -0658 9e00 mulmv $AX1.L, $AX1.H, $ACC0 -0659 f000 lsl16 $ACC0 -065a 4e00 addp $ACC0 -065b 234c lrs $AX1.H, @0x004c -065c 214d lrs $AX1.L, @0x004d -065d 4a00 addax $ACC0, $AX1 -065e 2e20 srs @0x0020, $AC0.M -065f 2c21 srs @0x0021, $AC0.L -0660 1fd8 mrr $AC0.M, $AX0.L -0661 0240 000f andi $AC0.M, #0x000f -0663 2e19 srs @0x0019, $AC0.M -0664 264a lrs $AC0.M, @0x004a -0665 244b lrs $AC0.L, @0x004b -0666 5800 subax $ACC0, $AX0 -0667 2e22 srs @0x0022, $AC0.M -0668 2c23 srs @0x0023, $AC0.L -0669 02df ret -} - -{ -066a 221e lrs $AX0.H, @0x001e -066b 201f lrs $AX0.L, @0x001f -066c 8100 clr $ACC0 -066d 264a lrs $AC0.M, @0x004a -066e 244b lrs $AC0.L, @0x004b -066f 147c lsr $ACC0, #-4 -0670 5800 subax $ACC0, $AX0 -0671 0295 067a jz 0x067a -0673 02bf 06ec call 0x06ec -0675 0e10 lris $AC0.M, #0x10 -0676 2e1a srs @0x001a, $AC0.M -0677 8100 clr $ACC0 -0678 2e19 srs @0x0019, $AC0.M -0679 02df ret -} - -{ -067a 224a lrs $AX0.H, @0x004a -067b 204b lrs $AX0.L, @0x004b -067c 8100 clr $ACC0 -067d 261c lrs $AC0.M, @0x001c -067e 241d lrs $AC0.L, @0x001d -067f 5800 subax $ACC0, $AX0 -0680 0290 0687 jge 0x0687 -0682 02bf 06ec call 0x06ec -0684 2623 lrs $AC0.M, @0x0023 -0685 029f 0676 jmp 0x0676 -} - -{ -0687 2648 lrs $AC0.M, @0x0048 -0688 2449 lrs $AC0.L, @0x0049 -0689 2e1c srs @0x001c, $AC0.M -068a 2c1d srs @0x001d, $AC0.L -068b 0e10 lris $AC0.M, #0x10 -068c 2e1a srs @0x001a, $AC0.M -068d 02bf 064f call 0x064f -068f 2642 lrs $AC0.M, @0x0042 -0690 2e3f srs @0x003f, $AC0.M -0691 2643 lrs $AC0.M, @0x0043 -0692 2e3e srs @0x003e, $AC0.M -0693 8100 clr $ACC0 -0694 00fe 0362 sr @0x0362, $AC0.M -0696 02bf 06ec call 0x06ec -0698 02df ret -} - -{ -0699 b100 tst $ACC0 -069a 02d5 retz -069b 04fe addis $AC0.M, #0xfe -069c 1f1e mrr $AX0.L, $AC0.M -069d 191e lrri $AC0.M, @$AR0 -069e 0291 06a4 jl 0x06a4 -06a0 191a lrri $AX0.H, @$AR0 -06a1 0058 loop $AX0.L -06a2 64a0 movr'ls $ACC0, $AX0.H : $AX0.H, $AC0.M -06a3 6433 movr's $ACC0, $AX0.H : @$AR3, $AC0.M -06a4 1b7e srri @$AR3, $AC0.M -06a5 02df ret -} - -{ -06a6 0092 0004 lri $CR, #0x0004 -06a8 02bf 064f call 0x064f -06aa 8100 clr $ACC0 -06ab 00fe 0362 sr @0x0362, $AC0.M -06ad 8100 clr $ACC0 -06ae 2622 lrs $AC0.M, @0x0022 -06af 2423 lrs $AC0.L, @0x0023 -06b0 b100 tst $ACC0 -06b1 0294 06c3 jnz 0x06c3 -06b3 02bf 066a call 0x066a -06b5 2219 lrs $AX0.H, @0x0019 -06b6 8600 tstaxh $AX0.H -06b7 0294 06c0 jnz 0x06c0 -06b9 02bf 0636 call 0x0636 -06bb b900 tst $ACC1 -06bc 0295 06e9 jz 0x06e9 -06be 02bf 064f call 0x064f -06c0 8100 clr $ACC0 -06c1 2622 lrs $AC0.M, @0x0022 -06c2 2423 lrs $AC0.L, @0x0023 -06c3 1f1f mrr $AX0.L, $AC1.M -06c4 009a 0000 lri $AX0.H, #0x0000 -06c6 5800 subax $ACC0, $AX0 -06c7 0290 06d6 jge 0x06d6 -06c9 8100 clr $ACC0 -06ca 2619 lrs $AC0.M, @0x0019 -06cb b100 tst $ACC0 -06cc 0294 06d0 jnz 0x06d0 -06ce 02bf 066a call 0x066a -06d0 02bf 0628 call 0x0628 -06d2 02bf 064f call 0x064f -06d4 029f 06ad jmp 0x06ad -} - -{ -06d6 8100 clr $ACC0 -06d7 2619 lrs $AC0.M, @0x0019 -06d8 b100 tst $ACC0 -06d9 0294 06dd jnz 0x06dd -06db 02bf 066a call 0x066a -06dd 02bf 0636 call 0x0636 -06df b900 tst $ACC1 -06e0 0295 06e9 jz 0x06e9 -06e2 02bf 064f call 0x064f -06e4 029f 06d6 jmp 0x06d6 -} - -{ -06e6 8100 clr $ACC0 -06e7 005f loop $AC1.M -06e8 1b7e srri @$AR3, $AC0.M -06e9 0092 00ff lri $CR, #0x00ff -06eb 02df ret -} - -{ -06ec 00ff 0360 sr @0x0360, $AC1.M -06ee 00da 0362 lr $AX0.H, @0x0362 -06f0 8600 tstaxh $AX0.H -06f1 0294 06fe jnz 0x06fe -06f3 0a01 lris $AX0.H, #0x01 -06f4 00fa 0362 sr @0x0362, $AX0.H -06f6 2620 lrs $AC0.M, @0x0020 -06f7 2421 lrs $AC0.L, @0x0021 -06f8 009f 0005 lri $AC1.M, #0x0005 -06fa 02bf 0103 call 0x0103 -06fc 0092 0004 lri $CR, #0x0004 -06fe 0080 ffd3 lri $AR0, #0xffd3 -0700 0084 0000 lri $IX0, #0x0000 -0702 199e lrrn $AC0.M, @$AR0 -0703 1ffe mrr $AC1.M, $AC0.M -0704 1401 lsl $ACC0, #1 -0705 0240 001e andi $AC0.M, #0x001e -0707 0200 0300 addi $AC0.M, #0x0300 -0709 1c3e mrr $AR1, $AC0.M -070a 157c lsr $ACC1, #-4 -070b 0340 000f andi $AC1.M, #0x000f -070d 0a11 lris $AX0.H, #0x11 -070e 5500 subr $ACC1, $AX0.H -070f 009a 00f0 lri $AX0.H, #0x00f0 -0711 009b 000f lri $AX1.H, #0x000f -0713 0082 0370 lri $AR2, #0x0370 -0715 1998 lrrn $AX0.L, @$AR0 -0716 6000 movr $ACC0, $AX0.L -0717 1107 071e bloopi #0x07, 0x071e -{ - 0719 3400 andr $AC0.M, $AX0.H - 071a 1408 lsl $ACC0, #8 - 071b 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M - 071c 3644 andr'ln $AC0.M, $AX1.H : $AX0.L, @$AR0 - 071d 140c lsl $ACC0, #12 - 071e 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M -} -071f 3400 andr $AC0.M, $AX0.H -0720 1408 lsl $ACC0, #8 -0721 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M -0722 3600 andr $AC0.M, $AX1.H -0723 140c lsl $ACC0, #12 -0724 1b5e srri @$AR2, $AC0.M -0725 8f00 set40 -0726 1f7f mrr $AX1.H, $AC1.M -0727 203e lrs $AX0.L, @0x003e -0728 273f lrs $AC1.M, @0x003f -0729 193a lrri $AX0.H, @$AR1 -072a 1939 lrri $AX1.L, @$AR1 -072b 0080 0370 lri $AR0, #0x0370 -072d 0081 0430 lri $AR1, #0x0430 -072f 1c80 mrr $IX0, $AR0 -0730 a000 mulx $AX0.L, $AX1.L -0731 ea70 maddc'l $AC1.M, $AX1.L : $AC0.M, @$AR0 -0732 1108 073b bloopi #0x08, 0x073b -0734 3a93 asrnrx'mv $ACC0, $AX1.H : $AX0.L, $AC1.M -0735 a478 mulxac'l $AX0.L, $AX1.L, $ACC0 : $AC1.M, @$AR0 -0736 1485 asl $ACC0, #5 -0737 e831 maddc's $AC0.M, $AX1.L : @$AR1, $AC0.M -0738 3b92 asrnrx'mv $ACC1, $AX1.H : $AX0.L, $AC0.M -0739 a570 mulxac'l $AX0.L, $AX1.L, $ACC1 : $AC0.M, @$AR0 -073a 1585 asl $ACC1, #5 -073b ea39 maddc's $AC1.M, $AX1.L : @$AR1, $AC1.M -073c 8e00 set16 -073d 8900 clr $ACC1 -073e 00df 0360 lr $AC1.M, @0x0360 -0740 02df ret -} - -{ -0741 0080 0346 lri $AR0, #0x0346 -0743 02bf 0051 call 0x0051 -0745 8100 clr $ACC0 -0746 0080 0430 lri $AR0, #0x0430 -0748 1010 loopi #0x10 - 0749 1b1e srri @$AR0, $AC0.M -074a 00fe 0442 sr @0x0442, $AC0.M -074c 00fe 0443 sr @0x0443, $AC0.M -074e 009c 0000 lri $AC0.L, #0x0000 -0750 00fe 041c sr @0x041c, $AC0.M -0752 00fc 041d sr @0x041d, $AC0.L -0754 009e 0100 lri $AC0.M, #0x0100 -0756 009c f100 lri $AC0.L, #0xf100 -0758 00fe 044e sr @0x044e, $AC0.M -075a 00fc 044f sr @0x044f, $AC0.L -075c 009e 0040 lri $AC0.M, #0x0040 -075e 009c 0000 lri $AC0.L, #0x0000 -0760 00fe 044c sr @0x044c, $AC0.M -0762 00fc 044d sr @0x044d, $AC0.L -0764 009e 0009 lri $AC0.M, #0x0009 -0766 00fe 0440 sr @0x0440, $AC0.M -0768 009e 0010 lri $AC0.M, #0x0010 -076a 00fe 041a sr @0x041a, $AC0.M -076c 009e 0100 lri $AC0.M, #0x0100 -076e 009c f250 lri $AC0.L, #0xf250 -0770 00fe 044a sr @0x044a, $AC0.M -0772 00fc 044b sr @0x044b, $AC0.L -0774 009c 0000 lri $AC0.L, #0x0000 -0776 00fe 0448 sr @0x0448, $AC0.M -0778 00fc 0449 sr @0x0449, $AC0.L -077a 009e 0001 lri $AC0.M, #0x0001 -077c 00fe 0441 sr @0x0441, $AC0.M -077e 8900 clr $ACC1 -077f 00ff 0401 sr @0x0401, $AC1.M -0781 1180 079b bloopi #0x80, 0x079b -{ - 0783 0083 0580 lri $AR3, #0x0580 - 0785 009f 0100 lri $AC1.M, #0x0100 - 0787 02bf 06a6 call 0x06a6 - 0789 0081 0346 lri $AR1, #0x0346 - 078b 193e lrri $AC0.M, @$AR1 - 078c 18bc lrrd $AC0.L, @$AR1 - 078d 009f 0580 lri $AC1.M, #0x0580 - 078f 0080 0100 lri $AR0, #0x0100 - 0791 02bf 008b call 0x008b - 0793 0081 0346 lri $AR1, #0x0346 - 0795 193e lrri $AC0.M, @$AR1 - 0796 18bc lrrd $AC0.L, @$AR1 - 0797 0098 0200 lri $AX0.L, #0x0200 - 0799 7000 addaxl $ACC0, $AX0.L - 079a 1b3e srri @$AR1, $AC0.M - 079b 1abc srrd @$AR1, $AC0.L -} -079c 029f 0049 jmp 0x0049 -} - -void 079e_AudioFormatRAW20() -{ -079e 8900 clr $ACC1 -079f 009f 0050 lri $AC1.M, #0x0050 -07a1 0083 0520 lri $AR3, #0x0520 -07a3 02bf 07b9 call 0x07b9 -07a5 029f 04e7 jmp 0x04e7 -} - -void 07a7_AudioFormatRAW21() -{ -07a7 00d8 0402 lr $AX0.L, @0x0402 -07a9 8100 clr $ACC0 -07aa 8900 clr $ACC1 -07ab 00dc 0418 lr $AC0.L, @0x0418 -07ad 009a 0050 lri $AX0.H, #0x0050 -07af 9000 mul $AX0.L, $AX0.H -07b0 9400 mulac $AX0.L, $AX0.H, $ACC0 -07b1 1404 lsl $ACC0, #4 -07b2 1ffe mrr $AC1.M, $AC0.M -07b3 0083 0580 lri $AR3, #0x0580 -07b5 02bf 07b9 call 0x07b9 -07b7 029f 04df jmp 0x04df -} - -{ -07b9 0092 0004 lri $CR, #0x0004 -07bb 8100 clr $ACC0 -07bc 2622 lrs $AC0.M, @0x0022 -07bd 2423 lrs $AC0.L, @0x0023 -07be 1f1f mrr $AX0.L, $AC1.M -07bf 009a 0000 lri $AX0.H, #0x0000 -07c1 5800 subax $ACC0, $AX0 -07c2 0290 07d9 jge 0x07d9 -07c4 8900 clr $ACC1 -07c5 00c0 0423 lr $AR0, @0x0423 -07c7 02bf 07fe call 0x07fe -07c9 8100 clr $ACC0 -07ca 1fd8 mrr $AC0.M, $AX0.L -07cb 2223 lrs $AX0.H, @0x0023 -07cc 5400 subr $ACC0, $AX0.H -07cd 0007 dar $AR3 -07ce 1979 lrri $AX1.L, @$AR3 -07cf 005e loop $AC0.M -07d0 1b79 srri @$AR3, $AX1.L -07d1 009f 0001 lri $AC1.M, #0x0001 -07d3 2f01 srs @0x0001, $AC1.M -07d4 8900 clr $ACC1 -07d5 2f23 srs @0x0023, $AC1.M -07d6 0092 00ff lri $CR, #0x00ff -07d8 02df ret -} - -{ -07d9 2e22 srs @0x0022, $AC0.M -07da 2c23 srs @0x0023, $AC0.L -07db 8100 clr $ACC0 -07dc 8900 clr $ACC1 -07dd 264a lrs $AC0.M, @0x004a -07de 271c lrs $AC1.M, @0x001c -07df 5c00 sub $ACC0, $ACC1 -07e0 2e1e srs @0x001e, $AC0.M -07e1 5000 subr $ACC0, $AX0.L -07e2 0290 07f8 jge 0x07f8 -07e4 00c0 041e lr $AR0, @0x041e -07e6 02bf 07fe call 0x07fe -07e8 8100 clr $ACC0 -07e9 1fd8 mrr $AC0.M, $AX0.L -07ea 221e lrs $AX0.H, @0x001e -07eb 5400 subr $ACC0, $AX0.H -07ec 1c1e mrr $AR0, $AC0.M -07ed 8100 clr $ACC0 -07ee 2e1c srs @0x001c, $AC0.M -07ef 2648 lrs $AC0.M, @0x0048 -07f0 2449 lrs $AC0.L, @0x0049 -07f1 2e4c srs @0x004c, $AC0.M -07f2 2c4d srs @0x004d, $AC0.L -07f3 02bf 07fe call 0x07fe -07f5 0092 00ff lri $CR, #0x00ff -07f7 02df ret -} - -{ -07f8 1c18 mrr $AR0, $AX0.L -07f9 02bf 07fe call 0x07fe -07fb 0092 00ff lri $CR, #0x00ff -07fd 02df ret -} - -{ -07fe 8100 clr $ACC0 -07ff 1fc0 mrr $AC0.M, $AR0 -0800 b100 tst $ACC0 -0801 02d5 retz -0802 8900 clr $ACC1 -0803 271c lrs $AC1.M, @0x001c -0804 0340 0001 andi $AC1.M, #0x0001 -0806 009b 0000 lri $AX1.H, #0x0000 -0808 1f3f mrr $AX1.L, $AC1.M -0809 264c lrs $AC0.M, @0x004c -080a 244d lrs $AC0.L, @0x004d -080b 8900 clr $ACC1 -080c 251c lrs $AC1.L, @0x001c -080d 1501 lsl $ACC1, #1 -080e 4c00 add $ACC0, $ACC1 -080f 5a00 subax $ACC0, $AX1 -0810 5a00 subax $ACC0, $AX1 -0811 1c20 mrr $AR1, $AR0 -0812 1fe0 mrr $AC1.M, $AR0 -0813 0502 addis $AC1.M, #0x02 -0814 1c1f mrr $AR0, $AC1.M -0815 009f 0a00 lri $AC1.M, #0x0a00 -0817 0092 00ff lri $CR, #0x00ff -0819 02bf 007e call 0x007e -081b 0092 0004 lri $CR, #0x0004 -081d 271c lrs $AC1.M, @0x001c -081e 1f61 mrr $AX1.H, $AR1 -081f 4700 addr $ACC1, $AX1.H -0820 2f1c srs @0x001c, $AC1.M -0821 0080 0a00 lri $AR0, #0x0a00 -0823 8900 clr $ACC1 -0824 1ff9 mrr $AC1.M, $AX1.L -0825 b900 tst $ACC1 -0826 0274 ifnz -0827 0008 iar $AR0 -0828 8900 clr $ACC1 -0829 1fe1 mrr $AC1.M, $AR1 -082a 191e lrri $AC0.M, @$AR0 -082b 0701 cmpis $AC1.M, #0x01 -082c 0293 0835 jle 0x0835 -082e 191a lrri $AX0.H, @$AR0 -082f 05fe addis $AC1.M, #0xfe -0830 005f loop $AC1.M -0831 64a0 movr'ls $ACC0, $AX0.H : $AX0.H, $AC0.M -0832 1b7e srri @$AR3, $AC0.M -0833 1b7a srri @$AR3, $AX0.H -0834 02df ret -} - -{ -0835 1b7e srri @$AR3, $AC0.M -0836 02df ret -} - -{ -0837 0092 0004 lri $CR, #0x0004 -0839 2201 lrs $AX0.H, @0x0001 -083a 8600 tstaxh $AX0.H -083b 0294 0868 jnz 0x0868 -083d 2204 lrs $AX0.H, @0x0004 -083e 8600 tstaxh $AX0.H -083f 02b4 08bc callnz 0x08bc -0841 2219 lrs $AX0.H, @0x0019 -0842 8600 tstaxh $AX0.H -0843 0295 085d jz 0x085d -0845 009e 0430 lri $AC0.M, #0x0430 -0847 4400 addr $ACC0, $AX0.H -0848 1c1e mrr $AR0, $AC0.M -0849 0e10 lris $AC0.M, #0x10 -084a 5400 subr $ACC0, $AX0.H -084b 1f7e mrr $AX1.H, $AC0.M -084c 02bf 0699 call 0x0699 -084e d900 cmpar $ACC1, $AX1.H -084f 0292 085c jg 0x085c -0851 0295 0858 jz 0x0858 -0853 2619 lrs $AC0.M, @0x0019 -0854 4c00 add $ACC0, $ACC1 -0855 2e19 srs @0x0019, $AC0.M -0856 029f 08b9 jmp 0x08b9 - -0858 8100 clr $ACC0 -0859 2e19 srs @0x0019, $AC0.M -085a 029f 08b9 jmp 0x08b9 - -085c 5700 subr $ACC1, $AX1.H -085d 8100 clr $ACC0 -085e 2605 lrs $AC0.M, @0x0005 -085f b100 tst $ACC0 -0860 0295 0879 jz 0x0879 -0862 8100 clr $ACC0 -0863 2e05 srs @0x0005, $AC0.M -0864 2241 lrs $AX0.H, @0x0041 -0865 8600 tstaxh $AX0.H -0866 0294 086f jnz 0x086f -0868 8100 clr $ACC0 -0869 005f loop $AC1.M -086a 1b7e srri @$AR3, $AC0.M -086b 7400 incm $AC0.M -086c 2e01 srs @0x0001, $AC0.M -086d 029f 08b9 jmp 0x08b9 - -086f 2648 lrs $AC0.M, @0x0048 -0870 2449 lrs $AC0.L, @0x0049 -0871 2e1c srs @0x001c, $AC0.M -0872 2c1d srs @0x001d, $AC0.L -0873 02bf 08c1 call 0x08c1 -0875 2642 lrs $AC0.M, @0x0042 -0876 2443 lrs $AC0.L, @0x0043 -0877 2e3f srs @0x003f, $AC0.M -0878 2c3e srs @0x003e, $AC0.L -0879 00ff 0360 sr @0x0360, $AC1.M -087b 2620 lrs $AC0.M, @0x0020 -087c 2421 lrs $AC0.L, @0x0021 -087d 009f 0005 lri $AC1.M, #0x0005 -087f 02bf 0103 call 0x0103 -0881 0092 0004 lri $CR, #0x0004 -0883 8900 clr $ACC1 -0884 00ff 0362 sr @0x0362, $AC1.M -0886 00df 0360 lr $AC1.M, @0x0360 -0888 02bf 08db call 0x08db -088a 8100 clr $ACC0 -088b 00de 0362 lr $AC0.M, @0x0362 -088d 2240 lrs $AX0.H, @0x0040 -088e 4400 addr $ACC0, $AX0.H -088f 00fe 0362 sr @0x0362, $AC0.M -0891 8100 clr $ACC0 -0892 2622 lrs $AC0.M, @0x0022 -0893 2423 lrs $AC0.L, @0x0023 -0894 0a01 lris $AX0.H, #0x01 -0895 0081 0405 lri $AR1, #0x0405 -0897 7a00 dec $ACC0 -0898 b100 tst $ACC0 -0899 0275 ifz -089a 1a3a srr @$AR1, $AX0.H -089b 2e22 srs @0x0022, $AC0.M -089c 2c23 srs @0x0023, $AC0.L -089d 0710 cmpis $AC1.M, #0x10 -089e 0293 08a7 jle 0x08a7 -08a0 05f0 addis $AC1.M, #0xf0 -08a1 2205 lrs $AX0.H, @0x0005 -08a2 8600 tstaxh $AX0.H -08a3 0294 0862 jnz 0x0862 -08a5 029f 0888 jmp 0x0888 -08a7 0275 ifz -08a8 8900 clr $ACC1 -08a9 2f19 srs @0x0019, $AC1.M -08aa 1fc3 mrr $AC0.M, $AR3 -08ab 04f0 addis $AC0.M, #0xf0 -08ac 1c1e mrr $AR0, $AC0.M -08ad 0083 0430 lri $AR3, #0x0430 -08af 0e10 lris $AC0.M, #0x10 -08b0 02bf 0699 call 0x0699 -08b2 2620 lrs $AC0.M, @0x0020 -08b3 2421 lrs $AC0.L, @0x0021 -08b4 00d8 0362 lr $AX0.L, @0x0362 -08b6 7000 addaxl $ACC0, $AX0.L -08b7 2c21 srs @0x0021, $AC0.L -08b8 2e20 srs @0x0020, $AC0.M -08b9 0092 00ff lri $CR, #0x00ff -08bb 02df ret -} - -{ -08bc 8100 clr $ACC0 -08bd 2e1c srs @0x001c, $AC0.M -08be 2e1d srs @0x001d, $AC0.M -08bf 2e3e srs @0x003e, $AC0.M -08c0 2e3f srs @0x003f, $AC0.M -08c1 231c lrs $AX1.H, @0x001c -08c2 211d lrs $AX1.L, @0x001d -08c3 264a lrs $AC0.M, @0x004a -08c4 244b lrs $AC0.L, @0x004b -08c5 5a00 subax $ACC0, $AX1 -08c6 147c lsr $ACC0, #-4 -08c7 2e22 srs @0x0022, $AC0.M -08c8 2c23 srs @0x0023, $AC0.L -08c9 261c lrs $AC0.M, @0x001c -08ca 241d lrs $AC0.L, @0x001d -08cb 147c lsr $ACC0, #-4 -08cc 2240 lrs $AX0.H, @0x0040 -08cd c010 mulc'mv $AC0.M, $AX0.H : $AX0.L, $AC0.L -08ce 9600 mulmv $AX0.L, $AX0.H, $ACC0 -08cf f000 lsl16 $ACC0 -08d0 4e00 addp $ACC0 -08d1 234c lrs $AX1.H, @0x004c -08d2 214d lrs $AX1.L, @0x004d -08d3 4a00 addax $ACC0, $AX1 -08d4 2e20 srs @0x0020, $AC0.M -08d5 2c21 srs @0x0021, $AC0.L -08d6 8100 clr $ACC0 -08d7 2e05 srs @0x0005, $AC0.M -08d8 2e19 srs @0x0019, $AC0.M -08d9 2e04 srs @0x0004, $AC0.M -08da 02df ret -} - -{ -08db 00ff 0360 sr @0x0360, $AC1.M -08dd 0080 ffd3 lri $AR0, #0xffd3 -08df 0084 0000 lri $IX0, #0x0000 -08e1 199e lrrn $AC0.M, @$AR0 -08e2 1ffe mrr $AC1.M, $AC0.M -08e3 1401 lsl $ACC0, #1 -08e4 0240 001e andi $AC0.M, #0x001e -08e6 0200 0300 addi $AC0.M, #0x0300 -08e8 1c3e mrr $AR1, $AC0.M -08e9 157c lsr $ACC1, #-4 -08ea 0340 000f andi $AC1.M, #0x000f -08ec 0a11 lris $AX0.H, #0x11 -08ed 5500 subr $ACC1, $AX0.H -08ee 009a 00f0 lri $AX0.H, #0x00f0 -08f0 009b 000f lri $AX1.H, #0x000f -08f2 0082 0370 lri $AR2, #0x0370 -08f4 1998 lrrn $AX0.L, @$AR0 -08f5 6000 movr $ACC0, $AX0.L -08f6 1107 08fd bloopi #0x07, 0x08fd -{ - 08f8 3400 andr $AC0.M, $AX0.H - 08f9 1408 lsl $ACC0, #8 - 08fa 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M - 08fb 3644 andr'ln $AC0.M, $AX1.H : $AX0.L, @$AR0 - 08fc 140c lsl $ACC0, #12 - 08fd 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M -} -08fe 3400 andr $AC0.M, $AX0.H -08ff 1408 lsl $ACC0, #8 -0900 6032 movr's $ACC0, $AX0.L : @$AR2, $AC0.M -0901 3600 andr $AC0.M, $AX1.H -0902 140c lsl $ACC0, #12 -0903 1b5e srri @$AR2, $AC0.M -0904 8f00 set40 -0905 1f7f mrr $AX1.H, $AC1.M -0906 203e lrs $AX0.L, @0x003e -0907 273f lrs $AC1.M, @0x003f -0908 193a lrri $AX0.H, @$AR1 -0909 1939 lrri $AX1.L, @$AR1 -090a 0080 0370 lri $AR0, #0x0370 -090c 1c80 mrr $IX0, $AR0 -090d a000 mulx $AX0.L, $AX1.L -090e ea70 maddc'l $AC1.M, $AX1.L : $AC0.M, @$AR0 -090f 3a93 asrnrx'mv $ACC0, $AX1.H : $AX0.L, $AC1.M -0910 a478 mulxac'l $AX0.L, $AX1.L, $ACC0 : $AC1.M, @$AR0 -0911 1485 asl $ACC0, #5 -0912 e833 maddc's $AC0.M, $AX1.L : @$AR3, $AC0.M -0913 3b92 asrnrx'mv $ACC1, $AX1.H : $AX0.L, $AC0.M -0914 a570 mulxac'l $AX0.L, $AX1.L, $ACC1 : $AC0.M, @$AR0 -0915 1585 asl $ACC1, #5 -0916 ea3b maddc's $AC1.M, $AX1.L : @$AR3, $AC1.M -0917 1106 0920 bloopi #0x06, 0x0920 -{ - 0919 3a93 asrnrx'mv $ACC0, $AX1.H : $AX0.L, $AC1.M - 091a a478 mulxac'l $AX0.L, $AX1.L, $ACC0 : $AC1.M, @$AR0 - 091b 1485 asl $ACC0, #5 - 091c e833 maddc's $AC0.M, $AX1.L : @$AR3, $AC0.M - 091d 3b92 asrnrx'mv $ACC1, $AX1.H : $AX0.L, $AC0.M - 091e a570 mulxac'l $AX0.L, $AX1.L, $ACC1 : $AC0.M, @$AR0 - 091f 1585 asl $ACC1, #5 - 0920 ea3b maddc's $AC1.M, $AX1.L : @$AR3, $AC1.M -} -0921 3a93 asrnrx'mv $ACC0, $AX1.H : $AX0.L, $AC1.M -0922 a478 mulxac'l $AX0.L, $AX1.L, $ACC0 : $AC1.M, @$AR0 -0923 1485 asl $ACC0, #5 -0924 e833 maddc's $AC0.M, $AX1.L : @$AR3, $AC0.M -0925 3b92 asrnrx'mv $ACC1, $AX1.H : $AX0.L, $AC0.M -0926 a500 mulxac $AX0.L, $AX1.L, $ACC1 -0927 1585 asl $ACC1, #5 -0928 1b7f srri @$AR3, $AC1.M -0929 2e3e srs @0x003e, $AC0.M -092a 2f3f srs @0x003f, $AC1.M -092b 8e00 set16 -092c 8900 clr $ACC1 -092d 00df 0360 lr $AC1.M, @0x0360 -092f 02df ret -} - -{ -0930 0083 0520 lri $AR3, #0x0520 -0932 00de 041b lr $AC0.M, @0x041b -0934 1050 loopi #0x50 - 0935 1b7e srri @$AR3, $AC0.M -0936 029f 04e7 jmp 0x04e7 -} - -0938 0000 nop -0939 0000 nop -093a 0000 nop -093b 0000 nop -093c 0000 nop -093d 0000 nop -093e 0000 nop -093f 0000 nop diff -Nru dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_Zelda.txt dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_Zelda.txt --- dolphin-emu-2.0+svn5985/docs/DSP/DSP_UC_Zelda.txt 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/docs/DSP/DSP_UC_Zelda.txt 2010-08-18 03:25:25.000000000 +0100 @@ -1555,7 +1555,7 @@ // 0419 0080 002d lri $AR0, #0x002d // 041b 029f 0603 jmp 0x0603 - 0603_Unk(0x02d) + 0603_FinalizeFrame(0x02d) } // Command 07 - not seen used. @@ -2111,7 +2111,8 @@ 0601 0658 cmpis $ACC0, #0x58 0602 065b cmpis $ACC0, #0x5b -void 0603_Unk(_returnAddr($AR0)) + // at the end of a frame, we get a mail telling ucode what to do next +void 0603_FinalizeFrame(_returnAddr($AR0)) { // 0603 00e0 03f9 sr @0x03f9, $AR0 0x03f9 = _returnAddr @@ -2143,28 +2144,32 @@ switch(AR3 - 0x05FF) { case 0x00: HALT(); break; - case 0x00: HALT(); break; - case 0x01: 0658_SoftReset(); break; - case 0x02: 065b_ContinueWithUCode(); break; + case 0x01: 0618_PrepareBootUcode(); break; + case 0x02: 0658_SoftReset(); break; + case 0x03: 065b_ContinueWithUCode(); break; + default: HALT(); + // 0616 0021 halt } - } - - -0616 0021 halt + 0617 0021 halt -void 0618_Unk() { + // Sets up info needed to dma in a chunk to iram or dram, + // and calls irom to do actual dma. irom returns to address given in AR0 +void 0618_PrepareBootUcode() { + // Dunno what that's about... 0618 009a 0002 lri $AX0.H, #0x0002 061a 00fa 03a3 sr @0x03a3, $AX0.H + 061c 8100 clr $ACC0 061d 8900 clr $ACC1 + //061e 02bf 065e call 0x065e 065e_WaitForCPUMailBox_AC0() 0620 24ff lrs $AC0.L, @CMBL - //0621 02bf 0664 call 0x0664 + //0621 02bf 0664 call 0x0664 0664_WaitForCPUMailBox_AC1() 0623 25ff lrs $AC1.L, @CMBL @@ -2174,10 +2179,11 @@ 0626 27ff lrs $AC1.M, @CMBL 0627 2ece srs @DSMAH, $AC0.M - 0628 2ccf srs @DSMAL, $AC0.L + 0628 2ccf srs @DSMAL, $AC0.L // 0 0629 16c9 0001 si @DSCR, #0x0001 - 062b 2fcd srs @DSPA, $AC1.M - 062c 2dcb srs @DSBL, $AC1.L + 062b 2fcd srs @DSPA, $AC1.M // 2 + 062c 2dcb srs @DSBL, $AC1.L // 1 + 062d 8100 clr $ACC0 062e 8900 clr $ACC1 @@ -2220,15 +2226,22 @@ 065e_WaitForCPUMailBox_AC0() 064b 23ff lrs $AX1.H, @CMBL - 064c 26c9 lrs $AC0.M, @DSCR - 064d 02a0 0004 andf $AC0.M, #0x0004 - 064f 029c 064c jlnz 0x064c - 0651 1206 sbclr #0x06 - 0652 1203 sbclr #0x03 - 0653 1204 sbclr #0x04 - 0654 1205 sbclr #0x05 - 0655 029f 80b5 jmp 0x80b5 - **** GOTO ROM!! + + // Make sure dma is ready + // 064c 26c9 lrs $AC0.M, @DSCR + // 064d 02a0 0004 andf $AC0.M, #0x0004 + // 064f 029c 064c jlnz 0x064c + + // Reset some of the state + // 0651 1206 sbclr #0x06 + // 0652 1203 sbclr #0x03 + // 0653 1204 sbclr #0x04 + // 0654 1205 sbclr #0x05 + + // 0655 029f 80b5 jmp 0x80b5 + 80b5_BootUcode(); + + // Should not reach here 0657 0021 halt } diff -Nru dolphin-emu-2.0+svn5985/Externals/Bochs_disasm/SConscript dolphin-emu-2.0+svn6107/Externals/Bochs_disasm/SConscript --- dolphin-emu-2.0+svn5985/Externals/Bochs_disasm/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/Bochs_disasm/SConscript 2010-08-18 03:25:36.000000000 +0100 @@ -15,3 +15,4 @@ files += [ "stdafx.cpp" ] env.StaticLibrary(env['local_libs'] + "bdisasm", files) +env['CPPPATH'] += ['#Externals/Bochs_disasm'] diff -Nru dolphin-emu-2.0+svn5985/Externals/CLRun/clrun/clrun.c dolphin-emu-2.0+svn6107/Externals/CLRun/clrun/clrun.c --- dolphin-emu-2.0+svn5985/Externals/CLRun/clrun/clrun.c 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/CLRun/clrun/clrun.c 2010-08-18 03:25:26.000000000 +0100 @@ -36,26 +36,26 @@ } -// Windows-specific DLL code -#if defined _WIN32 && defined CLRUN_DYNAMICLIB -HINSTANCE g_hInstance; - -BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle - DWORD dwReason, // reason called - LPVOID lpvReserved) // reserved -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - break; - - case DLL_PROCESS_DETACH: - break; - default: - break; - } - - g_hInstance = hinstDLL; - return TRUE; -} +// Windows-specific DLL code +#if defined _WIN32 && defined CLRUN_DYNAMICLIB +HINSTANCE g_hInstance; + +BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD dwReason, // reason called + LPVOID lpvReserved) // reserved +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + break; + + case DLL_PROCESS_DETACH: + break; + default: + break; + } + + g_hInstance = hinstDLL; + return TRUE; +} #endif diff -Nru dolphin-emu-2.0+svn5985/Externals/GLew/SConscript dolphin-emu-2.0+svn6107/Externals/GLew/SConscript --- dolphin-emu-2.0+svn5985/Externals/GLew/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/GLew/SConscript 2010-08-18 03:25:26.000000000 +0100 @@ -2,6 +2,9 @@ Import('env') +if env.has_key('shared_glew') and env['shared_glew']: + Return() + files = [ 'src/glew.c', 'src/glewinfo.c', @@ -9,3 +12,4 @@ ] env.StaticLibrary(env['local_libs'] + "GLEW", files) +env['CPPPATH'] += ['#Externals/GLew/include'] diff -Nru dolphin-emu-2.0+svn5985/Externals/Lua/SConscript dolphin-emu-2.0+svn6107/Externals/Lua/SConscript --- dolphin-emu-2.0+svn5985/Externals/Lua/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/Lua/SConscript 2010-08-18 03:25:36.000000000 +0100 @@ -42,3 +42,4 @@ ] luaenv.StaticLibrary(env['local_libs'] + "lua", files) +env['CPPPATH'] += ['#Externals/Lua'] diff -Nru dolphin-emu-2.0+svn5985/Externals/LZO/SConscript dolphin-emu-2.0+svn6107/Externals/LZO/SConscript --- dolphin-emu-2.0+svn5985/Externals/LZO/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/LZO/SConscript 2010-08-18 03:25:36.000000000 +0100 @@ -2,8 +2,12 @@ Import('env') +if env.has_key('shared_lzo') and env['shared_lzo']: + Return() + files = [ "minilzo.c", ] env.StaticLibrary(env['local_libs'] + "lzo2", files) +env['CPPPATH'] += ['#Externals/LZO'] diff -Nru dolphin-emu-2.0+svn5985/Externals/SDL/SConscript dolphin-emu-2.0+svn6107/Externals/SDL/SConscript --- dolphin-emu-2.0+svn5985/Externals/SDL/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/SDL/SConscript 2010-08-18 03:25:27.000000000 +0100 @@ -3,6 +3,9 @@ Import('env') import sys +if env.has_key('shared_sdl') and env['shared_sdl']: + Return() + files = [ 'src/SDL.c', 'src/SDL_error.c', @@ -11,6 +14,7 @@ ] if sys.platform.count('bsd'): + env['LIBS'] += ['usbhid'] files += [ 'src/joystick/bsd/SDL_sysjoystick.c', 'src/stdlib/SDL_malloc.c', @@ -35,3 +39,4 @@ ] env.StaticLibrary(env['local_libs'] + "SDL", files) +env['CPPPATH'] += ['#Externals/SDL', '#Externals/SDL/include'] diff -Nru dolphin-emu-2.0+svn5985/Externals/SDL/src/joystick/bsd/SDL_sysjoystick.c dolphin-emu-2.0+svn6107/Externals/SDL/src/joystick/bsd/SDL_sysjoystick.c --- dolphin-emu-2.0+svn5985/Externals/SDL/src/joystick/bsd/SDL_sysjoystick.c 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/SDL/src/joystick/bsd/SDL_sysjoystick.c 2010-08-18 03:25:28.000000000 +0100 @@ -87,7 +87,7 @@ struct report { struct usb_ctl_report *buf; /* Buffer */ - size_t size; /* Buffer size */ + ssize_t size; /* Buffer size */ int rid; /* Report ID */ enum { SREPORT_UNINIT, diff -Nru dolphin-emu-2.0+svn5985/Externals/SFML/src/SConscript dolphin-emu-2.0+svn6107/Externals/SFML/src/SConscript --- dolphin-emu-2.0+svn5985/Externals/SFML/src/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/SFML/src/SConscript 2010-08-18 03:25:34.000000000 +0100 @@ -2,6 +2,9 @@ Import('env') +if env.has_key('shared_sfml') and env['shared_sfml']: + Return() + files = [ "SFML/Network/Ftp.cpp", "SFML/Network/Http.cpp", @@ -14,3 +17,4 @@ ] env.StaticLibrary(env['local_libs'] + "sfml-network", files) +env['CPPPATH'] += ['#Externals/SFML/include'] diff -Nru dolphin-emu-2.0+svn5985/Externals/SOIL/SConscript dolphin-emu-2.0+svn6107/Externals/SOIL/SConscript --- dolphin-emu-2.0+svn5985/Externals/SOIL/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/SOIL/SConscript 2010-08-18 03:25:26.000000000 +0100 @@ -2,6 +2,9 @@ Import('env') +if env.has_key('shared_soil') and env['shared_soil']: + Return() + files = [ 'image_DXT.c', 'image_helper.c', @@ -10,3 +13,4 @@ ] env.StaticLibrary(env['local_libs'] + "SOIL", files) +env['CPPPATH'] += ['#Externals/SOIL'] diff -Nru dolphin-emu-2.0+svn5985/Externals/SOIL/SOIL.c dolphin-emu-2.0+svn6107/Externals/SOIL/SOIL.c --- dolphin-emu-2.0+svn5985/Externals/SOIL/SOIL.c 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/SOIL/SOIL.c 2010-08-18 03:25:26.000000000 +0100 @@ -975,11 +975,11 @@ void check_for_GL_errors( const char *calling_location ) { /* check for errors */ - GLenum err_code = glGetError(); + GLenum err_code = GL_REPORT_ERROR(); while( GL_NO_ERROR != err_code ) { printf( "OpenGL Error @ %s: %i", calling_location, err_code ); - err_code = glGetError(); + err_code = GL_REPORT_ERROR(); } } #else diff -Nru dolphin-emu-2.0+svn5985/Externals/SOIL/stbi_DDS_aug_c.h dolphin-emu-2.0+svn6107/Externals/SOIL/stbi_DDS_aug_c.h --- dolphin-emu-2.0+svn5985/Externals/SOIL/stbi_DDS_aug_c.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/SOIL/stbi_DDS_aug_c.h 2010-08-18 03:25:26.000000000 +0100 @@ -271,12 +271,13 @@ stbi_uc *dds_data = NULL; stbi_uc block[16*4]; stbi_uc compressed[8]; - int flags, DXT_family; + unsigned int flags; + int DXT_family; int has_alpha, has_mipmap; int is_compressed, cubemap_faces; - int block_pitch, num_blocks; + int block_pitch, cf; DDS_header header; - int i, sz, cf; + unsigned int i, num_blocks, sz; // load the header if( sizeof( DDS_header ) != 128 ) { @@ -335,8 +336,8 @@ { // where are we? int bx, by, bw=4, bh=4; - int ref_x = 4 * (i % block_pitch); - int ref_y = 4 * (i / block_pitch); + unsigned int ref_x = 4 * (i % block_pitch); + unsigned int ref_y = 4 * (i / block_pitch); // get the next block's worth of compressed data, and decompress it if( DXT_family == 1 ) { diff -Nru dolphin-emu-2.0+svn5985/Externals/SOIL/stb_image_aug.c dolphin-emu-2.0+svn6107/Externals/SOIL/stb_image_aug.c --- dolphin-emu-2.0+svn5985/Externals/SOIL/stb_image_aug.c 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/SOIL/stb_image_aug.c 2010-08-18 03:25:26.000000000 +0100 @@ -1,3758 +1,3758 @@ -/* stbi-1.18 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c - when you control the images you're loading - - QUICK NOTES: - Primarily of interest to game developers and other people who can - avoid problematic images and only need the trivial interface - - JPEG baseline (no JPEG progressive, no oddball channel decimations) - PNG 8-bit only - BMP non-1bpp, non-RLE - TGA (not sure what subset, if a subset) - PSD (composited view only, no extra channels) - HDR (radiance rgbE format) - writes BMP,TGA (define STBI_NO_WRITE to remove code) - decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code) - supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) - - TODO: - stbi_info_* - - history: - 1.18 fix a threading bug (local mutable static) - 1.17 support interlaced PNG - 1.16 major bugfix - convert_format converted one too many pixels - 1.15 initialize some fields for thread safety - 1.14 fix threadsafe conversion bug; header-file-only version (#define STBI_HEADER_FILE_ONLY before including) - 1.13 threadsafe - 1.12 const qualifiers in the API - 1.11 Support installable IDCT, colorspace conversion routines - 1.10 Fixes for 64-bit (don't use "unsigned long") - optimized upsampling by Fabian "ryg" Giesen - 1.09 Fix format-conversion for PSD code (bad global variables!) - 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz - 1.07 attempt to fix C++ warning/errors again - 1.06 attempt to fix C++ warning/errors again - 1.05 fix TGA loading to return correct *comp and use good luminance calc - 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free - 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR - 1.02 support for (subset of) HDR files, float interface for preferred access to them - 1.01 fix bug: possible bug in handling right-side up bmps... not sure - fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all - 1.00 interface to zlib that skips zlib header - 0.99 correct handling of alpha in palette - 0.98 TGA loader by lonesock; dynamically add loaders (untested) - 0.97 jpeg errors on too large a file; also catch another malloc failure - 0.96 fix detection of invalid v value - particleman@mollyrocket forum - 0.95 during header scan, seek to markers in case of padding - 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same - 0.93 handle jpegtran output; verbose errors - 0.92 read 4,8,16,24,32-bit BMP files of several formats - 0.91 output 24-bit Windows 3.0 BMP files - 0.90 fix a few more warnings; bump version number to approach 1.0 - 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd - 0.60 fix compiling as c++ - 0.59 fix warnings: merge Dave Moore's -Wall fixes - 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian - 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less - than 16 available - 0.56 fix bug: zlib uncompressed mode len vs. nlen - 0.55 fix bug: restart_interval not initialized to 0 - 0.54 allow NULL for 'int *comp' - 0.53 fix bug in png 3->4; speedup png decoding - 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments - 0.51 obey req_comp requests, 1-component jpegs return as 1-component, - on 'test' only check type, not whether we support this variant -*/ - -#include "stb_image_aug.h" - -#ifndef STBI_NO_HDR -#include // ldexp -#include // strcmp -#endif - -#ifndef STBI_NO_STDIO -#include -#endif -#include -#include -#include -#include - -#ifndef _MSC_VER - #ifdef __cplusplus - #define __forceinline inline - #else - #define __forceinline - #endif -#endif - - -// implementation: -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef signed short int16; -typedef unsigned int uint32; -typedef signed int int32; -typedef unsigned int uint; - -// should produce compiler error if size is wrong -typedef unsigned char validate_uint32[sizeof(uint32)==4]; - -#if defined(STBI_NO_STDIO) && !defined(STBI_NO_WRITE) -#define STBI_NO_WRITE -#endif - -#ifndef STBI_NO_DDS -#include "stbi_DDS_aug.h" -#endif - -// I (JLD) want full messages for SOIL -#define STBI_FAILURE_USERMSG 1 - -////////////////////////////////////////////////////////////////////////////// -// -// Generic API that works on all image types -// - -// this is not threadsafe -static const char *failure_reason; - -const char *stbi_failure_reason(void) -{ - return failure_reason; -} - -static int e(const char *str) -{ - failure_reason = str; - return 0; -} - -#ifdef STBI_NO_FAILURE_STRINGS - #define e(x,y) 0 -#elif defined(STBI_FAILURE_USERMSG) - #define e(x,y) e(y) -#else - #define e(x,y) e(x) -#endif - -#define epf(x,y) ((float *) (e(x,y)?NULL:NULL)) -#define epuc(x,y) ((unsigned char *) (e(x,y)?NULL:NULL)) - -void stbi_image_free(void *retval_from_stbi_load) -{ - free(retval_from_stbi_load); -} - -#define MAX_LOADERS 32 -stbi_loader *loaders[MAX_LOADERS]; -static int max_loaders = 0; - -int stbi_register_loader(stbi_loader *loader) -{ - int i; - for (i=0; i < MAX_LOADERS; ++i) { - // already present? - if (loaders[i] == loader) - return 1; - // end of the list? - if (loaders[i] == NULL) { - loaders[i] = loader; - max_loaders = i+1; - return 1; - } - } - // no room for it - return 0; -} - -#ifndef STBI_NO_HDR -static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp); -static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp); -#endif - -#ifndef STBI_NO_STDIO -unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - FILE *f = fopen(filename, "rb"); - unsigned char *result; - if (!f) return epuc("can't fopen", "Unable to open file"); - result = stbi_load_from_file(f,x,y,comp,req_comp); - fclose(f); - return result; -} - -unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - int i; - if (stbi_jpeg_test_file(f)) - return stbi_jpeg_load_from_file(f,x,y,comp,req_comp); - if (stbi_png_test_file(f)) - return stbi_png_load_from_file(f,x,y,comp,req_comp); - if (stbi_bmp_test_file(f)) - return stbi_bmp_load_from_file(f,x,y,comp,req_comp); - if (stbi_psd_test_file(f)) - return stbi_psd_load_from_file(f,x,y,comp,req_comp); - #ifndef STBI_NO_DDS - if (stbi_dds_test_file(f)) - return stbi_dds_load_from_file(f,x,y,comp,req_comp); - #endif - #ifndef STBI_NO_HDR - if (stbi_hdr_test_file(f)) { - float *hdr = stbi_hdr_load_from_file(f, x,y,comp,req_comp); - return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); - } - #endif - for (i=0; i < max_loaders; ++i) - if (loaders[i]->test_file(f)) - return loaders[i]->load_from_file(f,x,y,comp,req_comp); - // test tga last because it's a crappy test! - if (stbi_tga_test_file(f)) - return stbi_tga_load_from_file(f,x,y,comp,req_comp); - return epuc("unknown image type", "Image not of any known type, or corrupt"); -} -#endif - -unsigned char *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - int i; - if (stbi_jpeg_test_memory(buffer,len)) - return stbi_jpeg_load_from_memory(buffer,len,x,y,comp,req_comp); - if (stbi_png_test_memory(buffer,len)) - return stbi_png_load_from_memory(buffer,len,x,y,comp,req_comp); - if (stbi_bmp_test_memory(buffer,len)) - return stbi_bmp_load_from_memory(buffer,len,x,y,comp,req_comp); - if (stbi_psd_test_memory(buffer,len)) - return stbi_psd_load_from_memory(buffer,len,x,y,comp,req_comp); - #ifndef STBI_NO_DDS - if (stbi_dds_test_memory(buffer,len)) - return stbi_dds_load_from_memory(buffer,len,x,y,comp,req_comp); - #endif - #ifndef STBI_NO_HDR - if (stbi_hdr_test_memory(buffer, len)) { - float *hdr = stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp); - return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); - } - #endif - for (i=0; i < max_loaders; ++i) - if (loaders[i]->test_memory(buffer,len)) - return loaders[i]->load_from_memory(buffer,len,x,y,comp,req_comp); - // test tga last because it's a crappy test! - if (stbi_tga_test_memory(buffer,len)) - return stbi_tga_load_from_memory(buffer,len,x,y,comp,req_comp); - return epuc("unknown image type", "Image not of any known type, or corrupt"); -} - -#ifndef STBI_NO_HDR - -#ifndef STBI_NO_STDIO -float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - FILE *f = fopen(filename, "rb"); - float *result; - if (!f) return epf("can't fopen", "Unable to open file"); - result = stbi_loadf_from_file(f,x,y,comp,req_comp); - fclose(f); - return result; -} - -float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *data; - #ifndef STBI_NO_HDR - if (stbi_hdr_test_file(f)) - return stbi_hdr_load_from_file(f,x,y,comp,req_comp); - #endif - data = stbi_load_from_file(f, x, y, comp, req_comp); - if (data) - return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); - return epf("unknown image type", "Image not of any known type, or corrupt"); -} -#endif - -float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi_uc *data; - #ifndef STBI_NO_HDR - if (stbi_hdr_test_memory(buffer, len)) - return stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp); - #endif - data = stbi_load_from_memory(buffer, len, x, y, comp, req_comp); - if (data) - return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); - return epf("unknown image type", "Image not of any known type, or corrupt"); -} -#endif - -// these is-hdr-or-not is defined independent of whether STBI_NO_HDR is -// defined, for API simplicity; if STBI_NO_HDR is defined, it always -// reports false! - -int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) -{ - #ifndef STBI_NO_HDR - return stbi_hdr_test_memory(buffer, len); - #else - return 0; - #endif -} - -#ifndef STBI_NO_STDIO -extern int stbi_is_hdr (char const *filename) -{ - FILE *f = fopen(filename, "rb"); - int result=0; - if (f) { - result = stbi_is_hdr_from_file(f); - fclose(f); - } - return result; -} - -extern int stbi_is_hdr_from_file(FILE *f) -{ - #ifndef STBI_NO_HDR - return stbi_hdr_test_file(f); - #else - return 0; - #endif -} - -#endif - -// @TODO: get image dimensions & components without fully decoding -#ifndef STBI_NO_STDIO -extern int stbi_info (char const *filename, int *x, int *y, int *comp); -extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); -#endif -extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); - -#ifndef STBI_NO_HDR -static float h2l_gamma_i=1.0f/2.2f, h2l_scale_i=1.0f; -static float l2h_gamma=2.2f, l2h_scale=1.0f; - -void stbi_hdr_to_ldr_gamma(float gammafactor) { h2l_gamma_i = 1/gammafactor; } -void stbi_hdr_to_ldr_scale(float scale) { h2l_scale_i = 1/scale; } - -void stbi_ldr_to_hdr_gamma(float gammafactor) { l2h_gamma = gammafactor; } -void stbi_ldr_to_hdr_scale(float scale) { l2h_scale = scale; } -#endif - - -////////////////////////////////////////////////////////////////////////////// -// -// Common code used by all image loaders -// - -enum -{ - SCAN_load=0, - SCAN_type, - SCAN_header, -}; - -typedef struct -{ - uint32 img_x, img_y; - int img_n, img_out_n; - - #ifndef STBI_NO_STDIO - FILE *img_file; - #endif - uint8 *img_buffer, *img_buffer_end; -} stbi; - -#ifndef STBI_NO_STDIO -static void start_file(stbi *s, FILE *f) -{ - s->img_file = f; +/* stbi-1.18 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c + when you control the images you're loading + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline (no JPEG progressive, no oddball channel decimations) + PNG 8-bit only + BMP non-1bpp, non-RLE + TGA (not sure what subset, if a subset) + PSD (composited view only, no extra channels) + HDR (radiance rgbE format) + writes BMP,TGA (define STBI_NO_WRITE to remove code) + decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code) + supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) + + TODO: + stbi_info_* + + history: + 1.18 fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug; header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less + than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant +*/ + +#include "stb_image_aug.h" + +#ifndef STBI_NO_HDR +#include // ldexp +#include // strcmp +#endif + +#ifndef STBI_NO_STDIO +#include +#endif +#include +#include +#include +#include + +#ifndef _MSC_VER + #ifdef __cplusplus + #define __forceinline inline + #else + #define __forceinline + #endif +#endif + + +// implementation: +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; +typedef unsigned int uint; + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(uint32)==4]; + +#if defined(STBI_NO_STDIO) && !defined(STBI_NO_WRITE) +#define STBI_NO_WRITE +#endif + +#ifndef STBI_NO_DDS +#include "stbi_DDS_aug.h" +#endif + +// I (JLD) want full messages for SOIL +#define STBI_FAILURE_USERMSG 1 + +////////////////////////////////////////////////////////////////////////////// +// +// Generic API that works on all image types +// + +// this is not threadsafe +static const char *failure_reason; + +const char *stbi_failure_reason(void) +{ + return failure_reason; +} + +static int e(const char *str) +{ + failure_reason = str; + return 0; +} + +#ifdef STBI_NO_FAILURE_STRINGS + #define e(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define e(x,y) e(y) +#else + #define e(x,y) e(x) +#endif + +#define epf(x,y) ((float *) (e(x,y)?NULL:NULL)) +#define epuc(x,y) ((unsigned char *) (e(x,y)?NULL:NULL)) + +void stbi_image_free(void *retval_from_stbi_load) +{ + free(retval_from_stbi_load); +} + +#define MAX_LOADERS 32 +stbi_loader *loaders[MAX_LOADERS]; +static int max_loaders = 0; + +int stbi_register_loader(stbi_loader *loader) +{ + int i; + for (i=0; i < MAX_LOADERS; ++i) { + // already present? + if (loaders[i] == loader) + return 1; + // end of the list? + if (loaders[i] == NULL) { + loaders[i] = loader; + max_loaders = i+1; + return 1; + } + } + // no room for it + return 0; +} + +#ifndef STBI_NO_HDR +static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_STDIO +unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = fopen(filename, "rb"); + unsigned char *result; + if (!f) return epuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + int i; + if (stbi_jpeg_test_file(f)) + return stbi_jpeg_load_from_file(f,x,y,comp,req_comp); + if (stbi_png_test_file(f)) + return stbi_png_load_from_file(f,x,y,comp,req_comp); + if (stbi_bmp_test_file(f)) + return stbi_bmp_load_from_file(f,x,y,comp,req_comp); + if (stbi_psd_test_file(f)) + return stbi_psd_load_from_file(f,x,y,comp,req_comp); + #ifndef STBI_NO_DDS + if (stbi_dds_test_file(f)) + return stbi_dds_load_from_file(f,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_HDR + if (stbi_hdr_test_file(f)) { + float *hdr = stbi_hdr_load_from_file(f, x,y,comp,req_comp); + return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + for (i=0; i < max_loaders; ++i) + if (loaders[i]->test_file(f)) + return loaders[i]->load_from_file(f,x,y,comp,req_comp); + // test tga last because it's a crappy test! + if (stbi_tga_test_file(f)) + return stbi_tga_load_from_file(f,x,y,comp,req_comp); + return epuc("unknown image type", "Image not of any known type, or corrupt"); +} +#endif + +unsigned char *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + int i; + if (stbi_jpeg_test_memory(buffer,len)) + return stbi_jpeg_load_from_memory(buffer,len,x,y,comp,req_comp); + if (stbi_png_test_memory(buffer,len)) + return stbi_png_load_from_memory(buffer,len,x,y,comp,req_comp); + if (stbi_bmp_test_memory(buffer,len)) + return stbi_bmp_load_from_memory(buffer,len,x,y,comp,req_comp); + if (stbi_psd_test_memory(buffer,len)) + return stbi_psd_load_from_memory(buffer,len,x,y,comp,req_comp); + #ifndef STBI_NO_DDS + if (stbi_dds_test_memory(buffer,len)) + return stbi_dds_load_from_memory(buffer,len,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_HDR + if (stbi_hdr_test_memory(buffer, len)) { + float *hdr = stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp); + return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + for (i=0; i < max_loaders; ++i) + if (loaders[i]->test_memory(buffer,len)) + return loaders[i]->load_from_memory(buffer,len,x,y,comp,req_comp); + // test tga last because it's a crappy test! + if (stbi_tga_test_memory(buffer,len)) + return stbi_tga_load_from_memory(buffer,len,x,y,comp,req_comp); + return epuc("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_HDR + +#ifndef STBI_NO_STDIO +float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = fopen(filename, "rb"); + float *result; + if (!f) return epf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi_hdr_test_file(f)) + return stbi_hdr_load_from_file(f,x,y,comp,req_comp); + #endif + data = stbi_load_from_file(f, x, y, comp, req_comp); + if (data) + return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return epf("unknown image type", "Image not of any known type, or corrupt"); +} +#endif + +float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *data; + #ifndef STBI_NO_HDR + if (stbi_hdr_test_memory(buffer, len)) + return stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp); + #endif + data = stbi_load_from_memory(buffer, len, x, y, comp, req_comp); + if (data) + return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return epf("unknown image type", "Image not of any known type, or corrupt"); +} +#endif + +// these is-hdr-or-not is defined independent of whether STBI_NO_HDR is +// defined, for API simplicity; if STBI_NO_HDR is defined, it always +// reports false! + +int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + return stbi_hdr_test_memory(buffer, len); + #else + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +extern int stbi_is_hdr (char const *filename) +{ + FILE *f = fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +extern int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + return stbi_hdr_test_file(f); + #else + return 0; + #endif +} + +#endif + +// @TODO: get image dimensions & components without fully decoding +#ifndef STBI_NO_STDIO +extern int stbi_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +#endif +extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); + +#ifndef STBI_NO_HDR +static float h2l_gamma_i=1.0f/2.2f, h2l_scale_i=1.0f; +static float l2h_gamma=2.2f, l2h_scale=1.0f; + +void stbi_hdr_to_ldr_gamma(float gammafactor) { h2l_gamma_i = 1/gammafactor; } +void stbi_hdr_to_ldr_scale(float scale) { h2l_scale_i = 1/scale; } + +void stbi_ldr_to_hdr_gamma(float gammafactor) { l2h_gamma = gammafactor; } +void stbi_ldr_to_hdr_scale(float scale) { l2h_scale = scale; } +#endif + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + SCAN_load=0, + SCAN_type, + SCAN_header, +}; + +typedef struct +{ + uint32 img_x, img_y; + int img_n, img_out_n; + + #ifndef STBI_NO_STDIO + FILE *img_file; + #endif + uint8 *img_buffer, *img_buffer_end; +} stbi; + +#ifndef STBI_NO_STDIO +static void start_file(stbi *s, FILE *f) +{ + s->img_file = f; s->img_buffer = NULL; s->img_buffer_end = NULL; -} -#endif - -static void start_mem(stbi *s, uint8 const *buffer, int len) -{ -#ifndef STBI_NO_STDIO - s->img_file = NULL; -#endif - s->img_buffer = (uint8 *) buffer; - s->img_buffer_end = (uint8 *) buffer+len; -} - -__forceinline static int get8(stbi *s) -{ -#ifndef STBI_NO_STDIO - if (s->img_file) { - int c = fgetc(s->img_file); - return c == EOF ? 0 : c; - } -#endif - if (s->img_buffer < s->img_buffer_end) - return *s->img_buffer++; - return 0; -} - -__forceinline static int at_eof(stbi *s) -{ -#ifndef STBI_NO_STDIO - if (s->img_file) - return feof(s->img_file); -#endif - return s->img_buffer >= s->img_buffer_end; -} - -__forceinline static uint8 get8u(stbi *s) -{ - return (uint8) get8(s); -} - -static void skip(stbi *s, int n) -{ -#ifndef STBI_NO_STDIO - if (s->img_file) - fseek(s->img_file, n, SEEK_CUR); - else -#endif - s->img_buffer += n; -} - -static int get16(stbi *s) -{ - int z = get8(s); - return (z << 8) + get8(s); -} - -static uint32 get32(stbi *s) -{ - uint32 z = get16(s); - return (z << 16) + get16(s); -} - -static int get16le(stbi *s) -{ - int z = get8(s); - return z + (get8(s) << 8); -} - -static uint32 get32le(stbi *s) -{ - uint32 z = get16le(s); - return z + (get16le(s) << 16); -} - -static void getn(stbi *s, stbi_uc *buffer, int n) -{ -#ifndef STBI_NO_STDIO - if (s->img_file) { - fread(buffer, 1, n, s->img_file); - return; - } -#endif - memcpy(buffer, s->img_buffer, n); - s->img_buffer += n; -} - -////////////////////////////////////////////////////////////////////////////// -// -// generic converter from built-in img_n to req_comp -// individual types do this automatically as much as possible (e.g. jpeg -// does all cases internally since it needs to colorspace convert anyway, -// and it never has alpha, so very few cases ). png can automatically -// interleave an alpha=255 channel, but falls back to this for other cases -// -// assume data buffer is malloced, so malloc a new one and free that one -// only failure mode is malloc failing - -static uint8 compute_y(int r, int g, int b) -{ - return (uint8) (((r*77) + (g*150) + (29*b)) >> 8); -} - -static unsigned char *convert_format(unsigned char *data, int img_n, int req_comp, uint x, uint y) -{ - int i,j; - unsigned char *good; - - if (req_comp == img_n) return data; - assert(req_comp >= 1 && req_comp <= 4); - - good = (unsigned char *) malloc(req_comp * x * y); - if (good == NULL) { - free(data); - return epuc("outofmem", "Out of memory"); - } - - for (j=0; j < (int) y; ++j) { - unsigned char *src = data + j * x * img_n ; - unsigned char *dest = good + j * x * req_comp; - - #define COMBO(a,b) ((a)*8+(b)) - #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) - // convert source image with img_n components to one with req_comp components; - // avoid switch per pixel, so use switch per scanline and massive macros - switch(COMBO(img_n, req_comp)) { - CASE(1,2) dest[0]=src[0], dest[1]=255; break; - CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; - CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; - CASE(2,1) dest[0]=src[0]; break; - CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; - CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; - CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; - CASE(3,1) dest[0]=compute_y(src[0],src[1],src[2]); break; - CASE(3,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = 255; break; - CASE(4,1) dest[0]=compute_y(src[0],src[1],src[2]); break; - CASE(4,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; - CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; - default: assert(0); - } - #undef CASE - } - - free(data); - return good; -} - -#ifndef STBI_NO_HDR -static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp) -{ - int i,k,n; - float *output = (float *) malloc(x * y * comp * sizeof(float)); - if (output == NULL) { free(data); return epf("outofmem", "Out of memory"); } - // compute number of non-alpha components - if (comp & 1) n = comp; else n = comp-1; - for (i=0; i < x*y; ++i) { - for (k=0; k < n; ++k) { - output[i*comp + k] = (float) pow(data[i*comp+k]/255.0f, l2h_gamma) * l2h_scale; - } - if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; - } - free(data); - return output; -} - -#define float2int(x) ((int) (x)) -static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp) -{ - int i,k,n; - stbi_uc *output = (stbi_uc *) malloc(x * y * comp); - if (output == NULL) { free(data); return epuc("outofmem", "Out of memory"); } - // compute number of non-alpha components - if (comp & 1) n = comp; else n = comp-1; - for (i=0; i < x*y; ++i) { - for (k=0; k < n; ++k) { - float z = (float) pow(data[i*comp+k]*h2l_scale_i, h2l_gamma_i) * 255 + 0.5f; - if (z < 0) z = 0; - if (z > 255) z = 255; - output[i*comp + k] = float2int(z); - } - if (k < comp) { - float z = data[i*comp+k] * 255 + 0.5f; - if (z < 0) z = 0; - if (z > 255) z = 255; - output[i*comp + k] = float2int(z); - } - } - free(data); - return output; -} -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// "baseline" JPEG/JFIF decoder (not actually fully baseline implementation) -// -// simple implementation -// - channel subsampling of at most 2 in each dimension -// - doesn't support delayed output of y-dimension -// - simple interface (only one output format: 8-bit interleaved RGB) -// - doesn't try to recover corrupt jpegs -// - doesn't allow partial loading, loading multiple at once -// - still fast on x86 (copying globals into locals doesn't help x86) -// - allocates lots of intermediate memory (full size of all components) -// - non-interleaved case requires this anyway -// - allows good upsampling (see next) -// high-quality -// - upsampled channels are bilinearly interpolated, even across blocks -// - quality integer IDCT derived from IJG's 'slow' -// performance -// - fast huffman; reasonable integer IDCT -// - uses a lot of intermediate memory, could cache poorly -// - load http://nothings.org/remote/anemones.jpg 3 times on 2.8Ghz P4 -// stb_jpeg: 1.34 seconds (MSVC6, default release build) -// stb_jpeg: 1.06 seconds (MSVC6, processor = Pentium Pro) -// IJL11.dll: 1.08 seconds (compiled by intel) -// IJG 1998: 0.98 seconds (MSVC6, makefile provided by IJG) -// IJG 1998: 0.95 seconds (MSVC6, makefile + proc=PPro) - -// huffman decoding acceleration -#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache - -typedef struct -{ - uint8 fast[1 << FAST_BITS]; - // weirdly, repacking this into AoS is a 10% speed loss, instead of a win - uint16 code[256]; - uint8 values[256]; - uint8 size[257]; - unsigned int maxcode[18]; - int delta[17]; // old 'firstsymbol' - old 'firstcode' -} huffman; - -typedef struct -{ - #if STBI_SIMD - unsigned short dequant2[4][64]; - #endif - stbi s; - huffman huff_dc[4]; - huffman huff_ac[4]; - uint8 dequant[4][64]; - -// sizes for components, interleaved MCUs - int img_h_max, img_v_max; - int img_mcu_x, img_mcu_y; - int img_mcu_w, img_mcu_h; - -// definition of jpeg image component - struct - { - int id; - int h,v; - int tq; - int hd,ha; - int dc_pred; - - int x,y,w2,h2; - uint8 *data; - void *raw_data; - uint8 *linebuf; - } img_comp[4]; - - uint32 code_buffer; // jpeg entropy-coded buffer - int code_bits; // number of valid bits - unsigned char marker; // marker seen while filling entropy buffer - int nomore; // flag if we saw a marker so must stop - - int scan_n, order[4]; - int restart_interval, todo; -} jpeg; - -static int build_huffman(huffman *h, int *count) -{ - int i,j,k=0,code; - // build size list for each symbol (from JPEG spec) - for (i=0; i < 16; ++i) - for (j=0; j < count[i]; ++j) - h->size[k++] = (uint8) (i+1); - h->size[k] = 0; - - // compute actual symbols (from jpeg spec) - code = 0; - k = 0; - for(j=1; j <= 16; ++j) { - // compute delta to add to code to compute symbol id - h->delta[j] = k - code; - if (h->size[k] == j) { - while (h->size[k] == j) - h->code[k++] = (uint16) (code++); - if (code-1 >= (1 << j)) return e("bad code lengths","Corrupt JPEG"); - } - // compute largest code + 1 for this size, preshifted as needed later - h->maxcode[j] = code << (16-j); - code <<= 1; - } - h->maxcode[j] = 0xffffffff; - - // build non-spec acceleration table; 255 is flag for not-accelerated - memset(h->fast, 255, 1 << FAST_BITS); - for (i=0; i < k; ++i) { - int s = h->size[i]; - if (s <= FAST_BITS) { - int c = h->code[i] << (FAST_BITS-s); - int m = 1 << (FAST_BITS-s); - for (j=0; j < m; ++j) { - h->fast[c+j] = (uint8) i; - } - } - } - return 1; -} - -static void grow_buffer_unsafe(jpeg *j) -{ - do { - int b = j->nomore ? 0 : get8(&j->s); - if (b == 0xff) { - int c = get8(&j->s); - if (c != 0) { - j->marker = (unsigned char) c; - j->nomore = 1; - return; - } - } - j->code_buffer = (j->code_buffer << 8) | b; - j->code_bits += 8; - } while (j->code_bits <= 24); -} - -// (1 << n) - 1 -static uint32 bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; - -// decode a jpeg huffman value from the bitstream -__forceinline static int decode(jpeg *j, huffman *h) -{ - unsigned int temp; - int c,k; - - if (j->code_bits < 16) grow_buffer_unsafe(j); - - // look at the top FAST_BITS and determine what symbol ID it is, - // if the code is <= FAST_BITS - c = (j->code_buffer >> (j->code_bits - FAST_BITS)) & ((1 << FAST_BITS)-1); - k = h->fast[c]; - if (k < 255) { - if (h->size[k] > j->code_bits) - return -1; - j->code_bits -= h->size[k]; - return h->values[k]; - } - - // naive test is to shift the code_buffer down so k bits are - // valid, then test against maxcode. To speed this up, we've - // preshifted maxcode left so that it has (16-k) 0s at the - // end; in other words, regardless of the number of bits, it - // wants to be compared against something shifted to have 16; - // that way we don't need to shift inside the loop. - if (j->code_bits < 16) - temp = (j->code_buffer << (16 - j->code_bits)) & 0xffff; - else - temp = (j->code_buffer >> (j->code_bits - 16)) & 0xffff; - for (k=FAST_BITS+1 ; ; ++k) - if (temp < h->maxcode[k]) - break; - if (k == 17) { - // error! code not found - j->code_bits -= 16; - return -1; - } - - if (k > j->code_bits) - return -1; - - // convert the huffman code to the symbol id - c = ((j->code_buffer >> (j->code_bits - k)) & bmask[k]) + h->delta[k]; - assert((((j->code_buffer) >> (j->code_bits - h->size[c])) & bmask[h->size[c]]) == h->code[c]); - - // convert the id to a symbol - j->code_bits -= k; - return h->values[c]; -} - -// combined JPEG 'receive' and JPEG 'extend', since baseline -// always extends everything it receives. -__forceinline static int extend_receive(jpeg *j, int n) -{ - unsigned int m = 1 << (n-1); - unsigned int k; - if (j->code_bits < n) grow_buffer_unsafe(j); - k = (j->code_buffer >> (j->code_bits - n)) & bmask[n]; - j->code_bits -= n; - // the following test is probably a random branch that won't - // predict well. I tried to table accelerate it but failed. - // maybe it's compiling as a conditional move? - if (k < m) - return (-1 << n) + k + 1; - else - return k; -} - -// given a value that's at position X in the zigzag stream, -// where does it appear in the 8x8 matrix coded as row-major? -static uint8 dezigzag[64+15] = -{ - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63, - // let corrupt input sample past end - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63 -}; - -// decode one 64-entry block-- -static int decode_block(jpeg *j, short data[64], huffman *hdc, huffman *hac, int b) -{ - int diff,dc,k; - int t = decode(j, hdc); - if (t < 0) return e("bad huffman code","Corrupt JPEG"); - - // 0 all the ac values now so we can do it 32-bits at a time - memset(data,0,64*sizeof(data[0])); - - diff = t ? extend_receive(j, t) : 0; - dc = j->img_comp[b].dc_pred + diff; - j->img_comp[b].dc_pred = dc; - data[0] = (short) dc; - - // decode AC components, see JPEG spec - k = 1; - do { - int r,s; - int rs = decode(j, hac); - if (rs < 0) return e("bad huffman code","Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (rs != 0xf0) break; // end block - k += 16; - } else { - k += r; - // decode into unzigzag'd location - data[dezigzag[k++]] = (short) extend_receive(j,s); - } - } while (k < 64); - return 1; -} - -// take a -128..127 value and clamp it and convert to 0..255 -__forceinline static uint8 clamp(int x) -{ - x += 128; - // trick to use a single test to catch both cases - if ((unsigned int) x > 255) { - if (x < 0) return 0; - if (x > 255) return 255; - } - return (uint8) x; -} - -#define f2f(x) (int) (((x) * 4096 + 0.5)) -#define fsh(x) ((x) << 12) - -// derived from jidctint -- DCT_ISLOW -#define IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ - int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ - p2 = s2; \ - p3 = s6; \ - p1 = (p2+p3) * f2f(0.5411961f); \ - t2 = p1 + p3*f2f(-1.847759065f); \ - t3 = p1 + p2*f2f( 0.765366865f); \ - p2 = s0; \ - p3 = s4; \ - t0 = fsh(p2+p3); \ - t1 = fsh(p2-p3); \ - x0 = t0+t3; \ - x3 = t0-t3; \ - x1 = t1+t2; \ - x2 = t1-t2; \ - t0 = s7; \ - t1 = s5; \ - t2 = s3; \ - t3 = s1; \ - p3 = t0+t2; \ - p4 = t1+t3; \ - p1 = t0+t3; \ - p2 = t1+t2; \ - p5 = (p3+p4)*f2f( 1.175875602f); \ - t0 = t0*f2f( 0.298631336f); \ - t1 = t1*f2f( 2.053119869f); \ - t2 = t2*f2f( 3.072711026f); \ - t3 = t3*f2f( 1.501321110f); \ - p1 = p5 + p1*f2f(-0.899976223f); \ - p2 = p5 + p2*f2f(-2.562915447f); \ - p3 = p3*f2f(-1.961570560f); \ - p4 = p4*f2f(-0.390180644f); \ - t3 += p1+p4; \ - t2 += p2+p3; \ - t1 += p2+p4; \ - t0 += p1+p3; - -#if !STBI_SIMD -// .344 seconds on 3*anemones.jpg -static void idct_block(uint8 *out, int out_stride, short data[64], uint8 *dequantize) -{ - int i,val[64],*v=val; - uint8 *o,*dq = dequantize; - short *d = data; - - // columns - for (i=0; i < 8; ++i,++d,++dq, ++v) { - // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing - if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 - && d[40]==0 && d[48]==0 && d[56]==0) { - // no shortcut 0 seconds - // (1|2|3|4|5|6|7)==0 0 seconds - // all separate -0.047 seconds - // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds - int dcterm = d[0] * dq[0] << 2; - v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; - } else { - IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24], - d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56]) - // constants scaled things up by 1<<12; let's bring them back - // down, but keep 2 extra bits of precision - x0 += 512; x1 += 512; x2 += 512; x3 += 512; - v[ 0] = (x0+t3) >> 10; - v[56] = (x0-t3) >> 10; - v[ 8] = (x1+t2) >> 10; - v[48] = (x1-t2) >> 10; - v[16] = (x2+t1) >> 10; - v[40] = (x2-t1) >> 10; - v[24] = (x3+t0) >> 10; - v[32] = (x3-t0) >> 10; - } - } - - for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { - // no fast case since the first 1D IDCT spread components out - IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) - // constants scaled things up by 1<<12, plus we had 1<<2 from first - // loop, plus horizontal and vertical each scale by sqrt(8) so together - // we've got an extra 1<<3, so 1<<17 total we need to remove. - x0 += 65536; x1 += 65536; x2 += 65536; x3 += 65536; - o[0] = clamp((x0+t3) >> 17); - o[7] = clamp((x0-t3) >> 17); - o[1] = clamp((x1+t2) >> 17); - o[6] = clamp((x1-t2) >> 17); - o[2] = clamp((x2+t1) >> 17); - o[5] = clamp((x2-t1) >> 17); - o[3] = clamp((x3+t0) >> 17); - o[4] = clamp((x3-t0) >> 17); - } -} -#else -static void idct_block(uint8 *out, int out_stride, short data[64], unsigned short *dequantize) -{ - int i,val[64],*v=val; - uint8 *o; - unsigned short *dq = dequantize; - short *d = data; - - // columns - for (i=0; i < 8; ++i,++d,++dq, ++v) { - // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing - if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 - && d[40]==0 && d[48]==0 && d[56]==0) { - // no shortcut 0 seconds - // (1|2|3|4|5|6|7)==0 0 seconds - // all separate -0.047 seconds - // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds - int dcterm = d[0] * dq[0] << 2; - v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; - } else { - IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24], - d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56]) - // constants scaled things up by 1<<12; let's bring them back - // down, but keep 2 extra bits of precision - x0 += 512; x1 += 512; x2 += 512; x3 += 512; - v[ 0] = (x0+t3) >> 10; - v[56] = (x0-t3) >> 10; - v[ 8] = (x1+t2) >> 10; - v[48] = (x1-t2) >> 10; - v[16] = (x2+t1) >> 10; - v[40] = (x2-t1) >> 10; - v[24] = (x3+t0) >> 10; - v[32] = (x3-t0) >> 10; - } - } - - for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { - // no fast case since the first 1D IDCT spread components out - IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) - // constants scaled things up by 1<<12, plus we had 1<<2 from first - // loop, plus horizontal and vertical each scale by sqrt(8) so together - // we've got an extra 1<<3, so 1<<17 total we need to remove. - x0 += 65536; x1 += 65536; x2 += 65536; x3 += 65536; - o[0] = clamp((x0+t3) >> 17); - o[7] = clamp((x0-t3) >> 17); - o[1] = clamp((x1+t2) >> 17); - o[6] = clamp((x1-t2) >> 17); - o[2] = clamp((x2+t1) >> 17); - o[5] = clamp((x2-t1) >> 17); - o[3] = clamp((x3+t0) >> 17); - o[4] = clamp((x3-t0) >> 17); - } -} -static stbi_idct_8x8 stbi_idct_installed = idct_block; - -extern void stbi_install_idct(stbi_idct_8x8 func) -{ - stbi_idct_installed = func; -} -#endif - -#define MARKER_none 0xff -// if there's a pending marker from the entropy stream, return that -// otherwise, fetch from the stream and get a marker. if there's no -// marker, return 0xff, which is never a valid marker value -static uint8 get_marker(jpeg *j) -{ - uint8 x; - if (j->marker != MARKER_none) { x = j->marker; j->marker = MARKER_none; return x; } - x = get8u(&j->s); - if (x != 0xff) return MARKER_none; - while (x == 0xff) - x = get8u(&j->s); - return x; -} - -// in each scan, we'll have scan_n components, and the order -// of the components is specified by order[] -#define RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) - -// after a restart interval, reset the entropy decoder and -// the dc prediction -static void reset(jpeg *j) -{ - j->code_bits = 0; - j->code_buffer = 0; - j->nomore = 0; - j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; - j->marker = MARKER_none; - j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; - // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, - // since we don't even allow 1<<30 pixels -} - -static int parse_entropy_coded_data(jpeg *z) -{ - reset(z); - if (z->scan_n == 1) { - int i,j; - #if STBI_SIMD - __declspec(align(16)) - #endif - short data[64]; - int n = z->order[0]; - // non-interleaved data, we just need to process one block at a time, - // in trivial scanline order - // number of blocks to do just depends on how many actual "pixels" this - // component has, independent of interleaved MCU blocking and such - int w = (z->img_comp[n].x+7) >> 3; - int h = (z->img_comp[n].y+7) >> 3; - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) { - if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; - #if STBI_SIMD - stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); - #else - idct_block(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); - #endif - // every data block is an MCU, so countdown the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) grow_buffer_unsafe(z); - // if it's NOT a restart, then just bail, so we get corrupt data - // rather than no data - if (!RESTART(z->marker)) return 1; - reset(z); - } - } - } - } else { // interleaved! - int i,j,k,x,y; - short data[64]; - for (j=0; j < z->img_mcu_y; ++j) { - for (i=0; i < z->img_mcu_x; ++i) { - // scan an interleaved mcu... process scan_n components in order - for (k=0; k < z->scan_n; ++k) { - int n = z->order[k]; - // scan out an mcu's worth of this component; that's just determined - // by the basic H and V specified for the component - for (y=0; y < z->img_comp[n].v; ++y) { - for (x=0; x < z->img_comp[n].h; ++x) { - int x2 = (i*z->img_comp[n].h + x)*8; - int y2 = (j*z->img_comp[n].v + y)*8; - if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; - #if STBI_SIMD - stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); - #else - idct_block(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); - #endif - } - } - } - // after all interleaved components, that's an interleaved MCU, - // so now count down the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) grow_buffer_unsafe(z); - // if it's NOT a restart, then just bail, so we get corrupt data - // rather than no data - if (!RESTART(z->marker)) return 1; - reset(z); - } - } - } - } - return 1; -} - -static int process_marker(jpeg *z, int m) -{ - int L; - switch (m) { - case MARKER_none: // no marker found - return e("expected marker","Corrupt JPEG"); - - case 0xC2: // SOF - progressive - return e("progressive jpeg","JPEG format not supported (progressive)"); - - case 0xDD: // DRI - specify restart interval - if (get16(&z->s) != 4) return e("bad DRI len","Corrupt JPEG"); - z->restart_interval = get16(&z->s); - return 1; - - case 0xDB: // DQT - define quantization table - L = get16(&z->s)-2; - while (L > 0) { - int q = get8(&z->s); - int p = q >> 4; - int t = q & 15,i; - if (p != 0) return e("bad DQT type","Corrupt JPEG"); - if (t > 3) return e("bad DQT table","Corrupt JPEG"); - for (i=0; i < 64; ++i) - z->dequant[t][dezigzag[i]] = get8u(&z->s); - #if STBI_SIMD - for (i=0; i < 64; ++i) - z->dequant2[t][i] = z->dequant[t][i]; - #endif - L -= 65; - } - return L==0; - - case 0xC4: // DHT - define huffman table - L = get16(&z->s)-2; - while (L > 0) { - uint8 *v; - int sizes[16],i,m2=0; - int q = get8(&z->s); - int tc = q >> 4; - int th = q & 15; - if (tc > 1 || th > 3) return e("bad DHT header","Corrupt JPEG"); - for (i=0; i < 16; ++i) { - sizes[i] = get8(&z->s); - m2 += sizes[i]; - } - L -= 17; - if (tc == 0) { - if (!build_huffman(z->huff_dc+th, sizes)) return 0; - v = z->huff_dc[th].values; - } else { - if (!build_huffman(z->huff_ac+th, sizes)) return 0; - v = z->huff_ac[th].values; - } - for (i=0; i < m2; ++i) - v[i] = get8u(&z->s); - L -= m2; - } - return L==0; - } - // check for comment block or APP blocks - if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { - skip(&z->s, get16(&z->s)-2); - return 1; - } - return 0; -} - -// after we see SOS -static int process_scan_header(jpeg *z) -{ - int i; - int Ls = get16(&z->s); - z->scan_n = get8(&z->s); - if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s.img_n) return e("bad SOS component count","Corrupt JPEG"); - if (Ls != 6+2*z->scan_n) return e("bad SOS len","Corrupt JPEG"); - for (i=0; i < z->scan_n; ++i) { - int ID = get8(&z->s), which; - int q = get8(&z->s); - for (which = 0; which < z->s.img_n; ++which) - if (z->img_comp[which].id == ID) - break; - if (which == z->s.img_n) return 0; - z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return e("bad DC huff","Corrupt JPEG"); - z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return e("bad AC huff","Corrupt JPEG"); - z->order[i] = which; - } - if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG"); - get8(&z->s); // should be 63, but might be 0 - if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG"); - - return 1; -} - -static int process_frame_header(jpeg *z, int scan) -{ - stbi *s = &z->s; - int Lf,p,i,q, h_max=1,v_max=1,c; - Lf = get16(s); if (Lf < 11) return e("bad SOF len","Corrupt JPEG"); // JPEG - p = get8(s); if (p != 8) return e("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline - s->img_y = get16(s); if (s->img_y == 0) return e("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG - s->img_x = get16(s); if (s->img_x == 0) return e("0 width","Corrupt JPEG"); // JPEG requires - c = get8(s); - if (c != 3 && c != 1) return e("bad component count","Corrupt JPEG"); // JFIF requires - s->img_n = c; - for (i=0; i < c; ++i) { - z->img_comp[i].data = NULL; - z->img_comp[i].linebuf = NULL; - } - - if (Lf != 8+3*s->img_n) return e("bad SOF len","Corrupt JPEG"); - - for (i=0; i < s->img_n; ++i) { - z->img_comp[i].id = get8(s); - if (z->img_comp[i].id != i+1) // JFIF requires - if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! - return e("bad component ID","Corrupt JPEG"); - q = get8(s); - z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return e("bad H","Corrupt JPEG"); - z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return e("bad V","Corrupt JPEG"); - z->img_comp[i].tq = get8(s); if (z->img_comp[i].tq > 3) return e("bad TQ","Corrupt JPEG"); - } - - if (scan != SCAN_load) return 1; - - if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); - - for (i=0; i < s->img_n; ++i) { - if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; - if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; - } - - // compute interleaved mcu info - z->img_h_max = h_max; - z->img_v_max = v_max; - z->img_mcu_w = h_max * 8; - z->img_mcu_h = v_max * 8; - z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; - z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; - - for (i=0; i < s->img_n; ++i) { - // number of effective pixels (e.g. for non-interleaved MCU) - z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; - z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; - // to simplify generation, we'll allocate enough memory to decode - // the bogus oversized data from using interleaved MCUs and their - // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't - // discard the extra data until colorspace conversion - z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; - z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; - z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); - if (z->img_comp[i].raw_data == NULL) { - for(--i; i >= 0; --i) { - free(z->img_comp[i].raw_data); - z->img_comp[i].data = NULL; - } - return e("outofmem", "Out of memory"); - } - // align blocks for installable-idct using mmx/sse - z->img_comp[i].data = (uint8*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); - z->img_comp[i].linebuf = NULL; - } - - return 1; -} - -// use comparisons since in some cases we handle more than one case (e.g. SOF) -#define DNL(x) ((x) == 0xdc) -#define SOI(x) ((x) == 0xd8) -#define EOI(x) ((x) == 0xd9) -#define SOF(x) ((x) == 0xc0 || (x) == 0xc1) -#define SOS(x) ((x) == 0xda) - -static int decode_jpeg_header(jpeg *z, int scan) -{ - int m; - z->marker = MARKER_none; // initialize cached marker to empty - m = get_marker(z); - if (!SOI(m)) return e("no SOI","Corrupt JPEG"); - if (scan == SCAN_type) return 1; - m = get_marker(z); - while (!SOF(m)) { - if (!process_marker(z,m)) return 0; - m = get_marker(z); - while (m == MARKER_none) { - // some files have extra padding after their blocks, so ok, we'll scan - if (at_eof(&z->s)) return e("no SOF", "Corrupt JPEG"); - m = get_marker(z); - } - } - if (!process_frame_header(z, scan)) return 0; - return 1; -} - -static int decode_jpeg_image(jpeg *j) -{ - int m; - j->restart_interval = 0; - if (!decode_jpeg_header(j, SCAN_load)) return 0; - m = get_marker(j); - while (!EOI(m)) { - if (SOS(m)) { - if (!process_scan_header(j)) return 0; - if (!parse_entropy_coded_data(j)) return 0; - } else { - if (!process_marker(j, m)) return 0; - } - m = get_marker(j); - } - return 1; -} - -// static jfif-centered resampling (across block boundaries) - -typedef uint8 *(*resample_row_func)(uint8 *out, uint8 *in0, uint8 *in1, - int w, int hs); - -#define div4(x) ((uint8) ((x) >> 2)) - -static uint8 *resample_row_1(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) -{ - return in_near; -} - -static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) -{ - // need to generate two samples vertically for every one in input - int i; - for (i=0; i < w; ++i) - out[i] = div4(3*in_near[i] + in_far[i] + 2); - return out; -} - -static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) -{ - // need to generate two samples horizontally for every one in input - int i; - uint8 *input = in_near; - if (w == 1) { - // if only one sample, can't do any interpolation - out[0] = out[1] = input[0]; - return out; - } - - out[0] = input[0]; - out[1] = div4(input[0]*3 + input[1] + 2); - for (i=1; i < w-1; ++i) { - int n = 3*input[i]+2; - out[i*2+0] = div4(n+input[i-1]); - out[i*2+1] = div4(n+input[i+1]); - } - out[i*2+0] = div4(input[w-2]*3 + input[w-1] + 2); - out[i*2+1] = input[w-1]; - return out; -} - -#define div16(x) ((uint8) ((x) >> 4)) - -static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) -{ - // need to generate 2x2 samples for every one in input - int i,t0,t1; - if (w == 1) { - out[0] = out[1] = div4(3*in_near[0] + in_far[0] + 2); - return out; - } - - t1 = 3*in_near[0] + in_far[0]; - out[0] = div4(t1+2); - for (i=1; i < w; ++i) { - t0 = t1; - t1 = 3*in_near[i]+in_far[i]; - out[i*2-1] = div16(3*t0 + t1 + 8); - out[i*2 ] = div16(3*t1 + t0 + 8); - } - out[w*2-1] = div4(t1+2); - return out; -} - -static uint8 *resample_row_generic(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) -{ - // resample with nearest-neighbor - int i,j; - for (i=0; i < w; ++i) - for (j=0; j < hs; ++j) - out[i*hs+j] = in_near[i]; - return out; -} - -#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) - -// 0.38 seconds on 3*anemones.jpg (0.25 with processor = Pro) -// VC6 without processor=Pro is generating multiple LEAs per multiply! -static void YCbCr_to_RGB_row(uint8 *out, const uint8 *y, const uint8 *pcb, const uint8 *pcr, int count, int step) -{ - int i; - for (i=0; i < count; ++i) { - int y_fixed = (y[i] << 16) + 32768; // rounding - int r,g,b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr*float2fixed(1.40200f); - g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); - b = y_fixed + cb*float2fixed(1.77200f); - r >>= 16; - g >>= 16; - b >>= 16; - if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } - if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } - if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } - out[0] = (uint8)r; - out[1] = (uint8)g; - out[2] = (uint8)b; - out[3] = 255; - out += step; - } -} - -#if STBI_SIMD -static stbi_YCbCr_to_RGB_run stbi_YCbCr_installed = YCbCr_to_RGB_row; - -void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func) -{ - stbi_YCbCr_installed = func; -} -#endif - - -// clean up the temporary component buffers -static void cleanup_jpeg(jpeg *j) -{ - int i; - for (i=0; i < j->s.img_n; ++i) { - if (j->img_comp[i].data) { - free(j->img_comp[i].raw_data); - j->img_comp[i].data = NULL; - } - if (j->img_comp[i].linebuf) { - free(j->img_comp[i].linebuf); - j->img_comp[i].linebuf = NULL; - } - } -} - -typedef struct -{ - resample_row_func resample; - uint8 *line0,*line1; - int hs,vs; // expansion factor in each axis - int w_lores; // horizontal pixels pre-expansion - int ystep; // how far through vertical expansion we are - int ypos; // which pre-expansion row we're on -} stbi_resample; - -static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) -{ - int n, decode_n; - // validate req_comp - if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); - z->s.img_n = 0; - - // load a jpeg image from whichever source - if (!decode_jpeg_image(z)) { cleanup_jpeg(z); return NULL; } - - // determine actual number of components to generate - n = req_comp ? req_comp : z->s.img_n; - - if (z->s.img_n == 3 && n < 3) - decode_n = 1; - else - decode_n = z->s.img_n; - - // resample and color-convert - { - int k; - uint i,j; - uint8 *output; - uint8 *coutput[4]; - - stbi_resample res_comp[4]; - - for (k=0; k < decode_n; ++k) { - stbi_resample *r = &res_comp[k]; - - // allocate line buffer big enough for upsampling off the edges - // with upsample factor of 4 - z->img_comp[k].linebuf = (uint8 *) malloc(z->s.img_x + 3); - if (!z->img_comp[k].linebuf) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } - - r->hs = z->img_h_max / z->img_comp[k].h; - r->vs = z->img_v_max / z->img_comp[k].v; - r->ystep = r->vs >> 1; - r->w_lores = (z->s.img_x + r->hs-1) / r->hs; - r->ypos = 0; - r->line0 = r->line1 = z->img_comp[k].data; - - if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; - else if (r->hs == 1 && r->vs == 2) r->resample = resample_row_v_2; - else if (r->hs == 2 && r->vs == 1) r->resample = resample_row_h_2; - else if (r->hs == 2 && r->vs == 2) r->resample = resample_row_hv_2; - else r->resample = resample_row_generic; - } - - // can't error after this so, this is safe - output = (uint8 *) malloc(n * z->s.img_x * z->s.img_y + 1); - if (!output) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } - - // now go ahead and resample - for (j=0; j < z->s.img_y; ++j) { - uint8 *out = output + n * z->s.img_x * j; - for (k=0; k < decode_n; ++k) { - stbi_resample *r = &res_comp[k]; - int y_bot = r->ystep >= (r->vs >> 1); - coutput[k] = r->resample(z->img_comp[k].linebuf, - y_bot ? r->line1 : r->line0, - y_bot ? r->line0 : r->line1, - r->w_lores, r->hs); - if (++r->ystep >= r->vs) { - r->ystep = 0; - r->line0 = r->line1; - if (++r->ypos < z->img_comp[k].y) - r->line1 += z->img_comp[k].w2; - } - } - if (n >= 3) { - uint8 *y = coutput[0]; - if (z->s.img_n == 3) { - #if STBI_SIMD - stbi_YCbCr_installed(out, y, coutput[1], coutput[2], z->s.img_x, n); - #else - YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s.img_x, n); - #endif - } else - for (i=0; i < z->s.img_x; ++i) { - out[0] = out[1] = out[2] = y[i]; - out[3] = 255; // not used if n==3 - out += n; - } - } else { - uint8 *y = coutput[0]; - if (n == 1) - for (i=0; i < z->s.img_x; ++i) out[i] = y[i]; - else - for (i=0; i < z->s.img_x; ++i) *out++ = y[i], *out++ = 255; - } - } - cleanup_jpeg(z); - *out_x = z->s.img_x; - *out_y = z->s.img_y; - if (comp) *comp = z->s.img_n; // report original components, not output - return output; - } -} - -#ifndef STBI_NO_STDIO -unsigned char *stbi_jpeg_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - jpeg j; - start_file(&j.s, f); - return load_jpeg_image(&j, x,y,comp,req_comp); -} - -unsigned char *stbi_jpeg_load(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_jpeg_load_from_file(f,x,y,comp,req_comp); - fclose(f); - return data; -} -#endif - -unsigned char *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - jpeg j; - start_mem(&j.s, buffer,len); - return load_jpeg_image(&j, x,y,comp,req_comp); -} - -#ifndef STBI_NO_STDIO -int stbi_jpeg_test_file(FILE *f) -{ - int n,r; - jpeg j; - n = ftell(f); - start_file(&j.s, f); - r = decode_jpeg_header(&j, SCAN_type); - fseek(f,n,SEEK_SET); - return r; -} -#endif - -int stbi_jpeg_test_memory(stbi_uc const *buffer, int len) -{ - jpeg j; - start_mem(&j.s, buffer,len); - return decode_jpeg_header(&j, SCAN_type); -} - -// @TODO: -#ifndef STBI_NO_STDIO -extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp); -extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp); -#endif -extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); - -// public domain zlib decode v0.2 Sean Barrett 2006-11-18 -// simple implementation -// - all input must be provided in an upfront buffer -// - all output is written to a single output buffer (can malloc/realloc) -// performance -// - fast huffman - -// fast-way is faster to check than jpeg huffman, but slow way is slower -#define ZFAST_BITS 9 // accelerate all cases in default tables -#define ZFAST_MASK ((1 << ZFAST_BITS) - 1) - -// zlib-style huffman encoding -// (jpegs packs from left, zlib from right, so can't share code) -typedef struct -{ - uint16 fast[1 << ZFAST_BITS]; - uint16 firstcode[16]; - int maxcode[17]; - uint16 firstsymbol[16]; - uint8 size[288]; - uint16 value[288]; -} zhuffman; - -__forceinline static int bitreverse16(int n) -{ - n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); - n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); - n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); - n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); - return n; -} - -__forceinline static int bit_reverse(int v, int bits) -{ - assert(bits <= 16); - // to bit reverse n bits, reverse 16 and shift - // e.g. 11 bits, bit reverse and shift away 5 - return bitreverse16(v) >> (16-bits); -} - -static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) -{ - int i,k=0; - int code, next_code[16], sizes[17]; - - // DEFLATE spec for generating codes - memset(sizes, 0, sizeof(sizes)); - memset(z->fast, 255, sizeof(z->fast)); - for (i=0; i < num; ++i) - ++sizes[sizelist[i]]; - sizes[0] = 0; - for (i=1; i < 16; ++i) - assert(sizes[i] <= (1 << i)); - code = 0; - for (i=1; i < 16; ++i) { - next_code[i] = code; - z->firstcode[i] = (uint16) code; - z->firstsymbol[i] = (uint16) k; - code = (code + sizes[i]); - if (sizes[i]) - if (code-1 >= (1 << i)) return e("bad codelengths","Corrupt JPEG"); - z->maxcode[i] = code << (16-i); // preshift for inner loop - code <<= 1; - k += sizes[i]; - } - z->maxcode[16] = 0x10000; // sentinel - for (i=0; i < num; ++i) { - int s = sizelist[i]; - if (s) { - int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; - z->size[c] = (uint8)s; - z->value[c] = (uint16)i; - if (s <= ZFAST_BITS) { - int k2 = bit_reverse(next_code[s],s); - while (k2 < (1 << ZFAST_BITS)) { - z->fast[k2] = (uint16) c; - k2 += (1 << s); - } - } - ++next_code[s]; - } - } - return 1; -} - -// zlib-from-memory implementation for PNG reading -// because PNG allows splitting the zlib stream arbitrarily, -// and it's annoying structurally to have PNG call ZLIB call PNG, -// we require PNG read all the IDATs and combine them into a single -// memory buffer - -typedef struct -{ - uint8 *zbuffer, *zbuffer_end; - int num_bits; - uint32 code_buffer; - - char *zout; - char *zout_start; - char *zout_end; - int z_expandable; - - zhuffman z_length, z_distance; -} zbuf; - -__forceinline static int zget8(zbuf *z) -{ - if (z->zbuffer >= z->zbuffer_end) return 0; - return *z->zbuffer++; -} - -static void fill_bits(zbuf *z) -{ - do { - assert(z->code_buffer < (1U << z->num_bits)); - z->code_buffer |= zget8(z) << z->num_bits; - z->num_bits += 8; - } while (z->num_bits <= 24); -} - -__forceinline static unsigned int zreceive(zbuf *z, int n) -{ - unsigned int k; - if (z->num_bits < n) fill_bits(z); - k = z->code_buffer & ((1 << n) - 1); - z->code_buffer >>= n; - z->num_bits -= n; - return k; -} - -__forceinline static int zhuffman_decode(zbuf *a, zhuffman *z) -{ - int b,s,k; - if (a->num_bits < 16) fill_bits(a); - b = z->fast[a->code_buffer & ZFAST_MASK]; - if (b < 0xffff) { - s = z->size[b]; - a->code_buffer >>= s; - a->num_bits -= s; - return z->value[b]; - } - - // not resolved by fast table, so compute it the slow way - // use jpeg approach, which requires MSbits at top - k = bit_reverse(a->code_buffer, 16); - for (s=ZFAST_BITS+1; ; ++s) - if (k < z->maxcode[s]) - break; - if (s == 16) return -1; // invalid code! - // code size is s, so: - b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; - assert(z->size[b] == s); - a->code_buffer >>= s; - a->num_bits -= s; - return z->value[b]; -} - -static int expand(zbuf *z, int n) // need to make room for n bytes -{ - char *q; - int cur, limit; - if (!z->z_expandable) return e("output buffer limit","Corrupt PNG"); - cur = (int) (z->zout - z->zout_start); - limit = (int) (z->zout_end - z->zout_start); - while (cur + n > limit) - limit *= 2; - q = (char *) realloc(z->zout_start, limit); - if (q == NULL) return e("outofmem", "Out of memory"); - z->zout_start = q; - z->zout = q + cur; - z->zout_end = q + limit; - return 1; -} - -static int length_base[31] = { - 3,4,5,6,7,8,9,10,11,13, - 15,17,19,23,27,31,35,43,51,59, - 67,83,99,115,131,163,195,227,258,0,0 }; - -static int length_extra[31]= -{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; - -static int dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, -257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; - -static int dist_extra[32] = -{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -static int parse_huffman_block(zbuf *a) -{ - for(;;) { - int z = zhuffman_decode(a, &a->z_length); - if (z < 256) { - if (z < 0) return e("bad huffman code","Corrupt PNG"); // error in huffman codes - if (a->zout >= a->zout_end) if (!expand(a, 1)) return 0; - *a->zout++ = (char) z; - } else { - uint8 *p; - int len,dist; - if (z == 256) return 1; - z -= 257; - len = length_base[z]; - if (length_extra[z]) len += zreceive(a, length_extra[z]); - z = zhuffman_decode(a, &a->z_distance); - if (z < 0) return e("bad huffman code","Corrupt PNG"); - dist = dist_base[z]; - if (dist_extra[z]) dist += zreceive(a, dist_extra[z]); - if (a->zout - a->zout_start < dist) return e("bad dist","Corrupt PNG"); - if (a->zout + len > a->zout_end) if (!expand(a, len)) return 0; - p = (uint8 *) (a->zout - dist); - while (len--) - *a->zout++ = *p++; - } - } -} - -static int compute_huffman_codes(zbuf *a) -{ - static uint8 length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; - zhuffman z_codelength; - uint8 lencodes[286+32+137];//padding for maximum single op - uint8 codelength_sizes[19]; - int i,n; - - int hlit = zreceive(a,5) + 257; - int hdist = zreceive(a,5) + 1; - int hclen = zreceive(a,4) + 4; - - memset(codelength_sizes, 0, sizeof(codelength_sizes)); - for (i=0; i < hclen; ++i) { - int s = zreceive(a,3); - codelength_sizes[length_dezigzag[i]] = (uint8) s; - } - if (!zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; - - n = 0; - while (n < hlit + hdist) { - int c = zhuffman_decode(a, &z_codelength); - assert(c >= 0 && c < 19); - if (c < 16) - lencodes[n++] = (uint8) c; - else if (c == 16) { - c = zreceive(a,2)+3; - memset(lencodes+n, lencodes[n-1], c); - n += c; - } else if (c == 17) { - c = zreceive(a,3)+3; - memset(lencodes+n, 0, c); - n += c; - } else { - assert(c == 18); - c = zreceive(a,7)+11; - memset(lencodes+n, 0, c); - n += c; - } - } - if (n != hlit+hdist) return e("bad codelengths","Corrupt PNG"); - if (!zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; - if (!zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; - return 1; -} - -static int parse_uncompressed_block(zbuf *a) -{ - uint8 header[4]; - int len,nlen,k; - if (a->num_bits & 7) - zreceive(a, a->num_bits & 7); // discard - // drain the bit-packed data into header - k = 0; - while (a->num_bits > 0) { - header[k++] = (uint8) (a->code_buffer & 255); // wtf this warns? - a->code_buffer >>= 8; - a->num_bits -= 8; - } - assert(a->num_bits == 0); - // now fill header the normal way - while (k < 4) - header[k++] = (uint8) zget8(a); - len = header[1] * 256 + header[0]; - nlen = header[3] * 256 + header[2]; - if (nlen != (len ^ 0xffff)) return e("zlib corrupt","Corrupt PNG"); - if (a->zbuffer + len > a->zbuffer_end) return e("read past buffer","Corrupt PNG"); - if (a->zout + len > a->zout_end) - if (!expand(a, len)) return 0; - memcpy(a->zout, a->zbuffer, len); - a->zbuffer += len; - a->zout += len; - return 1; -} - -static int parse_zlib_header(zbuf *a) -{ - int cmf = zget8(a); - int cm = cmf & 15; - /* int cinfo = cmf >> 4; */ - int flg = zget8(a); - if ((cmf*256+flg) % 31 != 0) return e("bad zlib header","Corrupt PNG"); // zlib spec - if (flg & 32) return e("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png - if (cm != 8) return e("bad compression","Corrupt PNG"); // DEFLATE required for png - // window = 1 << (8 + cinfo)... but who cares, we fully buffer output - return 1; -} - -// @TODO: should statically initialize these for optimal thread safety -static uint8 default_length[288], default_distance[32]; -static void init_defaults(void) -{ - int i; // use <= to match clearly with spec - for (i=0; i <= 143; ++i) default_length[i] = 8; - for ( ; i <= 255; ++i) default_length[i] = 9; - for ( ; i <= 279; ++i) default_length[i] = 7; - for ( ; i <= 287; ++i) default_length[i] = 8; - - for (i=0; i <= 31; ++i) default_distance[i] = 5; -} - -int stbi_png_partial; // a quick hack to only allow decoding some of a PNG... I should implement real streaming support instead -static int parse_zlib(zbuf *a, int parse_header) -{ - int final, type; - if (parse_header) - if (!parse_zlib_header(a)) return 0; - a->num_bits = 0; - a->code_buffer = 0; - do { - final = zreceive(a,1); - type = zreceive(a,2); - if (type == 0) { - if (!parse_uncompressed_block(a)) return 0; - } else if (type == 3) { - return 0; - } else { - if (type == 1) { - // use fixed code lengths - if (!default_distance[31]) init_defaults(); - if (!zbuild_huffman(&a->z_length , default_length , 288)) return 0; - if (!zbuild_huffman(&a->z_distance, default_distance, 32)) return 0; - } else { - if (!compute_huffman_codes(a)) return 0; - } - if (!parse_huffman_block(a)) return 0; - } - if (stbi_png_partial && a->zout - a->zout_start > 65536) - break; - } while (!final); - return 1; -} - -static int do_zlib(zbuf *a, char *obuf, int olen, int expandable, int parse_header) -{ - a->zout_start = obuf; - a->zout = obuf; - a->zout_end = obuf + olen; - a->z_expandable = expandable; - - return parse_zlib(a, parse_header); -} - -char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) -{ - zbuf a; - char *p = (char *) malloc(initial_size); - if (p == NULL) return NULL; - a.zbuffer = (uint8 *) buffer; - a.zbuffer_end = (uint8 *) buffer + len; - if (do_zlib(&a, p, initial_size, 1, 1)) { - if (outlen) *outlen = (int) (a.zout - a.zout_start); - return a.zout_start; - } else { - free(a.zout_start); - return NULL; - } -} - -char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) -{ - return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); -} - -int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) -{ - zbuf a; - a.zbuffer = (uint8 *) ibuffer; - a.zbuffer_end = (uint8 *) ibuffer + ilen; - if (do_zlib(&a, obuffer, olen, 0, 1)) - return (int) (a.zout - a.zout_start); - else - return -1; -} - -char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) -{ - zbuf a; - char *p = (char *) malloc(16384); - if (p == NULL) return NULL; - a.zbuffer = (uint8 *) buffer; - a.zbuffer_end = (uint8 *) buffer+len; - if (do_zlib(&a, p, 16384, 1, 0)) { - if (outlen) *outlen = (int) (a.zout - a.zout_start); - return a.zout_start; - } else { - free(a.zout_start); - return NULL; - } -} - -int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) -{ - zbuf a; - a.zbuffer = (uint8 *) ibuffer; - a.zbuffer_end = (uint8 *) ibuffer + ilen; - if (do_zlib(&a, obuffer, olen, 0, 0)) - return (int) (a.zout - a.zout_start); - else - return -1; -} - -// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 -// simple implementation -// - only 8-bit samples -// - no CRC checking -// - allocates lots of intermediate memory -// - avoids problem of streaming data between subsystems -// - avoids explicit window management -// performance -// - uses stb_zlib, a PD zlib implementation with fast huffman decoding - - -typedef struct -{ - uint32 length; - uint32 type; -} chunk; - -#define PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) - -static chunk get_chunk_header(stbi *s) -{ - chunk c; - c.length = get32(s); - c.type = get32(s); - return c; -} - -static int check_png_header(stbi *s) -{ - static uint8 png_sig[8] = { 137,80,78,71,13,10,26,10 }; - int i; - for (i=0; i < 8; ++i) - if (get8(s) != png_sig[i]) return e("bad png sig","Not a PNG"); - return 1; -} - -typedef struct -{ - stbi s; - uint8 *idata, *expanded, *out; -} png; - - -enum { - F_none=0, F_sub=1, F_up=2, F_avg=3, F_paeth=4, - F_avg_first, F_paeth_first, -}; - -static uint8 first_row_filter[5] = -{ - F_none, F_sub, F_none, F_avg_first, F_paeth_first -}; - -static int paeth(int a, int b, int c) -{ - int p = a + b - c; - int pa = abs(p-a); - int pb = abs(p-b); - int pc = abs(p-c); - if (pa <= pb && pa <= pc) return a; - if (pb <= pc) return b; - return c; -} - -// create the png data from post-deflated data -static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, uint32 x, uint32 y) -{ - stbi *s = &a->s; - uint32 i,j,stride = x*out_n; - int k; - int img_n = s->img_n; // copy it into a local for later - assert(out_n == s->img_n || out_n == s->img_n+1); - if (stbi_png_partial) y = 1; - a->out = (uint8 *) malloc(x * y * out_n); - if (!a->out) return e("outofmem", "Out of memory"); - if (!stbi_png_partial) { - if (s->img_x == x && s->img_y == y) { +} +#endif + +static void start_mem(stbi *s, uint8 const *buffer, int len) +{ +#ifndef STBI_NO_STDIO + s->img_file = NULL; +#endif + s->img_buffer = (uint8 *) buffer; + s->img_buffer_end = (uint8 *) buffer+len; +} + +__forceinline static int get8(stbi *s) +{ +#ifndef STBI_NO_STDIO + if (s->img_file) { + int c = fgetc(s->img_file); + return c == EOF ? 0 : c; + } +#endif + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + return 0; +} + +__forceinline static int at_eof(stbi *s) +{ +#ifndef STBI_NO_STDIO + if (s->img_file) + return feof(s->img_file); +#endif + return s->img_buffer >= s->img_buffer_end; +} + +__forceinline static uint8 get8u(stbi *s) +{ + return (uint8) get8(s); +} + +static void skip(stbi *s, int n) +{ +#ifndef STBI_NO_STDIO + if (s->img_file) + fseek(s->img_file, n, SEEK_CUR); + else +#endif + s->img_buffer += n; +} + +static uint16 get16(stbi *s) +{ + int z = get8(s); + return (z << 8) + get8(s); +} + +static uint32 get32(stbi *s) +{ + uint32 z = get16(s); + return (z << 16) + get16(s); +} + +static uint16 get16le(stbi *s) +{ + int z = get8(s); + return z + (get8(s) << 8); +} + +static uint32 get32le(stbi *s) +{ + uint32 z = get16le(s); + return z + (get16le(s) << 16); +} + +static void getn(stbi *s, stbi_uc *buffer, int n) +{ +#ifndef STBI_NO_STDIO + if (s->img_file) { + fread(buffer, 1, n, s->img_file); + return; + } +#endif + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; +} + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static uint8 compute_y(int r, int g, int b) +{ + return (uint8) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *convert_format(unsigned char *data, int img_n, int req_comp, uint x, uint y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + assert(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) malloc(req_comp * x * y); + if (good == NULL) { + free(data); + return epuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define COMBO(a,b) ((a)*8+(b)) + #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch(COMBO(img_n, req_comp)) { + CASE(1,2) dest[0]=src[0], dest[1]=255; break; + CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; + CASE(2,1) dest[0]=src[0]; break; + CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; + CASE(3,1) dest[0]=compute_y(src[0],src[1],src[2]); break; + CASE(3,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = 255; break; + CASE(4,1) dest[0]=compute_y(src[0],src[1],src[2]); break; + CASE(4,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; + CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + default: assert(0); + } + #undef CASE + } + + free(data); + return good; +} + +#ifndef STBI_NO_HDR +static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output = (float *) malloc(x * y * comp * sizeof(float)); + if (output == NULL) { free(data); return epf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) pow(data[i*comp+k]/255.0f, l2h_gamma) * l2h_scale; + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + free(data); + return output; +} + +#define float2int(x) ((int) (x)) +static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output = (stbi_uc *) malloc(x * y * comp); + if (output == NULL) { free(data); return epuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*h2l_scale_i, h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = float2int(z); + } + } + free(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder (not actually fully baseline implementation) +// +// simple implementation +// - channel subsampling of at most 2 in each dimension +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - uses a lot of intermediate memory, could cache poorly +// - load http://nothings.org/remote/anemones.jpg 3 times on 2.8Ghz P4 +// stb_jpeg: 1.34 seconds (MSVC6, default release build) +// stb_jpeg: 1.06 seconds (MSVC6, processor = Pentium Pro) +// IJL11.dll: 1.08 seconds (compiled by intel) +// IJG 1998: 0.98 seconds (MSVC6, makefile provided by IJG) +// IJG 1998: 0.95 seconds (MSVC6, makefile + proc=PPro) + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + uint8 fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + uint16 code[256]; + uint8 values[256]; + uint8 size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} huffman; + +typedef struct +{ + #if STBI_SIMD + unsigned short dequant2[4][64]; + #endif + stbi s; + huffman huff_dc[4]; + huffman huff_ac[4]; + uint8 dequant[4][64]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + uint8 *data; + void *raw_data; + uint8 *linebuf; + } img_comp[4]; + + uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int scan_n, order[4]; + int restart_interval, todo; +} jpeg; + +static int build_huffman(huffman *h, int *count) +{ + int i,j,k=0,code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (uint8) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (uint16) (code++); + if (code-1 >= (1 << j)) return e("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (uint8) i; + } + } + } + return 1; +} + +static void grow_buffer_unsafe(jpeg *j) +{ + do { + int b = j->nomore ? 0 : get8(&j->s); + if (b == 0xff) { + int c = get8(&j->s); + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer = (j->code_buffer << 8) | b; + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static uint32 bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +__forceinline static int decode(jpeg *j, huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (j->code_bits - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + if (h->size[k] > j->code_bits) + return -1; + j->code_bits -= h->size[k]; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + if (j->code_bits < 16) + temp = (j->code_buffer << (16 - j->code_bits)) & 0xffff; + else + temp = (j->code_buffer >> (j->code_bits - 16)) & 0xffff; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (j->code_bits - k)) & bmask[k]) + h->delta[k]; + assert((((j->code_buffer) >> (j->code_bits - h->size[c])) & bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + return h->values[c]; +} + +// combined JPEG 'receive' and JPEG 'extend', since baseline +// always extends everything it receives. +__forceinline static int extend_receive(jpeg *j, int n) +{ + unsigned int m = 1 << (n-1); + unsigned int k; + if (j->code_bits < n) grow_buffer_unsafe(j); + k = (j->code_buffer >> (j->code_bits - n)) & bmask[n]; + j->code_bits -= n; + // the following test is probably a random branch that won't + // predict well. I tried to table accelerate it but failed. + // maybe it's compiling as a conditional move? + if (k < m) + return (-1 << n) + k + 1; + else + return k; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static uint8 dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int decode_block(jpeg *j, short data[64], huffman *hdc, huffman *hac, int b) +{ + int diff,dc,k; + int t = decode(j, hdc); + if (t < 0) return e("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) dc; + + // decode AC components, see JPEG spec + k = 1; + do { + int r,s; + int rs = decode(j, hac); + if (rs < 0) return e("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + data[dezigzag[k++]] = (short) extend_receive(j,s); + } + } while (k < 64); + return 1; +} + +// take a -128..127 value and clamp it and convert to 0..255 +__forceinline static uint8 clamp(int x) +{ + x += 128; + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (uint8) x; +} + +#define f2f(x) (int) (((x) * 4096 + 0.5)) +#define fsh(x) ((x) << 12) + +// derived from jidctint -- DCT_ISLOW +#define IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * f2f(0.5411961f); \ + t2 = p1 + p3*f2f(-1.847759065f); \ + t3 = p1 + p2*f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = fsh(p2+p3); \ + t1 = fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*f2f( 1.175875602f); \ + t0 = t0*f2f( 0.298631336f); \ + t1 = t1*f2f( 2.053119869f); \ + t2 = t2*f2f( 3.072711026f); \ + t3 = t3*f2f( 1.501321110f); \ + p1 = p5 + p1*f2f(-0.899976223f); \ + p2 = p5 + p2*f2f(-2.562915447f); \ + p3 = p3*f2f(-1.961570560f); \ + p4 = p4*f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +#if !STBI_SIMD +// .344 seconds on 3*anemones.jpg +static void idct_block(uint8 *out, int out_stride, short data[64], uint8 *dequantize) +{ + int i,val[64],*v=val; + uint8 *o,*dq = dequantize; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d,++dq, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] * dq[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24], + d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + x0 += 65536; x1 += 65536; x2 += 65536; x3 += 65536; + o[0] = clamp((x0+t3) >> 17); + o[7] = clamp((x0-t3) >> 17); + o[1] = clamp((x1+t2) >> 17); + o[6] = clamp((x1-t2) >> 17); + o[2] = clamp((x2+t1) >> 17); + o[5] = clamp((x2-t1) >> 17); + o[3] = clamp((x3+t0) >> 17); + o[4] = clamp((x3-t0) >> 17); + } +} +#else +static void idct_block(uint8 *out, int out_stride, short data[64], unsigned short *dequantize) +{ + int i,val[64],*v=val; + uint8 *o; + unsigned short *dq = dequantize; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d,++dq, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] * dq[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24], + d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + x0 += 65536; x1 += 65536; x2 += 65536; x3 += 65536; + o[0] = clamp((x0+t3) >> 17); + o[7] = clamp((x0-t3) >> 17); + o[1] = clamp((x1+t2) >> 17); + o[6] = clamp((x1-t2) >> 17); + o[2] = clamp((x2+t1) >> 17); + o[5] = clamp((x2-t1) >> 17); + o[3] = clamp((x3+t0) >> 17); + o[4] = clamp((x3-t0) >> 17); + } +} +static stbi_idct_8x8 stbi_idct_installed = idct_block; + +extern void stbi_install_idct(stbi_idct_8x8 func) +{ + stbi_idct_installed = func; +} +#endif + +#define MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static uint8 get_marker(jpeg *j) +{ + uint8 x; + if (j->marker != MARKER_none) { x = j->marker; j->marker = MARKER_none; return x; } + x = get8u(&j->s); + if (x != 0xff) return MARKER_none; + while (x == 0xff) + x = get8u(&j->s); + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, reset the entropy decoder and +// the dc prediction +static void reset(jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->marker = MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int parse_entropy_coded_data(jpeg *z) +{ + reset(z); + if (z->scan_n == 1) { + int i,j; + #if STBI_SIMD + __declspec(align(16)) + #endif + short data[64]; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #if STBI_SIMD + stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + idct_block(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!RESTART(z->marker)) return 1; + reset(z); + } + } + } + } else { // interleaved! + int i,j,k,x,y; + short data[64]; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #if STBI_SIMD + stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + idct_block(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!RESTART(z->marker)) return 1; + reset(z); + } + } + } + } + return 1; +} + +static int process_marker(jpeg *z, int m) +{ + int L; + switch (m) { + case MARKER_none: // no marker found + return e("expected marker","Corrupt JPEG"); + + case 0xC2: // SOF - progressive + return e("progressive jpeg","JPEG format not supported (progressive)"); + + case 0xDD: // DRI - specify restart interval + if (get16(&z->s) != 4) return e("bad DRI len","Corrupt JPEG"); + z->restart_interval = get16(&z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = get16(&z->s)-2; + while (L > 0) { + int q = get8(&z->s); + int p = q >> 4; + int t = q & 15,i; + if (p != 0) return e("bad DQT type","Corrupt JPEG"); + if (t > 3) return e("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) + z->dequant[t][dezigzag[i]] = get8u(&z->s); + #if STBI_SIMD + for (i=0; i < 64; ++i) + z->dequant2[t][i] = z->dequant[t][i]; + #endif + L -= 65; + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = get16(&z->s)-2; + while (L > 0) { + uint8 *v; + int sizes[16],i,m2=0; + int q = get8(&z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return e("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = get8(&z->s); + m2 += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < m2; ++i) + v[i] = get8u(&z->s); + L -= m2; + } + return L==0; + } + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + skip(&z->s, get16(&z->s)-2); + return 1; + } + return 0; +} + +// after we see SOS +static int process_scan_header(jpeg *z) +{ + int i; + int Ls = get16(&z->s); + z->scan_n = get8(&z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s.img_n) return e("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return e("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int ID = get8(&z->s), which; + int q = get8(&z->s); + for (which = 0; which < z->s.img_n; ++which) + if (z->img_comp[which].id == ID) + break; + if (which == z->s.img_n) return 0; + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return e("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return e("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG"); + get8(&z->s); // should be 63, but might be 0 + if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG"); + + return 1; +} + +static int process_frame_header(jpeg *z, int scan) +{ + stbi *s = &z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = get16(s); if (Lf < 11) return e("bad SOF len","Corrupt JPEG"); // JPEG + p = get8(s); if (p != 8) return e("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = get16(s); if (s->img_y == 0) return e("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = get16(s); if (s->img_x == 0) return e("0 width","Corrupt JPEG"); // JPEG requires + c = get8(s); + if (c != 3 && c != 1) return e("bad component count","Corrupt JPEG"); // JFIF requires + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return e("bad SOF len","Corrupt JPEG"); + + for (i=0; i < s->img_n; ++i) { + z->img_comp[i].id = get8(s); + if (z->img_comp[i].id != i+1) // JFIF requires + if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! + return e("bad component ID","Corrupt JPEG"); + q = get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return e("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return e("bad V","Corrupt JPEG"); + z->img_comp[i].tq = get8(s); if (z->img_comp[i].tq > 3) return e("bad TQ","Corrupt JPEG"); + } + + if (scan != SCAN_load) return 1; + + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + if (z->img_comp[i].raw_data == NULL) { + for(--i; i >= 0; --i) { + free(z->img_comp[i].raw_data); + z->img_comp[i].data = NULL; + } + return e("outofmem", "Out of memory"); + } + // align blocks for installable-idct using mmx/sse + z->img_comp[i].data = (uint8*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].linebuf = NULL; + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define DNL(x) ((x) == 0xdc) +#define SOI(x) ((x) == 0xd8) +#define EOI(x) ((x) == 0xd9) +#define SOF(x) ((x) == 0xc0 || (x) == 0xc1) +#define SOS(x) ((x) == 0xda) + +static int decode_jpeg_header(jpeg *z, int scan) +{ + int m; + z->marker = MARKER_none; // initialize cached marker to empty + m = get_marker(z); + if (!SOI(m)) return e("no SOI","Corrupt JPEG"); + if (scan == SCAN_type) return 1; + m = get_marker(z); + while (!SOF(m)) { + if (!process_marker(z,m)) return 0; + m = get_marker(z); + while (m == MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (at_eof(&z->s)) return e("no SOF", "Corrupt JPEG"); + m = get_marker(z); + } + } + if (!process_frame_header(z, scan)) return 0; + return 1; +} + +static int decode_jpeg_image(jpeg *j) +{ + int m; + j->restart_interval = 0; + if (!decode_jpeg_header(j, SCAN_load)) return 0; + m = get_marker(j); + while (!EOI(m)) { + if (SOS(m)) { + if (!process_scan_header(j)) return 0; + if (!parse_entropy_coded_data(j)) return 0; + } else { + if (!process_marker(j, m)) return 0; + } + m = get_marker(j); + } + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef uint8 *(*resample_row_func)(uint8 *out, uint8 *in0, uint8 *in1, + int w, int hs); + +#define div4(x) ((uint8) ((x) >> 2)) + +static uint8 *resample_row_1(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + return in_near; +} + +static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + for (i=0; i < w; ++i) + out[i] = div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + uint8 *input = in_near; + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = div4(n+input[i-1]); + out[i*2+1] = div4(n+input[i+1]); + } + out[i*2+0] = div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + return out; +} + +#define div16(x) ((uint8) ((x) >> 4)) + +static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = div16(3*t0 + t1 + 8); + out[i*2 ] = div16(3*t1 + t0 + 8); + } + out[w*2-1] = div4(t1+2); + return out; +} + +static uint8 *resample_row_generic(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) + +// 0.38 seconds on 3*anemones.jpg (0.25 with processor = Pro) +// VC6 without processor=Pro is generating multiple LEAs per multiply! +static void YCbCr_to_RGB_row(uint8 *out, const uint8 *y, const uint8 *pcb, const uint8 *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 16) + 32768; // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr*float2fixed(1.40200f); + g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); + b = y_fixed + cb*float2fixed(1.77200f); + r >>= 16; + g >>= 16; + b >>= 16; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (uint8)r; + out[1] = (uint8)g; + out[2] = (uint8)b; + out[3] = 255; + out += step; + } +} + +#if STBI_SIMD +static stbi_YCbCr_to_RGB_run stbi_YCbCr_installed = YCbCr_to_RGB_row; + +void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func) +{ + stbi_YCbCr_installed = func; +} +#endif + + +// clean up the temporary component buffers +static void cleanup_jpeg(jpeg *j) +{ + int i; + for (i=0; i < j->s.img_n; ++i) { + if (j->img_comp[i].data) { + free(j->img_comp[i].raw_data); + j->img_comp[i].data = NULL; + } + if (j->img_comp[i].linebuf) { + free(j->img_comp[i].linebuf); + j->img_comp[i].linebuf = NULL; + } + } +} + +typedef struct +{ + resample_row_func resample; + uint8 *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi_resample; + +static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n; + // validate req_comp + if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); + z->s.img_n = 0; + + // load a jpeg image from whichever source + if (!decode_jpeg_image(z)) { cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s.img_n; + + if (z->s.img_n == 3 && n < 3) + decode_n = 1; + else + decode_n = z->s.img_n; + + // resample and color-convert + { + int k; + uint i,j; + uint8 *output; + uint8 *coutput[4]; + + stbi_resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi_resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (uint8 *) malloc(z->s.img_x + 3); + if (!z->img_comp[k].linebuf) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s.img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = resample_row_hv_2; + else r->resample = resample_row_generic; + } + + // can't error after this so, this is safe + output = (uint8 *) malloc(n * z->s.img_x * z->s.img_y + 1); + if (!output) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s.img_y; ++j) { + uint8 *out = output + n * z->s.img_x * j; + for (k=0; k < decode_n; ++k) { + stbi_resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + uint8 *y = coutput[0]; + if (z->s.img_n == 3) { + #if STBI_SIMD + stbi_YCbCr_installed(out, y, coutput[1], coutput[2], z->s.img_x, n); + #else + YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s.img_x, n); + #endif + } else + for (i=0; i < z->s.img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + uint8 *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s.img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s.img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + cleanup_jpeg(z); + *out_x = z->s.img_x; + *out_y = z->s.img_y; + if (comp) *comp = z->s.img_n; // report original components, not output + return output; + } +} + +#ifndef STBI_NO_STDIO +unsigned char *stbi_jpeg_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + jpeg j; + start_file(&j.s, f); + return load_jpeg_image(&j, x,y,comp,req_comp); +} + +unsigned char *stbi_jpeg_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_jpeg_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return data; +} +#endif + +unsigned char *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + jpeg j; + start_mem(&j.s, buffer,len); + return load_jpeg_image(&j, x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +int stbi_jpeg_test_file(FILE *f) +{ + int n,r; + jpeg j; + n = ftell(f); + start_file(&j.s, f); + r = decode_jpeg_header(&j, SCAN_type); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_jpeg_test_memory(stbi_uc const *buffer, int len) +{ + jpeg j; + start_mem(&j.s, buffer,len); + return decode_jpeg_header(&j, SCAN_type); +} + +// @TODO: +#ifndef STBI_NO_STDIO +extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp); +#endif +extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define ZFAST_BITS 9 // accelerate all cases in default tables +#define ZFAST_MASK ((1 << ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + uint16 fast[1 << ZFAST_BITS]; + uint16 firstcode[16]; + int maxcode[17]; + uint16 firstsymbol[16]; + uint8 size[288]; + uint16 value[288]; +} zhuffman; + +__forceinline static int bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +__forceinline static int bit_reverse(int v, int bits) +{ + assert(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return bitreverse16(v) >> (16-bits); +} + +static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 255, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + assert(sizes[i] <= (1 << i)); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (uint16) code; + z->firstsymbol[i] = (uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return e("bad codelengths","Corrupt JPEG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + z->size[c] = (uint8)s; + z->value[c] = (uint16)i; + if (s <= ZFAST_BITS) { + int k2 = bit_reverse(next_code[s],s); + while (k2 < (1 << ZFAST_BITS)) { + z->fast[k2] = (uint16) c; + k2 += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + uint8 *zbuffer, *zbuffer_end; + int num_bits; + uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + zhuffman z_length, z_distance; +} zbuf; + +__forceinline static int zget8(zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void fill_bits(zbuf *z) +{ + do { + assert(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +__forceinline static unsigned int zreceive(zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +__forceinline static int zhuffman_decode(zbuf *a, zhuffman *z) +{ + int b,s,k; + if (a->num_bits < 16) fill_bits(a); + b = z->fast[a->code_buffer & ZFAST_MASK]; + if (b < 0xffff) { + s = z->size[b]; + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; + } + + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = bit_reverse(a->code_buffer, 16); + for (s=ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + assert(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +static int expand(zbuf *z, int n) // need to make room for n bytes +{ + char *q; + int cur, limit; + if (!z->z_expandable) return e("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) realloc(z->zout_start, limit); + if (q == NULL) return e("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static int length_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static int length_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static int dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static int dist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int parse_huffman_block(zbuf *a) +{ + for(;;) { + int z = zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return e("bad huffman code","Corrupt PNG"); // error in huffman codes + if (a->zout >= a->zout_end) if (!expand(a, 1)) return 0; + *a->zout++ = (char) z; + } else { + uint8 *p; + int len,dist; + if (z == 256) return 1; + z -= 257; + len = length_base[z]; + if (length_extra[z]) len += zreceive(a, length_extra[z]); + z = zhuffman_decode(a, &a->z_distance); + if (z < 0) return e("bad huffman code","Corrupt PNG"); + dist = dist_base[z]; + if (dist_extra[z]) dist += zreceive(a, dist_extra[z]); + if (a->zout - a->zout_start < dist) return e("bad dist","Corrupt PNG"); + if (a->zout + len > a->zout_end) if (!expand(a, len)) return 0; + p = (uint8 *) (a->zout - dist); + while (len--) + *a->zout++ = *p++; + } + } +} + +static int compute_huffman_codes(zbuf *a) +{ + static uint8 length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + zhuffman z_codelength; + uint8 lencodes[286+32+137];//padding for maximum single op + uint8 codelength_sizes[19]; + int i,n; + + int hlit = zreceive(a,5) + 257; + int hdist = zreceive(a,5) + 1; + int hclen = zreceive(a,4) + 4; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (uint8) s; + } + if (!zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < hlit + hdist) { + int c = zhuffman_decode(a, &z_codelength); + assert(c >= 0 && c < 19); + if (c < 16) + lencodes[n++] = (uint8) c; + else if (c == 16) { + c = zreceive(a,2)+3; + memset(lencodes+n, lencodes[n-1], c); + n += c; + } else if (c == 17) { + c = zreceive(a,3)+3; + memset(lencodes+n, 0, c); + n += c; + } else { + assert(c == 18); + c = zreceive(a,7)+11; + memset(lencodes+n, 0, c); + n += c; + } + } + if (n != hlit+hdist) return e("bad codelengths","Corrupt PNG"); + if (!zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int parse_uncompressed_block(zbuf *a) +{ + uint8 header[4]; + int len,nlen,k; + if (a->num_bits & 7) + zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (uint8) (a->code_buffer & 255); // wtf this warns? + a->code_buffer >>= 8; + a->num_bits -= 8; + } + assert(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = (uint8) zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return e("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return e("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!expand(a, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int parse_zlib_header(zbuf *a) +{ + int cmf = zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = zget8(a); + if ((cmf*256+flg) % 31 != 0) return e("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return e("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return e("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +// @TODO: should statically initialize these for optimal thread safety +static uint8 default_length[288], default_distance[32]; +static void init_defaults(void) +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) default_length[i] = 8; + for ( ; i <= 255; ++i) default_length[i] = 9; + for ( ; i <= 279; ++i) default_length[i] = 7; + for ( ; i <= 287; ++i) default_length[i] = 8; + + for (i=0; i <= 31; ++i) default_distance[i] = 5; +} + +int stbi_png_partial; // a quick hack to only allow decoding some of a PNG... I should implement real streaming support instead +static int parse_zlib(zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = zreceive(a,1); + type = zreceive(a,2); + if (type == 0) { + if (!parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!default_distance[31]) init_defaults(); + if (!zbuild_huffman(&a->z_length , default_length , 288)) return 0; + if (!zbuild_huffman(&a->z_distance, default_distance, 32)) return 0; + } else { + if (!compute_huffman_codes(a)) return 0; + } + if (!parse_huffman_block(a)) return 0; + } + if (stbi_png_partial && a->zout - a->zout_start > 65536) + break; + } while (!final); + return 1; +} + +static int do_zlib(zbuf *a, char *obuf, int olen, int expandable, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = expandable; + + return parse_zlib(a, parse_header); +} + +char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + zbuf a; + char *p = (char *) malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer + len; + if (do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + zbuf a; + a.zbuffer = (uint8 *) ibuffer; + a.zbuffer_end = (uint8 *) ibuffer + ilen; + if (do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + zbuf a; + char *p = (char *) malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer+len; + if (do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + zbuf a; + a.zbuffer = (uint8 *) ibuffer; + a.zbuffer_end = (uint8 *) ibuffer + ilen; + if (do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + + +typedef struct +{ + uint32 length; + uint32 type; +} chunk; + +#define PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +static chunk get_chunk_header(stbi *s) +{ + chunk c; + c.length = get32(s); + c.type = get32(s); + return c; +} + +static int check_png_header(stbi *s) +{ + static uint8 png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (get8(s) != png_sig[i]) return e("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi s; + uint8 *idata, *expanded, *out; +} png; + + +enum { + F_none=0, F_sub=1, F_up=2, F_avg=3, F_paeth=4, + F_avg_first, F_paeth_first, +}; + +static uint8 first_row_filter[5] = +{ + F_none, F_sub, F_none, F_avg_first, F_paeth_first +}; + +static int paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +// create the png data from post-deflated data +static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, uint32 x, uint32 y) +{ + stbi *s = &a->s; + uint32 i,j,stride = x*out_n; + int k; + int img_n = s->img_n; // copy it into a local for later + assert(out_n == s->img_n || out_n == s->img_n+1); + if (stbi_png_partial) y = 1; + a->out = (uint8 *) malloc(x * y * out_n); + if (!a->out) return e("outofmem", "Out of memory"); + if (!stbi_png_partial) { + if (s->img_x == x && s->img_y == y) { if (raw_len != (img_n * x + 1) * y) - return e("not enough pixels","Corrupt PNG"); - } else { // interlaced: + return e("not enough pixels","Corrupt PNG"); + } else { // interlaced: if (raw_len < (img_n * x + 1) * y) - return e("not enough pixels","Corrupt PNG"); + return e("not enough pixels","Corrupt PNG"); + } + } + for (j=0; j < y; ++j) { + uint8 *cur = a->out + stride*j; + uint8 *prior = cur - stride; + int filter = *raw++; + if (filter > 4) return e("invalid filter","Corrupt PNG"); + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + // handle first pixel explicitly + for (k=0; k < img_n; ++k) { + switch(filter) { + case F_none : cur[k] = raw[k]; break; + case F_sub : cur[k] = raw[k]; break; + case F_up : cur[k] = raw[k] + prior[k]; break; + case F_avg : cur[k] = raw[k] + (prior[k]>>1); break; + case F_paeth : cur[k] = (uint8) (raw[k] + paeth(0,prior[k],0)); break; + case F_avg_first : cur[k] = raw[k]; break; + case F_paeth_first: cur[k] = raw[k]; break; + } + } + if (img_n != out_n) cur[img_n] = 255; + raw += img_n; + cur += out_n; + prior += out_n; + // this is a little gross, so that we don't switch per-pixel or per-component + if (img_n == out_n) { + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, raw+=img_n,cur+=img_n,prior+=img_n) \ + for (k=0; k < img_n; ++k) + switch(filter) { + CASE(F_none) cur[k] = raw[k]; break; + CASE(F_sub) cur[k] = raw[k] + cur[k-img_n]; break; + CASE(F_up) cur[k] = raw[k] + prior[k]; break; + CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-img_n])>>1); break; + CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],prior[k],prior[k-img_n])); break; + CASE(F_avg_first) cur[k] = raw[k] + (cur[k-img_n] >> 1); break; + CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],0,0)); break; + } + #undef CASE + } else { + assert(img_n+1 == out_n); + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ + for (k=0; k < img_n; ++k) + switch(filter) { + CASE(F_none) cur[k] = raw[k]; break; + CASE(F_sub) cur[k] = raw[k] + cur[k-out_n]; break; + CASE(F_up) cur[k] = raw[k] + prior[k]; break; + CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-out_n])>>1); break; + CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; + CASE(F_avg_first) cur[k] = raw[k] + (cur[k-out_n] >> 1); break; + CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],0,0)); break; + } + #undef CASE + } + } + return 1; +} + +static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int interlaced) +{ + uint8 *final; + int p; + int save; + if (!interlaced) + return create_png_image_raw(a, raw, raw_len, out_n, a->s.img_x, a->s.img_y); + save = stbi_png_partial; + stbi_png_partial = 0; + + // de-interlacing + final = (uint8 *) malloc(a->s.img_x * a->s.img_y * out_n); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s.img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s.img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + if (!create_png_image_raw(a, raw, raw_len, out_n, x, y)) { + free(final); + return 0; + } + for (j=0; j < y; ++j) + for (i=0; i < x; ++i) + memcpy(final + (j*yspc[p]+yorig[p])*a->s.img_x*out_n + (i*xspc[p]+xorig[p])*out_n, + a->out + (j*x+i)*out_n, out_n); + free(a->out); + raw += (x*out_n+1)*y; + raw_len -= (x*out_n+1)*y; + } + } + a->out = final; + + stbi_png_partial = save; + return 1; +} + +static int compute_transparency(png *z, uint8 tc[3], int out_n) +{ + stbi *s = &z->s; + uint32 i, pixel_count = s->img_x * s->img_y; + uint8 *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + assert(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int expand_palette(png *a, uint8 *palette, int len, int pal_img_n) +{ + uint32 i, pixel_count = a->s.img_x * a->s.img_y; + uint8 *p, *temp_out, *orig = a->out; + + p = (uint8 *) malloc(pixel_count * pal_img_n); + if (p == NULL) return e("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + free(a->out); + a->out = temp_out; + return 1; +} + +static int parse_png_file(png *z, int scan, int req_comp) +{ + uint8 palette[1024], pal_img_n=0; + uint8 has_trans=0, tc[3]; + uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0; + stbi *s = &z->s; + + if (!check_png_header(s)) return 0; + + if (scan == SCAN_type) return 1; + + for(;;first=0) { + chunk c = get_chunk_header(s); + if (first && c.type != PNG_TYPE('I','H','D','R')) + return e("first not IHDR","Corrupt PNG"); + switch (c.type) { + case PNG_TYPE('I','H','D','R'): { + int depth,color,comp,filter; + if (!first) return e("multiple IHDR","Corrupt PNG"); + if (c.length != 13) return e("bad IHDR len","Corrupt PNG"); + s->img_x = get32(s); if (s->img_x > (1 << 24)) return e("too large","Very large image (corrupt?)"); + s->img_y = get32(s); if (s->img_y > (1 << 24)) return e("too large","Very large image (corrupt?)"); + depth = get8(s); if (depth != 8) return e("8bit only","PNG not supported: 8-bit only"); + color = get8(s); if (color > 6) return e("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return e("bad ctype","Corrupt PNG"); + comp = get8(s); if (comp) return e("bad comp method","Corrupt PNG"); + filter= get8(s); if (filter) return e("bad filter method","Corrupt PNG"); + interlace = get8(s); if (interlace>1) return e("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return e("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); + if (scan == SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return e("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case PNG_TYPE('P','L','T','E'): { + if (c.length > 256*3) return e("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return e("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = get8u(s); + palette[i*4+1] = get8u(s); + palette[i*4+2] = get8u(s); + palette[i*4+3] = 255; + } + break; + } + + case PNG_TYPE('t','R','N','S'): { + if (z->idata) return e("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return e("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return e("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = get8u(s); + } else { + if (!(s->img_n & 1)) return e("tRNS with alpha","Corrupt PNG"); + if (c.length != (uint32) s->img_n*2) return e("bad tRNS len","Corrupt PNG"); + has_trans = 1; + for (k=0; k < s->img_n; ++k) + tc[k] = (uint8) get16(s); // non 8-bit images will be larger + } + break; + } + + case PNG_TYPE('I','D','A','T'): { + if (pal_img_n && !pal_len) return e("no PLTE","Corrupt PNG"); + if (scan == SCAN_header) { s->img_n = pal_img_n; return 1; } + if (ioff + c.length > idata_limit) { + uint8 *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + p = (uint8 *) realloc(z->idata, idata_limit); if (p == NULL) return e("outofmem", "Out of memory"); + z->idata = p; + } + #ifndef STBI_NO_STDIO + if (s->img_file) + { + if (fread(z->idata+ioff,1,c.length,s->img_file) != c.length) return e("outofdata","Corrupt PNG"); + } + else + #endif + { + memcpy(z->idata+ioff, s->img_buffer, c.length); + s->img_buffer += c.length; + } + ioff += c.length; + break; + } + + case PNG_TYPE('I','E','N','D'): { + uint32 raw_len; + if (scan != SCAN_load) return 1; + if (z->idata == NULL) return e("no IDAT","Corrupt PNG"); + z->expanded = (uint8 *) stbi_zlib_decode_malloc((char *) z->idata, ioff, (int *) &raw_len); + if (z->expanded == NULL) return 0; // zlib should set error + free(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!create_png_image(z, z->expanded, raw_len, s->img_out_n, interlace)) return 0; + if (has_trans) + if (!compute_transparency(z, tc, s->img_out_n)) return 0; + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!expand_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } + free(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX chunk not known"; + invalid_chunk[0] = (uint8) (c.type >> 24); + invalid_chunk[1] = (uint8) (c.type >> 16); + invalid_chunk[2] = (uint8) (c.type >> 8); + invalid_chunk[3] = (uint8) (c.type >> 0); + #endif + return e(invalid_chunk, "PNG not supported: unknown chunk type"); + } + skip(s, c.length); + break; + } + // end of chunk, read and skip CRC + get32(s); + } +} + +static unsigned char *do_png(png *p, int *x, int *y, int *n, int req_comp) +{ + unsigned char *result=NULL; + p->expanded = NULL; + p->idata = NULL; + p->out = NULL; + if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); + if (parse_png_file(p, SCAN_load, req_comp)) { + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s.img_out_n) { + result = convert_format(result, p->s.img_out_n, req_comp, p->s.img_x, p->s.img_y); + p->s.img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s.img_x; + *y = p->s.img_y; + if (n) *n = p->s.img_n; + } + free(p->out); p->out = NULL; + free(p->expanded); p->expanded = NULL; + free(p->idata); p->idata = NULL; + + return result; +} + +#ifndef STBI_NO_STDIO +unsigned char *stbi_png_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + png p; + start_file(&p.s, f); + return do_png(&p, x,y,comp,req_comp); +} + +unsigned char *stbi_png_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_png_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return data; +} +#endif + +unsigned char *stbi_png_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + png p; + start_mem(&p.s, buffer,len); + return do_png(&p, x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +int stbi_png_test_file(FILE *f) +{ + png p; + int n,r; + n = ftell(f); + start_file(&p.s, f); + r = parse_png_file(&p, SCAN_type,STBI_default); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_png_test_memory(stbi_uc const *buffer, int len) +{ + png p; + start_mem(&p.s, buffer, len); + return parse_png_file(&p, SCAN_type,STBI_default); +} + +// TODO: load header from png +#ifndef STBI_NO_STDIO +int stbi_png_info (char const *filename, int *x, int *y, int *comp) +{ + png p; + FILE *f = fopen(filename, "rb"); + if (!f) return 0; + start_file(&p.s, f); + if (parse_png_file(&p, SCAN_header, 0)) { + if(x) *x = p.s.img_x; + if(y) *y = p.s.img_y; + if (comp) *comp = p.s.img_n; + fclose(f); + return 1; + } + fclose(f); + return 0; +} + +extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp); +#endif +extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + +// Microsoft/Windows BMP image + +static int bmp_test(stbi *s) +{ + int sz; + if (get8(s) != 'B') return 0; + if (get8(s) != 'M') return 0; + get32le(s); // discard filesize + get16le(s); // discard reserved + get16le(s); // discard reserved + get32le(s); // discard data offset + sz = get32le(s); + if (sz == 12 || sz == 40 || sz == 56 || sz == 108) return 1; + return 0; +} + +#ifndef STBI_NO_STDIO +int stbi_bmp_test_file (FILE *f) +{ + stbi s; + int r,n = ftell(f); + start_file(&s,f); + r = bmp_test(&s); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_bmp_test_memory (stbi_uc const *buffer, int len) +{ + stbi s; + start_mem(&s, buffer, len); + return bmp_test(&s); +} + +// returns 0..31 for the highest set bit +static int high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +static int shiftsigned(int v, int shift, int bits) +{ + int result; + int z=0; + + if (shift < 0) v <<= -shift; + else v >>= shift; + result = v; + + z = bits; + while (z < 8) { + result += v >> z; + z += bits; + } + return result; +} + +static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + uint8 *out; + unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0; + stbi_uc pal[256][4]; + int psize=0,i,j,compress=0,width; + int bpp, flip_vertically, pad, target, offset, hsz; + if (get8(s) != 'B' || get8(s) != 'M') return epuc("not BMP", "Corrupt BMP"); + get32le(s); // discard filesize + get16le(s); // discard reserved + get16le(s); // discard reserved + offset = get32le(s); + hsz = get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) return epuc("unknown BMP", "BMP type not supported: unknown"); + failure_reason = "bad BMP"; + if (hsz == 12) { + s->img_x = get16le(s); + s->img_y = get16le(s); + } else { + s->img_x = get32le(s); + s->img_y = get32le(s); + } + if (get16le(s) != 1) return 0; + bpp = get16le(s); + if (bpp == 1) return epuc("monochrome", "BMP type not supported: 1-bit"); + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + if (hsz == 12) { + if (bpp < 24) + psize = (offset - 14 - 24) / 3; + } else { + compress = get32le(s); + if (compress == 1 || compress == 2) return epuc("BMP RLE", "BMP type not supported: RLE"); + get32le(s); // discard sizeof + get32le(s); // discard hres + get32le(s); // discard vres + get32le(s); // discard colorsused + get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + get32le(s); + get32le(s); + get32le(s); + get32le(s); + } + if (bpp == 16 || bpp == 32) { + mr = mg = mb = 0; + if (compress == 0) { + if (bpp == 32) { + mr = 0xff << 16; + mg = 0xff << 8; + mb = 0xff << 0; + ma = 0xff << 24; + fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255 + } else { + mr = 31 << 10; + mg = 31 << 5; + mb = 31 << 0; + } + } else if (compress == 3) { + mr = get32le(s); + mg = get32le(s); + mb = get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (mr == mg && mg == mb) { + // ?!?!? + return NULL; + } + } else + return NULL; + } + } else { + assert(hsz == 108); + mr = get32le(s); + mg = get32le(s); + mb = get32le(s); + ma = get32le(s); + get32le(s); // discard color space + for (i=0; i < 12; ++i) + get32le(s); // discard color space parameters + } + if (bpp < 16) + psize = (offset - 14 - hsz) >> 2; + } + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + out = (stbi_uc *) malloc(target * s->img_x * s->img_y); + if (!out) return epuc("outofmem", "Out of memory"); + if (bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { free(out); return epuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = get8(s); + pal[i][1] = get8(s); + pal[i][0] = get8(s); + if (hsz != 12) get8(s); + pal[i][3] = 255; + } + skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); + if (bpp == 4) width = (s->img_x + 1) >> 1; + else if (bpp == 8) width = s->img_x; + else { free(out); return epuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=get8(s),v2=0; + if (bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (bpp == 8) ? get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + skip(s, pad); + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + skip(s, offset - 14 - hsz); + if (bpp == 24) width = 3 * s->img_x; + else if (bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (bpp == 24) { + easy = 1; + } else if (bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0xff000000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) return epuc("bad masks", "Corrupt BMP"); + // right shift amt to put high bit in position #7 + rshift = high_bit(mr)-7; rcount = bitcount(mr); + gshift = high_bit(mg)-7; gcount = bitcount(mr); + bshift = high_bit(mb)-7; bcount = bitcount(mr); + ashift = high_bit(ma)-7; acount = bitcount(mr); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + int a; + out[z+2] = get8(s); + out[z+1] = get8(s); + out[z+0] = get8(s); + z += 3; + a = (easy == 2 ? get8(s) : 255); + if (target == 4) out[z++] = a; + } + } else { + for (i=0; i < (int) s->img_x; ++i) { + uint32 v = (bpp == 16 ? get16le(s) : get32le(s)); + int a; + out[z++] = shiftsigned(v & mr, rshift, rcount); + out[z++] = shiftsigned(v & mg, gshift, gcount); + out[z++] = shiftsigned(v & mb, bshift, bcount); + a = (ma ? shiftsigned(v & ma, ashift, acount) : 255); + if (target == 4) out[z++] = a; + } + } + skip(s, pad); + } + } + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = target; + return out; +} + +#ifndef STBI_NO_STDIO +stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_bmp_load_from_file(f, x,y,comp,req_comp); + fclose(f); + return data; +} + +stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s, f); + return bmp_load(&s, x,y,comp,req_comp); +} +#endif + +stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s, buffer, len); + return bmp_load(&s, x,y,comp,req_comp); +} + +// Targa Truevision - TGA +// by Jonathan Dummer + +static int tga_test(stbi *s) +{ + int sz; + get8u(s); // discard Offset + sz = get8u(s); // color type + if( sz > 1 ) return 0; // only RGB or indexed allowed + sz = get8u(s); // image type + if( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE + get16(s); // discard palette start + get16(s); // discard palette length + get8(s); // discard bits per palette color entry + get16(s); // discard x origin + get16(s); // discard y origin + if( get16(s) < 1 ) return 0; // test width + if( get16(s) < 1 ) return 0; // test height + sz = get8(s); // bits per pixel + if( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) ) return 0; // only RGB or RGBA or grey allowed + return 1; // seems to have passed everything +} + +#ifndef STBI_NO_STDIO +int stbi_tga_test_file (FILE *f) +{ + stbi s; + int r,n = ftell(f); + start_file(&s, f); + r = tga_test(&s); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_tga_test_memory (stbi_uc const *buffer, int len) +{ + stbi s; + start_mem(&s, buffer, len); + return tga_test(&s); +} + +static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + // read in the TGA header stuff + int tga_offset = get8u(s); + int tga_indexed = get8u(s); + int tga_image_type = get8u(s); + int tga_is_RLE = 0; + int tga_palette_start = get16le(s); + int tga_palette_len = get16le(s); + int tga_palette_bits = get8u(s); + int tga_x_origin = get16le(s); + int tga_y_origin = get16le(s); + int tga_width = get16le(s); + int tga_height = get16le(s); + int tga_bits_per_pixel = get8u(s); + int tga_inverted = get8u(s); + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4]; + unsigned char trans_data[4] = {0,0,0,0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + // do a tiny bit of precessing + if( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + /* int tga_alpha_bits = tga_inverted & 15; */ + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // error check + if( //(tga_indexed) || + (tga_width < 1) || (tga_height < 1) || + (tga_image_type < 1) || (tga_image_type > 3) || + ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && + (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) + ) + { + return NULL; + } + + // If I'm paletted, then I'll use the number of bits from the palette + if( tga_indexed ) + { + tga_bits_per_pixel = tga_palette_bits; + } + + // tga info + *x = tga_width; + *y = tga_height; + if( (req_comp < 1) || (req_comp > 4) ) + { + // just use whatever the file was + req_comp = tga_bits_per_pixel / 8; + *comp = req_comp; + } else + { + // force a new number of components + *comp = tga_bits_per_pixel/8; + } + tga_data = (unsigned char*)malloc( tga_width * tga_height * req_comp ); + + // skip to the data's starting position (offset usually = 0) + skip(s, tga_offset ); + // do I need to load a palette? + if( tga_indexed ) + { + // any data to skip? (offset usually = 0) + skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); + getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 ); + } + // load the data + for( i = 0; i < tga_width * tga_height; ++i ) + { + // if I'm in RLE mode, do I need to get a RLE chunk? + if( tga_is_RLE ) + { + if( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = get8u(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if( read_next_pixel ) + { + // load however much data we did have + if( tga_indexed ) + { + // read in 1 byte, then perform the lookup + int pal_idx = get8u(s); + if( pal_idx >= tga_palette_len ) + { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_bits_per_pixel / 8; + for( j = 0; j*8 < tga_bits_per_pixel; ++j ) + { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else + { + // read in the data raw + for( j = 0; j*8 < tga_bits_per_pixel; ++j ) + { + raw_data[j] = get8u(s); + } + } + // convert raw to the intermediate format + switch( tga_bits_per_pixel ) + { + case 8: + // Luminous => RGBA + trans_data[0] = raw_data[0]; + trans_data[1] = raw_data[0]; + trans_data[2] = raw_data[0]; + trans_data[3] = 255; + break; + case 16: + // Luminous,Alpha => RGBA + trans_data[0] = raw_data[0]; + trans_data[1] = raw_data[0]; + trans_data[2] = raw_data[0]; + trans_data[3] = raw_data[1]; + break; + case 24: + // BGR => RGBA + trans_data[0] = raw_data[2]; + trans_data[1] = raw_data[1]; + trans_data[2] = raw_data[0]; + trans_data[3] = 255; + break; + case 32: + // BGRA => RGBA + trans_data[0] = raw_data[2]; + trans_data[1] = raw_data[1]; + trans_data[2] = raw_data[0]; + trans_data[3] = raw_data[3]; + break; + default: + return NULL; + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + // convert to final format + switch( req_comp ) + { + case 1: + // RGBA => Luminance + tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); + break; + case 2: + // RGBA => Luminance,Alpha + tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); + tga_data[i*req_comp+1] = trans_data[3]; + break; + case 3: + // RGBA => RGB + tga_data[i*req_comp+0] = trans_data[0]; + tga_data[i*req_comp+1] = trans_data[1]; + tga_data[i*req_comp+2] = trans_data[2]; + break; + case 4: + // RGBA => RGBA + tga_data[i*req_comp+0] = trans_data[0]; + tga_data[i*req_comp+1] = trans_data[1]; + tga_data[i*req_comp+2] = trans_data[2]; + tga_data[i*req_comp+3] = trans_data[3]; + break; + } + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if( tga_inverted ) + { + for( j = 0; j*2 < tga_height; ++j ) + { + int index1 = j * tga_width * req_comp; + int index2 = (tga_height - 1 - j) * tga_width * req_comp; + for( i = tga_width * req_comp; i > 0; --i ) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if( tga_palette != NULL ) + { + free( tga_palette ); + } + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} + +#ifndef STBI_NO_STDIO +stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_tga_load_from_file(f, x,y,comp,req_comp); + fclose(f); + return data; +} + +stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s, f); + return tga_load(&s, x,y,comp,req_comp); +} +#endif + +stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s, buffer, len); + return tga_load(&s, x,y,comp,req_comp); +} + + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicholas Schulz, tweaked by STB + +static int psd_test(stbi *s) +{ + if (get32(s) != 0x38425053) return 0; // "8BPS" + else return 1; +} + +#ifndef STBI_NO_STDIO +int stbi_psd_test_file(FILE *f) +{ + stbi s; + int r,n = ftell(f); + start_file(&s, f); + r = psd_test(&s); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +int stbi_psd_test_memory(stbi_uc const *buffer, int len) +{ + stbi s; + start_mem(&s, buffer, len); + return psd_test(&s); +} + +static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + int pixelCount; + int channelCount, compression; + int channel, i, count, len; + int w,h; + uint8 *out; + + // Check identifier + if (get32(s) != 0x38425053) // "8BPS" + return epuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (get16(s) != 1) + return epuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = get16(s); + if (channelCount < 0 || channelCount > 16) + return epuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = get32(s); + w = get32(s); + + // Make sure the depth is 8 bits. + if (get16(s) != 8) + return epuc("unsupported bit depth", "PSD bit depth is not 8 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (get16(s) != 3) + return epuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + skip(s,get32(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + skip(s, get32(s) ); + + // Skip the reserved data. + skip(s, get32(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = get16(s); + if (compression > 1) + return epuc("bad compression", "PSD has an unknown compression format"); + + // Create the destination image. + out = (stbi_uc *) malloc(4 * w*h); + if (!out) return epuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + uint8 *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4; + } else { + // Read the RLE data. + count = 0; + while (count < pixelCount) { + len = get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + count += len; + while (len) { + *p = get8(s); + p += 4; + len--; + } + } else if (len > 128) { + uint32 val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len ^= 0x0FF; + len += 2; + val = get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + uint8 *p; + + p = out + channel; + if (channel > channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4; + } else { + // Read the data. + count = 0; + for (i = 0; i < pixelCount; i++) + *p = get8(s), p += 4; + } + } + } + + if (req_comp && req_comp != 4) { + out = convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // convert_format frees input on failure + } + + if (comp) *comp = channelCount; + *y = h; + *x = w; + + return out; +} + +#ifndef STBI_NO_STDIO +stbi_uc *stbi_psd_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *data; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + data = stbi_psd_load_from_file(f, x,y,comp,req_comp); + fclose(f); + return data; +} + +stbi_uc *stbi_psd_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s, f); + return psd_load(&s, x,y,comp,req_comp); +} +#endif + +stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s, buffer, len); + return psd_load(&s, x,y,comp,req_comp); +} + + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int hdr_test(stbi *s) +{ + const char *signature = "#?RADIANCE\n"; + int i; + for (i=0; signature[i]; ++i) + if (get8(s) != signature[i]) + return 0; + return 1; +} + +int stbi_hdr_test_memory(stbi_uc const *buffer, int len) +{ + stbi s; + start_mem(&s, buffer, len); + return hdr_test(&s); +} + +#ifndef STBI_NO_STDIO +int stbi_hdr_test_file(FILE *f) +{ + stbi s; + int r,n = ftell(f); + start_file(&s, f); + r = hdr_test(&s); + fseek(f,n,SEEK_SET); + return r; +} +#endif + +#define HDR_BUFLEN 1024 +static char *hdr_gettoken(stbi *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = get8(z); + + while (!at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == HDR_BUFLEN-1) { + // flush to end of line + while (!at_eof(z) && get8(z) != '\n') + ; + break; + } + c = get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + + +static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + char buffer[HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + + + // Check identifier + if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + return epf("not HDR", "Corrupt HDR image"); + + // Parse header + while(1) { + token = hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return epf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = strtol(token, NULL, 10); + + *x = width; + *y = height; + + *comp = 3; + if (req_comp == 0) req_comp = 3; + + // Read data + hdr_data = (float *) malloc(height * width * req_comp * sizeof(float)); + + // Load image data + // image data is stored as some number of sca + if( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + getn(s, rgbe, 4); + hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = get8(s); + c2 = get8(s); + len = get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4] = { c1,c2,len, get8(s) }; + hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + free(scanline); + goto main_decode_loop; // yes, this is fucking insane; blame the fucking insane format + } + len <<= 8; + len |= get8(s); + if (len != width) { free(hdr_data); free(scanline); return epf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4); + + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = get8(s); + if (count > 128) { + // Run + value = get8(s); + count -= 128; + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = get8(s); + } + } + } + for (i=0; i < width; ++i) + hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + free(scanline); + } + + return hdr_data; +} + +static stbi_uc *hdr_load_rgbe(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + char buffer[HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + stbi_uc *rgbe_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + + + // Check identifier + if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + return epuc("not HDR", "Corrupt HDR image"); + + // Parse header + while(1) { + token = hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return epuc("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return epuc("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return epuc("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = strtol(token, NULL, 10); + + *x = width; + *y = height; + + // RGBE _MUST_ come out as 4 components + *comp = 4; + req_comp = 4; + + // Read data + rgbe_data = (stbi_uc *) malloc(height * width * req_comp * sizeof(stbi_uc)); + // point to the beginning + scanline = rgbe_data; + + // Load image data + // image data is stored as some number of scan lines + if( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + main_decode_loop: + //getn(rgbe, 4); + getn(s,scanline, 4); + scanline += 4; + } + } + } else { + // Read RLE-encoded data + for (j = 0; j < height; ++j) { + c1 = get8(s); + c2 = get8(s); + len = get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + scanline[0] = c1; + scanline[1] = c2; + scanline[2] = len; + scanline[3] = get8(s); + scanline += 4; + i = 1; + j = 0; + goto main_decode_loop; // yes, this is insane; blame the insane format + } + len <<= 8; + len |= get8(s); + if (len != width) { free(rgbe_data); return epuc("invalid decoded scanline length", "corrupt HDR"); } + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = get8(s); + if (count > 128) { + // Run + value = get8(s); + count -= 128; + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = get8(s); + } + } + } + // move the scanline on + scanline += 4 * width; + } + } + + return rgbe_data; +} + +#ifndef STBI_NO_STDIO +float *stbi_hdr_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s,f); + return hdr_load(&s,x,y,comp,req_comp); +} + +stbi_uc *stbi_hdr_load_rgbe_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s,f); + return hdr_load_rgbe(&s,x,y,comp,req_comp); +} + +stbi_uc *stbi_hdr_load_rgbe (char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = fopen(filename, "rb"); + unsigned char *result; + if (!f) return epuc("can't fopen", "Unable to open file"); + result = stbi_hdr_load_rgbe_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} +#endif + +float *stbi_hdr_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s,buffer, len); + return hdr_load(&s,x,y,comp,req_comp); +} + +stbi_uc *stbi_hdr_load_rgbe_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s,buffer, len); + return hdr_load_rgbe(&s,x,y,comp,req_comp); +} + +#endif // STBI_NO_HDR + +/////////////////////// write image /////////////////////// + +#ifndef STBI_NO_WRITE + +static void write8(FILE *f, int x) { uint8 z = (uint8) x; fwrite(&z,1,1,f); } + +static void writefv(FILE *f, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { uint8 x = va_arg(v, int); write8(f,x); break; } + case '2': { int16 x = va_arg(v, int); write8(f,x); write8(f,x>>8); break; } + case '4': { int32 x = va_arg(v, int); write8(f,x); write8(f,x>>8); write8(f,x>>16); write8(f,x>>24); break; } + default: + assert(0); + va_end(v); + return; + } + } +} + +static void writef(FILE *f, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + writefv(f,fmt,v); + va_end(v); +} + +static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad) +{ + uint8 bg[3] = { 255, 0, 255}, px[3]; + uint32 zero = 0; + int i,j,k, j_end; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + uint8 *d = (uint8 *) data + (j*x+i)*comp; + if (write_alpha < 0) + fwrite(&d[comp-1], 1, 1, f); + switch (comp) { + case 1: + case 2: writef(f, "111", d[0],d[0],d[0]); + break; + case 4: + if (!write_alpha) { + for (k=0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255; + writef(f, "111", px[1-rgb_dir],px[1],px[1+rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + writef(f, "111", d[1-rgb_dir],d[1],d[1+rgb_dir]); + break; + } + if (write_alpha > 0) + fwrite(&d[comp-1], 1, 1, f); } - } - for (j=0; j < y; ++j) { - uint8 *cur = a->out + stride*j; - uint8 *prior = cur - stride; - int filter = *raw++; - if (filter > 4) return e("invalid filter","Corrupt PNG"); - // if first row, use special filter that doesn't sample previous row - if (j == 0) filter = first_row_filter[filter]; - // handle first pixel explicitly - for (k=0; k < img_n; ++k) { - switch(filter) { - case F_none : cur[k] = raw[k]; break; - case F_sub : cur[k] = raw[k]; break; - case F_up : cur[k] = raw[k] + prior[k]; break; - case F_avg : cur[k] = raw[k] + (prior[k]>>1); break; - case F_paeth : cur[k] = (uint8) (raw[k] + paeth(0,prior[k],0)); break; - case F_avg_first : cur[k] = raw[k]; break; - case F_paeth_first: cur[k] = raw[k]; break; - } - } - if (img_n != out_n) cur[img_n] = 255; - raw += img_n; - cur += out_n; - prior += out_n; - // this is a little gross, so that we don't switch per-pixel or per-component - if (img_n == out_n) { - #define CASE(f) \ - case f: \ - for (i=x-1; i >= 1; --i, raw+=img_n,cur+=img_n,prior+=img_n) \ - for (k=0; k < img_n; ++k) - switch(filter) { - CASE(F_none) cur[k] = raw[k]; break; - CASE(F_sub) cur[k] = raw[k] + cur[k-img_n]; break; - CASE(F_up) cur[k] = raw[k] + prior[k]; break; - CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-img_n])>>1); break; - CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],prior[k],prior[k-img_n])); break; - CASE(F_avg_first) cur[k] = raw[k] + (cur[k-img_n] >> 1); break; - CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],0,0)); break; - } - #undef CASE - } else { - assert(img_n+1 == out_n); - #define CASE(f) \ - case f: \ - for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ - for (k=0; k < img_n; ++k) - switch(filter) { - CASE(F_none) cur[k] = raw[k]; break; - CASE(F_sub) cur[k] = raw[k] + cur[k-out_n]; break; - CASE(F_up) cur[k] = raw[k] + prior[k]; break; - CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-out_n])>>1); break; - CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; - CASE(F_avg_first) cur[k] = raw[k] + (cur[k-out_n] >> 1); break; - CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],0,0)); break; - } - #undef CASE - } - } - return 1; -} - -static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int interlaced) -{ - uint8 *final; - int p; - int save; - if (!interlaced) - return create_png_image_raw(a, raw, raw_len, out_n, a->s.img_x, a->s.img_y); - save = stbi_png_partial; - stbi_png_partial = 0; - - // de-interlacing - final = (uint8 *) malloc(a->s.img_x * a->s.img_y * out_n); - for (p=0; p < 7; ++p) { - int xorig[] = { 0,4,0,2,0,1,0 }; - int yorig[] = { 0,0,4,0,2,0,1 }; - int xspc[] = { 8,8,4,4,2,2,1 }; - int yspc[] = { 8,8,8,4,4,2,2 }; - int i,j,x,y; - // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 - x = (a->s.img_x - xorig[p] + xspc[p]-1) / xspc[p]; - y = (a->s.img_y - yorig[p] + yspc[p]-1) / yspc[p]; - if (x && y) { - if (!create_png_image_raw(a, raw, raw_len, out_n, x, y)) { - free(final); - return 0; - } - for (j=0; j < y; ++j) - for (i=0; i < x; ++i) - memcpy(final + (j*yspc[p]+yorig[p])*a->s.img_x*out_n + (i*xspc[p]+xorig[p])*out_n, - a->out + (j*x+i)*out_n, out_n); - free(a->out); - raw += (x*out_n+1)*y; - raw_len -= (x*out_n+1)*y; - } - } - a->out = final; - - stbi_png_partial = save; - return 1; -} - -static int compute_transparency(png *z, uint8 tc[3], int out_n) -{ - stbi *s = &z->s; - uint32 i, pixel_count = s->img_x * s->img_y; - uint8 *p = z->out; - - // compute color-based transparency, assuming we've - // already got 255 as the alpha value in the output - assert(out_n == 2 || out_n == 4); - - if (out_n == 2) { - for (i=0; i < pixel_count; ++i) { - p[1] = (p[0] == tc[0] ? 0 : 255); - p += 2; - } - } else { - for (i=0; i < pixel_count; ++i) { - if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) - p[3] = 0; - p += 4; - } - } - return 1; -} - -static int expand_palette(png *a, uint8 *palette, int len, int pal_img_n) -{ - uint32 i, pixel_count = a->s.img_x * a->s.img_y; - uint8 *p, *temp_out, *orig = a->out; - - p = (uint8 *) malloc(pixel_count * pal_img_n); - if (p == NULL) return e("outofmem", "Out of memory"); - - // between here and free(out) below, exitting would leak - temp_out = p; - - if (pal_img_n == 3) { - for (i=0; i < pixel_count; ++i) { - int n = orig[i]*4; - p[0] = palette[n ]; - p[1] = palette[n+1]; - p[2] = palette[n+2]; - p += 3; - } - } else { - for (i=0; i < pixel_count; ++i) { - int n = orig[i]*4; - p[0] = palette[n ]; - p[1] = palette[n+1]; - p[2] = palette[n+2]; - p[3] = palette[n+3]; - p += 4; - } - } - free(a->out); - a->out = temp_out; - return 1; -} - -static int parse_png_file(png *z, int scan, int req_comp) -{ - uint8 palette[1024], pal_img_n=0; - uint8 has_trans=0, tc[3]; - uint32 ioff=0, idata_limit=0, i, pal_len=0; - int first=1,k,interlace=0; - stbi *s = &z->s; - - if (!check_png_header(s)) return 0; - - if (scan == SCAN_type) return 1; - - for(;;first=0) { - chunk c = get_chunk_header(s); - if (first && c.type != PNG_TYPE('I','H','D','R')) - return e("first not IHDR","Corrupt PNG"); - switch (c.type) { - case PNG_TYPE('I','H','D','R'): { - int depth,color,comp,filter; - if (!first) return e("multiple IHDR","Corrupt PNG"); - if (c.length != 13) return e("bad IHDR len","Corrupt PNG"); - s->img_x = get32(s); if (s->img_x > (1 << 24)) return e("too large","Very large image (corrupt?)"); - s->img_y = get32(s); if (s->img_y > (1 << 24)) return e("too large","Very large image (corrupt?)"); - depth = get8(s); if (depth != 8) return e("8bit only","PNG not supported: 8-bit only"); - color = get8(s); if (color > 6) return e("bad ctype","Corrupt PNG"); - if (color == 3) pal_img_n = 3; else if (color & 1) return e("bad ctype","Corrupt PNG"); - comp = get8(s); if (comp) return e("bad comp method","Corrupt PNG"); - filter= get8(s); if (filter) return e("bad filter method","Corrupt PNG"); - interlace = get8(s); if (interlace>1) return e("bad interlace method","Corrupt PNG"); - if (!s->img_x || !s->img_y) return e("0-pixel image","Corrupt PNG"); - if (!pal_img_n) { - s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); - if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); - if (scan == SCAN_header) return 1; - } else { - // if paletted, then pal_n is our final components, and - // img_n is # components to decompress/filter. - s->img_n = 1; - if ((1 << 30) / s->img_x / 4 < s->img_y) return e("too large","Corrupt PNG"); - // if SCAN_header, have to scan to see if we have a tRNS - } - break; - } - - case PNG_TYPE('P','L','T','E'): { - if (c.length > 256*3) return e("invalid PLTE","Corrupt PNG"); - pal_len = c.length / 3; - if (pal_len * 3 != c.length) return e("invalid PLTE","Corrupt PNG"); - for (i=0; i < pal_len; ++i) { - palette[i*4+0] = get8u(s); - palette[i*4+1] = get8u(s); - palette[i*4+2] = get8u(s); - palette[i*4+3] = 255; - } - break; - } - - case PNG_TYPE('t','R','N','S'): { - if (z->idata) return e("tRNS after IDAT","Corrupt PNG"); - if (pal_img_n) { - if (scan == SCAN_header) { s->img_n = 4; return 1; } - if (pal_len == 0) return e("tRNS before PLTE","Corrupt PNG"); - if (c.length > pal_len) return e("bad tRNS len","Corrupt PNG"); - pal_img_n = 4; - for (i=0; i < c.length; ++i) - palette[i*4+3] = get8u(s); - } else { - if (!(s->img_n & 1)) return e("tRNS with alpha","Corrupt PNG"); - if (c.length != (uint32) s->img_n*2) return e("bad tRNS len","Corrupt PNG"); - has_trans = 1; - for (k=0; k < s->img_n; ++k) - tc[k] = (uint8) get16(s); // non 8-bit images will be larger - } - break; - } - - case PNG_TYPE('I','D','A','T'): { - if (pal_img_n && !pal_len) return e("no PLTE","Corrupt PNG"); - if (scan == SCAN_header) { s->img_n = pal_img_n; return 1; } - if (ioff + c.length > idata_limit) { - uint8 *p; - if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; - while (ioff + c.length > idata_limit) - idata_limit *= 2; - p = (uint8 *) realloc(z->idata, idata_limit); if (p == NULL) return e("outofmem", "Out of memory"); - z->idata = p; - } - #ifndef STBI_NO_STDIO - if (s->img_file) - { - if (fread(z->idata+ioff,1,c.length,s->img_file) != c.length) return e("outofdata","Corrupt PNG"); - } - else - #endif - { - memcpy(z->idata+ioff, s->img_buffer, c.length); - s->img_buffer += c.length; - } - ioff += c.length; - break; - } - - case PNG_TYPE('I','E','N','D'): { - uint32 raw_len; - if (scan != SCAN_load) return 1; - if (z->idata == NULL) return e("no IDAT","Corrupt PNG"); - z->expanded = (uint8 *) stbi_zlib_decode_malloc((char *) z->idata, ioff, (int *) &raw_len); - if (z->expanded == NULL) return 0; // zlib should set error - free(z->idata); z->idata = NULL; - if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) - s->img_out_n = s->img_n+1; - else - s->img_out_n = s->img_n; - if (!create_png_image(z, z->expanded, raw_len, s->img_out_n, interlace)) return 0; - if (has_trans) - if (!compute_transparency(z, tc, s->img_out_n)) return 0; - if (pal_img_n) { - // pal_img_n == 3 or 4 - s->img_n = pal_img_n; // record the actual colors we had - s->img_out_n = pal_img_n; - if (req_comp >= 3) s->img_out_n = req_comp; - if (!expand_palette(z, palette, pal_len, s->img_out_n)) - return 0; - } - free(z->expanded); z->expanded = NULL; - return 1; - } - - default: - // if critical, fail - if ((c.type & (1 << 29)) == 0) { - #ifndef STBI_NO_FAILURE_STRINGS - // not threadsafe - static char invalid_chunk[] = "XXXX chunk not known"; - invalid_chunk[0] = (uint8) (c.type >> 24); - invalid_chunk[1] = (uint8) (c.type >> 16); - invalid_chunk[2] = (uint8) (c.type >> 8); - invalid_chunk[3] = (uint8) (c.type >> 0); - #endif - return e(invalid_chunk, "PNG not supported: unknown chunk type"); - } - skip(s, c.length); - break; - } - // end of chunk, read and skip CRC - get32(s); - } -} - -static unsigned char *do_png(png *p, int *x, int *y, int *n, int req_comp) -{ - unsigned char *result=NULL; - p->expanded = NULL; - p->idata = NULL; - p->out = NULL; - if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); - if (parse_png_file(p, SCAN_load, req_comp)) { - result = p->out; - p->out = NULL; - if (req_comp && req_comp != p->s.img_out_n) { - result = convert_format(result, p->s.img_out_n, req_comp, p->s.img_x, p->s.img_y); - p->s.img_out_n = req_comp; - if (result == NULL) return result; - } - *x = p->s.img_x; - *y = p->s.img_y; - if (n) *n = p->s.img_n; - } - free(p->out); p->out = NULL; - free(p->expanded); p->expanded = NULL; - free(p->idata); p->idata = NULL; - - return result; -} - -#ifndef STBI_NO_STDIO -unsigned char *stbi_png_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - png p; - start_file(&p.s, f); - return do_png(&p, x,y,comp,req_comp); -} - -unsigned char *stbi_png_load(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_png_load_from_file(f,x,y,comp,req_comp); - fclose(f); - return data; -} -#endif - -unsigned char *stbi_png_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - png p; - start_mem(&p.s, buffer,len); - return do_png(&p, x,y,comp,req_comp); -} - -#ifndef STBI_NO_STDIO -int stbi_png_test_file(FILE *f) -{ - png p; - int n,r; - n = ftell(f); - start_file(&p.s, f); - r = parse_png_file(&p, SCAN_type,STBI_default); - fseek(f,n,SEEK_SET); - return r; -} -#endif - -int stbi_png_test_memory(stbi_uc const *buffer, int len) -{ - png p; - start_mem(&p.s, buffer, len); - return parse_png_file(&p, SCAN_type,STBI_default); -} - -// TODO: load header from png -#ifndef STBI_NO_STDIO -int stbi_png_info (char const *filename, int *x, int *y, int *comp) -{ - png p; - FILE *f = fopen(filename, "rb"); - if (!f) return 0; - start_file(&p.s, f); - if (parse_png_file(&p, SCAN_header, 0)) { - if(x) *x = p.s.img_x; - if(y) *y = p.s.img_y; - if (comp) *comp = p.s.img_n; - fclose(f); - return 1; - } - fclose(f); - return 0; -} - -extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp); -#endif -extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); - -// Microsoft/Windows BMP image - -static int bmp_test(stbi *s) -{ - int sz; - if (get8(s) != 'B') return 0; - if (get8(s) != 'M') return 0; - get32le(s); // discard filesize - get16le(s); // discard reserved - get16le(s); // discard reserved - get32le(s); // discard data offset - sz = get32le(s); - if (sz == 12 || sz == 40 || sz == 56 || sz == 108) return 1; - return 0; -} - -#ifndef STBI_NO_STDIO -int stbi_bmp_test_file (FILE *f) -{ - stbi s; - int r,n = ftell(f); - start_file(&s,f); - r = bmp_test(&s); - fseek(f,n,SEEK_SET); - return r; -} -#endif - -int stbi_bmp_test_memory (stbi_uc const *buffer, int len) -{ - stbi s; - start_mem(&s, buffer, len); - return bmp_test(&s); -} - -// returns 0..31 for the highest set bit -static int high_bit(unsigned int z) -{ - int n=0; - if (z == 0) return -1; - if (z >= 0x10000) n += 16, z >>= 16; - if (z >= 0x00100) n += 8, z >>= 8; - if (z >= 0x00010) n += 4, z >>= 4; - if (z >= 0x00004) n += 2, z >>= 2; - if (z >= 0x00002) n += 1, z >>= 1; - return n; -} - -static int bitcount(unsigned int a) -{ - a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 - a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 - a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits - a = (a + (a >> 8)); // max 16 per 8 bits - a = (a + (a >> 16)); // max 32 per 8 bits - return a & 0xff; -} - -static int shiftsigned(int v, int shift, int bits) -{ - int result; - int z=0; - - if (shift < 0) v <<= -shift; - else v >>= shift; - result = v; - - z = bits; - while (z < 8) { - result += v >> z; - z += bits; - } - return result; -} - -static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) -{ - uint8 *out; - unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0; - stbi_uc pal[256][4]; - int psize=0,i,j,compress=0,width; - int bpp, flip_vertically, pad, target, offset, hsz; - if (get8(s) != 'B' || get8(s) != 'M') return epuc("not BMP", "Corrupt BMP"); - get32le(s); // discard filesize - get16le(s); // discard reserved - get16le(s); // discard reserved - offset = get32le(s); - hsz = get32le(s); - if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) return epuc("unknown BMP", "BMP type not supported: unknown"); - failure_reason = "bad BMP"; - if (hsz == 12) { - s->img_x = get16le(s); - s->img_y = get16le(s); - } else { - s->img_x = get32le(s); - s->img_y = get32le(s); - } - if (get16le(s) != 1) return 0; - bpp = get16le(s); - if (bpp == 1) return epuc("monochrome", "BMP type not supported: 1-bit"); - flip_vertically = ((int) s->img_y) > 0; - s->img_y = abs((int) s->img_y); - if (hsz == 12) { - if (bpp < 24) - psize = (offset - 14 - 24) / 3; - } else { - compress = get32le(s); - if (compress == 1 || compress == 2) return epuc("BMP RLE", "BMP type not supported: RLE"); - get32le(s); // discard sizeof - get32le(s); // discard hres - get32le(s); // discard vres - get32le(s); // discard colorsused - get32le(s); // discard max important - if (hsz == 40 || hsz == 56) { - if (hsz == 56) { - get32le(s); - get32le(s); - get32le(s); - get32le(s); - } - if (bpp == 16 || bpp == 32) { - mr = mg = mb = 0; - if (compress == 0) { - if (bpp == 32) { - mr = 0xff << 16; - mg = 0xff << 8; - mb = 0xff << 0; - ma = 0xff << 24; - fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255 - } else { - mr = 31 << 10; - mg = 31 << 5; - mb = 31 << 0; - } - } else if (compress == 3) { - mr = get32le(s); - mg = get32le(s); - mb = get32le(s); - // not documented, but generated by photoshop and handled by mspaint - if (mr == mg && mg == mb) { - // ?!?!? - return NULL; - } - } else - return NULL; - } - } else { - assert(hsz == 108); - mr = get32le(s); - mg = get32le(s); - mb = get32le(s); - ma = get32le(s); - get32le(s); // discard color space - for (i=0; i < 12; ++i) - get32le(s); // discard color space parameters - } - if (bpp < 16) - psize = (offset - 14 - hsz) >> 2; - } - s->img_n = ma ? 4 : 3; - if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 - target = req_comp; - else - target = s->img_n; // if they want monochrome, we'll post-convert - out = (stbi_uc *) malloc(target * s->img_x * s->img_y); - if (!out) return epuc("outofmem", "Out of memory"); - if (bpp < 16) { - int z=0; - if (psize == 0 || psize > 256) { free(out); return epuc("invalid", "Corrupt BMP"); } - for (i=0; i < psize; ++i) { - pal[i][2] = get8(s); - pal[i][1] = get8(s); - pal[i][0] = get8(s); - if (hsz != 12) get8(s); - pal[i][3] = 255; - } - skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); - if (bpp == 4) width = (s->img_x + 1) >> 1; - else if (bpp == 8) width = s->img_x; - else { free(out); return epuc("bad bpp", "Corrupt BMP"); } - pad = (-width)&3; - for (j=0; j < (int) s->img_y; ++j) { - for (i=0; i < (int) s->img_x; i += 2) { - int v=get8(s),v2=0; - if (bpp == 4) { - v2 = v & 15; - v >>= 4; - } - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; - if (i+1 == (int) s->img_x) break; - v = (bpp == 8) ? get8(s) : v2; - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; - } - skip(s, pad); - } - } else { - int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; - int z = 0; - int easy=0; - skip(s, offset - 14 - hsz); - if (bpp == 24) width = 3 * s->img_x; - else if (bpp == 16) width = 2*s->img_x; - else /* bpp = 32 and pad = 0 */ width=0; - pad = (-width) & 3; - if (bpp == 24) { - easy = 1; - } else if (bpp == 32) { - if (mb == 0xff && mg == 0xff00 && mr == 0xff000000 && ma == 0xff000000) - easy = 2; - } - if (!easy) { - if (!mr || !mg || !mb) return epuc("bad masks", "Corrupt BMP"); - // right shift amt to put high bit in position #7 - rshift = high_bit(mr)-7; rcount = bitcount(mr); - gshift = high_bit(mg)-7; gcount = bitcount(mr); - bshift = high_bit(mb)-7; bcount = bitcount(mr); - ashift = high_bit(ma)-7; acount = bitcount(mr); - } - for (j=0; j < (int) s->img_y; ++j) { - if (easy) { - for (i=0; i < (int) s->img_x; ++i) { - int a; - out[z+2] = get8(s); - out[z+1] = get8(s); - out[z+0] = get8(s); - z += 3; - a = (easy == 2 ? get8(s) : 255); - if (target == 4) out[z++] = a; - } - } else { - for (i=0; i < (int) s->img_x; ++i) { - uint32 v = (bpp == 16 ? get16le(s) : get32le(s)); - int a; - out[z++] = shiftsigned(v & mr, rshift, rcount); - out[z++] = shiftsigned(v & mg, gshift, gcount); - out[z++] = shiftsigned(v & mb, bshift, bcount); - a = (ma ? shiftsigned(v & ma, ashift, acount) : 255); - if (target == 4) out[z++] = a; - } - } - skip(s, pad); - } - } - if (flip_vertically) { - stbi_uc t; - for (j=0; j < (int) s->img_y>>1; ++j) { - stbi_uc *p1 = out + j *s->img_x*target; - stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; - for (i=0; i < (int) s->img_x*target; ++i) { - t = p1[i], p1[i] = p2[i], p2[i] = t; - } - } - } - - if (req_comp && req_comp != target) { - out = convert_format(out, target, req_comp, s->img_x, s->img_y); - if (out == NULL) return out; // convert_format frees input on failure - } - - *x = s->img_x; - *y = s->img_y; - if (comp) *comp = target; - return out; -} - -#ifndef STBI_NO_STDIO -stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp) -{ - stbi_uc *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_bmp_load_from_file(f, x,y,comp,req_comp); - fclose(f); - return data; -} - -stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_file(&s, f); - return bmp_load(&s, x,y,comp,req_comp); -} -#endif - -stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_mem(&s, buffer, len); - return bmp_load(&s, x,y,comp,req_comp); -} - -// Targa Truevision - TGA -// by Jonathan Dummer - -static int tga_test(stbi *s) -{ - int sz; - get8u(s); // discard Offset - sz = get8u(s); // color type - if( sz > 1 ) return 0; // only RGB or indexed allowed - sz = get8u(s); // image type - if( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE - get16(s); // discard palette start - get16(s); // discard palette length - get8(s); // discard bits per palette color entry - get16(s); // discard x origin - get16(s); // discard y origin - if( get16(s) < 1 ) return 0; // test width - if( get16(s) < 1 ) return 0; // test height - sz = get8(s); // bits per pixel - if( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) ) return 0; // only RGB or RGBA or grey allowed - return 1; // seems to have passed everything -} - -#ifndef STBI_NO_STDIO -int stbi_tga_test_file (FILE *f) -{ - stbi s; - int r,n = ftell(f); - start_file(&s, f); - r = tga_test(&s); - fseek(f,n,SEEK_SET); - return r; -} -#endif - -int stbi_tga_test_memory (stbi_uc const *buffer, int len) -{ - stbi s; - start_mem(&s, buffer, len); - return tga_test(&s); -} - -static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) -{ - // read in the TGA header stuff - int tga_offset = get8u(s); - int tga_indexed = get8u(s); - int tga_image_type = get8u(s); - int tga_is_RLE = 0; - int tga_palette_start = get16le(s); - int tga_palette_len = get16le(s); - int tga_palette_bits = get8u(s); - int tga_x_origin = get16le(s); - int tga_y_origin = get16le(s); - int tga_width = get16le(s); - int tga_height = get16le(s); - int tga_bits_per_pixel = get8u(s); - int tga_inverted = get8u(s); - // image data - unsigned char *tga_data; - unsigned char *tga_palette = NULL; - int i, j; - unsigned char raw_data[4]; - unsigned char trans_data[4] = {0,0,0,0}; - int RLE_count = 0; - int RLE_repeating = 0; - int read_next_pixel = 1; - // do a tiny bit of precessing - if( tga_image_type >= 8 ) - { - tga_image_type -= 8; - tga_is_RLE = 1; - } - /* int tga_alpha_bits = tga_inverted & 15; */ - tga_inverted = 1 - ((tga_inverted >> 5) & 1); - - // error check - if( //(tga_indexed) || - (tga_width < 1) || (tga_height < 1) || - (tga_image_type < 1) || (tga_image_type > 3) || - ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && - (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) - ) - { - return NULL; - } - - // If I'm paletted, then I'll use the number of bits from the palette - if( tga_indexed ) - { - tga_bits_per_pixel = tga_palette_bits; - } - - // tga info - *x = tga_width; - *y = tga_height; - if( (req_comp < 1) || (req_comp > 4) ) - { - // just use whatever the file was - req_comp = tga_bits_per_pixel / 8; - *comp = req_comp; - } else - { - // force a new number of components - *comp = tga_bits_per_pixel/8; - } - tga_data = (unsigned char*)malloc( tga_width * tga_height * req_comp ); - - // skip to the data's starting position (offset usually = 0) - skip(s, tga_offset ); - // do I need to load a palette? - if( tga_indexed ) - { - // any data to skip? (offset usually = 0) - skip(s, tga_palette_start ); - // load the palette - tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); - getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 ); - } - // load the data - for( i = 0; i < tga_width * tga_height; ++i ) - { - // if I'm in RLE mode, do I need to get a RLE chunk? - if( tga_is_RLE ) - { - if( RLE_count == 0 ) - { - // yep, get the next byte as a RLE command - int RLE_cmd = get8u(s); - RLE_count = 1 + (RLE_cmd & 127); - RLE_repeating = RLE_cmd >> 7; - read_next_pixel = 1; - } else if( !RLE_repeating ) - { - read_next_pixel = 1; - } - } else - { - read_next_pixel = 1; - } - // OK, if I need to read a pixel, do it now - if( read_next_pixel ) - { - // load however much data we did have - if( tga_indexed ) - { - // read in 1 byte, then perform the lookup - int pal_idx = get8u(s); - if( pal_idx >= tga_palette_len ) - { - // invalid index - pal_idx = 0; - } - pal_idx *= tga_bits_per_pixel / 8; - for( j = 0; j*8 < tga_bits_per_pixel; ++j ) - { - raw_data[j] = tga_palette[pal_idx+j]; - } - } else - { - // read in the data raw - for( j = 0; j*8 < tga_bits_per_pixel; ++j ) - { - raw_data[j] = get8u(s); - } - } - // convert raw to the intermediate format - switch( tga_bits_per_pixel ) - { - case 8: - // Luminous => RGBA - trans_data[0] = raw_data[0]; - trans_data[1] = raw_data[0]; - trans_data[2] = raw_data[0]; - trans_data[3] = 255; - break; - case 16: - // Luminous,Alpha => RGBA - trans_data[0] = raw_data[0]; - trans_data[1] = raw_data[0]; - trans_data[2] = raw_data[0]; - trans_data[3] = raw_data[1]; - break; - case 24: - // BGR => RGBA - trans_data[0] = raw_data[2]; - trans_data[1] = raw_data[1]; - trans_data[2] = raw_data[0]; - trans_data[3] = 255; - break; - case 32: - // BGRA => RGBA - trans_data[0] = raw_data[2]; - trans_data[1] = raw_data[1]; - trans_data[2] = raw_data[0]; - trans_data[3] = raw_data[3]; - break; - default: - return NULL; - } - // clear the reading flag for the next pixel - read_next_pixel = 0; - } // end of reading a pixel - // convert to final format - switch( req_comp ) - { - case 1: - // RGBA => Luminance - tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); - break; - case 2: - // RGBA => Luminance,Alpha - tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); - tga_data[i*req_comp+1] = trans_data[3]; - break; - case 3: - // RGBA => RGB - tga_data[i*req_comp+0] = trans_data[0]; - tga_data[i*req_comp+1] = trans_data[1]; - tga_data[i*req_comp+2] = trans_data[2]; - break; - case 4: - // RGBA => RGBA - tga_data[i*req_comp+0] = trans_data[0]; - tga_data[i*req_comp+1] = trans_data[1]; - tga_data[i*req_comp+2] = trans_data[2]; - tga_data[i*req_comp+3] = trans_data[3]; - break; - } - // in case we're in RLE mode, keep counting down - --RLE_count; - } - // do I need to invert the image? - if( tga_inverted ) - { - for( j = 0; j*2 < tga_height; ++j ) - { - int index1 = j * tga_width * req_comp; - int index2 = (tga_height - 1 - j) * tga_width * req_comp; - for( i = tga_width * req_comp; i > 0; --i ) - { - unsigned char temp = tga_data[index1]; - tga_data[index1] = tga_data[index2]; - tga_data[index2] = temp; - ++index1; - ++index2; - } - } - } - // clear my palette, if I had one - if( tga_palette != NULL ) - { - free( tga_palette ); - } - // the things I do to get rid of an error message, and yet keep - // Microsoft's C compilers happy... [8^( - tga_palette_start = tga_palette_len = tga_palette_bits = - tga_x_origin = tga_y_origin = 0; - // OK, done - return tga_data; -} - -#ifndef STBI_NO_STDIO -stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp) -{ - stbi_uc *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_tga_load_from_file(f, x,y,comp,req_comp); - fclose(f); - return data; -} - -stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_file(&s, f); - return tga_load(&s, x,y,comp,req_comp); -} -#endif - -stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_mem(&s, buffer, len); - return tga_load(&s, x,y,comp,req_comp); -} - - -// ************************************************************************************************* -// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicholas Schulz, tweaked by STB - -static int psd_test(stbi *s) -{ - if (get32(s) != 0x38425053) return 0; // "8BPS" - else return 1; -} - -#ifndef STBI_NO_STDIO -int stbi_psd_test_file(FILE *f) -{ - stbi s; - int r,n = ftell(f); - start_file(&s, f); - r = psd_test(&s); - fseek(f,n,SEEK_SET); - return r; -} -#endif - -int stbi_psd_test_memory(stbi_uc const *buffer, int len) -{ - stbi s; - start_mem(&s, buffer, len); - return psd_test(&s); -} - -static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) -{ - int pixelCount; - int channelCount, compression; - int channel, i, count, len; - int w,h; - uint8 *out; - - // Check identifier - if (get32(s) != 0x38425053) // "8BPS" - return epuc("not PSD", "Corrupt PSD image"); - - // Check file type version. - if (get16(s) != 1) - return epuc("wrong version", "Unsupported version of PSD image"); - - // Skip 6 reserved bytes. - skip(s, 6 ); - - // Read the number of channels (R, G, B, A, etc). - channelCount = get16(s); - if (channelCount < 0 || channelCount > 16) - return epuc("wrong channel count", "Unsupported number of channels in PSD image"); - - // Read the rows and columns of the image. - h = get32(s); - w = get32(s); - - // Make sure the depth is 8 bits. - if (get16(s) != 8) - return epuc("unsupported bit depth", "PSD bit depth is not 8 bit"); - - // Make sure the color mode is RGB. - // Valid options are: - // 0: Bitmap - // 1: Grayscale - // 2: Indexed color - // 3: RGB color - // 4: CMYK color - // 7: Multichannel - // 8: Duotone - // 9: Lab color - if (get16(s) != 3) - return epuc("wrong color format", "PSD is not in RGB color format"); - - // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) - skip(s,get32(s) ); - - // Skip the image resources. (resolution, pen tool paths, etc) - skip(s, get32(s) ); - - // Skip the reserved data. - skip(s, get32(s) ); - - // Find out if the data is compressed. - // Known values: - // 0: no compression - // 1: RLE compressed - compression = get16(s); - if (compression > 1) - return epuc("bad compression", "PSD has an unknown compression format"); - - // Create the destination image. - out = (stbi_uc *) malloc(4 * w*h); - if (!out) return epuc("outofmem", "Out of memory"); - pixelCount = w*h; - - // Initialize the data to zero. - //memset( out, 0, pixelCount * 4 ); - - // Finally, the image data. - if (compression) { - // RLE as used by .PSD and .TIFF - // Loop until you get the number of unpacked bytes you are expecting: - // Read the next source byte into n. - // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. - // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. - // Else if n is 128, noop. - // Endloop - - // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, - // which we're going to just skip. - skip(s, h * channelCount * 2 ); - - // Read the RLE data by channel. - for (channel = 0; channel < 4; channel++) { - uint8 *p; - - p = out+channel; - if (channel >= channelCount) { - // Fill this channel with default data. - for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4; - } else { - // Read the RLE data. - count = 0; - while (count < pixelCount) { - len = get8(s); - if (len == 128) { - // No-op. - } else if (len < 128) { - // Copy next len+1 bytes literally. - len++; - count += len; - while (len) { - *p = get8(s); - p += 4; - len--; - } - } else if (len > 128) { - uint32 val; - // Next -len+1 bytes in the dest are replicated from next source byte. - // (Interpret len as a negative 8-bit int.) - len ^= 0x0FF; - len += 2; - val = get8(s); - count += len; - while (len) { - *p = val; - p += 4; - len--; - } - } - } - } - } - - } else { - // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) - // where each channel consists of an 8-bit value for each pixel in the image. - - // Read the data by channel. - for (channel = 0; channel < 4; channel++) { - uint8 *p; - - p = out + channel; - if (channel > channelCount) { - // Fill this channel with default data. - for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4; - } else { - // Read the data. - count = 0; - for (i = 0; i < pixelCount; i++) - *p = get8(s), p += 4; - } - } - } - - if (req_comp && req_comp != 4) { - out = convert_format(out, 4, req_comp, w, h); - if (out == NULL) return out; // convert_format frees input on failure - } - - if (comp) *comp = channelCount; - *y = h; - *x = w; - - return out; -} - -#ifndef STBI_NO_STDIO -stbi_uc *stbi_psd_load(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - stbi_uc *data; - FILE *f = fopen(filename, "rb"); - if (!f) return NULL; - data = stbi_psd_load_from_file(f, x,y,comp,req_comp); - fclose(f); - return data; -} - -stbi_uc *stbi_psd_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_file(&s, f); - return psd_load(&s, x,y,comp,req_comp); -} -#endif - -stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_mem(&s, buffer, len); - return psd_load(&s, x,y,comp,req_comp); -} - - -// ************************************************************************************************* -// Radiance RGBE HDR loader -// originally by Nicolas Schulz -#ifndef STBI_NO_HDR -static int hdr_test(stbi *s) -{ - const char *signature = "#?RADIANCE\n"; - int i; - for (i=0; signature[i]; ++i) - if (get8(s) != signature[i]) - return 0; - return 1; -} - -int stbi_hdr_test_memory(stbi_uc const *buffer, int len) -{ - stbi s; - start_mem(&s, buffer, len); - return hdr_test(&s); -} - -#ifndef STBI_NO_STDIO -int stbi_hdr_test_file(FILE *f) -{ - stbi s; - int r,n = ftell(f); - start_file(&s, f); - r = hdr_test(&s); - fseek(f,n,SEEK_SET); - return r; -} -#endif - -#define HDR_BUFLEN 1024 -static char *hdr_gettoken(stbi *z, char *buffer) -{ - int len=0; - char c = '\0'; - - c = get8(z); - - while (!at_eof(z) && c != '\n') { - buffer[len++] = c; - if (len == HDR_BUFLEN-1) { - // flush to end of line - while (!at_eof(z) && get8(z) != '\n') - ; - break; - } - c = get8(z); - } - - buffer[len] = 0; - return buffer; -} - -static void hdr_convert(float *output, stbi_uc *input, int req_comp) -{ - if( input[3] != 0 ) { - float f1; - // Exponent - f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); - if (req_comp <= 2) - output[0] = (input[0] + input[1] + input[2]) * f1 / 3; - else { - output[0] = input[0] * f1; - output[1] = input[1] * f1; - output[2] = input[2] * f1; - } - if (req_comp == 2) output[1] = 1; - if (req_comp == 4) output[3] = 1; - } else { - switch (req_comp) { - case 4: output[3] = 1; /* fallthrough */ - case 3: output[0] = output[1] = output[2] = 0; - break; - case 2: output[1] = 1; /* fallthrough */ - case 1: output[0] = 0; - break; - } - } -} - - -static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) -{ - char buffer[HDR_BUFLEN]; - char *token; - int valid = 0; - int width, height; - stbi_uc *scanline; - float *hdr_data; - int len; - unsigned char count, value; - int i, j, k, c1,c2, z; - - - // Check identifier - if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) - return epf("not HDR", "Corrupt HDR image"); - - // Parse header - while(1) { - token = hdr_gettoken(s,buffer); - if (token[0] == 0) break; - if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; - } - - if (!valid) return epf("unsupported format", "Unsupported HDR format"); - - // Parse width and height - // can't use sscanf() if we're not using stdio! - token = hdr_gettoken(s,buffer); - if (strncmp(token, "-Y ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); - token += 3; - height = strtol(token, &token, 10); - while (*token == ' ') ++token; - if (strncmp(token, "+X ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); - token += 3; - width = strtol(token, NULL, 10); - - *x = width; - *y = height; - - *comp = 3; - if (req_comp == 0) req_comp = 3; - - // Read data - hdr_data = (float *) malloc(height * width * req_comp * sizeof(float)); - - // Load image data - // image data is stored as some number of sca - if( width < 8 || width >= 32768) { - // Read flat data - for (j=0; j < height; ++j) { - for (i=0; i < width; ++i) { - stbi_uc rgbe[4]; - main_decode_loop: - getn(s, rgbe, 4); - hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); - } - } - } else { - // Read RLE-encoded data - scanline = NULL; - - for (j = 0; j < height; ++j) { - c1 = get8(s); - c2 = get8(s); - len = get8(s); - if (c1 != 2 || c2 != 2 || (len & 0x80)) { - // not run-length encoded, so we have to actually use THIS data as a decoded - // pixel (note this can't be a valid pixel--one of RGB must be >= 128) - stbi_uc rgbe[4] = { c1,c2,len, get8(s) }; - hdr_convert(hdr_data, rgbe, req_comp); - i = 1; - j = 0; - free(scanline); - goto main_decode_loop; // yes, this is fucking insane; blame the fucking insane format - } - len <<= 8; - len |= get8(s); - if (len != width) { free(hdr_data); free(scanline); return epf("invalid decoded scanline length", "corrupt HDR"); } - if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4); - - for (k = 0; k < 4; ++k) { - i = 0; - while (i < width) { - count = get8(s); - if (count > 128) { - // Run - value = get8(s); - count -= 128; - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = value; - } else { - // Dump - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = get8(s); - } - } - } - for (i=0; i < width; ++i) - hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); - } - free(scanline); - } - - return hdr_data; -} - -static stbi_uc *hdr_load_rgbe(stbi *s, int *x, int *y, int *comp, int req_comp) -{ - char buffer[HDR_BUFLEN]; - char *token; - int valid = 0; - int width, height; - stbi_uc *scanline; - stbi_uc *rgbe_data; - int len; - unsigned char count, value; - int i, j, k, c1,c2, z; - - - // Check identifier - if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) - return epuc("not HDR", "Corrupt HDR image"); - - // Parse header - while(1) { - token = hdr_gettoken(s,buffer); - if (token[0] == 0) break; - if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; - } - - if (!valid) return epuc("unsupported format", "Unsupported HDR format"); - - // Parse width and height - // can't use sscanf() if we're not using stdio! - token = hdr_gettoken(s,buffer); - if (strncmp(token, "-Y ", 3)) return epuc("unsupported data layout", "Unsupported HDR format"); - token += 3; - height = strtol(token, &token, 10); - while (*token == ' ') ++token; - if (strncmp(token, "+X ", 3)) return epuc("unsupported data layout", "Unsupported HDR format"); - token += 3; - width = strtol(token, NULL, 10); - - *x = width; - *y = height; - - // RGBE _MUST_ come out as 4 components - *comp = 4; - req_comp = 4; - - // Read data - rgbe_data = (stbi_uc *) malloc(height * width * req_comp * sizeof(stbi_uc)); - // point to the beginning - scanline = rgbe_data; - - // Load image data - // image data is stored as some number of scan lines - if( width < 8 || width >= 32768) { - // Read flat data - for (j=0; j < height; ++j) { - for (i=0; i < width; ++i) { - main_decode_loop: - //getn(rgbe, 4); - getn(s,scanline, 4); - scanline += 4; - } - } - } else { - // Read RLE-encoded data - for (j = 0; j < height; ++j) { - c1 = get8(s); - c2 = get8(s); - len = get8(s); - if (c1 != 2 || c2 != 2 || (len & 0x80)) { - // not run-length encoded, so we have to actually use THIS data as a decoded - // pixel (note this can't be a valid pixel--one of RGB must be >= 128) - scanline[0] = c1; - scanline[1] = c2; - scanline[2] = len; - scanline[3] = get8(s); - scanline += 4; - i = 1; - j = 0; - goto main_decode_loop; // yes, this is insane; blame the insane format - } - len <<= 8; - len |= get8(s); - if (len != width) { free(rgbe_data); return epuc("invalid decoded scanline length", "corrupt HDR"); } - for (k = 0; k < 4; ++k) { - i = 0; - while (i < width) { - count = get8(s); - if (count > 128) { - // Run - value = get8(s); - count -= 128; - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = value; - } else { - // Dump - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = get8(s); - } - } - } - // move the scanline on - scanline += 4 * width; - } - } - - return rgbe_data; -} - -#ifndef STBI_NO_STDIO -float *stbi_hdr_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_file(&s,f); - return hdr_load(&s,x,y,comp,req_comp); -} - -stbi_uc *stbi_hdr_load_rgbe_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_file(&s,f); - return hdr_load_rgbe(&s,x,y,comp,req_comp); -} - -stbi_uc *stbi_hdr_load_rgbe (char const *filename, int *x, int *y, int *comp, int req_comp) -{ - FILE *f = fopen(filename, "rb"); - unsigned char *result; - if (!f) return epuc("can't fopen", "Unable to open file"); - result = stbi_hdr_load_rgbe_file(f,x,y,comp,req_comp); - fclose(f); - return result; -} -#endif - -float *stbi_hdr_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_mem(&s,buffer, len); - return hdr_load(&s,x,y,comp,req_comp); -} - -stbi_uc *stbi_hdr_load_rgbe_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi s; - start_mem(&s,buffer, len); - return hdr_load_rgbe(&s,x,y,comp,req_comp); -} - -#endif // STBI_NO_HDR - -/////////////////////// write image /////////////////////// - -#ifndef STBI_NO_WRITE - -static void write8(FILE *f, int x) { uint8 z = (uint8) x; fwrite(&z,1,1,f); } - -static void writefv(FILE *f, const char *fmt, va_list v) -{ - while (*fmt) { - switch (*fmt++) { - case ' ': break; - case '1': { uint8 x = va_arg(v, int); write8(f,x); break; } - case '2': { int16 x = va_arg(v, int); write8(f,x); write8(f,x>>8); break; } - case '4': { int32 x = va_arg(v, int); write8(f,x); write8(f,x>>8); write8(f,x>>16); write8(f,x>>24); break; } - default: - assert(0); - va_end(v); - return; - } - } -} - -static void writef(FILE *f, const char *fmt, ...) -{ - va_list v; - va_start(v, fmt); - writefv(f,fmt,v); - va_end(v); -} - -static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad) -{ - uint8 bg[3] = { 255, 0, 255}, px[3]; - uint32 zero = 0; - int i,j,k, j_end; - - if (vdir < 0) - j_end = -1, j = y-1; - else - j_end = y, j = 0; - - for (; j != j_end; j += vdir) { - for (i=0; i < x; ++i) { - uint8 *d = (uint8 *) data + (j*x+i)*comp; - if (write_alpha < 0) - fwrite(&d[comp-1], 1, 1, f); - switch (comp) { - case 1: - case 2: writef(f, "111", d[0],d[0],d[0]); - break; - case 4: - if (!write_alpha) { - for (k=0; k < 3; ++k) - px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255; - writef(f, "111", px[1-rgb_dir],px[1],px[1+rgb_dir]); - break; - } - /* FALLTHROUGH */ - case 3: - writef(f, "111", d[1-rgb_dir],d[1],d[1+rgb_dir]); - break; - } - if (write_alpha > 0) - fwrite(&d[comp-1], 1, 1, f); - } - fwrite(&zero,scanline_pad,1,f); - } -} - -static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...) -{ - FILE *f = fopen(filename, "wb"); - if (f) { - va_list v; - va_start(v, fmt); - writefv(f, fmt, v); - va_end(v); - write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad); - fclose(f); - } - return f != NULL; -} - -int stbi_write_bmp(char const *filename, int x, int y, int comp, void *data) -{ - int pad = (-x*3) & 3; - return outfile(filename,-1,-1,x,y,comp,data,0,pad, - "11 4 22 4" "4 44 22 444444", - 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header - 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header -} - -int stbi_write_tga(char const *filename, int x, int y, int comp, void *data) -{ - int has_alpha = !(comp & 1); - return outfile(filename, -1,-1, x, y, comp, data, has_alpha, 0, - "111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); -} - -// any other image formats that do interleaved rgb data? -// PNG: requires adler32,crc32 -- significant amount of code -// PSD: no, channels output separately -// TIFF: no, stripwise-interleaved... i think - -#endif // STBI_NO_WRITE - -// add in my DDS loading support -#ifndef STBI_NO_DDS -#include "stbi_DDS_aug_c.h" -#endif + fwrite(&zero,scanline_pad,1,f); + } +} + +static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...) +{ + FILE *f = fopen(filename, "wb"); + if (f) { + va_list v; + va_start(v, fmt); + writefv(f, fmt, v); + va_end(v); + write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad); + fclose(f); + } + return f != NULL; +} + +int stbi_write_bmp(char const *filename, int x, int y, int comp, void *data) +{ + int pad = (-x*3) & 3; + return outfile(filename,-1,-1,x,y,comp,data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +int stbi_write_tga(char const *filename, int x, int y, int comp, void *data) +{ + int has_alpha = !(comp & 1); + return outfile(filename, -1,-1, x, y, comp, data, has_alpha, 0, + "111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); +} + +// any other image formats that do interleaved rgb data? +// PNG: requires adler32,crc32 -- significant amount of code +// PSD: no, channels output separately +// TIFF: no, stripwise-interleaved... i think + +#endif // STBI_NO_WRITE + +// add in my DDS loading support +#ifndef STBI_NO_DDS +#include "stbi_DDS_aug_c.h" +#endif diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/definitions.h dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/definitions.h --- dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/definitions.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/definitions.h 2010-08-18 03:25:26.000000000 +0100 @@ -34,7 +34,7 @@ #ifndef DEFINITIONS_H_INCLUDED #define DEFINITIONS_H_INCLUDED -#ifndef WIN32 +#ifndef _WIN32 #include "Log.h" // NOTICE_LEVEL is more appropriate for the uses of WIIUSE_INFO than INFO_LEVEL diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/io_nix.c dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/io_nix.c --- dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/io_nix.c 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/io_nix.c 2010-08-18 03:25:26.000000000 +0100 @@ -22,17 +22,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * - * $Header$ - * - */ - -/** - * @file - * @brief Handles device I/O for *nix. */ -#ifndef WIN32 - #include #include @@ -48,190 +39,121 @@ #include #include -#include "definitions.h" #include "wiiuse_internal.h" - + static int wiiuse_connect_single(struct wiimote_t* wm, char* address); -/** - * @brief Find a wiimote or wiimotes. - * - * @param wm An array of wiimote_t structures. - * @param max_wiimotes The number of wiimote structures in \a wm. - * @param timeout The number of seconds before the search times out. - * - * @return The number of wiimotes found. - * - * @see wiimote_connect() - * - * This function will only look for wiimote devices. \n - * When a device is found the address in the structures will be set. \n - * You can then call wiimote_connect() to connect to the found \n - * devices. - */ -int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { +// Find a wiimote or wiimotes. +// Does not replace already found wiimotes even if they are disconnected. +// wm An array of wiimote_t structures. +// max_wiimotes The number of wiimote structures in wm. +// timeout The number of seconds before the search times out. +// Returns the total number of found wiimotes. +// This function will only look for wiimote devices. +// When a device is found the address in the structures will be set. +// You can then call wiimote_connect() to connect to the found devices. +int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) +{ int device_id; int device_sock; int found_devices; - int found_wiimotes; + int found_wiimotes = 0; + int i; - /* reset all wiimote bluetooth device addresses */ - for (found_wiimotes = 0; found_wiimotes < max_wiimotes; ++found_wiimotes) - wm[found_wiimotes]->bdaddr = *BDADDR_ANY; - found_wiimotes = 0; + // Count the number of already found wiimotes + for (i = 0; i < max_wiimotes; ++i) + { + if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) + found_wiimotes++; + } - /* get the id of the first bluetooth device. */ + // get the id of the first bluetooth device. device_id = hci_get_route(NULL); - if (device_id < 0) { + if (device_id < 0) + { perror("hci_get_route"); return 0; } - /* create a socket to the device */ + // create a socket to the device device_sock = hci_open_dev(device_id); - if (device_sock < 0) { + if (device_sock < 0) + { perror("hci_open_dev"); return 0; } - inquiry_info scan_info_arr[128]; - inquiry_info* scan_info = scan_info_arr; - memset(&scan_info_arr, 0, sizeof(scan_info_arr)); - - /* scan for bluetooth devices for 'timeout' seconds */ - found_devices = hci_inquiry(device_id, timeout, 128, NULL, &scan_info, IREQ_CACHE_FLUSH); - if (found_devices < 0) { - perror("hci_inquiry"); - return 0; - } - - WIIUSE_INFO("Found %i bluetooth device(s).", found_devices); - - int i = 0; - - /* display discovered devices */ - for (; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) { - if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) && - (scan_info[i].dev_class[1] == WM_DEV_CLASS_1) && - (scan_info[i].dev_class[2] == WM_DEV_CLASS_2)) + int try_num = 0; + while ((try_num < timeout) && (found_wiimotes < max_wiimotes)) + { + inquiry_info scan_info_arr[128]; + inquiry_info* scan_info = scan_info_arr; + memset(&scan_info_arr, 0, sizeof(scan_info_arr)); + + // scan for bluetooth devices for ~one second + found_devices = hci_inquiry(device_id, 1, 128, NULL, &scan_info, IREQ_CACHE_FLUSH); + if (found_devices < 0) { - /* found a device */ - ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str); - - WIIUSE_INFO("Found wiimote (%s) [id %i].", wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid); - - wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr; - WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND); - ++found_wiimotes; + perror("hci_inquiry"); + return 0; } - } - - close(device_sock); - return found_wiimotes; -} -// Scan for more wiimotes and add them to the wm structure. -// Does not replace already found wiimotes even if they are disconnected. -// Returns the total number of found wiimotes. -// It would probably be safe to replace wiiuse_find with this function. The only thing -// it does that this does not is reset the bdaddr fields. -int wiiuse_find_more(struct wiimote_t** wm, int max_wiimotes, int timeout) { -int device_id; -int device_sock; -int found_devices; -int found_wiimotes = 0; -int i; - -// Count the number of already found wiimotes -for (i = 0; i < max_wiimotes; ++i) { - if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) - found_wiimotes++; -} - -// get the id of the first bluetooth device. -device_id = hci_get_route(NULL); -if (device_id < 0) { - perror("hci_get_route"); - return 0; -} - -// create a socket to the device -device_sock = hci_open_dev(device_id); -if (device_sock < 0) { - perror("hci_open_dev"); - return 0; -} + WIIUSE_INFO("Found %i bluetooth device(s).", found_devices); -inquiry_info scan_info_arr[128]; -inquiry_info* scan_info = scan_info_arr; -memset(&scan_info_arr, 0, sizeof(scan_info_arr)); - -// scan for bluetooth devices for timeout seconds -found_devices = hci_inquiry(device_id, timeout, 128, NULL, &scan_info, IREQ_CACHE_FLUSH); -if (found_devices < 0) { - perror("hci_inquiry"); - return 0; -} - -WIIUSE_INFO("Found %i bluetooth device(s).", found_devices); - -// display discovered devices -for (i = 0; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) { - if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) && - (scan_info[i].dev_class[1] == WM_DEV_CLASS_1) && - (scan_info[i].dev_class[2] == WM_DEV_CLASS_2)) - { - int new_wiimote = 1; - int j; - // Determine if this wiimote has already been found. - for (j = 0; j < found_wiimotes && new_wiimote; ++j) - { - if (WIIMOTE_IS_SET(wm[j], WIIMOTE_STATE_DEV_FOUND) && - bacmp(&scan_info[i].bdaddr,&wm[j]->bdaddr) == 0) - new_wiimote = 0; - } - - if (new_wiimote) + // display discovered devices + for (i = 0; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) { - // found a new device - ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str); - - WIIUSE_INFO("Found wiimote (%s) [id %i].", wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid); - - wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr; - WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND); - ++found_wiimotes; + if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) && + (scan_info[i].dev_class[1] == WM_DEV_CLASS_1) && + (scan_info[i].dev_class[2] == WM_DEV_CLASS_2)) + { + int new_wiimote = 1; + int j; + // Determine if this wiimote has already been found. + for (j = 0; j < found_wiimotes && new_wiimote; ++j) + { + if (WIIMOTE_IS_SET(wm[j], WIIMOTE_STATE_DEV_FOUND) && + bacmp(&scan_info[i].bdaddr,&wm[j]->bdaddr) == 0) + new_wiimote = 0; + } + + if (new_wiimote) + { + // found a new device + ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str); + + WIIUSE_INFO("Found wiimote (%s) [id %i].", + wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid); + + wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr; + WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND); + ++found_wiimotes; + } + } } + try_num++; } -} -close(device_sock); -return found_wiimotes; + close(device_sock); + return found_wiimotes; } -/** - * @brief Connect to a wiimote or wiimotes once an address is known. - * - * @param wm An array of wiimote_t structures. - * @param wiimotes The number of wiimote structures in \a wm. - * - * @return The number of wiimotes that successfully connected. - * - * @see wiiuse_find() - * @see wiiuse_connect_single() - * @see wiiuse_disconnect() - * - * Connect to a number of wiimotes when the address is already set - * in the wiimote_t structures. These addresses are normally set - * by the wiiuse_find() function, but can also be set manually. - */ -int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { +// Connect to a wiimote or wiimotes once an address is known. +// wm An array of wiimote_t structures. +// wiimotes The number of wiimote structures in wm. +// Return the number of wiimotes that successfully connected. +// Connect to a number of wiimotes when the address is already set +// in the wiimote_t structures. These addresses are normally set +// by the wiiuse_find() function, but can also be set manually. +int wiiuse_connect(struct wiimote_t** wm, int wiimotes) +{ int connected = 0; int i = 0; - for (; i < wiimotes; ++i) { + for (; i < wiimotes; ++i) + { if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) - /* if the device address is not set, skip it */ + // if the device address is not set, skip it continue; if (wiiuse_connect_single(wm[i], NULL)) @@ -241,17 +163,13 @@ return connected; } - -/** - * @brief Connect to a wiimote with a known address. - * - * @param wm Pointer to a wiimote_t structure. - * @param address The address of the device to connect to. - * If NULL, use the address in the struct set by wiiuse_find(). - * - * @return 1 on success, 0 on failure - */ -static int wiiuse_connect_single(struct wiimote_t* wm, char* address) { +// Connect to a wiimote with a known address. +// wm Pointer to a wiimote_t structure. +// address The address of the device to connect to. +// If NULL, use the address in the struct set by wiiuse_find(). +// Return 1 on success, 0 on failure +static int wiiuse_connect_single(struct wiimote_t* wm, char* address) +{ struct sockaddr_l2 addr; if (!wm || WIIMOTE_IS_CONNECTED(wm)) @@ -260,20 +178,18 @@ addr.l2_family = AF_BLUETOOTH; bdaddr_t *bdaddr = &wm->bdaddr; if (address) - /* use provided address */ + // use provided address str2ba(address, &addr.l2_bdaddr); else { if (bacmp(bdaddr, BDADDR_ANY) == 0) return 0; - /* use address of device discovered */ + // use address of device discovered addr.l2_bdaddr = *bdaddr; - + } - /* - * OUTPUT CHANNEL - */ + // OUTPUT CHANNEL wm->out_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); if (wm->out_sock == -1) return 0; @@ -281,17 +197,17 @@ addr.l2_cid = 0; addr.l2_psm = htobs(WM_OUTPUT_CHANNEL); - /* connect to wiimote */ - if (connect(wm->out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + // connect to wiimote + if (connect(wm->out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) + { perror("connect() output sock"); return 0; } - /* - * INPUT CHANNEL - */ + // INPUT CHANNEL wm->in_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); - if (wm->in_sock == -1) { + if (wm->in_sock == -1) + { close(wm->out_sock); wm->out_sock = -1; return 0; @@ -299,8 +215,9 @@ addr.l2_psm = htobs(WM_INPUT_CHANNEL); - /* connect to wiimote */ - if (connect(wm->in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + // connect to wiimote + if (connect(wm->in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) + { perror("connect() interrupt sock"); close(wm->out_sock); wm->out_sock = -1; @@ -308,25 +225,19 @@ } WIIUSE_INFO("Connected to wiimote [id %i].", wm->unid); - /* do the handshake */ + // do the handshake WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); - + wiiuse_set_report_type(wm); return 1; } - -/** - * @brief Disconnect a wiimote. - * - * @param wm Pointer to a wiimote_t structure. - * - * @see wiiuse_connect() - * - * Note that this will not free the wiimote structure. - */ -void wiiuse_disconnect(struct wiimote_t* wm) { +// Disconnect a wiimote. +// wm Pointer to a wiimote_t structure. +// Note that this will not free the wiimote structure. +void wiiuse_disconnect(struct wiimote_t* wm) +{ if (!wm || !WIIMOTE_IS_CONNECTED(wm)) return; @@ -340,58 +251,65 @@ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); } -int wiiuse_io_read(struct wiimote_t* wm) { + +int wiiuse_io_read(struct wiimote_t* wm) +{ struct timeval tv; fd_set fds; int r; if (!wm) return 0; - /* block select() for 1/2000th of a second */ + // block select() for 1/2000th of a second tv.tv_sec = 0; tv.tv_usec = wm->timeout * 1000; // timeout is in Milliseconds tv_usec is in Microseconds! FD_ZERO(&fds); - /* only poll it if it is connected */ - if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED)) { + // only poll it if it is connected + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED)) + { FD_SET(wm->in_sock, &fds); //highest_fd = wm[i]->in_sock; } else - /* nothing to poll */ + // nothing to poll return 0; - if (select(wm->in_sock + 1, &fds, NULL, NULL, &tv) == -1) { + if (select(wm->in_sock + 1, &fds, NULL, NULL, &tv) == -1) + { WIIUSE_ERROR("Unable to select() the wiimote interrupt socket(s)."); perror("Error Details"); return 0; } - /* if this wiimote is not connected, skip it */ + // if this wiimote is not connected, skip it if (!WIIMOTE_IS_CONNECTED(wm)) return 0; if (FD_ISSET(wm->in_sock, &fds)) { //memset(wm->event_buf, 0, sizeof(wm->event_buf)); - /* read the pending message into the buffer */ + // read the pending message into the buffer r = read(wm->in_sock, wm->event_buf, sizeof(wm->event_buf)); - if (r == -1) { - /* error reading data */ + if (r == -1) + { + // error reading data WIIUSE_ERROR("Receiving wiimote data (id %i).", wm->unid); perror("Error Details"); - if (errno == ENOTCONN) { - /* this can happen if the bluetooth dongle is disconnected */ + if (errno == ENOTCONN) + { + // this can happen if the bluetooth dongle is disconnected WIIUSE_ERROR("Bluetooth appears to be disconnected. Wiimote unid %i will be disconnected.", wm->unid); wiiuse_disconnect(wm); wm->event = WIIUSE_UNEXPECTED_DISCONNECT; } - + return 0; } - if (!r) { - /* remote disconnect */ + if (!r) + { + // remote disconnect wiiuse_disconnected(wm); return 0; } @@ -401,14 +319,9 @@ return 0; } - int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) { if(buf[0] == 0xa2) buf[0] = 0x52; // May not be needed. Will be changing/correcting in the next few revisions return write(wm->out_sock, buf, len); } - - - -#endif /* ifndef WIN32 */ diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/io_osx.m dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/io_osx.m --- dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/io_osx.m 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/io_osx.m 2010-08-18 03:25:26.000000000 +0100 @@ -31,6 +31,8 @@ * @brief Handles device I/O for OS X. */ +#import +extern OSErr UpdateSystemActivity(UInt8 activity); #define BLUETOOTH_VERSION_USE_CURRENT #import #import @@ -55,7 +57,7 @@ @interface SearchBT: NSObject { @public - int maxDevices; + unsigned int maxDevices; } @end @@ -113,6 +115,8 @@ } CFRunLoopStop(CFRunLoopGetCurrent()); + + UpdateSystemActivity(1); } - (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel @@ -172,7 +176,6 @@ majorDeviceClass: kBluetoothDeviceClassMajorPeripheral minorDeviceClass: kBluetoothDeviceClassMinorPeripheral2Joystick ]; - [bti setUpdateNewDeviceNames: NO]; IOReturn ret = [bti start]; if (ret == kIOReturnSuccess) diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/io_win.c dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/io_win.c --- dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/io_win.c 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/io_win.c 2010-08-18 03:25:26.000000000 +0100 @@ -31,7 +31,7 @@ * @brief Handles device I/O for Windows. */ -#ifdef WIN32 +#ifdef _WIN32 #include #include @@ -44,6 +44,8 @@ #include "definitions.h" #include "wiiuse_internal.h" +int wiiuse_remove(struct wiimote_t** wm, int wiimotes, int max_wiimotes); + int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int wiimotes) { GUID device_id; HANDLE dev; @@ -58,8 +60,8 @@ // todo: handle/remove (unexpected and forced) disconnected wiimotes here // removal of unneeded wiimotes and exiting when we got enough wiimotes connected - if(wiiuse_remove(wm, wiimotes, max_wiimotes)) - return wm; + if (wiiuse_remove(wm, wiimotes, max_wiimotes)) + return max_wiimotes; device_data.cbSize = sizeof(device_data); @@ -69,7 +71,7 @@ // get all hid devices connected device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); - for (;wiimotes < max_wiimotes; ++index) { + for (index = 0; wiimotes < max_wiimotes; ++index) { if (detail_data) { free(detail_data); @@ -398,4 +400,4 @@ } -#endif /* ifdef WIN32 */ +#endif /* ifdef _WIN32 */ diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/ir.c dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/ir.c --- dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/ir.c 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/ir.c 2010-08-18 03:25:26.000000000 +0100 @@ -34,7 +34,7 @@ #include #include -#ifndef WIN32 +#ifndef _WIN32 #include #endif diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/SConscript dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/SConscript --- dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/SConscript 2010-08-18 03:25:26.000000000 +0100 @@ -3,11 +3,10 @@ Import('env') import sys -if (sys.platform == 'linux2' and not env['HAVE_BLUEZ']) or \ - (not sys.platform == 'darwin' and - not sys.platform == 'linux2' and - not sys.platform == 'win32'): - env['HAVE_WIIUSE'] = 0 +env['HAVE_WIIUSE'] = 0 + +if not sys.platform == 'darwin' and not sys.platform == 'win32' and \ + not (sys.platform == 'linux2' and env['HAVE_BLUEZ']): Return() env['HAVE_WIIUSE'] = 1 @@ -25,3 +24,4 @@ files += [ "io_win.c" ] env.StaticLibrary(env['local_libs'] + "wiiuse", files) +env['CPPPATH'] += ['#Externals/WiiUse/Src'] diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/wiiuse.c dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/wiiuse.c --- dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/wiiuse.c 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/wiiuse.c 2010-08-18 03:25:26.000000000 +0100 @@ -38,7 +38,7 @@ #include #include -#ifndef WIN32 +#ifndef _WIN32 #include #else #include @@ -352,7 +352,7 @@ { int x = 2; printf("[DEBUG] (id %i) SEND: (%x) %.2x ", wm->unid, buf[0], buf[1]); - #ifndef WIN32 + #ifndef _WIN32 for (; x < len+2; ++x) #else for (; x < len+1; ++x) @@ -376,7 +376,7 @@ * @param type The type of bluetooth stack to use. */ void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type) { - #ifdef WIN32 + #ifdef _WIN32 int i; if (!wm) return; diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/wiiuse.h dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/wiiuse.h --- dolphin-emu-2.0+svn5985/Externals/WiiUse/Src/wiiuse.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/Src/wiiuse.h 2010-08-18 03:25:26.000000000 +0100 @@ -220,17 +220,12 @@ WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm); WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte timeout); -#ifdef WIN32 +#ifdef _WIN32 WIIUSE_EXPORT extern int wiiuse_check_system_notification(unsigned int nMsg, WPARAM wParam, LPARAM lParam); WIIUSE_EXPORT extern int wiiuse_register_system_notification(HWND hwnd); #endif -#ifdef __linux__ -int wiiuse_find_more(struct wiimote_t** wm, int max_wiimotes, int timeout); -#endif - /* ir.c */ - WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level); /* io.c */ diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/wiiuse.sln dolphin-emu-2.0+svn6107/Externals/WiiUse/wiiuse.sln --- dolphin-emu-2.0+svn5985/Externals/WiiUse/wiiuse.sln 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/wiiuse.sln 2010-08-18 03:25:26.000000000 +0100 @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wiiuse", "wiiuse.vcproj", "{944EF6DE-471D-447E-A2FD-D37D58805169}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wiiuse", "wiiuse.vcproj", "{52F70249-373A-4401-A70A-FF22760EC1B8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,14 +11,14 @@ Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {944EF6DE-471D-447E-A2FD-D37D58805169}.Debug|Win32.ActiveCfg = Debug|Win32 - {944EF6DE-471D-447E-A2FD-D37D58805169}.Debug|Win32.Build.0 = Debug|Win32 - {944EF6DE-471D-447E-A2FD-D37D58805169}.Debug|x64.ActiveCfg = Debug|x64 - {944EF6DE-471D-447E-A2FD-D37D58805169}.Debug|x64.Build.0 = Debug|x64 - {944EF6DE-471D-447E-A2FD-D37D58805169}.Release|Win32.ActiveCfg = Release|Win32 - {944EF6DE-471D-447E-A2FD-D37D58805169}.Release|Win32.Build.0 = Release|Win32 - {944EF6DE-471D-447E-A2FD-D37D58805169}.Release|x64.ActiveCfg = Release|x64 - {944EF6DE-471D-447E-A2FD-D37D58805169}.Release|x64.Build.0 = Release|x64 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Debug|Win32.ActiveCfg = Debug|Win32 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Debug|Win32.Build.0 = Debug|Win32 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Debug|x64.ActiveCfg = Debug|x64 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Debug|x64.Build.0 = Debug|x64 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Release|Win32.ActiveCfg = Release|Win32 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Release|Win32.Build.0 = Release|Win32 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Release|x64.ActiveCfg = Release|x64 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff -Nru dolphin-emu-2.0+svn5985/Externals/WiiUse/wiiuse.vcproj dolphin-emu-2.0+svn6107/Externals/WiiUse/wiiuse.vcproj --- dolphin-emu-2.0+svn5985/Externals/WiiUse/wiiuse.vcproj 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/WiiUse/wiiuse.vcproj 2010-08-18 03:25:26.000000000 +0100 @@ -1,11 +1,11 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - Binary files /tmp/ovcw8AKJFk/dolphin-emu-2.0+svn5985/Externals/WiiUse/Win32/wiiuse.dll and /tmp/z1I4AwGv79/dolphin-emu-2.0+svn6107/Externals/WiiUse/Win32/wiiuse.dll differ Binary files /tmp/ovcw8AKJFk/dolphin-emu-2.0+svn5985/Externals/WiiUse/Win32/wiiuse.lib and /tmp/z1I4AwGv79/dolphin-emu-2.0+svn6107/Externals/WiiUse/Win32/wiiuse.lib differ Binary files /tmp/ovcw8AKJFk/dolphin-emu-2.0+svn5985/Externals/WiiUse/X64/wiiuse.dll and /tmp/z1I4AwGv79/dolphin-emu-2.0+svn6107/Externals/WiiUse/X64/wiiuse.dll differ Binary files /tmp/ovcw8AKJFk/dolphin-emu-2.0+svn5985/Externals/WiiUse/X64/wiiuse.lib and /tmp/z1I4AwGv79/dolphin-emu-2.0+svn6107/Externals/WiiUse/X64/wiiuse.lib differ diff -Nru dolphin-emu-2.0+svn5985/Externals/zlib/SConscript dolphin-emu-2.0+svn6107/Externals/zlib/SConscript --- dolphin-emu-2.0+svn5985/Externals/zlib/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Externals/zlib/SConscript 2010-08-18 03:25:36.000000000 +0100 @@ -2,6 +2,9 @@ Import('env') +if env.has_key('shared_zlib') and env['shared_zlib']: + Return() + files = [ 'adler32.c', 'compress.c', @@ -18,3 +21,4 @@ ] env.StaticLibrary(env['local_libs'] + "z", files) +env['CPPPATH'] += ['#Externals/zlib'] diff -Nru dolphin-emu-2.0+svn5985/SconsTests/utils.py dolphin-emu-2.0+svn6107/SconsTests/utils.py --- dolphin-emu-2.0+svn5985/SconsTests/utils.py 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/SconsTests/utils.py 2010-08-19 18:28:29.000000000 +0100 @@ -17,7 +17,7 @@ int main(int argc, char **argv) { return 0; } - \n""", '.c') + \n""", '.cpp') if not ret: context.env.Replace(LIBS = lastLIBS) @@ -30,14 +30,14 @@ if ret: context.env.ParseConfig('pkg-config --cflags --libs \'%s\'' % name) return int(ret) - + def CheckPKG(context, name): context.Message( 'Checking for %s... ' % name ) if platform.system().lower() == 'windows': - return 0 + return 0 ret = 1 if not ConfigPKG(context, name.lower()): - ret = CheckLib(context, name) + ret = CheckLib(context, name) context.Result(ret) return int(ret) @@ -52,27 +52,27 @@ else: found_ver = os.popen('sdl-config --version').read().strip() required = [int(n) for n in version.split(".")] - found = [int(n) for n in found_ver.split(".")] + found = [int(n) for n in found_ver.split(".")] ret = (found >= required) - + context.Result(ret) if ret: context.env.ParseConfig('sdl-config --cflags --libs') ret = CheckLib(context, 'SDL') return int(ret) - + def CheckPortaudio(context, version): found = 0 if CheckPKG(context, 'portaudio'): context.Message( 'Checking for lib portaudio version > %s... ' % version) - found = context.TryRun(""" + found = context.TryRun(""" #include #include int main(int argc, char **argv) { printf("%d", Pa_GetVersion()); return 0; } - \n""", '.c')[1] + \n""", '.cpp')[1] if found: ret = (version <= found) @@ -81,18 +81,22 @@ context.Result(ret) return int(ret) - -def GenerateRevFile(flavour, template, output): +def GenerateRevFile(flavour, template, output): try: - svnrev = os.popen('svnversion .').read().strip().split(':')[0] + svnrev = os.popen('svnversion ' + os.path.dirname(template)).\ + read().strip().split(':')[0] except: - svnrev = "" - - revstr = svnrev + "-" + flavour - tmpstr = open(template, "r").read().replace("$WCMODS?$WCREV$M:$WCREV$$",revstr) - outfile = open(output, 'w') - outfile.write(tmpstr +"\n") - outfile.close() - - return revstr + svnrev = '' + + if flavour: + svnrev += '-' + flavour + + if output: + tmpstr = open(template, 'r').read().\ + replace("$WCMODS?$WCREV$M:$WCREV$$", svnrev) + outfile = open(output, 'w') + outfile.write(tmpstr + '\n') + outfile.close() + + return svnrev diff -Nru dolphin-emu-2.0+svn5985/SconsTests/wxconfig.py dolphin-emu-2.0+svn6107/SconsTests/wxconfig.py --- dolphin-emu-2.0+svn5985/SconsTests/wxconfig.py 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/SconsTests/wxconfig.py 2010-08-18 03:25:25.000000000 +0100 @@ -7,7 +7,6 @@ # import os, os.path import re -import sys import glob import string @@ -151,7 +150,7 @@ # use `wx-config --debug` if it's in its help helpoutput = SystemWXConfig(context.env,'--help')[1] if helpoutput.find('--debug') != -1: - context.Message('--debug') + context.Message('--debug ') if SystemWXConfig(context.env,'--debug --libs')[0] == 0: context.env['wxconfig'] = context.env['wxconfig'] +' --debug' return CheckWXConfigVersion(context, version) diff -Nru dolphin-emu-2.0+svn5985/SConstruct dolphin-emu-2.0+svn6107/SConstruct --- dolphin-emu-2.0+svn5985/SConstruct 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/SConstruct 2010-08-18 03:25:25.000000000 +0100 @@ -5,13 +5,15 @@ import platform # Home made tests -sys.path.append('SconsTests') -import wxconfig -import utils +from SconsTests import utils +from SconsTests import wxconfig # Some features need at least SCons 1.2 EnsureSConsVersion(1, 2) +# Construction presets for platform +env = Environment(ENV = os.environ) + # Handle command line options vars = Variables('args.cache') @@ -19,43 +21,37 @@ BoolVariable('verbose', 'Set to show compilation lines', False), BoolVariable('bundle', 'Set to create distribution bundle', False), BoolVariable('lint', 'Set for lint build (fail on warnings)', False), - BoolVariable('nowx', 'Set for building with no WX libs', False), + BoolVariable('nowx', 'Set for building without wxWidgets', False), PathVariable('wxconfig', 'Path to wxconfig', None), - EnumVariable('flavor', 'Choose a build flavor', 'release', - allowed_values = ('release','devel','debug','fastlog','prof'), - ignorecase = 2), + EnumVariable('flavor', 'Choose a build flavor', 'release', allowed_values = + ('release','devel','debug','fastlog','prof'), ignorecase = 2), ) -if not sys.platform == 'win32' and not sys.platform == 'darwin': - vars.AddVariables( - PathVariable('destdir', - 'Temporary install location (for package building)', - None, PathVariable.PathAccept), - EnumVariable('install', - 'Choose a local or global installation', 'local', - allowed_values = ('local', 'global'), ignorecase = 2), - PathVariable('prefix', - 'Installation prefix (only used for a global build)', - '/usr', PathVariable.PathAccept), - PathVariable('userdir', - 'Set the name of the user data directory in home', - '.dolphin-emu', PathVariable.PathAccept), - BoolVariable('opencl', 'Build with OpenCL', False), - EnumVariable('pgo', 'Profile-Guided Optimization (generate or use)', - 'none', allowed_values = ('none', 'generate', 'use'), - ignorecase = 2), - BoolVariable('shared_glew', 'Use system shared libGLEW', True), - BoolVariable('shared_lzo', 'Use system shared liblzo2', True), - BoolVariable('shared_sdl', 'Use system shared libSDL', True), - BoolVariable('shared_sfml', 'Use system shared libsfml-network', True), - BoolVariable('shared_soil', 'Use system shared libSOIL', True), - BoolVariable('shared_zlib', 'Use system shared libz', True), - ('CC', 'The C compiler', 'gcc'), - ('CXX', 'The C++ compiler', 'g++'), - ) +if env['PLATFORM'] == 'posix': vars.AddVariables( + PathVariable('destdir', 'Temporary install location (for package building)', + None, PathVariable.PathAccept), + EnumVariable('install', 'Choose a local or global installation', 'local', + allowed_values = ('local', 'global'), ignorecase = 2), + PathVariable('prefix', 'Installation prefix (only used for a global build)', + '/usr', PathVariable.PathAccept), + PathVariable('userdir', 'Set the name of the user data directory in home', + '.dolphin-emu', PathVariable.PathAccept), + BoolVariable('opencl', 'Build with OpenCL', False), + EnumVariable('pgo', 'Profile-Guided Optimization (generate or use)', 'none', + allowed_values = ('none', 'generate', 'use'), ignorecase = 2), + BoolVariable('shared_glew', 'Use system shared libGLEW', True), + BoolVariable('shared_lzo', 'Use system shared liblzo2', True), + BoolVariable('shared_sdl', 'Use system shared libSDL', True), + BoolVariable('shared_sfml', 'Use system shared libsfml-network', True), + BoolVariable('shared_soil', 'Use system shared libSOIL', True), + BoolVariable('shared_zlib', 'Use system shared libz', True), + PathVariable('CC', 'The C compiler', 'gcc', PathVariable.PathAccept), + PathVariable('CXX', 'The C++ compiler', 'g++', PathVariable.PathAccept), + ) -env = Environment(ENV = os.environ, variables = vars) -Export('env') +# Save the given command line options +vars.Update(env) +vars.Save('args.cache', env) # Die on unknown variables unknown = vars.UnknownVariables() @@ -63,61 +59,6 @@ print "Unknown variables:", unknown.keys() Exit(1) -# Save the given command line options -vars.Save('args.cache', env) - -cppDefines = [ - ( '_FILE_OFFSET_BITS', 64), - '_LARGEFILE_SOURCE', - 'GCC_HASCLASSVISIBILITY', - ] - -ccFlags = [ - '-Wall', - '-Wpacked', - '-Wpointer-arith', - '-Wshadow', - '-Wwrite-strings', - '-fPIC', - '-fno-exceptions', - '-fno-strict-aliasing', - '-fvisibility=hidden', - '-msse2', - ] - -if env['CCVERSION'] >= '4.3.0': ccFlags += [ - '-Wno-array-bounds', # False positives - '-Wno-unused-result', # Too many syscalls - ] - -# Build flavor -if env['flavor'] == 'debug': - ccFlags.append('-ggdb') - cppDefines.append('_DEBUG') #enables LOGGING - # FIXME: this disable wx debugging how do we make it work? - cppDefines.append('NDEBUG') -elif env['flavor'] == 'devel': - ccFlags.append('-ggdb') -elif env['flavor'] == 'fastlog': - ccFlags.append('-O3') - cppDefines.append('DEBUGFAST') -elif env['flavor'] == 'prof': - ccFlags.append('-O3') - ccFlags.append('-ggdb') -elif env['flavor'] == 'release': - ccFlags.append('-O3') - ccFlags.append('-fomit-frame-pointer'); - -if env['flavor'] == 'debug': - extra = '-debug' -elif env['flavor'] == 'prof': - extra = '-prof' -else: - extra = '' - -if env['lint']: - ccFlags.append('-Werror') - # Verbose compile if not env['verbose']: env['ARCOMSTR'] = "Archiving $TARGET" @@ -132,31 +73,35 @@ env['SHLINKCOMSTR'] = "Linking $TARGET" env['TARCOMSTR'] = "Creating $TARGET" -dirs = [ - 'Externals/Bochs_disasm', - 'Externals/Lua', - 'Externals/MemcardManager', - 'Externals/WiiUse/Src', - 'Source/Core/AudioCommon/Src', - 'Source/Core/Common/Src', - 'Source/Core/Core/Src', - 'Source/Core/DSPCore/Src', - 'Source/Core/DebuggerUICommon/Src', - 'Source/Core/DebuggerWX/Src', - 'Source/Core/DiscIO/Src', - 'Source/Core/DolphinWX/Src', - 'Source/Core/InputCommon/Src', - 'Source/Core/InputUICommon/Src', - 'Source/Core/VideoCommon/Src', - 'Source/DSPTool/Src', - 'Source/Plugins/Plugin_DSP_HLE/Src', - 'Source/Plugins/Plugin_DSP_LLE/Src', - 'Source/Plugins/Plugin_VideoOGL/Src', - 'Source/Plugins/Plugin_VideoSoftware/Src', - 'Source/Plugins/Plugin_Wiimote/Src', - 'Source/Plugins/Plugin_WiimoteNew/Src', - 'Source/UnitTests', - ] +if not env['flavor'] == 'debug': + env['CCFLAGS'] += ['-O3'] +if env['flavor'] == 'release': + env['CCFLAGS'] += ['-fomit-frame-pointer'] +elif not env['flavor'] == 'fastlog': + env['CCFLAGS'] += ['-ggdb'] +env['CCFLAGS'] += ['-fno-exceptions', '-fno-strict-aliasing'] +if env['CCVERSION'] >= '4.2.0': + env['CCFLAGS'] += ['-fvisibility=hidden'] + env['CXXFLAGS'] += ['-fvisibility-inlines-hidden'] + +if env['lint']: + env['CCFLAGS'] += ['-Werror'] +env['CCFLAGS'] += ['-Wall', '-Wextra'] +env['CCFLAGS'] += ['-Wno-missing-field-initializers', '-Wno-unused-parameter'] +env['CCFLAGS'] += ['-Wpacked', '-Wpointer-arith', '-Wshadow', '-Wwrite-strings'] +if env['CCVERSION'] < '4.2.0': + env['CCFLAGS'] += ['-Wno-pragmas'] +if env['CCVERSION'] >= '4.3.0': + env['CCFLAGS'] += ['-Wno-array-bounds', '-Wno-unused-result'] + +env['CPPDEFINES'] = [] +if env['flavor'] == 'debug': + env['CPPDEFINES'] += ['_DEBUG'] +elif env['flavor'] == 'fastlog': + env['CPPDEFINES'] += ['DEBUGFAST'] +env['CPPPATH'] = ['#Source/PluginSpecs'] +env['LIBPATH'] = [] +env['LIBS'] = [] # Object files env['build_dir'] = 'Build' + os.sep + platform.system() + \ @@ -168,73 +113,69 @@ # Default install path if not env.has_key('install') or env['install'] == 'local': env['prefix'] = 'Binary' + os.sep + platform.system() + \ - '-' + platform.machine() + extra + '-' + platform.machine() + if env['flavor'] == 'debug' or env['flavor'] == 'prof': + env['prefix'] += '-' + env['flavor'] -# Configuration tests section -tests = {'CheckWXConfig' : wxconfig.CheckWXConfig, - 'CheckPKGConfig' : utils.CheckPKGConfig, - 'CheckPKG' : utils.CheckPKG, - 'CheckSDL' : utils.CheckSDL, - 'CheckPortaudio' : utils.CheckPortaudio, - } - -rev = utils.GenerateRevFile(env['flavor'], - "Source/Core/Common/Src/svnrev_template.h", - "Source/Core/Common/Src/svnrev.h") - -env['CCFLAGS'] = ccFlags -env['CPPDEFINES'] = cppDefines -env['CPPPATH'] = ['#' + path for path in dirs] -env['CPPPATH'] += ['#Source/PluginSpecs'] -env['CXXFLAGS'] = ['-fvisibility-inlines-hidden'] -env['LIBPATH'] = [] -env['LIBS'] = [] -env['RPATH'] = [] +rev = utils.GenerateRevFile(env['flavor'], '.', None) # OS X specifics if sys.platform == 'darwin': - gccflags = ['-arch', 'x86_64', '-arch', 'i386', '-mmacosx-version-min=10.5'] - env['CCFLAGS'] += gccflags - env['CCFLAGS'] += ['-Wextra-tokens', '-Wnewline-eof'] + ccld = ['-arch', 'x86_64', '-arch', 'i386', '-mmacosx-version-min=10.5'] + env['CCFLAGS'] += ccld + env['CCFLAGS'] += ['-msse3'] env['CC'] = "gcc-4.2 -ObjC" env['CXX'] = "g++-4.2 -ObjC++" + #env['FRAMEWORKPATH'] += [ + # '/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks', + # '/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks'] env['FRAMEWORKS'] += ['AppKit', 'CoreFoundation', 'CoreServices'] env['FRAMEWORKS'] += ['AudioUnit', 'CoreAudio'] env['FRAMEWORKS'] += ['IOBluetooth', 'IOKit', 'OpenGL'] - env['LIBS'] += ['iconv'] - env['LINKFLAGS'] += gccflags - env['LINKFLAGS'] += ['-Z', '-L/Developer/SDKs/MacOSX10.5.sdk/usr/lib', + env['LIBPATH'] += ['/Developer/SDKs/MacOSX10.5.sdk/usr/lib'] + env['LIBS'] = ['gcc_s.10.5', 'iconv'] + env['LINKFLAGS'] += ccld + env['LINKFLAGS'] += ['-Wl,-search_paths_first', '-Wl,-Z'] + env['LINKFLAGS'] += [ '-F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks', '-F/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks'] + if platform.mac_ver()[0] < '10.6.0': env['HAVE_OPENCL'] = 0 else: + env['CCFLAGS'] += ['-Wextra-tokens', '-Wnewline-eof'] env['HAVE_OPENCL'] = 1 - env['LINKFLAGS'] += ['-weak_framework', 'OpenCL'] + env['FRAMEWORKSFLAGS'] = ['-weak_framework', 'OpenCL'] + if env['nowx']: env['HAVE_WX'] = 0 else: - conf = env.Configure(custom_tests = tests) - env['HAVE_WX'] = conf.CheckWXConfig(2.9, - ['aui', 'adv', 'core', 'base', 'gl'], 0) + wxenv = env.Clone(LIBPATH = '') + conf = wxenv.Configure(conf_dir = None, log_file = None, + custom_tests = {'CheckWXConfig' : wxconfig.CheckWXConfig}) + env['HAVE_WX'] = \ + conf.CheckWXConfig(2.9, 'aui adv core base gl'.split(), + env['flavor'] == 'debug') conf.Finish() - # wx-config wants us to link with the OS X QuickTime framework - # which is not available for x86_64 and we don't use it anyway. - # Strip it out to silence some harmless linker warnings. - # In the 10.5 SDK, Carbon is only partially built for x86_64. - frameworks = env['FRAMEWORKS'] - wxconfig.ParseWXConfig(env) - if env['CPPDEFINES'].count('WXUSINGDLL'): - env['FRAMEWORKS'] = frameworks + if not env['HAVE_WX']: + print "wxWidgets 2.9 not found using " + env['wxconfig'] + Exit(1) + wxconfig.ParseWXConfig(wxenv) + env['CPPDEFINES'] += ['__WXOSX_COCOA__'] + env['CPPPATH'] = wxenv['CPPPATH'] + if not wxenv['CPPDEFINES'].count('WXUSINGDLL'): + env['FRAMEWORKS'] = wxenv['FRAMEWORKS'] + env['LIBPATH'] += wxenv['LIBPATH'] + env['LIBS'] = wxenv['LIBS'] + env['CPPPATH'] += ['#Externals'] + env['FRAMEWORKPATH'] += ['Externals/Cg'] env['FRAMEWORKS'] += ['Cg'] - env['LINKFLAGS'] += ['-FExternals/Cg'] env['shared_zlib'] = True + env['data_dir'] = '#' + env['prefix'] + '/Dolphin.app/Contents/Resources' env['plugin_dir'] = '#' + env['prefix'] + '/Dolphin.app/Contents/PlugIns' - env.Install(env['data_dir'], 'Data/Sys') - env.Install(env['data_dir'], 'Data/User') - dirs += ['Externals/dylibbundler'] + if env['bundle']: app = env['prefix'] + '/Dolphin.app' dmg = env['prefix'] + '/Dolphin-r' + rev + '.dmg' @@ -243,16 +184,24 @@ ' && hdiutil internet-enable -yes ' + dmg) elif sys.platform == 'win32': - env['tools'] = ['mingw'] - dirs += ['Source/Plugins/Plugin_VideoDX9/Src'] - dirs += ['Source/Plugins/Plugin_VideoDX11/Src'] + pass else: - env['CCFLAGS'] += ['-pthread'] - env['CXXFLAGS'] += ['-Wno-deprecated'] # XXX - env['CPPPATH'].insert(0, '#') + env['CCFLAGS'] += ['-fPIC', '-msse2'] + env['CPPPATH'].insert(0, '#') # Make sure we pick up our own config.h + if sys.platform == 'linux2': + env['CPPDEFINES'] += [('_FILE_OFFSET_BITS', 64), '_LARGEFILE_SOURCE'] + env['CXXFLAGS'] += ['-Wno-deprecated'] # XXX env['LINKFLAGS'] += ['-pthread'] - conf = env.Configure(custom_tests = tests, config_h="#config.h") + env['RPATH'] = [] + + conf = env.Configure(config_h = "#config.h", custom_tests = { + 'CheckPKG' : utils.CheckPKG, + 'CheckPKGConfig' : utils.CheckPKGConfig, + 'CheckPortaudio' : utils.CheckPortaudio, + 'CheckSDL' : utils.CheckSDL, + 'CheckWXConfig' : wxconfig.CheckWXConfig, + }) if not conf.CheckPKGConfig('0.15.0'): print "Can't find pkg-config, some tests will fail" @@ -279,16 +228,14 @@ if env['nowx']: env['HAVE_WX'] = 0 else: - env['HAVE_WX'] = conf.CheckWXConfig(2.8, - ['aui', 'adv', 'core', 'base'], 0) + env['HAVE_WX'] = conf.CheckWXConfig(2.8, 'aui adv core base'.split(), + env['flavor'] == 'debug') conf.Define('HAVE_WX', env['HAVE_WX']) wxconfig.ParseWXConfig(env) if not env['HAVE_WX']: - print "WX libraries not found - see config.log" + print "wxWidgets not found - see config.log" Exit(1) - conf.CheckPKG('usbhid') - env['HAVE_BLUEZ'] = conf.CheckPKG('bluez') conf.Define('HAVE_BLUEZ', env['HAVE_BLUEZ']) @@ -300,7 +247,7 @@ conf.Define('HAVE_OPENAL', env['HAVE_OPENAL']) env['HAVE_PORTAUDIO'] = conf.CheckPortaudio(1890) conf.Define('HAVE_PORTAUDIO', env['HAVE_PORTAUDIO']) - env['HAVE_PULSEAUDIO'] = conf.CheckPKG('libpulse-simple') + env['HAVE_PULSEAUDIO'] = conf.CheckPKG('libpulse') conf.Define('HAVE_PULSEAUDIO', env['HAVE_PULSEAUDIO']) env['HAVE_X11'] = conf.CheckPKG('x11') @@ -308,7 +255,6 @@ conf.Define('HAVE_XRANDR', env['HAVE_XRANDR']) conf.Define('HAVE_X11', env['HAVE_X11']) - # Check for GTK 2.0 or newer if env['HAVE_WX'] and not conf.CheckPKG('gtk+-2.0'): print "gtk+-2.0 developement headers not detected" print "gtk+-2.0 is required to build the WX GUI" @@ -334,18 +280,18 @@ env['HAVE_OPENCL'] = 0 # PGO - Profile Guided Optimization - if env['pgo']=='generate': - ccFlags.append('-fprofile-generate') - env['LINKFLAGS']='-fprofile-generate' - if env['pgo']=='use': - ccFlags.append('-fprofile-use') - env['LINKFLAGS']='-fprofile-use' + if env['pgo'] == 'generate': + env['CCFLAGS'] += ['-fprofile-generate'] + env['LINKFLAGS'] += ['-fprofile-generate'] + if env['pgo'] == 'use': + env['CCFLAGS'] += ['-fprofile-use'] + env['LINKFLAGS'] += ['-fprofile-use'] # Profiling - if (env['flavor'] == 'prof'): - proflibs = [ '/usr/lib/oprofile', '/usr/local/lib/oprofile' ] - env['LIBPATH'].append(proflibs) - env['RPATH'].append(proflibs) + if env['flavor'] == 'prof': + proflibs = ['/usr/lib/oprofile', '/usr/local/lib/oprofile'] + env['LIBPATH'] += ['proflibs'] + env['RPATH'] += ['proflibs'] if conf.CheckPKG('opagent'): conf.Define('USE_OPROFILE', 1) else: @@ -366,7 +312,7 @@ env['binary_dir'] = env['prefix'] + '/bin' env['data_dir'] = env['prefix'] + "/share/dolphin-emu" env['plugin_dir'] = env['prefix'] + '/lib/dolphin-emu' - conf.Define('DATA_DIR', "\"" + env['data_dir'] + "\"") + conf.Define('DATA_DIR', "\"" + env['data_dir'] + "/\"") conf.Define('LIBS_DIR', "\"" + env['prefix'] + '/lib/' + "\"") # Setup destdir for package building # Warning: The program will not run from this location. @@ -388,10 +334,6 @@ # After all configuration tests are done conf.Finish() - # Data install - env.InstallAs(env['data_dir'] + '/sys', 'Data/Sys') - env.InstallAs(env['data_dir'] + '/user', 'Data/User') - env.Alias('install', env['prefix']) # Local (static) libraries must be first in the search path for the build in @@ -399,32 +341,52 @@ # during autoconfiguration as they will then be detected as system libraries. env['LIBPATH'].insert(0, env['local_libs']) -if not env.has_key('shared_glew') or not env['shared_glew']: - env['CPPPATH'] += ['#Externals/GLew/include'] - dirs += ['Externals/GLew'] -if not env.has_key('shared_lzo') or not env['shared_lzo']: - env['CPPPATH'] += ['#Externals/LZO'] - dirs += ['Externals/LZO'] -if not env.has_key('shared_sdl') or not env['shared_sdl']: - env['CPPPATH'] += ['#Externals/SDL'] - env['CPPPATH'] += ['#Externals/SDL/include'] - dirs += ['Externals/SDL'] -if not env.has_key('shared_soil') or not env['shared_soil']: - env['CPPPATH'] += ['#Externals/SOIL'] - dirs += ['Externals/SOIL'] -if not env.has_key('shared_sfml') or not env['shared_sfml']: - env['CPPPATH'] += ['#Externals/SFML/include'] - dirs += ['Externals/SFML/src'] -if not env.has_key('shared_zlib') or not env['shared_zlib']: - env['CPPPATH'] += ['#Externals/zlib'] - dirs += ['Externals/zlib'] +dirs = [ + 'Externals/Bochs_disasm', + #'Externals/CLRun', + 'Externals/Lua', + 'Externals/MemcardManager', + 'Externals/WiiUse/Src', + 'Externals/GLew', + 'Externals/LZO', + #'Externals/OpenAL', + 'Externals/SDL', + 'Externals/SOIL', + 'Externals/SFML/src', + #'Externals/wxWidgets', + 'Externals/zlib', + 'Source/Core/AudioCommon/Src', + 'Source/Core/Common/Src', + 'Source/Core/Core/Src', + 'Source/Core/DSPCore/Src', + 'Source/Core/DebuggerUICommon/Src', + 'Source/Core/DebuggerWX/Src', + 'Source/Core/DiscIO/Src', + 'Source/Core/DolphinWX/Src', + 'Source/Core/InputCommon/Src', + 'Source/Core/InputUICommon/Src', + 'Source/Core/VideoCommon/Src', + 'Source/DSPTool/Src', + 'Source/Plugins/Plugin_DSP_HLE/Src', + 'Source/Plugins/Plugin_DSP_LLE/Src', + #'Source/Plugins/Plugin_VideoDX11/Src', + #'Source/Plugins/Plugin_VideoDX9/Src', + 'Source/Plugins/Plugin_VideoOGL/Src', + 'Source/Plugins/Plugin_VideoSoftware/Src', + 'Source/Plugins/Plugin_Wiimote/Src', + 'Source/Plugins/Plugin_WiimoteNew/Src', + 'Source/UnitTests', + ] +# Now that platform configuration is done, propagate it to modules for subdir in dirs: - SConscript(subdir + os.sep + 'SConscript', - variant_dir = env['build_dir'] + os.sep + subdir, duplicate = 0) + SConscript(dirs = subdir, duplicate = 0, exports = 'env', + variant_dir = env['build_dir'] + os.sep + subdir) + if subdir.startswith('Source/Core'): + env['CPPPATH'] += ['#' + subdir] # Print a nice progress indication when not compiling Progress(['-\r', '\\\r', '|\r', '/\r'], interval = 5) -# Generate help +# Generate help, printing current status of options Help(vars.GenerateHelpText(env)) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/AudioCommon/Src/Mixer.cpp dolphin-emu-2.0+svn6107/Source/Core/AudioCommon/Src/Mixer.cpp --- dolphin-emu-2.0+svn5985/Source/Core/AudioCommon/Src/Mixer.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/AudioCommon/Src/Mixer.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -136,9 +136,9 @@ void CMixer::PushSamples(short *samples, unsigned int num_samples) { - // The auto throttle function. This loop will put a ceiling on the CPU MHz. if (m_throttle) { + // The auto throttle function. This loop will put a ceiling on the CPU MHz. while (Common::AtomicLoad(m_numSamples) >= MAX_SAMPLES - RESERVED_SAMPLES) { if (g_dspInitialize.pEmulatorState) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/AudioCommon/Src/PulseAudioStream.cpp dolphin-emu-2.0+svn6107/Source/Core/AudioCommon/Src/PulseAudioStream.cpp --- dolphin-emu-2.0+svn5985/Source/Core/AudioCommon/Src/PulseAudioStream.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/AudioCommon/Src/PulseAudioStream.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -21,9 +21,11 @@ #include "PulseAudioStream.h" #define BUFFER_SIZE 4096 -#define BUFFER_SIZE_BYTES (BUFFER_SIZE*2*2) +#define BUFFER_SIZE_BYTES (BUFFER_SIZE * 4) -PulseAudio::PulseAudio(CMixer *mixer) : SoundStream(mixer), thread_data(0), handle(NULL) +PulseAudio::PulseAudio(CMixer *mixer) + : SoundStream(mixer), thread_running(false), mainloop(NULL) + , context(NULL), stream(NULL), iVolume(100) { mix_buffer = new u8[BUFFER_SIZE_BYTES]; } @@ -33,22 +35,22 @@ delete [] mix_buffer; } -static void *ThreadTrampoline(void *args) +void *PulseAudio::ThreadTrampoline(void *args) { - reinterpret_cast(args)->SoundLoop(); + ((PulseAudio *)args)->SoundLoop(); return NULL; } bool PulseAudio::Start() { + thread_running = true; thread = new Common::Thread(&ThreadTrampoline, this); - thread_data = 0; return true; } void PulseAudio::Stop() { - thread_data = 1; + thread_running = false; delete thread; thread = NULL; } @@ -61,22 +63,16 @@ // Called on audio thread. void PulseAudio::SoundLoop() { - if (!PulseInit()) { - thread_data = 2; - return; - } - while (!thread_data) + thread_running = PulseInit(); + + while (thread_running) { - int err; int frames_to_deliver = 512; - m_mixer->Mix(reinterpret_cast(mix_buffer), frames_to_deliver); - if (pa_simple_write(handle, mix_buffer, frames_to_deliver * 2 * 2, &err) < 0) - { - ERROR_LOG(AUDIO, "pa_simple_write fail: %s", pa_strerror(err)); - } + m_mixer->Mix((short *)mix_buffer, frames_to_deliver); + if (!Write(mix_buffer, frames_to_deliver * 4)) + ERROR_LOG(AUDIO, "PulseAudio failure writing data"); } PulseShutdown(); - thread_data = 2; } bool PulseAudio::PulseInit() @@ -88,25 +84,238 @@ 2 }; - int err; + mainloop = pa_threaded_mainloop_new(); + + context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "dolphin-emu"); + pa_context_set_state_callback(context, ContextStateCB, this); + + if (pa_context_connect(context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) + { + ERROR_LOG(AUDIO, "PulseAudio failed to connect context: %s", + pa_strerror(pa_context_errno(context))); + return false; + } + + pa_threaded_mainloop_lock(mainloop); + pa_threaded_mainloop_start(mainloop); + + for (;;) + { + pa_context_state_t state; + + state = pa_context_get_state(context); + + if (state == PA_CONTEXT_READY) + break; + + if (!PA_CONTEXT_IS_GOOD(state)) + { + ERROR_LOG(AUDIO, "PulseAudio context state failure: %s", + pa_strerror(pa_context_errno(context))); + pa_threaded_mainloop_unlock(mainloop); + return false; + } + + // Wait until the context is ready + pa_threaded_mainloop_wait(mainloop); + } + + if (!(stream = pa_stream_new(context, "emulator", &ss, NULL))) + { + ERROR_LOG(AUDIO, "PulseAudio failed to create playback stream: %s", + pa_strerror(pa_context_errno(context))); + pa_threaded_mainloop_unlock(mainloop); + return false; + } + + // Set callbacks for the playback stream + pa_stream_set_state_callback(stream, StreamStateCB, this); + pa_stream_set_write_callback(stream, StreamWriteCB, this); - if (!(handle = pa_simple_new(NULL, "dolphin-emu", PA_STREAM_PLAYBACK, NULL, - "emulator", &ss, NULL, NULL, &err))) + if (pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_NOFLAGS, NULL, NULL) < 0) { - ERROR_LOG(AUDIO, "PulseAudio open error: %s\n", pa_strerror(err)); + ERROR_LOG(AUDIO, "PulseAudio failed to connect playback stream: %s", + pa_strerror(pa_context_errno(context))); + pa_threaded_mainloop_unlock(mainloop); return false; } - NOTICE_LOG(AUDIO, "Pulse successfully initialized.\n"); + for (;;) + { + pa_stream_state_t state; + + state = pa_stream_get_state(stream); + + if (state == PA_STREAM_READY) + break; + + if (!PA_STREAM_IS_GOOD(state)) + { + ERROR_LOG(AUDIO, "PulseAudio stream state failure: %s", + pa_strerror(pa_context_errno(context))); + pa_threaded_mainloop_unlock(mainloop); + return false; + } + + // Wait until the stream is ready + pa_threaded_mainloop_wait(mainloop); + } + + pa_threaded_mainloop_unlock(mainloop); + + SetVolume(iVolume); + + NOTICE_LOG(AUDIO, "Pulse successfully initialized."); return true; } void PulseAudio::PulseShutdown() { - if (handle != NULL) + if (mainloop) + pa_threaded_mainloop_stop(mainloop); + + if (stream) + pa_stream_unref(stream); + + if (context) { - pa_simple_free(handle); - handle = NULL; + pa_context_disconnect(context); + pa_context_unref(context); + } + + if (mainloop) + pa_threaded_mainloop_free(mainloop); +} + +void PulseAudio::SignalMainLoop() +{ + pa_threaded_mainloop_signal(mainloop, 0); +} + +void PulseAudio::ContextStateCB(pa_context *c, void *userdata) +{ + switch (pa_context_get_state(c)) + { + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + ((PulseAudio *)userdata)->SignalMainLoop(); + break; + + default: + break; } } +void PulseAudio::StreamStateCB(pa_stream *s, void * userdata) +{ + switch (pa_stream_get_state(s)) + { + case PA_STREAM_READY: + case PA_STREAM_TERMINATED: + case PA_STREAM_FAILED: + ((PulseAudio *)userdata)->SignalMainLoop(); + break; + + default: + break; + } +} + +void PulseAudio::StreamWriteCB(pa_stream *s, size_t length, void *userdata) +{ + ((PulseAudio *)userdata)->SignalMainLoop(); +} + +static bool StateIsGood(pa_context *context, pa_stream *stream) +{ + if (!context || !PA_CONTEXT_IS_GOOD(pa_context_get_state(context)) || + !stream || !PA_STREAM_IS_GOOD(pa_stream_get_state(stream))) + { + if ((context && pa_context_get_state(context) == PA_CONTEXT_FAILED) || + (stream && pa_stream_get_state(stream) == PA_STREAM_FAILED)) + { + ERROR_LOG(AUDIO, "PulseAudio state failure: %s", + pa_strerror(pa_context_errno(context))); + } + else + { + ERROR_LOG(AUDIO, "PulseAudio state failure: %s", + pa_strerror(PA_ERR_BADSTATE)); + } + return false; + } + return true; +} + +bool PulseAudio::Write(const void *data, size_t length) +{ + if (!data || length == 0 || !stream) + return false; + + pa_threaded_mainloop_lock(mainloop); + + if (!StateIsGood(context, stream)) + { + pa_threaded_mainloop_unlock(mainloop); + return false; + } + + while (length > 0) + { + size_t l; + int r; + + while (!(l = pa_stream_writable_size(stream))) + { + pa_threaded_mainloop_wait(mainloop); + if (!StateIsGood(context, stream)) + { + pa_threaded_mainloop_unlock(mainloop); + return false; + } + } + + if (l == (size_t)-1) + { + ERROR_LOG(AUDIO, "PulseAudio invalid stream: %s", + pa_strerror(pa_context_errno(context))); + pa_threaded_mainloop_unlock(mainloop); + return false; + } + + if (l > length) + l = length; + + r = pa_stream_write(stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); + if (r < 0) + { + ERROR_LOG(AUDIO, "PulseAudio error writing to stream: %s", + pa_strerror(pa_context_errno(context))); + pa_threaded_mainloop_unlock(mainloop); + return false; + } + + data = (const uint8_t*) data + l; + length -= l; + } + + pa_threaded_mainloop_unlock(mainloop); + return true; +} + +void PulseAudio::SetVolume(int volume) +{ + iVolume = volume; + + if (!stream) + return; + + pa_cvolume cvolume; + const pa_channel_map *channels = pa_stream_get_channel_map(stream); + pa_cvolume_set(&cvolume, channels->channels, + iVolume * (PA_VOLUME_NORM - PA_VOLUME_MUTED) / 100); + + pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), + &cvolume, NULL, this); +} diff -Nru dolphin-emu-2.0+svn5985/Source/Core/AudioCommon/Src/PulseAudioStream.h dolphin-emu-2.0+svn6107/Source/Core/AudioCommon/Src/PulseAudioStream.h --- dolphin-emu-2.0+svn5985/Source/Core/AudioCommon/Src/PulseAudioStream.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/AudioCommon/Src/PulseAudioStream.h 2010-08-18 03:25:17.000000000 +0100 @@ -19,9 +19,7 @@ #define _PULSE_AUDIO_STREAM_H #if defined(HAVE_PULSEAUDIO) && HAVE_PULSEAUDIO -#include -#include -#include +#include #endif #include "Common.h" @@ -37,30 +35,34 @@ virtual ~PulseAudio(); virtual bool Start(); - virtual void SoundLoop(); virtual void Stop(); + virtual void SetVolume(int volume); + + static bool isValid() {return true;} - static bool isValid() { - return true; - } - virtual bool usesMixer() const { - return true; - } + virtual bool usesMixer() const {return true;} virtual void Update(); private: + virtual void SoundLoop(); + static void *ThreadTrampoline(void *args); bool PulseInit(); void PulseShutdown(); + bool Write(const void *data, size_t bytes); + void SignalMainLoop(); + static void ContextStateCB(pa_context *c, void *userdata); + static void StreamStateCB(pa_stream *s, void * userdata); + static void StreamWriteCB(pa_stream *s, size_t length, void *userdata); u8 *mix_buffer; Common::Thread *thread; - // 0 = continue - // 1 = shutdown - // 2 = done shutting down. - volatile int thread_data; + volatile bool thread_running; - pa_simple *handle; + pa_threaded_mainloop *mainloop; + pa_context *context; + pa_stream *stream; + int iVolume; #else public: PulseAudio(CMixer *mixer) : SoundStream(mixer) {} @@ -68,4 +70,3 @@ }; #endif - diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Common.vcproj dolphin-emu-2.0+svn6107/Source/Core/Common/Common.vcproj --- dolphin-emu-2.0+svn5985/Source/Core/Common/Common.vcproj 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Common.vcproj 2010-08-18 03:25:19.000000000 +0100 @@ -29,7 +29,7 @@ > + + diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/make_svnrev.h.vbs dolphin-emu-2.0+svn6107/Source/Core/Common/make_svnrev.h.vbs --- dolphin-emu-2.0+svn5985/Source/Core/Common/make_svnrev.h.vbs 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/make_svnrev.h.vbs 2010-08-18 03:25:19.000000000 +0100 @@ -1,22 +1,38 @@ set wshShell = CreateObject("WScript.Shell") -basedir = wscript.arguments(0) -outfile = basedir & "/Src/svnrev.h" -svncmd = "SubWCRev ../../.. " & basedir & "/Src/svnrev_template.h " & outfile +outfile = "./Src/svnrev.h" +svncmd = "SubWCRev ../../.. ./Src/svnrev_template.h " & outfile +svntestcmd = "SubWCRev ../../.." hgcmd = "hg svn info" +const svn = 0 +const hg = 1 -ret = wshShell.run(svncmd, 0, true) -if ret <> 0 then ' Perhaps we should just check for 6? dunno/care... - set hgexec = wshShell.exec(hgcmd) +set oFS = CreateObject("Scripting.fileSystemObject") +if not oFS.FileExists(outfile) then + oFS.CreateTextFile(outfile) + file_rev = 0 +else + set oFile = oFS.OpenTextFile(outfile) + set re = new regexp + re.pattern = "[0-9]+" + file_rev = re.execute(oFile.readline)(0) +end if + +set testexec = wshShell.exec(svntestcmd) +do while testexec.status = 0 : wscript.sleep 100 : loop +if testexec.exitcode = 0 then + testout = testexec.stdout.readall + set re = new regexp + re.pattern = "Last committed at revision [0-9]+" + cur_rev = split(re.execute(testout)(0))(4) + cur_cms = svn +else + set hgexec = wshShell.exec(hgcmd) do while hgexec.status = 0 : wscript.sleep 100 : loop do while true line = hgexec.stdout.readline if instr(line, "Revision") then - sline = split(line) - wscript.echo "Hg: Working copy at SVN revision " & sline(1) - set oFS = CreateObject("Scripting.fileSystemObject") - set oFile = oFS.CreateTextFile(outfile, true) - oFile.writeline("#define SVN_REV_STR """ & sline(1) & """") - set oFS = nothing + cur_rev = split(line)(1) + cur_cms = hg exit do end if if hgexec.stdout.atEndofStream then @@ -25,3 +41,15 @@ end if loop end if + +if file_rev = cur_rev then + wscript.echo "svnrev.h doesn't need updating" + wscript.quit 0 +elseif cur_cms = svn then + ret = wshShell.run(svncmd, 0, true) +elseif cur_cms = hg then + set oFile = CreateObject("Scripting.fileSystemObject").CreateTextFile(outfile, true) + oFile.writeline("#define SVN_REV_STR """ & cur_rev & """") +else + wscript.echo "WTF, shouldn't be here!" +end if \ No newline at end of file diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Atomic_GCC.h dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Atomic_GCC.h --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Atomic_GCC.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Atomic_GCC.h 2010-08-18 03:25:19.000000000 +0100 @@ -45,6 +45,10 @@ __sync_and_and_fetch(&target, value); } +inline void AtomicDecrement(volatile u32& target) { + __sync_add_and_fetch(&target, -1); +} + inline void AtomicIncrement(volatile u32& target) { __sync_add_and_fetch(&target, 1); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/BreakPoints.cpp dolphin-emu-2.0+svn6107/Source/Core/Common/Src/BreakPoints.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/BreakPoints.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/BreakPoints.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -26,9 +26,9 @@ { if (Log) { - DEBUG_LOG(MEMMAP, "CHK %08x %s%i at %08x (%s)", - iValue, write ? "Write" : "Read", // read or write - size*8, addr, // address + DEBUG_LOG(MEMMAP, "CHK %08x %s%i %08x at %08x (%s)", + debug_interface->getPC(), + write ? "Write" : "Read", size*8, iValue, addr, // address debug_interface->getDescription(addr).c_str() // symbol map description ); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/CommonFuncs.h dolphin-emu-2.0+svn6107/Source/Core/Common/Src/CommonFuncs.h --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/CommonFuncs.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/CommonFuncs.h 2010-08-18 03:25:20.000000000 +0100 @@ -27,6 +27,19 @@ template struct CompileTimeAssert; template<> struct CompileTimeAssert {}; +#if defined __GNUC__ && !defined __SSSE3__ +#include +static __inline __m128i __attribute__((__always_inline__)) +_mm_shuffle_epi8(__m128i a, __m128i mask) +{ + __m128i result; + __asm__("pshufb %1, %0" + : "=x" (result) + : "xm" (mask), "0" (a)); + return result; +} +#endif + #ifndef _WIN32 #include @@ -44,6 +57,7 @@ #define Crash() {asm ("int $3");} #endif #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) + inline u32 _rotl(u32 x, int shift) { shift &= 31; if (!shift) return x; @@ -65,7 +79,7 @@ unsigned int n = shift % 64; return (x >> n) | (x << (64 - n)); } - #define SLEEP(x) usleep(x*1000) + #else // WIN32 // Function Cross-Compatibility #define strcasecmp _stricmp @@ -80,7 +94,6 @@ #define ftell _ftelli64 #define atoll _atoi64 #define stat64 _stat64 - #define SLEEP(x) Sleep(x) #if _M_IX86 #define Crash() {__asm int 3} diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Common.h dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Common.h --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Common.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Common.h 2010-08-18 03:25:20.000000000 +0100 @@ -145,4 +145,8 @@ #define __chdir chdir #endif +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || defined __APPLE__ +#define _M_SSE 0x301 +#endif + #endif // _COMMON_H_ diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/FifoQueue.h dolphin-emu-2.0+svn6107/Source/Core/Common/Src/FifoQueue.h --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/FifoQueue.h 1970-01-01 01:00:00.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/FifoQueue.h 2010-08-18 03:25:20.000000000 +0100 @@ -0,0 +1,114 @@ + +#ifndef _FIFO_QUEUE_H_ +#define _FIFO_QUEUE_H_ + +// a simple lockless thread-safe, +// single reader, single writer queue + +#include "Atomic.h" + +namespace Common +{ + +template +class FifoQueue +{ +public: + FifoQueue() : m_size(0) + { + m_write_ptr = m_read_ptr = new ElementPtr(); + } + + ~FifoQueue() + { + // this will empty out the whole queue + delete m_read_ptr; + } + + u32 Size() const + { + return m_size; + } + + bool Empty() const + { + //return (m_read_ptr == m_write_ptr); + return (0 == m_size); + } + + const T& Front() const + { + return *m_read_ptr->current; + } + + void Push(const T& t) + { + // create the element, add it to the queue + m_write_ptr->current = new T(t); + // set the next pointer to a new element ptr + // then advance the write pointer + m_write_ptr = m_write_ptr->next = new ElementPtr(); + Common::AtomicIncrement(m_size); + } + + void Pop() + { + Common::AtomicDecrement(m_size); + ElementPtr *const tmpptr = m_read_ptr; + // advance the read pointer + m_read_ptr = m_read_ptr->next; + // set the next element to NULL to stop the recursive deletion + tmpptr->next = NULL; + delete tmpptr; // this also deletes the element + } + + bool Pop(T& t) + { + if (Empty()) + return false; + + t = Front(); + Pop(); + + return true; + } + + // not thread-safe + void Clear() + { + m_size = 0; + delete m_read_ptr; + m_write_ptr = m_read_ptr = new ElementPtr(); + } + +private: + // stores a pointer to element + // and a pointer to the next ElementPtr + class ElementPtr + { + public: + ElementPtr() : current(NULL), next(NULL) {} + + ~ElementPtr() + { + if (current) + { + delete current; + // recusion ftw + if (next) + delete next; + } + } + + T *volatile current; + ElementPtr *volatile next; + }; + + ElementPtr *volatile m_write_ptr; + ElementPtr *volatile m_read_ptr; + volatile u32 m_size; +}; + +} + +#endif diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Hash.cpp dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Hash.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Hash.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Hash.cpp 2010-08-18 03:25:20.000000000 +0100 @@ -105,21 +105,6 @@ } -// Another fast and decent hash -u32 HashFNV1(const u8* ptr, int length) -{ - u32 hash = 0x811c9dc5; - - for (int i = 0; i < length; i++) - { - hash *= 1677761; - hash ^= ptr[i]; - } - - return(hash); -} - - // Stupid hash - but can't go back now :) // Don't use for new things. At least it's reasonably fast. u32 HashEctor(const u8* ptr, int length) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/LinearDiskCache.cpp dolphin-emu-2.0+svn6107/Source/Core/Common/Src/LinearDiskCache.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/LinearDiskCache.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/LinearDiskCache.cpp 2010-08-18 03:25:20.000000000 +0100 @@ -22,7 +22,7 @@ // Update this to the current SVN revision every time you change shader generation code. // We don't automatically get this from SVN_REV because that would mean regenerating the // shader cache for every revision, graphics-related or not, which is simply annoying. -const int version = 5896; +const int version = 6103; LinearDiskCache::LinearDiskCache() : file_(NULL), num_entries_(0) { diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Log.h dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Log.h --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Log.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Log.h 2010-08-18 03:25:20.000000000 +0100 @@ -140,8 +140,8 @@ #define _dbg_update_() ; #ifndef _dbg_assert_ -#define _dbg_assert_(_t_, _a_) ; -#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) ; +#define _dbg_assert_(_t_, _a_) {} +#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) {} #endif // dbg_assert #endif // MAX_LOGLEVEL DEBUG diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Plugin.cpp dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Plugin.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Plugin.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Plugin.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -93,7 +93,7 @@ } // Config: Open the Config window -void CPlugin::Config(HWND _hwnd) +void CPlugin::Config(void *_hwnd) { if (m_DllConfig != NULL) m_DllConfig(_hwnd); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Plugin.h dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Plugin.h --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/Plugin.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/Plugin.h 2010-08-18 03:25:20.000000000 +0100 @@ -25,7 +25,7 @@ namespace Common { typedef void (__cdecl * TGetDllInfo)(PLUGIN_INFO*); - typedef void (__cdecl * TDllConfig)(HWND); + typedef void (__cdecl * TDllConfig)(void *); typedef void* (__cdecl * TDllDebugger)(void *, bool); typedef void (__cdecl * TSetDllGlobals)(PLUGIN_GLOBALS*); typedef void (__cdecl * TInitialize)(void *); @@ -47,8 +47,8 @@ void SetGlobals(PLUGIN_GLOBALS* _PluginGlobals); void *LoadSymbol(const char *sym); - void Config(HWND _hwnd); - void About(HWND _hwnd); + void Config(void *_hwnd); + void About(void *_hwnd); void *Debug(void *Parent, bool Show); void DoState(unsigned char **ptr, int mode); void EmuStateChange(PLUGIN_EMUSTATE newState); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/PluginVideo.cpp dolphin-emu-2.0+svn6107/Source/Core/Common/Src/PluginVideo.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/PluginVideo.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/PluginVideo.cpp 2010-08-18 03:25:20.000000000 +0100 @@ -39,6 +39,7 @@ Video_GatherPipeBursted = 0; Video_WaitForFrameFinish = 0; Video_IsFifoBusy = 0; + Video_AbortFrame = 0; Video_Prepare = reinterpret_cast (LoadSymbol("Video_Prepare")); @@ -74,6 +75,8 @@ (LoadSymbol("Video_WaitForFrameFinish")); Video_IsFifoBusy = reinterpret_cast (LoadSymbol("Video_IsFifoBusy")); + Video_AbortFrame = reinterpret_cast + (LoadSymbol("Video_AbortFrame")); if ((Video_Prepare != 0) && (Video_BeginField != 0) && (Video_EndField != 0) && @@ -91,7 +94,8 @@ (Video_PixelEngineWrite32 != 0) && (Video_GatherPipeBursted != 0) && (Video_WaitForFrameFinish != 0) && - (Video_IsFifoBusy != 0)) + (Video_IsFifoBusy != 0) && + (Video_AbortFrame != 0)) validVideo = true; } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/PluginVideo.h dolphin-emu-2.0+svn6107/Source/Core/Common/Src/PluginVideo.h --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/PluginVideo.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/PluginVideo.h 2010-08-18 03:25:20.000000000 +0100 @@ -40,6 +40,7 @@ typedef void (__cdecl* TVideo_GatherPipeBursted)(); typedef void (__cdecl* TVideo_WaitForFrameFinish)(); typedef bool (__cdecl* TVideo_IsFifoBusy)(); +typedef void (__cdecl* TVideo_AbortFrame)(); class PluginVideo : public CPlugin { @@ -68,6 +69,7 @@ TVideo_GatherPipeBursted Video_GatherPipeBursted; TVideo_WaitForFrameFinish Video_WaitForFrameFinish; TVideo_IsFifoBusy Video_IsFifoBusy; + TVideo_AbortFrame Video_AbortFrame; private: bool validVideo; }; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/Src/SConscript dolphin-emu-2.0+svn6107/Source/Core/Common/Src/SConscript --- dolphin-emu-2.0+svn5985/Source/Core/Common/Src/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/Src/SConscript 2010-08-18 03:25:19.000000000 +0100 @@ -1,7 +1,12 @@ # -*- python -*- Import('env') +import os import sys +from SconsTests import utils + +utils.GenerateRevFile(env['flavor'], Dir('#Source/Core/Common/Src').abspath + + os.sep + 'svnrev_template.h', 'svnrev.h') files = [ "ABI.cpp", @@ -48,3 +53,4 @@ files += [ "stdafx.cpp" ] env.StaticLibrary(env['local_libs'] + "common", files) +env['CPPPATH'] += ['.'] diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Common/SVNRevGen.vcproj dolphin-emu-2.0+svn6107/Source/Core/Common/SVNRevGen.vcproj --- dolphin-emu-2.0+svn5985/Source/Core/Common/SVNRevGen.vcproj 1970-01-01 01:00:00.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Common/SVNRevGen.vcproj 2010-08-18 03:25:19.000000000 +0100 @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/ConfigManager.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/ConfigManager.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/ConfigManager.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/ConfigManager.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -34,6 +34,7 @@ { "ToggleFullscreen", 13 /* WXK_RETURN */, 0x0001 /* wxMOD_ALT */ }, { "PlayPause", 349 /* WXK_F10 */, 0x0000 /* wxMOD_NONE */ }, { "Stop", 27 /* WXK_ESCAPE */, 0x0000 /* wxMOD_NONE */ }, + { "Screenshot", 348 /* WXK_F9 */, 0x0000 /* wxMOD_NONE */ }, { "Wiimote1Connect", 344 /* WXK_F5 */, 0x0001 /* wxMOD_ALT */ }, { "Wiimote2Connect", 345 /* WXK_F6 */, 0x0001 /* wxMOD_ALT */ }, { "Wiimote3Connect", 346 /* WXK_F7 */, 0x0001 /* wxMOD_ALT */ }, @@ -290,6 +291,7 @@ ini.Get("Core", "WiiKeyboard", &m_WiiKeyboard, false); ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false); ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false); + ini.Get("Core", "MMU", &m_LocalCoreStartupParameter.bMMU, false); ini.Get("Core", "TLBHack", &m_LocalCoreStartupParameter.iTLBHack, 0); ini.Get("Core", "FrameLimit", &m_Framelimit, 1); // auto frame limit by default ini.Get("Core", "UseFPS", &b_UseFPS, false); // use vps as default diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/ConfigManager.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/ConfigManager.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/ConfigManager.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/ConfigManager.h 2010-08-18 03:25:19.000000000 +0100 @@ -71,8 +71,6 @@ // framelimit choose int m_Framelimit; bool b_UseFPS; - // FIFO watermark tightness - int m_WatermarkTightness; // other interface settings bool m_InterfaceToolbar; bool m_InterfaceStatusbar; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/Console.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/Console.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/Console.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/Console.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -55,7 +55,7 @@ { #if MAX_LOGLEVEL >= INFO_LEVEL u32 EA = - Memory::TranslatePageAddress(addr, Memory::FLAG_NO_EXCEPTION); + Memory::TranslateAddress(addr, Memory::FLAG_NO_EXCEPTION); INFO_LOG(CONSOLE, "EA 0x%08x to 0x%08x", addr, EA); #endif } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/Core.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/Core.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/Core.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/Core.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -101,7 +101,7 @@ bool g_bStopping = false; bool g_bHwInit = false; bool g_bRealWiimote = false; -HWND g_pWindowHandle = NULL; +void *g_pWindowHandle = NULL; Common::Thread* g_EmuThread = NULL; @@ -183,6 +183,7 @@ SCoreStartupParameter &_CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; g_CoreStartupParameter = _CoreParameter; + // FIXME DEBUG_LOG(BOOT, dump_params()); Host_SetWaitCursor(true); @@ -330,6 +331,7 @@ VideoInitialize.pSetInterrupt = ProcessorInterface::SetInterrupt; VideoInitialize.pRegisterEvent = CoreTiming::RegisterEvent; VideoInitialize.pScheduleEvent_Threadsafe = CoreTiming::ScheduleEvent_Threadsafe; + VideoInitialize.pRemoveEvent = CoreTiming::RemoveAllEvents; // This is first the m_Panel handle, then it is updated to have the new window handle VideoInitialize.pWindowHandle = _CoreParameter.hMainWindow; VideoInitialize.pLog = Callback_VideoLog; @@ -357,7 +359,7 @@ Plugins.GetVideo()->Initialize(&VideoInitialize); // Call the dll // Under linux, this is an X11 Window, not a HWND! - g_pWindowHandle = (HWND)VideoInitialize.pWindowHandle; + g_pWindowHandle = VideoInitialize.pWindowHandle; Callback_PeekMessages = VideoInitialize.pPeekMessages; g_pUpdateFPSDisplay = VideoInitialize.pUpdateFPSDisplay; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/CoreParameter.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/CoreParameter.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/CoreParameter.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/CoreParameter.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -32,7 +32,7 @@ SCoreStartupParameter::SCoreStartupParameter() : hInstance(0), hMainWindow(0), - bJITNoBlockCache(false), bJITBlockLinking(false), + bJITNoBlockCache(false), bJITBlockLinking(true), bJITOff(false), bJITLoadStoreOff(false), bJITLoadStorelXzOff(false), bJITLoadStorelwzOff(false), bJITLoadStorelbzxOff(false), @@ -47,8 +47,7 @@ bLockThreads(false), bEnableCheats(false), bRunCompareServer(false), bRunCompareClient(false), - iTLBHack(0), SelectedLanguage(0), - bWii(false), + bMMU(false), bSMC(false), iTLBHack(0), SelectedLanguage(0), bWii(false), bConfirmStop(false), bHideCursor(false), bAutoHideCursor(false), bUsePanicHandlers(true), iRenderWindowXPos(0), iRenderWindowYPos(0), @@ -70,9 +69,11 @@ bDSPThread = true; bLockThreads = true; bEnableFPRF = false; - bWii = false; - SelectedLanguage = 0; + bMMU = false; + bSMC = false; iTLBHack = 0; + SelectedLanguage = 0; + bWii = false; iPosX = 100; iPosY = 100; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/CoreParameter.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/CoreParameter.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/CoreParameter.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/CoreParameter.h 2010-08-18 03:25:19.000000000 +0100 @@ -25,6 +25,7 @@ HK_FULLSCREEN, HK_PLAY_PAUSE, HK_STOP, + HK_SCREENSHOT, HK_WIIMOTE1_CONNECT, HK_WIIMOTE2_CONNECT, HK_WIIMOTE3_CONNECT, @@ -77,6 +78,8 @@ bool bRunCompareServer; bool bRunCompareClient; + bool bMMU; + bool bSMC; int iTLBHack; int SelectedLanguage; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/CoreTiming.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/CoreTiming.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/CoreTiming.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/CoreTiming.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -24,7 +24,7 @@ #include "StringUtil.h" #include "PluginManager.h" -#define MAX_SLICE_LENGTH 20000 +#define MAX_SLICE_LENGTH 32000 namespace CoreTiming { @@ -96,6 +96,13 @@ eventPool = ev; } +void FreeTsEvent(Event* ev) +{ + ev->next = eventTsPool; + eventTsPool = ev; + allocatedTsEvents--; +} + int RegisterEvent(const char *name, TimedCallback callback) { EventType type; @@ -171,6 +178,7 @@ p.Do(ev->time); p.Do(ev->type); p.Do(ev->userdata); + p.Do(ev->fifoWait); ev->next = 0; prev = ev; ev = ev->next; @@ -188,6 +196,7 @@ p.Do(ev->time); p.Do(ev->type); p.Do(ev->userdata); + p.Do(ev->fifoWait); ev = ev->next; } more_events = 0; @@ -302,6 +311,7 @@ void RemoveEvent(int event_type) { + if (!first) return; if (first->type == event_type) @@ -330,6 +340,50 @@ } } +void RemoveThreadsafeEvent(int event_type) +{ + externalEventSection.Enter(); + if (!tsFirst) + { + externalEventSection.Leave(); + return; + } + if (tsFirst->type == event_type) + { + Event *next = tsFirst->next; + FreeTsEvent(tsFirst); + tsFirst = next; + } + if (!tsFirst) + { + externalEventSection.Leave(); + return; + } + Event *prev = tsFirst; + Event *ptr = prev->next; + while (ptr) + { + if (ptr->type == event_type) + { + prev->next = ptr->next; + FreeTsEvent(ptr); + ptr = prev->next; + } + else + { + prev = ptr; + ptr = ptr->next; + } + } + externalEventSection.Leave(); +} + +void RemoveAllEvents(int event_type) +{ + RemoveThreadsafeEvent(event_type); + RemoveEvent(event_type); +} + void SetMaximumSlice(int maximumSliceLength) { maxSliceLength = maximumSliceLength; @@ -468,7 +522,7 @@ while (ptr) { unsigned int t = ptr->type; - if (t < 0 || t >= event_types.size()) + if (t >= event_types.size()) PanicAlert("Invalid event type %i", t); const char *name = event_types[ptr->type].name; if (!name) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/CoreTiming.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/CoreTiming.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/CoreTiming.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/CoreTiming.h 2010-08-18 03:25:18.000000000 +0100 @@ -62,6 +62,8 @@ // We only permit one event of each type in the queue at a time. void RemoveEvent(int event_type); +void RemoveThreadsafeEvent(int event_type); +void RemoveAllEvents(int event_type); bool IsScheduled(int event_type); void Advance(); void MoveEvents(); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/Debugger/PPCDebugInterface.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/Debugger/PPCDebugInterface.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/Debugger/PPCDebugInterface.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/Debugger/PPCDebugInterface.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -113,14 +113,12 @@ void PPCDebugInterface::setBreakpoint(unsigned int address) { - if (PowerPC::breakpoints.Add(address)) - jit->NotifyBreakpoint(address, true); + PowerPC::breakpoints.Add(address); } void PPCDebugInterface::clearBreakpoint(unsigned int address) { - if (PowerPC::breakpoints.Remove(address)) - jit->NotifyBreakpoint(address, false); + PowerPC::breakpoints.Remove(address); } void PPCDebugInterface::clearAllBreakpoints() {} diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/GeckoCode.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/GeckoCode.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/GeckoCode.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/GeckoCode.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -3,6 +3,7 @@ #include "Thread.h" #include "HW/Memmap.h" +#include "ConfigManager.h" #include "vector" @@ -142,6 +143,8 @@ bool RunActiveCodes() { + if (false == SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) + return true; if (false == active_codes_lock.TryEnter()) return true; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/DSP.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/DSP.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/DSP.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/DSP.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -497,6 +497,7 @@ void Read32(u32& _uReturnValue, const u32 _iAddress) { INFO_LOG(DSPINTERFACE, "DSPInterface(r32) 0x%08x", _iAddress); + switch (_iAddress & 0xFFFF) { // DSP @@ -504,6 +505,24 @@ _uReturnValue = (dsp_plugin->DSP_ReadMailboxHigh(true) << 16) | dsp_plugin->DSP_ReadMailboxLow(true); break; + // AI + case AUDIO_DMA_START_HI: + _uReturnValue = g_audioDMA.SourceAddress; + break; + + // ARAM + case AR_DMA_ARADDR_H: + _uReturnValue = g_arDMA.ARAddr; + break; + + case AR_DMA_CNT_H: + _uReturnValue = g_arDMA.Cnt.Hex; + break; + + case AR_DMA_MMADDR_H: + _uReturnValue = g_arDMA.MMAddr; + break; + default: _dbg_assert_(DSPINTERFACE,0); break; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/EXI_DeviceEthernet.h 2010-08-18 03:25:18.000000000 +0100 @@ -64,7 +64,7 @@ _size = _size + s; } void clear() { _size = 0; } - u8* const p() { return _buffer; } + u8* p() { return _buffer; } private: u8* _buffer; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/Memmap.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/Memmap.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/Memmap.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/Memmap.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -58,6 +58,7 @@ /* Enable the Translation Lookaside Buffer functions. TLBHack = 1 in Dolphin.ini or a .ini file will set this to true */ bool bFakeVMEM = false; +bool bMMU = false; // ============== @@ -348,6 +349,7 @@ { bool wii = SConfig::GetInstance().m_LocalCoreStartupParameter.bWii; bFakeVMEM = SConfig::GetInstance().m_LocalCoreStartupParameter.iTLBHack == 1; + bMMU = SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU; u32 flags = 0; if (wii) flags |= MV_WII_ONLY; @@ -416,28 +418,43 @@ return inst.hex; } -u32 Read_Opcode_JIT(const u32 _Address) +u32 Read_Opcode_JIT(u32 _Address) { #ifdef FAST_ICACHE - if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 && - (_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area - (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000) + if (bMMU && !bFakeVMEM && + (_Address >> 28) != 0x0 && + (_Address >> 28) != 0x8 && + (_Address >> 28) != 0x9 && + (_Address >> 28) != 0xC && + (_Address >> 28) != 0xD + ) { - PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address); - return 0; + _Address = Memory::TranslateAddress(_Address, FLAG_OPCODE); + if (_Address == 0) + { + return 0; + } } - - u32 inst = Read_Opcode(_Address); + + u32 inst = PowerPC::ppcState.iCache.ReadInstruction(_Address); #else u32 inst = Memory::ReadUnchecked_U32(_Address); #endif // if a crash occured after that message - // that means that we've compiled outdated code from the cache instead of memory + // that means that we have compiled outdated code from the cache instead of memory // this could happen if a game forgot to icbi the new code #if defined(_DEBUG) || defined(DEBUGFAST) u32 inst_mem = Memory::ReadUnchecked_U32(_Address); if (inst_mem != inst) ERROR_LOG(POWERPC, "JIT: compiling outdated code. addr=%x, mem=%x, cache=%x", _Address, inst_mem, inst); + + inst = Read_Opcode_JIT_LC(_Address); + if (inst_mem != inst) + { + ERROR_LOG(POWERPC, "JIT: self-modifying code detected. addr=%x, mem=%x, cache=%x", _Address, inst_mem, inst); + PanicAlert("JIT: self-modifying code detected. addr=%x, mem=%x, cache=%x", _Address, inst_mem, inst); + Write_Opcode_JIT(_Address, inst_mem); + } #endif return inst; } @@ -451,6 +468,7 @@ (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000) { PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address); + ERROR_LOG(MEMMAP, "iCacheJIT: Reading Opcode from %x. Please report.", _Address); return 0; } u8* iCache; @@ -505,132 +523,14 @@ #endif } - -// ======================================================= -/* Functions to detect and trace memory read/write errors. Turn of JIT LoadStore to - make it work, and add a return 0 at the beginning of CheckDTLB to avoid closing - Dolphin just as it starts to get interesting. You can also try to change - the TitleID write in IOCTL_ES_GETTITLEID to 0x00000000, otherwise it will never even - get to making the bad dev/di request. - - I'm currently at (---, 8021347c) : Write32: Program wrote [0x7fd5d340] to [0x933e00f8], - 0x8021347c seems to write the out buffer to a 0x933e.... address before it is copies - to the 0x133e.... address for the Ioctlv. But why does it generate this bad address - when it made a good one 120 milliseconds earlier? - */ -// ------------- -bool ValidMemory(const u32 _Address) -{ - switch (_Address >> 24) - { - case 0x00: - case 0x01: - case 0x80: - case 0x81: - case 0xC0: - case 0xC1: - return true; - - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) - return true; - else - return false; - case 0x7e: - case 0x7f: - if (bFakeVMEM) - return true; - else - return false; - - case 0xE0: - if (_Address < (0xE0000000 + L1_CACHE_SIZE)) - return true; - else - return false; - case 0xCC: - case 0xCD: - case 0xC8: - return true; - } - return false; -} - -void CheckForBadAddresses(u32 Address, u32 Data, bool Read, int Bits) +void GenerateISIException_JIT(u32 _EffectiveAddress) { - if (!ValidMemory(Address)) - { - if(Read) - { - WARN_LOG(CONSOLE, "Read%i: Program tried to read [%08x] from [%08x]", Bits, Address); - } - else - { - ERROR_LOG(CONSOLE, "Write%i: Program tried to write [%08x] to [%08x]", Bits, Data, Address); - } - } + GenerateISIException(_EffectiveAddress); - if (Address == 0) - { - if(Read) - { - WARN_LOG(CONSOLE, "Read%i: Program read [0x%08x] from [0x%08x] * * * 0 * * *", Bits, Data, Address); - } - else - { - WARN_LOG(CONSOLE, "Write%i: Program wrote [0x%08x] to [0x%08x] * * * 0 * * *", Bits, Data, Address); - } - } - // Try to figure out where the dev/di Ioctl arguments are stored (including buffer out), so we can - // find the bad one - if( - Data == 0x1090f4c0 // good out buffer right before it, for sound/smashbros_sound.brsar - || Data == 0x10913b00 // second one - || Data == 0x7fd5d340 // first bad out buffer - || Data == 0x133e00f8 // the address that store the bad 0x7fd5d340, this changes every time - || Data == 0x2a24aa // menu2\sc_title_en.pac byte size - || ( - (PC == 0x8021347c || PC == 0x801f6a20 || PC == 0x800202d0 || PC == 0x80229964 - || PC == 0x801d88bc) /* this could be interesting, because the bad out buffer 0x7fd5d340 - is 0x80000000 - size = 0x7fd5d340 perhaps some function read 0x80000000, I dunno */ - && Data == 0x80000000) - ) - { - if(Read) - { - ERROR_LOG(CONSOLE, "Read%i: Program read [0x%08x] from [0x%08x] * * * * * * * * * * * *", Bits, Data, Address); - } - else - { - ERROR_LOG(CONSOLE, "Write%i: Program wrote [0x%08x] to [0x%08x] * * * * * * * * * * * *", Bits,Data, Address); - } - } + // Remove the invalid instruction from the icache, forcing a recompile + Write_Opcode_JIT(_EffectiveAddress, JIT_ICACHE_INVALID_WORD); } - -void CheckForBadAddresses8(u32 Address, u8 Data, bool Read) -{CheckForBadAddresses(Address, (u32)Data, Read, 8);} - -void CheckForBadAddresses16(u32 Address, u16 Data, bool Read) -{CheckForBadAddresses(Address, (u32)Data, Read, 16);} - -void CheckForBadAddresses32(u32 Address, u32 Data, bool Read) -{CheckForBadAddresses(Address, (u32)Data, Read, 32);} - -void CheckForBadAddresses64(u32 Address, u64 Data, bool Read) -{CheckForBadAddresses(Address, (u32)Data, Read, 64);} - void WriteBigEData(const u8 *_pData, const u32 _Address, const u32 _iSize) { memcpy(GetPointer(_Address), _pData, _iSize); @@ -709,7 +609,6 @@ _string = stringBuffer; } - // GetPointer must always return an address in the bottom 32 bits of address space, so that 64-bit // programs don't have problems directly addressing any part of memory. u8 *GetPointer(const u32 _Address) @@ -741,10 +640,6 @@ else return 0; - case 0x7E: - case 0x7F: - return (u8*)(((char*)m_pVirtualFakeVMEM) + (_Address & RAM_MASK)); - case 0xE0: if (_Address < (0xE0000000 + L1_CACHE_SIZE)) return GetCachePtr() + (_Address & L1_CACHE_MASK); @@ -758,14 +653,17 @@ case 0xCD: _dbg_assert_msg_(MEMMAP, 0, "Memory", "GetPointer from IO Bridge doesnt work"); return NULL; - //case 0x47: TODO - case 0x7B: - case 0xFF: - break; - default: - if (!PanicYesNo("Unknown pointer address prefix %02X, report this to the devs: 0x%08X \n Continue?", (_Address >> 24), _Address)) - Crash(); + if (bFakeVMEM) + { + return (u8*)(((char*)m_pVirtualFakeVMEM) + (_Address & RAM_MASK)); + } + else + { + if (!Core::g_CoreStartupParameter.bMMU && !PanicYesNo("Unknown pointer address prefix %02X, report this to the devs: 0x%08X \n Continue?", (_Address >> 24), _Address)) + Crash(); + return 0; + } break; } return NULL; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/MemmapFunctions.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/MemmapFunctions.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/MemmapFunctions.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/MemmapFunctions.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -147,7 +147,7 @@ } template -inline void ReadFromHardware(T &_var, u32 em_address, u32 effective_address, Memory::XCheckTLBFlag flag) +inline void ReadFromHardware(T &_var, const u32 em_address, const u32 effective_address, Memory::XCheckTLBFlag flag) { // TODO: Figure out the fastest order of tests for both read and write (they are probably different). if ((em_address & 0xC8000000) == 0xC8000000) @@ -185,11 +185,8 @@ { _var = bswap((*(const T*)&m_pL1Cache[em_address & L1_CACHE_MASK])); } - else if (em_address >= 0xE0000000) - { - PanicAlert("READ: Invalid address: %08x", em_address); - } - else if (bFakeVMEM && ((em_address &0xF0000000) == 0x70000000)) + else if ((bFakeVMEM && ((em_address &0xF0000000) == 0x70000000)) || + (bFakeVMEM && ((em_address &0xF0000000) == 0x40000000))) { // fake VMEM _var = bswap((*(const T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK])); @@ -197,30 +194,29 @@ else { // MMU - u32 tlb_addr = TranslateBlockAddress(em_address); + u32 tlb_addr = TranslateAddress(em_address, flag); if (tlb_addr == 0) { - tlb_addr = TranslatePageAddress(em_address, flag); - if (tlb_addr != 0) - _var = bswap((*(const T*)&m_pRAM[tlb_addr & RAM_MASK])); - else - PanicAlert("READ: Invalid address: %08x", em_address); + if (flag == FLAG_READ) + { + GenerateDSIException(em_address, false); + } } else + { _var = bswap((*(const T*)&m_pRAM[tlb_addr & RAM_MASK])); + } } - - // Debugging: CheckForBadAddresses##_type(em_address, _var, true); } template inline void WriteToHardware(u32 em_address, const T data, u32 effective_address, Memory::XCheckTLBFlag flag) { - // Debugging: CheckForBadAddresses##_type(em_address, data, false); // First, let's check for FIFO writes, since they are probably the most common // reason we end up in this function: - if (em_address == 0xCC008000) { + if (em_address == 0xCC008000) + { switch (sizeof(T)) { case 1: GPFifo::Write8((u8)data, em_address); return; case 2: GPFifo::Write16((u16)data, em_address); return; @@ -243,22 +239,26 @@ } return; } - else if (em_address <= 0xcc009000) { + else if (em_address <= 0xcc009000) + { hwWrite(data, em_address); return; } /* WIIMODE */ else if (((em_address & 0xFF000000) == 0xCD000000) && - (em_address <= 0xcd009000)) { + (em_address <= 0xcd009000)) + { hwWriteWii(data,em_address); return; } else if (((em_address & 0xFFF00000) == 0xCD800000) && - (em_address <= 0xCD809000)) { + (em_address <= 0xCD809000)) + { hwWriteIOBridge(data,em_address); return; } - else { + else + { ERROR_LOG(MEMMAP, "hwwrite [%08x] := %08x (PC: %08x)", em_address, data, PC); _dbg_assert_msg_(MEMMAP,0,"Memory - Unknown HW address %08x", em_address); } @@ -268,6 +268,11 @@ ((em_address & 0xF0000000) == 0x00000000)) { *(T*)&m_pRAM[em_address & RAM_MASK] = bswap(data); + + // Required for games with self modifying code (e.g. Monster House) + if (Core::g_CoreStartupParameter.bSMC) + Write_Opcode_JIT(em_address, 0x14141414); + return; } else if (((em_address & 0xF0000000) == 0x90000000) || @@ -282,12 +287,8 @@ *(T*)&m_pL1Cache[em_address & L1_CACHE_MASK] = bswap(data); return; } - else if (em_address >= 0xE0000000) - { - ERROR_LOG(MEMMAP,"WRITE: Cache address out of bounds (addr: %08x data: %08x)", em_address, data); - /* PanicAlert("WRITE: Cache address %08x out of bounds", em_address); */ - } - else if (bFakeVMEM && ((em_address &0xF0000000) == 0x70000000)) + else if ((bFakeVMEM && ((em_address &0xF0000000) == 0x70000000)) || + (bFakeVMEM && ((em_address &0xF0000000) == 0x40000000))) { // fake VMEM *(T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK] = bswap(data); @@ -295,18 +296,18 @@ else { // MMU - u32 tlb_addr = TranslateBlockAddress(em_address); + u32 tlb_addr = TranslateAddress(em_address, flag); if (tlb_addr == 0) { - tlb_addr = TranslatePageAddress(em_address, flag); - if (tlb_addr != 0) - *(T*)&m_pRAM[tlb_addr & RAM_MASK] = bswap(data); - else - PanicAlert("WRITE: Invalid address: %08x", em_address); + if (flag == FLAG_WRITE) + { + GenerateDSIException(em_address, true); + } } else + { *(T*)&m_pRAM[tlb_addr & RAM_MASK] = bswap(data); - + } } } // ===================== @@ -316,7 +317,7 @@ /* These functions are primarily called by the Interpreter functions and are routed to the correct location through ReadFromHardware and WriteToHardware */ // ---------------- -u32 Read_Opcode(const u32 _Address) +u32 Read_Opcode(u32 _Address) { if (_Address == 0x00000000) { @@ -325,9 +326,24 @@ return 0x00000000; } - /*u32 _var = 0; - ReadFromHardware(_var, _Address, _Address, FLAG_OPCODE); - return _var;*/ + if (Core::g_CoreStartupParameter.bMMU && + (_Address >> 28) != 0x0 && + (_Address >> 28) != 0x8 && + (_Address >> 28) != 0x9 && + (_Address >> 28) != 0xC && + (_Address >> 28) != 0xD) + { + // TODO: Check for MSR instruction address translation flag before translating + u32 tlb_addr = Memory::TranslateAddress(_Address, FLAG_OPCODE); + if (tlb_addr == 0) + { + GenerateISIException(_Address); + return 0; + } + else + _Address = tlb_addr; + } + return PowerPC::ppcState.iCache.ReadInstruction(_Address); } @@ -587,40 +603,25 @@ u32 pagetable_base = 0; u32 pagetable_hashmask = 0; -void GenerateDSIException(u32 _EffectiveAdress, bool _bWrite) +void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite) { if (_bWrite) PowerPC::ppcState.spr[SPR_DSISR] = PPC_EXC_DSISR_PAGE | PPC_EXC_DSISR_STORE; else PowerPC::ppcState.spr[SPR_DSISR] = PPC_EXC_DSISR_PAGE; - PowerPC::ppcState.spr[SPR_DAR] = _EffectiveAdress; + PowerPC::ppcState.spr[SPR_DAR] = _EffectiveAddress; - INFO_LOG(MEMMAP, "Generate DSI Exception 0x%08x", _EffectiveAdress); PowerPC::ppcState.Exceptions |= EXCEPTION_DSI; } -void GenerateISIException() +void GenerateISIException(u32 _EffectiveAddress) { - // shuffle2: ISI exception doesn't modify DSISR at all, to my knowledge... - //PowerPC::ppcState.spr[SPR_DSISR] = 0x4000000; // maybe this was a typo for PPC_EXC_DSISR_PAGE? + // Address of instruction could not be translated + SRR1 = (1 << 30) | (MSR & 0x3fffff); + NPC = _EffectiveAddress; - // Instead, it modifies bits 1-4 in SRR1 depending on conditions: - // Bit 1: set if the translation of an attempted access is not found in the primary hash table entry group - // (HTEG), or in the rehashed secondary HTEG, or in the range of a IBAT register (page fault - // condition); otherwise cleared. - // Bit 2: cleared - // Bit 3: Set if the fetch access occurs to a direct-store segment (SR[T] = 1), to a noexecute - // segment (N bit set in segment descriptor), or to guarded memory - // when MSR[IR] = 1. Otherwise, cleared. - // Bit 4: Set if a memory access is not permitted by the page or IBAT protection - // mechanism, described in Chapter 7, "Memory Management" otherwise cleared. - // Only one of 1,3, or 4 may be set at a time - - // For now let's just say that hash lookup failed - SRR1 = 0x10000000; - INFO_LOG(MEMMAP, "Generate ISI Exception"); PowerPC::ppcState.Exceptions |= EXCEPTION_ISI; } @@ -650,17 +651,167 @@ pagetable_hashmask = ((xx<<10)|0x3ff); } -// Page Address Translation -u32 TranslatePageAddress(u32 _Address, XCheckTLBFlag _Flag) + +// TLB cache +//#define FAST_TLB_CACHE + +#define TLB_SIZE 128 +#define TLB_WAYS 2 +#define NUM_TLBS 2 + +#define PAGE_SIZE 4096 +#define PAGE_INDEX_SHIFT 12 +#define PAGE_INDEX_MASK 0x3f +#define PAGE_TAG_SHIFT 18 + +#define TLB_FLAG_MOST_RECENT 0x01 +#define TLB_FLAG_INVALID 0x02 + +typedef struct tlb_entry { - // TLB cache - for (int i = 0; i < 16; i++) { - if ((_Address & ~0xfff) == (PowerPC::ppcState.tlb_va[(PowerPC::ppcState.tlb_last + i) & 15])) { - u32 result = PowerPC::ppcState.tlb_pa[(PowerPC::ppcState.tlb_last + i) & 15] | (_Address & 0xfff); - PowerPC::ppcState.tlb_last = i; - return result; + u32 tag; + u32 paddr; + u8 flags; +} tlb_entry; + +// TODO: tlb needs to be in ppcState for save-state purposes. +tlb_entry tlb[NUM_TLBS][TLB_SIZE/TLB_WAYS][TLB_WAYS]; + +u32 LookupTLBPageAddress(const XCheckTLBFlag _Flag, const u32 vpa, u32 *paddr) +{ +#ifdef FAST_TLB_CACHE + tlb_entry *tlbe = tlb[_Flag == FLAG_OPCODE][(vpa>>PAGE_INDEX_SHIFT)&PAGE_INDEX_MASK]; + if(tlbe[0].tag == (vpa & ~0xfff) && !(tlbe[0].flags & TLB_FLAG_INVALID)) + { + tlbe[0].flags |= TLB_FLAG_MOST_RECENT; + tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT; + *paddr = tlbe[0].paddr | (vpa & 0xfff); + return 1; + } + if(tlbe[1].tag == (vpa & ~0xfff) && !(tlbe[1].flags & TLB_FLAG_INVALID)) + { + tlbe[1].flags |= TLB_FLAG_MOST_RECENT; + tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; + *paddr = tlbe[1].paddr | (vpa & 0xfff); + return 1; + } + return 0; +#else + u32 _Address = vpa; + if (_Flag == FLAG_OPCODE) + { + for (u32 i = (PowerPC::ppcState.itlb_last); i > (PowerPC::ppcState.itlb_last - 128); i--) + { + if ((_Address & ~0xfff) == (PowerPC::ppcState.itlb_va[i & 127])) + { + u32 result = PowerPC::ppcState.itlb_pa[i & 127] | (_Address & 0xfff); + PowerPC::ppcState.itlb_last = i; + paddr = &result; + return 1; + } + } + } + else + { + for (u32 i = (PowerPC::ppcState.dtlb_last); i > (PowerPC::ppcState.dtlb_last - 128); i--) + { + if ((_Address & ~0xfff) == (PowerPC::ppcState.dtlb_va[i & 127])) + { + u32 result = PowerPC::ppcState.dtlb_pa[i & 127] | (_Address & 0xfff); + PowerPC::ppcState.dtlb_last = i; + paddr = &result; + return 1; + } } } + return 0; +#endif +} + +void UpdateTLBEntry(const XCheckTLBFlag _Flag, UPTE2 PTE2, const u32 vpa) +{ +#ifdef FAST_TLB_CACHE + tlb_entry *tlbe = tlb[_Flag == FLAG_OPCODE][(vpa>>PAGE_INDEX_SHIFT)&PAGE_INDEX_MASK]; + if((tlbe[0].flags & TLB_FLAG_MOST_RECENT) == 0) + { + tlbe[0].flags = TLB_FLAG_MOST_RECENT; + tlbe[1].flags &= ~TLB_FLAG_MOST_RECENT; + tlbe[0].paddr = PTE2.RPN << PAGE_INDEX_SHIFT; + tlbe[0].tag = vpa & ~0xfff; + } + else + { + tlbe[1].flags = TLB_FLAG_MOST_RECENT; + tlbe[0].flags &= ~TLB_FLAG_MOST_RECENT; + tlbe[1].paddr = PTE2.RPN << PAGE_INDEX_SHIFT; + tlbe[1].tag = vpa & ~0xfff; + } +#else + if (_Flag == FLAG_OPCODE) + { + // ITLB cache + PowerPC::ppcState.itlb_last++; + PowerPC::ppcState.itlb_last &= 127; + PowerPC::ppcState.itlb_pa[PowerPC::ppcState.itlb_last] = PTE2.RPN << PAGE_INDEX_SHIFT; + PowerPC::ppcState.itlb_va[PowerPC::ppcState.itlb_last] = vpa & ~0xfff; + } + else + { + // DTLB cache + PowerPC::ppcState.dtlb_last++; + PowerPC::ppcState.dtlb_last &= 127; + PowerPC::ppcState.dtlb_pa[PowerPC::ppcState.dtlb_last] = PTE2.RPN << PAGE_INDEX_SHIFT; + PowerPC::ppcState.dtlb_va[PowerPC::ppcState.dtlb_last] = vpa & ~0xfff; + } +#endif +} + +void InvalidateTLBEntry(u32 vpa) +{ +#ifdef FAST_TLB_CACHE + tlb_entry *tlbe = tlb[0][(vpa>>PAGE_INDEX_SHIFT)&PAGE_INDEX_MASK]; + if(tlbe[0].tag == (vpa & ~0xfff)) + { + tlbe[0].flags |= TLB_FLAG_INVALID; + } + if(tlbe[1].tag == (vpa & ~0xfff)) + { + tlbe[1].flags |= TLB_FLAG_INVALID; + } + tlb_entry *tlbe_i = tlb[1][(vpa>>PAGE_INDEX_SHIFT)&PAGE_INDEX_MASK]; + if(tlbe_i[0].tag == (vpa & ~0xfff)) + { + tlbe_i[0].flags |= TLB_FLAG_INVALID; + } + if(tlbe_i[1].tag == (vpa & ~0xfff)) + { + tlbe_i[1].flags |= TLB_FLAG_INVALID; + } +#else + u32 _Address = vpa; + for (int i = 0; i < 128; i++) + { + if ((_Address & ~0xfff) == (PowerPC::ppcState.dtlb_va[(PowerPC::ppcState.dtlb_last + i) & 127])) + { + PowerPC::ppcState.dtlb_pa[(PowerPC::ppcState.dtlb_last + i) & 127] = 0; + PowerPC::ppcState.dtlb_va[(PowerPC::ppcState.dtlb_last + i) & 127] = 0; + } + if ((_Address & ~0xfff) == (PowerPC::ppcState.itlb_va[(PowerPC::ppcState.itlb_last + i) & 127])) + { + PowerPC::ppcState.itlb_pa[(PowerPC::ppcState.itlb_last + i) & 127] = 0; + PowerPC::ppcState.itlb_va[(PowerPC::ppcState.itlb_last + i) & 127] = 0; + } + } +#endif +} + +// Page Address Translation +u32 TranslatePageAddress(const u32 _Address, const XCheckTLBFlag _Flag) +{ + // TLB cache + u32 translatedAddress = 0; + if (LookupTLBPageAddress(_Flag, _Address, &translatedAddress)) + return translatedAddress; u32 sr = PowerPC::ppcState.sr[EA_SR(_Address)]; @@ -673,7 +824,7 @@ // hash function no 1 "xor" .360 u32 hash1 = (VSID ^ page_index); - u32 pteg_addr = ((hash1 & pagetable_hashmask)<<6) | pagetable_base; + u32 pteg_addr = ((hash1 & pagetable_hashmask) << 6) | pagetable_base; // hash1 for (int i = 0; i < 8; i++) @@ -688,11 +839,7 @@ UPTE2 PTE2; PTE2.Hex = bswap((*(u32*)&pRAM[(pteg_addr + 4)])); - // TLB cache - PowerPC::ppcState.tlb_last++; - PowerPC::ppcState.tlb_last &= 15; - PowerPC::ppcState.tlb_pa[PowerPC::ppcState.tlb_last] = PTE2.RPN << 12; - PowerPC::ppcState.tlb_va[PowerPC::ppcState.tlb_last] = _Address & ~0xfff; + UpdateTLBEntry(_Flag, PTE2, _Address); // set the access bits switch (_Flag) @@ -712,7 +859,7 @@ // hash function no 2 "not" .360 hash1 = ~hash1; - pteg_addr = ((hash1 & pagetable_hashmask)<<6) | pagetable_base; + pteg_addr = ((hash1 & pagetable_hashmask) << 6) | pagetable_base; for (int i = 0; i < 8; i++) { u32 pte = bswap(*(u32*)&pRAM[pteg_addr]); @@ -723,11 +870,7 @@ UPTE2 PTE2; PTE2.Hex = bswap((*(u32*)&pRAM[(pteg_addr + 4)])); - // TLB cache - PowerPC::ppcState.tlb_last++; - PowerPC::ppcState.tlb_last &= 15; - PowerPC::ppcState.tlb_pa[PowerPC::ppcState.tlb_last] = PTE2.RPN << 12; - PowerPC::ppcState.tlb_va[PowerPC::ppcState.tlb_last] = _Address & ~0xfff; + UpdateTLBEntry(_Flag, PTE2, _Address); switch (_Flag) { @@ -743,27 +886,6 @@ } pteg_addr+=8; } - - - // If we got this far something went wrong and we save the exception data - switch(_Flag) - { - case FLAG_NO_EXCEPTION: - break; - - case FLAG_READ: - GenerateDSIException(_Address, false); - break; - - case FLAG_WRITE: - GenerateDSIException(_Address, true); - break; - - case FLAG_OPCODE: - GenerateISIException(); - break; - } - return 0; } @@ -778,53 +900,78 @@ #define BAT_EA_4(v) ((v)&0xf0000000) // Block Address Translation -u32 TranslateBlockAddress(u32 addr) +u32 TranslateBlockAddress(const u32 addr, const XCheckTLBFlag _Flag) { u32 result = 0; UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr); + // TODO: Check for enhanced mode before switching to Wii mode int bats = Core::g_CoreStartupParameter.bWii?8:4; for (int i = 0; i < bats; i++) { - u32 bl17 = ~(BATU_BL(PowerPC::ppcState.spr[SPR_DBAT0U + i * 2])<<17); - u32 addr2 = addr & (bl17 | 0xf001ffff); - u32 batu = (m_MSR.PR ? BATU_Vp : BATU_Vs); - - if (BATU_BEPI(addr2) == BATU_BEPI(PowerPC::ppcState.spr[SPR_DBAT0U + i * 2])) { - // bat applies to this address - if (PowerPC::ppcState.spr[SPR_DBAT0U + i * 2] & batu) { - // bat entry valid - u32 offset = BAT_EA_OFFSET(addr); - u32 page = BAT_EA_11(addr); - page &= ~bl17; - page |= BATL_BRPN(PowerPC::ppcState.spr[SPR_DBAT0L + i * 2]); - // fixme: check access rights - result = page | offset; - return result; + if (_Flag != FLAG_OPCODE) + { + u32 bl17 = ~(BATU_BL(PowerPC::ppcState.spr[SPR_DBAT0U + i * 2]) << 17); + u32 addr2 = addr & (bl17 | 0xf001ffff); + u32 batu = (m_MSR.PR ? BATU_Vp : BATU_Vs); + + if (BATU_BEPI(addr2) == BATU_BEPI(PowerPC::ppcState.spr[SPR_DBAT0U + i * 2])) + { + // bat applies to this address + if (PowerPC::ppcState.spr[SPR_DBAT0U + i * 2] & batu) + { + // bat entry valid + u32 offset = BAT_EA_OFFSET(addr); + u32 page = BAT_EA_11(addr); + page &= ~bl17; + page |= BATL_BRPN(PowerPC::ppcState.spr[SPR_DBAT0L + i * 2]); + // fixme: check access rights + result = page | offset; + return result; + } } } + else + { + u32 bl17 = ~(BATU_BL(PowerPC::ppcState.spr[SPR_IBAT0U + i * 2]) << 17); + u32 addr2 = addr & (bl17 | 0xf001ffff); + u32 batu = (m_MSR.PR ? BATU_Vp : BATU_Vs); - bl17 = ~(BATU_BL(PowerPC::ppcState.spr[SPR_IBAT0U + i * 2])<<17); - addr2 = addr & (bl17 | 0xf001ffff); - batu = (m_MSR.PR ? BATU_Vp : BATU_Vs); - - if (BATU_BEPI(addr2) == BATU_BEPI(PowerPC::ppcState.spr[SPR_IBAT0U + i * 2])) { - // bat applies to this address - if (PowerPC::ppcState.spr[SPR_IBAT0U + i * 2] & batu) { - // bat entry valid - u32 offset = BAT_EA_OFFSET(addr); - u32 page = BAT_EA_11(addr); - page &= ~bl17; - page |= BATL_BRPN(PowerPC::ppcState.spr[SPR_IBAT0L + i * 2]); - // fixme: check access rights - result = page | offset; - return result; + if (BATU_BEPI(addr2) == BATU_BEPI(PowerPC::ppcState.spr[SPR_IBAT0U + i * 2])) + { + // bat applies to this address + if (PowerPC::ppcState.spr[SPR_IBAT0U + i * 2] & batu) + { + // bat entry valid + u32 offset = BAT_EA_OFFSET(addr); + u32 page = BAT_EA_11(addr); + page &= ~bl17; + page |= BATL_BRPN(PowerPC::ppcState.spr[SPR_IBAT0L + i * 2]); + // fixme: check access rights + result = page | offset; + return result; + } } } } return 0; } +u32 TranslateAddress(const u32 _Address, const XCheckTLBFlag _Flag) +{ + // TODO: Check for MSR data/instruction address translation flag before translating + u32 tlb_addr = TranslateBlockAddress(_Address, _Flag); + if (tlb_addr == 0) + { + tlb_addr = TranslatePageAddress(_Address, _Flag); + if (tlb_addr != 0) + { + return tlb_addr; + } + } + else + return tlb_addr; - + return 0; +} } // namespace diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/Memmap.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/Memmap.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/Memmap.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/Memmap.h 2010-08-18 03:25:18.000000000 +0100 @@ -51,7 +51,7 @@ // so be sure to load it into a 64-bit register. extern u8 *base; -// These are guarenteed to point to "low memory" addresses (sub-32-bit). +// These are guaranteed to point to "low memory" addresses (sub-32-bit). extern u8 *m_pRAM; extern u8 *m_pEXRAM; extern u8 *m_pL1Cache; @@ -72,10 +72,14 @@ IO_SIZE = 0x10000, EXRAM_SIZE = 0x4000000, EXRAM_MASK = 0x3FFFFFF, + + ADDR_MASK_HW_ACCESS = 0x0c000000, + ADDR_MASK_MEM1 = 0x20000000, + #ifdef _M_IX86 MEMVIEW32_MASK = 0x3FFFFFFF, #endif -}; +}; // Init and Shutdown bool IsInitialized(); @@ -112,7 +116,7 @@ // used by interpreter to read instructions, uses iCache u32 Read_Opcode(const u32 _Address); -// used by JIT to read instructions, uses iCacheJIT +// used by JIT to read instructions u32 Read_Opcode_JIT(const u32 _Address); // used by JIT. uses iCacheJIT. Reads in the "Locked cache" mode u32 Read_Opcode_JIT_LC(const u32 _Address); @@ -169,11 +173,15 @@ FLAG_WRITE, FLAG_OPCODE, }; -u32 TranslatePageAddress(u32 _Address, XCheckTLBFlag _Flag); -u32 TranslateBlockAddress(u32 _Address); +u32 TranslateAddress(u32 _Address, XCheckTLBFlag _Flag); +void InvalidateTLBEntry(u32 _Address); +void GenerateDSIException(u32 _EffectiveAdress, bool _bWrite); +void GenerateISIException(u32 _EffectiveAdress); +void GenerateISIException_JIT(u32 _EffectiveAdress); extern u32 pagetable_base; extern u32 pagetable_hashmask; }; #endif + diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/ProcessorInterface.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/ProcessorInterface.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/ProcessorInterface.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/ProcessorInterface.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -24,7 +24,7 @@ #include "../CoreTiming.h" #include "ProcessorInterface.h" #include "GPFifo.h" - +#include "../PluginManager.h" namespace ProcessorInterface { @@ -181,6 +181,8 @@ break; case PI_FIFO_RESET: + //Abort the actual frame + CPluginManager::GetInstance().GetVideo()->Video_AbortFrame(); //Fifo_CPUWritePointer = Fifo_CPUBase; ?? //PanicAlert("Unknown write to PI_FIFO_RESET (%08x)", _uValue); WARN_LOG(PROCESSORINTERFACE, "Fifo reset (%08x)", _uValue); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -299,7 +299,7 @@ msg.addData((void *)"\x00\x00\x00\x00", 4); break; case 0x15: - while (*jvs_io++); + while (*jvs_io++) {}; msg.addData(1); break; case 0x20: diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h 2010-08-18 03:25:19.000000000 +0100 @@ -101,11 +101,7 @@ { SBuffer Buffer; Buffer.m_Address = Memory::Read_U32(BufferVectorOffset); - - // Restore cached address, mauled by emulator's ioctl functions. - Memory::Write_U32(Buffer.m_Address | 0x80000000, BufferVectorOffset); BufferVectorOffset += 4; - Buffer.m_Size = Memory::Read_U32(BufferVectorOffset); BufferVectorOffset += 4; DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer in%i: 0x%08x, 0x%x", @@ -118,10 +114,7 @@ { SBuffer Buffer; Buffer.m_Address = Memory::Read_U32(BufferVectorOffset); - - Memory::Write_U32(Buffer.m_Address | 0x80000000, BufferVectorOffset); BufferVectorOffset += 4; - Buffer.m_Size = Memory::Read_U32(BufferVectorOffset); BufferVectorOffset += 4; DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer io%i: 0x%08x, 0x%x", diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/LuaInterface.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/LuaInterface.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/LuaInterface.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/LuaInterface.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -2797,6 +2797,7 @@ game_ini.Get("Core", "CPUOnThread", &StartUp.bCPUThread, StartUp.bCPUThread); game_ini.Get("Core", "SkipIdle", &StartUp.bSkipIdle, StartUp.bSkipIdle); game_ini.Get("Core", "EnableFPRF", &StartUp.bEnableFPRF, StartUp.bEnableFPRF); + game_ini.Get("Core", "MMU", &StartUp.bMMU, StartUp.bMMU); game_ini.Get("Core", "TLBHack", &StartUp.iTLBHack, StartUp.iTLBHack); // Wii settings if (StartUp.bWii) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PluginManager.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PluginManager.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PluginManager.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PluginManager.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -420,15 +420,15 @@ { case PLUGIN_TYPE_VIDEO: if (GetVideo() != NULL) - GetVideo()->Config((HWND)_Parent); + GetVideo()->Config(_Parent); break; case PLUGIN_TYPE_DSP: if (GetDSP() != NULL) - GetDSP()->Config((HWND)_Parent); + GetDSP()->Config(_Parent); break; case PLUGIN_TYPE_WIIMOTE: if (GetWiimote() != NULL) - GetWiimote()->Config((HWND)_Parent); + GetWiimote()->Config(_Parent); break; default: PanicAlert("Type %d config not supported in plugin %s", Type, _rFilename); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -82,32 +82,54 @@ static UGeckoInstruction instCode; NPC = PC + sizeof(UGeckoInstruction); - instCode.hex = Memory::Read_Opcode(PC); + instCode.hex = Memory::Read_Opcode(PC); - UReg_MSR& msr = (UReg_MSR&)MSR; - if (msr.FP) //If FPU is enabled, just execute - m_opTable[instCode.OPCD](instCode); - else + if (instCode.hex != 0) { - // check if we have to generate a FPU unavailable exception - if (!PPCTables::UsesFPU(instCode)) + UReg_MSR& msr = (UReg_MSR&)MSR; + if (msr.FP) //If FPU is enabled, just execute + { m_opTable[instCode.OPCD](instCode); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + PowerPC::CheckExceptions(); + m_EndBlock = true; + } + } else { - PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; - PowerPC::CheckExceptions(); - m_EndBlock = true; + // check if we have to generate a FPU unavailable exception + if (!PPCTables::UsesFPU(instCode)) + { + m_opTable[instCode.OPCD](instCode); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + PowerPC::CheckExceptions(); + m_EndBlock = true; + } + } + else + { + PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; + PowerPC::CheckExceptions(); + m_EndBlock = true; + } } - + } + else + { + // Memory exception on instruction fetch + PowerPC::CheckExceptions(); + m_EndBlock = true; } last_pc = PC; PC = NPC; +#if defined(_DEBUG) || defined(DEBUGFAST) if (PowerPC::ppcState.gpr[1] == 0) { printf("%i Corrupt stack", PowerPC::ppcState.DebugCount); } -#if defined(_DEBUG) || defined(DEBUGFAST) PowerPC::ppcState.DebugCount++; #endif patches(); @@ -224,11 +246,15 @@ void unknown_instruction(UGeckoInstruction _inst) { - char disasm[256]; - DisassembleGekko(Memory::ReadUnchecked_U32(last_pc), last_pc, disasm, 256); - printf("Last PC = %08x : %s\n", last_pc, disasm); - Dolphin_Debugger::PrintCallstack(); - _dbg_assert_msg_(POWERPC, 0, "\nIntCPU: Unknown instr %08x at PC = %08x last_PC = %08x LR = %08x\n", _inst.hex, PC, last_pc, LR); + if (_inst.hex != 0) + { + char disasm[256]; + DisassembleGekko(Memory::ReadUnchecked_U32(last_pc), last_pc, disasm, 256); + printf("Last PC = %08x : %s\n", last_pc, disasm); + Dolphin_Debugger::PrintCallstack(); + _dbg_assert_msg_(POWERPC, 0, "\nIntCPU: Unknown instr %08x at PC = %08x last_PC = %08x LR = %08x\n", _inst.hex, PC, last_pc, LR); + } + } } // namespace diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -58,100 +58,148 @@ void lbz(UGeckoInstruction _inst) { - m_GPR[_inst.RD] = (u32)Memory::Read_U8(Helper_Get_EA(_inst)); + u32 temp = (u32)Memory::Read_U8(Helper_Get_EA(_inst)); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + m_GPR[_inst.RD] = temp; } void lbzu(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_U(_inst); - m_GPR[_inst.RD] = (u32)Memory::Read_U8(uAddress); - m_GPR[_inst.RA] = uAddress; + u32 temp = (u32)Memory::Read_U8(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + m_GPR[_inst.RA] = uAddress; + } } void lfd(UGeckoInstruction _inst) { - riPS0(_inst.FD) = Memory::Read_U64(Helper_Get_EA(_inst)); + u64 temp = Memory::Read_U64(Helper_Get_EA(_inst)); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + riPS0(_inst.FD) = temp; } void lfdu(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_U(_inst); - riPS0(_inst.FD) = Memory::Read_U64(uAddress); - m_GPR[_inst.RA] = uAddress; + u64 temp = Memory::Read_U64(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + riPS0(_inst.FD) = temp; + m_GPR[_inst.RA] = uAddress; + } } void lfdux(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_UX(_inst); - riPS0(_inst.FD) = Memory::Read_U64(uAddress); - m_GPR[_inst.RA] = uAddress; + u64 temp = Memory::Read_U64(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + riPS0(_inst.FD) = temp; + m_GPR[_inst.RA] = uAddress; + } } void lfdx(UGeckoInstruction _inst) { - riPS0(_inst.FD) = Memory::Read_U64(Helper_Get_EA_X(_inst)); + u64 temp = Memory::Read_U64(Helper_Get_EA_X(_inst)); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + riPS0(_inst.FD) = temp; } void lfs(UGeckoInstruction _inst) { u32 uTemp = Memory::Read_U32(Helper_Get_EA(_inst)); - double value = *(float*)&uTemp; - rPS0(_inst.FD) = value; - rPS1(_inst.FD) = value; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + double value = *(float*)&uTemp; + rPS0(_inst.FD) = value; + rPS1(_inst.FD) = value; + } } void lfsu(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_U(_inst); u32 uTemp = Memory::Read_U32(uAddress); - double value = *(float*)&uTemp; - rPS0(_inst.FD) = value; - rPS1(_inst.FD) = value; - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + double value = *(float*)&uTemp; + rPS0(_inst.FD) = value; + rPS1(_inst.FD) = value; + m_GPR[_inst.RA] = uAddress; + } + } void lfsux(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_UX(_inst); u32 uTemp = Memory::Read_U32(uAddress); - double value = *(float*)&uTemp; - rPS0(_inst.FD) = value; - rPS1(_inst.FD) = value; - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + double value = *(float*)&uTemp; + rPS0(_inst.FD) = value; + rPS1(_inst.FD) = value; + m_GPR[_inst.RA] = uAddress; + } } void lfsx(UGeckoInstruction _inst) { u32 uTemp = Memory::Read_U32(Helper_Get_EA_X(_inst)); - double value = *(float*)&uTemp; - rPS0(_inst.FD) = value; - rPS1(_inst.FD) = value; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + double value = *(float*)&uTemp; + rPS0(_inst.FD) = value; + rPS1(_inst.FD) = value; + } } void lha(UGeckoInstruction _inst) { - m_GPR[_inst.RD] = (u32)(s32)(s16)Memory::Read_U16(Helper_Get_EA(_inst)); + u32 temp = (u32)(s32)(s16)Memory::Read_U16(Helper_Get_EA(_inst)); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + } } void lhau(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_U(_inst); - m_GPR[_inst.RD] = (u32)(s32)(s16)Memory::Read_U16(uAddress); - m_GPR[_inst.RA] = uAddress; + u32 temp = (u32)(s32)(s16)Memory::Read_U16(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + m_GPR[_inst.RA] = uAddress; + } } void lhz(UGeckoInstruction _inst) { - m_GPR[_inst.RD] = (u32)(u16)Memory::Read_U16(Helper_Get_EA(_inst)); + u32 temp = (u32)(u16)Memory::Read_U16(Helper_Get_EA(_inst)); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + } } void lhzu(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_U(_inst); - m_GPR[_inst.RD] = (u32)(u16)Memory::Read_U16(uAddress); - m_GPR[_inst.RA] = uAddress; + u32 temp = (u32)(u16)Memory::Read_U16(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + m_GPR[_inst.RA] = uAddress; + } } +// FIXME: lmw should do a total rollback if a DSI occurs void lmw(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA(_inst); @@ -160,14 +208,18 @@ u32 TempReg = Memory::Read_U32(uAddress); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { - PanicAlert("DSI exception in lmv."); + PanicAlert("DSI exception in lmw"); + NOTICE_LOG(POWERPC, "DSI exception in lmw"); return; } - - m_GPR[iReg] = TempReg; + else + { + m_GPR[iReg] = TempReg; + } } } +// FIXME: stmw should do a total rollback if a DSI occurs void stmw(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA(_inst); @@ -175,14 +227,22 @@ { Memory::Write_U32(m_GPR[iReg], uAddress); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + PanicAlert("DSI exception in stmw"); + NOTICE_LOG(POWERPC, "DSI exception in stmw"); return; + } } } void lwz(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA(_inst); - m_GPR[_inst.RD] = Memory::Read_U32(uAddress); + u32 temp = Memory::Read_U32(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + } // hack to detect SelectThread loop // should probably run a pass through memory instead before execution @@ -204,8 +264,12 @@ void lwzu(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_U(_inst); - m_GPR[_inst.RD] = Memory::Read_U32(uAddress); - m_GPR[_inst.RA] = uAddress; + u32 temp = Memory::Read_U32(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + m_GPR[_inst.RA] = uAddress; + } } void stb(UGeckoInstruction _inst) @@ -217,7 +281,10 @@ { u32 uAddress = Helper_Get_EA_U(_inst); Memory::Write_U8((u8)m_GPR[_inst.RS], uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void stfd(UGeckoInstruction _inst) @@ -229,7 +296,10 @@ { u32 uAddress = Helper_Get_EA_U(_inst); Memory::Write_U64(riPS0(_inst.FS), uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void stfs(UGeckoInstruction _inst) @@ -244,7 +314,10 @@ { u32 uAddress = Helper_Get_EA_U(_inst); Memory::Write_U32(ConvertToSingle(riPS0(_inst.FS)), uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void sth(UGeckoInstruction _inst) @@ -256,7 +329,10 @@ { u32 uAddress = Helper_Get_EA_U(_inst); Memory::Write_U16((u16)m_GPR[_inst.RS], uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void stw(UGeckoInstruction _inst) @@ -268,7 +344,10 @@ { u32 uAddress = Helper_Get_EA_U(_inst); Memory::Write_U32(m_GPR[_inst.RS], uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void dcba(UGeckoInstruction _inst) @@ -330,7 +409,9 @@ EA = b + m_GPR[_inst.RB]; if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000)) + { PowerPC::ppcState.Exceptions |= EXCEPTION_DSI; + } if (EA & 3) PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT; @@ -350,7 +431,9 @@ EA = b + m_GPR[_inst.RB]; if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000)) + { PowerPC::ppcState.Exceptions |= EXCEPTION_DSI; + } if (EA & 3) PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT; @@ -372,48 +455,75 @@ { u32 address = Helper_Get_EA_X(_inst); PowerPC::ppcState.iCache.Invalidate(address); - jit->GetBlockCache()->InvalidateICache(address); } void lbzux(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_UX(_inst); - m_GPR[_inst.RD] = (u32)Memory::Read_U8(uAddress); - m_GPR[_inst.RA] = uAddress; + u32 temp = (u32)Memory::Read_U8(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + m_GPR[_inst.RA] = uAddress; + } } void lbzx(UGeckoInstruction _inst) { - m_GPR[_inst.RD] = (u32)Memory::Read_U8(Helper_Get_EA_X(_inst)); + u32 temp = (u32)Memory::Read_U8(Helper_Get_EA_X(_inst)); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + } } void lhaux(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_UX(_inst); - m_GPR[_inst.RD] = (s32)(s16)Memory::Read_U16(uAddress); - m_GPR[_inst.RA] = uAddress; + s32 temp = (s32)(s16)Memory::Read_U16(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + m_GPR[_inst.RA] = uAddress; + } } void lhax(UGeckoInstruction _inst) { - m_GPR[_inst.RD] = (s32)(s16)Memory::Read_U16(Helper_Get_EA_X(_inst)); + s32 temp = (s32)(s16)Memory::Read_U16(Helper_Get_EA_X(_inst)); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + } } void lhbrx(UGeckoInstruction _inst) { - m_GPR[_inst.RD] = (u32)Common::swap16(Memory::Read_U16(Helper_Get_EA_X(_inst))); + u32 temp = (u32)Common::swap16(Memory::Read_U16(Helper_Get_EA_X(_inst))); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + } } void lhzux(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_UX(_inst); - m_GPR[_inst.RD] = (u32)Memory::Read_U16(uAddress); - m_GPR[_inst.RA] = uAddress; + u32 temp = (u32)Memory::Read_U16(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + m_GPR[_inst.RA] = uAddress; + } } void lhzx(UGeckoInstruction _inst) { - m_GPR[_inst.RD] = (u32)Memory::Read_U16(Helper_Get_EA_X(_inst)); + u32 temp = (u32)Memory::Read_U16(Helper_Get_EA_X(_inst)); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + } } void lswx(UGeckoInstruction _inst) @@ -426,27 +536,42 @@ void lwbrx(UGeckoInstruction _inst) { - m_GPR[_inst.RD] = Common::swap32(Memory::Read_U32(Helper_Get_EA_X(_inst))); + u32 temp = Common::swap32(Memory::Read_U32(Helper_Get_EA_X(_inst))); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + } } void lwzux(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_UX(_inst); - m_GPR[_inst.RD] = Memory::Read_U32(uAddress); - m_GPR[_inst.RA] = uAddress; + u32 temp = Memory::Read_U32(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + m_GPR[_inst.RA] = uAddress; + } } void lwzx(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_X(_inst); - m_GPR[_inst.RD] = Memory::Read_U32(uAddress); + u32 temp = Memory::Read_U32(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + } } void stbux(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_UX(_inst); Memory::Write_U8((u8)m_GPR[_inst.RS], uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void stbx(UGeckoInstruction _inst) @@ -458,7 +583,10 @@ { u32 uAddress = Helper_Get_EA_UX(_inst); Memory::Write_U64(riPS0(_inst.FS), uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void stfdx(UGeckoInstruction _inst) @@ -482,7 +610,10 @@ { u32 uAddress = Helper_Get_EA_UX(_inst); Memory::Write_U32(ConvertToSingle(riPS0(_inst.FS)), uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void stfsx(UGeckoInstruction _inst) @@ -499,7 +630,10 @@ { u32 uAddress = Helper_Get_EA_UX(_inst); Memory::Write_U16((u16)m_GPR[_inst.RS], uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void sthx(UGeckoInstruction _inst) @@ -509,7 +643,7 @@ // __________________________________________________________________________________________________ // lswi - bizarro string instruction -// +// FIXME: Should rollback if a DSI occurs void lswi(UGeckoInstruction _inst) { u32 EA; @@ -555,7 +689,7 @@ // todo : optimize ? // __________________________________________________________________________________________________ // stswi - bizarro string instruction -// +// FIXME: Should rollback if a DSI occurs void stswi(UGeckoInstruction _inst) { u32 EA; @@ -581,7 +715,9 @@ } Memory::Write_U8((m_GPR[r] >> (24 - i)) & 0xFF, EA); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { return; + } i += 8; if (i == 32) @@ -612,10 +748,13 @@ void lwarx(UGeckoInstruction _inst) { u32 uAddress = Helper_Get_EA_X(_inst); - m_GPR[_inst.RD] = Memory::Read_U32(uAddress); - - g_bReserve = true; - g_reserveAddr = uAddress; + u32 temp = Memory::Read_U32(uAddress); + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RD] = temp; + g_bReserve = true; + g_reserveAddr = uAddress; + } } void stwcxd(UGeckoInstruction _inst) @@ -626,9 +765,12 @@ uAddress = Helper_Get_EA_X(_inst); if (uAddress == g_reserveAddr) { Memory::Write_U32(m_GPR[_inst.RS], uAddress); - g_bReserve = false; - SetCRField(0, 2 | GetXER_SO()); - return; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + g_bReserve = false; + SetCRField(0, 2 | GetXER_SO()); + return; + } } } @@ -639,7 +781,10 @@ { u32 uAddress = Helper_Get_EA_UX(_inst); Memory::Write_U32(m_GPR[_inst.RS], uAddress); - m_GPR[_inst.RA] = uAddress; + if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) + { + m_GPR[_inst.RA] = uAddress; + } } void stwx(UGeckoInstruction _inst) @@ -665,14 +810,7 @@ { // Invalidate TLB entry u32 _Address = m_GPR[_inst.RB]; - for (int i = 0; i < 16; i++) - { - if ((_Address & ~0xfff) == (PowerPC::ppcState.tlb_va[(PowerPC::ppcState.tlb_last + i) & 15])) - { - PowerPC::ppcState.tlb_pa[(PowerPC::ppcState.tlb_last + i) & 15] = 0; - PowerPC::ppcState.tlb_va[(PowerPC::ppcState.tlb_last + i) & 15] = 0; - } - } + Memory::InvalidateTLBEntry(_Address); } void tlbsync(UGeckoInstruction _inst) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -153,7 +153,6 @@ fResult = 0; break; } - return fResult; } @@ -170,12 +169,23 @@ if (_inst.W == 0) { - rPS0(_inst.RS) = Helper_Dequantize(EA, ldType, ldScale); - rPS1(_inst.RS) = Helper_Dequantize(EA+c, ldType, ldScale); + float ps0 = Helper_Dequantize(EA, ldType, ldScale); + float ps1 = Helper_Dequantize(EA+c, ldType, ldScale); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } + rPS0(_inst.RS) = ps0; + rPS1(_inst.RS) = ps1; } else { - rPS0(_inst.RS) = Helper_Dequantize(EA, ldType, ldScale); + float ps0 = Helper_Dequantize(EA, ldType, ldScale); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } + rPS0(_inst.RS) = ps0; rPS1(_inst.RS) = 1.0f; } } @@ -193,12 +203,23 @@ if (_inst.W == 0) { - rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale ); - rPS1(_inst.RS) = Helper_Dequantize( EA+c, ldType, ldScale ); + float ps0 = Helper_Dequantize( EA, ldType, ldScale ); + float ps1 = Helper_Dequantize( EA+c, ldType, ldScale ); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } + rPS0(_inst.RS) = ps0; + rPS1(_inst.RS) = ps1; } else { - rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale ); + float ps0 = Helper_Dequantize( EA, ldType, ldScale ); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } + rPS0(_inst.RS) = ps0; rPS1(_inst.RS) = 1.0f; } m_GPR[_inst.RA] = EA; @@ -246,6 +267,10 @@ { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); } + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } m_GPR[_inst.RA] = EA; } @@ -262,13 +287,29 @@ if (_inst.Wx == 0) { - rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale ); - rPS1(_inst.RS) = Helper_Dequantize( EA+c, ldType, ldScale ); + float ps0 = Helper_Dequantize( EA, ldType, ldScale ); + float ps1 = Helper_Dequantize( EA+c, ldType, ldScale ); + + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } + + rPS0(_inst.RS) = ps0; + rPS1(_inst.RS) = ps1; } else { - rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale ); - rPS1(_inst.RS) = 1.0f; + float ps0 = Helper_Dequantize( EA, ldType, ldScale ); + float ps1 = 1.0f; + + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } + + rPS0(_inst.RS) = ps0; + rPS1(_inst.RS) = ps1; } } @@ -307,12 +348,23 @@ if (_inst.Wx == 0) { - rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale ); - rPS1(_inst.RS) = Helper_Dequantize( EA+c, ldType, ldScale ); + float ps0 = Helper_Dequantize( EA, ldType, ldScale ); + float ps1 = Helper_Dequantize( EA+c, ldType, ldScale ); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } + rPS0(_inst.RS) = ps0; + rPS1(_inst.RS) = ps1; } else { - rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale ); + float ps0 = Helper_Dequantize( EA, ldType, ldScale ); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } + rPS0(_inst.RS) = ps0; rPS1(_inst.RS) = 1.0f; } m_GPR[_inst.RA] = EA; @@ -338,6 +390,10 @@ { Helper_Quantize(EA, rPS0(_inst.RS), stType, stScale); } + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + return; + } m_GPR[_inst.RA] = EA; } // namespace======= diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Tables.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -63,40 +63,40 @@ {28, Interpreter::andi_rc, {"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}}, {29, Interpreter::andis_rc, {"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}}, - {32, Interpreter::lwz, {"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, - {33, Interpreter::lwzu, {"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, - {34, Interpreter::lbz, {"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, - {35, Interpreter::lbzu, {"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, - {40, Interpreter::lhz, {"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, - {41, Interpreter::lhzu, {"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, - - {42, Interpreter::lha, {"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}}, - {43, Interpreter::lhau, {"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}}, - - {44, Interpreter::sth, {"sth", OPTYPE_STORE, FL_IN_A | FL_IN_S}}, - {45, Interpreter::sthu, {"sthu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}}, - {36, Interpreter::stw, {"stw", OPTYPE_STORE, FL_IN_A | FL_IN_S}}, - {37, Interpreter::stwu, {"stwu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}}, - {38, Interpreter::stb, {"stb", OPTYPE_STORE, FL_IN_A | FL_IN_S}}, - {39, Interpreter::stbu, {"stbu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}}, - - {46, Interpreter::lmw, {"lmw", OPTYPE_SYSTEM, FL_EVIL, 10}}, - {47, Interpreter::stmw, {"stmw", OPTYPE_SYSTEM, FL_EVIL, 10}}, - - {48, Interpreter::lfs, {"lfs", OPTYPE_LOADFP, FL_IN_A | FL_USE_FPU}}, - {49, Interpreter::lfsu, {"lfsu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A | FL_USE_FPU}}, - {50, Interpreter::lfd, {"lfd", OPTYPE_LOADFP, FL_IN_A | FL_USE_FPU}}, - {51, Interpreter::lfdu, {"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A | FL_USE_FPU}}, - - {52, Interpreter::stfs, {"stfs", OPTYPE_STOREFP, FL_IN_A | FL_USE_FPU}}, - {53, Interpreter::stfsu, {"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A | FL_USE_FPU}}, - {54, Interpreter::stfd, {"stfd", OPTYPE_STOREFP, FL_IN_A | FL_USE_FPU}}, - {55, Interpreter::stfdu, {"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A | FL_USE_FPU}}, - - {56, Interpreter::psq_l, {"psq_l", OPTYPE_PS, FL_IN_A | FL_USE_FPU}}, - {57, Interpreter::psq_lu, {"psq_lu", OPTYPE_PS, FL_OUT_A | FL_IN_A | FL_USE_FPU}}, - {60, Interpreter::psq_st, {"psq_st", OPTYPE_PS, FL_IN_A | FL_USE_FPU}}, - {61, Interpreter::psq_stu, {"psq_stu", OPTYPE_PS, FL_OUT_A | FL_IN_A | FL_USE_FPU}}, + {32, Interpreter::lwz, {"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A | FL_LOADSTORE}}, + {33, Interpreter::lwzu, {"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE}}, + {34, Interpreter::lbz, {"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A | FL_LOADSTORE}}, + {35, Interpreter::lbzu, {"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE}}, + {40, Interpreter::lhz, {"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A | FL_LOADSTORE}}, + {41, Interpreter::lhzu, {"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE}}, + + {42, Interpreter::lha, {"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A | FL_LOADSTORE}}, + {43, Interpreter::lhau, {"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE}}, + + {44, Interpreter::sth, {"sth", OPTYPE_STORE, FL_IN_A | FL_IN_S | FL_LOADSTORE}}, + {45, Interpreter::sthu, {"sthu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE}}, + {36, Interpreter::stw, {"stw", OPTYPE_STORE, FL_IN_A | FL_IN_S | FL_LOADSTORE}}, + {37, Interpreter::stwu, {"stwu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE}}, + {38, Interpreter::stb, {"stb", OPTYPE_STORE, FL_IN_A | FL_IN_S | FL_LOADSTORE}}, + {39, Interpreter::stbu, {"stbu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE}}, + + {46, Interpreter::lmw, {"lmw", OPTYPE_SYSTEM, FL_EVIL | FL_LOADSTORE, 10}}, + {47, Interpreter::stmw, {"stmw", OPTYPE_SYSTEM, FL_EVIL | FL_LOADSTORE, 10}}, + + {48, Interpreter::lfs, {"lfs", OPTYPE_LOADFP, FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + {49, Interpreter::lfsu, {"lfsu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + {50, Interpreter::lfd, {"lfd", OPTYPE_LOADFP, FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + {51, Interpreter::lfdu, {"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + + {52, Interpreter::stfs, {"stfs", OPTYPE_STOREFP, FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + {53, Interpreter::stfsu, {"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + {54, Interpreter::stfd, {"stfd", OPTYPE_STOREFP, FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + {55, Interpreter::stfdu, {"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + + {56, Interpreter::psq_l, {"psq_l", OPTYPE_PS, FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + {57, Interpreter::psq_lu, {"psq_lu", OPTYPE_PS, FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + {60, Interpreter::psq_st, {"psq_st", OPTYPE_PS, FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, + {61, Interpreter::psq_stu, {"psq_stu", OPTYPE_PS, FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE}}, //missing: 0, 5, 6, 9, 22, 30, 62, 58 {0, Interpreter::unknown_instruction, {"unknown_instruction", OPTYPE_UNKNOWN, 0}}, @@ -151,10 +151,10 @@ static GekkoOPTemplate table4_3[] = { - {6, Interpreter::psq_lx, {"psq_lx", OPTYPE_PS, FL_USE_FPU}}, - {7, Interpreter::psq_stx, {"psq_stx", OPTYPE_PS, FL_USE_FPU}}, - {38, Interpreter::psq_lux, {"psq_lux", OPTYPE_PS, FL_USE_FPU}}, - {39, Interpreter::psq_stux, {"psq_stux", OPTYPE_PS, FL_USE_FPU}}, + {6, Interpreter::psq_lx, {"psq_lx", OPTYPE_PS, FL_USE_FPU | FL_LOADSTORE}}, + {7, Interpreter::psq_stx, {"psq_stx", OPTYPE_PS, FL_USE_FPU | FL_LOADSTORE}}, + {38, Interpreter::psq_lux, {"psq_lux", OPTYPE_PS, FL_USE_FPU | FL_LOADSTORE}}, + {39, Interpreter::psq_stux, {"psq_stux", OPTYPE_PS, FL_USE_FPU | FL_LOADSTORE}}, }; static GekkoOPTemplate table19[] = @@ -207,63 +207,63 @@ {1014, Interpreter::dcbz, {"dcbz", OPTYPE_DCACHE, 0, 4}}, //load word - {23, Interpreter::lwzx, {"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, - {55, Interpreter::lwzux, {"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + {23, Interpreter::lwzx, {"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, + {55, Interpreter::lwzux, {"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B | FL_LOADSTORE}}, //load halfword - {279, Interpreter::lhzx, {"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, - {311, Interpreter::lhzux, {"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + {279, Interpreter::lhzx, {"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, + {311, Interpreter::lhzux, {"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B | FL_LOADSTORE}}, //load halfword signextend - {343, Interpreter::lhax, {"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, - {375, Interpreter::lhaux, {"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + {343, Interpreter::lhax, {"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, + {375, Interpreter::lhaux, {"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B | FL_LOADSTORE}}, //load byte - {87, Interpreter::lbzx, {"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, - {119, Interpreter::lbzux, {"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}}, + {87, Interpreter::lbzx, {"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, + {119, Interpreter::lbzux, {"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B | FL_LOADSTORE}}, //load byte reverse - {534, Interpreter::lwbrx, {"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, - {790, Interpreter::lhbrx, {"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}}, + {534, Interpreter::lwbrx, {"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, + {790, Interpreter::lhbrx, {"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, // Conditional load/store (Wii SMP) - {150, Interpreter::stwcxd, {"stwcxd", OPTYPE_STORE, FL_EVIL | FL_SET_CR0}}, - {20, Interpreter::lwarx, {"lwarx", OPTYPE_LOAD, FL_EVIL | FL_OUT_D | FL_IN_A0B | FL_SET_CR0}}, + {150, Interpreter::stwcxd, {"stwcxd", OPTYPE_STORE, FL_EVIL | FL_SET_CR0 | FL_LOADSTORE}}, + {20, Interpreter::lwarx, {"lwarx", OPTYPE_LOAD, FL_EVIL | FL_OUT_D | FL_IN_A0B | FL_SET_CR0 | FL_LOADSTORE}}, //load string (Inst these) - {533, Interpreter::lswx, {"lswx", OPTYPE_LOAD, FL_EVIL | FL_IN_A | FL_OUT_D}}, - {597, Interpreter::lswi, {"lswi", OPTYPE_LOAD, FL_EVIL | FL_IN_AB | FL_OUT_D}}, + {533, Interpreter::lswx, {"lswx", OPTYPE_LOAD, FL_EVIL | FL_IN_A | FL_OUT_D | FL_LOADSTORE}}, + {597, Interpreter::lswi, {"lswi", OPTYPE_LOAD, FL_EVIL | FL_IN_AB | FL_OUT_D | FL_LOADSTORE}}, //store word - {151, Interpreter::stwx, {"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, - {183, Interpreter::stwux, {"stwux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}}, + {151, Interpreter::stwx, {"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, + {183, Interpreter::stwux, {"stwux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B | FL_LOADSTORE}}, //store halfword - {407, Interpreter::sthx, {"sthx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, - {439, Interpreter::sthux, {"sthux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}}, + {407, Interpreter::sthx, {"sthx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, + {439, Interpreter::sthux, {"sthux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B | FL_LOADSTORE}}, //store byte - {215, Interpreter::stbx, {"stbx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, - {247, Interpreter::stbux, {"stbux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}}, + {215, Interpreter::stbx, {"stbx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, + {247, Interpreter::stbux, {"stbux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B | FL_LOADSTORE}}, //store bytereverse - {662, Interpreter::stwbrx, {"stwbrx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}}, - {918, Interpreter::sthbrx, {"sthbrx", OPTYPE_STORE, FL_IN_A | FL_IN_B}}, + {662, Interpreter::stwbrx, {"stwbrx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B | FL_LOADSTORE}}, + {918, Interpreter::sthbrx, {"sthbrx", OPTYPE_STORE, FL_IN_A | FL_IN_B | FL_LOADSTORE}}, - {661, Interpreter::stswx, {"stswx", OPTYPE_STORE, FL_EVIL}}, - {725, Interpreter::stswi, {"stswi", OPTYPE_STORE, FL_EVIL}}, + {661, Interpreter::stswx, {"stswx", OPTYPE_STORE, FL_EVIL | FL_LOADSTORE}}, + {725, Interpreter::stswi, {"stswi", OPTYPE_STORE, FL_EVIL | FL_LOADSTORE}}, // fp load/store - {535, Interpreter::lfsx, {"lfsx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU}}, - {567, Interpreter::lfsux, {"lfsux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B | FL_USE_FPU}}, - {599, Interpreter::lfdx, {"lfdx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU}}, - {631, Interpreter::lfdux, {"lfdux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B | FL_USE_FPU}}, - - {663, Interpreter::stfsx, {"stfsx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU}}, - {695, Interpreter::stfsux, {"stfsux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B | FL_USE_FPU}}, - {727, Interpreter::stfdx, {"stfdx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU}}, - {759, Interpreter::stfdux, {"stfdux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B | FL_USE_FPU}}, - {983, Interpreter::stfiwx, {"stfiwx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU}}, + {535, Interpreter::lfsx, {"lfsx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU | FL_LOADSTORE}}, + {567, Interpreter::lfsux, {"lfsux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B | FL_USE_FPU | FL_LOADSTORE}}, + {599, Interpreter::lfdx, {"lfdx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU | FL_LOADSTORE}}, + {631, Interpreter::lfdux, {"lfdux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B | FL_USE_FPU | FL_LOADSTORE}}, + + {663, Interpreter::stfsx, {"stfsx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU | FL_LOADSTORE}}, + {695, Interpreter::stfsux, {"stfsux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B | FL_USE_FPU | FL_LOADSTORE}}, + {727, Interpreter::stfdx, {"stfdx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU | FL_LOADSTORE}}, + {759, Interpreter::stfdux, {"stfdux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B | FL_USE_FPU | FL_LOADSTORE}}, + {983, Interpreter::stfiwx, {"stfiwx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B | FL_USE_FPU | FL_LOADSTORE}}, {19, Interpreter::mfcr, {"mfcr", OPTYPE_SYSTEM, FL_OUT_D}}, {83, Interpreter::mfmsr, {"mfmsr", OPTYPE_SYSTEM, FL_OUT_D}}, diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -174,17 +174,17 @@ { {528, &Jit64::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, {16, &Jit64::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, - {257, &Jit64::Default}, //"crand", OPTYPE_CR, FL_EVIL}}, - {129, &Jit64::Default}, //"crandc", OPTYPE_CR, FL_EVIL}}, - {289, &Jit64::Default}, //"creqv", OPTYPE_CR, FL_EVIL}}, - {225, &Jit64::Default}, //"crnand", OPTYPE_CR, FL_EVIL}}, - {33, &Jit64::Default}, //"crnor", OPTYPE_CR, FL_EVIL}}, - {449, &Jit64::Default}, //"cror", OPTYPE_CR, FL_EVIL}}, - {417, &Jit64::Default}, //"crorc", OPTYPE_CR, FL_EVIL}}, - {193, &Jit64::Default}, //"crxor", OPTYPE_CR, FL_EVIL}}, + {257, &Jit64::crXXX}, //"crand", OPTYPE_CR, FL_EVIL}}, + {129, &Jit64::crXXX}, //"crandc", OPTYPE_CR, FL_EVIL}}, + {289, &Jit64::crXXX}, //"creqv", OPTYPE_CR, FL_EVIL}}, + {225, &Jit64::crXXX}, //"crnand", OPTYPE_CR, FL_EVIL}}, + {33, &Jit64::crXXX}, //"crnor", OPTYPE_CR, FL_EVIL}}, + {449, &Jit64::crXXX}, //"cror", OPTYPE_CR, FL_EVIL}}, + {417, &Jit64::crXXX}, //"crorc", OPTYPE_CR, FL_EVIL}}, + {193, &Jit64::crXXX}, //"crxor", OPTYPE_CR, FL_EVIL}}, {150, &Jit64::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}}, - {0, &Jit64::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}}, + {0, &Jit64::mcrf}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}}, {50, &Jit64::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}}, {18, &Jit64::Default}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}} @@ -193,14 +193,14 @@ static GekkoOPTemplate table31[] = { - {28, &Jit64::andx}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {60, &Jit64::Default}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {444, &Jit64::orx}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {124, &Jit64::Default}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {316, &Jit64::xorx}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {412, &Jit64::Default}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {476, &Jit64::Default}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, - {284, &Jit64::Default}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {28, &Jit64::boolX}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {60, &Jit64::boolX}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {444, &Jit64::boolX}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {124, &Jit64::boolX}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {316, &Jit64::boolX}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {412, &Jit64::boolX}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {476, &Jit64::boolX}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, + {284, &Jit64::boolX}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}}, {0, &Jit64::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}}, {32, &Jit64::cmpXX}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}}, {26, &Jit64::cntlzwx}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}}, @@ -287,7 +287,7 @@ {339, &Jit64::mfspr}, //"mfspr", OPTYPE_SPR, FL_OUT_D}}, {467, &Jit64::mtspr}, //"mtspr", OPTYPE_SPR, 0, 2}}, {371, &Jit64::mftb}, //"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER}}, - {512, &Jit64::Default}, //"mcrxr", OPTYPE_SYSTEM, 0}}, + {512, &Jit64::mcrxr}, //"mcrxr", OPTYPE_SYSTEM, 0}}, {595, &Jit64::Default}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}}, {659, &Jit64::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}}, @@ -307,10 +307,10 @@ static GekkoOPTemplate table31_2[] = { {266, &Jit64::addx}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, - {10, &Jit64::Default}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, + {10, &Jit64::addcx}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, {138, &Jit64::addex}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, - {234, &Jit64::Default}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, - {202, &Jit64::Default}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {234, &Jit64::addmex}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {202, &Jit64::addzex}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {491, &Jit64::Default}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, {459, &Jit64::divwux}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}}, {75, &Jit64::Default}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}}, @@ -320,8 +320,8 @@ {40, &Jit64::subfx}, //"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}}, {8, &Jit64::subfcx}, //"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}}, {136, &Jit64::subfex}, //"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, - {232, &Jit64::Default}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, - {200, &Jit64::Default}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {232, &Jit64::subfmex}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {200, &Jit64::subfzex}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, }; static GekkoOPTemplate table59[] = @@ -389,8 +389,6 @@ #endif info->compileCount++; info->lastUse = jit->js.compilerPC; - } else { - PanicAlert("Tried to compile illegal (or unknown) instruction %08x, at %08x", op.inst.hex, jit->js.compilerPC); } } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -129,8 +129,6 @@ //FP blocks test for FPU available, jump here if false fpException = AlignCode4(); - MOV(32, R(EAX), M(&PC)); - MOV(32, M(&NPC), R(EAX)); OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE)); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExceptions)); MOV(32, R(EAX), M(&NPC)); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -47,7 +47,9 @@ gpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL); - WriteExceptionExit(EXCEPTION_SYSCALL); + MOV(32, M(&PC), Imm32(js.compilerPC + 4)); + OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_SYSCALL)); + WriteExceptionExit(); } void Jit64::rfi(UGeckoInstruction inst) @@ -59,15 +61,12 @@ fpr.Flush(FLUSH_ALL); // See Interpreter rfi for details const u32 mask = 0x87C0FFFF; - // MSR = (MSR & ~mask) | (SRR1 & mask); - MOV(32, R(EAX), M(&MSR)); - MOV(32, R(ECX), M(&SRR1)); - AND(32, R(EAX), Imm32(~mask)); - AND(32, R(ECX), Imm32(mask)); - OR(32, R(EAX), R(ECX)); - // MSR &= 0xFFFDFFFF; //TODO: VERIFY - AND(32, R(EAX), Imm32(0xFFFBFFFF)); - MOV(32, M(&MSR), R(EAX)); + const u32 clearMSR13 = 0xFFFBFFFF; // Mask used to clear the bit MSR[13] + // MSR = ((MSR & ~mask) | (SRR1 & mask)) & clearMSR13; + AND(32, M(&MSR), Imm32((~mask) & clearMSR13)); + MOV(32, R(EAX), M(&SRR1)); + AND(32, R(EAX), Imm32(mask & clearMSR13)); + OR(32, M(&MSR), R(EAX)); // NPC = SRR0; MOV(32, R(EAX), M(&SRR0)); WriteRfiExitDestInEAX(); @@ -124,87 +123,41 @@ gpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL); - CCFlags branch = CC_Z; - - //const bool only_counter_check = (inst.BO & 16) ? true : false; - //const bool only_condition_check = (inst.BO & 4) ? true : false; - //if (only_condition_check && only_counter_check) - // PanicAlert("Bizarre bcx encountered. Likely bad or corrupt code."); - bool doFullTest = ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) && ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0); - bool ctrDecremented = false; - - if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit - { - TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); - if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch - branch = CC_NZ; - else - branch = CC_Z; - - if (doFullTest) - SETcc(branch, R(EAX)); - } - else - { - if (doFullTest) - MOV(32, R(EAX), Imm32(1)); - } - + FixupBranch pCTRDontBranch; if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR { - // Decrement CTR SUB(32, M(&CTR), Imm8(1)); - ctrDecremented = true; - // Test whether to branch if CTR is zero or not if (inst.BO & BO_BRANCH_IF_CTR_0) - branch = CC_Z; + pCTRDontBranch = J_CC(CC_NZ); else - branch = CC_NZ; - - if (doFullTest) - SETcc(branch, R(ECX)); - } - else - { - if (doFullTest) - MOV(32, R(ECX), Imm32(1)); + pCTRDontBranch = J_CC(CC_Z); } - if (doFullTest) - { - TEST(32, R(EAX), R(ECX)); - branch = CC_Z; - } - else + FixupBranch pConditionDontBranch; + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit { - if (branch == CC_Z) - branch = CC_NZ; + TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); + if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch + pConditionDontBranch = J_CC(CC_Z); else - branch = CC_Z; - } - - if (!ctrDecremented && (inst.BO & BO_DONT_DECREMENT_FLAG) == 0) - { - SUB(32, M(&CTR), Imm8(1)); - } - FixupBranch skip; - if (inst.BO != 20) - { - skip = J_CC(branch); + pConditionDontBranch = J_CC(CC_NZ); } - u32 destination; + if (inst.LK) MOV(32, M(&LR), Imm32(js.compilerPC + 4)); + + u32 destination; if(inst.AA) destination = SignExt16(inst.BD << 2); else destination = js.compilerPC + SignExt16(inst.BD << 2); WriteExit(destination, 0); - if (inst.BO != 20) - { - SetJumpTarget(skip); - WriteExit(js.compilerPC + 4, 1); - } + + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) + SetJumpTarget( pConditionDontBranch ); + if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) + SetJumpTarget( pCTRDontBranch ); + WriteExit(js.compilerPC + 4, 1); } void Jit64::bcctrx(UGeckoInstruction inst) @@ -243,20 +196,19 @@ branch = CC_Z; else branch = CC_NZ; - MOV(32, R(EAX), Imm32(js.compilerPC + 4)); FixupBranch b = J_CC(branch, false); MOV(32, R(EAX), M(&CTR)); + AND(32, R(EAX), Imm32(0xFFFFFFFC)); //MOV(32, M(&PC), R(EAX)); => Already done in WriteExitDestInEAX() if (inst.LK_3) MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4; + WriteExitDestInEAX(0); // Would really like to continue the block here, but it ends. TODO. SetJumpTarget(b); - WriteExitDestInEAX(0); - return; + WriteExit(js.compilerPC + 4, 1); } } - void Jit64::bclrx(UGeckoInstruction inst) { INSTRUCTION_START @@ -264,50 +216,42 @@ gpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL); - //Special case BLR & BLRL - if ((inst.hex & ~1) == 0x4e800020) + + FixupBranch pCTRDontBranch; + if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR { - //CDynaRegCache::Flush(); + SUB(32, M(&CTR), Imm8(1)); + if (inst.BO & BO_BRANCH_IF_CTR_0) + pCTRDontBranch = J_CC(CC_NZ); + else + pCTRDontBranch = J_CC(CC_Z); + } + + FixupBranch pConditionDontBranch; + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit + { + TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); + if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch + pConditionDontBranch = J_CC(CC_Z); + else + pConditionDontBranch = J_CC(CC_NZ); + } + // This below line can be used to prove that blr "eats flags" in practice. // This observation will let us do a lot of fun observations. #ifdef ACID_TEST AND(32, M(&CR), Imm32(~(0xFF000000))); #endif - MOV(32, R(EAX), M(&LR)); - //MOV(32, M(&PC), R(EAX)); => Already done in WriteExitDestInEAX() - if (inst.LK_3) - MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4; - WriteExitDestInEAX(0); - return; - } else if ((inst.BO_2 & BO_DONT_DECREMENT_FLAG) == 0) { - // Decrement CTR. Not mutually exclusive... - // Will fall back to int, but we should be able to do it here, sometime - } else if ((inst.BO_2 & BO_DONT_CHECK_CONDITION) == 0) { - // Test a CR bit. Not too hard. - // beqlr- 4d820020 - // blelr- 4c810020 - // blrl 4e800021 - // bnelr 4c820020 - // etc... - TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); - Gen::CCFlags branch; - if (inst.BO_2 & BO_BRANCH_IF_TRUE) - branch = CC_Z; - else - branch = CC_NZ; - FixupBranch b = J_CC(branch, false); - MOV(32, R(EAX), M(&LR)); - //MOV(32, M(&PC), R(EAX)); => Already done in WriteExitDestInEAX() - if (inst.LK_3) - MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4; - WriteExitDestInEAX(0); - // Would really like to continue the block here, but it ends. TODO. - SetJumpTarget(b); - WriteExit(js.compilerPC + 4, 1); - return; - } - // Call interpreter - Default(inst); - MOV(32, R(EAX), M(&NPC)); - WriteExitDestInEAX(0); + + MOV(32, R(EAX), M(&LR)); + AND(32, R(EAX), Imm32(0xFFFFFFFC)); + if (inst.LK) + MOV(32, M(&LR), Imm32(js.compilerPC + 4)); + WriteExitDestInEAX(0); + + if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) + SetJumpTarget( pConditionDontBranch ); + if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) + SetJumpTarget( pCTRDontBranch ); + WriteExit(js.compilerPC + 4, 1); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -175,35 +175,35 @@ where this cause problems, so I'm enabling this by default, since I seem to get perhaps as much as 20% more fps with this option enabled. If you suspect that this option cause problems you can also disable it from the debugging window. */ - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) + if (Core::g_CoreStartupParameter.bEnableDebugging) { jo.enableBlocklink = false; - SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle = false; + Core::g_CoreStartupParameter.bSkipIdle = false; } else { - jo.enableBlocklink = true; + if (!Core::g_CoreStartupParameter.bJITBlockLinking) + { + jo.enableBlocklink = false; + } + else + jo.enableBlocklink = !Core::g_CoreStartupParameter.bMMU; } #ifdef _M_X64 - jo.enableFastMem = SConfig::GetInstance().m_LocalCoreStartupParameter.bUseFastMem; + jo.enableFastMem = Core::g_CoreStartupParameter.bUseFastMem; #else jo.enableFastMem = false; #endif - jo.assumeFPLoadFromMem = true; + jo.assumeFPLoadFromMem = Core::g_CoreStartupParameter.bUseFastMem; jo.fpAccurateFcmp = true; // Fallback to Interpreter jo.optimizeGatherPipe = true; jo.fastInterrupts = false; jo.accurateSinglePrecision = true; + js.memcheck = Core::g_CoreStartupParameter.bMMU; gpr.SetEmitter(this); fpr.SetEmitter(this); - if (Core::g_CoreStartupParameter.bJITBlockLinking) - { - jo.enableBlocklink = false; - SuccessAlert("Your game was started without JIT Block Linking"); - } - trampolines.Init(); AllocCodeSpace(CODE_SIZE); @@ -218,7 +218,6 @@ ClearCodeSpace(); } - void Jit64::Shutdown() { FreeCodeSpace(); @@ -266,15 +265,6 @@ // Yup, just don't do anything. } -void Jit64::NotifyBreakpoint(u32 em_address, bool set) -{ - int block_num = blocks.GetBlockNumberFromStartAddress(em_address); - if (block_num >= 0) - { - blocks.DestroyBlock(block_num, false); - } -} - static const bool ImHereDebug = false; static const bool ImHereLog = false; static std::map been_here; @@ -349,11 +339,10 @@ JMP(asm_routines.testExceptions, true); } -void Jit64::WriteExceptionExit(u32 exception) +void Jit64::WriteExceptionExit() { Cleanup(); - OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(exception)); - MOV(32, M(&PC), Imm32(js.compilerPC + 4)); + SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); JMP(asm_routines.testExceptions, true); } @@ -361,7 +350,6 @@ { CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode; pExecAddr(); - //Will return when PowerPC::state changes } void Jit64::SingleStep() @@ -370,7 +358,7 @@ pExecAddr(); } -void Jit64::Trace(PPCAnalyst::CodeBuffer *code_buf, u32 em_address) +void Jit64::Trace() { char regs[500] = ""; char fregs[750] = ""; @@ -392,11 +380,11 @@ strncat(fregs, reg, 750); } #endif - const PPCAnalyst::CodeOp &op = code_buf->codebuffer[0]; - char ppcInst[256]; - DisassembleGekko(op.inst.hex, em_address, ppcInst, 256); - NOTICE_LOG(DYNA_REC, "JIT64 PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs, op.inst.hex, ppcInst); + NOTICE_LOG(DYNA_REC, "JIT64 PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s", + PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], + PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, + PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs); } void STACKALIGN Jit64::Jit(u32 em_address) @@ -410,21 +398,42 @@ blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, &code_buffer, b)); } - const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b) { int blockSize = code_buf->GetSize(); - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) + // Memory exception on instruction fetch + bool memory_exception = false; + + // A broken block is a block that does not end in a branch + bool broken_block = false; + + if (Core::g_CoreStartupParameter.bEnableDebugging) { // Comment out the following to disable breakpoints (speed-up) blockSize = 1; - Trace(code_buf, em_address); + broken_block = true; + Trace(); } if (em_address == 0) PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR); + if (Core::g_CoreStartupParameter.bMMU && + (em_address >> 28) != 0x0 && + (em_address >> 28) != 0x8 && + (em_address >> 28) != 0x9 && + (em_address >> 28) != 0xC && + (em_address >> 28) != 0xD + ) + { + if (!Memory::TranslateAddress(em_address, Memory::FLAG_OPCODE)) + { + // Memory exception occurred during instruction fetch + memory_exception = true; + } + } + int size = 0; js.isLastInstruction = false; js.blockStart = em_address; @@ -435,7 +444,12 @@ //Analyze the block, collect all instructions it is made of (including inlining, //if that is enabled), reorder instructions for optimal performance, and join joinable instructions. - u32 nextPC = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, code_buf, blockSize); + u32 nextPC = em_address; + if (!memory_exception) + { + // If there is a memory exception inside a block (broken_block==true), compile up to that instruction. + nextPC = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize); + } PPCAnalyst::CodeOp *ops = code_buf->codebuffer; @@ -465,16 +479,6 @@ SetJumpTarget(b1); } - if (false && jo.fastInterrupts) - { - // This does NOT yet work. - TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF)); - FixupBranch b1 = J_CC(CC_Z); - MOV(32, M(&PC), Imm32(js.blockStart)); - JMP(asm_routines.testExceptions, true); - SetJumpTarget(b1); - } - // Conditionally add profiling code. if (Profiler::g_ProfileBlocks) { ADD(32, M(&b->runCount), Imm8(1)); @@ -498,18 +502,22 @@ gpr.Start(js.gpa); fpr.Start(js.fpa); - js.downcountAmount = js.st.numCycles; - if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) - js.downcountAmount = js.st.numCycles + PatchEngine::GetSpeedhackCycles(em_address); + js.downcountAmount = 0; + if (!Core::g_CoreStartupParameter.bEnableDebugging) + js.downcountAmount += PatchEngine::GetSpeedhackCycles(em_address); js.skipnext = false; js.blockSize = size; + js.compilerPC = nextPC; // Translate instructions for (int i = 0; i < (int)size; i++) { js.compilerPC = ops[i].address; js.op = &ops[i]; js.instructionNumber = i; + const GekkoOPInfo *opinfo = ops[i].opinfo; + js.downcountAmount += (opinfo->numCyclesMinusOne + 1); + if (i == (int)size - 1) { // WARNING - cmp->branch merging will screw this up. @@ -539,8 +547,40 @@ } if (!ops[i].skip) + { + if (js.memcheck && (opinfo->flags & FL_USE_FPU)) + { + //This instruction uses FPU - needs to add FP exception bailout + TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); // Test FP enabled bit + FixupBranch b1 = J_CC(CC_NZ); + + // If a FPU exception occurs, the exception handler will read + // from PC. Update PC with the latest value in case that happens. + MOV(32, M(&PC), Imm32(ops[i].address)); + SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); + JMP(asm_routines.fpException, true); + SetJumpTarget(b1); + } + Jit64Tables::CompileInstruction(ops[i]); + if (js.memcheck && (opinfo->flags & FL_LOADSTORE)) + { + // In case we are about to jump to the dispatcher, flush regs + gpr.Flush(FLUSH_ALL); + fpr.Flush(FLUSH_ALL); + + TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI)); + FixupBranch noMemException = J_CC(CC_Z); + + // If a memory exception occurs, the exception handler will read + // from PC. Update PC with the latest value in case that happens. + MOV(32, M(&PC), Imm32(ops[i].address)); + WriteExceptionExit(); + SetJumpTarget(noMemException); + } + } + #if defined(_DEBUG) || defined(DEBUGFAST) if (gpr.SanityCheck() || fpr.SanityCheck()) { @@ -558,7 +598,14 @@ if (js.cancel) break; } - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) + + if (memory_exception) + { + ABI_CallFunctionC(reinterpret_cast(&Memory::GenerateISIException_JIT), js.compilerPC); + WriteExceptionExit(); + } + + if (broken_block) { gpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -34,24 +34,24 @@ fpr.Lock(d, a, b); if (d == a) { - fpr.LoadToX64(d, true); + fpr.BindToRegister(d, true); (this->*op)(fpr.RX(d), fpr.R(b)); } else if (d == b && reversible) { - fpr.LoadToX64(d, true); + fpr.BindToRegister(d, true); (this->*op)(fpr.RX(d), fpr.R(a)); } else if (a != d && b != d) { // Sources different from d, can use rather quick solution - fpr.LoadToX64(d, !dupe); + fpr.BindToRegister(d, !dupe); MOVSD(fpr.RX(d), fpr.R(a)); (this->*op)(fpr.RX(d), fpr.R(b)); } else if (b != d) { - fpr.LoadToX64(d, !dupe); + fpr.BindToRegister(d, !dupe); MOVSD(XMM0, fpr.R(b)); MOVSD(fpr.RX(d), fpr.R(a)); (this->*op)(fpr.RX(d), Gen::R(XMM0)); @@ -60,7 +60,7 @@ { MOVSD(XMM0, fpr.R(a)); MOVSD(XMM1, fpr.R(b)); - fpr.LoadToX64(d, !dupe); + fpr.BindToRegister(d, !dupe); (this->*op)(XMM0, Gen::R(XMM1)); MOVSD(fpr.RX(d), Gen::R(XMM0)); } @@ -87,7 +87,7 @@ int d = inst.FD; int b = inst.FB; fpr.Lock(b, d); - fpr.LoadToX64(d, true, true); + fpr.BindToRegister(d, true, true); MOVSD(XMM0, M((void *)&one_const)); SQRTSD(XMM1, fpr.R(b)); DIVSD(XMM0, R(XMM1)); @@ -160,7 +160,7 @@ XORPD(XMM0, M((void*)&psSignBits2)); break; } - fpr.LoadToX64(d, false); + fpr.BindToRegister(d, false); //YES it is necessary to dupe the result :( //TODO : analysis - does the top reg get used? If so, dupe, if not, don't. if (single_precision) { @@ -186,7 +186,7 @@ int d = inst.FD; int b = inst.FB; fpr.Lock(b, d); - fpr.LoadToX64(d, true, true); + fpr.BindToRegister(d, true, true); MOVSD(XMM0, fpr.R(b)); switch (inst.SUBOP10) { case 40: // fnegx @@ -216,7 +216,7 @@ int d = inst.FD; int b = inst.FB; fpr.Lock(b, d); - fpr.LoadToX64(d, true, true); + fpr.BindToRegister(d, true, true); MOVSD(XMM0, fpr.R(b)); MOVSD(fpr.R(d), XMM0); fpr.UnlockAll(); @@ -238,7 +238,7 @@ int crf = inst.CRFD; fpr.Lock(a,b); - if (a != b) fpr.LoadToX64(a, true); + if (a != b) fpr.BindToRegister(a, true); // Are we masking sNaN invalid floating point exceptions? If not this could crash if we don't handle the exception? UCOMISD(fpr.R(a).GetSimpleReg(), fpr.R(b)); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit.h 2010-08-18 03:25:18.000000000 +0100 @@ -52,6 +52,16 @@ Core::g_CoreStartupParameter.bJIT##type##Off) \ {Default(inst); return;} +#define MEMCHECK_START \ + FixupBranch memException; \ + if (js.memcheck) \ + { TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI)); \ + memException = J_CC(CC_NZ); } + +#define MEMCHECK_END \ + if (js.memcheck) \ + SetJumpTarget(memException); + class Jit64 : public JitBase { private: @@ -69,6 +79,7 @@ int block_flags; bool isLastInstruction; + bool memcheck; int fifoBytesThisBlock; @@ -104,13 +115,12 @@ JitBlockCache *GetBlockCache() { return &blocks; } - void NotifyBreakpoint(u32 em_address, bool set); - void Trace(PPCAnalyst::CodeBuffer *code_buffer, u32 em_address); + void Trace(); void ClearCache(); const u8 *GetDispatcher() { - return asm_routines.dispatcher; // asm_routines.dispatcher + return asm_routines.dispatcher; } const CommonAsmRoutines *GetAsmRoutines() { return &asm_routines; @@ -132,7 +142,7 @@ void WriteExit(u32 destination, int exit_num); void WriteExitDestInEAX(int exit_num); - void WriteExceptionExit(u32 exception); + void WriteExceptionExit(); void WriteRfiExitDestInEAX(); void WriteCallInterpreter(UGeckoInstruction _inst); void Cleanup(); @@ -158,9 +168,7 @@ void DynaRunTable63(UGeckoInstruction _inst); void addx(UGeckoInstruction inst); - void orx(UGeckoInstruction inst); - void xorx(UGeckoInstruction inst); - void andx(UGeckoInstruction inst); + void addcx(UGeckoInstruction inst); void mulli(UGeckoInstruction inst); void mulhwux(UGeckoInstruction inst); void mullwx(UGeckoInstruction inst); @@ -168,6 +176,8 @@ void srawix(UGeckoInstruction inst); void srawx(UGeckoInstruction inst); void addex(UGeckoInstruction inst); + void addmex(UGeckoInstruction inst); + void addzex(UGeckoInstruction inst); void extsbx(UGeckoInstruction inst); void extshx(UGeckoInstruction inst); @@ -187,6 +197,11 @@ void mftb(UGeckoInstruction inst); void mtcrf(UGeckoInstruction inst); void mfcr(UGeckoInstruction inst); + void mcrf(UGeckoInstruction inst); + void mcrxr(UGeckoInstruction inst); + + void boolX(UGeckoInstruction inst); + void crXXX(UGeckoInstruction inst); void reg_imm(UGeckoInstruction inst); @@ -236,6 +251,8 @@ void subfcx(UGeckoInstruction inst); void subfx(UGeckoInstruction inst); void subfex(UGeckoInstruction inst); + void subfmex(UGeckoInstruction inst); + void subfzex(UGeckoInstruction inst); void lbzx(UGeckoInstruction inst); void lwzx(UGeckoInstruction inst); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -28,29 +28,42 @@ void Jit64::GenerateCarry() { // USES_XER FixupBranch pNoCarry = J_CC(CC_NC); - OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(1 << 29)); + OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_CA_MASK)); FixupBranch pContinue = J(); SetJumpTarget(pNoCarry); - AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(1 << 29))); + AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(XER_CA_MASK))); SetJumpTarget(pContinue); } void Jit64::ComputeRC(const Gen::OpArg & arg) { - CMP(32, arg, Imm8(0)); - FixupBranch pLesser = J_CC(CC_L); - FixupBranch pGreater = J_CC(CC_G); - MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x2)); // _x86Reg == 0 - FixupBranch continue1 = J(); - - SetJumpTarget(pGreater); - MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x4)); // _x86Reg > 0 - FixupBranch continue2 = J(); + if( arg.IsImm() ) + { + s32 value = (s32)arg.offset; + if( value < 0 ) + MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x8)); + else if( value > 0 ) + MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x4)); + else + MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x2)); + } + else + { + CMP(32, arg, Imm8(0)); + FixupBranch pLesser = J_CC(CC_L); + FixupBranch pGreater = J_CC(CC_G); + MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x2)); // _x86Reg == 0 + FixupBranch continue1 = J(); + + SetJumpTarget(pGreater); + MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x4)); // _x86Reg > 0 + FixupBranch continue2 = J(); - SetJumpTarget(pLesser); - MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x8)); // _x86Reg < 0 + SetJumpTarget(pLesser); + MOV(8, M(&PowerPC::ppcState.cr_fast[0]), Imm8(0x8)); // _x86Reg < 0 - SetJumpTarget(continue1); - SetJumpTarget(continue2); + SetJumpTarget(continue1); + SetJumpTarget(continue2); + } } u32 Add(u32 a, u32 b) {return a + b;} @@ -63,24 +76,20 @@ gpr.Lock(d, a); if (a || binary || carry) // yeh nasty special case addic { - if (a == d) + if (gpr.R(a).IsImm() && !carry) { - if (gpr.R(d).IsImm() && !carry) - { - gpr.SetImmediate32(d, doop((u32)gpr.R(d).offset, value)); - } - else - { - if (gpr.R(d).IsImm()) - gpr.LoadToX64(d, false); - (this->*op)(32, gpr.R(d), Imm32(value)); //m_GPR[d] = m_GPR[_inst.RA] + _inst.SIMM_16; - if (carry) - GenerateCarry(); - } + gpr.SetImmediate32(d, doop((u32)gpr.R(a).offset, value)); + } + else if (a == d) + { + gpr.KillImmediate(d, true, true); + (this->*op)(32, gpr.R(d), Imm32(value)); //m_GPR[d] = m_GPR[_inst.RA] + _inst.SIMM_16; + if (carry) + GenerateCarry(); } else { - gpr.LoadToX64(d, false); + gpr.BindToRegister(d, false); MOV(32, gpr.R(d), gpr.R(a)); (this->*op)(32, gpr.R(d), Imm32(value)); //m_GPR[d] = m_GPR[_inst.RA] + _inst.SIMM_16; if (carry) @@ -94,7 +103,7 @@ #ifdef __APPLE__ // XXX soren // FIXME: Seems to be required on OS X (see r5799) - gpr.StoreFromX64(d); + gpr.StoreFromRegister(d); #endif } else @@ -103,7 +112,6 @@ } if (Rc) { - // Todo - special case immediates. ComputeRC(gpr.R(d)); } gpr.UnlockAll(); @@ -122,7 +130,7 @@ gpr.SetImmediate32(d, (u32)gpr.R(a).offset + (u32)(s32)(s16)inst.SIMM_16); } else if (inst.SIMM_16 == 0 && d != a && a != 0) { gpr.Lock(a, d); - gpr.LoadToX64(d, false, true); + gpr.BindToRegister(d, false, true); MOV(32, gpr.R(d), gpr.R(a)); gpr.UnlockAll(); } else { @@ -137,8 +145,9 @@ gpr.SetImmediate32(d, ((u32)inst.SIMM_16 << 16) + (u32)(s32)js.next_inst.SIMM_16); #ifdef __APPLE__ // FIXME: Seems to be required on OS X (see r5799) - gpr.StoreFromX64(d); + gpr.StoreFromRegister(d); #endif + js.downcountAmount++; js.skipnext = true; break; } @@ -146,8 +155,9 @@ gpr.SetImmediate32(d, ((u32)inst.SIMM_16 << 16) | (u32)js.next_inst.UIMM); #ifdef __APPLE__ // FIXME: Seems to be required on OS X (see r5799) - gpr.StoreFromX64(d); + gpr.StoreFromRegister(d); #endif + js.downcountAmount++; js.skipnext = true; break; } @@ -170,8 +180,8 @@ case 29: regimmop(a, s, true, inst.UIMM << 16, And, &XEmitter::AND, true); break; case 26: regimmop(a, s, true, inst.UIMM, Xor, &XEmitter::XOR, false); break; //xori case 27: regimmop(a, s, true, inst.UIMM << 16, Xor, &XEmitter::XOR, false); break; //xoris - case 12: //regimmop(d, a, false, (u32)(s32)inst.SIMM_16, Add, XEmitter::ADD, false, true); //addic - case 13: //regimmop(d, a, true, (u32)(s32)inst.SIMM_16, Add, XEmitter::ADD, true, true); //addic_rc + case 12: regimmop(d, a, false, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, false, true); break; //addic + case 13: regimmop(d, a, true, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, true, true); break; //addic_rc default: Default(inst); break; @@ -190,8 +200,11 @@ bool merge_branch = false; int test_crf = js.next_inst.BI >> 2; // Check if the next instruction is a branch - if it is, merge the two. - if (js.next_inst.OPCD == 16 && (js.next_inst.BO & BO_DONT_DECREMENT_FLAG) && - !(js.next_inst.BO & 16) && (js.next_inst.BO & 4) && !js.next_inst.LK) { + if (((js.next_inst.OPCD == 16 /* bcx */) || + ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528) /* bcctrx */) || + ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 16) /* bclrx */)) && + (js.next_inst.BO & BO_DONT_DECREMENT_FLAG) && + !(js.next_inst.BO & BO_DONT_CHECK_CONDITION)) { // Looks like a decent conditional branch that we can merge with. // It only test CR, not CTR. if (test_crf == crf) { @@ -199,164 +212,432 @@ } } - Gen::CCFlags less_than, greater_than; OpArg comparand; + bool signedCompare; if (inst.OPCD == 31) { + // cmp / cmpl gpr.Lock(a, b); - gpr.LoadToX64(a, true, false); comparand = gpr.R(b); - if (inst.SUBOP10 == 32) { - //cmpl - less_than = CC_B; - greater_than = CC_A; - } else { - //cmp - less_than = CC_L; - greater_than = CC_G; - } + signedCompare = (inst.SUBOP10 == 0); } else { - gpr.KillImmediate(a); // todo, optimize instead, but unlikely to make a difference + gpr.Lock(a); if (inst.OPCD == 10) { //cmpli - less_than = CC_B; - greater_than = CC_A; - comparand = Imm32(inst.UIMM); + comparand = Imm32((u32)inst.UIMM); + signedCompare = false; } else if (inst.OPCD == 11) { //cmpi - less_than = CC_L; - greater_than = CC_G; - comparand = Imm32((s32)(s16)inst.UIMM); + comparand = Imm32((u32)(s32)(s16)inst.UIMM); + signedCompare = true; } else { + signedCompare = false; // silence compiler warning PanicAlert("cmpXX"); - less_than = CC_O; - greater_than = CC_O; - comparand = Imm32(0); } } - if (!merge_branch) { - // Keep the normal code separate for clarity. - CMP(32, gpr.R(a), comparand); - - FixupBranch pLesser = J_CC(less_than); - FixupBranch pGreater = J_CC(greater_than); - MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x2)); // _x86Reg == 0 - FixupBranch continue1 = J(); - SetJumpTarget(pGreater); - MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x4)); // _x86Reg > 0 - FixupBranch continue2 = J(); - SetJumpTarget(pLesser); - MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x8)); // _x86Reg < 0 - SetJumpTarget(continue1); - SetJumpTarget(continue2); - // TODO: If we ever care about SO, borrow a trick from - // http://maws.mameworld.info/maws/mamesrc/src/emu/cpu/powerpc/drc_ops.c : bt, adc - } else { - int test_bit = 8 >> (js.next_inst.BI & 3); - bool condition = (js.next_inst.BO & 8) ? false : true; - CMP(32, gpr.R(a), comparand); + if (gpr.R(a).IsImm() && comparand.IsImm()) + { + // Both registers contain immediate values, so we can pre-compile the compare result + u8 compareResult; + if (signedCompare) + { + if ((s32)gpr.R(a).offset == (s32)comparand.offset) + compareResult = 0x2; + else if ((s32)gpr.R(a).offset > (s32)comparand.offset) + compareResult = 0x4; + else + compareResult = 0x8; + } + else + { + if ((u32)gpr.R(a).offset == (u32)comparand.offset) + compareResult = 0x2; + else if ((u32)gpr.R(a).offset > (u32)comparand.offset) + compareResult = 0x4; + else + compareResult = 0x8; + } + MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(compareResult)); gpr.UnlockAll(); - u32 destination1; - if (js.next_inst.AA) - destination1 = SignExt16(js.next_inst.BD << 2); - else - destination1 = js.next_compilerPC + SignExt16(js.next_inst.BD << 2); - u32 destination2 = js.next_compilerPC + 4; + if (merge_branch) + { + js.downcountAmount++; - // Test swapping (in the future, will be used to inline across branches the right way) - // if (rand() & 1) - // std::swap(destination1, destination2), condition = !condition; - - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); - FixupBranch pLesser = J_CC(less_than); - FixupBranch pGreater = J_CC(greater_than); - MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x2)); // == 0 - FixupBranch continue1 = J(); + gpr.Flush(FLUSH_ALL); + fpr.Flush(FLUSH_ALL); - SetJumpTarget(pGreater); - MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x4)); // > 0 - FixupBranch continue2 = J(); + int test_bit = 8 >> (js.next_inst.BI & 3); + u8 conditionResult = (js.next_inst.BO & BO_BRANCH_IF_TRUE) ? test_bit : 0; + if ((compareResult & test_bit) == conditionResult) + { + if (js.next_inst.OPCD == 16) // bcx + { + if (js.next_inst.LK) + MOV(32, M(&LR), Imm32(js.compilerPC + 4)); + + u32 destination; + if (js.next_inst.AA) + destination = SignExt16(js.next_inst.BD << 2); + else + destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2); + WriteExit(destination, 0); + } + else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx + { + if (js.next_inst.LK) + MOV(32, M(&LR), Imm32(js.compilerPC + 4)); + MOV(32, R(EAX), M(&CTR)); + AND(32, R(EAX), Imm32(0xFFFFFFFC)); + WriteExitDestInEAX(0); + } + else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 16)) // bclrx + { + MOV(32, R(EAX), M(&LR)); + if (js.next_inst.LK) + MOV(32, M(&LR), Imm32(js.compilerPC + 4)); + WriteExitDestInEAX(0); + } + else + { + PanicAlert("WTF invalid branch"); + } + } + else + { + WriteExit(js.next_compilerPC + 4, 0); + } - SetJumpTarget(pLesser); - MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x8)); // < 0 - FixupBranch continue3; - if (!!(8 & test_bit) == condition) continue3 = J(); - if (!!(4 & test_bit) != condition) SetJumpTarget(continue2); - if (!!(2 & test_bit) != condition) SetJumpTarget(continue1); + js.cancel = true; + } + } + else + { + Gen::CCFlags less_than, greater_than; + if (signedCompare) + { + less_than = CC_L; + greater_than = CC_G; + } + else + { + less_than = CC_B; + greater_than = CC_A; + } + + if (gpr.R(a).IsImm() || (!gpr.R(a).IsSimpleReg() && !comparand.IsImm() && !comparand.IsSimpleReg())) + { + // Syntax for CMP is invalid with such arguments. We must load RA in a register. + gpr.BindToRegister(a, true, false); + } + CMP(32, gpr.R(a), comparand); + gpr.UnlockAll(); + + if (!merge_branch) + { + // Keep the normal code separate for clarity. + + FixupBranch pLesser = J_CC(less_than); + FixupBranch pGreater = J_CC(greater_than); + MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x2)); // _x86Reg == 0 + FixupBranch continue1 = J(); + SetJumpTarget(pGreater); + MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x4)); // _x86Reg > 0 + FixupBranch continue2 = J(); + SetJumpTarget(pLesser); + MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x8)); // _x86Reg < 0 + SetJumpTarget(continue1); + SetJumpTarget(continue2); + // TODO: If we ever care about SO, borrow a trick from + // http://maws.mameworld.info/maws/mamesrc/src/emu/cpu/powerpc/drc_ops.c : bt, adc + } else { + js.downcountAmount++; + int test_bit = 8 >> (js.next_inst.BI & 3); + bool condition = (js.next_inst.BO & BO_BRANCH_IF_TRUE) ? false : true; + + // Test swapping (in the future, will be used to inline across branches the right way) + // if (rand() & 1) + // std::swap(destination1, destination2), condition = !condition; + + gpr.Flush(FLUSH_ALL); + fpr.Flush(FLUSH_ALL); + FixupBranch pLesser = J_CC(less_than); + FixupBranch pGreater = J_CC(greater_than); + MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x2)); // == 0 + FixupBranch continue1 = J(); + + SetJumpTarget(pGreater); + MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x4)); // > 0 + FixupBranch continue2 = J(); + + SetJumpTarget(pLesser); + MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x8)); // < 0 + FixupBranch continue3; + if (!!(8 & test_bit) == condition) continue3 = J(); + if (!!(4 & test_bit) != condition) SetJumpTarget(continue2); + if (!!(2 & test_bit) != condition) SetJumpTarget(continue1); + if (js.next_inst.OPCD == 16) // bcx + { + if (js.next_inst.LK) + MOV(32, M(&LR), Imm32(js.compilerPC + 4)); - WriteExit(destination1, 0); + u32 destination; + if (js.next_inst.AA) + destination = SignExt16(js.next_inst.BD << 2); + else + destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2); + WriteExit(destination, 0); + } + else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx + { + if (js.next_inst.LK) + MOV(32, M(&LR), Imm32(js.compilerPC + 4)); + MOV(32, R(EAX), M(&CTR)); + AND(32, R(EAX), Imm32(0xFFFFFFFC)); + WriteExitDestInEAX(0); + } + else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 16)) // bclrx + { + MOV(32, R(EAX), M(&LR)); + AND(32, R(EAX), Imm32(0xFFFFFFFC)); + if (js.next_inst.LK) + MOV(32, M(&LR), Imm32(js.compilerPC + 4)); + WriteExitDestInEAX(0); + } + else + { + PanicAlert("WTF invalid branch"); + } - if (!!(8 & test_bit) == condition) SetJumpTarget(continue3); - if (!!(4 & test_bit) == condition) SetJumpTarget(continue2); - if (!!(2 & test_bit) == condition) SetJumpTarget(continue1); + if (!!(8 & test_bit) == condition) SetJumpTarget(continue3); + if (!!(4 & test_bit) == condition) SetJumpTarget(continue2); + if (!!(2 & test_bit) == condition) SetJumpTarget(continue1); - WriteExit(destination2, 1); + WriteExit(js.next_compilerPC + 4, 1); - js.cancel = true; + js.cancel = true; + } } gpr.UnlockAll(); } -void Jit64::orx(UGeckoInstruction inst) +void Jit64::boolX(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(Integer) - int a = inst.RA; - int s = inst.RS; - int b = inst.RB; - - if (s == b && s != a) + int a = inst.RA, s = inst.RS, b = inst.RB; + _dbg_assert_msg_(DYNA_REC, inst.OPCD == 31, "Invalid boolX"); + + if (gpr.R(s).IsImm() && gpr.R(b).IsImm()) + { + if (inst.SUBOP10 == 28) /* andx */ + gpr.SetImmediate32(a, (u32)gpr.R(s).offset & (u32)gpr.R(b).offset); + else if (inst.SUBOP10 == 476) /* nandx */ + gpr.SetImmediate32(a, ~((u32)gpr.R(s).offset & (u32)gpr.R(b).offset)); + else if (inst.SUBOP10 == 60) /* andcx */ + gpr.SetImmediate32(a, (u32)gpr.R(s).offset & (~(u32)gpr.R(b).offset)); + else if (inst.SUBOP10 == 444) /* orx */ + gpr.SetImmediate32(a, (u32)gpr.R(s).offset | (u32)gpr.R(b).offset); + else if (inst.SUBOP10 == 124) /* norx */ + gpr.SetImmediate32(a, ~((u32)gpr.R(s).offset | (u32)gpr.R(b).offset)); + else if (inst.SUBOP10 == 412) /* orcx */ + gpr.SetImmediate32(a, (u32)gpr.R(s).offset | (~(u32)gpr.R(b).offset)); + else if (inst.SUBOP10 == 316) /* xorx */ + gpr.SetImmediate32(a, (u32)gpr.R(s).offset ^ (u32)gpr.R(b).offset); + else if (inst.SUBOP10 == 284) /* eqvx */ + gpr.SetImmediate32(a, ~((u32)gpr.R(s).offset ^ (u32)gpr.R(b).offset)); + } + else if (s == b) { - gpr.Lock(a,s); - gpr.LoadToX64(a, false); - MOV(32, gpr.R(a), gpr.R(s)); + if ((inst.SUBOP10 == 28 /* andx */) || (inst.SUBOP10 == 444 /* orx */)) + { + if (a != s) + { + gpr.Lock(a,s); + gpr.BindToRegister(a, false, true); + MOV(32, gpr.R(a), gpr.R(s)); + gpr.UnlockAll(); + } + } + else if ((inst.SUBOP10 == 476 /* nandx */) || (inst.SUBOP10 == 124 /* norx */)) + { + if (a != s) + { + gpr.Lock(a,s); + gpr.BindToRegister(a, false, true); + MOV(32, gpr.R(a), gpr.R(s)); + } + else + { + gpr.KillImmediate(a, true, true); + } + NOT(32, gpr.R(a)); + gpr.UnlockAll(); + } + else if ((inst.SUBOP10 == 412 /* orcx */) || (inst.SUBOP10 == 284 /* eqvx */)) + { + gpr.SetImmediate32(a, 0xFFFFFFFF); + } + else if ((inst.SUBOP10 == 60 /* andcx */) || (inst.SUBOP10 == 316 /* xorx */)) + { + gpr.SetImmediate32(a, 0); + } + else + { + PanicAlert("WTF!"); + } + } + else if ((a == s) || (a == b)) + { + gpr.Lock(a,((a == s) ? b : s)); + OpArg operand = ((a == s) ? gpr.R(b) : gpr.R(s)); + gpr.BindToRegister(a, true, true); + + if (inst.SUBOP10 == 28) /* andx */ + { + AND(32, gpr.R(a), operand); + } + else if (inst.SUBOP10 == 476) /* nandx */ + { + AND(32, gpr.R(a), operand); + NOT(32, gpr.R(a)); + } + else if (inst.SUBOP10 == 60) /* andcx */ + { + if (a == b) + { + NOT(32, gpr.R(a)); + AND(32, gpr.R(a), operand); + } + else + { + MOV(32, R(EAX), operand); + NOT(32, R(EAX)); + AND(32, gpr.R(a), R(EAX)); + } + } + else if (inst.SUBOP10 == 444) /* orx */ + { + OR(32, gpr.R(a), operand); + } + else if (inst.SUBOP10 == 124) /* norx */ + { + OR(32, gpr.R(a), operand); + NOT(32, gpr.R(a)); + } + else if (inst.SUBOP10 == 412) /* orcx */ + { + if (a == b) + { + NOT(32, gpr.R(a)); + OR(32, gpr.R(a), operand); + } + else + { + MOV(32, R(EAX), operand); + NOT(32, R(EAX)); + OR(32, gpr.R(a), R(EAX)); + } + } + else if (inst.SUBOP10 == 316) /* xorx */ + { + XOR(32, gpr.R(a), operand); + } + else if (inst.SUBOP10 == 284) /* eqvx */ + { + XOR(32, gpr.R(a), operand); + NOT(32, gpr.R(a)); + } + else + { + PanicAlert("WTF"); + } gpr.UnlockAll(); } else { - gpr.Lock(a, s, b); - gpr.LoadToX64(a, (a == s || a == b), true); - if (a == s) + gpr.Lock(a,s,b); + gpr.BindToRegister(a, false, true); + + if (inst.SUBOP10 == 28) /* andx */ + { + MOV(32, gpr.R(a), gpr.R(s)); + AND(32, gpr.R(a), gpr.R(b)); + } + else if (inst.SUBOP10 == 476) /* nandx */ + { + MOV(32, gpr.R(a), gpr.R(s)); + AND(32, gpr.R(a), gpr.R(b)); + NOT(32, gpr.R(a)); + } + else if (inst.SUBOP10 == 60) /* andcx */ + { + MOV(32, gpr.R(a), gpr.R(b)); + NOT(32, gpr.R(a)); + AND(32, gpr.R(a), gpr.R(s)); + } + else if (inst.SUBOP10 == 444) /* orx */ + { + MOV(32, gpr.R(a), gpr.R(s)); OR(32, gpr.R(a), gpr.R(b)); - else if (a == b) - OR(32, gpr.R(a), gpr.R(s)); - else { + } + else if (inst.SUBOP10 == 124) /* norx */ + { + MOV(32, gpr.R(a), gpr.R(s)); + OR(32, gpr.R(a), gpr.R(b)); + NOT(32, gpr.R(a)); + } + else if (inst.SUBOP10 == 412) /* orcx */ + { MOV(32, gpr.R(a), gpr.R(b)); + NOT(32, gpr.R(a)); OR(32, gpr.R(a), gpr.R(s)); } + else if (inst.SUBOP10 == 316) /* xorx */ + { + MOV(32, gpr.R(a), gpr.R(s)); + XOR(32, gpr.R(a), gpr.R(b)); + } + else if (inst.SUBOP10 == 284) /* eqvx */ + { + MOV(32, gpr.R(a), gpr.R(s)); + XOR(32, gpr.R(a), gpr.R(b)); + NOT(32, gpr.R(a)); + } + else + { + PanicAlert("WTF!"); + } gpr.UnlockAll(); } - + if (inst.Rc) { ComputeRC(gpr.R(a)); } } - -// m_GPR[_inst.RA] = m_GPR[_inst.RS] ^ m_GPR[_inst.RB]; -void Jit64::xorx(UGeckoInstruction inst) +void Jit64::extsbx(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(Integer) - int a = inst.RA; - int s = inst.RS; - int b = inst.RB; + int a = inst.RA, s = inst.RS; - if (s == b) { - gpr.SetImmediate32(a, 0); + if (gpr.R(s).IsImm()) + { + gpr.SetImmediate32(a, (u32)(s32)(s8)gpr.R(s).offset); } else { - gpr.LoadToX64(a, a == s || a == b, true); - gpr.Lock(a, s, b); + gpr.Lock(a, s); + gpr.BindToRegister(a, a == s, true); + // Always force moving to EAX because it isn't possible + // to refer to the lowest byte of some registers, at least in + // 32-bit mode. MOV(32, R(EAX), gpr.R(s)); - XOR(32, R(EAX), gpr.R(b)); - MOV(32, gpr.R(a), R(EAX)); + MOVSX(32, 8, gpr.RX(a), R(AL)); // watch out for ah and friends gpr.UnlockAll(); } @@ -366,57 +647,30 @@ } } -void Jit64::andx(UGeckoInstruction inst) +void Jit64::extshx(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(Integer) - int a = inst.RA, s = inst.RS, b = inst.RB; - if (a != s && a != b) { - gpr.LoadToX64(a, false, true); - } else { - gpr.LoadToX64(a, true, true); - } - gpr.Lock(a, s, b); - MOV(32, R(EAX), gpr.R(s)); - AND(32, R(EAX), gpr.R(b)); - MOV(32, gpr.R(a), R(EAX)); - gpr.UnlockAll(); + int a = inst.RA, s = inst.RS; - if (inst.Rc) { - // result is already in eax - ComputeRC(R(EAX)); + if (gpr.R(s).IsImm()) + { + gpr.SetImmediate32(a, (u32)(s32)(s16)gpr.R(s).offset); } -} - -void Jit64::extsbx(UGeckoInstruction inst) -{ - INSTRUCTION_START - JITDISABLE(Integer) - int a = inst.RA, - s = inst.RS; - gpr.LoadToX64(a, a == s, true); - // Always force moving to EAX because it isn't possible - // to refer to the lowest byte of some registers, at least in - // 32-bit mode. - MOV(32, R(EAX), gpr.R(s)); - MOVSX(32, 8, gpr.RX(a), R(AL)); // watch out for ah and friends - if (inst.Rc) { - ComputeRC(gpr.R(a)); + else + { + gpr.Lock(a, s); + gpr.KillImmediate(s, true, false); + gpr.BindToRegister(a, a == s, true); + // This looks a little dangerous, but it's safe because + // every 32-bit register has a 16-bit half at the same index + // as the 32-bit register. + MOVSX(32, 16, gpr.RX(a), gpr.R(s)); + gpr.UnlockAll(); } -} -void Jit64::extshx(UGeckoInstruction inst) -{ - INSTRUCTION_START - JITDISABLE(Integer) - int a = inst.RA, s = inst.RS; - gpr.KillImmediate(s); - gpr.LoadToX64(a, a == s, true); - // This looks a little dangerous, but it's safe because - // every 32-bit register has a 16-bit half at the same index - // as the 32-bit register. - MOVSX(32, 16, gpr.RX(a), gpr.R(s)); - if (inst.Rc) { + if (inst.Rc) + { ComputeRC(gpr.R(a)); } } @@ -427,7 +681,7 @@ JITDISABLE(Integer) int a = inst.RA, d = inst.RD; gpr.Lock(a, d); - gpr.LoadToX64(d, a == d, true); + gpr.BindToRegister(d, a == d, true); int imm = inst.SIMM_16; MOV(32, R(EAX), gpr.R(a)); NOT(32, R(EAX)); @@ -444,10 +698,7 @@ JITDISABLE(Integer) int a = inst.RA, b = inst.RB, d = inst.RD; gpr.Lock(a, b, d); - if(d != a && d != b) - gpr.LoadToX64(d, false, true); - else - gpr.LoadToX64(d, true, true); + gpr.BindToRegister(d, (d == a || d == b), true); // For some reason, I could not get the jit versions of sub* // working with x86 sub...so we use the ~a + b + 1 method @@ -478,10 +729,7 @@ int a = inst.RA, b = inst.RB, d = inst.RD; gpr.FlushLockX(ECX); gpr.Lock(a, b, d); - if(d != a && d != b) - gpr.LoadToX64(d, false, true); - else - gpr.LoadToX64(d, true, true); + gpr.BindToRegister(d, (d == a || d == b), true); // Get CA MOV(32, R(ECX), M(&PowerPC::ppcState.spr[SPR_XER])); @@ -514,25 +762,104 @@ } } +void Jit64::subfmex(UGeckoInstruction inst) +{ + // USES_XER + INSTRUCTION_START + JITDISABLE(Integer) + int a = inst.RA, d = inst.RD; + + if (d == a) + { + gpr.Lock(d); + gpr.BindToRegister(d, true); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + NOT(32, gpr.R(d)); + ADC(32, gpr.R(d), Imm32(0xFFFFFFFF)); + GenerateCarry(); + gpr.UnlockAll(); + } + else + { + gpr.Lock(a, d); + gpr.BindToRegister(d, false); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + MOV(32, gpr.R(d), gpr.R(a)); + NOT(32, gpr.R(d)); + ADC(32, gpr.R(d), Imm32(0xFFFFFFFF)); + GenerateCarry(); + gpr.UnlockAll(); + } + + if (inst.Rc) + { + ComputeRC(gpr.R(d)); + } +} + +void Jit64::subfzex(UGeckoInstruction inst) +{ + // USES_XER + INSTRUCTION_START + JITDISABLE(Integer) + int a = inst.RA, d = inst.RD; + + if (d == a) + { + gpr.Lock(d); + gpr.BindToRegister(d, true); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + NOT(32, gpr.R(d)); + ADC(32, gpr.R(d), Imm8(0)); + GenerateCarry(); + gpr.UnlockAll(); + } + else + { + gpr.Lock(a, d); + gpr.BindToRegister(d, false); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + MOV(32, gpr.R(d), gpr.R(a)); + NOT(32, gpr.R(d)); + ADC(32, gpr.R(d), Imm8(0)); + GenerateCarry(); + gpr.UnlockAll(); + } + + if (inst.Rc) + { + ComputeRC(gpr.R(d)); + } +} + void Jit64::subfx(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(Integer) int a = inst.RA, b = inst.RB, d = inst.RD; - gpr.Lock(a, b, d); - if (d != a && d != b) { - gpr.LoadToX64(d, false, true); - } else { - gpr.LoadToX64(d, true, true); + + if (gpr.R(a).IsImm() && gpr.R(b).IsImm()) + { + gpr.SetImmediate32(d, (u32)gpr.R(b).offset - (u32)gpr.R(a).offset); } - MOV(32, R(EAX), gpr.R(b)); - SUB(32, R(EAX), gpr.R(a)); - MOV(32, gpr.R(d), R(EAX)); - gpr.UnlockAll(); + else + { + gpr.Lock(a, b, d); + gpr.BindToRegister(d, (d == a || d == b), true); + MOV(32, R(EAX), gpr.R(b)); + SUB(32, R(EAX), gpr.R(a)); + MOV(32, gpr.R(d), R(EAX)); + gpr.UnlockAll(); + } + if (inst.OE) PanicAlert("OE: subfx"); - if (inst.Rc) { - // result is already in eax - ComputeRC(R(EAX)); + if (inst.Rc) + { + ComputeRC(gpr.R(d)); } } @@ -541,11 +868,19 @@ INSTRUCTION_START JITDISABLE(Integer) int a = inst.RA, d = inst.RD; - gpr.Lock(a, d); - gpr.LoadToX64(d, (d == a), true); - gpr.KillImmediate(a); - IMUL(32, gpr.RX(d), gpr.R(a), Imm32((u32)(s32)inst.SIMM_16)); - gpr.UnlockAll(); + + if (gpr.R(a).IsImm()) + { + gpr.SetImmediate32(d, (s32)gpr.R(a).offset * (s32)inst.SIMM_16); + } + else + { + gpr.Lock(a, d); + gpr.BindToRegister(d, (d == a), true); + gpr.KillImmediate(a, true, false); + IMUL(32, gpr.RX(d), gpr.R(a), Imm32((u32)(s32)inst.SIMM_16)); + gpr.UnlockAll(); + } } void Jit64::mullwx(UGeckoInstruction inst) @@ -553,18 +888,28 @@ INSTRUCTION_START JITDISABLE(Integer) int a = inst.RA, b = inst.RB, d = inst.RD; - gpr.Lock(a, b, d); - gpr.LoadToX64(d, (d == a || d == b), true); - if (d == a) { - IMUL(32, gpr.RX(d), gpr.R(b)); - } else if (d == b) { - IMUL(32, gpr.RX(d), gpr.R(a)); - } else { - MOV(32, gpr.R(d), gpr.R(b)); - IMUL(32, gpr.RX(d), gpr.R(a)); + + if (gpr.R(a).IsImm() && gpr.R(b).IsImm()) + { + gpr.SetImmediate32(d, (s32)gpr.R(a).offset * (s32)gpr.R(b).offset); } - gpr.UnlockAll(); - if (inst.Rc) { + else + { + gpr.Lock(a, b, d); + gpr.BindToRegister(d, (d == a || d == b), true); + if (d == a) { + IMUL(32, gpr.RX(d), gpr.R(b)); + } else if (d == b) { + IMUL(32, gpr.RX(d), gpr.R(a)); + } else { + MOV(32, gpr.R(d), gpr.R(b)); + IMUL(32, gpr.RX(d), gpr.R(a)); + } + gpr.UnlockAll(); + } + + if (inst.Rc) + { ComputeRC(gpr.R(d)); } } @@ -574,23 +919,28 @@ INSTRUCTION_START JITDISABLE(Integer) int a = inst.RA, b = inst.RB, d = inst.RD; - gpr.FlushLockX(EDX); - gpr.Lock(a, b, d); - if (d != a && d != b) { - gpr.LoadToX64(d, false, true); - } else { - gpr.LoadToX64(d, true, true); + + if (gpr.R(a).IsImm() && gpr.R(b).IsImm()) + { + gpr.SetImmediate32(d, (u32)(((u64)gpr.R(a).offset * (u64)gpr.R(b).offset) >> 32)); } - if (gpr.RX(d) == EDX) - PanicAlert("mulhwux : WTF"); - MOV(32, R(EAX), gpr.R(a)); - gpr.KillImmediate(b); - MUL(32, gpr.R(b)); - gpr.UnlockAll(); - gpr.UnlockAllX(); - MOV(32, gpr.R(d), R(EDX)); + else + { + gpr.FlushLockX(EDX); + gpr.Lock(a, b, d); + gpr.BindToRegister(d, (d == a || d == b), true); + if (gpr.RX(d) == EDX) + PanicAlert("mulhwux : WTF"); + MOV(32, R(EAX), gpr.R(a)); + gpr.KillImmediate(b, true, false); + MUL(32, gpr.R(b)); + gpr.UnlockAll(); + gpr.UnlockAllX(); + MOV(32, gpr.R(d), R(EDX)); + } + if (inst.Rc) - ComputeRC(R(EDX)); + ComputeRC(gpr.R(d)); } void Jit64::divwux(UGeckoInstruction inst) @@ -598,130 +948,218 @@ INSTRUCTION_START JITDISABLE(Integer) int a = inst.RA, b = inst.RB, d = inst.RD; - gpr.FlushLockX(EDX); - gpr.Lock(a, b, d); - if (d != a && d != b) { - gpr.LoadToX64(d, false, true); - } else { - gpr.LoadToX64(d, true, true); + + if (gpr.R(a).IsImm() && gpr.R(b).IsImm()) + { + if( gpr.R(b).offset == 0 ) + gpr.SetImmediate32(d, 0); + else + gpr.SetImmediate32(d, (u32)gpr.R(a).offset / (u32)gpr.R(b).offset); } - MOV(32, R(EAX), gpr.R(a)); - XOR(32, R(EDX), R(EDX)); - gpr.KillImmediate(b); - CMP(32, gpr.R(b), Imm32(0)); - // doesn't handle if OE is set, but int doesn't either... - FixupBranch not_div_by_zero = J_CC(CC_NZ); - MOV(32, gpr.R(d), R(EDX)); - MOV(32, R(EAX), gpr.R(d)); - FixupBranch end = J(); - SetJumpTarget(not_div_by_zero); - DIV(32, gpr.R(b)); - MOV(32, gpr.R(d), R(EAX)); - SetJumpTarget(end); - gpr.UnlockAll(); - gpr.UnlockAllX(); - if (inst.Rc) { - ComputeRC(R(EAX)); + else + { + gpr.FlushLockX(EDX); + gpr.Lock(a, b, d); + gpr.BindToRegister(d, (d == a || d == b), true); + MOV(32, R(EAX), gpr.R(a)); + XOR(32, R(EDX), R(EDX)); + gpr.KillImmediate(b, true, false); + CMP(32, gpr.R(b), Imm32(0)); + // doesn't handle if OE is set, but int doesn't either... + FixupBranch not_div_by_zero = J_CC(CC_NZ); + MOV(32, gpr.R(d), R(EDX)); + MOV(32, R(EAX), gpr.R(d)); + FixupBranch end = J(); + SetJumpTarget(not_div_by_zero); + DIV(32, gpr.R(b)); + MOV(32, gpr.R(d), R(EAX)); + SetJumpTarget(end); + gpr.UnlockAll(); + gpr.UnlockAllX(); + } + + if (inst.Rc) + { + ComputeRC(gpr.R(d)); } } void Jit64::addx(UGeckoInstruction inst) { - INSTRUCTION_START - JITDISABLE(Integer) - int a = inst.RA, b = inst.RB, d = inst.RD; - _assert_msg_(DYNA_REC, !inst.OE, "Add - OE enabled :("); - - if (a != d && b != d && a != b) + INSTRUCTION_START + JITDISABLE(Integer) + int a = inst.RA, b = inst.RB, d = inst.RD; + _assert_msg_(DYNA_REC, !inst.OE, "Add - OE enabled :("); + + if (gpr.R(a).IsImm() && gpr.R(b).IsImm()) + { + gpr.SetImmediate32(d, (u32)gpr.R(a).offset + (u32)gpr.R(b).offset); + } + else if (gpr.R(a).IsSimpleReg() && gpr.R(b).IsSimpleReg()) { gpr.Lock(a, b, d); - gpr.LoadToX64(d, false); - if (gpr.R(a).IsSimpleReg() && gpr.R(b).IsSimpleReg()) { - LEA(32, gpr.RX(d), MComplex(gpr.RX(a), gpr.RX(b), 1, 0)); - } else { - MOV(32, gpr.R(d), gpr.R(a)); - ADD(32, gpr.R(d), gpr.R(b)); - } - if (inst.Rc) - { - ComputeRC(gpr.R(d)); - } + gpr.BindToRegister(d, false); + LEA(32, gpr.RX(d), MComplex(gpr.RX(a), gpr.RX(b), 1, 0)); + gpr.UnlockAll(); + } + else if ((d == a) || (d == b)) + { + int operand = ((d == a) ? b : a); + gpr.Lock(a, b, d); + gpr.BindToRegister(d, true); + ADD(32, gpr.R(d), gpr.R(operand)); gpr.UnlockAll(); } - else if (d == a && d != b) + else { - gpr.Lock(b, d); - gpr.LoadToX64(d, true); + gpr.Lock(a, b, d); + gpr.BindToRegister(d, false); + MOV(32, gpr.R(d), gpr.R(a)); ADD(32, gpr.R(d), gpr.R(b)); - if (inst.Rc) - { - ComputeRC(gpr.R(d)); - } gpr.UnlockAll(); } - else if (d == b && d != a) + + if (inst.Rc) { - gpr.Lock(a, d); - gpr.LoadToX64(d, true); - ADD(32, gpr.R(d), gpr.R(a)); - if (inst.Rc) - { ComputeRC(gpr.R(d)); - } + } +} + +void Jit64::addex(UGeckoInstruction inst) +{ + // USES_XER + INSTRUCTION_START + JITDISABLE(Integer) + int a = inst.RA, b = inst.RB, d = inst.RD; + + if ((d == a) || (d == b)) + { + gpr.Lock(a, b, d); + gpr.BindToRegister(d, true); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + ADC(32, gpr.R(d), gpr.R((d == a) ? b : a)); + GenerateCarry(); gpr.UnlockAll(); } - else if( a == b && b == d && a == d) + else { - gpr.Lock(d); - gpr.LoadToX64(d, true); - ADD(32, gpr.R(d), gpr.R(d)); - if (inst.Rc) - { - ComputeRC(gpr.R(d)); - } + gpr.Lock(a, b, d); + gpr.BindToRegister(d, false); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + MOV(32, gpr.R(d), gpr.R(a)); + ADC(32, gpr.R(d), gpr.R(b)); + GenerateCarry(); gpr.UnlockAll(); } - else if( a == b && b != d) + + if (inst.Rc) + { + ComputeRC(gpr.R(d)); + } +} + +void Jit64::addcx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(Integer) + int a = inst.RA, b = inst.RB, d = inst.RD; + _assert_msg_(DYNA_REC, !inst.OE, "Add - OE enabled :("); + + if ((d == a) || (d == b)) { - gpr.Lock(a, d); - gpr.LoadToX64(d, false); + int operand = ((d == a) ? b : a); + gpr.Lock(a, b, d); + gpr.BindToRegister(d, true); + ADD(32, gpr.R(d), gpr.R(operand)); + GenerateCarry(); + gpr.UnlockAll(); + } + else + { + gpr.Lock(a, b, d); + gpr.BindToRegister(d, false); MOV(32, gpr.R(d), gpr.R(a)); - ADD(32, gpr.R(d), gpr.R(d)); - if (inst.Rc) - { + ADD(32, gpr.R(d), gpr.R(b)); + GenerateCarry(); + gpr.UnlockAll(); + } + + if (inst.Rc) + { ComputeRC(gpr.R(d)); - } + } +} + +void Jit64::addmex(UGeckoInstruction inst) +{ + // USES_XER + INSTRUCTION_START + JITDISABLE(Integer) + int a = inst.RA, d = inst.RD; + + if (d == a) + { + gpr.Lock(d); + gpr.BindToRegister(d, true); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + ADC(32, gpr.R(d), Imm32(0xFFFFFFFF)); + GenerateCarry(); gpr.UnlockAll(); } else { - Default(inst); return; + gpr.Lock(a, d); + gpr.BindToRegister(d, false); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + MOV(32, gpr.R(d), gpr.R(a)); + ADC(32, gpr.R(d), Imm32(0xFFFFFFFF)); + GenerateCarry(); + gpr.UnlockAll(); } + + if (inst.Rc) + { + ComputeRC(gpr.R(d)); + } } -// This can be optimized -void Jit64::addex(UGeckoInstruction inst) -{ - // USES_XER - INSTRUCTION_START - JITDISABLE(Integer) - int a = inst.RA, b = inst.RB, d = inst.RD; - gpr.Lock(a, b, d); - if (d != a && d != b) - gpr.LoadToX64(d, false); +void Jit64::addzex(UGeckoInstruction inst) +{ + // USES_XER + INSTRUCTION_START + JITDISABLE(Integer) + int a = inst.RA, d = inst.RD; + + if (d == a) + { + gpr.Lock(d); + gpr.BindToRegister(d, true); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + ADC(32, gpr.R(d), Imm8(0)); + GenerateCarry(); + gpr.UnlockAll(); + } else - gpr.LoadToX64(d, true); - MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); - SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag - MOV(32, R(EAX), gpr.R(a)); - ADC(32, R(EAX), gpr.R(b)); - MOV(32, gpr.R(d), R(EAX)); - GenerateCarry(); - gpr.UnlockAll(); - if (inst.Rc) { - ComputeRC(R(EAX)); + gpr.Lock(a, d); + gpr.BindToRegister(d, false); + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(30)); // shift the carry flag out into the x86 carry flag + MOV(32, gpr.R(d), gpr.R(a)); + ADC(32, gpr.R(d), Imm8(0)); + GenerateCarry(); + gpr.UnlockAll(); } + + if (inst.Rc) + { + ComputeRC(gpr.R(d)); + } } void Jit64::rlwinmx(UGeckoInstruction inst) @@ -730,47 +1168,48 @@ JITDISABLE(Integer) int a = inst.RA; int s = inst.RS; - if (gpr.R(s).IsImm() && !inst.Rc) + if (gpr.R(s).IsImm()) { unsigned result = (int)gpr.R(s).offset; if (inst.SH != 0) result = _rotl(result, inst.SH); result &= Helper_Mask(inst.MB, inst.ME); gpr.SetImmediate32(a, result); - return; - } - - gpr.Lock(a, s); - gpr.LoadToX64(a, a == s); - if (a != s) - { - MOV(32, gpr.R(a), gpr.R(s)); - } - - if (inst.MB == 0 && inst.ME==31-inst.SH) - { - SHL(32, gpr.R(a), Imm8(inst.SH)); - } - else if (inst.ME == 31 && inst.MB == 32 - inst.SH) - { - SHR(32, gpr.R(a), Imm8(inst.MB)); } else { - bool written = false; - if (inst.SH != 0) + gpr.Lock(a, s); + gpr.BindToRegister(a, a == s); + if (a != s) { - ROL(32, gpr.R(a), Imm8(inst.SH)); - written = true; + MOV(32, gpr.R(a), gpr.R(s)); } - if (!(inst.MB==0 && inst.ME==31)) + + if (inst.MB == 0 && inst.ME==31-inst.SH) { - written = true; - AND(32, gpr.R(a), Imm32(Helper_Mask(inst.MB, inst.ME))); + SHL(32, gpr.R(a), Imm8(inst.SH)); } - _assert_msg_(DYNA_REC, written, "W T F!!!"); + else if (inst.ME == 31 && inst.MB == 32 - inst.SH) + { + SHR(32, gpr.R(a), Imm8(inst.MB)); + } + else + { + bool written = false; + if (inst.SH != 0) + { + ROL(32, gpr.R(a), Imm8(inst.SH)); + written = true; + } + if (!(inst.MB==0 && inst.ME==31)) + { + written = true; + AND(32, gpr.R(a), Imm32(Helper_Mask(inst.MB, inst.ME))); + } + _assert_msg_(DYNA_REC, written, "W T F!!!"); + } + gpr.UnlockAll(); } - gpr.UnlockAll(); if (inst.Rc) { @@ -785,26 +1224,26 @@ JITDISABLE(Integer) int a = inst.RA; int s = inst.RS; - if (gpr.R(a).IsImm() || gpr.R(s).IsImm()) + + if (gpr.R(a).IsImm() && gpr.R(s).IsImm()) { - Default(inst); - return; + u32 mask = Helper_Mask(inst.MB,inst.ME); + gpr.SetImmediate32(a, ((u32)gpr.R(a).offset & ~mask) | (_rotl((u32)gpr.R(s).offset,inst.SH) & mask)); } - - if (a != s) + else { gpr.Lock(a, s); - gpr.LoadToX64(a, true); + gpr.KillImmediate(a, true, true); + u32 mask = Helper_Mask(inst.MB, inst.ME); + MOV(32, R(EAX), gpr.R(s)); + AND(32, gpr.R(a), Imm32(~mask)); + if (inst.SH) + ROL(32, R(EAX), Imm8(inst.SH)); + AND(32, R(EAX), Imm32(mask)); + OR(32, gpr.R(a), R(EAX)); + gpr.UnlockAll(); } - u32 mask = Helper_Mask(inst.MB, inst.ME); - MOV(32, R(EAX), gpr.R(s)); - AND(32, gpr.R(a), Imm32(~mask)); - if (inst.SH) - ROL(32, R(EAX), Imm8(inst.SH)); - AND(32, R(EAX), Imm32(mask)); - OR(32, gpr.R(a), R(EAX)); - gpr.UnlockAll(); if (inst.Rc) { ComputeRC(gpr.R(a)); @@ -816,26 +1255,30 @@ INSTRUCTION_START JITDISABLE(Integer) int a = inst.RA, b = inst.RB, s = inst.RS; - if (gpr.R(a).IsImm()) + + u32 mask = Helper_Mask(inst.MB, inst.ME); + if (gpr.R(b).IsImm() && gpr.R(s).IsImm()) { - Default(inst); - return; + gpr.SetImmediate32(a, _rotl((u32)gpr.R(s).offset, (u32)gpr.R(b).offset & 0x1F) & mask); + } + else + { + gpr.FlushLockX(ECX); + gpr.Lock(a, b, s); + gpr.KillImmediate(a, (a == s || a == b), true); + MOV(32, R(EAX), gpr.R(s)); + MOV(32, R(ECX), gpr.R(b)); + AND(32, R(ECX), Imm32(0x1f)); + ROL(32, R(EAX), R(ECX)); + AND(32, R(EAX), Imm32(mask)); + MOV(32, gpr.R(a), R(EAX)); + gpr.UnlockAll(); + gpr.UnlockAllX(); } - u32 mask = Helper_Mask(inst.MB, inst.ME); - gpr.FlushLockX(ECX); - gpr.Lock(a, b, s); - MOV(32, R(EAX), gpr.R(s)); - MOV(32, R(ECX), gpr.R(b)); - AND(32, R(ECX), Imm32(0x1f)); - ROL(32, R(EAX), R(ECX)); - AND(32, R(EAX), Imm32(mask)); - MOV(32, gpr.R(a), R(EAX)); - gpr.UnlockAll(); - gpr.UnlockAllX(); if (inst.Rc) { - ComputeRC(R(EAX)); + ComputeRC(gpr.R(a)); } } @@ -845,12 +1288,21 @@ JITDISABLE(Integer) int a = inst.RA; int d = inst.RD; - gpr.Lock(a, d); - gpr.LoadToX64(d, a == d, true); - if (a != d) - MOV(32, gpr.R(d), gpr.R(a)); - NEG(32, gpr.R(d)); - gpr.UnlockAll(); + + if (gpr.R(a).IsImm()) + { + gpr.SetImmediate32(d, ~((u32)gpr.R(a).offset) + 1); + } + else + { + gpr.Lock(a, d); + gpr.BindToRegister(d, a == d, true); + if (a != d) + MOV(32, gpr.R(d), gpr.R(a)); + NEG(32, gpr.R(d)); + gpr.UnlockAll(); + } + if (inst.Rc) { ComputeRC(gpr.R(d)); @@ -864,22 +1316,32 @@ int a = inst.RA; int b = inst.RB; int s = inst.RS; - gpr.FlushLockX(ECX); - gpr.Lock(a, b, s); - gpr.LoadToX64(a, a == s || a == b || s == b, true); - MOV(32, R(ECX), gpr.R(b)); - XOR(32, R(EAX), R(EAX)); - TEST(32, R(ECX), Imm32(32)); - FixupBranch branch = J_CC(CC_NZ); - MOV(32, R(EAX), gpr.R(s)); - SHR(32, R(EAX), R(ECX)); - SetJumpTarget(branch); - MOV(32, gpr.R(a), R(EAX)); - gpr.UnlockAll(); - gpr.UnlockAllX(); + + if (gpr.R(b).IsImm() && gpr.R(s).IsImm()) + { + u32 amount = (u32)gpr.R(b).offset; + gpr.SetImmediate32(a, (amount & 0x20) ? 0 : ((u32)gpr.R(s).offset >> (amount & 0x1f))); + } + else + { + gpr.FlushLockX(ECX); + gpr.Lock(a, b, s); + gpr.BindToRegister(a, a == s || a == b || s == b, true); + MOV(32, R(ECX), gpr.R(b)); + XOR(32, R(EAX), R(EAX)); + TEST(32, R(ECX), Imm32(32)); + FixupBranch branch = J_CC(CC_NZ); + MOV(32, R(EAX), gpr.R(s)); + SHR(32, R(EAX), R(ECX)); + SetJumpTarget(branch); + MOV(32, gpr.R(a), R(EAX)); + gpr.UnlockAll(); + gpr.UnlockAllX(); + } + if (inst.Rc) { - ComputeRC(R(EAX)); + ComputeRC(gpr.R(a)); } } @@ -890,22 +1352,32 @@ int a = inst.RA; int b = inst.RB; int s = inst.RS; - gpr.FlushLockX(ECX); - gpr.Lock(a, b, s); - gpr.LoadToX64(a, a == s || a == b || s == b, true); - MOV(32, R(ECX), gpr.R(b)); - XOR(32, R(EAX), R(EAX)); - TEST(32, R(ECX), Imm32(32)); - FixupBranch branch = J_CC(CC_NZ); - MOV(32, R(EAX), gpr.R(s)); - SHL(32, R(EAX), R(ECX)); - SetJumpTarget(branch); - MOV(32, gpr.R(a), R(EAX)); - gpr.UnlockAll(); - gpr.UnlockAllX(); + + if (gpr.R(b).IsImm() && gpr.R(s).IsImm()) + { + u32 amount = (u32)gpr.R(b).offset; + gpr.SetImmediate32(a, (amount & 0x20) ? 0 : (u32)gpr.R(s).offset << amount); + } + else + { + gpr.FlushLockX(ECX); + gpr.Lock(a, b, s); + gpr.BindToRegister(a, a == s || a == b || s == b, true); + MOV(32, R(ECX), gpr.R(b)); + XOR(32, R(EAX), R(EAX)); + TEST(32, R(ECX), Imm32(32)); + FixupBranch branch = J_CC(CC_NZ); + MOV(32, R(EAX), gpr.R(s)); + SHL(32, R(EAX), R(ECX)); + SetJumpTarget(branch); + MOV(32, gpr.R(a), R(EAX)); + gpr.UnlockAll(); + gpr.UnlockAllX(); + } + if (inst.Rc) { - ComputeRC(R(EAX)); + ComputeRC(gpr.R(a)); } } @@ -917,9 +1389,9 @@ int a = inst.RA; int b = inst.RB; int s = inst.RS; - gpr.Lock(a, s); + gpr.Lock(a, s, b); gpr.FlushLockX(ECX); - gpr.LoadToX64(a, a == s || a == b, true); + gpr.BindToRegister(a, a == s || a == b, true); MOV(32, R(ECX), gpr.R(b)); TEST(32, R(ECX), Imm32(32)); FixupBranch topBitSet = J_CC(CC_NZ); @@ -963,7 +1435,7 @@ if (amount != 0) { gpr.Lock(a, s); - gpr.LoadToX64(a, a == s, true); + gpr.BindToRegister(a, a == s, true); MOV(32, R(EAX), gpr.R(s)); MOV(32, gpr.R(a), R(EAX)); SAR(32, gpr.R(a), Imm8(amount)); @@ -984,7 +1456,7 @@ Default(inst); return; gpr.Lock(a, s); JitClearCA(); - gpr.LoadToX64(a, a == s, true); + gpr.BindToRegister(a, a == s, true); if (a != s) MOV(32, gpr.R(a), gpr.R(s)); gpr.UnlockAll(); @@ -1002,19 +1474,28 @@ JITDISABLE(Integer) int a = inst.RA; int s = inst.RS; - if (gpr.R(a).IsImm() || gpr.R(s).IsImm() || s == a) + + if (gpr.R(s).IsImm()) { - Default(inst); - return; + u32 mask = 0x80000000; + u32 i = 0; + for (; i < 32; i++, mask >>= 1) + if ((u32)gpr.R(s).offset & mask) + break; + gpr.SetImmediate32(a, i); + } + else + { + gpr.Lock(a, s); + gpr.KillImmediate(s, true, false); + gpr.BindToRegister(a, (a == s), true); + BSR(32, gpr.R(a).GetSimpleReg(), gpr.R(s)); + FixupBranch gotone = J_CC(CC_NZ); + MOV(32, gpr.R(a), Imm32(63)); + SetJumpTarget(gotone); + XOR(32, gpr.R(a), Imm8(0x1f)); // flip order + gpr.UnlockAll(); } - gpr.Lock(a, s); - gpr.LoadToX64(a, false); - BSR(32, gpr.R(a).GetSimpleReg(), gpr.R(s)); - FixupBranch gotone = J_CC(CC_NZ); - MOV(32, gpr.R(a), Imm32(63)); - SetJumpTarget(gotone); - XOR(32, gpr.R(a), Imm8(0x1f)); // flip order - gpr.UnlockAll(); if (inst.Rc) { diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -38,75 +38,78 @@ { INSTRUCTION_START JITDISABLE(LoadStore) + if (Core::g_CoreStartupParameter.bJITLoadStorelbzxOff) { Default(inst); return; } int a = inst.RA, b = inst.RB, d = inst.RD; - gpr.Lock(a, b, d); gpr.FlushLockX(ABI_PARAM1); - if (b == d || a == d) - gpr.LoadToX64(d, true, true); - else - gpr.LoadToX64(d, false, true); MOV(32, R(ABI_PARAM1), gpr.R(b)); if (a) + { ADD(32, R(ABI_PARAM1), gpr.R(a)); -#if 0 + } + SafeLoadRegToEAX(ABI_PARAM1, 8, 0); + + MEMCHECK_START + + gpr.KillImmediate(d, false, true); MOV(32, gpr.R(d), R(EAX)); -#else - UnsafeLoadRegToReg(ABI_PARAM1, gpr.RX(d), 8, 0, false); -#endif - gpr.UnlockAll(); + + MEMCHECK_END + gpr.UnlockAllX(); } -void Jit64::lwzx(UGeckoInstruction inst) +void Jit64::lhax(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(LoadStore) int a = inst.RA, b = inst.RB, d = inst.RD; - gpr.Lock(a, b, d); gpr.FlushLockX(ABI_PARAM1); - if (b == d || a == d) - gpr.LoadToX64(d, true, true); - else - gpr.LoadToX64(d, false, true); MOV(32, R(ABI_PARAM1), gpr.R(b)); if (a) + { ADD(32, R(ABI_PARAM1), gpr.R(a)); -#if 1 - SafeLoadRegToEAX(ABI_PARAM1, 32, 0); + } + + // Some homebrew actually loads from a hw reg with this instruction + SafeLoadRegToEAX(ABI_PARAM1, 16, 0, true); + + MEMCHECK_START + + gpr.KillImmediate(d, false, true); MOV(32, gpr.R(d), R(EAX)); -#else - UnsafeLoadRegToReg(ABI_PARAM1, gpr.RX(d), 32, 0, false); -#endif - gpr.UnlockAll(); + + MEMCHECK_END + gpr.UnlockAllX(); } -void Jit64::lhax(UGeckoInstruction inst) +void Jit64::lwzx(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(LoadStore) int a = inst.RA, b = inst.RB, d = inst.RD; - gpr.Lock(a, b, d); gpr.FlushLockX(ABI_PARAM1); - if (b == d || a == d) - gpr.LoadToX64(d, true, true); - else - gpr.LoadToX64(d, false, true); MOV(32, R(ABI_PARAM1), gpr.R(b)); if (a) + { ADD(32, R(ABI_PARAM1), gpr.R(a)); + } - // Some homebrew actually loads from a hw reg with this instruction - SafeLoadRegToEAX(ABI_PARAM1, 16, 0, true); + SafeLoadRegToEAX(ABI_PARAM1, 32, 0); + + MEMCHECK_START + + gpr.KillImmediate(d, false, true); MOV(32, gpr.R(d), R(EAX)); - gpr.UnlockAll(); + MEMCHECK_END + gpr.UnlockAllX(); } @@ -114,6 +117,7 @@ { INSTRUCTION_START JITDISABLE(LoadStore) + if (Core::g_CoreStartupParameter.bJITLoadStorelXzOff) { Default(inst); return; } @@ -135,16 +139,16 @@ { // TODO(LinesPrower): // - Rewrite this! - // It seems to be ugly and unefficient, but I don't know JIT stuff enough to make it right + // It seems to be ugly and inefficient, but I don't know JIT stuff enough to make it right // It only demonstrates the idea // do our job at first s32 offset = (s32)(s16)inst.SIMM_16; gpr.FlushLockX(ABI_PARAM1); - gpr.Lock(d, a); + gpr.Lock(d); MOV(32, R(ABI_PARAM1), gpr.R(a)); SafeLoadRegToEAX(ABI_PARAM1, 32, offset); - gpr.LoadToX64(d, false, true); + gpr.KillImmediate(d, false, true); MOV(32, gpr.R(d), R(EAX)); gpr.UnlockAll(); gpr.UnlockAllX(); @@ -178,6 +182,7 @@ Default(inst); return; } + int accessSize; switch (inst.OPCD) { @@ -193,40 +198,34 @@ return; } - //Still here? Do regular path. -#if defined(_M_X64) - if (accessSize == 8 || accessSize == 16 || !jo.enableFastMem) { -#else - if (true) { -#endif - // Safe and boring + if (accessSize == 32 && jo.enableFastMem && !Core::g_CoreStartupParameter.bMMU) + { + // Fast and daring + gpr.Lock(a, d); + gpr.BindToRegister(a, true, false); + gpr.BindToRegister(d, a == d, true); + MOV(accessSize, gpr.R(d), MComplex(RBX, gpr.R(a).GetSimpleReg(), SCALE_1, offset)); + BSWAP(32, gpr.R(d).GetSimpleReg()); + gpr.UnlockAll(); + } + else + { gpr.FlushLockX(ABI_PARAM1); - gpr.Lock(d, a); + gpr.Lock(a); + gpr.BindToRegister(a, true, false); MOV(32, R(ABI_PARAM1), gpr.R(a)); SafeLoadRegToEAX(ABI_PARAM1, accessSize, offset); - gpr.LoadToX64(d, false, true); + + MEMCHECK_START + + gpr.KillImmediate(d, false, true); MOV(32, gpr.R(d), R(EAX)); + + MEMCHECK_END + gpr.UnlockAll(); gpr.UnlockAllX(); - return; - } - - // Fast and daring - gpr.Lock(a, d); - gpr.LoadToX64(a, true, false); - gpr.LoadToX64(d, a == d, true); - MOV(accessSize, gpr.R(d), MComplex(RBX, gpr.R(a).GetSimpleReg(), SCALE_1, offset)); - switch (accessSize) { - case 32: - BSWAP(32, gpr.R(d).GetSimpleReg()); - break; - // Careful in the backpatch - need to properly nop over first - // case 16: - // BSWAP(32, gpr.R(d).GetSimpleReg()); - // SHR(32, gpr.R(d), Imm8(16)); - // break; } - gpr.UnlockAll(); } void Jit64::lha(UGeckoInstruction inst) @@ -239,14 +238,17 @@ s32 offset = (s32)(s16)inst.SIMM_16; // Safe and boring gpr.FlushLockX(ABI_PARAM1); - gpr.Lock(d, a); MOV(32, R(ABI_PARAM1), gpr.R(a)); SafeLoadRegToEAX(ABI_PARAM1, 16, offset, true); - gpr.LoadToX64(d, d == a, true); + + MEMCHECK_START + + gpr.KillImmediate(d, false, true); MOV(32, gpr.R(d), R(EAX)); - gpr.UnlockAll(); + + MEMCHECK_END + gpr.UnlockAllX(); - return; } void Jit64::lwzux(UGeckoInstruction inst) @@ -260,17 +262,20 @@ Default(inst); return; } - gpr.Lock(a, b, d); - - gpr.LoadToX64(d, b == d, true); - gpr.LoadToX64(a, true, true); + gpr.Lock(a); + gpr.BindToRegister(a, true, true); ADD(32, gpr.R(a), gpr.R(b)); MOV(32, R(EAX), gpr.R(a)); SafeLoadRegToEAX(EAX, 32, 0, false); + + MEMCHECK_START + + gpr.KillImmediate(d, false, true); MOV(32, gpr.R(d), R(EAX)); + MEMCHECK_END + gpr.UnlockAll(); - return; } // Zero cache line. @@ -348,7 +353,7 @@ gpr.SetImmediate32(a, addr); MOV(accessSize, R(EAX), gpr.R(s)); BSWAP(accessSize, EAX); - WriteToConstRamAddress(accessSize, R(EAX), addr); + WriteToConstRamAddress(accessSize, R(EAX), addr); return; } // Other IO not worth the trouble. @@ -368,7 +373,12 @@ MOV(accessSize, MDisp(ABI_PARAM1, (u32)Memory::base + (u32)offset), R(EAX)); #endif if (update) + { + gpr.Lock(a); + gpr.KillImmediate(a, true, true); ADD(32, gpr.R(a), Imm32(offset)); + gpr.UnlockAll(); + } gpr.UnlockAllX(); return; } @@ -379,7 +389,7 @@ { // Fast and daring - requires 64-bit MOV(32, R(EAX), gpr.R(s)); - gpr.LoadToX64(a, true, false); + gpr.BindToRegister(a, true, false); BSWAP(32, EAX); MOV(accessSize, MComplex(RBX, gpr.RX(a), SCALE_1, (u32)offset), R(EAX)); return; @@ -387,35 +397,23 @@ #endif*/ //Still here? Do regular path. - gpr.Lock(s, a); + gpr.FlushLockX(ECX, EDX); + gpr.Lock(s, a); MOV(32, R(EDX), gpr.R(a)); MOV(32, R(ECX), gpr.R(s)); - if (offset) - ADD(32, R(EDX), Imm32((u32)offset)); + SafeWriteRegToReg(ECX, EDX, accessSize, offset); + if (update && offset) { - gpr.LoadToX64(a, true, true); - MOV(32, gpr.R(a), R(EDX)); - } - TEST(32, R(EDX), Imm32(0x0C000000)); - FixupBranch unsafe_addr = J_CC(CC_NZ); - BSWAP(accessSize, ECX); -#ifdef _M_X64 - MOV(accessSize, MComplex(RBX, EDX, SCALE_1, 0), R(ECX)); -#else - AND(32, R(EDX), Imm32(Memory::MEMVIEW32_MASK)); - MOV(accessSize, MDisp(EDX, (u32)Memory::base), R(ECX)); -#endif - FixupBranch skip_call = J(); - SetJumpTarget(unsafe_addr); - switch (accessSize) - { - case 32: ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U32, 2), ECX, EDX); break; - case 16: ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U16, 2), ECX, EDX); break; - case 8: ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U8, 2), ECX, EDX); break; + MEMCHECK_START + + gpr.KillImmediate(a, true, true); + ADD(32, gpr.R(a), Imm32((u32)offset)); + + MEMCHECK_END } - SetJumpTarget(skip_call); + gpr.UnlockAll(); gpr.UnlockAllX(); } @@ -440,7 +438,7 @@ gpr.FlushLockX(ECX, EDX); if (inst.SUBOP10 & 32) { - gpr.LoadToX64(a, true, true); + gpr.BindToRegister(a, true, true); ADD(32, gpr.R(a), gpr.R(b)); MOV(32, R(EDX), gpr.R(a)); } else { @@ -459,9 +457,14 @@ MOV(32, R(ECX), gpr.R(s)); SafeWriteRegToReg(ECX, EDX, accessSize, 0); + //MEMCHECK_START + + // TODO: Insert rA update code here + + //MEMCHECK_END + gpr.UnlockAll(); gpr.UnlockAllX(); - return; } // A few games use these heavily in video codecs. @@ -478,7 +481,7 @@ { MOV(32, R(ECX), MComplex(EBX, EAX, SCALE_1, (i - inst.RD) * 4)); BSWAP(32, ECX); - gpr.LoadToX64(i, false, true); + gpr.BindToRegister(i, false, true); MOV(32, gpr.R(i), R(ECX)); } gpr.UnlockAllX(); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -63,7 +63,6 @@ } s32 offset = (s32)(s16)inst.SIMM_16; gpr.FlushLockX(ABI_PARAM1); - gpr.Lock(a); MOV(32, R(ABI_PARAM1), gpr.R(a)); if (jo.assumeFPLoadFromMem) { @@ -74,12 +73,16 @@ SafeLoadRegToEAX(ABI_PARAM1, 32, offset); } + MEMCHECK_START + MOV(32, M(&temp32), R(EAX)); fpr.Lock(d); - fpr.LoadToX64(d, false); + fpr.BindToRegister(d, false); CVTSS2SD(fpr.RX(d), M(&temp32)); MOVDDUP(fpr.RX(d), fpr.R(d)); - gpr.UnlockAll(); + + MEMCHECK_END + gpr.UnlockAllX(); fpr.UnlockAll(); } @@ -90,6 +93,8 @@ INSTRUCTION_START JITDISABLE(LoadStoreFloating) + if (js.memcheck) { Default(inst); return; } + int d = inst.RD; int a = inst.RA; if (!a) @@ -102,8 +107,8 @@ gpr.Lock(a); MOV(32, R(ABI_PARAM1), gpr.R(a)); // TODO - optimize. This has to load the previous value - upper double should stay unmodified. - fpr.LoadToX64(d, true); fpr.Lock(d); + fpr.BindToRegister(d, true); X64Reg xd = fpr.RX(d); if (cpu_info.bSSSE3) { #ifdef _M_X64 @@ -119,18 +124,28 @@ MOV(64, R(EAX), MComplex(RBX, ABI_PARAM1, SCALE_1, offset)); BSWAP(64, EAX); MOV(64, M(&temp64), R(EAX)); + + MEMCHECK_START + MOVSD(XMM0, M(&temp64)); MOVSD(xd, R(XMM0)); + + MEMCHECK_END #else AND(32, R(ABI_PARAM1), Imm32(Memory::MEMVIEW32_MASK)); MOV(32, R(EAX), MDisp(ABI_PARAM1, (u32)Memory::base + offset)); BSWAP(32, EAX); MOV(32, M((void*)((u8 *)&temp64+4)), R(EAX)); + + MEMCHECK_START + MOV(32, R(EAX), MDisp(ABI_PARAM1, (u32)Memory::base + offset + 4)); BSWAP(32, EAX); MOV(32, M(&temp64), R(EAX)); MOVSD(XMM0, M(&temp64)); MOVSD(xd, R(XMM0)); + + MEMCHECK_END #if 0 // Alternate implementation; possibly faster AND(32, R(ABI_PARAM1), Imm32(Memory::MEMVIEW32_MASK)); @@ -156,6 +171,8 @@ INSTRUCTION_START JITDISABLE(LoadStoreFloating) + if (js.memcheck) { Default(inst); return; } + int s = inst.RS; int a = inst.RA; if (!a) @@ -167,7 +184,7 @@ gpr.FlushLockX(ABI_PARAM1); gpr.Lock(a); fpr.Lock(s); - gpr.LoadToX64(a, true, false); + gpr.BindToRegister(a, true, false); LEA(32, ABI_PARAM1, MDisp(gpr.R(a).GetSimpleReg(), offset)); TEST(32, R(ABI_PARAM1), Imm32(0x0c000000)); FixupBranch not_ram = J_CC(CC_Z); @@ -205,20 +222,30 @@ #endif } else { #ifdef _M_X64 - fpr.LoadToX64(s, true, false); + fpr.BindToRegister(s, true, false); MOVSD(M(&temp64), fpr.RX(s)); + + MEMCHECK_START + MOV(64, R(EAX), M(&temp64)); BSWAP(64, EAX); MOV(64, MComplex(RBX, ABI_PARAM1, SCALE_1, 0), R(EAX)); + + MEMCHECK_END #else - fpr.LoadToX64(s, true, false); + fpr.BindToRegister(s, true, false); MOVSD(M(&temp64), fpr.RX(s)); + + MEMCHECK_START + MOV(32, R(EAX), M(&temp64)); BSWAP(32, EAX); MOV(32, MDisp(ABI_PARAM1, (u32)Memory::base + 4), R(EAX)); MOV(32, R(EAX), M((void*)((u8 *)&temp64 + 4))); BSWAP(32, EAX); MOV(32, MDisp(ABI_PARAM1, (u32)Memory::base), R(EAX)); + + MEMCHECK_END #endif } SetJumpTarget(quit); @@ -272,7 +299,12 @@ ADD(32, R(ABI_PARAM2), Imm32(offset)); if (update && offset) { + MEMCHECK_START + + gpr.KillImmediate(a, false, true); MOV(32, gpr.R(a), R(ABI_PARAM2)); + + MEMCHECK_END } CVTSD2SS(XMM0, fpr.R(s)); SafeWriteFloatToReg(XMM0, ABI_PARAM2); @@ -295,7 +327,8 @@ ADD(32, R(ABI_PARAM1), gpr.R(inst.RA)); CVTSD2SS(XMM0, fpr.R(inst.RS)); MOVD_xmm(R(EAX), XMM0); - UnsafeWriteRegToReg(EAX, ABI_PARAM1, 32, 0); + SafeWriteRegToReg(EAX, ABI_PARAM1, 32, 0); + gpr.UnlockAllX(); fpr.UnlockAll(); } @@ -306,12 +339,14 @@ INSTRUCTION_START JITDISABLE(LoadStoreFloating) - fpr.Lock(inst.RS); - fpr.LoadToX64(inst.RS, false, true); MOV(32, R(EAX), gpr.R(inst.RB)); if (inst.RA) + { ADD(32, R(EAX), gpr.R(inst.RA)); - if (cpu_info.bSSSE3) { + } + if (cpu_info.bSSSE3 && !js.memcheck) { + fpr.Lock(inst.RS); + fpr.BindToRegister(inst.RS, false, true); X64Reg r = fpr.R(inst.RS).GetSimpleReg(); #ifdef _M_IX86 AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); @@ -319,14 +354,25 @@ #else MOVD_xmm(r, MComplex(RBX, EAX, SCALE_1, 0)); #endif + MEMCHECK_START + PSHUFB(r, M((void *)bswapShuffle1x4)); CVTSS2SD(r, R(r)); MOVDDUP(r, R(r)); + + MEMCHECK_END } else { - UnsafeLoadRegToReg(EAX, EAX, 32, false); + SafeLoadRegToEAX(EAX, 32, false); + + MEMCHECK_START + MOV(32, M(&temp32), R(EAX)); CVTSS2SD(XMM0, M(&temp32)); + fpr.Lock(inst.RS); + fpr.BindToRegister(inst.RS, false, true); MOVDDUP(fpr.R(inst.RS).GetSimpleReg(), R(XMM0)); + + MEMCHECK_END } fpr.UnlockAll(); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -54,6 +54,8 @@ INSTRUCTION_START JITDISABLE(LoadStorePaired) + if (js.memcheck) { Default(inst); return; } + if (!inst.RA) { // TODO: Support these cases if it becomes necessary. @@ -97,8 +99,8 @@ gpr.FlushLockX(EAX, EDX); gpr.FlushLockX(ECX); if (update) - gpr.LoadToX64(inst.RA, true, true); - fpr.LoadToX64(inst.RS, true); + gpr.BindToRegister(inst.RA, true, true); + fpr.BindToRegister(inst.RS, true, false); MOV(32, R(ECX), gpr.R(inst.RA)); if (offset) ADD(32, R(ECX), Imm32((u32)offset)); @@ -136,6 +138,8 @@ INSTRUCTION_START JITDISABLE(LoadStorePaired) + if (js.memcheck) { Default(inst); return; } + if (!inst.RA) { Default(inst); @@ -155,8 +159,8 @@ gpr.FlushLockX(EAX, EDX); gpr.FlushLockX(ECX); - gpr.LoadToX64(inst.RA, true, true); - fpr.LoadToX64(inst.RS, false, true); + gpr.BindToRegister(inst.RA, true, update && offset); + fpr.BindToRegister(inst.RS, false, true); if (offset) LEA(32, ECX, MDisp(gpr.RX(inst.RA), offset)); else @@ -174,7 +178,13 @@ ABI_AlignStack(0); CALLptr(MDisp(EDX, (u32)(u64)asm_routines.pairedLoadQuantized)); ABI_RestoreStack(0); + +// MEMCHECK_START // FIXME: MMU does not work here because of unsafe memory access + CVTPS2PD(fpr.RX(inst.RS), R(XMM0)); + +// MEMCHECK_END + gpr.UnlockAll(); gpr.UnlockAllX(); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -50,7 +50,7 @@ int b = inst.FB; if (d == b) return; - fpr.LoadToX64(d, false); + fpr.BindToRegister(d, false); MOVAPD(fpr.RX(d), fpr.R(b)); } @@ -72,8 +72,8 @@ fpr.FlushLockX(XMM7); fpr.FlushLockX(XMM6); fpr.Lock(a, b, c, d); - fpr.LoadToX64(a, true, false); - fpr.LoadToX64(d, false, true); + fpr.BindToRegister(a, true, false); + fpr.BindToRegister(d, false, true); // BLENDPD would have been nice... MOVAPD(XMM7, fpr.R(a)); CMPPD(XMM7, M((void*)psZeroZero), 1); //less-than = 111111 @@ -99,12 +99,12 @@ fpr.Lock(d, b); if (d != b) { - fpr.LoadToX64(d, false); + fpr.BindToRegister(d, false); MOVAPD(fpr.RX(d), fpr.R(b)); } else { - fpr.LoadToX64(d, true); + fpr.BindToRegister(d, true); } switch (inst.SUBOP10) @@ -133,6 +133,7 @@ int d = inst.FD; int b = inst.FB; fpr.Lock(d, b); + fpr.BindToRegister(d, (d == b), true); SQRTPD(XMM0, fpr.R(b)); MOVAPD(XMM1, M((void*)&psOneOne)); DIVPD(XMM1, R(XMM0)); @@ -161,24 +162,24 @@ if (d == a) { - fpr.LoadToX64(d, true); + fpr.BindToRegister(d, true); (this->*op)(fpr.RX(d), fpr.R(b)); } else if (d == b && reversible) { - fpr.LoadToX64(d, true); + fpr.BindToRegister(d, true); (this->*op)(fpr.RX(d), fpr.R(a)); } else if (a != d && b != d) { //sources different from d, can use rather quick solution - fpr.LoadToX64(d, false); + fpr.BindToRegister(d, false); MOVAPD(fpr.RX(d), fpr.R(a)); (this->*op)(fpr.RX(d), fpr.R(b)); } else if (b != d) { - fpr.LoadToX64(d, false); + fpr.BindToRegister(d, false); MOVAPD(XMM0, fpr.R(b)); MOVAPD(fpr.RX(d), fpr.R(a)); (this->*op)(fpr.RX(d), Gen::R(XMM0)); @@ -187,7 +188,7 @@ { MOVAPD(XMM0, fpr.R(a)); MOVAPD(XMM1, fpr.R(b)); - fpr.LoadToX64(d, false); + fpr.BindToRegister(d, false); (this->*op)(XMM0, Gen::R(XMM1)); MOVAPD(fpr.RX(d), Gen::R(XMM0)); } @@ -231,7 +232,7 @@ int b = inst.FB; int c = inst.FC; fpr.Lock(a,b,c,d); - fpr.LoadToX64(d, d == a || d == b || d == c, true); + fpr.BindToRegister(d, d == a || d == b || d == c, true); switch (inst.SUBOP5) { case 10: @@ -271,7 +272,7 @@ int a = inst.FA; int c = inst.FC; fpr.Lock(a, c, d); - fpr.LoadToX64(d, d == a || d == c, true); + fpr.BindToRegister(d, d == a || d == c, true); switch (inst.SUBOP5) { case 12: @@ -329,7 +330,7 @@ default: _assert_msg_(DYNA_REC, 0, "ps_merge - invalid op"); } - fpr.LoadToX64(d, false); + fpr.BindToRegister(d, false); MOVAPD(fpr.RX(d), Gen::R(XMM0)); fpr.UnlockAll(); } @@ -387,7 +388,7 @@ //fpr.UnlockAll(); return; } - fpr.LoadToX64(d, false); + fpr.BindToRegister(d, false); MOVAPD(fpr.RX(d), Gen::R(XMM0)); ForceSinglePrecisionP(fpr.RX(d)); fpr.UnlockAll(); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -128,7 +128,7 @@ int preg = xregs[xr].ppcReg; if (!locks[preg]) { - StoreFromX64(preg); + StoreFromRegister(preg); return xr; } } @@ -159,7 +159,7 @@ PanicAlert("Flushing non existent reg"); if (!xregs[reg].free) { - StoreFromX64(xregs[reg].ppcReg); + StoreFromRegister(xregs[reg].ppcReg); } } @@ -185,9 +185,12 @@ { if (regs[preg].away && regs[preg].location.IsSimpleReg()) { - xregs[regs[preg].location.GetSimpleReg()].free = true; - xregs[regs[preg].location.GetSimpleReg()].dirty = false; + X64Reg xr = regs[preg].location.GetSimpleReg(); + xregs[xr].free = true; + xregs[xr].dirty = false; + xregs[xr].ppcReg = -1; regs[preg].away = false; + regs[preg].location = GetDefaultLocation(preg); } } @@ -252,15 +255,18 @@ return M(&ppcState.ps[reg][0]); } -void RegCache::KillImmediate(int preg) +void RegCache::KillImmediate(int preg, bool doLoad, bool makeDirty) { - if (regs[preg].away && regs[preg].location.IsImm()) + if (regs[preg].away) { - LoadToX64(preg, true, true); + if (regs[preg].location.IsImm()) + BindToRegister(preg, doLoad, makeDirty); + else if (regs[preg].location.IsSimpleReg()) + xregs[RX(preg)].dirty |= makeDirty; } } -void GPRRegCache::LoadToX64(int i, bool doLoad, bool makeDirty) +void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty) { if (!regs[i].away && regs[i].location.IsImm()) PanicAlert("Bad immediate"); @@ -297,7 +303,7 @@ } } -void GPRRegCache::StoreFromX64(int i) +void GPRRegCache::StoreFromRegister(int i) { if (regs[i].away) { @@ -316,21 +322,21 @@ doStore = true; } OpArg newLoc = GetDefaultLocation(i); - // if (doStore) //<-- Breaks JIT compilation + if (doStore) emit->MOV(32, newLoc, regs[i].location); regs[i].location = newLoc; regs[i].away = false; } } -void FPURegCache::LoadToX64(int i, bool doLoad, bool makeDirty) +void FPURegCache::BindToRegister(int i, bool doLoad, bool makeDirty) { _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - load - imm"); if (!regs[i].away) { // Reg is at home in the memory register file. Let's pull it out. X64Reg xr = GetFreeXReg(); - _assert_msg_(DYNA_REC, xr >= 0 && xr < NUMXREGS, "WTF - load - invalid reg"); + _assert_msg_(DYNA_REC, xr < NUMXREGS, "WTF - load - invalid reg"); xregs[xr].ppcReg = i; xregs[xr].free = false; xregs[xr].dirty = makeDirty; @@ -351,13 +357,13 @@ } } -void FPURegCache::StoreFromX64(int i) +void FPURegCache::StoreFromRegister(int i) { _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - store - imm"); if (regs[i].away) { X64Reg xr = regs[i].location.GetSimpleReg(); - _assert_msg_(DYNA_REC, xr >= 0 && xr < NUMXREGS, "WTF - store - invalid reg"); + _assert_msg_(DYNA_REC, xr < NUMXREGS, "WTF - store - invalid reg"); xregs[xr].free = true; xregs[xr].dirty = false; xregs[xr].ppcReg = -1; @@ -389,12 +395,12 @@ if (regs[i].location.IsSimpleReg()) { X64Reg xr = RX(i); - StoreFromX64(i); + StoreFromRegister(i); xregs[xr].dirty = false; } else if (regs[i].location.IsImm()) { - StoreFromX64(i); + StoreFromRegister(i); } else { diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h 2010-08-18 03:25:18.000000000 +0100 @@ -96,12 +96,12 @@ virtual void Flush(FlushMode mode); virtual void Flush(PPCAnalyst::CodeOp *op) {Flush(FLUSH_ALL);} int SanityCheck() const; - void KillImmediate(int preg); + void KillImmediate(int preg, bool doLoad, bool makeDirty); //TODO - instead of doload, use "read", "write" //read only will not set dirty flag - virtual void LoadToX64(int preg, bool doLoad = true, bool makeDirty = true) = 0; - virtual void StoreFromX64(int preg) = 0; + virtual void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) = 0; + virtual void StoreFromRegister(int preg) = 0; const OpArg &R(int preg) const {return regs[preg].location;} X64Reg RX(int preg) const @@ -131,8 +131,8 @@ { public: void Start(PPCAnalyst::BlockRegStats &stats); - void LoadToX64(int preg, bool doLoad = true, bool makeDirty = true); - void StoreFromX64(int preg); + void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true); + void StoreFromRegister(int preg); OpArg GetDefaultLocation(int reg) const; const int *GetAllocationOrder(int &count); void SetImmediate32(int preg, u32 immValue); @@ -143,8 +143,8 @@ { public: void Start(PPCAnalyst::BlockRegStats &stats); - void LoadToX64(int preg, bool doLoad = true, bool makeDirty = true); - void StoreFromX64(int preg); + void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true); + void StoreFromRegister(int preg); const int *GetAllocationOrder(int &count); OpArg GetDefaultLocation(int reg) const; }; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -72,8 +72,11 @@ } // OK, this is easy. - gpr.Lock(d); - gpr.LoadToX64(d, true); + if (!gpr.R(d).IsImm()) + { + gpr.Lock(d); + gpr.BindToRegister(d, true, false); + } MOV(32, M(&PowerPC::ppcState.spr[iIndex]), gpr.R(d)); gpr.UnlockAll(); } @@ -98,7 +101,7 @@ // fall through default: gpr.Lock(d); - gpr.LoadToX64(d, false); + gpr.BindToRegister(d, false); MOV(32, gpr.R(d), M(&PowerPC::ppcState.spr[iIndex])); gpr.UnlockAll(); break; @@ -113,8 +116,13 @@ { INSTRUCTION_START JITDISABLE(SystemRegisters) - gpr.LoadToX64(inst.RS, true, false); + if (!gpr.R(inst.RS).IsImm()) + { + gpr.Lock(inst.RS); + gpr.BindToRegister(inst.RS, true, false); + } MOV(32, M(&MSR), gpr.R(inst.RS)); + gpr.UnlockAll(); gpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL); WriteExit(js.compilerPC + 4, 0); @@ -127,8 +135,10 @@ INSTRUCTION_START JITDISABLE(SystemRegisters) //Privileged? - gpr.LoadToX64(inst.RD, false); + gpr.Lock(inst.RD); + gpr.BindToRegister(inst.RD, false, true); MOV(32, gpr.R(inst.RD), M(&MSR)); + gpr.UnlockAll(); } void Jit64::mftb(UGeckoInstruction inst) @@ -144,15 +154,15 @@ JITDISABLE(SystemRegisters) // USES_CR int d = inst.RD; - gpr.LoadToX64(d, false, true); + gpr.Lock(d); + gpr.KillImmediate(d, false, true); MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[0])); - SHL(32, R(EAX), Imm8(4)); - for (int i = 1; i < 7; i++) { - OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[i])); + for (int i = 1; i < 8; i++) { SHL(32, R(EAX), Imm8(4)); + OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[i])); } - OR(8, R(EAX), M(&PowerPC::ppcState.cr_fast[7])); MOV(32, gpr.R(d), R(EAX)); + gpr.UnlockAll(); } void Jit64::mtcrf(UGeckoInstruction inst) @@ -161,32 +171,138 @@ JITDISABLE(SystemRegisters) // USES_CR - u32 mask = 0; u32 crm = inst.CRM; - if (crm == 0xFF) { - gpr.FlushLockX(ECX); - MOV(32, R(EAX), gpr.R(inst.RS)); - for (int i = 0; i < 8; i++) { - MOV(32, R(ECX), R(EAX)); - SHR(32, R(ECX), Imm8(28 - (i * 4))); - AND(32, R(ECX), Imm32(0xF)); - MOV(8, M(&PowerPC::ppcState.cr_fast[i]), R(ECX)); + if (crm != 0) + { + if (gpr.R(inst.RS).IsImm()) + { + for (int i = 0; i < 8; i++) + { + if ((crm & (0x80 >> i)) != 0) + { + u8 newcr = (gpr.R(inst.RS).offset >> (28 - (i * 4))) & 0xF; + MOV(8, M(&PowerPC::ppcState.cr_fast[i]), Imm8(newcr)); + } + } } - gpr.UnlockAllX(); - } else { - Default(inst); - return; - - // TODO: translate this to work in new CR model. - for (int i = 0; i < 8; i++) { - if (crm & (1 << i)) - mask |= 0xF << (i*4); + else + { + gpr.Lock(inst.RS); + gpr.BindToRegister(inst.RS, true, false); + for (int i = 0; i < 8; i++) + { + if ((crm & (0x80 >> i)) != 0) + { + MOV(32, R(EAX), gpr.R(inst.RS)); + SHR(32, R(EAX), Imm8(28 - (i * 4))); + AND(32, R(EAX), Imm32(0xF)); + MOV(8, M(&PowerPC::ppcState.cr_fast[i]), R(EAX)); + } + } + gpr.UnlockAll(); } - MOV(32, R(EAX), gpr.R(inst.RS)); - MOV(32, R(ECX), M(&PowerPC::ppcState.cr)); - AND(32, R(EAX), Imm32(mask)); - AND(32, R(ECX), Imm32(~mask)); - OR(32, R(EAX), R(ECX)); - MOV(32, M(&PowerPC::ppcState.cr), R(EAX)); } } + +void Jit64::mcrf(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(SystemRegisters) + + // USES_CR + if (inst.CRFS != inst.CRFD) + { + MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRFS])); + MOV(8, M(&PowerPC::ppcState.cr_fast[inst.CRFD]), R(EAX)); + } +} + +void Jit64::mcrxr(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(SystemRegisters) + + // USES_CR + + // Copy XER[0-3] into CR[inst.CRFD] + MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER])); + SHR(32, R(EAX), Imm8(28)); + MOV(8, M(&PowerPC::ppcState.cr_fast[inst.CRFD]), R(EAX)); + + // Clear XER[0-3] + AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(0x0FFFFFFF)); +} + +void Jit64::crXXX(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(SystemRegisters) + _dbg_assert_msg_(DYNA_REC, inst.OPCD == 19, "Invalid crXXX"); + + // USES_CR + + // Get bit CRBA in EAX aligned with bit CRBD + int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3); + MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[inst.CRBA >> 2])); + if (shiftA < 0) + SHL(8, R(EAX), Imm8(-shiftA)); + else if (shiftA > 0) + SHR(8, R(EAX), Imm8(shiftA)); + + // Get bit CRBB in ECX aligned with bit CRBD + gpr.FlushLockX(ECX); + int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3); + MOV(8, R(ECX), M(&PowerPC::ppcState.cr_fast[inst.CRBB >> 2])); + if (shiftB < 0) + SHL(8, R(ECX), Imm8(-shiftB)); + else if (shiftB > 0) + SHR(8, R(ECX), Imm8(shiftB)); + + // Compute combined bit + switch(inst.SUBOP10) + { + case 33: // crnor + OR(8, R(EAX), R(ECX)); + NOT(8, R(EAX)); + break; + + case 129: // crandc + NOT(8, R(ECX)); + AND(8, R(EAX), R(ECX)); + break; + + case 193: // crxor + XOR(8, R(EAX), R(ECX)); + break; + + case 225: // crnand + AND(8, R(EAX), R(ECX)); + NOT(8, R(EAX)); + break; + + case 257: // crand + AND(8, R(EAX), R(ECX)); + break; + + case 289: // creqv + XOR(8, R(EAX), R(ECX)); + NOT(8, R(EAX)); + break; + + case 417: // crorc + NOT(8, R(ECX)); + OR(8, R(EAX), R(ECX)); + break; + + case 449: // cror + OR(8, R(EAX), R(ECX)); + break; + } + + // Store result bit in CRBD + AND(8, R(EAX), Imm8(0x8 >> (inst.CRBD & 3))); + AND(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), Imm8(~(0x8 >> (inst.CRBD & 3)))); + OR(8, M(&PowerPC::ppcState.cr_fast[inst.CRBD >> 2]), R(EAX)); + + gpr.UnlockAllX(); +} diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -129,6 +129,7 @@ #pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned #endif +#include #include "IR.h" #include "../PPCTables.h" #include "../../CoreTiming.h" @@ -374,6 +375,22 @@ return getOp1(Op1); } + if (InstLoc negOp1 = isNeg(Op1)) { + // TODO: Test the folding below + // -A + -B --> -(A + B) + if (InstLoc negOp2 = isNeg(Op2)) { + return FoldSub(EmitIntConst(0), FoldAdd(negOp1, negOp2)); + } + + // -A + B --> B - A + return FoldSub(Op2, negOp1); + } + + // A + -B --> A - B + if (InstLoc negOp2 = isNeg(Op2)) { + return FoldSub(Op1, negOp2); + } + // TODO: Test the folding below // (x * i0) + x => x * (i0 + 1) if (getOpcode(*Op1) == Mul && isImm(*getOp2(Op1)) && isSameValue(getOp1(Op1), Op2)) { @@ -425,6 +442,12 @@ return EmitIntConst(0); } + // TODO: Test the folding below + // x - (-A) => x + A + if (InstLoc negOp2 = isNeg(Op2)) { + return FoldAdd(Op1, negOp2); + } + // (x - i0) => x + -i0 if (isImm(*Op2)) { return FoldAdd(Op1, EmitIntConst(-GetImmValue(Op2))); @@ -566,6 +589,14 @@ } // TODO: Test the folding below + // -X * -Y => X * Y + if (InstLoc negOp1 = isNeg(Op1)) { + if (InstLoc negOp2 = isNeg(Op2)) { + return FoldMul(negOp1, negOp2); + } + } + + // TODO: Test the folding below // x * (1 << y) => x << y if (getOpcode(*Op2) == Shl && isImm(*getOp1(Op2)) && GetImmValue(getOp1(Op2)) == 1) { return FoldShl(Op1, getOp2(Op2)); @@ -1017,6 +1048,12 @@ return true; } + if (getNumberOfOperands(Op1) == 2 && getOpcode(*Op1) != StorePaired && getOpcode(*Op1) == getOpcode(*Op2) && + isSameValue(getOp1(Op1), getOp1(Op2)) && isSameValue(getOp2(Op1), getOp2(Op2))) + { + return true; + } + return false; } @@ -1028,27 +1065,44 @@ // 3 -> UOp // 4 -> BiOp unsigned IRBuilder::getComplexity(InstLoc I) const { - static unsigned complexities[256]; - if (complexities[0] == 0) { - complexities[Nop] = 1; - complexities[CInt16] = 1; - complexities[CInt32] = 1; + const unsigned Opcode = getOpcode(*I); + if (Opcode == Nop || Opcode == CInt16 || Opcode == CInt32) { + return 1; + } + + const unsigned numberOfOperands = getNumberOfOperands(I); + if (numberOfOperands == -1U) { + return 0; + } + + return numberOfOperands + 2; +} + + +unsigned IRBuilder::getNumberOfOperands(InstLoc I) const { + static unsigned numberOfOperands[256]; + if (numberOfOperands[0] == 0) { + std::fill_n(numberOfOperands, sizeof(numberOfOperands) / sizeof(numberOfOperands[0]), -1U); + + numberOfOperands[Nop] = 0; + numberOfOperands[CInt16] = 0; + numberOfOperands[CInt32] = 0; static unsigned ZeroOp[] = {LoadCR, LoadLink, LoadMSR, LoadGReg, LoadCTR, InterpreterBranch, LoadCarry, RFIExit, LoadFReg, LoadFRegDENToZero, LoadGQR, Int3, }; static unsigned UOp[] = {StoreLink, BranchUncond, StoreCR, StoreMSR, StoreFPRF, StoreGReg, StoreCTR, Load8, Load16, Load32, SExt16, SExt8, Cntlzw, StoreCarry, SystemCall, ShortIdleLoop, LoadSingle, LoadDouble, LoadPaired, StoreFReg, DupSingleToMReg, DupSingleToPacked, ExpandPackedToMReg, CompactMRegToPacked, FSNeg, FSRSqrt, FDNeg, FPDup0, FPDup1, FPNeg, DoubleToSingle, StoreGQR, StoreSRR, }; static unsigned BiOp[] = {BranchCond, IdleBranch, And, Xor, Sub, Or, Add, Mul, Rol, Shl, Shrl, Sarl, ICmpEq, ICmpNe, ICmpUgt, ICmpUlt, ICmpSgt, ICmpSlt, ICmpSge, ICmpSle, Store8, Store16, Store32, ICmpCRSigned, ICmpCRUnsigned, InterpreterFallback, StoreSingle, StoreDouble, StorePaired, InsertDoubleInMReg, FSMul, FSAdd, FSSub, FDMul, FDAdd, FDSub, FPAdd, FPMul, FPSub, FPMerge00, FPMerge01, FPMerge10, FPMerge11, FDCmpCR, }; for (size_t i = 0; i < sizeof(ZeroOp) / sizeof(ZeroOp[0]); ++i) { - complexities[ZeroOp[i]] = 2; + numberOfOperands[ZeroOp[i]] = 0; } for (size_t i = 0; i < sizeof(UOp) / sizeof(UOp[0]); ++i) { - complexities[UOp[i]] = 3; + numberOfOperands[UOp[i]] = 1; } for (size_t i = 0; i < sizeof(BiOp) / sizeof(BiOp[0]); ++i) { - complexities[BiOp[i]] = 4; + numberOfOperands[BiOp[i]] = 2; } } - return complexities[getOpcode(*I)]; + return numberOfOperands[getOpcode(*I)]; } // Performs a few simplifications for commutative operators @@ -1073,7 +1127,7 @@ return; } - // Transform: (op (op V, C1), C2) ==> (op V, (op C1, C2)) + // (V op C1) op C2 => V + (C1 + C2) if (getOpcode(*Op1) == Opcode && isImm(*getOp2(Op1)) && isImm(*Op2)) { const InstLoc Op1Old = Op1; const InstLoc Op2Old = Op2; @@ -1081,6 +1135,7 @@ Op2 = FoldBiOp(Opcode, getOp2(Op1Old), Op2Old); } + // ((V1 op C1) op (V2 op C2)) => ((V1 op V2) op (C1 op C2)) // Transform: (op (op V1, C1), (op V2, C2)) ==> (op (op V1, V2), (op C1,C2)) if (getOpcode(*Op1) == Opcode && isImm(*getOp2(Op1)) && getOpcode(*Op2) == Opcode && isImm(*getOp2(Op2))) { const InstLoc Op1Old = Op1; @@ -1088,6 +1143,23 @@ Op1 = FoldBiOp(Opcode, getOp1(Op1Old), getOp1(Op2Old)); Op2 = FoldBiOp(Opcode, getOp2(Op1Old), getOp2(Op2Old)); } + + // FIXME: Following code has a bug. + // ((w op x) op (y op z)) => (((w op x) op y) op z) + /* + if (getOpcode(*Op1) == Opcode && getOpcode(*Op2) == Opcode) { + // Sort the operands where the complexities will be descending order. + std::pair ops[4]; + ops[0] = std::make_pair(getComplexity(getOp1(Op1)), getOp1(Op1)); + ops[1] = std::make_pair(getComplexity(getOp2(Op1)), getOp2(Op1)); + ops[2] = std::make_pair(getComplexity(getOp1(Op2)), getOp1(Op2)); + ops[3] = std::make_pair(getComplexity(getOp2(Op2)), getOp2(Op2)); + std::sort(ops, ops + 4, std::greater >()); + + Op1 = FoldBiOp(Opcode, FoldBiOp(Opcode, ops[0].second, ops[1].second), ops[2].second); + Op2 = ops[3].second; + } + */ } bool IRBuilder::maskedValueIsZero(InstLoc Op1, InstLoc Op2) const { @@ -1114,4 +1186,13 @@ return NULL; } +// Returns I' if I == (0 - I') +InstLoc IRBuilder::isNeg(InstLoc I) const { + if (getOpcode(*I) == Sub && isImm(*getOp1(I)) && GetImmValue(getOp1(I)) == 0) { + return getOp2(I); + } + + return NULL; +} + } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h 2010-08-18 03:25:18.000000000 +0100 @@ -145,6 +145,7 @@ StoreDouble, StoreFReg, FDCmpCR, + CFloatOne, // Store 1.0f into the specified floating register // "Trinary" operators // FIXME: Need to change representation! @@ -163,6 +164,10 @@ ShortIdleLoop, // Idle loop seen in homebrew like wii mahjong, // just a branch + // used for MMU, at least until someone + // has a better idea of integrating it + FPExceptionCheckStart, FPExceptionCheckEnd, + ISIException, // "Opcode" representing a register too far away to // reference directly; this is a size optimization Tramp, @@ -389,6 +394,15 @@ InstLoc EmitSystemCall(InstLoc pc) { return FoldUOp(SystemCall, pc); } + InstLoc EmitFPExceptionCheckStart(InstLoc pc) { + return EmitUOp(FPExceptionCheckStart, pc); + } + InstLoc EmitFPExceptionCheckEnd(InstLoc pc) { + return EmitUOp(FPExceptionCheckEnd, pc); + } + InstLoc EmitISIException(InstLoc dest) { + return EmitUOp(ISIException, dest); + } InstLoc EmitRFIExit() { return FoldZeroOp(RFIExit, 0); } @@ -500,6 +514,9 @@ InstLoc EmitFDCmpCR(InstLoc op1, InstLoc op2) { return FoldBiOp(FDCmpCR, op1, op2); } + InstLoc EmitCFloatOne() { + return FoldZeroOp(CFloatOne, 0); + } InstLoc EmitLoadGQR(unsigned gqr) { return FoldZeroOp(LoadGQR, gqr); } @@ -544,6 +561,8 @@ IRBuilder() { Reset(); } + unsigned getNumberOfOperands(InstLoc I) const; + private: IRBuilder(IRBuilder&); // DO NOT IMPLEMENT unsigned isSameValue(InstLoc Op1, InstLoc Op2) const; @@ -551,6 +570,7 @@ void simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2); bool maskedValueIsZero(InstLoc Op1, InstLoc Op2) const; InstLoc isNot(InstLoc I) const; + InstLoc isNeg(InstLoc I) const; std::vector InstList; // FIXME: We must ensure this is // continuous! diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -465,7 +465,6 @@ } static void regEmitMemLoad(RegInfo& RI, InstLoc I, unsigned Size) { - bool win32 = false; if (RI.UseProfile) { unsigned curLoad = ProfiledLoads[RI.numProfiledLoads++]; if (!(curLoad & 0x0C000000)) { @@ -486,15 +485,8 @@ if (RI.MakeProfile) { RI.Jit->MOV(32, M(&ProfiledLoads[RI.numProfiledLoads++]), R(ECX)); } -#ifdef _M_IX86 - win32 = true; -#endif - FixupBranch argh; - if (!(win32 && SConfig::GetInstance().m_LocalCoreStartupParameter.iTLBHack == 1)) - { - RI.Jit->TEST(32, R(ECX), Imm32(0x0C000000)); - argh = RI.Jit->J_CC(CC_Z); - } + RI.Jit->TEST(32, R(ECX), Imm32(0x0C000000)); + FixupBranch argh = RI.Jit->J_CC(CC_Z); // Slow safe read using Memory::Read_Ux routines #ifdef _M_IX86 // we don't allocate EAX on x64 so no reason to save it. @@ -514,14 +506,10 @@ RI.Jit->POP(32, R(EAX)); #endif } - if (!(win32 && SConfig::GetInstance().m_LocalCoreStartupParameter.iTLBHack == 1)) - { - FixupBranch arg2 = RI.Jit->J(); - // Fast unsafe read using memory pointer EBX - RI.Jit->SetJumpTarget(argh); - RI.Jit->UnsafeLoadRegToReg(ECX, reg, Size, 0, false); - RI.Jit->SetJumpTarget(arg2); - } + FixupBranch arg2 = RI.Jit->J(); + RI.Jit->SetJumpTarget(argh); + RI.Jit->UnsafeLoadRegToReg(ECX, reg, Size, 0, false); + RI.Jit->SetJumpTarget(arg2); if (regReadUse(RI, I)) RI.regs[reg] = I; } @@ -705,6 +693,9 @@ case RFIExit: case InterpreterBranch: case ShortIdleLoop: + case FPExceptionCheckStart: + case FPExceptionCheckEnd: + case ISIException: case Int3: case Tramp: // No liveness effects @@ -734,6 +725,7 @@ case LoadDouble: case LoadSingle: case LoadPaired: + case CFloatOne: if (thisUsed) regMarkUse(RI, I, getOp1(I), 1); break; @@ -1178,6 +1170,16 @@ regNormalRegClear(RI, I); break; } + case CFloatOne: { + if (!thisUsed) break; + X64Reg reg = fregFindFreeReg(RI); + static const float one = 1.0f; + Jit->MOV(32, R(ECX), Imm32(*(u32*)&one)); + Jit->MOVD_xmm(reg, R(ECX)); + RI.fregs[reg] = I; + regNormalRegClear(RI, I); + break; + } case LoadDouble: { if (!thisUsed) break; X64Reg reg = fregFindFreeReg(RI); @@ -1607,10 +1609,9 @@ } case SystemCall: { unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); - Jit->Cleanup(); Jit->OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_SYSCALL)); Jit->MOV(32, M(&PC), Imm32(InstLoc + 4)); - Jit->JMP(((JitIL *)jit)->asm_routines.testExceptions, true); + Jit->WriteExceptionExit(); break; } case InterpreterBranch: { @@ -1627,14 +1628,46 @@ Jit->AND(32, R(EAX), Imm32(~mask)); Jit->AND(32, R(ECX), Imm32(mask)); Jit->OR(32, R(EAX), R(ECX)); - // MSR &= 0xFFFDFFFF; //TODO: VERIFY - Jit->AND(32, R(EAX), Imm32(0xFFFDFFFF)); + // MSR &= 0xFFFBFFFF; // Mask used to clear the bit MSR[13] + Jit->AND(32, R(EAX), Imm32(0xFFFBFFFF)); Jit->MOV(32, M(&MSR), R(EAX)); // NPC = SRR0; Jit->MOV(32, R(EAX), M(&SRR0)); Jit->WriteRfiExitDestInEAX(); break; } + case FPExceptionCheckStart: { + unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); + //This instruction uses FPU - needs to add FP exception bailout + Jit->TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); // Test FP enabled bit + FixupBranch b1 = Jit->J_CC(CC_NZ); + + // If a FPU exception occurs, the exception handler will read + // from PC. Update PC with the latest value in case that happens. + Jit->MOV(32, M(&PC), Imm32(InstLoc)); + Jit->SUB(32, M(&CoreTiming::downcount), Jit->js.downcountAmount > 127 ? Imm32(Jit->js.downcountAmount) : Imm8(Jit->js.downcountAmount)); + Jit->JMP(Jit->asm_routines.fpException, true); + Jit->SetJumpTarget(b1); + break; + } + case FPExceptionCheckEnd: { + unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); + Jit->TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI)); + FixupBranch noMemException = Jit->J_CC(CC_Z); + + // If a memory exception occurs, the exception handler will read + // from PC. Update PC with the latest value in case that happens. + Jit->MOV(32, M(&PC), Imm32(InstLoc)); + Jit->WriteExceptionExit(); + Jit->SetJumpTarget(noMemException); + break; + } + case ISIException: { + unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); + Jit->ABI_CallFunctionC(reinterpret_cast(&Memory::GenerateISIException_JIT), InstLoc); + Jit->WriteExceptionExit(); + break; + } case Int3: { Jit->INT3(); break; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -172,7 +172,11 @@ } else { - jo.enableBlocklink = true; // Speed boost, but not 100% safe + if (!Core::g_CoreStartupParameter.bJITBlockLinking) + jo.enableBlocklink = false; + else + // Speed boost, but not 100% safe + jo.enableBlocklink = !Core::g_CoreStartupParameter.bMMU; } #ifdef _M_X64 @@ -180,11 +184,12 @@ #else jo.enableFastMem = false; #endif - jo.assumeFPLoadFromMem = true; + jo.assumeFPLoadFromMem = Core::g_CoreStartupParameter.bUseFastMem; jo.fpAccurateFcmp = false; jo.optimizeGatherPipe = true; jo.fastInterrupts = false; jo.accurateSinglePrecision = false; + js.memcheck = Core::g_CoreStartupParameter.bMMU; trampolines.Init(); AllocCodeSpace(CODE_SIZE); @@ -251,15 +256,6 @@ // Yup, just don't do anything. } -void JitIL::NotifyBreakpoint(u32 em_address, bool set) -{ - int block_num = blocks.GetBlockNumberFromStartAddress(em_address); - if (block_num >= 0) - { - blocks.DestroyBlock(block_num, false); - } -} - static const bool ImHereDebug = false; static const bool ImHereLog = false; static std::map been_here; @@ -336,11 +332,10 @@ JMP(asm_routines.testExceptions, true); } -void JitIL::WriteExceptionExit(u32 exception) +void JitIL::WriteExceptionExit() { Cleanup(); - OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(exception)); - MOV(32, M(&PC), Imm32(js.compilerPC + 4)); + SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); JMP(asm_routines.testExceptions, true); } @@ -357,13 +352,13 @@ pExecAddr(); } -void JitIL::Trace(PPCAnalyst::CodeBuffer *code_buf, u32 em_address) +void JitIL::Trace() { char regs[500] = ""; char fregs[750] = ""; #ifdef JIT_LOG_GPR - for (unsigned int i = 0; i < 32; i++) + for (int i = 0; i < 32; i++) { char reg[50]; sprintf(reg, "r%02d: %08x ", i, PowerPC::ppcState.gpr[i]); @@ -372,18 +367,18 @@ #endif #ifdef JIT_LOG_FPR - for (unsigned int i = 0; i < 32; i++) + for (int i = 0; i < 32; i++) { char reg[50]; sprintf(reg, "f%02d: %016x ", i, riPS0(i)); strncat(fregs, reg, 750); } #endif - const PPCAnalyst::CodeOp &op = code_buf->codebuffer[0]; - char ppcInst[256]; - DisassembleGekko(op.inst.hex, em_address, ppcInst, 256); - - NOTICE_LOG(DYNA_REC, "JITIL PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs, op.inst.hex, ppcInst); + + NOTICE_LOG(DYNA_REC, "JITIL PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s", + PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], + PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, + PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs); } void STACKALIGN JitIL::Jit(u32 em_address) @@ -401,17 +396,37 @@ { int blockSize = code_buf->GetSize(); + // Memory exception on instruction fetch + bool memory_exception = false; + + // A broken block is a block that does not end in a branch + bool broken_block = false; + if (Core::g_CoreStartupParameter.bEnableDebugging) { // Comment out the following to disable breakpoints (speed-up) blockSize = 1; - Trace(code_buf, em_address); + Trace(); } if (em_address == 0) PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR); - int size; + if (Core::g_CoreStartupParameter.bMMU && + (em_address >> 28) != 0x0 && + (em_address >> 28) != 0x8 && + (em_address >> 28) != 0x9 && + (em_address >> 28) != 0xC && + (em_address >> 28) != 0xD) + { + if (!Memory::TranslateAddress(em_address, Memory::FLAG_OPCODE)) + { + // Memory exception occurred during instruction fetch + memory_exception = true; + } + } + + int size = 0; js.isLastInstruction = false; js.blockStart = em_address; js.fifoBytesThisBlock = 0; @@ -420,7 +435,12 @@ //Analyze the block, collect all instructions it is made of (including inlining, //if that is enabled), reorder instructions for optimal performance, and join joinable instructions. - b->exitAddress[0] = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, code_buf, blockSize); + b->exitAddress[0] = em_address; + if (!memory_exception) + { + // If there is a memory exception inside a block (broken_block==true), compile up to that instruction. + b->exitAddress[0] = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize); + } PPCAnalyst::CodeOp *ops = code_buf->codebuffer; const u8 *start = AlignCode4(); //TODO: Test if this or AlignCode16 make a difference from GetCodePtr @@ -456,8 +476,7 @@ ibuild.Reset(); - js.downcountAmount = js.st.numCycles; - + js.downcountAmount = 0; if (!Core::g_CoreStartupParameter.bEnableDebugging) js.downcountAmount += PatchEngine::GetSpeedhackCycles(em_address); @@ -467,6 +486,9 @@ js.compilerPC = ops[i].address; js.op = &ops[i]; js.instructionNumber = i; + const GekkoOPInfo *opinfo = GetOpInfo(ops[i].inst); + js.downcountAmount += (opinfo->numCyclesMinusOne + 1); + if (i == (int)size - 1) { js.isLastInstruction = true; @@ -481,10 +503,25 @@ if (!ops[i].skip) { + if (js.memcheck && (opinfo->flags & FL_USE_FPU)) + { + ibuild.EmitFPExceptionCheckStart(ibuild.EmitIntConst(ops[i].address)); + } + JitILTables::CompileInstruction(ops[i]); + + if (js.memcheck && (opinfo->flags & FL_LOADSTORE)) + { + ibuild.EmitFPExceptionCheckEnd(ibuild.EmitIntConst(ops[i].address)); + } } } + if (memory_exception) + { + ibuild.EmitISIException(ibuild.EmitIntConst(em_address)); + } + // Perform actual code generation WriteCode(); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h 2010-08-18 03:25:18.000000000 +0100 @@ -84,8 +84,7 @@ void Jit(u32 em_address); const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b); - void NotifyBreakpoint(u32 em_address, bool set); - void Trace(PPCAnalyst::CodeBuffer *code_buffer, u32 em_address); + void Trace(); void ClearCache(); const u8 *GetDispatcher() { @@ -112,7 +111,7 @@ void WriteExit(u32 destination, int exit_num); void WriteExitDestInEAX(int exit_num); - void WriteExceptionExit(u32 exception); + void WriteExceptionExit(); void WriteRfiExitDestInEAX(); void WriteCallInterpreter(UGeckoInstruction _inst); void Cleanup(); @@ -171,6 +170,7 @@ void mftb(UGeckoInstruction inst); void mtcrf(UGeckoInstruction inst); void mfcr(UGeckoInstruction inst); + void crXX(UGeckoInstruction inst); void reg_imm(UGeckoInstruction inst); @@ -205,6 +205,7 @@ void fsign(UGeckoInstruction inst); void stX(UGeckoInstruction inst); //stw sth stb void lXz(UGeckoInstruction inst); + void lbzu(UGeckoInstruction inst); void lha(UGeckoInstruction inst); void rlwinmx(UGeckoInstruction inst); void rlwimix(UGeckoInstruction inst); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Integer.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Integer.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Integer.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Integer.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -125,6 +125,7 @@ rhs = ibuild.EmitIntConst(inst.SIMM_16); res = ibuild.EmitICmpCRSigned(lhs, rhs); } + js.downcountAmount++; //TODO: should this be somewhere else? ibuild.EmitStoreCR(res, inst.CRFD); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -39,6 +39,7 @@ { INSTRUCTION_START JITDISABLE(LoadStore) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB); if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); @@ -50,7 +51,8 @@ void JitIL::lXz(UGeckoInstruction inst) { INSTRUCTION_START - JITDISABLE(LoadStore) + JITDISABLE(LoadStore) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16); if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); @@ -67,10 +69,21 @@ ibuild.EmitStoreGReg(val, inst.RD); } +void JitIL::lbzu(UGeckoInstruction inst) { + INSTRUCTION_START + JITDISABLE(LoadStore) + // FIXME: lbzu crashes GFZP01(F-Zero GX) @ 0x8008575C + const IREmitter::InstLoc uAddress = ibuild.EmitAdd(ibuild.EmitLoadGReg(inst.RA), ibuild.EmitIntConst((int)inst.SIMM_16)); + const IREmitter::InstLoc temp = ibuild.EmitLoad8(uAddress); + ibuild.EmitStoreGReg(temp, inst.RD); + ibuild.EmitStoreGReg(uAddress, inst.RA); +} + void JitIL::lha(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(LoadStore) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst((s32)(s16)inst.SIMM_16); if (inst.RA) @@ -84,6 +97,7 @@ { INSTRUCTION_START JITDISABLE(LoadStore) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB); if (inst.RA) { addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); @@ -131,6 +145,7 @@ { INSTRUCTION_START JITDISABLE(LoadStore) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), value = ibuild.EmitLoadGReg(inst.RS); if (inst.RA) @@ -150,6 +165,7 @@ { INSTRUCTION_START JITDISABLE(LoadStore) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB), value = ibuild.EmitLoadGReg(inst.RS); addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); @@ -169,6 +185,7 @@ { INSTRUCTION_START JITDISABLE(LoadStore) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16); if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); @@ -184,6 +201,7 @@ { INSTRUCTION_START JITDISABLE(LoadStore) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16); if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -43,6 +43,7 @@ { INSTRUCTION_START JITDISABLE(LoadStoreFloating) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val; if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); @@ -56,6 +57,7 @@ { INSTRUCTION_START JITDISABLE(LoadStoreFloating) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val; if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); @@ -70,6 +72,7 @@ { INSTRUCTION_START JITDISABLE(LoadStoreFloating) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val = ibuild.EmitLoadFReg(inst.RS); if (inst.RA) @@ -85,6 +88,7 @@ { INSTRUCTION_START JITDISABLE(LoadStoreFloating) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val = ibuild.EmitLoadFReg(inst.RS); if (inst.RA) @@ -101,6 +105,7 @@ { INSTRUCTION_START JITDISABLE(LoadStoreFloating) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB), val = ibuild.EmitLoadFReg(inst.RS); if (inst.RA) @@ -115,6 +120,7 @@ { INSTRUCTION_START JITDISABLE(LoadStoreFloating) + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB), val; if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -37,7 +37,7 @@ { INSTRUCTION_START JITDISABLE(LoadStorePaired) - if (inst.W) {Default(inst); return;} + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val; if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); @@ -45,20 +45,30 @@ ibuild.EmitStoreGReg(addr, inst.RA); val = ibuild.EmitLoadFReg(inst.RS); val = ibuild.EmitCompactMRegToPacked(val); - ibuild.EmitStorePaired(val, addr, inst.I); + if (inst.W == 0) { + ibuild.EmitStorePaired(val, addr, inst.I); + } else { + IREmitter::InstLoc addr4 = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4)); + IREmitter::InstLoc backup = ibuild.EmitLoad32(addr4); + ibuild.EmitStorePaired(val, addr, inst.I); + ibuild.EmitStore32(backup, addr4); + } } void JitIL::psq_l(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(LoadStorePaired) - if (inst.W) {Default(inst); return;} + if (js.memcheck) { Default(inst); return; } IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val; if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); if (inst.OPCD == 57) ibuild.EmitStoreGReg(addr, inst.RA); val = ibuild.EmitLoadPaired(addr, inst.I); + if (inst.W) { + val = ibuild.EmitFPMerge00(val, ibuild.EmitCFloatOne()); + } val = ibuild.EmitExpandPackedToMReg(val); ibuild.EmitStoreFReg(val, inst.RD); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -186,3 +186,76 @@ } #endif } + +void JitIL::crXX(UGeckoInstruction inst) +{ + // Ported from Jit_SystemRegister.cpp + + // Get bit CRBA in EAX aligned with bit CRBD + const int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3); + IREmitter::InstLoc eax = ibuild.EmitLoadCR(inst.CRBA >> 2); + if (shiftA < 0) + eax = ibuild.EmitShl(eax, ibuild.EmitIntConst(-shiftA)); + else if (shiftA > 0) + eax = ibuild.EmitShrl(eax, ibuild.EmitIntConst(shiftA)); + + // Get bit CRBB in ECX aligned with bit CRBD + const int shiftB = (inst.CRBD & 3) - (inst.CRBB & 3); + IREmitter::InstLoc ecx = ibuild.EmitLoadCR(inst.CRBB >> 2); + if (shiftB < 0) + ecx = ibuild.EmitShl(ecx, ibuild.EmitIntConst(-shiftB)); + else if (shiftB > 0) + ecx = ibuild.EmitShrl(ecx, ibuild.EmitIntConst(shiftB)); + + // Compute combined bit + const unsigned subop = inst.SUBOP10; + switch (subop) { + case 257: + // crand + eax = ibuild.EmitAnd(eax, ecx); + break; + case 129: + // crandc + ecx = ibuild.EmitXor(ecx, ibuild.EmitIntConst(-1U)); + eax = ibuild.EmitAnd(eax, ecx); + break; + case 289: + // creqv + eax = ibuild.EmitXor(eax, ecx); + eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(-1U)); + break; + case 225: + // crnand + eax = ibuild.EmitAnd(eax, ecx); + eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(-1U)); + break; + case 33: + // crnor + eax = ibuild.EmitOr(eax, ecx); + eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(-1U)); + break; + case 449: + // cror + eax = ibuild.EmitOr(eax, ecx); + break; + case 417: + // crorc + ecx = ibuild.EmitXor(ecx, ibuild.EmitIntConst(-1U)); + eax = ibuild.EmitOr(eax, ecx); + break; + case 193: + // crxor + eax = ibuild.EmitXor(eax, ecx); + break; + default: + PanicAlert("crXX: invalid instruction"); + break; + } + + // Store result bit in CRBD + eax = ibuild.EmitAnd(eax, ibuild.EmitIntConst(0x8 >> (inst.CRBD & 3))); + IREmitter::InstLoc bd = ibuild.EmitLoadCR(inst.CRBD >> 2); + bd = ibuild.EmitAnd(bd, ibuild.EmitIntConst(~(0x8 >> (inst.CRBD & 3)))); + bd = ibuild.EmitOr(bd, eax); + ibuild.EmitStoreCR(bd, inst.CRBD >> 2); +} diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -176,14 +176,14 @@ { {528, &JitIL::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, {16, &JitIL::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}}, - {257, &JitIL::Default}, //"crand", OPTYPE_CR, FL_EVIL}}, - {129, &JitIL::Default}, //"crandc", OPTYPE_CR, FL_EVIL}}, - {289, &JitIL::Default}, //"creqv", OPTYPE_CR, FL_EVIL}}, - {225, &JitIL::Default}, //"crnand", OPTYPE_CR, FL_EVIL}}, - {33, &JitIL::Default}, //"crnor", OPTYPE_CR, FL_EVIL}}, - {449, &JitIL::Default}, //"cror", OPTYPE_CR, FL_EVIL}}, - {417, &JitIL::Default}, //"crorc", OPTYPE_CR, FL_EVIL}}, - {193, &JitIL::Default}, //"crxor", OPTYPE_CR, FL_EVIL}}, + {257, &JitIL::crXX}, //"crand", OPTYPE_CR, FL_EVIL}}, + {129, &JitIL::crXX}, //"crandc", OPTYPE_CR, FL_EVIL}}, + {289, &JitIL::crXX}, //"creqv", OPTYPE_CR, FL_EVIL}}, + {225, &JitIL::crXX}, //"crnand", OPTYPE_CR, FL_EVIL}}, + {33, &JitIL::crXX}, //"crnor", OPTYPE_CR, FL_EVIL}}, + {449, &JitIL::crXX}, //"cror", OPTYPE_CR, FL_EVIL}}, + {417, &JitIL::crXX}, //"crorc", OPTYPE_CR, FL_EVIL}}, + {193, &JitIL::crXX}, //"crxor", OPTYPE_CR, FL_EVIL}}, {150, &JitIL::DoNothing}, //"isync", OPTYPE_ICACHE, FL_EVIL}}, {0, &JitIL::Default}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}}, diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h 2010-08-18 03:25:18.000000000 +0100 @@ -64,6 +64,8 @@ bool isLastInstruction; bool forceUnsafeLoad; + bool memcheck; + bool broken_block; int fifoBytesThisBlock; @@ -90,7 +92,6 @@ virtual void ClearCache() = 0; virtual void Run() = 0; virtual void SingleStep() = 0; - virtual void NotifyBreakpoint(u32 em_address, bool set) = 0; const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -127,7 +127,7 @@ // is full and when saving and loading states. void JitBlockCache::Clear() { - Core::DisplayMessage("Cleared code cache.", 3000); + Core::DisplayMessage("Clearing code cache.", 3000); for (int i = 0; i < num_blocks; i++) { DestroyBlock(i, false); @@ -135,7 +135,16 @@ links_to.clear(); block_map.clear(); num_blocks = 0; - memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS); + memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS); + } + + void JitBlockCache::ClearSafe() + { +#ifdef JIT_UNLIMITED_ICACHE + memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE); + memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE); + memset(iCacheVMEM, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE); +#endif } /*void JitBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag) @@ -360,7 +369,7 @@ } b.invalid = true; #ifdef JIT_UNLIMITED_ICACHE - Memory::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode); + Memory::Write_Opcode_JIT(b.originalAddress, b.originalFirstOpcode?b.originalFirstOpcode:JIT_ICACHE_INVALID_WORD); #else if (Memory::ReadFast32(b.originalAddress) == block_num) Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress); @@ -399,7 +408,7 @@ #ifdef JIT_UNLIMITED_ICACHE // invalidate iCache. - // icbi can be called with any address, so we sholud check + // icbi can be called with any address, so we should check if ((address & ~JIT_ICACHE_MASK) != 0x80000000 && (address & ~JIT_ICACHE_MASK) != 0x00000000 && (address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area (address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (address & ~JIT_ICACHEEX_MASK) != 0x10000000) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.h 2010-08-18 03:25:18.000000000 +0100 @@ -91,11 +91,15 @@ public: JitBlockCache() : blockCodePointers(0), blocks(0), num_blocks(0), - iCache(0), iCacheEx(0), iCacheVMEM(0), MAX_NUM_BLOCKS(0) { } +#ifdef JIT_UNLIMITED_ICACHE + iCache(0), iCacheEx(0), iCacheVMEM(0), +#endif + MAX_NUM_BLOCKS(0) { } int AllocateBlock(u32 em_address); void FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr); void Clear(); + void ClearSafe(); void Init(); void Shutdown(); void Reset(); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -31,15 +31,8 @@ using namespace Gen; -void EmuCodeBlock::JitClearCA() -{ - AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~XER_CA_MASK)); //XER.CA = 0 -} - -void EmuCodeBlock::JitSetCA() -{ - OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_CA_MASK)); //XER.CA = 1 -} +static const u8 GC_ALIGNED16(pbswapShuffle1x4[16]) = {3, 2, 1, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; +static u32 GC_ALIGNED16(float_buffer); void EmuCodeBlock::UnsafeLoadRegToReg(X64Reg reg_addr, X64Reg reg_value, int accessSize, s32 offset, bool signExtend) { @@ -60,7 +53,9 @@ SAR(32, R(reg_value), Imm8(16)); else SHR(32, R(reg_value), Imm8(16)); - } else if (signExtend) { + } + else if (signExtend) + { // TODO: bake 8-bit into the original load. MOVSX(32, accessSize, reg_value, R(reg_value)); } @@ -76,26 +71,45 @@ #endif } -void EmuCodeBlock::SafeLoadRegToEAX(X64Reg reg, int accessSize, s32 offset, bool signExtend) +void EmuCodeBlock::SafeLoadRegToEAX(X64Reg reg_addr, int accessSize, s32 offset, bool signExtend) { - if (offset) - ADD(32, R(reg), Imm32((u32)offset)); - TEST(32, R(reg), Imm32(0x0C000000)); - FixupBranch argh = J_CC(CC_Z); - switch (accessSize) + if (Core::g_CoreStartupParameter.bUseFastMem && (accessSize == 32 || accessSize == 8) && !Core::g_CoreStartupParameter.bMMU) + { + // FIXME: accessSize == 16 does not work. Breaks mkdd + UnsafeLoadRegToReg(reg_addr, EAX, accessSize, offset, signExtend); + } + else { - case 32: ABI_CallFunctionR(thunks.ProtectFunction((void *)&Memory::Read_U32, 1), reg); break; - case 16: ABI_CallFunctionR(thunks.ProtectFunction((void *)&Memory::Read_U16_ZX, 1), reg); break; - case 8: ABI_CallFunctionR(thunks.ProtectFunction((void *)&Memory::Read_U8_ZX, 1), reg); break; - } - if (signExtend && accessSize < 32) { - // Need to sign extend values coming from the Read_U* functions. - MOVSX(32, accessSize, EAX, R(EAX)); - } - FixupBranch arg2 = J(); - SetJumpTarget(argh); - UnsafeLoadRegToReg(reg, EAX, accessSize, 0, signExtend); - SetJumpTarget(arg2); + if (offset) + ADD(32, R(reg_addr), Imm32((u32)offset)); + + u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS; + + if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.iTLBHack) + { + mem_mask |= Memory::ADDR_MASK_MEM1; + } + + TEST(32, R(reg_addr), Imm32(mem_mask)); + FixupBranch fast = J_CC(CC_Z); + + switch (accessSize) + { + case 32: ABI_CallFunctionR(thunks.ProtectFunction((void *)&Memory::Read_U32, 1), reg_addr); break; + case 16: ABI_CallFunctionR(thunks.ProtectFunction((void *)&Memory::Read_U16_ZX, 1), reg_addr); break; + case 8: ABI_CallFunctionR(thunks.ProtectFunction((void *)&Memory::Read_U8_ZX, 1), reg_addr); break; + } + if (signExtend && accessSize < 32) + { + // Need to sign extend values coming from the Read_U* functions. + MOVSX(32, accessSize, EAX, R(EAX)); + } + + FixupBranch exit = J(); + SetJumpTarget(fast); + UnsafeLoadRegToReg(reg_addr, EAX, accessSize, 0, signExtend); + SetJumpTarget(exit); + } } void EmuCodeBlock::UnsafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int accessSize, s32 offset, bool swap) @@ -116,27 +130,40 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int accessSize, s32 offset, bool swap) { if (offset) - ADD(32, R(reg_addr), Imm32(offset)); - TEST(32, R(reg_addr), Imm32(0x0C000000)); - FixupBranch argh = J_CC(CC_Z); + ADD(32, R(reg_addr), Imm32((u32)offset)); + + u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS; + + if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.iTLBHack) + { + mem_mask |= Memory::ADDR_MASK_MEM1; + } + + TEST(32, R(reg_addr), Imm32(mem_mask)); + FixupBranch fast = J_CC(CC_Z); + switch (accessSize) { case 32: ABI_CallFunctionRR(thunks.ProtectFunction(swap ? ((void *)&Memory::Write_U32) : ((void *)&Memory::Write_U32_Swap), 2), reg_value, reg_addr); break; case 16: ABI_CallFunctionRR(thunks.ProtectFunction(swap ? ((void *)&Memory::Write_U16) : ((void *)&Memory::Write_U16_Swap), 2), reg_value, reg_addr); break; case 8: ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U8, 2), reg_value, reg_addr); break; } - FixupBranch arg2 = J(); - SetJumpTarget(argh); + FixupBranch exit = J(); + SetJumpTarget(fast); UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, 0, swap); - SetJumpTarget(arg2); + SetJumpTarget(exit); } -static const u8 GC_ALIGNED16(pbswapShuffle1x4[16]) = {3, 2, 1, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; -static u32 GC_ALIGNED16(float_buffer); - void EmuCodeBlock::SafeWriteFloatToReg(X64Reg xmm_value, X64Reg reg_addr) { - TEST(32, R(reg_addr), Imm32(0x0C000000)); + u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS; + + if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.iTLBHack) + { + mem_mask |= Memory::ADDR_MASK_MEM1; + } + + TEST(32, R(reg_addr), Imm32(mem_mask)); if (false && cpu_info.bSSSE3) { // This path should be faster but for some reason it causes errors so I've disabled it. FixupBranch argh = J_CC(CC_Z); @@ -147,12 +174,12 @@ FixupBranch arg2 = J(); SetJumpTarget(argh); PSHUFB(xmm_value, M((void *)pbswapShuffle1x4)); - #ifdef _M_IX86 +#ifdef _M_IX86 AND(32, R(reg_addr), Imm32(Memory::MEMVIEW32_MASK)); MOVD_xmm(MDisp(reg_addr, (u32)Memory::base), xmm_value); - #else +#else MOVD_xmm(MComplex(RBX, reg_addr, SCALE_1, 0), xmm_value); - #endif +#endif SetJumpTarget(arg2); } else { MOVSS(M(&float_buffer), xmm_value); @@ -197,3 +224,13 @@ CVTPS2PD(xmm, R(xmm)); } } + +void EmuCodeBlock::JitClearCA() +{ + AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~XER_CA_MASK)); //XER.CA = 0 +} + +void EmuCodeBlock::JitSetCA() +{ + OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_CA_MASK)); //XER.CA = 1 +} diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PowerPC.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PowerPC.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PowerPC.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PowerPC.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -267,7 +267,6 @@ { SRR0 = NPC; //GenerateISIException() sets up SRR1 - SRR1 |= MSR & 0x87C0FFFF; MSR |= (MSR >> 17) & 1; MSR &= ~0x04EF36; NPC = 0x80000400; @@ -306,6 +305,10 @@ SRR1 = MSR & 0x87C0FFFF; MSR |= (MSR >> 17) & 1; MSR &= ~0x04EF36; + // TODO: Verify whether the code below is correct + //SRR1 = MSR & 0x0000FFFF; + //MSR |= (MSR >> 16) & 1; + //MSR &= ~0x04EF32; NPC = 0x80000800; INFO_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE"); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PowerPC.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PowerPC.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PowerPC.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PowerPC.h 2010-08-18 03:25:18.000000000 +0100 @@ -66,11 +66,14 @@ // also for power management, but we don't care about that. u32 spr[1024]; - u32 tlb_last; - u32 tlb_va[16]; - u32 tlb_pa[16]; + u32 dtlb_last; + u32 dtlb_va[128]; + u32 dtlb_pa[128]; + + u32 itlb_last; + u32 itlb_va[128]; + u32 itlb_pa[128]; - InstructionCache iCache; }; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -285,7 +285,7 @@ // Does not yet perform inlining - although there are plans for that. // Returns the exit address of the next PC -u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa, BlockRegStats *fpa, CodeBuffer *buffer, int blockSize) +u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa, BlockRegStats *fpa, bool &broken_block, CodeBuffer *buffer, int blockSize) { memset(st, 0, sizeof(st)); @@ -296,6 +296,7 @@ gpa->any = true; fpa->any = false; + for (int i = 0; i < 32; i++) { gpa->firstRead[i] = -1; @@ -317,161 +318,162 @@ // Do analysis of the code, look for dependencies etc int numSystemInstructions = 0; for (int i = 0; i < maxsize; i++) - { - num_inst++; - memset(&code[i], 0, sizeof(CodeOp)); - code[i].address = address; - - UGeckoInstruction inst = Memory::Read_Opcode_JIT(code[i].address); - - _assert_msg_(POWERPC, inst.hex != 0, "Zero Op - Error flattening %08x op %08x", address + i*4, inst.hex); - code[i].inst = inst; - code[i].branchTo = -1; - code[i].branchToIndex = -1; - code[i].skip = false; - GekkoOPInfo *opinfo = GetOpInfo(inst); - code[i].opinfo = opinfo; - if (opinfo) + { + UGeckoInstruction inst = Memory::Read_Opcode_JIT(address); + if (inst.hex != 0) + { + num_inst++; + memset(&code[i], 0, sizeof(CodeOp)); + GekkoOPInfo *opinfo = GetOpInfo(inst); + code[i].opinfo = opinfo; + code[i].address = address; + code[i].inst = inst; + code[i].branchTo = -1; + code[i].branchToIndex = -1; + code[i].skip = false; numCycles += opinfo->numCyclesMinusOne + 1; - _assert_msg_(POWERPC, opinfo != 0, "Invalid Op - Error flattening %08x op %08x", address + i*4, inst.hex); - - code[i].wantsCR0 = false; - code[i].wantsCR1 = false; - code[i].wantsPS1 = false; - - int flags = opinfo->flags; - - if (flags & FL_USE_FPU) - fpa->any = true; - if (flags & FL_TIMER) - gpa->anyTimer = true; - - // Does the instruction output CR0? - if (flags & FL_RC_BIT) - code[i].outputCR0 = inst.hex & 1; //todo fix - else if ((flags & FL_SET_CRn) && inst.CRFD == 0) - code[i].outputCR0 = true; - else - code[i].outputCR0 = (flags & FL_SET_CR0) ? true : false; + code[i].wantsCR0 = false; + code[i].wantsCR1 = false; + code[i].wantsPS1 = false; + + int flags = opinfo->flags; + + if (flags & FL_USE_FPU) + fpa->any = true; + + if (flags & FL_TIMER) + gpa->anyTimer = true; + + // Does the instruction output CR0? + if (flags & FL_RC_BIT) + code[i].outputCR0 = inst.hex & 1; //todo fix + else if ((flags & FL_SET_CRn) && inst.CRFD == 0) + code[i].outputCR0 = true; + else + code[i].outputCR0 = (flags & FL_SET_CR0) ? true : false; - // Does the instruction output CR1? - if (flags & FL_RC_BIT_F) - code[i].outputCR1 = inst.hex & 1; //todo fix - else if ((flags & FL_SET_CRn) && inst.CRFD == 1) - code[i].outputCR1 = true; - else - code[i].outputCR1 = (flags & FL_SET_CR1) ? true : false; + // Does the instruction output CR1? + if (flags & FL_RC_BIT_F) + code[i].outputCR1 = inst.hex & 1; //todo fix + else if ((flags & FL_SET_CRn) && inst.CRFD == 1) + code[i].outputCR1 = true; + else + code[i].outputCR1 = (flags & FL_SET_CR1) ? true : false; - int numOut = 0; - int numIn = 0; - if (flags & FL_OUT_A) - { - code[i].regsOut[numOut++] = inst.RA; - gpa->SetOutputRegister(inst.RA, i); - } - if (flags & FL_OUT_D) - { - code[i].regsOut[numOut++] = inst.RD; - gpa->SetOutputRegister(inst.RD, i); - } - if (flags & FL_OUT_S) - { - code[i].regsOut[numOut++] = inst.RS; - gpa->SetOutputRegister(inst.RS, i); - } - if ((flags & FL_IN_A) || ((flags & FL_IN_A0) && inst.RA != 0)) - { - code[i].regsIn[numIn++] = inst.RA; - gpa->SetInputRegister(inst.RA, i); - } - if (flags & FL_IN_B) - { - code[i].regsIn[numIn++] = inst.RB; - gpa->SetInputRegister(inst.RB, i); - } - if (flags & FL_IN_C) - { - code[i].regsIn[numIn++] = inst.RC; - gpa->SetInputRegister(inst.RC, i); - } - if (flags & FL_IN_S) - { - code[i].regsIn[numIn++] = inst.RS; - gpa->SetInputRegister(inst.RS, i); - } + int numOut = 0; + int numIn = 0; + if (flags & FL_OUT_A) + { + code[i].regsOut[numOut++] = inst.RA; + gpa->SetOutputRegister(inst.RA, i); + } + if (flags & FL_OUT_D) + { + code[i].regsOut[numOut++] = inst.RD; + gpa->SetOutputRegister(inst.RD, i); + } + if (flags & FL_OUT_S) + { + code[i].regsOut[numOut++] = inst.RS; + gpa->SetOutputRegister(inst.RS, i); + } + if ((flags & FL_IN_A) || ((flags & FL_IN_A0) && inst.RA != 0)) + { + code[i].regsIn[numIn++] = inst.RA; + gpa->SetInputRegister(inst.RA, i); + } + if (flags & FL_IN_B) + { + code[i].regsIn[numIn++] = inst.RB; + gpa->SetInputRegister(inst.RB, i); + } + if (flags & FL_IN_C) + { + code[i].regsIn[numIn++] = inst.RC; + gpa->SetInputRegister(inst.RC, i); + } + if (flags & FL_IN_S) + { + code[i].regsIn[numIn++] = inst.RS; + gpa->SetInputRegister(inst.RS, i); + } - // Set remaining register slots as unused (-1) - for (int j = numIn; j < 3; j++) - code[i].regsIn[j] = -1; - for (int j = numOut; j < 2; j++) - code[i].regsOut[j] = -1; - for (int j = 0; j < 3; j++) - code[i].fregsIn[j] = -1; - code[i].fregOut = -1; + // Set remaining register slots as unused (-1) + for (int j = numIn; j < 3; j++) + code[i].regsIn[j] = -1; + for (int j = numOut; j < 2; j++) + code[i].regsOut[j] = -1; + for (int j = 0; j < 3; j++) + code[i].fregsIn[j] = -1; + code[i].fregOut = -1; - switch (opinfo->type) - { - case OPTYPE_INTEGER: - case OPTYPE_LOAD: - case OPTYPE_STORE: - break; - case OPTYPE_FPU: - break; - case OPTYPE_LOADFP: - break; - case OPTYPE_BRANCH: - if (code[i].inst.hex == 0x4e800020) + switch (opinfo->type) { - // For analysis purposes, we can assume that blr eats flags. - code[i].outputCR0 = true; - code[i].outputCR1 = true; + case OPTYPE_INTEGER: + case OPTYPE_LOAD: + case OPTYPE_STORE: + case OPTYPE_LOADFP: + case OPTYPE_STOREFP: + break; + case OPTYPE_FPU: + break; + case OPTYPE_BRANCH: + if (code[i].inst.hex == 0x4e800020) + { + // For analysis purposes, we can assume that blr eats flags. + code[i].outputCR0 = true; + code[i].outputCR1 = true; + } + break; + case OPTYPE_SYSTEM: + case OPTYPE_SYSTEMFP: + numSystemInstructions++; + break; } - break; - case OPTYPE_SYSTEM: - case OPTYPE_SYSTEMFP: - numSystemInstructions++; - break; - } - bool follow = false; - u32 destination; - if (inst.OPCD == 18 && blockSize > 1) - { - //Is bx - should we inline? yes! - if (inst.AA) - destination = SignExt26(inst.LI << 2); - else - destination = address + SignExt26(inst.LI << 2); - if (destination != blockstart) - follow = true; - } - if (follow) - numFollows++; - if (numFollows > 1) + bool follow = false; + u32 destination; + if (inst.OPCD == 18 && blockSize > 1) + { + //Is bx - should we inline? yes! + if (inst.AA) + destination = SignExt26(inst.LI << 2); + else + destination = address + SignExt26(inst.LI << 2); + if (destination != blockstart) + follow = true; + } + if (follow) + numFollows++; + if (numFollows > 1) + follow = false; follow = false; - follow = false; - if (!follow) - { - if (opinfo->flags & FL_ENDBLOCK) //right now we stop early + if (!follow) { - foundExit = true; - break; + if (opinfo->flags & FL_ENDBLOCK) //right now we stop early + { + foundExit = true; + break; + } + address += 4; + } + else + { + code[i].skip = true; + address = destination; } - address += 4; } else { - code[i].skip = true; - address = destination; + // Memory exception occurred + break; } - } - if (!foundExit && blockSize > 1) - NOTICE_LOG(POWERPC, "Analyzer ERROR - Function %08x too big, size is 0x%08x", blockstart, address-blockstart); + } st->numCycles = numCycles; // Instruction Reordering Pass - if (blockSize > 1) + if (num_inst > 1) { // Bubble down compares towards branches, so that they can be merged. // -2: -1 for the pair, -1 for not swapping with the final instruction which is probably the branch. @@ -493,6 +495,13 @@ } } } + + if (!foundExit && num_inst > 0) + { + // A broken block is a block that does not end in a branch + broken_block = true; + } + // Scan for CR0 dependency // assume next block wants CR0 to be safe bool wantsCR0 = true; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PPCAnalyst.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PPCAnalyst.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PPCAnalyst.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PPCAnalyst.h 2010-08-18 03:25:18.000000000 +0100 @@ -108,7 +108,7 @@ }; -u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa, BlockRegStats *fpa, CodeBuffer *buffer, int blockSize); +u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa, BlockRegStats *fpa, bool &broken_block, CodeBuffer *buffer, int blockSize); void LogFunctionCall(u32 addr); void FindFunctions(u32 startAddr, u32 endAddr, PPCSymbolDB *func_db); bool AnalyzeFunction(u32 startAddr, Symbol &func, int max_size = 0); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PPCCache.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PPCCache.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PPCCache.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PPCCache.cpp 2010-08-18 03:25:18.000000000 +0100 @@ -18,12 +18,14 @@ #include "PPCCache.h" #include "../HW/Memmap.h" #include "PowerPC.h" +#include "JitCommon/JitBase.h" +#include "JitCommon/JitCache.h" namespace PowerPC { - u32 plru_mask[8] = {11,11,19,19,37,37,69,69}; - u32 plru_value[8] = {11,3,17,1,36,4,64,0}; + const u32 plru_mask[8] = {11,11,19,19,37,37,69,69}; + const u32 plru_value[8] = {11,3,17,1,36,4,64,0}; InstructionCache::InstructionCache() { @@ -74,10 +76,14 @@ memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex)); memset(lookup_table_vmem, 0xff, sizeof(lookup_table_vmem)); #endif + if (jit) + jit->GetBlockCache()->ClearSafe(); } void InstructionCache::Invalidate(u32 addr) { + if (jit) + jit->GetBlockCache()->InvalidateICache(addr); if (!HID0.ICE) return; // invalidates the whole set @@ -99,7 +105,7 @@ u32 InstructionCache::ReadInstruction(u32 addr) { - if (!HID0.ICE) // instuction cache is disabled + if (!HID0.ICE) // instruction cache is disabled return Memory::ReadUnchecked_U32(addr); u32 set = (addr >> 5) & 0x7f; u32 tag = addr >> 12; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PPCTables.h dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PPCTables.h --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/PowerPC/PPCTables.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/PowerPC/PPCTables.h 2010-08-18 03:25:18.000000000 +0100 @@ -49,6 +49,7 @@ FL_CHECKEXCEPTIONS = (1<<16), FL_EVIL = (1<<17), FL_USE_FPU = (1<<18), + FL_LOADSTORE = (1<<19), }; enum diff -Nru dolphin-emu-2.0+svn5985/Source/Core/Core/Src/State.cpp dolphin-emu-2.0+svn6107/Source/Core/Core/Src/State.cpp --- dolphin-emu-2.0+svn5985/Source/Core/Core/Src/State.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/Core/Src/State.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -71,7 +71,7 @@ // Don't forget to increase this after doing changes on the savestate system -#define STATE_VERSION 2 +#define STATE_VERSION 3 void DoState(PointerWrap &p) @@ -93,16 +93,6 @@ PowerPC::DoState(p); HW::DoState(p); CoreTiming::DoState(p); - - // TODO: it's a GIGANTIC waste of time and space to savestate the following - // (adds 128MB of mostly-empty cache data to every savestate). - // it seems to be unnecessary as far as I can tell, - // but I can't prove it is yet so I'll leave it here for now... -#ifdef JIT_UNLIMITED_ICACHE - p.DoVoid(jit->GetBlockCache()->GetICache(), JIT_ICACHE_SIZE); - p.DoVoid(jit->GetBlockCache()->GetICacheEx(), JIT_ICACHEEX_SIZE); - p.DoVoid(jit->GetBlockCache()->GetICacheVMEM(), JIT_ICACHE_SIZE); -#endif } void LoadBufferStateCallback(u64 userdata, int cyclesLate) @@ -112,8 +102,6 @@ return; } - jit->ClearCache(); - u8 *ptr = *cur_buffer; PointerWrap p(&ptr, PointerWrap::MODE_READ); DoState(p); @@ -129,8 +117,6 @@ return; } - jit->ClearCache(); - u8 *ptr = NULL; PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); @@ -163,8 +149,6 @@ return; } - jit->ClearCache(); - u8 *ptr = *cur_buffer; PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); DoState(p); @@ -248,9 +232,13 @@ void SaveStateCallback(u64 userdata, int cyclesLate) { - State_Flush(); + // Stop the clock while we save the state + PowerPC::Pause(); + + // Wait for the other threaded sub-systems to stop too + SLEEP(100); - jit->ClearCache(); + State_Flush(); // Measure the size of the buffer. u8 *ptr = 0; @@ -271,12 +259,21 @@ Core::DisplayMessage("Saving State...", 1000); saveThread = new Common::Thread(CompressAndDumpState, saveData); + + // Resume the clock + PowerPC::Start(); } void LoadStateCallback(u64 userdata, int cyclesLate) { bool bCompressedState; + // Stop the clock while we load the state + PowerPC::Pause(); + + // Wait for the other threaded sub-systems to stop too + SLEEP(100); + State_Flush(); // Save temp buffer for undo load state @@ -362,8 +359,6 @@ fclose(f); - jit->ClearCache(); - u8 *ptr = buffer; PointerWrap p(&ptr, PointerWrap::MODE_READ); DoState(p); @@ -374,6 +369,11 @@ Core::DisplayMessage("Unable to Load : Can't load state from other revisions !", 4000); delete[] buffer; + + state_op_in_progress = false; + + // Resume the clock + PowerPC::Start(); } void VerifyStateCallback(u64 userdata, int cyclesLate) @@ -456,8 +456,6 @@ fclose(f); - jit->ClearCache(); - u8 *ptr = buffer; PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); DoState(p); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DebuggerUICommon/Src/CodeView.cpp dolphin-emu-2.0+svn6107/Source/Core/DebuggerUICommon/Src/CodeView.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DebuggerUICommon/Src/CodeView.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DebuggerUICommon/Src/CodeView.cpp 2010-08-18 03:25:19.000000000 +0100 @@ -123,15 +123,21 @@ } else { - debugger->toggleBreakpoint(YToAddress(y)); - redraw(); - Host_UpdateBreakPointView(); + ToggleBreakpoint(YToAddress(y)); } event.Skip(true); } +void CCodeView::ToggleBreakpoint(u32 address) +{ + debugger->toggleBreakpoint(address); + redraw(); + Host_UpdateBreakPointView(); +} + + void CCodeView::OnMouseMove(wxMouseEvent& event) { wxRect rc = GetClientRect(); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DebuggerUICommon/Src/CodeView.h dolphin-emu-2.0+svn6107/Source/Core/DebuggerUICommon/Src/CodeView.h --- dolphin-emu-2.0+svn5985/Source/Core/DebuggerUICommon/Src/CodeView.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DebuggerUICommon/Src/CodeView.h 2010-08-18 03:25:19.000000000 +0100 @@ -47,6 +47,7 @@ void InsertBlrNop(int); u32 GetSelection() {return(selection);} + void ToggleBreakpoint(u32 address); struct BlrStruct // for IDM_INSERTBLR { diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.h dolphin-emu-2.0+svn6107/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.h --- dolphin-emu-2.0+svn5985/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.h 2010-08-18 03:25:19.000000000 +0100 @@ -20,17 +20,6 @@ #include -#define wxUSE_XPM_IN_MSW 1 -#define USE_XPM_BITMAPS 1 - -// Defined in CodeWindow.cpp extern wxFont DebuggerFont; -// define this to use XPMs everywhere (by default, BMPs are used under Win) -// BMPs use less space, but aren't compiled into the executable on other platforms - -#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW -#error You need to enable XPM support to use XPM bitmaps with toolbar! -#endif // USE_XPM_BITMAPS - #endif diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DebuggerWX/Src/CodeWindow.cpp dolphin-emu-2.0+svn6107/Source/Core/DebuggerWX/Src/CodeWindow.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DebuggerWX/Src/CodeWindow.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DebuggerWX/Src/CodeWindow.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -116,6 +116,7 @@ // Toolbar EVT_MENU(IDM_STEP, CCodeWindow::OnCodeStep) EVT_MENU(IDM_STEPOVER, CCodeWindow::OnCodeStep) + EVT_MENU(IDM_TOGGLE_BREAKPOINT, CCodeWindow::OnCodeStep) EVT_MENU(IDM_SKIP, CCodeWindow::OnCodeStep) EVT_MENU(IDM_SETPC, CCodeWindow::OnCodeStep) EVT_MENU(IDM_GOTOPC, CCodeWindow::OnCodeStep) @@ -167,9 +168,10 @@ void CCodeWindow::OnKeyDown(wxKeyEvent& event) { - event.Skip(); - - if ((event.GetKeyCode() == WXK_SPACE) && Parent->IsActive()) SingleCPUStep(); + if (event.GetKeyCode() == WXK_SPACE && event.GetModifiers() == wxMOD_NONE) + SingleStep(); + else + event.Skip(); } void CCodeWindow::OnHostMessage(wxCommandEvent& event) @@ -199,13 +201,17 @@ switch (event.GetId()) { case IDM_STEP: - SingleCPUStep(); + SingleStep(); break; case IDM_STEPOVER: - CCPU::EnableStepping(true); // TODO: Huh? + StepOver(); break; + case IDM_TOGGLE_BREAKPOINT: + ToggleBreakpoint(); + break; + case IDM_SKIP: PC += 4; Update(); @@ -289,14 +295,47 @@ } } -void CCodeWindow::SingleCPUStep() +void CCodeWindow::SingleStep() { - CCPU::StepOpcode(&sync_event); - wxThread::Sleep(20); - // need a short wait here - JumpToAddress(PC); - Update(); - Host_UpdateLogDisplay(); + if (CCPU::IsStepping()) + { + CCPU::StepOpcode(&sync_event); + wxThread::Sleep(20); + // need a short wait here + JumpToAddress(PC); + Update(); + Host_UpdateLogDisplay(); + } +} + +void CCodeWindow::StepOver() +{ + if (CCPU::IsStepping()) + { + UGeckoInstruction inst = Memory::Read_Instruction(PC); + if (inst.LK) + { + PowerPC::breakpoints.Add(PC + 4, true); + CCPU::EnableStepping(false); + JumpToAddress(PC); + Update(); + } + else + SingleStep(); + + UpdateButtonStates(); + // Update all toolbars in the aui manager + Parent->UpdateGUI(); + } +} + +void CCodeWindow::ToggleBreakpoint() +{ + if (CCPU::IsStepping()) + { + if (codeview) codeview->ToggleBreakpoint(codeview->GetSelection()); + Update(); + } } void CCodeWindow::UpdateLists() @@ -398,11 +437,11 @@ interpreter->Check(_LocalCoreStartupParameter.iCPUCore == 0); pCoreMenu->AppendSeparator(); - jitblocklinking = pCoreMenu->Append(IDM_JITBLOCKLINKING, _T("&JIT Block Linking off"), + pCoreMenu->Append(IDM_JITBLOCKLINKING, _T("&JIT Block Linking off"), _T("Provide safer execution by not linking the JIT blocks."), wxITEM_CHECK); - jitnoblockcache = pCoreMenu->Append(IDM_JITNOBLOCKCACHE, _T("&Disable JIT Cache"), + pCoreMenu->Append(IDM_JITNOBLOCKCACHE, _T("&Disable JIT Cache"), _T("Avoid any involuntary JIT cache clearing, this may prevent Zelda TP from crashing.") _T(" [This option must be selected before a game is started.]"), wxITEM_CHECK); @@ -413,32 +452,42 @@ pCoreMenu->Append(IDM_SEARCHINSTRUCTION, _T("&Search for an op")); pCoreMenu->AppendSeparator(); - jitoff = pCoreMenu->Append(IDM_JITOFF, _T("&JIT off (JIT core)"), + pCoreMenu->Append(IDM_JITOFF, _T("&JIT off (JIT core)"), _T("Turn off all JIT functions, but still use the JIT core from Jit.cpp"), wxITEM_CHECK); - jitlsoff = pCoreMenu->Append(IDM_JITLSOFF, _T("&JIT LoadStore off"), + pCoreMenu->Append(IDM_JITLSOFF, _T("&JIT LoadStore off"), wxEmptyString, wxITEM_CHECK); - jitlslbzxoff = pCoreMenu->Append(IDM_JITLSLBZXOFF, _T(" &JIT LoadStore lbzx off"), + pCoreMenu->Append(IDM_JITLSLBZXOFF, _T(" &JIT LoadStore lbzx off"), wxEmptyString, wxITEM_CHECK); - jitlslxzoff = pCoreMenu->Append(IDM_JITLSLXZOFF, _T(" &JIT LoadStore lXz off"), + pCoreMenu->Append(IDM_JITLSLXZOFF, _T(" &JIT LoadStore lXz off"), wxEmptyString, wxITEM_CHECK); - jitlslwzoff = pCoreMenu->Append(IDM_JITLSLWZOFF, _T(" &JIT LoadStore lwz off"), + pCoreMenu->Append(IDM_JITLSLWZOFF, _T(" &JIT LoadStore lwz off"), wxEmptyString, wxITEM_CHECK); - jitlspoff = pCoreMenu->Append(IDM_JITLSFOFF, _T("&JIT LoadStore Floating off"), + pCoreMenu->Append(IDM_JITLSFOFF, _T("&JIT LoadStore Floating off"), wxEmptyString, wxITEM_CHECK); - jitlsfoff = pCoreMenu->Append(IDM_JITLSPOFF, _T("&JIT LoadStore Paired off"), + pCoreMenu->Append(IDM_JITLSPOFF, _T("&JIT LoadStore Paired off"), wxEmptyString, wxITEM_CHECK); - jitfpoff = pCoreMenu->Append(IDM_JITFPOFF, _T("&JIT FloatingPoint off"), + pCoreMenu->Append(IDM_JITFPOFF, _T("&JIT FloatingPoint off"), wxEmptyString, wxITEM_CHECK); - jitioff = pCoreMenu->Append(IDM_JITIOFF, _T("&JIT Integer off"), + pCoreMenu->Append(IDM_JITIOFF, _T("&JIT Integer off"), wxEmptyString, wxITEM_CHECK); - jitpoff = pCoreMenu->Append(IDM_JITPOFF, _T("&JIT Paired off"), + pCoreMenu->Append(IDM_JITPOFF, _T("&JIT Paired off"), wxEmptyString, wxITEM_CHECK); - jitsroff = pCoreMenu->Append(IDM_JITSROFF, _T("&JIT SystemRegisters off"), + pCoreMenu->Append(IDM_JITSROFF, _T("&JIT SystemRegisters off"), wxEmptyString, wxITEM_CHECK); pMenuBar->Append(pCoreMenu, _T("&JIT")); + + // Debug Menu + wxMenu* pDebugMenu = new wxMenu; + + pDebugMenu->Append(IDM_STEP, _T("Step &Into\tF11")); + pDebugMenu->Append(IDM_STEPOVER, _T("Step &Over\tF10")); + pDebugMenu->Append(IDM_TOGGLE_BREAKPOINT, _T("Toggle &Breakpoint\tF9")); + + pMenuBar->Append(pDebugMenu, _T("&Debug")); + CreateMenuSymbols(pMenuBar); } @@ -511,7 +560,10 @@ } // Clear the JIT cache to enable these changes - jit->ClearCache(); + if (jit) + { + jit->ClearCache(); + } // Update UpdateButtonStates(); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DebuggerWX/Src/CodeWindowFunctions.cpp dolphin-emu-2.0+svn6107/Source/Core/DebuggerWX/Src/CodeWindowFunctions.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DebuggerWX/Src/CodeWindowFunctions.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DebuggerWX/Src/CodeWindowFunctions.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -560,7 +560,6 @@ if (Win) { Parent->DoRemovePage(Win, false); - Win->Close(); Win->Destroy(); } } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DebuggerWX/Src/CodeWindow.h dolphin-emu-2.0+svn6107/Source/Core/DebuggerWX/Src/CodeWindow.h --- dolphin-emu-2.0+svn5985/Source/Core/DebuggerWX/Src/CodeWindow.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DebuggerWX/Src/CodeWindow.h 2010-08-18 03:25:21.000000000 +0100 @@ -129,9 +129,13 @@ void OnCallersListChange(wxCommandEvent& event); void OnCallsListChange(wxCommandEvent& event); void OnCodeViewChange(wxCommandEvent &event); - void SingleCPUStep(); void OnHostMessage(wxCommandEvent& event); + // Debugger functions + void SingleStep(); + void StepOver(); + void ToggleBreakpoint(); + void UpdateLists(); void UpdateCallstack(); void OnKeyDown(wxKeyEvent& event); @@ -139,15 +143,6 @@ void InitBitmaps(); void CreateGUIControls(const SCoreStartupParameter& _LocalCoreStartupParameter); - wxMenuItem* jitblocklinking, *jitnoblockcache, *jitoff; - wxMenuItem* jitlsoff, *jitlslxzoff, *jitlslwzoff, *jitlslbzxoff; - wxMenuItem* jitlspoff; - wxMenuItem* jitlsfoff; - wxMenuItem* jitfpoff; - wxMenuItem* jitioff; - wxMenuItem* jitpoff; - wxMenuItem* jitsroff; - CCodeView* codeview; wxListBox* callstack; wxListBox* symbols; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DebuggerWX/Src/JitWindow.cpp dolphin-emu-2.0+svn6107/Source/Core/DebuggerWX/Src/JitWindow.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DebuggerWX/Src/JitWindow.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DebuggerWX/Src/JitWindow.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -176,7 +176,8 @@ PPCAnalyst::BlockStats st; PPCAnalyst::BlockRegStats gpa; PPCAnalyst::BlockRegStats fpa; - if (PPCAnalyst::Flatten(ppc_addr, &size, &st, &gpa, &fpa, &code_buffer, size) != 0xffffffff) + bool broken_block = false; + if (PPCAnalyst::Flatten(ppc_addr, &size, &st, &gpa, &fpa, broken_block, &code_buffer, size) != 0xffffffff) { sptr = (char*)xDis; for (int i = 0; i < size; i++) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/CompressedBlob.cpp dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/CompressedBlob.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/CompressedBlob.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/CompressedBlob.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -227,7 +227,7 @@ if (inpos != 0) ratio = (int)(100 * position / inpos); char temp[512]; - sprintf(temp, "%i of %i blocks. compression ratio %i%%", i, header.num_blocks, ratio); + sprintf(temp, "%i of %i blocks. Compression ratio %i%%", i, header.num_blocks, ratio); callback(temp, (float)i / (float)header.num_blocks, arg); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/NANDContentLoader.cpp dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/NANDContentLoader.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/NANDContentLoader.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/NANDContentLoader.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -117,9 +117,9 @@ const std::vector& GetContent() const { return m_Content; } - const u16 GetTitleVersion() const {return m_TileVersion;} - const u16 GetNumEntries() const {return m_numEntries;} - const DiscIO::IVolume::ECountry GetCountry() const; + u16 GetTitleVersion() const {return m_TileVersion;} + u16 GetNumEntries() const {return m_numEntries;} + DiscIO::IVolume::ECountry GetCountry() const; private: @@ -333,7 +333,7 @@ return true; } -const DiscIO::IVolume::ECountry CNANDContentLoader::GetCountry() const +DiscIO::IVolume::ECountry CNANDContentLoader::GetCountry() const { if (!IsValid()) return DiscIO::IVolume::COUNTRY_UNKNOWN; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/NANDContentLoader.h dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/NANDContentLoader.h --- dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/NANDContentLoader.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/NANDContentLoader.h 2010-08-18 03:25:17.000000000 +0100 @@ -59,9 +59,9 @@ virtual const u8* GetTicketView() const = 0; virtual const u8* GetTmdHeader() const = 0; virtual const std::vector& GetContent() const = 0; - virtual const u16 GetTitleVersion() const = 0; - virtual const u16 GetNumEntries() const = 0; - virtual const DiscIO::IVolume::ECountry GetCountry() const = 0; + virtual u16 GetTitleVersion() const = 0; + virtual u16 GetNumEntries() const = 0; + virtual DiscIO::IVolume::ECountry GetCountry() const = 0; enum { diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/VolumeGC.cpp dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/VolumeGC.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/VolumeGC.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/VolumeGC.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -78,12 +78,12 @@ std::string CVolumeGC::GetMakerID() const { if (m_pReader == NULL) - return false; + return std::string(); char makerID[3]; if (!Read(0x4, 0x2, (u8*)&makerID)) - return false; - makerID[2] = 0; + return std::string(); + makerID[2] = '\0'; return makerID; } @@ -103,11 +103,11 @@ u32 CVolumeGC::GetFSTSize() const { if (m_pReader == NULL) - return false; + return 0; u32 size; if (!Read(0x428, 0x4, (u8*)&size)) - return false; + return 0; return Common::swap32(size); } @@ -115,13 +115,13 @@ std::string CVolumeGC::GetApploaderDate() const { if (m_pReader == NULL) - return false; + return std::string(); char date[16]; if (!Read(0x2440, 0x10, (u8*)&date)) - return false; + return std::string(); // Should be 0 already, but just in case - date[10] = 0; + date[10] = '\0'; return date; } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DiscIO/Src/VolumeWiiCrypted.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -107,19 +107,19 @@ { if (m_pReader == NULL) { - return(false); + return std::string(); } char ID[7]; if (!Read(0, 6, (u8*)ID)) { - return(false); + return std::string(); } - ID[6] = 0; + ID[6] = '\0'; - return(ID); + return ID; } @@ -138,83 +138,83 @@ { if (m_pReader == NULL) { - return(false); + return std::string(); } char makerID[3]; if (!Read(0x4, 0x2, (u8*)&makerID)) { - return(false); + return std::string(); } - makerID[2] = 0; + makerID[2] = '\0'; - return(makerID); + return makerID; } std::string CVolumeWiiCrypted::GetName() const { if (m_pReader == NULL) { - return(""); + return std::string(); } char name[0xFF]; if (!Read(0x20, 0x60, (u8*)&name)) { - return(""); + return std::string(); } - return(name); + return name; } u32 CVolumeWiiCrypted::GetFSTSize() const { if (m_pReader == NULL) { - return(false); + return 0; } u32 size; if (!Read(0x428, 0x4, (u8*)&size)) { - return(false); + return 0; } - return(size); + return size; } std::string CVolumeWiiCrypted::GetApploaderDate() const { if (m_pReader == NULL) { - return(false); + return std::string(); } char date[16]; if (!Read(0x2440, 0x10, (u8*)&date)) { - return(false); + return std::string(); } - date[10] = 0; + date[10] = '\0'; - return(date); + return date; } u64 CVolumeWiiCrypted::GetSize() const { if (m_pReader) { - return(m_pReader->GetDataSize()); + return m_pReader->GetDataSize(); } else { - return(0); + return 0; } } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/DolphinWX.vcproj dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/DolphinWX.vcproj --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/DolphinWX.vcproj 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/DolphinWX.vcproj 2010-08-18 03:25:15.000000000 +0100 @@ -30,7 +30,7 @@ > #include -#include "Globals.h" #include "Common.h" #include "IniFile.h" #include "BootManager.h" @@ -46,6 +45,7 @@ #include "SysConf.h" #include "Core.h" #if defined(HAVE_WX) && HAVE_WX + #include "Globals.h" #include "ConfigMain.h" #include "Frame.h" #include "CodeWindow.h" @@ -107,6 +107,8 @@ game_ini.Get("Core", "SkipIdle", &StartUp.bSkipIdle, StartUp.bSkipIdle); game_ini.Get("Core", "EnableFPRF", &StartUp.bEnableFPRF, StartUp.bEnableFPRF); game_ini.Get("Core", "TLBHack", &StartUp.iTLBHack, StartUp.iTLBHack); + game_ini.Get("Core", "MMU", &StartUp.bMMU, StartUp.bMMU); + game_ini.Get("Core", "SMC", &StartUp.bSMC, StartUp.bSMC); // Wii settings if (StartUp.bWii) { diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/ConfigMain.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/ConfigMain.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/ConfigMain.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/ConfigMain.cpp 2010-08-18 03:25:15.000000000 +0100 @@ -36,7 +36,7 @@ #include "../../Common/Src/OpenCL.h" #ifdef __APPLE__ -#include +#include #endif extern CFrame* main_frame; @@ -1181,7 +1181,19 @@ { const CPluginInfo* pInfo = static_cast(_pChoice->GetClientData(Index)); if (pInfo != NULL) - CPluginManager::GetInstance().OpenConfig((HWND) this->GetHandle(), pInfo->GetFilename().c_str(), pInfo->GetPluginInfo().Type); + { + #ifdef _WIN32 + // Make sure only one dialog can be opened at a time in Windows, + // but is unnecessary and looks bad in linux. + Disable(); + #endif + CPluginManager::GetInstance().OpenConfig(this, + pInfo->GetFilename().c_str(), pInfo->GetPluginInfo().Type); + #ifdef _WIN32 + Enable(); + Raise(); + #endif + } } } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/FrameAui.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/FrameAui.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/FrameAui.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/FrameAui.cpp 2010-08-18 03:25:15.000000000 +0100 @@ -145,8 +145,8 @@ ConsoleParent->Enable(); DoAddPage(ConsoleParent, - g_pCodeWindow ? g_pCodeWindow->iNbAffiliation[1] : 0, - g_pCodeWindow ? bFloatWindow[1] : false); + g_pCodeWindow ? g_pCodeWindow->iNbAffiliation[1] : 0, + g_pCodeWindow ? bFloatWindow[1] : false); } else // Hide { @@ -175,13 +175,13 @@ { case IDM_LOGWINDOW: if (!g_pCodeWindow) - SConfig::GetInstance().m_InterfaceLogWindow = event.IsChecked(); + SConfig::GetInstance().m_InterfaceLogWindow = bShow; ToggleLogWindow(bShow); break; case IDM_CONSOLEWINDOW: if (!g_pCodeWindow) - SConfig::GetInstance().m_InterfaceConsole = event.IsChecked(); - ToggleConsole(event.IsChecked()); + SConfig::GetInstance().m_InterfaceConsole = bShow; + ToggleConsole(bShow); break; case IDM_REGISTERWINDOW: g_pCodeWindow->ToggleRegisterWindow(bShow); @@ -202,7 +202,6 @@ g_pCodeWindow->ToggleDLLWindow(IDM_VIDEOWINDOW, bShow); break; } - event.Skip(); } // Notebooks @@ -247,9 +246,9 @@ wxAuiNotebook* Ctrl = (wxAuiNotebook*)event.GetEventObject(); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_LOGWINDOW) - ToggleLogWindow(false); + ToggleLogWindow(false); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_CONSOLEWINDOW) - ToggleConsole(false); + ToggleConsole(false); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_REGISTERWINDOW) g_pCodeWindow->ToggleRegisterWindow(false); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_BREAKPOINTWINDOW) @@ -308,7 +307,8 @@ { nb->RemovePage(nb->GetPageIndex(Win)); // Create the parent frame and reparent the window - CreateParentFrame(Win->GetId() + IDM_LOGWINDOW_PARENT - IDM_LOGWINDOW, Win->GetName(), Win); + CreateParentFrame(Win->GetId() + IDM_LOGWINDOW_PARENT - IDM_LOGWINDOW, + Win->GetName(), Win); if (nb->GetPageCount() == 0) AddRemoveBlankPage(); } @@ -320,7 +320,7 @@ wxFrame * Win = (wxFrame*)FindWindowById(Id); if (!Win) return; - wxWindow * Child = Win->GetWindowChildren().Item(0)->GetData(); + wxWindow * Child = Win->GetChildren().Item(0)->GetData(); Child->Reparent(this); DoAddPage(Child, g_pCodeWindow->iNbAffiliation[Child->GetId() - IDM_LOGWINDOW], false); Win->Destroy(); @@ -335,7 +335,7 @@ wxMenu* MenuPopup = new wxMenu; wxMenuItem* Item = new wxMenuItem(MenuPopup, wxID_ANY, - wxT("Select floating windows")); + wxT("Select floating windows")); MenuPopup->Append(Item); Item->Enable(false); MenuPopup->Append(new wxMenuItem(MenuPopup)); @@ -345,7 +345,7 @@ if (Win && Win->IsEnabled()) { Item = new wxMenuItem(MenuPopup, i + IDM_FLOAT_LOGWINDOW - IDM_LOGWINDOW, - Win->GetName(), wxT(""), wxITEM_CHECK); + Win->GetName(), wxT(""), wxITEM_CHECK); MenuPopup->Append(Item); Item->Check(!!FindWindowById(i + IDM_LOGWINDOW_PARENT - IDM_LOGWINDOW)); } @@ -371,8 +371,8 @@ wxAuiNotebook * NB = NULL; for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { - if (m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) - NB = (wxAuiNotebook*)m_Mgr->GetAllPanes().Item(i).window; + if (m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiNotebook))) + NB = (wxAuiNotebook*)m_Mgr->GetAllPanes()[i].window; } if (NB) { @@ -401,7 +401,8 @@ { if (!Win) return; - wxWindow *Parent = FindWindowById(Win->GetId() + IDM_LOGWINDOW_PARENT - IDM_LOGWINDOW); + wxWindow *Parent = FindWindowById(Win->GetId() + + IDM_LOGWINDOW_PARENT - IDM_LOGWINDOW); if (Parent) { @@ -439,13 +440,13 @@ void CFrame::DoAddPage(wxWindow *Win, int i, bool Float) { if (!Win) return; - if (GetNotebookCount() == 0) return; if (i < 0 || i > GetNotebookCount()-1) i = 0; if (Win && GetNotebookFromId(i)->GetPageIndex(Win) != wxNOT_FOUND) return; if (!Float) GetNotebookFromId(i)->AddPage(Win, Win->GetName(), true); else - CreateParentFrame(Win->GetId() + IDM_LOGWINDOW_PARENT - IDM_LOGWINDOW, Win->GetName(), Win); + CreateParentFrame(Win->GetId() + IDM_LOGWINDOW_PARENT - IDM_LOGWINDOW, + Win->GetName(), Win); } // Toolbar @@ -462,13 +463,16 @@ // Create the popup menu wxMenu* menuPopup = new wxMenu; - wxMenuItem* Item = new wxMenuItem(menuPopup, IDM_PERSPECTIVES_ADD_PANE, wxT("Add new pane")); + wxMenuItem* Item = new wxMenuItem(menuPopup, IDM_PERSPECTIVES_ADD_PANE, + wxT("Add new pane")); menuPopup->Append(Item); menuPopup->Append(new wxMenuItem(menuPopup)); - Item = new wxMenuItem(menuPopup, IDM_TAB_SPLIT, wxT("Tab split"), wxT(""), wxITEM_CHECK); + Item = new wxMenuItem(menuPopup, IDM_TAB_SPLIT, wxT("Tab split"), + wxT(""), wxITEM_CHECK); menuPopup->Append(Item); Item->Check(m_bTabSplit); - Item = new wxMenuItem(menuPopup, IDM_NO_DOCKING, wxT("No docking"), wxT(""), wxITEM_CHECK); + Item = new wxMenuItem(menuPopup, IDM_NO_DOCKING, wxT("No docking"), + wxT(""), wxITEM_CHECK); menuPopup->Append(Item); Item->Check(m_bNoDocking); @@ -495,7 +499,8 @@ // create the popup menu wxMenu* menuPopup = new wxMenu; - wxMenuItem* Item = new wxMenuItem(menuPopup, IDM_ADD_PERSPECTIVE, wxT("Create new perspective")); + wxMenuItem* Item = new wxMenuItem(menuPopup, IDM_ADD_PERSPECTIVE, + wxT("Create new perspective")); menuPopup->Append(Item); if (Perspectives.size() > 0) @@ -504,7 +509,8 @@ for (u32 i = 0; i < Perspectives.size(); i++) { wxMenuItem* mItem = new wxMenuItem(menuPopup, IDM_PERSPECTIVES_0 + i, - wxString::FromAscii(Perspectives[i].Name.c_str()), wxT(""), wxITEM_CHECK); + wxString::FromAscii(Perspectives[i].Name.c_str()), + wxT(""), wxITEM_CHECK); menuPopup->Append(mItem); if (i == ActivePerspective) mItem->Check(true); } @@ -557,10 +563,11 @@ { case IDM_ADD_PERSPECTIVE: { - wxTextEntryDialog dlg(this, wxT("Enter a name for the new perspective:"), - wxT("Create new perspective")); + wxTextEntryDialog dlg(this, + wxT("Enter a name for the new perspective:"), + wxT("Create new perspective")); wxString DefaultValue = wxString::Format(wxT("Perspective %d"), - Perspectives.size() + 1); + Perspectives.size() + 1); dlg.SetValue(DefaultValue); bool DlgOk = false; int Return = 0; while (!DlgOk) @@ -571,7 +578,7 @@ else if (dlg.GetValue().Find(wxT(",")) != -1) { wxMessageBox(wxT("The name can not contain the character ','"), - wxT("Notice"), wxOK, this); + wxT("Notice"), wxOK, this); wxString Str = dlg.GetValue(); Str.Replace(wxT(","), wxT(""), true); dlg.SetValue(Str); @@ -579,7 +586,7 @@ else if (dlg.GetValue().IsSameAs(wxT(""))) { wxMessageBox(wxT("The name can not be empty"), - wxT("Notice"), wxOK, this); + wxT("Notice"), wxOK, this); dlg.SetValue(DefaultValue); } else @@ -590,7 +597,7 @@ Tmp.Name = dlg.GetValue().mb_str(); Tmp.Perspective = m_Mgr->SavePerspective(); - ActivePerspective = Perspectives.size(); + ActivePerspective = (u32)Perspectives.size(); Perspectives.push_back(Tmp); UpdateCurrentPerspective(); @@ -612,7 +619,7 @@ wxAuiPaneInfoArray& AllPanes = m_Mgr->GetAllPanes(); for (int i = 0, Count = (int)AllPanes.GetCount(); i < Count; ++i) { - wxAuiPaneInfo& Pane = AllPanes.Item(i); + wxAuiPaneInfo& Pane = AllPanes[i]; if (Pane.window->IsKindOf(CLASSINFO(wxAuiToolBar))) { Pane.Show(); @@ -629,7 +636,7 @@ wxAuiPaneInfoArray& AllPanes = m_Mgr->GetAllPanes(); for (u32 i = 0; i < AllPanes.GetCount(); ++i) { - wxAuiPaneInfo& Pane = AllPanes.Item(i); + wxAuiPaneInfo& Pane = AllPanes[i]; if (Pane.window->IsKindOf(CLASSINFO(wxAuiNotebook))) { // Default @@ -659,7 +666,7 @@ wxAuiPaneInfoArray& AllPanes = m_Mgr->GetAllPanes(); for (int i = 0, Count = (int)AllPanes.GetCount(); i < Count; ++i) { - wxAuiPaneInfo& Pane = AllPanes.Item(i); + wxAuiPaneInfo& Pane = AllPanes[i]; if (Pane.window->IsKindOf(CLASSINFO(wxAuiNotebook))) { wxAuiNotebook* NB = (wxAuiNotebook*)Pane.window; @@ -689,46 +696,23 @@ wxWindow * Win = FindWindowById(IDM_CONSOLEWINDOW); if (!Win) return; - // Get OS version - int wxBorder, Border, LowerBorder, MenuBar, ScrollBar, WidthReduction; - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - if (osvi.dwMajorVersion == 6) // Vista (same as 7?) - { - wxBorder = 2; - Border = 4; - LowerBorder = 6; - MenuBar = 30; // Including upper border - ScrollBar = 19; - } - else // XP - { - wxBorder = 2; - Border = 4; - LowerBorder = 6; - MenuBar = 30; - ScrollBar = 19; - } - WidthReduction = 30 - Border; + const int wxBorder = 2, Border = 4, + MenuBar = 30, ScrollBar = 19; // Get the client size - int X = Win->GetClientSize().GetX(); - int Y = Win->GetClientSize().GetY(); + int X = Win->GetSize().GetX(); + int Y = Win->GetSize().GetY(); int InternalWidth = X - wxBorder*2 - ScrollBar; int InternalHeight = Y - wxBorder*2; - int WindowWidth = InternalWidth + Border*2 + /*max out the width in the word wrap mode*/ 100; + int WindowWidth = InternalWidth + Border*2 + + /*max out the width in the word wrap mode*/ 100; int WindowHeight = InternalHeight + MenuBar; // Resize buffer ConsoleListener* Console = LogManager::GetInstance()->getConsoleListener(); - Console->PixelSpace(0,0, InternalWidth,InternalHeight, false); + Console->PixelSpace(0,0, InternalWidth, InternalHeight, false); // Move the window to hide the border - MoveWindow(GetConsoleWindow(), -Border-wxBorder,-MenuBar-wxBorder, WindowWidth + 100,WindowHeight, true); - // Move it to the bottom of the view order so that it doesn't hide the notebook tabs - // ... - // Log - //NOTICE_LOG(CONSOLE, "Size: %ix%i", X, Y); + MoveWindow(GetConsoleWindow(), -Border-wxBorder, -MenuBar-wxBorder, + WindowWidth + 100, WindowHeight, true); #endif } @@ -746,21 +730,21 @@ for (u32 i = 0, j = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { - if (!m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiToolBar))) + if (!m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiToolBar))) { - if (!m_Mgr->GetAllPanes().Item(i).IsOk()) return; + if (!m_Mgr->GetAllPanes()[i].IsOk()) return; if (Perspectives[ActivePerspective].Width.size() <= j || - Perspectives[ActivePerspective].Height.size() <= j) - continue; + Perspectives[ActivePerspective].Height.size() <= j) + continue; u32 W = Perspectives[ActivePerspective].Width[j], - H = Perspectives[ActivePerspective].Height[j]; + H = Perspectives[ActivePerspective].Height[j]; // Check limits W = Limit(W, 5, 95); - H = Limit(H, 5, 95); + H = Limit(H, 5, 95); // Convert percentages to pixel lengths W = (W * iClientX) / 100; - H = (H * iClientY) / 100; - m_Mgr->GetAllPanes().Item(i).BestSize(W,H).MinSize(W,H); + H = (H * iClientY) / 100; + m_Mgr->GetAllPanes()[i].BestSize(W,H).MinSize(W,H); j++; } @@ -769,17 +753,15 @@ for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { - if (!m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiToolBar))) + if (!m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiToolBar))) { - m_Mgr->GetAllPanes().Item(i).MinSize(-1,-1); + m_Mgr->GetAllPanes()[i].MinSize(-1,-1); } } } void CFrame::ReloadPanes() { - // Hide to avoid flickering - HideAllNotebooks(true); // Close all pages ClosePages(); @@ -793,7 +775,6 @@ .CaptionVisible(m_bEdit).Dockable(!m_bNoDocking).Position(i) .Name(PaneName).Caption(PaneName)); } - HideAllNotebooks(true); // Perspectives m_Mgr->LoadPerspective(Perspectives[ActivePerspective].Perspective, false); @@ -808,8 +789,6 @@ // Open notebook pages AddRemoveBlankPage(); g_pCodeWindow->OpenPages(); - if (g_pCodeWindow->bShowOnStart[0]) ToggleLogWindow(true); - if (g_pCodeWindow->bShowOnStart[1]) ToggleConsole(true); } void CFrame::DoLoadPerspective() @@ -817,8 +796,8 @@ ReloadPanes(); // Restore the exact window sizes, which LoadPerspective doesn't always do SetPaneSize(); - // Show - ShowAllNotebooks(true); + + m_Mgr->Update(); } // Update the local perspectives array @@ -845,7 +824,7 @@ _Section = StringFromFormat("P - %s", Tmp.Name.c_str()); ini.Get(_Section.c_str(), "Perspective", &_Perspective, - "layout2|" + "layout2|" "name=Pane 0;caption=Pane 0;state=768;dir=5;prop=100000;|" "name=Pane 1;caption=Pane 1;state=31458108;dir=4;prop=100000;|" "dock_size(5,0,0)=22|dock_size(4,0,0)=333|"); @@ -879,17 +858,17 @@ int iClientX = GetSize().GetX(), iClientY = GetSize().GetY(); current->Width.clear(); current->Height.clear(); - for (size_t i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) + for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { - if (!m_Mgr->GetAllPanes().Item(i).window-> + if (!m_Mgr->GetAllPanes()[i].window-> IsKindOf(CLASSINFO(wxAuiToolBar))) { // Save width and height as a percentage of the client width and height current->Width.push_back( - (m_Mgr->GetAllPanes().Item(i).window->GetClientSize().GetX() * 100) / - iClientX); + (m_Mgr->GetAllPanes()[i].window->GetClientSize().GetX() * 100) / + iClientX); current->Height.push_back( - (m_Mgr->GetAllPanes().Item(i).window->GetClientSize().GetY() * 100) / + (m_Mgr->GetAllPanes()[i].window->GetClientSize().GetY() * 100) / iClientY); } } @@ -919,20 +898,20 @@ ini.Set("Perspectives", "Active", ActivePerspective); // Save the perspectives - for (size_t i = 0; i < Perspectives.size(); i++) + for (u32 i = 0; i < Perspectives.size(); i++) { std::string _Section = "P - " + Perspectives[i].Name; ini.Set(_Section.c_str(), "Perspective", Perspectives[i].Perspective.mb_str()); std::string SWidth = "", SHeight = ""; - for (size_t j = 0; j < Perspectives[i].Width.size(); j++) + for (u32 j = 0; j < Perspectives[i].Width.size(); j++) { SWidth += StringFromFormat("%i,", Perspectives[i].Width[j]); SHeight += StringFromFormat("%i,", Perspectives[i].Height[j]); } // Remove the ending "," SWidth = SWidth.substr(0, SWidth.length()-1); - SHeight = SHeight.substr(0, SHeight.length()-1); + SHeight = SHeight.substr(0, SHeight.length()-1); ini.Set(_Section.c_str(), "Width", SWidth.c_str()); ini.Set(_Section.c_str(), "Height", SHeight.c_str()); @@ -963,8 +942,9 @@ { for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { - if (!m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) continue; - wxAuiNotebook * NB = (wxAuiNotebook*)m_Mgr->GetAllPanes().Item(i).window; + if (!m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiNotebook))) + continue; + wxAuiNotebook * NB = (wxAuiNotebook*)m_Mgr->GetAllPanes()[i].window; for(u32 j = 0; j < NB->GetPageCount(); j++) { if (NB->GetPage(j)->GetId() == Id) return NB->GetPage(j); @@ -973,12 +953,13 @@ return NULL; } -wxFrame * CFrame::CreateParentFrame(wxWindowID Id, const wxString& Title, wxWindow * Child) +wxFrame * CFrame::CreateParentFrame(wxWindowID Id, const wxString& Title, + wxWindow * Child) { - wxFrame * Frame = new wxFrame(this, Id, Title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE); + wxFrame * Frame = new wxFrame(this, Id, Title, + wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE); Child->Reparent(Frame); - Child->Show(); wxBoxSizer * m_MainSizer = new wxBoxSizer(wxHORIZONTAL); @@ -996,18 +977,20 @@ } // Main sizer - Frame->SetSizer( m_MainSizer ); + Frame->SetSizer(m_MainSizer); // Minimum frame size - Frame->SetMinSize(wxSize(200, -1)); + Frame->SetMinSize(wxSize(200, 200)); Frame->Show(); return Frame; } wxAuiNotebook* CFrame::CreateEmptyNotebook() { - long NOTEBOOK_STYLE = wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_EXTERNAL_MOVE - | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON | wxNO_BORDER; - wxAuiNotebook* NB = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, NOTEBOOK_STYLE); + const long NOTEBOOK_STYLE = wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | + wxAUI_NB_TAB_EXTERNAL_MOVE | wxAUI_NB_SCROLL_BUTTONS | + wxAUI_NB_WINDOWLIST_BUTTON | wxNO_BORDER; + wxAuiNotebook* NB = new wxAuiNotebook(this, wxID_ANY, + wxDefaultPosition, wxDefaultSize, NOTEBOOK_STYLE); return NB; } @@ -1015,13 +998,16 @@ { for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { - if (!m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) continue; - wxAuiNotebook * NB = (wxAuiNotebook*)m_Mgr->GetAllPanes().Item(i).window; + if (!m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiNotebook))) + continue; + wxAuiNotebook * NB = (wxAuiNotebook*)m_Mgr->GetAllPanes()[i].window; for(u32 j = 0; j < NB->GetPageCount(); j++) { - if (NB->GetPageText(j).IsSameAs(wxT("<>")) && NB->GetPageCount() > 1) NB->DeletePage(j); + if (NB->GetPageText(j).IsSameAs(wxT("<>")) && NB->GetPageCount() > 1) + NB->DeletePage(j); } - if (NB->GetPageCount() == 0) NB->AddPage(new wxPanel(this, wxID_ANY), wxT("<>"), true); + if (NB->GetPageCount() == 0) + NB->AddPage(new wxPanel(this, wxID_ANY), wxT("<>"), true); } } @@ -1029,11 +1015,13 @@ { for (u32 i = 0, j = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { - if (!m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) continue; - wxAuiNotebook * NB = (wxAuiNotebook*)m_Mgr->GetAllPanes().Item(i).window; + if (!m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiNotebook))) + continue; + wxAuiNotebook * NB = (wxAuiNotebook*)m_Mgr->GetAllPanes()[i].window; for(u32 k = 0; k < NB->GetPageCount(); k++) { - if (NB->GetPage(k)->GetId() == Id) return j; + if (NB->GetPage(k)->GetId() == Id) + return j; } j++; } @@ -1043,20 +1031,14 @@ // Close all panes with notebooks void CFrame::CloseAllNotebooks() { - int i = 0; - while(GetNotebookCount() > 0) + wxAuiPaneInfoArray AllPanes = m_Mgr->GetAllPanes(); + for (u32 i = 0; i < AllPanes.GetCount(); i++) { - if (m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) + if (AllPanes[i].window->IsKindOf(CLASSINFO(wxAuiNotebook))) { - m_Mgr->GetAllPanes().Item(i).DestroyOnClose(true); - m_Mgr->ClosePane(m_Mgr->GetAllPanes().Item(i)); - //m_Mgr->GetAllPanes().Item(i).window->Hide(); - //m_Mgr->DetachPane(m_Mgr->GetAllPanes().Item(i).window); - - i = 0; + AllPanes[i].DestroyOnClose(true); + m_Mgr->ClosePane(AllPanes[i]); } - else - i++; } } @@ -1065,7 +1047,8 @@ int Ret = 0; for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { - if (m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) Ret++; + if (m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiNotebook))) + Ret++; } return Ret; } @@ -1074,39 +1057,11 @@ { for (u32 i = 0, j = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) { - if (!m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) continue; - if (j == NBId) return (wxAuiNotebook*)m_Mgr->GetAllPanes().Item(i).window; + if (!m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiNotebook))) + continue; + if (j == NBId) + return (wxAuiNotebook*)m_Mgr->GetAllPanes()[i].window; j++; } return NULL; } - -void CFrame::ShowAllNotebooks(bool bShow) -{ - for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) - { - if (m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) - { - if (bShow) - m_Mgr->GetAllPanes().Item(i).Show(); - else - m_Mgr->GetAllPanes().Item(i).window->Hide(); - } - } - m_Mgr->Update(); -} - -void CFrame::HideAllNotebooks(bool Window) -{ - for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++) - { - if (m_Mgr->GetAllPanes().Item(i).window->IsKindOf(CLASSINFO(wxAuiNotebook))) - { - if (Window) - m_Mgr->GetAllPanes().Item(i).Hide(); - else - m_Mgr->GetAllPanes().Item(i).window->Hide(); - } - } - m_Mgr->Update(); -} diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/Frame.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/Frame.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/Frame.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/Frame.cpp 2010-08-18 03:25:15.000000000 +0100 @@ -306,9 +306,6 @@ EVT_MOVE(CFrame::OnMove) EVT_LIST_ITEM_ACTIVATED(LIST_CTRL, CFrame::OnGameListCtrl_ItemActivated) EVT_HOST_COMMAND(wxID_ANY, CFrame::OnHostMessage) -#if wxUSE_TIMER -EVT_TIMER(wxID_ANY, CFrame::OnTimer) -#endif EVT_AUI_PANE_CLOSE(CFrame::OnPaneClose) EVT_AUINOTEBOOK_PAGE_CLOSE(wxID_ANY, CFrame::OnNotebookPageClose) @@ -338,14 +335,11 @@ , g_pCodeWindow(NULL) , bRenderToMain(false), bNoWiimoteMsg(false) , m_ToolBar(NULL), m_ToolBarDebug(NULL), m_ToolBarAui(NULL) - , m_pStatusBar(NULL), m_GameListCtrl(NULL), m_Panel(NULL) + , m_GameListCtrl(NULL), m_Panel(NULL) , m_RenderFrame(NULL), m_RenderParent(NULL) , m_LogWindow(NULL), UseDebugger(_UseDebugger) , m_bBatchMode(_BatchMode), m_bEdit(false), m_bTabSplit(false), m_bNoDocking(false) - , m_bControlsCreated(false), m_bGameLoading(false), m_StopDlg(NULL) - #if wxUSE_TIMER - , m_timer(this) - #endif + , m_bGameLoading(false) { for (int i = 0; i <= IDM_CODEWINDOW - IDM_LOGWINDOW; i++) bFloatWindow[i] = false; @@ -355,9 +349,6 @@ // Give it a console early to show potential messages from this onward ConsoleListener *Console = LogManager::GetInstance()->getConsoleListener(); if (SConfig::GetInstance().m_InterfaceConsole) Console->Open(); - m_LogWindow = new CLogWindow(this, IDM_LOGWINDOW); - m_LogWindow->Hide(); - m_LogWindow->Disable(); // Start debugging mazimized if (UseDebugger) this->Maximize(true); @@ -365,16 +356,10 @@ if (UseDebugger) { g_pCodeWindow = new CCodeWindow(SConfig::GetInstance().m_LocalCoreStartupParameter, this, IDM_CODEWINDOW); - g_pCodeWindow->Hide(); LoadIniPerspectives(); + g_pCodeWindow->Load(); } - // Create timer - #if wxUSE_TIMER - int TimesPerSecond = 10; // We don't need more than this - m_timer.Start( floor((double)(1000 / TimesPerSecond)) ); - #endif - // Create toolbar bitmaps InitBitmaps(); @@ -384,9 +369,9 @@ SetIcon(IconTemp); // Give it a status bar - m_pStatusBar = CreateStatusBar(2, wxST_SIZEGRIP, ID_STATUSBAR); + SetStatusBar(CreateStatusBar(2, wxST_SIZEGRIP, ID_STATUSBAR)); if (!SConfig::GetInstance().m_InterfaceStatusbar) - m_pStatusBar->Hide(); + GetStatusBar()->Hide(); // Give it a menu bar CreateMenu(); @@ -412,26 +397,19 @@ if (g_pCodeWindow) { - m_Mgr->AddPane(m_Panel, wxAuiPaneInfo().Name(wxT("Pane 0")).Caption(wxT("Pane 0")).Show()); - } - else - { - m_Mgr->AddPane(m_Panel, wxAuiPaneInfo().Name(wxT("Pane 0")).Caption(wxT("Pane 0")).Hide()); - m_Mgr->AddPane(CreateEmptyNotebook(), wxAuiPaneInfo().Name(wxT("Pane 1")).Caption(wxT("Logging")).Hide()); - } - - // Setup perspectives - if (g_pCodeWindow) - { - m_Mgr->GetPane(wxT("Pane 0")).CenterPane().PaneBorder(false); + m_Mgr->AddPane(m_Panel, wxAuiPaneInfo() + .Name(wxT("Pane 0")).Caption(wxT("Pane 0")) + .CenterPane().PaneBorder(false).Show()); AuiFullscreen = m_Mgr->SavePerspective(); - m_Mgr->GetPane(wxT("Pane 0")).CenterPane().PaneBorder(true); } else { - m_Mgr->GetPane(wxT("Pane 0")).Show().PaneBorder(false).CaptionVisible(false).Layer(0).Center(); - m_Mgr->GetPane(wxT("Pane 1")).Hide().PaneBorder(false).CaptionVisible(true).Layer(0) - .FloatingSize(wxSize(600, 350)).CloseButton(false); + m_Mgr->AddPane(m_Panel, wxAuiPaneInfo() + .Name(wxT("Pane 0")).Caption(wxT("Pane 0")).PaneBorder(false) + .CaptionVisible(false).Layer(0).Center().Show()); + m_Mgr->AddPane(CreateEmptyNotebook(), wxAuiPaneInfo() + .Name(wxT("Pane 1")).Caption(wxT("Logging")).CaptionVisible(true) + .Layer(0).FloatingSize(wxSize(600, 350)).CloseButton(true).Hide()); AuiFullscreen = m_Mgr->SavePerspective(); } @@ -439,6 +417,10 @@ RecreateToolbar(); if (!SConfig::GetInstance().m_InterfaceToolbar) DoToggleToolbar(false); + m_LogWindow = new CLogWindow(this, IDM_LOGWINDOW); + m_LogWindow->Hide(); + m_LogWindow->Disable(); + // Create list of available plugins for the configuration window CPluginManager::GetInstance().ScanForPlugins(); @@ -446,15 +428,14 @@ if (g_pCodeWindow) { // Load perspective - LoadIniPerspectives(); DoLoadPerspective(); } else { if (SConfig::GetInstance().m_InterfaceLogWindow) - ToggleLogWindow(true); + ToggleLogWindow(true); if (SConfig::GetInstance().m_InterfaceConsole) - ToggleConsole(true); + ToggleConsole(true); } // Show window @@ -470,7 +451,7 @@ #if defined(HAVE_XRANDR) && HAVE_XRANDR m_XRRConfig = new X11Utils::XRRConfiguration(X11Utils::XDisplayFromHandle(GetHandle()), - X11Utils::XWindowFromHandle(GetHandle())); + X11Utils::XWindowFromHandle(GetHandle())); #endif // ------------------------- @@ -482,7 +463,6 @@ // ---------- // Update controls - m_bControlsCreated = true; UpdateGUI(); // If we are rerecording create the status bar now instead of later when a game starts @@ -495,14 +475,7 @@ // Destructor CFrame::~CFrame() { - m_bControlsCreated = false; - drives.clear(); - /* The statbar sample has this so I add this to, but I guess timer will be deleted after - this anyway */ - #if wxUSE_TIMER - if (m_timer.IsRunning()) m_timer.Stop(); - #endif #if defined(HAVE_XRANDR) && HAVE_XRANDR delete m_XRRConfig; @@ -641,15 +614,6 @@ } #endif -#if wxUSE_TIMER -void CFrame::OnTimer(wxTimerEvent& WXUNUSED(event)) -{ - // Process events. Primarily to update the statusbar text. - if (wxGetApp().Pending()) - wxGetApp().ProcessPendingEvents(); -} -#endif - void CFrame::OnHostMessage(wxCommandEvent& event) { switch (event.GetId()) @@ -659,9 +623,9 @@ break; case IDM_UPDATESTATUSBAR: - if (m_pStatusBar != NULL) + if (GetStatusBar() != NULL) { - m_pStatusBar->SetStatusText(event.GetString(), event.GetInt()); + GetStatusBar()->SetStatusText(event.GetString(), event.GetInt()); } break; @@ -703,8 +667,8 @@ return false; // Why these different cases? if (m_RenderParent == wxWindow::FindFocus() || - m_RenderParent == wxWindow::FindFocus()->GetParent() || - m_RenderParent->GetParent() == wxWindow::FindFocus()->GetParent()) + m_RenderParent == wxWindow::FindFocus()->GetParent() || + m_RenderParent->GetParent() == wxWindow::FindFocus()->GetParent()) return true; #endif return false; @@ -753,6 +717,8 @@ m_GameListCtrl->Update(); } + else if (!m_GameListCtrl->GetGameNames().size()) + m_GameListCtrl->BrowseForDirectory(); else // Game started by double click BootGame(std::string("")); @@ -772,12 +738,18 @@ // Toggle fullscreen if (IsHotkey(event, HK_FULLSCREEN)) DoFullscreen(!RendererIsFullscreen()); + // Send Debugger keys to CodeWindow + else if (g_pCodeWindow && (event.GetKeyCode() >= WXK_F9 && event.GetKeyCode() <= WXK_F11)) + event.Skip(); // Pause and Unpause else if (IsHotkey(event, HK_PLAY_PAUSE)) DoPause(); // Stop else if (IsHotkey(event, HK_STOP)) DoStop(); + // Screenshot hotkey + else if (IsHotkey(event, HK_SCREENSHOT)) + Core::ScreenShot(); // Wiimote connect and disconnect hotkeys else if (IsHotkey(event, HK_WIIMOTE1_CONNECT)) WiimoteId = 0; @@ -787,7 +759,7 @@ WiimoteId = 2; else if (IsHotkey(event, HK_WIIMOTE4_CONNECT)) WiimoteId = 3; - // state save and state load hotkeys + // State save and state load hotkeys else if (event.GetKeyCode() >= WXK_F1 && event.GetKeyCode() <= WXK_F8) { int slot_number = event.GetKeyCode() - WXK_F1 + 1; @@ -809,9 +781,6 @@ else event.Skip(); } - // screenshot hotkeys - else if (event.GetKeyCode() == WXK_F9 && event.GetModifiers() == wxMOD_NONE) - Core::ScreenShot(); else event.Skip(); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/Frame.h dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/Frame.h --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/Frame.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/Frame.h 2010-08-18 03:25:15.000000000 +0100 @@ -143,40 +143,9 @@ wxAuiToolBar *m_ToolBar, *m_ToolBarDebug, *m_ToolBarAui; bool bFloatWindow[IDM_CODEWINDOW - IDM_LOGWINDOW + 1]; - // Utility - wxWindow * GetNotebookPageFromId(wxWindowID Id); - wxAuiNotebook * GetNotebookFromId(u32); - int GetNotebookCount(); - wxString GetMenuLabel(int Id); - - // Perspectives - void AddRemoveBlankPage(); - void OnNotebookPageClose(wxAuiNotebookEvent& event); - void OnAllowNotebookDnD(wxAuiNotebookEvent& event); - void OnNotebookPageChanged(wxAuiNotebookEvent& event); - void OnFloatWindow(wxCommandEvent& event); - void ToggleFloatWindow(int Id); - void OnTab(wxAuiNotebookEvent& event); - int GetNotebookAffiliation(wxWindowID Id); - void ClosePages(); - void ShowAllNotebooks(bool Window = false); - void HideAllNotebooks(bool Window = false); - void CloseAllNotebooks(); + // Perspectives (Should find a way to make all of this private) void DoAddPage(wxWindow *Win, int i, bool Float); void DoRemovePage(wxWindow *, bool bHide = true); - void TogglePane(); - void SetPaneSize(); - void ResetToolbarStyle(); - void TogglePaneStyle(bool On, int EventId); - void ToggleNotebookStyle(bool On, long Style); - void ResizeConsole(); - // Float window - void DoUnfloatPage(int Id); - void OnFloatingPageClosed(wxCloseEvent& event); - void OnFloatingPageSize(wxSizeEvent& event); - void DoFloatNotebookPage(wxWindowID Id); - wxFrame * CreateParentFrame(wxWindowID Id = wxID_ANY, const wxString& title = wxT(""), wxWindow * = NULL); - // User perspectives. Should find a way to make these private. struct SPerspectives { std::string Name; @@ -184,39 +153,20 @@ std::vector Width, Height; }; std::vector Perspectives; - wxString AuiFullscreen, AuiCurrent; - wxArrayString AuiPerspective; u32 ActivePerspective; - void AddPane(); - void UpdateCurrentPerspective(); - void SaveIniPerspectives(); - void LoadIniPerspectives(); - void OnPaneClose(wxAuiManagerEvent& evt); - void ReloadPanes(); - void DoLoadPerspective(); - void OnDropDownToolbarSelect(wxCommandEvent& event); - void OnDropDownSettingsToolbar(wxAuiToolBarEvent& event); - void OnDropDownToolbarItem(wxAuiToolBarEvent& event); - void OnSelectPerspective(wxCommandEvent& event); private: - wxStatusBar* m_pStatusBar; - wxBoxSizer* sizerFrame; CGameListCtrl* m_GameListCtrl; wxPanel* m_Panel; CRenderFrame* m_RenderFrame; wxPanel* m_RenderParent; - wxToolBarToolBase* m_ToolPlay; CLogWindow* m_LogWindow; bool UseDebugger; bool m_bBatchMode; bool m_bEdit; bool m_bTabSplit; bool m_bNoDocking; - bool m_bControlsCreated; bool m_bGameLoading; - char newDiscpath[2048]; - wxMessageDialog *m_StopDlg; std::vector drives; @@ -255,8 +205,52 @@ void PopulateToolbarAui(wxAuiToolBar* toolBar); void RecreateToolbar(); void CreateMenu(); + + // Utility + wxString GetMenuLabel(int Id); + wxWindow * GetNotebookPageFromId(wxWindowID Id); + wxAuiNotebook * GetNotebookFromId(u32 NBId); + int GetNotebookCount(); wxAuiNotebook *CreateEmptyNotebook(); + // Perspectives + void AddRemoveBlankPage(); + void OnNotebookPageClose(wxAuiNotebookEvent& event); + void OnAllowNotebookDnD(wxAuiNotebookEvent& event); + void OnNotebookPageChanged(wxAuiNotebookEvent& event); + void OnFloatWindow(wxCommandEvent& event); + void ToggleFloatWindow(int Id); + void OnTab(wxAuiNotebookEvent& event); + int GetNotebookAffiliation(wxWindowID Id); + void ClosePages(); + void CloseAllNotebooks(); + void TogglePane(); + void SetPaneSize(); + void ResetToolbarStyle(); + void TogglePaneStyle(bool On, int EventId); + void ToggleNotebookStyle(bool On, long Style); + void ResizeConsole(); + // Float window + void DoUnfloatPage(int Id); + void OnFloatingPageClosed(wxCloseEvent& event); + void OnFloatingPageSize(wxSizeEvent& event); + void DoFloatNotebookPage(wxWindowID Id); + wxFrame * CreateParentFrame(wxWindowID Id = wxID_ANY, + const wxString& title = wxT(""), + wxWindow * = NULL); + wxString AuiFullscreen, AuiCurrent; + void AddPane(); + void UpdateCurrentPerspective(); + void SaveIniPerspectives(); + void LoadIniPerspectives(); + void OnPaneClose(wxAuiManagerEvent& evt); + void ReloadPanes(); + void DoLoadPerspective(); + void OnDropDownToolbarSelect(wxCommandEvent& event); + void OnDropDownSettingsToolbar(wxAuiToolBarEvent& event); + void OnDropDownToolbarItem(wxAuiToolBarEvent& event); + void OnSelectPerspective(wxCommandEvent& event); + #ifdef _WIN32 // Override window proc for tricks like screensaver disabling WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); @@ -331,21 +325,6 @@ bool RendererIsFullscreen(); void StartGame(const std::string& filename); - // MenuBar - // File - Drive - wxMenuItem* m_pSubMenuDrive; - - // Emulation - wxMenuItem* m_pSubMenuLoad; - wxMenuItem* m_pSubMenuSave; - wxMenuItem* m_pSubMenuFrameSkipping; - -#if wxUSE_TIMER - // Used to process command events - void OnTimer(wxTimerEvent& WXUNUSED(event)); - wxTimer m_timer; -#endif - // Event table DECLARE_EVENT_TABLE(); }; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/FrameTools.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/FrameTools.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/FrameTools.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/FrameTools.cpp 2010-08-18 03:25:16.000000000 +0100 @@ -107,7 +107,7 @@ fileMenu->Append(wxID_OPEN, _T("&Open...\tCtrl+O")); wxMenu *externalDrive = new wxMenu; - m_pSubMenuDrive = fileMenu->AppendSubMenu(externalDrive, _T("&Boot from DVD Drive...")); + fileMenu->Append(IDM_DRIVES, _T("&Boot from DVD Drive..."), externalDrive); drives = cdio_get_devices(); // Windows Limitation of 24 character drives @@ -139,24 +139,31 @@ emulationMenu->Append(IDM_FRAMESTEP, _T("&Frame Stepping"), wxEmptyString, wxITEM_CHECK); wxMenu *skippingMenu = new wxMenu; - m_pSubMenuFrameSkipping = emulationMenu->AppendSubMenu(skippingMenu, _T("Frame S&kipping")); + emulationMenu->AppendSubMenu(skippingMenu, _T("Frame S&kipping")); for(int i = 0; i < 10; i++) skippingMenu->Append(IDM_FRAMESKIP0 + i, wxString::Format(_T("%i"), i), wxEmptyString, wxITEM_RADIO); emulationMenu->AppendSeparator(); - emulationMenu->Append(IDM_SCREENSHOT, _T("Take S&creenshot\tF9")); + emulationMenu->Append(IDM_SCREENSHOT, GetMenuLabel(HK_SCREENSHOT)); + emulationMenu->AppendSeparator(); wxMenu *saveMenu = new wxMenu; wxMenu *loadMenu = new wxMenu; - m_pSubMenuLoad = emulationMenu->AppendSubMenu(loadMenu, _T("&Load State")); - m_pSubMenuSave = emulationMenu->AppendSubMenu(saveMenu, _T("Sa&ve State")); + emulationMenu->Append(IDM_LOADSTATE, _T("&Load State"), loadMenu); + emulationMenu->Append(IDM_SAVESTATE, _T("Sa&ve State"), saveMenu); saveMenu->Append(IDM_SAVESTATEFILE, _T("Save State...")); loadMenu->Append(IDM_UNDOSAVESTATE, _T("Last Overwritten State\tShift+F12")); saveMenu->AppendSeparator(); loadMenu->Append(IDM_LOADSTATEFILE, _T("Load State...")); - loadMenu->Append(IDM_LOADLASTSTATE, _T("Last Saved State\tF11")); + + // Reserve F11 for the "step into" function in the debugger + if (g_pCodeWindow) + loadMenu->Append(IDM_LOADLASTSTATE, _T("Last Saved State")); + else + loadMenu->Append(IDM_LOADLASTSTATE, _T("Last Saved State\tF11")); + loadMenu->Append(IDM_UNDOLOADSTATE, _T("Undo Load State\tF12")); loadMenu->AppendSeparator(); @@ -310,17 +317,15 @@ case HK_STOP: Label = _T("&Stop\t"); break; - case HK_WIIMOTE1_CONNECT: - Label = _T("Connect Wiimote 1\t"); + case HK_SCREENSHOT: + Label = _T("Take Screenshot\t"); break; + case HK_WIIMOTE1_CONNECT: case HK_WIIMOTE2_CONNECT: - Label = _T("Connect Wiimote 2\t"); - break; case HK_WIIMOTE3_CONNECT: - Label = _T("Connect Wiimote 3\t"); - break; case HK_WIIMOTE4_CONNECT: - Label = _T("Connect Wiimote 4\t"); + Label = wxString::Format(_T("Connect Wiimote %i\t"), + Id - HK_WIIMOTE1_CONNECT + 1); break; } @@ -365,7 +370,7 @@ void CFrame::PopulateToolbarAui(wxAuiToolBar* ToolBar) { int w = m_Bitmaps[Toolbar_FileOpen].GetWidth(), - h = m_Bitmaps[Toolbar_FileOpen].GetHeight(); + h = m_Bitmaps[Toolbar_FileOpen].GetHeight(); ToolBar->SetToolBitmapSize(wxSize(w, h)); ToolBar->AddTool(IDM_SAVE_PERSPECTIVE, wxT("Save"), g_pCodeWindow->m_Bitmaps[Toolbar_GotoPC], wxT("Save current perspective")); @@ -604,6 +609,7 @@ } else { + char newDiscpath[2048]; strncpy(newDiscpath, path.mb_str(), strlen(path.mb_str())+1); DVDInterface::ChangeDisc(newDiscpath); } @@ -630,7 +636,7 @@ wxFileSelectorDefaultWildcardStr, wxFileSelectorDefaultWildcardStr ), - wxFD_SAVE | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST, + wxFD_SAVE | wxFD_PREVIEW, this); if(path.IsEmpty()) @@ -722,7 +728,7 @@ m_RenderParent->GetSize(&width, &height); m_RenderParent->GetPosition(&x, &y); X11Utils::SendClientEvent(X11Utils::XDisplayFromHandle(GetHandle()), - "RESIZE", x, y, width, height); + "RESIZE", x, y, width, height); #endif m_LogWindow->Refresh(); m_LogWindow->Update(); @@ -739,7 +745,7 @@ memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); dmScreenSettings.dmSize = sizeof(dmScreenSettings); sscanf(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution.c_str(), - "%dx%d", &dmScreenSettings.dmPelsWidth, &dmScreenSettings.dmPelsHeight); + "%dx%d", &dmScreenSettings.dmPelsWidth, &dmScreenSettings.dmPelsHeight); dmScreenSettings.dmBitsPerPel = 32; dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; @@ -783,7 +789,8 @@ SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowYPos); wxSize size(SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowWidth, SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowHeight); - m_RenderFrame = new CRenderFrame((wxFrame*)this, wxID_ANY, _("Dolphin"), position, size); + m_RenderFrame = new CRenderFrame((wxFrame*)this, wxID_ANY, _("Dolphin"), position); + m_RenderFrame->SetClientSize(size.GetWidth(), size.GetHeight()); m_RenderFrame->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW, wxCloseEventHandler(CFrame::OnRenderParentClose), (wxObject*)0, this); @@ -879,11 +886,7 @@ // Ask for confirmation in case the user accidentally clicked Stop / Escape if (SConfig::GetInstance().m_LocalCoreStartupParameter.bConfirmStop) { - // Suppress duplicate dialog boxes - if (m_StopDlg) - return; - - m_StopDlg = new wxMessageDialog( + wxMessageDialog *m_StopDlg = new wxMessageDialog( this, wxT("Do you want to stop the current emulation?"), wxT("Please confirm..."), @@ -892,8 +895,7 @@ int Ret = m_StopDlg->ShowModal(); m_StopDlg->Destroy(); - m_StopDlg = NULL; - if (Ret == wxID_NO) + if (Ret != wxID_YES) return; } @@ -933,10 +935,10 @@ UpdateGUI(); // Clean framerate indications from the status bar. - m_pStatusBar->SetStatusText(wxT(" "), 0); + GetStatusBar()->SetStatusText(wxT(" "), 0); // Clear wiimote connection status from the status bar. - m_pStatusBar->SetStatusText(wxT(" "), 1); + GetStatusBar()->SetStatusText(wxT(" "), 1); // If batch mode was specified on the command-line, exit now. if (m_bBatchMode) @@ -964,20 +966,34 @@ void CFrame::OnPluginGFX(wxCommandEvent& WXUNUSED (event)) { + #ifdef _WIN32 + Disable(); // Fake a modal dialog + #endif CPluginManager::GetInstance().OpenConfig( - GetHandle(), + this, SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoPlugin.c_str(), PLUGIN_TYPE_VIDEO ); + #ifdef _WIN32 + Enable(); + Raise(); + #endif } void CFrame::OnPluginDSP(wxCommandEvent& WXUNUSED (event)) { + #ifdef _WIN32 + Disable(); // Fake a modal dialog + #endif CPluginManager::GetInstance().OpenConfig( - GetHandle(), + this, SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDSPPlugin.c_str(), PLUGIN_TYPE_DSP ); + #ifdef _WIN32 + Enable(); + Raise(); + #endif } void CFrame::OnPluginPAD(wxCommandEvent& WXUNUSED (event)) @@ -1006,11 +1022,18 @@ void CFrame::OnPluginWiimote(wxCommandEvent& WXUNUSED (event)) { + #ifdef _WIN32 + Disable(); // Fake a modal dialog + #endif CPluginManager::GetInstance().OpenConfig( - GetHandle(), + this, SConfig::GetInstance().m_LocalCoreStartupParameter.m_strWiimotePlugin.c_str(), PLUGIN_TYPE_WIIMOTE ); + #ifdef _WIN32 + Enable(); + Raise(); + #endif } void CFrame::OnHelp(wxCommandEvent& event) @@ -1231,9 +1254,6 @@ // Update the enabled/disabled status void CFrame::UpdateGUI() { - if (!m_bControlsCreated) - return; - // Save status bool Initialized = Core::isRunning(); bool Running = Core::GetState() == Core::CORE_RUN; @@ -1252,7 +1272,7 @@ // File GetMenuBar()->FindItem(wxID_OPEN)->Enable(!Initialized); - m_pSubMenuDrive->Enable(!Initialized); + GetMenuBar()->FindItem(IDM_DRIVES)->Enable(!Initialized); GetMenuBar()->FindItem(wxID_REFRESH)->Enable(!Initialized); GetMenuBar()->FindItem(IDM_BROWSE)->Enable(!Initialized); @@ -1269,29 +1289,39 @@ GetMenuBar()->FindItem(IDM_TOGGLE_FULLSCREEN)->SetItemLabel(GetMenuLabel(HK_FULLSCREEN)); GetMenuBar()->FindItem(IDM_PLAY)->SetItemLabel(GetMenuLabel(HK_PLAY_PAUSE)); GetMenuBar()->FindItem(IDM_STOP)->SetItemLabel(GetMenuLabel(HK_STOP)); + GetMenuBar()->FindItem(IDM_SCREENSHOT)->SetItemLabel(GetMenuLabel(HK_SCREENSHOT)); GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->SetItemLabel(GetMenuLabel(HK_WIIMOTE1_CONNECT)); GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->SetItemLabel(GetMenuLabel(HK_WIIMOTE2_CONNECT)); GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->SetItemLabel(GetMenuLabel(HK_WIIMOTE3_CONNECT)); GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->SetItemLabel(GetMenuLabel(HK_WIIMOTE4_CONNECT)); - m_pSubMenuLoad->Enable(Initialized); - m_pSubMenuSave->Enable(Initialized); + GetMenuBar()->FindItem(IDM_LOADSTATE)->Enable(Initialized); + GetMenuBar()->FindItem(IDM_SAVESTATE)->Enable(Initialized); // Misc GetMenuBar()->FindItem(IDM_CHANGEDISC)->Enable(Initialized); - if (DiscIO::CNANDContentManager::Access().GetNANDLoader(std::string(File::GetUserPath(D_WIIMENU_IDX))).IsValid()) + if (DiscIO::CNANDContentManager::Access().GetNANDLoader + (std::string(File::GetUserPath(D_WIIMENU_IDX))).IsValid()) GetMenuBar()->FindItem(IDM_LOAD_WII_MENU)->Enable(!Initialized); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Enable(Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Enable(Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Enable(Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Enable(Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)-> + Enable(Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)-> + Enable(Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)-> + Enable(Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)-> + Enable(Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii); if (Initialized && SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) { - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Check(GetUsbPointer()->AccessWiiMote(0x0100)->IsConnected() == 3); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Check(GetUsbPointer()->AccessWiiMote(0x0101)->IsConnected() == 3); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Check(GetUsbPointer()->AccessWiiMote(0x0102)->IsConnected() == 3); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Check(GetUsbPointer()->AccessWiiMote(0x0103)->IsConnected() == 3); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Check(GetUsbPointer()-> + AccessWiiMote(0x0100)->IsConnected() == 3); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Check(GetUsbPointer()-> + AccessWiiMote(0x0101)->IsConnected() == 3); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Check(GetUsbPointer()-> + AccessWiiMote(0x0102)->IsConnected() == 3); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Check(GetUsbPointer()-> + AccessWiiMote(0x0103)->IsConnected() == 3); } if (Running) @@ -1452,20 +1482,20 @@ { m_Mgr->GetPane(wxT("TBMain")).Show(); if (g_pCodeWindow) - { - m_Mgr->GetPane(wxT("TBDebug")).Show(); - m_Mgr->GetPane(wxT("TBAui")).Show(); - } + { + m_Mgr->GetPane(wxT("TBDebug")).Show(); + m_Mgr->GetPane(wxT("TBAui")).Show(); + } m_Mgr->Update(); } else { m_Mgr->GetPane(wxT("TBMain")).Hide(); if (g_pCodeWindow) - { - m_Mgr->GetPane(wxT("TBDebug")).Hide(); - m_Mgr->GetPane(wxT("TBAui")).Hide(); - } + { + m_Mgr->GetPane(wxT("TBDebug")).Hide(); + m_Mgr->GetPane(wxT("TBAui")).Hide(); + } m_Mgr->Update(); } } @@ -1475,9 +1505,9 @@ { SConfig::GetInstance().m_InterfaceStatusbar = event.IsChecked(); if (SConfig::GetInstance().m_InterfaceStatusbar == true) - m_pStatusBar->Show(); + GetStatusBar()->Show(); else - m_pStatusBar->Hide(); + GetStatusBar()->Hide(); this->SendSizeEvent(); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/GameListCtrl.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/GameListCtrl.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/GameListCtrl.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/GameListCtrl.cpp 2010-08-18 03:25:16.000000000 +0100 @@ -60,32 +60,50 @@ switch (one.GetCountry()) { - case DiscIO::IVolume::COUNTRY_JAPAN:; - case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break; - default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage; + case DiscIO::IVolume::COUNTRY_JAPAN: + case DiscIO::IVolume::COUNTRY_USA: + indexOne = 0; + break; + default: + indexOne = SConfig::GetInstance().m_InterfaceLanguage; } switch (other.GetCountry()) { - case DiscIO::IVolume::COUNTRY_JAPAN:; - case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break; - default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage; + case DiscIO::IVolume::COUNTRY_JAPAN: + case DiscIO::IVolume::COUNTRY_USA: + indexOther = 0; + break; + default: + indexOther = SConfig::GetInstance().m_InterfaceLanguage; } switch(currentColumn) { - case CGameListCtrl::COLUMN_TITLE: return strcasecmp(one.GetName(indexOne).c_str(), other.GetName(indexOther).c_str()) < 0; - case CGameListCtrl::COLUMN_NOTES: - { - // On Gamecube we show the company string, while it's empty on other platforms, so we show the description instead - std::string cmp1 = (one.GetPlatform() == GameListItem::GAMECUBE_DISC) ? one.GetCompany() : one.GetDescription(indexOne); - std::string cmp2 = (other.GetPlatform() == GameListItem::GAMECUBE_DISC) ? other.GetCompany() : other.GetDescription(indexOther); - return strcasecmp(cmp1.c_str(), cmp2.c_str()) < 0; - } - case CGameListCtrl::COLUMN_COUNTRY: return (one.GetCountry() < other.GetCountry()); - case CGameListCtrl::COLUMN_SIZE: return (one.GetFileSize() < other.GetFileSize()); - case CGameListCtrl::COLUMN_PLATFORM: return (one.GetPlatform() < other.GetPlatform()); - default: return strcasecmp(one.GetName(indexOne).c_str(), other.GetName(indexOther).c_str()) < 0; + case CGameListCtrl::COLUMN_TITLE: + return strcasecmp(one.GetName(indexOne).c_str(), + other.GetName(indexOther).c_str()) < 0; + case CGameListCtrl::COLUMN_NOTES: + { + // On Gamecube we show the company string, while it's empty on + // other platforms, so we show the description instead + std::string cmp1 = + (one.GetPlatform() == GameListItem::GAMECUBE_DISC) ? + one.GetCompany() : one.GetDescription(indexOne); + std::string cmp2 = + (other.GetPlatform() == GameListItem::GAMECUBE_DISC) ? + other.GetCompany() : other.GetDescription(indexOther); + return strcasecmp(cmp1.c_str(), cmp2.c_str()) < 0; + } + case CGameListCtrl::COLUMN_COUNTRY: + return (one.GetCountry() < other.GetCountry()); + case CGameListCtrl::COLUMN_SIZE: + return (one.GetFileSize() < other.GetFileSize()); + case CGameListCtrl::COLUMN_PLATFORM: + return (one.GetPlatform() < other.GetPlatform()); + default: + return strcasecmp(one.GetName(indexOne).c_str(), + other.GetName(indexOther).c_str()) < 0; } } @@ -118,7 +136,8 @@ END_EVENT_TABLE() -CGameListCtrl::CGameListCtrl(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style) +CGameListCtrl::CGameListCtrl(wxWindow* parent, const wxWindowID id, const + wxPoint& pos, const wxSize& size, long style) : wxListCtrl(parent, id, pos, size, style), toolTip(0) { } @@ -183,21 +202,22 @@ wxGetHomeDir(&dirHome); // browse - wxDirDialog dialog(this, _("Browse for a directory to add"), dirHome, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST); + wxDirDialog dialog(this, _("Browse for a directory to add"), dirHome, + wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST); if (dialog.ShowModal() == wxID_OK) { std::string sPath(dialog.GetPath().mb_str()); std::vector::iterator itResult = std::find( - SConfig::GetInstance().m_ISOFolder.begin(), SConfig::GetInstance().m_ISOFolder.end(), sPath - ); + SConfig::GetInstance().m_ISOFolder.begin(), + SConfig::GetInstance().m_ISOFolder.end(), sPath); if (itResult == SConfig::GetInstance().m_ISOFolder.end()) { SConfig::GetInstance().m_ISOFolder.push_back(sPath); SConfig::GetInstance().SaveSettings(); } - + Update(); } } @@ -233,9 +253,10 @@ InsertColumn(COLUMN_PLATFORM, _("")); InsertColumn(COLUMN_BANNER, _("Banner")); InsertColumn(COLUMN_TITLE, _("Title")); - - // Instead of showing the notes + the company, which is unknown with wii titles - // We show in the same column : company for GC games and description for wii/wad games + + // Instead of showing the notes + the company, which is unknown with + // wii titles We show in the same column : company for GC games and + // description for wii/wad games InsertColumn(COLUMN_NOTES, _("Notes")); InsertColumn(COLUMN_COUNTRY, _("")); InsertColumn(COLUMN_SIZE, _("Size")); @@ -268,8 +289,9 @@ else { wxString errorString; - // We just check for one hide setting to be enabled, as we may only have GC games - // for example, and hide them, so we should show the second message instead + // We just check for one hide setting to be enabled, as we may only + // have GC games for example, and hide them, so we should show the + // second message instead if ((SConfig::GetInstance().m_ListGC && SConfig::GetInstance().m_ListWii && SConfig::GetInstance().m_ListWad) && @@ -277,11 +299,13 @@ SConfig::GetInstance().m_ListUsa && SConfig::GetInstance().m_ListPal)) { - errorString = _("Dolphin could not find any GC/Wii ISOs. Doubleclick here to browse for files..."); + errorString = wxT("Dolphin could not find any GC/Wii ISOs. ") + wxT("Doubleclick here to browse for files..."); } else { - errorString = _("Dolphin is currently set to hide all games. Doubleclick here to show all games..."); + errorString = wxT("Dolphin is currently set to hide all games. ") + wxT("Doubleclick here to show all games..."); } InsertColumn(0, _("No ISOs or WADS found")); long index = InsertItem(0, errorString); @@ -299,7 +323,7 @@ const char* sizes[] = {"b", "KB", "MB", "GB", "TB", "PB", "EB"}; int s = 0; int frac = 0; - + while (_size > (s64)1024) { s++; @@ -317,12 +341,12 @@ } std::string CGameListCtrl::GetGamePaths() const -{ - return m_gamePath; +{ + return m_gamePath; } std::string CGameListCtrl::GetGameNames() const -{ - return m_gameList; +{ + return m_gameList; } #ifdef _WIN32 @@ -342,7 +366,8 @@ { // Retrieve the topmost shown item and get drawing offsets long top = GetTopItem(); - int flagOffset = GetColumnWidth(0) + GetColumnWidth(1) + GetColumnWidth(2) + GetColumnWidth(3); + int flagOffset = GetColumnWidth(0) + GetColumnWidth(1) + + GetColumnWidth(2) + GetColumnWidth(3); int stateOffset = flagOffset + GetColumnWidth(4) + GetColumnWidth(5); // Only redraw shown lines @@ -353,12 +378,16 @@ int itemY = itemRect.GetTop(); const GameListItem& rISOFile = m_ISOFiles[GetItemData(i)]; - m_imageListSmall->Draw(m_PlatformImageIndex[rISOFile.GetPlatform()], dc, itemRect.GetX()+3, itemY); - m_imageListSmall->Draw(m_FlagImageIndex[rISOFile.GetCountry()], dc, flagOffset, itemY); + m_imageListSmall->Draw(m_PlatformImageIndex[rISOFile.GetPlatform()], + dc, itemRect.GetX()+3, itemY); + m_imageListSmall->Draw(m_FlagImageIndex[rISOFile.GetCountry()], + dc, flagOffset, itemY); - ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + (rISOFile.GetUniqueID()) + ".ini").c_str()); + ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + + (rISOFile.GetUniqueID()) + ".ini").c_str()); ini.Get("EmuState", "EmulationStateId", &nState); - m_imageListSmall->Draw(m_EmuStateImageIndex[nState], dc, stateOffset, itemY); + m_imageListSmall->Draw(m_EmuStateImageIndex[nState], + dc, stateOffset, itemY); } } } @@ -382,7 +411,8 @@ // Insert a first row with the platform image, that will be used as the Index #ifndef _WIN32 - long ItemIndex = InsertItem(_Index, wxEmptyString, m_PlatformImageIndex[rISOFile.GetPlatform()]); + long ItemIndex = InsertItem(_Index, wxEmptyString, + m_PlatformImageIndex[rISOFile.GetPlatform()]); #else long ItemIndex = InsertItem(_Index, wxEmptyString, -1); #endif @@ -408,38 +438,50 @@ case DiscIO::IVolume::COUNTRY_JAPAN: { wxString name = wxString(rISOFile.GetName(0).c_str(), SJISConv); - m_gameList.append(StringFromFormat("%s (J)\n", (const char*)name.c_str())); + m_gameList.append(StringFromFormat("%s (J)\n", (const char *)name.c_str())); SetItem(_Index, COLUMN_TITLE, name, -1); - SetItem(_Index, COLUMN_NOTES, wxString(company.size() ? company.c_str() : rISOFile.GetDescription(0).c_str(), SJISConv), -1); + SetItem(_Index, COLUMN_NOTES, wxString(company.size() ? + company.c_str() : rISOFile.GetDescription(0).c_str(), + SJISConv), -1); } break; case DiscIO::IVolume::COUNTRY_USA: m_gameList.append(StringFromFormat("%s (U)\n", rISOFile.GetName(0).c_str())); - SetItem(_Index, COLUMN_TITLE, + SetItem(_Index, COLUMN_TITLE, wxString::From8BitData(rISOFile.GetName(0).c_str()), -1); - SetItem(_Index, COLUMN_NOTES, - wxString::From8BitData(company.size() ? company.c_str() : rISOFile.GetDescription(0).c_str()), -1); + SetItem(_Index, COLUMN_NOTES, + wxString::From8BitData(company.size() ? + company.c_str() : rISOFile.GetDescription(0).c_str()), -1); break; default: - m_gameList.append(StringFromFormat("%s (E)\n", rISOFile.GetName((int)SConfig::GetInstance().m_InterfaceLanguage).c_str())); - SetItem(_Index, COLUMN_TITLE, - wxString::From8BitData(rISOFile.GetName((int)SConfig::GetInstance().m_InterfaceLanguage).c_str()), -1); - SetItem(_Index, COLUMN_NOTES, wxString::From8BitData( - company.size() ? company.c_str() : rISOFile.GetDescription((int)SConfig::GetInstance().m_InterfaceLanguage).c_str()), -1); + m_gameList.append(StringFromFormat("%s (E)\n", + rISOFile.GetName(SConfig::GetInstance().m_InterfaceLanguage).c_str())); + SetItem(_Index, COLUMN_TITLE, + wxString::From8BitData( + rISOFile.GetName(SConfig::GetInstance().m_InterfaceLanguage).c_str()), + -1); + SetItem(_Index, COLUMN_NOTES, + wxString::From8BitData(company.size() ? + company.c_str() : + rISOFile.GetDescription(SConfig::GetInstance().m_InterfaceLanguage).c_str()), + -1); break; } } else // It's a Wad file { m_gameList.append(StringFromFormat("%s (WAD)\n", rISOFile.GetName(0).c_str())); - SetItem(_Index, COLUMN_TITLE, wxString(rISOFile.GetName(0).c_str(), SJISConv), -1); - SetItem(_Index, COLUMN_NOTES, wxString(rISOFile.GetDescription(0).c_str(), SJISConv), -1); + SetItem(_Index, COLUMN_TITLE, + wxString(rISOFile.GetName(0).c_str(), SJISConv), -1); + SetItem(_Index, COLUMN_NOTES, + wxString(rISOFile.GetDescription(0).c_str(), SJISConv), -1); } #ifndef _WIN32 // Load the INI file for columns that read from it IniFile ini; - ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + (rISOFile.GetUniqueID()) + ".ini").c_str()); + ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + + (rISOFile.GetUniqueID()) + ".ini").c_str()); // Emulation status int nState; @@ -476,7 +518,10 @@ { for(long i = 0; i < GetItemCount(); i++) { - wxColour color = (i & 1) ? blend50(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + wxColour color = (i & 1) ? + blend50(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)) : + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); CGameListCtrl::SetItemBackgroundColour(i, color); } } @@ -501,14 +546,16 @@ for (u32 k = 0; k < Directories.size(); k++) { NormalizeDirSep(&Directories.at(k)); - if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0) + if (strcmp(Directories.at(k).c_str(), + FST_Temp.children.at(j).physicalName.c_str()) == 0) { duplicate = true; break; } } if (!duplicate) - Directories.push_back(FST_Temp.children.at(j).physicalName.c_str()); + Directories.push_back( + FST_Temp.children.at(j).physicalName.c_str()); } } } @@ -536,7 +583,6 @@ (int)rFilenames.size(), // range this, // parent wxPD_APP_MODAL | - // wxPD_AUTO_HIDE | -- try this as well wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | @@ -559,9 +605,7 @@ // Update with the progress (i) and the message (msg) bool Cont = dialog.Update(i, msg); if (!Cont) - { break; - } #endif GameListItem ISOFile(rFilenames[i]); if (ISOFile.IsValid()) @@ -570,52 +614,53 @@ switch(ISOFile.GetPlatform()) { - case GameListItem::WII_DISC: - if (!SConfig::GetInstance().m_ListWii) - list = false; - break; - case GameListItem::WII_WAD: - if (!SConfig::GetInstance().m_ListWad) - list = false; - break; - default: - if (!SConfig::GetInstance().m_ListGC) - list = false; - break; + case GameListItem::WII_DISC: + if (!SConfig::GetInstance().m_ListWii) + list = false; + break; + case GameListItem::WII_WAD: + if (!SConfig::GetInstance().m_ListWad) + list = false; + break; + default: + if (!SConfig::GetInstance().m_ListGC) + list = false; + break; } switch(ISOFile.GetCountry()) { - case DiscIO::IVolume::COUNTRY_TAIWAN: - if (!SConfig::GetInstance().m_ListTaiwan) - list = false; - case DiscIO::IVolume::COUNTRY_KOREA: - if (!SConfig::GetInstance().m_ListKorea) - list = false; - break; - case DiscIO::IVolume::COUNTRY_JAPAN: - if (!SConfig::GetInstance().m_ListJap) - list = false; - break; - case DiscIO::IVolume::COUNTRY_USA: - if (!SConfig::GetInstance().m_ListUsa) - list = false; - break; - case DiscIO::IVolume::COUNTRY_FRANCE: - if (!SConfig::GetInstance().m_ListFrance) - list = false; - break; - case DiscIO::IVolume::COUNTRY_ITALY: - if (!SConfig::GetInstance().m_ListItaly) - list = false; - break; - default: - if (!SConfig::GetInstance().m_ListPal) - list = false; - break; + case DiscIO::IVolume::COUNTRY_TAIWAN: + if (!SConfig::GetInstance().m_ListTaiwan) + list = false; + case DiscIO::IVolume::COUNTRY_KOREA: + if (!SConfig::GetInstance().m_ListKorea) + list = false; + break; + case DiscIO::IVolume::COUNTRY_JAPAN: + if (!SConfig::GetInstance().m_ListJap) + list = false; + break; + case DiscIO::IVolume::COUNTRY_USA: + if (!SConfig::GetInstance().m_ListUsa) + list = false; + break; + case DiscIO::IVolume::COUNTRY_FRANCE: + if (!SConfig::GetInstance().m_ListFrance) + list = false; + break; + case DiscIO::IVolume::COUNTRY_ITALY: + if (!SConfig::GetInstance().m_ListItaly) + list = false; + break; + default: + if (!SConfig::GetInstance().m_ListPal) + list = false; + break; } - if (list) m_ISOFiles.push_back(ISOFile); + if (list) + m_ISOFiles.push_back(ISOFile); } } } @@ -628,7 +673,8 @@ for (u32 i = 0; i < drives.size() && i < 24; i++) { Drive[i] = new GameListItem(drives[i].c_str()); - if (Drive[i]->IsValid()) m_ISOFiles.push_back(*Drive[i]); + if (Drive[i]->IsValid()) + m_ISOFiles.push_back(*Drive[i]); } } @@ -649,14 +695,14 @@ CGameListCtrl *caller; int wxCALLBACK wxListCompare(long item1, long item2, long sortData) { - //return 1 if item1 > item2 - //return -1 if item1 < item2 - //0 for identity + // return 1 if item1 > item2 + // return -1 if item1 < item2 + // return 0 for identity const GameListItem *iso1 = caller->GetISO(item1); const GameListItem *iso2 = caller->GetISO(item2); - + int t = 1; - + if (sortData < 0) { t = -1; @@ -668,55 +714,77 @@ switch (iso1->GetCountry()) { - case DiscIO::IVolume::COUNTRY_JAPAN:; - case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break; - default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage; + case DiscIO::IVolume::COUNTRY_JAPAN: + case DiscIO::IVolume::COUNTRY_USA: + indexOne = 0; + break; + default: + indexOne = SConfig::GetInstance().m_InterfaceLanguage; } switch (iso2->GetCountry()) { - case DiscIO::IVolume::COUNTRY_JAPAN:; - case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break; - default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage; + case DiscIO::IVolume::COUNTRY_JAPAN: + case DiscIO::IVolume::COUNTRY_USA: + indexOther = 0; + break; + default: + indexOther = SConfig::GetInstance().m_InterfaceLanguage; } switch(sortData) { - case CGameListCtrl::COLUMN_TITLE: - return strcasecmp(iso1->GetName(indexOne).c_str(),iso2->GetName(indexOther).c_str()) *t; - case CGameListCtrl::COLUMN_NOTES: - { - std::string cmp1 = (iso1->GetPlatform() == GameListItem::GAMECUBE_DISC) ? iso1->GetCompany() : iso1->GetDescription(indexOne); - std::string cmp2 = (iso2->GetPlatform() == GameListItem::GAMECUBE_DISC) ? iso2->GetCompany() : iso2->GetDescription(indexOther); - return strcasecmp(cmp1.c_str(), cmp2.c_str()) *t; - } - case CGameListCtrl::COLUMN_COUNTRY: - if(iso1->GetCountry() > iso2->GetCountry()) return 1 *t; - if(iso1->GetCountry() < iso2->GetCountry()) return -1 *t; - return 0; - case CGameListCtrl::COLUMN_SIZE: - if (iso1->GetFileSize() > iso2->GetFileSize()) return 1 *t; - if (iso1->GetFileSize() < iso2->GetFileSize()) return -1 *t; - return 0; - case CGameListCtrl::COLUMN_PLATFORM: - if(iso1->GetPlatform() > iso2->GetPlatform()) return 1 *t; - if(iso1->GetPlatform() < iso2->GetPlatform()) return -1 *t; - return 0; - case CGameListCtrl::COLUMN_EMULATION_STATE: - IniFile ini; int nState1 = 0, nState2 = 0; - std::string GameIni1 = std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + iso1->GetUniqueID() + ".ini"; - std::string GameIni2 = std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + iso2->GetUniqueID() + ".ini"; - - ini.Load(GameIni1.c_str()); - ini.Get("EmuState", "EmulationStateId", &nState1); - ini.Load(GameIni2.c_str()); - ini.Get("EmuState", "EmulationStateId", &nState2); - - if(nState1 > nState2) return 1 *t; - if(nState1 < nState2) return -1 *t; - return 0; + case CGameListCtrl::COLUMN_TITLE: + return strcasecmp(iso1->GetName(indexOne).c_str(), + iso2->GetName(indexOther).c_str()) * t; + case CGameListCtrl::COLUMN_NOTES: + { + std::string cmp1 = + (iso1->GetPlatform() == GameListItem::GAMECUBE_DISC) ? + iso1->GetCompany() : iso1->GetDescription(indexOne); + std::string cmp2 = + (iso2->GetPlatform() == GameListItem::GAMECUBE_DISC) ? + iso2->GetCompany() : iso2->GetDescription(indexOther); + return strcasecmp(cmp1.c_str(), cmp2.c_str()) * t; + } + case CGameListCtrl::COLUMN_COUNTRY: + if(iso1->GetCountry() > iso2->GetCountry()) + return 1 * t; + if(iso1->GetCountry() < iso2->GetCountry()) + return -1 * t; + return 0; + case CGameListCtrl::COLUMN_SIZE: + if (iso1->GetFileSize() > iso2->GetFileSize()) + return 1 * t; + if (iso1->GetFileSize() < iso2->GetFileSize()) + return -1 * t; + return 0; + case CGameListCtrl::COLUMN_PLATFORM: + if(iso1->GetPlatform() > iso2->GetPlatform()) + return 1 * t; + if(iso1->GetPlatform() < iso2->GetPlatform()) + return -1 * t; + return 0; + case CGameListCtrl::COLUMN_EMULATION_STATE: + IniFile ini; + int nState1 = 0, nState2 = 0; + std::string GameIni1 = std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + + iso1->GetUniqueID() + ".ini"; + std::string GameIni2 = std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + + iso2->GetUniqueID() + ".ini"; + + ini.Load(GameIni1.c_str()); + ini.Get("EmuState", "EmulationStateId", &nState1); + ini.Load(GameIni2.c_str()); + ini.Get("EmuState", "EmulationStateId", &nState2); + + if(nState1 > nState2) + return 1 * t; + if(nState1 < nState2) + return -1 * t; + return 0; } - + return 0; } @@ -725,7 +793,7 @@ if(event.GetColumn() != COLUMN_BANNER) { int current_column = event.GetColumn(); - + if(last_column == current_column) { last_sort = -last_sort; @@ -735,7 +803,7 @@ last_column = current_column; last_sort = current_column; } - + caller = this; SortItems(wxListCompare, last_sort); } @@ -778,12 +846,14 @@ sLoop++; UnselectAll(); - SetItemState(i, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED); + SetItemState(i, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, + wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED); EnsureVisible(i); break; } - // If we get past the last game in the list, we'll have to go back to the first one. + // If we get past the last game in the list, + // we'll have to go back to the first one. if (i+1 == (int)m_ISOFiles.size() && sLoop > 0 && Loop > 0) i = -1; } @@ -794,15 +864,17 @@ // This shows a little tooltip with the current Game's emulation state void CGameListCtrl::OnMouseMotion(wxMouseEvent& event) { - int flags; long subitem = 0; + int flags; + long subitem = 0; long item = HitTest(event.GetPosition(), flags, &subitem); static int lastItem = -1; - if (item != wxNOT_FOUND) + if (item != wxNOT_FOUND) { if (subitem == COLUMN_EMULATION_STATE) { - if (toolTip || lastItem == item || this != FindFocus()) { + if (toolTip || lastItem == item || this != FindFocus()) + { event.Skip(); return; } @@ -810,10 +882,18 @@ const GameListItem& rISO = m_ISOFiles[GetItemData(item)]; IniFile ini; - ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + (rISO.GetUniqueID()) + ".ini").c_str()); + ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + + (rISO.GetUniqueID()) + ".ini").c_str()); // Emulation status - std::string emuState[5] = {"Broken", "Intro", "In-Game", "Playable", "Perfect"}, issues; + std::string emuState[5] = { + "Broken", + "Intro", + "In-Game", + "Playable", + "Perfect" + }; + std::string issues; int nState; ini.Get("EmuState", "EmulationStateId", &nState); @@ -830,15 +910,18 @@ if (nState > 0 && nState < 6) { char temp[2048]; - sprintf(temp, "^ %s%s%s", emuState[nState -1].c_str(), issues.size() > 0 ? " :\n" : "", issues.c_str()); + sprintf(temp, "^ %s%s%s", emuState[nState -1].c_str(), + issues.size() > 0 ? " :\n" : "", issues.c_str()); toolTip = new wxEmuStateTip(this, wxString(temp, *wxConvCurrent), &toolTip); } else toolTip = new wxEmuStateTip(this, wxT("Not Set"), &toolTip); - toolTip->SetBoundingRect(wxRect(mx - GetColumnWidth(subitem), my, GetColumnWidth(subitem), Rect.GetHeight())); - toolTip->SetPosition(wxPoint(mx - GetColumnWidth(subitem), my - 5 + Rect.GetHeight())); - + toolTip->SetBoundingRect(wxRect(mx - GetColumnWidth(subitem), + my, GetColumnWidth(subitem), Rect.GetHeight())); + toolTip->SetPosition(wxPoint(mx - GetColumnWidth(subitem), + my - 5 + Rect.GetHeight())); + lastItem = item; } } @@ -850,14 +933,15 @@ { // Focus the clicked item. int flags; - long item = HitTest(event.GetPosition(), flags); - if ((item != wxNOT_FOUND) && (GetSelectedItemCount() == 0) && (!event.ControlDown()) && (!event.ShiftDown())) + long item = HitTest(event.GetPosition(), flags); + if ((item != wxNOT_FOUND) && (GetSelectedItemCount() == 0) && + (!event.ControlDown()) && (!event.ShiftDown())) { SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); SetItemState(item, wxLIST_STATE_FOCUSED, wxLIST_STATE_FOCUSED); wxGetApp().GetCFrame()->UpdateGUI(); } - + event.Skip(); } @@ -865,8 +949,8 @@ { // Focus the clicked item. int flags; - long item = HitTest(event.GetPosition(), flags); - if (item != wxNOT_FOUND) + long item = HitTest(event.GetPosition(), flags); + if (item != wxNOT_FOUND) { if (GetItemState(item, wxLIST_STATE_SELECTED) != wxLIST_STATE_SELECTED) { @@ -892,7 +976,7 @@ } popupMenu->Append(IDM_OPENCONTAININGFOLDER, _("Open &containing folder")); popupMenu->AppendCheckItem(IDM_SETDEFAULTGCM, _("Set as &default ISO")); - + // First we have to decide a starting value when we append it if(selected_iso->GetFileName() == SConfig::GetInstance(). m_LocalCoreStartupParameter.m_strDefaultGCM) @@ -927,16 +1011,12 @@ const GameListItem * CGameListCtrl::GetSelectedISO() { if (m_ISOFiles.size() == 0) - { return NULL; - } else if (GetSelectedItemCount() == 0) - { return NULL; - } else { - long item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + long item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); if (item == wxNOT_FOUND) return new GameListItem(""); else @@ -953,7 +1033,7 @@ } } -void CGameListCtrl::OnOpenContainingFolder(wxCommandEvent& WXUNUSED (event)) +void CGameListCtrl::OnOpenContainingFolder(wxCommandEvent& WXUNUSED (event)) { const GameListItem *iso = GetSelectedISO(); if (!iso) @@ -963,7 +1043,7 @@ WxUtils::Explore(path.c_str()); } -void CGameListCtrl::OnOpenSaveFolder(wxCommandEvent& WXUNUSED (event)) +void CGameListCtrl::OnOpenSaveFolder(wxCommandEvent& WXUNUSED (event)) { const GameListItem *iso = GetSelectedISO(); if (!iso) @@ -991,27 +1071,26 @@ } } -// ======================================================= // Save this file as the default file -// ------------- -void CGameListCtrl::OnSetDefaultGCM(wxCommandEvent& event) +void CGameListCtrl::OnSetDefaultGCM(wxCommandEvent& event) { const GameListItem *iso = GetSelectedISO(); if (!iso) return; - - if (event.IsChecked()) // Write the new default value and save it the ini file + + if (event.IsChecked()) { - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = iso->GetFileName(); + // Write the new default value and save it the ini file + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = + iso->GetFileName(); SConfig::GetInstance().SaveSettings(); } - else // Othwerise blank the value and save it + else { + // Othwerise blank the value and save it SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = ""; SConfig::GetInstance().SaveSettings(); } } -// ============= - void CGameListCtrl::OnDeleteGCM(wxCommandEvent& WXUNUSED (event)) { @@ -1020,8 +1099,9 @@ const GameListItem *iso = GetSelectedISO(); if (!iso) return; - if (wxMessageBox(_("Are you sure you want to delete this file?\nIt will be gone forever!"), - wxMessageBoxCaptionStr, wxYES_NO | wxICON_EXCLAMATION) == wxYES) + if (wxMessageBox(wxT("Are you sure you want to delete this file?\n") + wxT("It will be gone forever!"), + wxMessageBoxCaptionStr, wxYES_NO | wxICON_EXCLAMATION) == wxYES) { File::Delete(iso->GetFileName().c_str()); Update(); @@ -1029,8 +1109,9 @@ } else { - if (wxMessageBox(_("Are you sure you want to delete these files?\nThey will be gone forever!"), - wxMessageBoxCaptionStr, wxYES_NO | wxICON_EXCLAMATION) == wxYES) + if (wxMessageBox(wxT("Are you sure you want to delete these files?\n") + wxT("They will be gone forever!"), + wxMessageBoxCaptionStr, wxYES_NO | wxICON_EXCLAMATION) == wxYES) { int selected = GetSelectedItemCount(); @@ -1044,7 +1125,7 @@ } } -void CGameListCtrl::OnProperties(wxCommandEvent& WXUNUSED (event)) +void CGameListCtrl::OnProperties(wxCommandEvent& WXUNUSED (event)) { const GameListItem *iso = GetSelectedISO(); if (!iso) @@ -1066,7 +1147,6 @@ 1000, // range this, // parent wxPD_APP_MODAL | - // wxPD_AUTO_HIDE | -- try this as well wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | @@ -1081,9 +1161,11 @@ void CGameListCtrl::MultiCompressCB(const char* text, float percent, void* arg) { percent = (((float)m_currentItem) + percent) / (float)m_numberItem; - wxString textString(StringFromFormat("%s (%i/%i) - %s", m_currentFilename.c_str(), (int)m_currentItem+1, (int)m_numberItem, text).c_str(), *wxConvCurrent); + wxString textString(StringFromFormat("%s (%i/%i) - %s", + m_currentFilename.c_str(), (int)m_currentItem+1, + (int)m_numberItem, text).c_str(), *wxConvCurrent); - ((wxProgressDialog*)arg)->Update((int)(percent*1000), textString); + ((wxProgressDialog*)arg)->Update((int)(percent*1000), textString); } void CGameListCtrl::OnMultiCompressGCM(wxCommandEvent& /*event*/) @@ -1101,61 +1183,82 @@ wxString dirHome; wxGetHomeDir(&dirHome); - wxDirDialog browseDialog(this, _("Browse for output directory"), dirHome, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST); + wxDirDialog browseDialog(this, _("Browse for output directory"), dirHome, + wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST); if (browseDialog.ShowModal() != wxID_OK) return; - wxProgressDialog progressDialog(_compress ? _("Compressing ISO") : _("Decompressing ISO"), - _("Working..."), - 1000, // range - this, // parent - wxPD_APP_MODAL | - // wxPD_AUTO_HIDE | -- try this as well - wxPD_ELAPSED_TIME | - wxPD_ESTIMATED_TIME | - wxPD_REMAINING_TIME | - wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small - ); - - progressDialog.SetSize(wxSize(600, 180)); + wxProgressDialog progressDialog(_compress ? + _("Compressing ISO") : _("Decompressing ISO"), + _("Working..."), + 1000, // range + this, // parent + wxPD_APP_MODAL | + wxPD_ELAPSED_TIME | + wxPD_ESTIMATED_TIME | + wxPD_REMAINING_TIME | + wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small + ); + + progressDialog.SetSize(wxSize(340, 180)); progressDialog.CenterOnParent(); m_currentItem = 0; m_numberItem = GetSelectedItemCount(); - for (u32 i=0; iIsCompressed() && _compress) { - std::string FileName; - SplitPath(iso->GetFileName(), NULL, &FileName, NULL); + std::string FileName, FileExt; + SplitPath(iso->GetFileName(), NULL, &FileName, &FileExt); m_currentFilename = FileName; FileName.append(".gcz"); std::string OutputFileName; - BuildCompleteFilename(OutputFileName, (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), FileName); - - DiscIO::CompressFileToBlob(iso->GetFileName().c_str(), OutputFileName.c_str(), (iso->GetPlatform() == GameListItem::WII_DISC) ? 1 : 0, 16384, &MultiCompressCB, &progressDialog); + BuildCompleteFilename(OutputFileName, + (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), + FileName); + + if (wxFileExists(wxString::FromAscii(OutputFileName.c_str())) && + wxMessageBox( + _("The file ") + wxString::FromAscii(OutputFileName.c_str()) + + _(" already exists.\nDo you wish to replace it?"), + _("Confirm File Overwrite"), + wxYES_NO) == wxNO) + continue; + + DiscIO::CompressFileToBlob(iso->GetFileName().c_str(), + OutputFileName.c_str(), + (iso->GetPlatform() == GameListItem::WII_DISC) ? 1 : 0, + 16384, &MultiCompressCB, &progressDialog); } else if (iso->IsCompressed() && !_compress) { - std::string FileName; - SplitPath(iso->GetFileName(), NULL, &FileName, NULL); + std::string FileName, FileExt; + SplitPath(iso->GetFileName(), NULL, &FileName, &FileExt); m_currentFilename = FileName; if (iso->GetPlatform() == GameListItem::WII_DISC) - { FileName.append(".iso"); - } else - { FileName.append(".gcm"); - } std::string OutputFileName; - BuildCompleteFilename(OutputFileName, (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), FileName); + BuildCompleteFilename(OutputFileName, + (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), + FileName); + + if (wxFileExists(wxString::FromAscii(OutputFileName.c_str())) && + wxMessageBox( + _("The file ") + wxString::FromAscii(OutputFileName.c_str()) + + _(" already exists.\nDo you wish to replace it?"), + _("Confirm File Overwrite"), + wxYES_NO) == wxNO) + continue; - DiscIO::DecompressBlobToFile(iso->GetFileName().c_str(), OutputFileName.c_str(), &MultiCompressCB, &progressDialog); + DiscIO::DecompressBlobToFile(iso->GetFileName().c_str(), + OutputFileName.c_str(), &MultiCompressCB, &progressDialog); } m_currentItem++; } @@ -1164,88 +1267,93 @@ void CGameListCtrl::CompressCB(const char* text, float percent, void* arg) { - ((wxProgressDialog*)arg)->Update((int)(percent*1000), wxString(text, *wxConvCurrent)); + ((wxProgressDialog*)arg)-> + Update((int)(percent*1000), wxString(text, *wxConvCurrent)); } -void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event)) +void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event)) { const GameListItem *iso = GetSelectedISO(); if (!iso) return; - wxString path, Ext; + wxString path; - std::string FileName; - SplitPath(iso->GetFileName(), NULL, &FileName, NULL); + std::string FileName, FilePath, FileExtension; + SplitPath(iso->GetFileName(), &FilePath, &FileName, &FileExtension); - if (iso->IsCompressed()) + do { - if (iso->GetPlatform() == GameListItem::WII_DISC) + if (iso->IsCompressed()) { - Ext = wxT("*.iso"); + wxString FileType; + if (iso->GetPlatform() == GameListItem::WII_DISC) + FileType = wxT("All Wii ISO files (iso)|*.iso"); + else + FileType = wxT("All Gamecube GCM files (gcm)|*.gcm"); + + path = wxFileSelector( + _T("Save decompressed GCM/ISO"), + wxString(FilePath.c_str(), *wxConvCurrent), + wxString(FileName.c_str(), *wxConvCurrent) + FileType.After('*'), + wxEmptyString, + FileType + + wxString::Format + ( + _T("|All files (%s)|%s"), + wxFileSelectorDefaultWildcardStr, + wxFileSelectorDefaultWildcardStr + ), + wxFD_SAVE, + this); } else { - Ext = wxT("*.gcm"); + path = wxFileSelector( + _T("Save compressed GCM/ISO"), + wxString(FilePath.c_str(), *wxConvCurrent), + wxString(FileName.c_str(), *wxConvCurrent) + _T(".gcz"), + wxEmptyString, + wxString::Format + ( + _T("All compressed GC/Wii ISO files (gcz)|*.gcz|All files (%s)|%s"), + wxFileSelectorDefaultWildcardStr, + wxFileSelectorDefaultWildcardStr + ), + wxFD_SAVE, + this); } - path = wxFileSelector( - _T("Save decompressed ISO"), - wxEmptyString, wxString(FileName.c_str(), *wxConvCurrent), wxEmptyString, - wxString::Format - ( - _T("All GC/Wii ISO files (%s)|%s|All files (%s)|%s"), - (char *)Ext.After('.').char_str(wxConvUTF8), - (char *)Ext.char_str(wxConvUTF8), - wxFileSelectorDefaultWildcardStr, - wxFileSelectorDefaultWildcardStr - ), - wxFD_SAVE, - this); - if (!path) - { return; - } - } - else - { - path = wxFileSelector( - _T("Save compressed ISO"), - wxEmptyString, wxString(FileName.c_str(), *wxConvCurrent), wxEmptyString, - wxString::Format - ( - _T("All compressed GC/Wii ISO files (gcz)|*.gcz|All files (%s)|%s"), - wxFileSelectorDefaultWildcardStr, - wxFileSelectorDefaultWildcardStr - ), - wxFD_SAVE, - this); - - if (!path) - { - return; - } - } + } while (wxFileExists(path) && + wxMessageBox( + _("The file ") + path + _(" already exists.\nDo you wish to replace it?"), + _("Confirm File Overwrite"), + wxYES_NO) == wxNO); + + wxProgressDialog dialog(iso->IsCompressed() ? + _T("Decompressing ISO") : _T("Compressing ISO"), + _T("Working..."), + 1000, // range + this, // parent + wxPD_APP_MODAL | + wxPD_ELAPSED_TIME | + wxPD_ESTIMATED_TIME | + wxPD_REMAINING_TIME | + wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small + ); - wxProgressDialog dialog(iso->IsCompressed() ? _T("Decompressing ISO") : _T("Compressing ISO"), - _T("Working..."), - 1000, // range - this, // parent - wxPD_APP_MODAL | - // wxPD_AUTO_HIDE | -- try this as well - wxPD_ELAPSED_TIME | - wxPD_ESTIMATED_TIME | - wxPD_REMAINING_TIME | - wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small - ); - - dialog.SetSize(wxSize(280, 180)); + dialog.SetSize(wxSize(340, 180)); dialog.CenterOnParent(); if (iso->IsCompressed()) - DiscIO::DecompressBlobToFile(iso->GetFileName().c_str(), path.char_str(), &CompressCB, &dialog); + DiscIO::DecompressBlobToFile(iso->GetFileName().c_str(), + path.char_str(), &CompressCB, &dialog); else - DiscIO::CompressFileToBlob(iso->GetFileName().c_str(), path.char_str(), (iso->GetPlatform() == GameListItem::WII_DISC) ? 1 : 0, 16384, &CompressCB, &dialog); + DiscIO::CompressFileToBlob(iso->GetFileName().c_str(), + path.char_str(), + (iso->GetPlatform() == GameListItem::WII_DISC) ? 1 : 0, + 16384, &CompressCB, &dialog); Update(); } @@ -1261,12 +1369,10 @@ void CGameListCtrl::AutomaticColumnWidth() { - wxRect rc(GetParent()->GetRect()); + wxRect rc(GetClientRect()); if (GetColumnCount() == 1) - { SetColumnWidth(0, rc.GetWidth()); - } else if (GetColumnCount() > 4) { int resizable = rc.GetWidth() - ( @@ -1274,14 +1380,13 @@ + GetColumnWidth(COLUMN_COUNTRY) + GetColumnWidth(COLUMN_SIZE) + GetColumnWidth(COLUMN_EMULATION_STATE) - + GetColumnWidth(COLUMN_PLATFORM) - + 5); // some pad to keep the horizontal scrollbar away :) + + GetColumnWidth(COLUMN_PLATFORM)); - // We hide the Company column if the window is too small - if (0.5*resizable > 200) + // We hide the Notes column if the window is too small + if (resizable > 400) { - SetColumnWidth(COLUMN_TITLE, 0.5*resizable); - SetColumnWidth(COLUMN_NOTES, 0.5*resizable); + SetColumnWidth(COLUMN_TITLE, resizable / 2); + SetColumnWidth(COLUMN_NOTES, resizable / 2); } else { diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/Globals.h dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/Globals.h --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/Globals.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/Globals.h 2010-08-18 03:25:16.000000000 +0100 @@ -16,19 +16,14 @@ // http://code.google.com/p/dolphin-emu/ - // This file holds global data for DolphinWx and DebuggerWx - #ifndef _GLOBALS_H #define _GLOBALS_H #include "Common.h" -// Constant Colors -const unsigned long COLOR_GRAY = 0xDCDCDC; - enum { Toolbar_DebugGo, @@ -85,6 +80,7 @@ IDM_FRAMESTEP, IDM_SCREENSHOT, IDM_BROWSE, + IDM_DRIVES, IDM_DRIVE1, IDM_DRIVE24 = IDM_DRIVE1 + 23,//248, @@ -202,6 +198,7 @@ ID_TOOLBAR_DEBUG, IDM_STEP, IDM_STEPOVER, + IDM_TOGGLE_BREAKPOINT, IDM_SKIP, IDM_SETPC, IDM_GOTOPC, @@ -247,49 +244,31 @@ LIST_CTRL = 1000 }; -#define wxUSE_XPM_IN_MSW 1 -#define USE_XPM_BITMAPS 1 - -// For compilers that support precompilation, includes . -//#include - -//#ifndef WX_PRECOMP -#if defined(HAVE_WX) && HAVE_WX - #include - //#endif - - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - // Define this to use XPMs everywhere (by default, BMPs are used under Win) - // BMPs use less space, but aren't compiled into the executable on other platforms - #if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW - #error You need to enable XPM support to use XPM bitmaps with toolbar! - #endif // USE_XPM_BITMAPS - - // custom message macro - #define EVT_HOST_COMMAND(id, fn) \ - DECLARE_EVENT_TABLE_ENTRY(\ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// custom message macro +#define EVT_HOST_COMMAND(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(\ wxEVT_HOST_COMMAND, id, wxID_ANY, \ (wxObjectEventFunction)(wxEventFunction) wxStaticCastEvent(wxCommandEventFunction, &fn), \ (wxObject*) NULL \ ), - extern const wxEventType wxEVT_HOST_COMMAND; +extern const wxEventType wxEVT_HOST_COMMAND; -#endif // HAVE_WX #endif // _GLOBALS_H - diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/HotkeyDlg.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/HotkeyDlg.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/HotkeyDlg.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/HotkeyDlg.cpp 2010-08-18 03:25:15.000000000 +0100 @@ -123,8 +123,8 @@ void HotkeyConfigDialog::DoGetButtons(int _GetId) { // Values used in this function - int Seconds = 4; // Seconds to wait for - int TimesPerSecond = 40; // How often to run the check + const int Seconds = 4; // Seconds to wait for + const int TimesPerSecond = 40; // How often to run the check // If the Id has changed or the timer is not running we should start one if( GetButtonWaitingID != _GetId || !m_ButtonMappingTimer->IsRunning() ) @@ -191,6 +191,7 @@ wxT("Toggle Fullscreen"), wxT("Play/Pause"), wxT("Stop"), + wxT("Take Screenshot"), wxT("Connect Wiimote 1"), wxT("Connect Wiimote 2"), wxT("Connect Wiimote 3"), diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/ISOFile.h dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/ISOFile.h --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/ISOFile.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/ISOFile.h 2010-08-18 03:25:15.000000000 +0100 @@ -21,6 +21,10 @@ #include "Volume.h" #include "VolumeCreator.h" +#if defined(HAVE_WX) && HAVE_WX +#include +#endif + class PointerWrap; class GameListItem { diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/ISOProperties.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/ISOProperties.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/ISOProperties.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/ISOProperties.cpp 2010-08-18 03:25:16.000000000 +0100 @@ -290,7 +290,9 @@ sbCoreOverrides = new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Core")); CPUThread = new wxCheckBox(m_GameConfig, ID_USEDUALCORE, _("Enable Dual Core"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); SkipIdle = new wxCheckBox(m_GameConfig, ID_IDLESKIP, _("Enable Idle Skipping"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); - TLBHack = new wxCheckBox(m_GameConfig, ID_TLBHACK, _("TLB Hack"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); + MMU = new wxCheckBox(m_GameConfig, ID_MMU, _("Enable MMU"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); + TLBHack = new wxCheckBox(m_GameConfig, ID_TLBHACK, _("MMU Speed Hack"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); + SMC = new wxCheckBox(m_GameConfig, ID_MMU, _("Enable self modifying code check"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); // Wii Console sbWiiOverrides = new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Wii Console")); EnableProgressiveScan = new wxCheckBox(m_GameConfig, ID_ENABLEPROGRESSIVESCAN, _("Enable Progressive Scan"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); @@ -316,6 +318,8 @@ SafeTextureCache = new wxCheckBox(m_GameConfig, ID_SAFETEXTURECACHE, _("Safe Texture Cache"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); DstAlphaPass = new wxCheckBox(m_GameConfig, ID_DSTALPHAPASS, _("Distance Alpha Pass"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); UseXFB = new wxCheckBox(m_GameConfig, ID_USEXFB, _("Use XFB"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); + UseZTPSpeedupHack = new wxCheckBox(m_GameConfig, ID_ZTP_SPEEDUP, _("ZTP hack"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); + UseZTPSpeedupHack->SetToolTip(wxT("Enable this to speed up The Legend of Zelda: Twilight Princess. Disable for ANY other game.")); // Hack Hacktext = new wxStaticText(m_GameConfig, ID_HACK_TEXT, _("Projection Hack for: "), wxDefaultPosition, wxDefaultSize); arrayStringFor_Hack.Add(_("None")); @@ -327,7 +331,7 @@ WMTightnessText = new wxStaticText(m_GameConfig, ID_WMTIGHTNESS_TEXT, wxT("Watermark tightness: "), wxDefaultPosition, wxDefaultSize); WMTightness = new wxTextCtrl(m_GameConfig, ID_WMTIGHTNESS, wxT(""), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC)); - WMTightness->SetToolTip(wxT("Change this if you get lots of FIFO overflow errors. Reasonable values range from 0 to 200.")); + WMTightness->SetToolTip(wxT("Change this if you get lots of FIFO overflow errors. Reasonable values range from 0 to 1000.")); // Emulation State sEmuState = new wxBoxSizer(wxHORIZONTAL); @@ -346,7 +350,9 @@ sbGameConfig->Add(OverrideText, 0, wxEXPAND|wxALL, 5); sbCoreOverrides->Add(CPUThread, 0, wxEXPAND|wxLEFT, 5); sbCoreOverrides->Add(SkipIdle, 0, wxEXPAND|wxLEFT, 5); + sbCoreOverrides->Add(MMU, 0, wxEXPAND|wxLEFT, 5); sbCoreOverrides->Add(TLBHack, 0, wxEXPAND|wxLEFT, 5); + sbCoreOverrides->Add(SMC, 0, wxEXPAND|wxLEFT, 5); sbWiiOverrides->Add(EnableProgressiveScan, 0, wxEXPAND|wxLEFT, 5); sbWiiOverrides->Add(EnableWideScreen, 0, wxEXPAND|wxLEFT, 5); sbVideoOverrides->Add(ForceFiltering, 0, wxEXPAND|wxLEFT, 5); @@ -355,6 +361,7 @@ sbVideoOverrides->Add(SafeTextureCache, 0, wxEXPAND|wxLEFT, 5); sbVideoOverrides->Add(DstAlphaPass, 0, wxEXPAND|wxLEFT, 5); sbVideoOverrides->Add(UseXFB, 0, wxEXPAND|wxLEFT, 5); + sbVideoOverrides->Add(UseZTPSpeedupHack, 0, wxEXPAND|wxLEFT, 5); wxFlexGridSizer* fifosizer = new wxFlexGridSizer(2, 2, 0, 0); fifosizer->Add(Hacktext, 0, wxLEFT, 5); @@ -520,9 +527,9 @@ sMain = new wxBoxSizer(wxVERTICAL); sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5); sMain->Add(sButtons, 0, wxEXPAND, 5); - sMain->SetMinSize(wxSize(400, 600)); + sMain->SetMinSize(wxSize(550, 600)); - m_Notebook->SetMaxSize(wxSize(400, 600)); + m_Notebook->SetMaxSize(wxSize(550, 600)); SetSizerAndFit(sMain); } @@ -809,11 +816,21 @@ else SkipIdle->Set3StateValue(wxCHK_UNDETERMINED); + if (GameIni.Get("Core", "MMU", &bTemp)) + MMU->Set3StateValue((wxCheckBoxState)bTemp); + else + MMU->Set3StateValue(wxCHK_UNDETERMINED); + if (GameIni.Get("Core", "TLBHack", &bTemp)) TLBHack->Set3StateValue((wxCheckBoxState)bTemp); else TLBHack->Set3StateValue(wxCHK_UNDETERMINED); + if (GameIni.Get("Core", "SMC", &bTemp)) + SMC->Set3StateValue((wxCheckBoxState)bTemp); + else + SMC->Set3StateValue(wxCHK_UNDETERMINED); + if (GameIni.Get("Wii", "ProgressiveScan", &bTemp)) EnableProgressiveScan->Set3StateValue((wxCheckBoxState)bTemp); else @@ -854,6 +871,11 @@ else UseXFB->Set3StateValue(wxCHK_UNDETERMINED); + if (GameIni.Get("Video", "ZTPSpeedupHack", &bTemp)) + UseZTPSpeedupHack->Set3StateValue((wxCheckBoxState)bTemp); + else + UseZTPSpeedupHack->Set3StateValue(wxCHK_UNDETERMINED); + if (GameIni.Get("Video", "FIFOWatermarkTightness", &sTemp)) WMTightness->SetValue(wxString(sTemp.c_str(), *wxConvCurrent)); else @@ -890,11 +912,21 @@ else GameIni.Set("Core", "SkipIdle", SkipIdle->Get3StateValue()); + if (MMU->Get3StateValue() == wxCHK_UNDETERMINED) + GameIni.DeleteKey("Core", "MMU"); + else + GameIni.Set("Core", "MMU", MMU->Get3StateValue()); + if (TLBHack->Get3StateValue() == wxCHK_UNDETERMINED) GameIni.DeleteKey("Core", "TLBHack"); else GameIni.Set("Core", "TLBHack", TLBHack->Get3StateValue()); + if (SMC->Get3StateValue() == wxCHK_UNDETERMINED) + GameIni.DeleteKey("Core", "SMC"); + else + GameIni.Set("Core", "SMC", SMC->Get3StateValue()); + if (EnableProgressiveScan->Get3StateValue() == wxCHK_UNDETERMINED) GameIni.DeleteKey("Wii", "ProgressiveScan"); else @@ -935,6 +967,11 @@ else GameIni.Set("Video", "UseXFB", UseXFB->Get3StateValue()); + if (UseZTPSpeedupHack->Get3StateValue() == wxCHK_UNDETERMINED) + GameIni.DeleteKey("Video", "ZTPSpeedupHack"); + else + GameIni.Set("Video", "ZTPSpeedupHack", UseZTPSpeedupHack->Get3StateValue()); + if (Hack->GetSelection() == -1) GameIni.DeleteKey("Video", "ProjectionHack"); else diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/ISOProperties.h dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/ISOProperties.h --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/ISOProperties.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/ISOProperties.h 2010-08-18 03:25:15.000000000 +0100 @@ -84,13 +84,13 @@ wxStaticText *OverrideText; // Core - wxCheckBox *CPUThread, *SkipIdle, *TLBHack; + wxCheckBox *CPUThread, *SkipIdle, *MMU, *SMC, *TLBHack; // Wii wxCheckBox *EnableProgressiveScan, *EnableWideScreen; // Video wxCheckBox *ForceFiltering, *EFBCopyDisable, *EFBToTextureEnable, - *SafeTextureCache, *DstAlphaPass, *UseXFB; + *SafeTextureCache, *DstAlphaPass, *UseXFB, *UseZTPSpeedupHack; wxStaticText *Hacktext; wxArrayString arrayStringFor_Hack; wxChoice *Hack; @@ -164,13 +164,16 @@ ID_OVERRIDE_TEXT, ID_USEDUALCORE, ID_IDLESKIP, + ID_MMU, ID_TLBHACK, + ID_SMC, ID_FORCEFILTERING, ID_EFBCOPYDISABLE, ID_EFBTOTEXTUREENABLE, ID_SAFETEXTURECACHE, ID_DSTALPHAPASS, ID_USEXFB, + ID_ZTP_SPEEDUP, ID_HACK_TEXT, ID_HACK, ID_WMTIGHTNESS_TEXT, diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/LogWindow.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/LogWindow.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/LogWindow.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/LogWindow.cpp 2010-08-18 03:25:16.000000000 +0100 @@ -15,20 +15,12 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ - -#include -#include -#include -#include -#include -#include - -#include "Core.h" // for Core::GetState() #include "LogWindow.h" #include "ConsoleListener.h" #include "Console.h" +#include "IniFile.h" #include "FileUtil.h" - +#include "DebuggerUIUtil.h" // Milliseconds between msgQueue flushes to wxTextCtrl #define UPDATETIME 200 @@ -46,6 +38,7 @@ EVT_CHECKBOX(IDM_WRITEWINDOW, CLogWindow::OnOptionsCheck) EVT_CHECKLISTBOX(IDM_LOGCHECKS, CLogWindow::OnLogCheck) EVT_TIMER(IDTM_UPDATELOG, CLogWindow::OnLogTimer) + EVT_SIZE(CLogWindow::OnSize) END_EVENT_TABLE() CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos, @@ -70,6 +63,9 @@ CreateGUIControls(); LoadSettings(); + + m_LogTimer = new wxTimer(this, IDTM_UPDATELOG); + m_LogTimer->Start(UPDATETIME); } void CLogWindow::CreateGUIControls() @@ -90,23 +86,27 @@ m_verbosity->SetFont(wxFont(7, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); // Font - m_FontChoice = new wxChoice(this, IDM_FONT, wxDefaultPosition, wxDefaultSize, 0, NULL, 0, wxDefaultValidator); + m_FontChoice = new wxChoice(this, IDM_FONT, + wxDefaultPosition, wxDefaultSize, 0, NULL, 0, wxDefaultValidator); m_FontChoice->Append(wxT("Default font")); m_FontChoice->Append(wxT("Monospaced font")); m_FontChoice->Append(wxT("Selected font")); m_FontChoice->SetSelection(0); DefaultFont = GetFont(); - MonoSpaceFont.SetNativeFontInfoUserDesc(wxString::FromAscii("lucida console windows-1252")); - Font.push_back(DefaultFont); - Font.push_back(MonoSpaceFont); - Font.push_back(DebuggerFont); + MonoSpaceFont.SetNativeFontInfoUserDesc(wxT("lucida console windows-1252")); + LogFont.push_back(DefaultFont); + LogFont.push_back(MonoSpaceFont); + LogFont.push_back(DebuggerFont); // Options wxCheckBox * m_WrapLine = new wxCheckBox(this, IDM_WRAPLINE, wxT("Word Wrap")); - m_writeFileCB = new wxCheckBox(this, IDM_WRITEFILE, wxT("Write to File"), wxDefaultPosition, wxDefaultSize, 0); - m_writeConsoleCB = new wxCheckBox(this, IDM_WRITECONSOLE, wxT("Write to Console"), wxDefaultPosition, wxDefaultSize, 0); - m_writeWindowCB = new wxCheckBox(this, IDM_WRITEWINDOW, wxT("Write to Window ->"), wxDefaultPosition, wxDefaultSize, 0); + m_writeFileCB = new wxCheckBox(this, IDM_WRITEFILE, + wxT("Write to File"), wxDefaultPosition, wxDefaultSize, 0); + m_writeConsoleCB = new wxCheckBox(this, IDM_WRITECONSOLE, + wxT("Write to Console"), wxDefaultPosition, wxDefaultSize, 0); + m_writeWindowCB = new wxCheckBox(this, IDM_WRITEWINDOW, + wxT("Write to Window ->"), wxDefaultPosition, wxDefaultSize, 0); m_checks = new wxCheckListBox(this, IDM_LOGCHECKS, wxDefaultPosition, wxDefaultSize); @@ -114,7 +114,6 @@ m_Log = CreateTextCtrl(this, IDM_LOG, wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP); m_cmdline = new wxTextCtrl(this, IDM_SUBMITCMD, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB); - //m_cmdline->SetFont(DebuggerFont); // Sizers sUber = new wxBoxSizer(wxHORIZONTAL); // whole plane @@ -125,8 +124,10 @@ wxStaticBoxSizer* sbLeftOptions = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Options")); wxBoxSizer* sLogCtrl = new wxBoxSizer(wxHORIZONTAL); - sLogCtrl->Add(new wxButton(this, IDM_TOGGLEALL, wxT("Toggle all"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT), 1); - sLogCtrl->Add(new wxButton(this, IDM_CLEARLOG, wxT("Clear"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT), 1); + sLogCtrl->Add(new wxButton(this, IDM_TOGGLEALL, wxT("Toggle all"), + wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT), 1); + sLogCtrl->Add(new wxButton(this, IDM_CLEARLOG, wxT("Clear"), + wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT), 1); sbLeftOptions->Add(m_FontChoice, 0, (wxDOWN), 1); sbLeftOptions->Add(m_WrapLine, 0, (wxDOWN), 1); @@ -145,13 +146,7 @@ sUber->Add(sRight, 1, wxEXPAND); this->SetSizer(sUber); - // Settings - // SetAffirmativeId(IDM_SUBMITCMD); - UpdateChecks(); m_cmdline->SetFocus(); - - m_LogTimer = new wxTimer(this, IDTM_UPDATELOG); - m_LogTimer->Start(UPDATETIME); } CLogWindow::~CLogWindow() @@ -170,14 +165,28 @@ event.Skip(); } +void CLogWindow::OnSize(wxSizeEvent& event) +{ + if (!Parent->g_pCodeWindow && + Parent->m_Mgr->GetPane(wxT("Pane 1")).IsShown()) + { + x = Parent->m_Mgr->GetPane(wxT("Pane 1")).rect.GetWidth(); + y = Parent->m_Mgr->GetPane(wxT("Pane 1")).rect.GetHeight(); + winpos = Parent->m_Mgr->GetPane(wxT("Pane 1")).dock_direction; + } + event.Skip(); +} + void CLogWindow::SaveSettings() { IniFile ini; + ini.Load(File::GetUserPath(F_LOGGERCONFIG_IDX)); + if (!Parent->g_pCodeWindow) { - ini.Set("LogWindow", "x", Parent->m_Mgr->GetPane(wxT("Pane 1")).rect.GetWidth()); - ini.Set("LogWindow", "y", Parent->m_Mgr->GetPane(wxT("Pane 1")).rect.GetHeight()); - ini.Set("LogWindow", "pos", Parent->m_Mgr->GetPane(wxT("Pane 1")).dock_direction); + ini.Set("LogWindow", "x", x); + ini.Set("LogWindow", "y", y); + ini.Set("LogWindow", "pos", winpos); } ini.Set("Options", "Verbosity", m_verbosity->GetSelection() + 1); ini.Set("Options", "Font", m_FontChoice->GetSelection()); @@ -205,8 +214,8 @@ m_verbosity->SetSelection(verbosity - 1); ini.Get("Options", "Font", &font, 0); m_FontChoice->SetSelection(font); - if (m_FontChoice->GetSelection() < (int)Font.size()) - m_Log->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, Font[m_FontChoice->GetSelection()])); + if (m_FontChoice->GetSelection() < (int)LogFont.size()) + m_Log->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, LogFont[m_FontChoice->GetSelection()])); ini.Get("Options", "WriteToFile", &m_writeFile, true); m_writeFileCB->SetValue(m_writeFile); ini.Get("Options", "WriteToConsole", &m_writeConsole, true); @@ -242,7 +251,6 @@ if (!m_cmdline) return; Console_Submit(m_cmdline->GetValue().To8BitData()); m_cmdline->SetValue(wxEmptyString); - NotifyUpdate(); } void CLogWindow::OnClear(wxCommandEvent& WXUNUSED (event)) @@ -256,8 +264,6 @@ m_LogSection.Leave(); m_console->ClearScreen(); - NOTICE_LOG(CONSOLE, "Console cleared"); - NotifyUpdate(); } // Enable or disable all boxes for the current verbosity level and save the changes. @@ -321,8 +327,8 @@ TC->SetBackgroundColour(*wxBLACK); if (m_FontChoice) { - if (m_FontChoice->GetSelection() < (int)Font.size()) - TC->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, Font[m_FontChoice->GetSelection()])); + if (m_FontChoice->GetSelection() < (int)LogFont.size()) + TC->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, LogFont[m_FontChoice->GetSelection()])); } return TC; } @@ -346,31 +352,36 @@ break; case IDM_WRAPLINE: - // SetWindowStyleFlag doesn't fully work, we need to redraw the window - //m_Log->SetWindowStyleFlag(m_Log->GetWindowStyleFlag() ^ wxTE_DONTWRAP); - /* Notice: To retain the colors when changing word wrapping we need to - loop through every letter with GetStyle and then reapply them letter by letter */ +#ifdef __WXGTK__ + m_Log->SetWindowStyleFlag(m_Log->GetWindowStyleFlag() ^ (wxTE_WORDWRAP | wxTE_DONTWRAP)); +#else + // Unfortunately wrapping styles can only be changed dynamically with wxGTK + // Notice: To retain the colors when changing word wrapping we need to + // loop through every letter with GetStyle and then reapply them letter by letter // Prevent m_Log access while it's being destroyed m_LogAccess = false; UnPopulateRight(); Text = m_Log->GetValue(); m_Log->Destroy(); - switch (event.IsChecked()) - { - case 0: m_Log = CreateTextCtrl(this, IDM_LOG, wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP); break; - case 1: m_Log = CreateTextCtrl(this, IDM_LOG, wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_WORDWRAP); break; - } + if (event.IsChecked()) + m_Log = CreateTextCtrl(this, IDM_LOG, + wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_WORDWRAP); + else + m_Log = CreateTextCtrl(this, IDM_LOG, + wxTE_RICH | wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP); m_Log->SetDefaultStyle(wxTextAttr(*wxWHITE)); m_Log->AppendText(Text); PopulateRight(); m_LogAccess = true; +#endif break; case IDM_FONT: // Update selected font - Font[Font.size()-1] = DebuggerFont; - m_Log->SetStyle(0, m_Log->GetLastPosition(), wxTextAttr(wxNullColour, wxNullColour, Font[event.GetSelection()])); - m_Log->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, Font[event.GetSelection()])); + LogFont[LogFont.size()-1] = DebuggerFont; + m_Log->SetStyle(0, m_Log->GetLastPosition(), + wxTextAttr(wxNullColour, wxNullColour, LogFont[event.GetSelection()])); + m_Log->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, LogFont[event.GetSelection()])); break; case IDM_WRITEFILE: @@ -413,12 +424,6 @@ m_LogManager->removeListener((LogTypes::LOG_TYPE)i, m_console); } } - /* - if (m_writeConsole && !m_console->IsOpen()) - wxGetApp().GetCFrame()->ToggleConsole(true); - else if (!m_writeConsole && m_console->IsOpen()) - wxGetApp().GetCFrame()->ToggleConsole(false); - */ break; } SaveSettings(); @@ -462,21 +467,13 @@ { if (!m_LogAccess) return; - //m_Log->Freeze(); UpdateLog(); - // Better auto scroll than wxTE_AUTO_SCROLL + // Scroll to the last line if (msgQueue.size() > 0) { m_Log->ScrollLines(1); m_Log->ShowPosition( m_Log->GetLastPosition() ); } - //m_Log->Thaw(); -} - -void CLogWindow::NotifyUpdate() -{ - UpdateChecks(); - //UpdateLog(); } void CLogWindow::UpdateLog() @@ -485,11 +482,8 @@ if (!m_Log) return; m_LogTimer->Stop(); - wxString collected_text; m_LogSection.Enter(); - // Rough estimate - collected_text.reserve(100 * msgQueue.size()); int msgQueueSize = (int)msgQueue.size(); for (int i = 0; i < msgQueueSize; i++) { @@ -527,13 +521,10 @@ // White timestamp m_Log->SetStyle(j, j + 9, wxTextAttr(*wxWHITE)); } - collected_text.Append(msgQueue.front().second); msgQueue.pop(); } m_LogSection.Leave(); - // Write all text at once, needs multiple SetStyle, may not be better - //if (collected_text.size()) m_Log->AppendText(collected_text); - // Return in 0.2 seconds + m_LogTimer->Start(UPDATETIME); } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/LogWindow.h dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/LogWindow.h --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/LogWindow.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/LogWindow.h 2010-08-18 03:25:16.000000000 +0100 @@ -17,12 +17,9 @@ #ifndef LOGWINDOW_H_ #define LOGWINDOW_H_ -#include "Main.h" // for wxGetApp + #include "LogManager.h" #include "Frame.h" -#include "DebuggerUIUtil.h" - -#include "IniFile.h" // Common #include "Thread.h" #include @@ -60,7 +57,6 @@ const wxString& name = wxT("Log") ); ~CLogWindow(); - void NotifyUpdate(); void SaveSettings(); void LoadSettings(); @@ -71,7 +67,7 @@ private: CFrame *Parent; wxFont DefaultFont, MonoSpaceFont; - std::vector Font; + std::vector LogFont; wxTimer *m_LogTimer; FileLogListener *m_fileLog; ConsoleListener *m_console; @@ -97,6 +93,7 @@ void CreateGUIControls(); void PopulateRight(); void UnPopulateRight(); void OnClose(wxCloseEvent& event); + void OnSize(wxSizeEvent& event); void OnSubmit(wxCommandEvent& event); void OnOptionsCheck(wxCommandEvent& event); void OnLogCheck(wxCommandEvent& event); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/Main.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/Main.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/Main.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/Main.cpp 2010-08-18 03:25:15.000000000 +0100 @@ -37,7 +37,6 @@ #include "Main.h" #include "ConfigManager.h" #include "CodeWindow.h" -#include "LogWindow.h" #include "JitWindow.h" #include "ExtendedTrace.h" #include "BootManager.h" @@ -350,8 +349,8 @@ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strWiimotePlugin = std::string(wiimotePluginFilename.mb_str()); - // Enable the PNG image handler - wxInitAllImageHandlers(); + // Enable the PNG image handler for screenshots + wxImage::AddHandler(new wxPNGHandler); SetEnableAlert(SConfig::GetInstance().m_LocalCoreStartupParameter.bUsePanicHandlers); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/MainNoGUI.cpp dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/MainNoGUI.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/MainNoGUI.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/MainNoGUI.cpp 2010-08-18 03:25:15.000000000 +0100 @@ -37,9 +37,7 @@ #endif #include "Core.h" -#include "Globals.h" #include "Host.h" -#include "ISOFile.h" #include "CPUDetect.h" #include "cmdline.h" #include "Thread.h" @@ -140,7 +138,7 @@ Display *dpy = XOpenDisplay(0); Window win = (Window)Core::GetWindowHandle(); - XSelectInput(dpy, win, KeyPressMask | KeyReleaseMask | FocusChangeMask); + XSelectInput(dpy, win, KeyPressMask | FocusChangeMask); #if defined(HAVE_XRANDR) && HAVE_XRANDR X11Utils::XRRConfiguration *XRRConfig = new X11Utils::XRRConfiguration(dpy, win); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/SConscript dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/SConscript --- dolphin-emu-2.0+svn5985/Source/Core/DolphinWX/Src/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DolphinWX/Src/SConscript 2010-08-18 03:25:15.000000000 +0100 @@ -3,6 +3,7 @@ Import('env') import os import sys +from SconsTests import utils files = [ 'BootManager.cpp', @@ -64,6 +65,8 @@ 'Library/Frameworks/Cg.framework', '#Externals/Cg/Cg.framework/Cg') + env.Install(env['data_dir'], '#Data/Sys') + env.Install(env['data_dir'], '#Data/User') env.Install(env['data_dir'], '#Source/Core/DolphinWX/resources/Dolphin.icns') @@ -79,23 +82,26 @@ CFBundleIdentifier = 'com.dolphin-emu.dolphin', CFBundlePackageType = 'APPL', CFBundleShortVersionString = - os.popen('svnversion -n ' + Dir('#').abspath).read(), + utils.GenerateRevFile('', Dir('#None').abspath, None), CFBundleVersion = '2.0', LSMinimumSystemVersion = '10.5.0', LSRequiresCarbon = True, ))) def Fixup(target, source, env): + if env['CPPDEFINES'].count('WXUSINGDLL'): + pass os.link(str(source[0]), str(target[0])) env.Append(BUILDERS = {'Fixup' : Builder(action = Fixup)}) env.Depends(exeGUIdist, env['plugin_dir']) - if env['CPPDEFINES'].count('WXUSINGDLL'): - env.Fixup(exeGUIdist, exeGUI) + env.Fixup(exeGUIdist, exeGUI) else: files += [ 'X11Utils.cpp' ] libs += [ 'SDL' ] exeGUI = env['binary_dir'] + '/dolphin-emu' exeNoGUI = env['binary_dir'] + '/dolphin-emu-nogui' + env.InstallAs(env['data_dir'] + '/sys', '#Data/Sys') + env.InstallAs(env['data_dir'] + '/user', '#Data/User') if env['HAVE_WX']: env.StaticLibrary(env['local_libs'] + 'memcard', memcardfiles) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/disassemble.cpp dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/disassemble.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/disassemble.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/disassemble.cpp 2010-08-18 03:25:20.000000000 +0100 @@ -202,7 +202,7 @@ if ((*pc & 0x7fff) >= 0x1000) { - *pc++; + ++pc; dest.append("; outside memory"); return false; } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/DspIntArithmetic.cpp dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/DspIntArithmetic.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/DspIntArithmetic.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/DspIntArithmetic.cpp 2010-08-18 03:25:20.000000000 +0100 @@ -47,8 +47,7 @@ void clrl(const UDSPInstruction opc) { u8 reg = (opc >> 8) & 0x1; - - s64 acc = (dsp_get_long_acc(reg) + 0x7fff) & ~0xffff; + s64 acc = dsp_round_long_acc(dsp_get_long_acc(reg)); zeroWriteBackLog(); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/DSPIntExtOps.cpp dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/DSPIntExtOps.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/DSPIntExtOps.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/DSPIntExtOps.cpp 2010-08-18 03:25:20.000000000 +0100 @@ -74,12 +74,7 @@ u8 sreg = (opc & 0x3) + DSP_REG_ACL0; u8 dreg = ((opc >> 2) & 0x3); -#if 0 //more tests - if ((sreg >= DSP_REG_ACM0) && (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT)) - writeToBackLog(0, dreg + DSP_REG_AXL0, ((u16)dsp_get_acc_h(sreg-DSP_REG_ACM0) & 0x0080) ? 0x8000 : 0x7fff); - else -#endif - writeToBackLog(0, dreg + DSP_REG_AXL0, g_dsp.r[sreg]); + writeToBackLog(0, dreg + DSP_REG_AXL0, g_dsp.r[sreg]); } // S @$arD, $acS.S @@ -475,7 +470,8 @@ } } -//needed for 0x3... +//needed for 0x3... cases when main and extended are modifying the same ACC +//games are not doing that + in motorola (similar dsp) dox this is forbidden to do //ex. corner case -> 0x3060: main opcode modifies .m, and extended .l -> .l shoudnt be zeroed because of .m write... void zeroWriteBackLogPreserveAcc(u8 acc) { diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/DspIntMultiplier.cpp dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/DspIntMultiplier.cpp --- dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/DspIntMultiplier.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/DspIntMultiplier.cpp 2010-08-18 03:25:20.000000000 +0100 @@ -33,7 +33,7 @@ s64 prod; if ((sign == 1) && (g_dsp.r[DSP_REG_SR] & SR_MUL_UNSIGNED)) //unsigned - prod = a * b; + prod = (u32)(a * b); else if ((sign == 2) && (g_dsp.r[DSP_REG_SR] & SR_MUL_UNSIGNED)) //mixed prod = a * (s16)b; else diff -Nru dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/DSPIntUtil.h dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/DSPIntUtil.h --- dolphin-emu-2.0+svn5985/Source/Core/DSPCore/Src/DSPIntUtil.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/DSPCore/Src/DSPIntUtil.h 2010-08-18 03:25:20.000000000 +0100 @@ -160,11 +160,6 @@ g_dsp.r[reg] = (u16)(s16)(s8)(u8)val; break; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - g_dsp.r[reg] = val; - break; - // Stack registers. case DSP_REG_ST0: case DSP_REG_ST1: @@ -217,7 +212,14 @@ inline s64 dsp_get_long_prod_round_prodl() { - return (dsp_get_long_prod() + 0x7fff) & ~0xffff; + s64 prod = dsp_get_long_prod(); + + if (prod & 0x10000) + prod = (prod + 0x8000) & ~0xffff; + else + prod = (prod + 0x7fff) & ~0xffff; + + return prod; } // For accurate emulation, this is wrong - but the real prod registers behave @@ -271,6 +273,16 @@ return ((s64)(s8)(val >> 32))<<32 | (u32)val; } +inline s64 dsp_round_long_acc(s64 val) +{ + if (val & 0x10000) + val = (val + 0x8000) & ~0xffff; + else + val = (val + 0x7fff) & ~0xffff; + + return val; +} + inline s16 dsp_get_acc_l(int _reg) { _assert_(_reg < 2); diff -Nru dolphin-emu-2.0+svn5985/Source/Core/InputUICommon/Src/ConfigDiag.cpp dolphin-emu-2.0+svn6107/Source/Core/InputUICommon/Src/ConfigDiag.cpp --- dolphin-emu-2.0+svn5985/Source/Core/InputUICommon/Src/ConfigDiag.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/InputUICommon/Src/ConfigDiag.cpp 2010-08-18 03:25:20.000000000 +0100 @@ -533,7 +533,7 @@ button_sizer->Add(add_button, 1, 0, 5); } - range_slider = new wxSlider( parent, -1, SLIDER_TICK_COUNT, 0, SLIDER_TICK_COUNT * 2, wxDefaultPosition, wxDefaultSize, wxSL_TOP | wxSL_LABELS /*| wxSL_AUTOTICKS*/ ); + range_slider = new wxSlider( parent, -1, SLIDER_TICK_COUNT, 0, SLIDER_TICK_COUNT * 5, wxDefaultPosition, wxDefaultSize, wxSL_TOP | wxSL_LABELS /*| wxSL_AUTOTICKS*/ ); range_slider->SetValue( control_reference->range * SLIDER_TICK_COUNT ); @@ -585,7 +585,7 @@ } } -void GamepadPage::LoadProfile( wxCommandEvent& event ) +void GamepadPage::LoadProfile(wxCommandEvent& event) { std::string fname; GamepadPage::GetProfilePath(fname); @@ -604,7 +604,7 @@ UpdateGUI(); } -void GamepadPage::SaveProfile( wxCommandEvent& event ) +void GamepadPage::SaveProfile(wxCommandEvent& event) { std::string fname; GamepadPage::GetProfilePath(fname); @@ -615,22 +615,27 @@ IniFile inifile; controller->SaveConfig(inifile.GetOrCreateSection("Profile")); inifile.Save(fname); + + m_config_dialog->UpdateProfileComboBox(); } - - m_config_dialog->UpdateProfileComboBox(); + else + PanicAlert("You must enter a valid profile name."); } -void GamepadPage::DeleteProfile( wxCommandEvent& event ) +void GamepadPage::DeleteProfile(wxCommandEvent& event) { std::string fname; GamepadPage::GetProfilePath(fname); const char* const fnamecstr = fname.c_str(); - if (File::Exists(fnamecstr)) + if (File::Exists(fnamecstr) && AskYesNo("Are you sure you want to delete \"%s\"?", + STR_FROM_WXSTR(profile_cbox->GetValue()).c_str())) + { File::Delete(fnamecstr); - m_config_dialog->UpdateProfileComboBox(); + m_config_dialog->UpdateProfileComboBox(); + } } void InputConfigDialog::UpdateDeviceComboBox() @@ -641,7 +646,8 @@ for ( ; i != e; ++i ) { (*i)->device_cbox->Clear(); - std::vector::const_iterator di = m_plugin.controller_interface.Devices().begin(), + std::vector::const_iterator + di = m_plugin.controller_interface.Devices().begin(), de = m_plugin.controller_interface.Devices().end(); for ( ; di!=de; ++di ) { @@ -670,11 +676,20 @@ m_plugin.controls_crit.Leave(); // leave } +ControlGroupBox::~ControlGroupBox() +{ + std::vector::const_iterator + i = options.begin(), + e = options.end(); + for (; i!=e; ++i) + delete *i; +} + ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWindow* const parent, wxWindow* const eventsink ) : wxStaticBoxSizer(wxVERTICAL, parent, wxString::FromAscii(group->name)) + , control_group(group) { - control_group = group; static_bitmap = NULL; wxFont m_SmallFont(7, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); @@ -689,7 +704,6 @@ ControlButton* const control_button = new ControlButton(parent, (*ci)->control_ref, 80); control_button->SetFont(m_SmallFont); - controls.push_back(control_button); control_buttons.push_back(control_button); if ((*ci)->control_ref->is_input) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/InputUICommon/Src/ConfigDiag.h dolphin-emu-2.0+svn6107/Source/Core/InputUICommon/Src/ConfigDiag.h --- dolphin-emu-2.0+svn5985/Source/Core/InputUICommon/Src/ConfigDiag.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/InputUICommon/Src/ConfigDiag.h 2010-08-18 03:25:20.000000000 +0100 @@ -161,12 +161,13 @@ { public: ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWindow* const parent, wxWindow* const eventsink ); + ~ControlGroupBox(); - ControllerEmu::ControlGroup* control_group; + std::vector options; + + ControllerEmu::ControlGroup* const control_group; wxStaticBitmap* static_bitmap; - std::vector< PadSetting* > options; - std::vector< wxButton* > controls; - std::vector control_buttons; + std::vector control_buttons; }; class ControlGroupsSizer : public wxBoxSizer diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/BPStructs.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/BPStructs.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/BPStructs.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/BPStructs.cpp 2010-08-18 03:25:16.000000000 +0100 @@ -34,10 +34,18 @@ using namespace BPFunctions; +u32 mapTexAddress; +bool mapTexFound; +int numWrites; + void BPInit() { memset(&bpmem, 0, sizeof(bpmem)); bpmem.bpMask = 0xFFFFFF; + + mapTexAddress = 0; + numWrites = 0; + mapTexFound = false; } void RenderToXFB(const BPCmd &bp, const EFBRectangle &rc, float yScale, float xfbLines, u32 xfbAddr, const u32 dstWidth, const u32 dstHeight) @@ -83,7 +91,35 @@ // FIXME: Hangs load-state, but should fix graphic-heavy games state loading //s_bpCritical.Enter(); - FlushPipeline(); + // BEGIN ZTP SPEEDUP HACK CHANGES + // This hunk of code disables the usual pipeline flush for certain BP Writes + // that occur while the minimap is being drawn in Zelda: Twilight Princess. + // This significantly increases speed while in hyrule field. In depth discussion + // on how this Hack came to be can be found at: http://forums.dolphin-emu.com/thread-10638.html + // -fircrestsk8 + if (g_ActiveConfig.bZTPSpeedHack) + { + if (!mapTexFound) + { + if (bp.address != BPMEM_TEV_COLOR_ENV && bp.address != BPMEM_TEV_ALPHA_ENV) + numWrites = 0; + else if (++numWrites >= 100) // seem that if 100 consecutive BP writes are called to either of these addresses in ZTP, + { // then it is safe to assume the map texture address is currently loaded into the BP memory + mapTexAddress = bpmem.tex[0].texImage3[0].hex << 5; + mapTexFound = true; + WARN_LOG(VIDEO, "\nZTP map texture found at address %08x\n", mapTexAddress); + } + FlushPipeline(); + } + else if ( (bpmem.tex[0].texImage3[0].hex << 5) != mapTexAddress || + bpmem.tevorders[0].getEnable(0) == 0 || + bp.address == BPMEM_TREF) + { + FlushPipeline(); + } + } // END ZTP SPEEDUP HACK + else FlushPipeline(); + ((u32*)&bpmem)[bp.address] = bp.newvalue; switch (bp.address) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/CommandProcessor.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/CommandProcessor.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/CommandProcessor.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/CommandProcessor.cpp 2010-08-18 03:25:16.000000000 +0100 @@ -77,7 +77,7 @@ #include "Fifo.h" #include "ChunkFile.h" #include "CommandProcessor.h" - +#include "PixelEngine.h" namespace CommandProcessor { @@ -411,6 +411,14 @@ m_CPStatusReg.OverflowHiWatermark = false; UpdateInterrupts(); + + // If the new fifo is being attached We make sure there wont be SetFinish event pending. + // This protection fix eternal darkness booting, because the second SetFinish event when it is booting + // seems invalid or has a bug and hang the game. + if (!fifo.bFF_GPReadEnable && tmpCtrl.GPReadEnable && !tmpCtrl.BPEnable) + { + PixelEngine::ResetSetFinish(); + } fifo.bFF_BPInt = tmpCtrl.BPInt; fifo.bFF_BPEnable = tmpCtrl.BPEnable; @@ -693,4 +701,18 @@ s_fifoIdleEvent.Set(); } +// This is called by the ProcessorInterface when PI_FIFO_RESET is writed, +// the general idea is abort all commands in the FIFO. +// This prevent Negative fifo.CPReadWriteDistance because when PI_FIFO_RESET happens +// the fifo.CPReadWriteDistance is writed to 0 +void AbortFrame() +{ + Fifo_SetRendering(false); + while(!fifo.CPCmdIdle) + Common::YieldCPU(); + Fifo_SetRendering(true); + PixelEngine::ResetSetToken(); + PixelEngine::ResetSetFinish(); +} + } // end of namespace CommandProcessor diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/CommandProcessor.h dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/CommandProcessor.h --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/CommandProcessor.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/CommandProcessor.h 2010-08-18 03:25:17.000000000 +0100 @@ -162,6 +162,7 @@ void FifoCriticalEnter(); void FifoCriticalLeave(); +void AbortFrame(); } // namespace CommandProcessor #endif // _COMMANDPROCESSOR_H diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/Fifo.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/Fifo.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/Fifo.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/Fifo.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -142,8 +142,7 @@ { video_initialize.pPeekMessages(); - VideoFifo_CheckEFBAccess(); - VideoFifo_CheckSwapRequest(); + VideoFifo_CheckAsyncRequest(); // check if we are able to run this buffer @@ -209,8 +208,7 @@ // If we don't, s_swapRequested (OGL only) or s_efbAccessRequested won't be set to false // leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing things down. - VideoFifo_CheckEFBAccess(); - VideoFifo_CheckSwapRequest(); + VideoFifo_CheckAsyncRequest(); CommandProcessor::isFifoBusy = false; } diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/Fifo.h dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/Fifo.h --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/Fifo.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/Fifo.h 2010-08-18 03:25:17.000000000 +0100 @@ -43,8 +43,6 @@ void Fifo_SetRendering(bool bEnabled); // Implemented by the Video Plugin -void VideoFifo_CheckSwapRequest(); -void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight); -void VideoFifo_CheckEFBAccess(); +void VideoFifo_CheckAsyncRequest(); #endif // _FIFO_H diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -26,7 +26,6 @@ #include #include #include -#include #include //#define DEBUG_OPENCL diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/PixelEngine.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/PixelEngine.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/PixelEngine.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/PixelEngine.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -377,4 +377,32 @@ INFO_LOG(PIXELENGINE, "VIDEO Set Finish"); } +//This function is used in CommandProcessor when write CTRL_REGISTER and the new fifo is attached. +void ResetSetFinish() +{ + //if SetFinish happened but PE_CTRL_REGISTER not, I reset the interrupt else + //remove event from the queque + if (g_bSignalFinishInterrupt) + { + g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, false); + g_bSignalFinishInterrupt = false; + + }else + { + g_VideoInitialize.pRemoveEvent(et_SetFinishOnMainThread); + } +} + +void ResetSetToken() +{ + if (g_bSignalTokenInterrupt) + { + g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, false); + g_bSignalTokenInterrupt = false; + + }else + { + g_VideoInitialize.pRemoveEvent(et_SetTokenOnMainThread); + } +} } // end of namespace PixelEngine diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/PixelEngine.h dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/PixelEngine.h --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/PixelEngine.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/PixelEngine.h 2010-08-18 03:25:16.000000000 +0100 @@ -67,6 +67,8 @@ // gfx plugin support void SetToken(const u16 _token, const int _bSetTokenAcknowledge); void SetFinish(void); +void ResetSetFinish(void); +void ResetSetToken(void); bool AllowIdleSkipping(); // Bounding box functionality. Paper Mario (both) are a couple of the few games that use it. diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/PixelShaderGen.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/PixelShaderGen.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/PixelShaderGen.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/PixelShaderGen.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -275,11 +275,11 @@ "(cc2.aaa)", // A2, "(textemp.rgb)", // TEXC, "(textemp.aaa)", // TEXA, - "(rastemp.rgb)", // RASC, - "(rastemp.aaa)", // RASA, + "(crastemp.rgb)", // RASC, + "(crastemp.aaa)", // RASA, "float3(1.0f, 1.0f, 1.0f)", // ONE "float3(0.5f, 0.5f, 0.5f)", // HALF - "(konsttemp.rgb)", //"konsttemp.rgb", // KONST + "(ckonsttemp.rgb)", //"konsttemp.rgb", // KONST "float3(0.0f, 0.0f, 0.0f)", // ZERO "PADERROR", "PADERROR", "PADERROR", "PADERROR" }; @@ -300,8 +300,8 @@ "cc1", // A1, "cc2", // A2, "textemp", // TEXA, - "rastemp", // RASA, - "konsttemp", // KONST, (hw1 had quarter) + "crastemp", // RASA, + "ckonsttemp", // KONST, (hw1 had quarter) "float4(0.0f, 0.0f, 0.0f, 0.0f)", // ZERO "PADERROR", "PADERROR", "PADERROR", "PADERROR", "PADERROR", "PADERROR", "PADERROR", "PADERROR", @@ -487,7 +487,7 @@ " float4 alphabump=0;\n" " float3 tevcoord;\n" " float2 wrappedcoord, tempcoord;\n" - " float4 cc0, cc1, cc2, cprev;\n\n"); + " float4 cc0, cc1, cc2, cprev,crastemp,ckonsttemp;\n\n"); // HACK to handle cases where the tex gen is not enabled if (numTexgen == 0) @@ -739,7 +739,18 @@ WRITE(p, "tevcoord.xy = wrappedcoord + indtevtrans%d;\n", n); } - WRITE(p, "rastemp = %s.%s;\n", tevRasTable[bpmem.tevorders[n / 2].getColorChan(n & 1)], rasswap); + TevStageCombiner::ColorCombiner &cc = bpmem.combiners[n].colorC; + TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[n].alphaC; + + bool bCRas = cc.a == TEVCOLORARG_RASA || cc.a == TEVCOLORARG_RASC || cc.b == TEVCOLORARG_RASA || cc.b == TEVCOLORARG_RASC || cc.c == TEVCOLORARG_RASA || cc.c == TEVCOLORARG_RASC || cc.d == TEVCOLORARG_RASA || cc.d == TEVCOLORARG_RASC; + bool bARas = ac.a == TEVALPHAARG_RASA || ac.b == TEVALPHAARG_RASA || ac.c == TEVALPHAARG_RASA || ac.d == TEVALPHAARG_RASA; + + if(bCRas || bARas) + { + WRITE(p, "rastemp = %s.%s;\n", tevRasTable[bpmem.tevorders[n / 2].getColorChan(n & 1)], rasswap); + WRITE(p, "crastemp = frac(4.0f + rastemp * (255.0f/256.0f)) * (256.0f/255.0f);\n"); + } + if (bpmem.tevorders[n/2].getEnable(n&1)) { @@ -761,13 +772,22 @@ int kc = bpmem.tevksel[n / 2].getKC(n & 1); int ka = bpmem.tevksel[n / 2].getKA(n & 1); - TevStageCombiner::ColorCombiner &cc = bpmem.combiners[n].colorC; - TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[n].alphaC; + bool bCKonst = cc.a == TEVCOLORARG_KONST || cc.b == TEVCOLORARG_KONST || cc.c == TEVCOLORARG_KONST || cc.d == TEVCOLORARG_KONST; bool bAKonst = ac.a == TEVALPHAARG_KONST || ac.b == TEVALPHAARG_KONST || ac.c == TEVALPHAARG_KONST || ac.d == TEVALPHAARG_KONST; if (bCKonst || bAKonst ) + { WRITE(p, "konsttemp = float4(%s, %s);\n", tevKSelTableC[kc], tevKSelTableA[ka]); + if(kc > 12 || ka > 15) + { + WRITE(p, "ckonsttemp = frac(4.0f + konsttemp * (255.0f/256.0f)) * (256.0f/255.0f);\n"); + } + else + { + WRITE(p, "ckonsttemp = konsttemp;\n"); + } + } if(cc.a == TEVCOLORARG_CPREV || cc.a == TEVCOLORARG_APREV @@ -1067,10 +1087,10 @@ "", //? "", //Linear "", //? - " fog = 1.0f - pow(2, -8.0f * fog);\n", //exp - " fog = 1.0f - pow(2, -8.0f * fog * fog);\n", //exp2 - " fog = pow(2, -8.0f * (1.0f - fog));\n", //backward exp - " fog = 1.0f - fog;\n fog = pow(2, -8.0f * fog * fog);\n" //backward exp2 + " fog = 1.0f - pow(2.0f, -8.0f * fog);\n", //exp + " fog = 1.0f - pow(2.0f, -8.0f * fog * fog);\n", //exp2 + " fog = pow(2.0f, -8.0f * (1.0f - fog));\n", //backward exp + " fog = 1.0f - fog;\n fog = pow(2.0f, -8.0f * fog * fog);\n" //backward exp2 }; static void WriteFog(char *&p) diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/TextureDecoder.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/TextureDecoder.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/TextureDecoder.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/TextureDecoder.cpp 2010-08-18 03:25:16.000000000 +0100 @@ -15,14 +15,6 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include - -#if _M_SSE >= 0x401 -#include -#elif _M_SSE >= 0x301 -#include -#endif - #include "Common.h" //#include "VideoCommon.h" // to get debug logs @@ -37,6 +29,14 @@ #include "LookUpTables.h" +#include + +#if _M_SSE >= 0x401 +#include +#elif _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__) +#include +#endif + bool TexFmt_Overlay_Enable=false; bool TexFmt_Overlay_Center=false; diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexLoader_Normal.cpp 2010-08-18 03:25:16.000000000 +0100 @@ -22,7 +22,7 @@ #include "NativeVertexWriter.h" #include "CPUDetect.h" -#if _M_SSE >= 0x301 +#if _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__) #include #endif diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexLoader_Normal.h dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexLoader_Normal.h --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexLoader_Normal.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexLoader_Normal.h 2010-08-18 03:25:16.000000000 +0100 @@ -18,6 +18,7 @@ #ifndef _VERTEXLOADER_NORMAL_H #define _VERTEXLOADER_NORMAL_H +#include "Common.h" #include "CommonTypes.h" class VertexLoader_Normal diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexLoader_Position.cpp 2010-08-18 03:25:16.000000000 +0100 @@ -22,7 +22,7 @@ #include "NativeVertexWriter.h" #include "CPUDetect.h" -#if _M_SSE >= 0x301 +#if _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__) #include #endif diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexLoader_TextCoord.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -24,7 +24,7 @@ #if _M_SSE >= 0x401 #include -#elif _M_SSE >= 0x301 +#elif _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__) #include #endif diff -Nru dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexShaderGen.cpp dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexShaderGen.cpp --- dolphin-emu-2.0+svn5985/Source/Core/VideoCommon/Src/VertexShaderGen.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Core/VideoCommon/Src/VertexShaderGen.cpp 2010-08-18 03:25:17.000000000 +0100 @@ -260,18 +260,19 @@ if (alpha.matsource) {// from vertex if (components & (VB_HAS_COL0< + + diff -Nru dolphin-emu-2.0+svn5985/Source/DSPSpy/main_spy.cpp dolphin-emu-2.0+svn6107/Source/DSPSpy/main_spy.cpp --- dolphin-emu-2.0+svn5985/Source/DSPSpy/main_spy.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/DSPSpy/main_spy.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -50,8 +50,7 @@ #include "ConsoleHelper.h" -// Pull in some constants etc from DSPCore. -#include "../Core/DSPCore/Src/DSPCore.h" +#include "dspregs.h" // This is where the DSP binary is. #include "dsp_code.h" diff -Nru dolphin-emu-2.0+svn5985/Source/DSPSpy/Stubs.cpp dolphin-emu-2.0+svn6107/Source/DSPSpy/Stubs.cpp --- dolphin-emu-2.0+svn5985/Source/DSPSpy/Stubs.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/DSPSpy/Stubs.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -17,6 +17,7 @@ // Stubs to make DSPCore compile as part of DSPSpy. +/* #include #include @@ -117,3 +118,5 @@ } } + +*/ \ No newline at end of file diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj 2010-08-18 03:25:21.000000000 +0100 @@ -571,6 +571,14 @@ > + + + + diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -15,7 +15,6 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ - #include "Config.h" #include "ConfigDlg.h" @@ -28,24 +27,33 @@ EVT_COMMAND_SCROLL(ID_VOLUME, DSPConfigDialogHLE::VolumeChanged) END_EVENT_TABLE() -DSPConfigDialogHLE::DSPConfigDialogHLE(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) +DSPConfigDialogHLE::DSPConfigDialogHLE(wxWindow *parent, wxWindowID id, + const wxString &title, const wxPoint &position, const wxSize& size, long style) : wxDialog(parent, id, title, position, size, style) { - m_OK = new wxButton(this, wxID_OK, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - + wxButton *m_OK = new wxButton(this, wxID_OK, wxT("OK"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + wxStaticBoxSizer *sbSettings = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Sound Settings")); wxStaticBoxSizer *sbSettingsV = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Volume")); // Create items - m_buttonEnableHLEAudio = new wxCheckBox(this, ID_ENABLE_HLE_AUDIO, wxT("Enable HLE Audio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_buttonEnableDTKMusic = new wxCheckBox(this, ID_ENABLE_DTK_MUSIC, wxT("Enable DTK Music"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_buttonEnableThrottle = new wxCheckBox(this, ID_ENABLE_THROTTLE, wxT("Enable Audio Throttle"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - wxStaticText *BackendText = new wxStaticText(this, wxID_ANY, wxT("Audio Backend"), wxDefaultPosition, wxDefaultSize, 0); - m_BackendSelection = new wxChoice(this, ID_BACKEND, wxDefaultPosition, wxSize(110, 20), wxArrayBackends, 0, wxDefaultValidator, wxEmptyString); + m_buttonEnableHLEAudio = new wxCheckBox(this, ID_ENABLE_HLE_AUDIO, wxT("Enable HLE Audio"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_buttonEnableDTKMusic = new wxCheckBox(this, ID_ENABLE_DTK_MUSIC, wxT("Enable DTK Music"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_buttonEnableThrottle = new wxCheckBox(this, ID_ENABLE_THROTTLE, wxT("Enable Audio Throttle"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + wxStaticText *BackendText = new wxStaticText(this, wxID_ANY, wxT("Audio Backend"), + wxDefaultPosition, wxDefaultSize, 0); + m_BackendSelection = new wxChoice(this, ID_BACKEND, wxDefaultPosition, wxSize(110, 20), + wxArrayBackends, 0, wxDefaultValidator, wxEmptyString); - m_volumeSlider = new wxSlider(this, ID_VOLUME, ac_Config.m_Volume, 1, 100, wxDefaultPosition, wxDefaultSize, wxSL_VERTICAL|wxSL_INVERSE); + m_volumeSlider = new wxSlider(this, ID_VOLUME, ac_Config.m_Volume, 1, 100, + wxDefaultPosition, wxDefaultSize, wxSL_VERTICAL | wxSL_INVERSE); m_volumeSlider->Enable(SupportsVolumeChanges(ac_Config.sBackend)); - m_volumeText = new wxStaticText(this, wxID_ANY, wxString::Format(wxT("%d %%"), ac_Config.m_Volume), wxDefaultPosition, wxDefaultSize, 0); + m_volumeText = new wxStaticText(this, wxID_ANY, wxString::Format(wxT("%d %%"), + ac_Config.m_Volume), wxDefaultPosition, wxDefaultSize, 0); // Update values m_buttonEnableHLEAudio->SetValue(g_Config.m_EnableHLEAudio ? true : false); @@ -59,8 +67,9 @@ wxT("Disabling this could cause abnormal game speed, such as too fast.\n") wxT("But sometimes enabling this could cause constant noise.\n") wxT("\nKeyboard Shortcut : Hold down to instantly disable Throttle.")); - m_BackendSelection->SetToolTip(wxT("Changing this will have no effect while the emulator is running!")); - m_volumeSlider->SetToolTip(wxT("This setting only affects DSound and OpenAL.")); + m_BackendSelection-> + SetToolTip(wxT("Changing this will have no effect while the emulator is running!")); + m_volumeSlider->SetToolTip(wxT("This setting only affects DSound, OpenAL, and PulseAudio.")); // Create sizer and add items to dialog wxBoxSizer *sMain = new wxBoxSizer(wxVERTICAL); @@ -75,14 +84,14 @@ sBackend->Add(m_BackendSelection, 0, wxALL, 1); sbSettings->Add(sBackend, 0, wxALL, 2); - sbSettingsV->Add(m_volumeSlider, 0, wxLEFT|wxRIGHT|wxALIGN_CENTER, 6); + sbSettingsV->Add(m_volumeSlider, 1, wxLEFT|wxRIGHT|wxALIGN_CENTER, 6); sbSettingsV->Add(m_volumeText, 0, wxALL|wxALIGN_LEFT, 4); sSettings->Add(sbSettings, 0, wxALL|wxEXPAND, 4); sSettings->Add(sbSettingsV, 0, wxALL|wxEXPAND, 4); sMain->Add(sSettings, 0, wxALL|wxEXPAND, 4); - - sButtons->AddStretchSpacer(); + + sButtons->AddStretchSpacer(); sButtons->Add(m_OK, 0, wxALL, 1); sMain->Add(sButtons, 0, wxALL|wxEXPAND, 4); SetSizerAndFit(sMain); @@ -145,10 +154,12 @@ // but getting the backend from string etc. is probably // too much just to enable/disable a stupid slider... return (backend == BACKEND_DIRECTSOUND || - backend == BACKEND_OPENAL); + backend == BACKEND_OPENAL || + backend == BACKEND_PULSEAUDIO); } void DSPConfigDialogHLE::BackendChanged(wxCommandEvent& event) { - m_volumeSlider->Enable(SupportsVolumeChanges(std::string(m_BackendSelection->GetStringSelection().mb_str()))); + m_volumeSlider->Enable(SupportsVolumeChanges( + std::string(m_BackendSelection->GetStringSelection().mb_str()))); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.h 2010-08-18 03:25:22.000000000 +0100 @@ -36,13 +36,12 @@ virtual ~DSPConfigDialogHLE(); void AddBackend(const char *backend); void ClearBackends(); - + private: DECLARE_EVENT_TABLE(); - + wxSlider* m_volumeSlider; wxStaticText* m_volumeText; - wxButton* m_OK; wxCheckBox* m_buttonEnableHLEAudio; wxCheckBox* m_buttonEnableDTKMusic; wxCheckBox* m_buttonEnableThrottle; @@ -57,7 +56,7 @@ ID_BACKEND, ID_VOLUME }; - + void OnOK(wxCommandEvent& event); void SettingsChanged(wxCommandEvent& event); void VolumeChanged(wxScrollEvent& event); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -21,6 +21,7 @@ CDSPHandler::CDSPHandler() : m_pUCode(NULL), + m_lastUCode(NULL), m_bHalt(false), m_bAssertInt(false) { @@ -86,3 +87,23 @@ m_MailHandler.Clear(); m_pUCode = UCodeFactory(_crc, m_MailHandler); } + +// TODO do it better? +// Assumes that every odd call to this func is by the persistent ucode. +// Even callers are deleted. +void CDSPHandler::SwapUCode(u32 _crc) +{ + m_MailHandler.Clear(); + + if (m_lastUCode == NULL) + { + m_lastUCode = m_pUCode; + m_pUCode = UCodeFactory(_crc, m_MailHandler); + } + else + { + delete m_pUCode; + m_pUCode = m_lastUCode; + m_lastUCode = NULL; + } +} diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/DSPHandler.h 2010-08-18 03:25:22.000000000 +0100 @@ -32,6 +32,7 @@ void SendMailToDSP(u32 _uMail); IUCode* GetUCode(); void SetUCode(u32 _crc); + void SwapUCode(u32 _crc); CMailHandler& AccessMailHandler() { return m_MailHandler; } @@ -63,6 +64,8 @@ static CDSPHandler* m_pInstance; IUCode* m_pUCode; + IUCode* m_lastUCode; + UDSPControl m_DSPControl; CMailHandler m_MailHandler; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/MailHandler.h 2010-08-18 03:25:22.000000000 +0100 @@ -45,7 +45,7 @@ else { // WARN_LOG(DSPHLE, "GetNextMail: No mails"); - return 0; // + return 0; } } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -103,22 +103,6 @@ } #endif -#if defined(HAVE_WX) && HAVE_WX -wxWindow* GetParentedWxWindow(HWND Parent) -{ -#ifdef _WIN32 - wxSetInstance((HINSTANCE)g_hInstance); - wxWindow *win = new wxWindow(); - win->SetHWND((WXHWND)Parent); - win->AdoptAttributesFromHWND(); - return win; -#else - return new wxWindow(); -#endif -} -#endif - - void *DllDebugger(void *_hParent, bool Show) { return NULL; @@ -145,14 +129,13 @@ LogManager::SetInstance((LogManager*)globals->logManager); } -void DllConfig(HWND _hParent) +void DllConfig(void *_hParent) { #if defined(HAVE_WX) && HAVE_WX // Load config settings g_Config.Load(); - wxWindow *frame = GetParentedWxWindow(_hParent); - m_ConfigFrame = new DSPConfigDialogHLE(frame); + m_ConfigFrame = new DSPConfigDialogHLE((wxWindow *)_hParent); // add backends std::vector backends = AudioCommon::GetSoundBackends(); @@ -163,23 +146,8 @@ m_ConfigFrame->AddBackend((*iter).c_str()); } - // Only allow one open at a time -#ifdef _WIN32 - frame->Disable(); - m_ConfigFrame->ShowModal(); - frame->Enable(); -#else m_ConfigFrame->ShowModal(); -#endif - -#ifdef _WIN32 - frame->SetFocus(); - frame->SetHWND(NULL); -#endif - m_ConfigFrame->Destroy(); - m_ConfigFrame = NULL; - frame->Destroy(); #endif } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/SConscript dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/SConscript --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/SConscript 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/SConscript 2010-08-18 03:25:22.000000000 +0100 @@ -17,6 +17,7 @@ 'UCodes/UCode_InitAudioSystem.cpp', 'UCodes/UCode_ROM.cpp', 'UCodes/UCodes.cpp', + 'UCodes/UCode_GBA.cpp', 'UCodes/UCode_Zelda.cpp', 'UCodes/UCode_Zelda_ADPCM.cpp', 'UCodes/UCode_Zelda_Voice.cpp', diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_ADPCM.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_ADPCM.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_ADPCM.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_ADPCM.h 2010-08-18 03:25:22.000000000 +0100 @@ -83,7 +83,8 @@ //if (mixer_control > 1000 && x > mixer_control) x = mixer_control; // maybe mixer_control also // has a volume target? //if (x >= 0x7fff) x = 0x7fff; // this seems a little high - if (x >= 0x4e20) x = 0x4e20; // add a definitive limit at 20 000 + //if (x >= 0x4e20) x = 0x4e20; // add a definitive limit at 20 000 + if (x >= 0x8000) x = 0x8000; // clamp to 32768; return x; // update volume } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -211,14 +211,10 @@ // Handle incoming mail void CUCode_AX::HandleMail(u32 _uMail) { - static s8 newucodemails = -1; - - if (newucodemails > -1) { - newucodemails++; - if (newucodemails == 10) { - newucodemails = -1; - m_rMailHandler.PushMail(DSP_RESUME); - } + if (m_UploadSetupInProgress) + { + PrepareBootUCode(_uMail); + return; } else { if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST) @@ -232,13 +228,16 @@ } else if (_uMail == 0xCDD10001) // Action 1 - new ucode upload ( GC: BayBlade S.T.B,...) { - NOTICE_LOG(DSPHLE,"DSP IROM - New Ucode!"); - newucodemails = 0; + DEBUG_LOG(DSPHLE,"DSP IROM - New Ucode!"); + // TODO find a better way to protect from HLEMixer? + soundStream->GetMixer()->SetHLEReady(false); + m_UploadSetupInProgress = true; } else if (_uMail == 0xCDD10002) // Action 2 - IROM_Reset(); ( GC: NFS Carbon, FF Crystal Chronicles,...) { - NOTICE_LOG(DSPHLE,"DSP IROM - Reset!"); + DEBUG_LOG(DSPHLE,"DSP IROM - Reset!"); CDSPHandler::GetInstance().SetUCode(UCODE_ROM); + return; } else if (_uMail == 0xCDD10003) // Action 3 - AX_GetNextCmdBlock(); { @@ -256,8 +255,13 @@ // Update with DSP Interrupt void CUCode_AX::Update(int cycles) { + if (NeedsResumeMail()) + { + m_rMailHandler.PushMail(DSP_RESUME); + g_dspInitialize.pGenerateDSPInterrupt(); + } // check if we have to send something - if (!m_rMailHandler.IsEmpty()) + else if (!m_rMailHandler.IsEmpty()) { g_dspInitialize.pGenerateDSPInterrupt(); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_Voice.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_Voice.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_Voice.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_Voice.h 2010-08-18 03:25:22.000000000 +0100 @@ -156,6 +156,7 @@ for (int s = 0; s < _iSize; s++) { int sample = 0; + u32 oldFrac = frac; frac += ratio; u32 newSamplePos = samplePos + (frac >> 16); //whole number of frac @@ -164,36 +165,37 @@ switch (pb.audio_addr.sample_format) { case AUDIOFORMAT_PCM8: - // TODO - the linear interpolation code below is somewhat suspicious - pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample - pb.adpcm.yn1 = ((s8)g_dspInitialize.pARAM_Read_U8(samplePos)) << 8; + pb.adpcm.yn2 = ((s8)g_dspInitialize.pARAM_Read_U8(samplePos)) << 8; //current sample + pb.adpcm.yn1 = ((s8)g_dspInitialize.pARAM_Read_U8(samplePos + 1)) << 8; //next sample if (pb.src_type == SRCTYPE_NEAREST) - { - sample = pb.adpcm.yn1; - } + sample = pb.adpcm.yn2; else // linear interpolation - { - sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16; - } + sample = (pb.adpcm.yn1 * (u16)oldFrac + pb.adpcm.yn2 * (u16)(0xFFFF - oldFrac) + pb.adpcm.yn2) >> 16; samplePos = newSamplePos; break; case AUDIOFORMAT_PCM16: - // TODO - the linear interpolation code below is somewhat suspicious - pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample - pb.adpcm.yn1 = (s16)(u16)((g_dspInitialize.pARAM_Read_U8(samplePos * 2) << 8) | (g_dspInitialize.pARAM_Read_U8((samplePos * 2 + 1)))); - if (pb.src_type == SRCTYPE_NEAREST) - sample = pb.adpcm.yn1; + pb.adpcm.yn2 = (s16)(u16)((g_dspInitialize.pARAM_Read_U8(samplePos * 2) << 8) | (g_dspInitialize.pARAM_Read_U8((samplePos * 2 + 1)))); //current sample + pb.adpcm.yn1 = (s16)(u16)((g_dspInitialize.pARAM_Read_U8((samplePos + 1) * 2) << 8) | (g_dspInitialize.pARAM_Read_U8(((samplePos + 1) * 2 + 1)))); //next sample + + if (pb.src_type == SRCTYPE_NEAREST) + sample = pb.adpcm.yn2; else // linear interpolation - sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16; + sample = (pb.adpcm.yn1 * (u16)oldFrac + pb.adpcm.yn2 * (u16)(0xFFFF - oldFrac) + pb.adpcm.yn2) >> 16; samplePos = newSamplePos; break; case AUDIOFORMAT_ADPCM: - sample = ADPCM_Step(pb.adpcm, samplePos, newSamplePos, frac); + ADPCM_Step(pb.adpcm, samplePos, newSamplePos, frac); + + if (pb.src_type == SRCTYPE_NEAREST) + sample = pb.adpcm.yn2; + else // linear interpolation + sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac) + pb.adpcm.yn2) >> 16; //adpcm moves on frac + break; default: diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -51,14 +51,10 @@ void CUCode_AXWii::HandleMail(u32 _uMail) { - static s8 newucodemails = -1; - - if (newucodemails > -1) { - newucodemails++; - if (newucodemails == 10) { - newucodemails = -1; - m_rMailHandler.PushMail(DSP_RESUME); - } + if (m_UploadSetupInProgress) + { + PrepareBootUCode(_uMail); + return; } else if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST) { @@ -72,24 +68,24 @@ break; case 0xCDD10001: // Action 1 - new ucode upload - NOTICE_LOG(DSPHLE,"DSP IROM - New Ucode!"); - newucodemails = 0; + DEBUG_LOG(DSPHLE,"DSP IROM - New Ucode!"); + // TODO find a better way to protect from HLEMixer? + soundStream->GetMixer()->SetHLEReady(false); + m_UploadSetupInProgress = true; break; case 0xCDD10002: // Action 2 - IROM_Reset(); ( WII: De Blob, Cursed Mountain,...) - NOTICE_LOG(DSPHLE,"DSP IROM - Reset!"); + DEBUG_LOG(DSPHLE,"DSP IROM - Reset!"); CDSPHandler::GetInstance().SetUCode(UCODE_ROM); - break; + return; case 0xCDD10003: // Action 3 - AX_GetNextCmdBlock() - //TODO: Implement?? break; default: - { DEBUG_LOG(DSPHLE, " >>>> u32 MAIL : AXTask Mail (%08x)", _uMail); AXTask(_uMail); - } + break; } } @@ -147,8 +143,13 @@ void CUCode_AXWii::Update(int cycles) { - // check if we have to sent something - if (!m_rMailHandler.IsEmpty()) + if (NeedsResumeMail()) + { + m_rMailHandler.PushMail(DSP_RESUME); + g_dspInitialize.pGenerateDSPInterrupt(); + } + // check if we have to send something + else if (!m_rMailHandler.IsEmpty()) { g_dspInitialize.pGenerateDSPInterrupt(); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.cpp 1970-01-01 01:00:00.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -0,0 +1,154 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "../Globals.h" +#include "../DSPHandler.h" +#include "UCodes.h" +#include "UCode_GBA.h" + +CUCode_GBA::CUCode_GBA(CMailHandler& _rMailHandler) +: IUCode(_rMailHandler) +{ + m_rMailHandler.PushMail(DSP_INIT); +} + +CUCode_GBA::~CUCode_GBA() +{ + m_rMailHandler.Clear(); +} + +void CUCode_GBA::Update(int cycles) +{ + // check if we have to send something + if (!m_rMailHandler.IsEmpty()) + { + g_dspInitialize.pGenerateDSPInterrupt(); + } +} + +void CUCode_GBA::HandleMail(u32 _uMail) +{ + static bool nextmail_is_mramaddr = false; + static bool calc_done = false; + + if (m_UploadSetupInProgress) + { + PrepareBootUCode(_uMail); + } + else if ((_uMail >> 16 == 0xabba) && !nextmail_is_mramaddr) + { + nextmail_is_mramaddr = true; + } + else if (nextmail_is_mramaddr) + { + nextmail_is_mramaddr = false; + u32 mramaddr = _uMail; + + struct sec_params_t { + u16 key[2]; + u16 unk1[2]; + u16 unk2[2]; + u32 length; + u32 dest_addr; + u32 pad[3]; + } sec_params; + + // 32 bytes from mram addr to dram @ 0 + for (int i = 0; i < 8; i++, mramaddr += 4) + ((u32*)&sec_params)[i] = Memory_Read_U32(mramaddr); + + // This is the main decrypt routine + u16 x11 = 0, x12 = 0, + x20 = 0, x21 = 0, x22 = 0, x23 = 0; + + x20 = Common::swap16(sec_params.key[0]) ^ 0x6f64; + x21 = Common::swap16(sec_params.key[1]) ^ 0x6573; + + s16 unk2 = (s8)sec_params.unk2[0]; + if (unk2 < 0) + { + x11 = ((~unk2 + 3) << 1) | (sec_params.unk1[0] << 4); + } + else if (unk2 == 0) + { + x11 = (sec_params.unk1[0] << 1) | 0x70; + } + else // unk2 > 0 + { + x11 = ((unk2 - 1) << 1) | (sec_params.unk1[0] << 4); + } + + s32 rounded_sub = ((sec_params.length + 7) & ~7) - 0x200; + u16 size = (rounded_sub < 0) ? 0 : rounded_sub >> 3; + + u32 t = (((size << 16) | 0x3f80) & 0x3f80ffff) << 1; + s16 t_low = (s8)(t >> 8); + t += (t_low & size) << 16; + x12 = t >> 16; + x11 |= (size & 0x4000) >> 14; // this would be stored in ac0.h if we weren't constrained to 32bit :) + t = ((x11 & 0xff) << 16) + ((x12 & 0xff) << 16) + (x12 << 8); + + u16 final11 = 0, final12 = 0; + final11 = x11 | ((t >> 8) & 0xff00) | 0x8080; + final12 = x12 | 0x8080; + + if ((final12 & 0x200) != 0) + { + x22 = final11 ^ 0x6f64; + x23 = final12 ^ 0x6573; + } + else + { + x22 = final11 ^ 0x6177; + x23 = final12 ^ 0x614b; + } + + // Send the result back to mram + *(u32*)Memory_Get_Pointer(sec_params.dest_addr) = Common::swap32((x20 << 16) | x21); + *(u32*)Memory_Get_Pointer(sec_params.dest_addr+4) = Common::swap32((x22 << 16) | x23); + + // Done! + DEBUG_LOG(DSPHLE, "\n%08x -> key %08x len %08x dest_addr %08x unk1 %08x unk2 %08x" + " 22 %04x 23 %04x", + mramaddr, + *(u32*)sec_params.key, sec_params.length, sec_params.dest_addr, + *(u32*)sec_params.unk1, *(u32*)sec_params.unk2, + x22, x23); + + calc_done = true; + m_rMailHandler.PushMail(DSP_DONE); + } + else if ((_uMail >> 16 == 0xcdd1) && calc_done) + { + switch (_uMail & 0xffff) + { + case 1: + m_UploadSetupInProgress = true; + break; + case 2: + CDSPHandler::GetInstance().SetUCode(UCODE_ROM); + break; + default: + DEBUG_LOG(DSPHLE, "CUCode_GBA - unknown 0xcdd1 cmd: %08x", _uMail); + break; + } + } + else + { + DEBUG_LOG(DSPHLE, "CUCode_GBA - unknown cmd: %08x", _uMail); + } +} diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.h 1970-01-01 01:00:00.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_GBA.h 2010-08-18 03:25:22.000000000 +0100 @@ -0,0 +1,29 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#pragma once + +#include "UCodes.h" + +struct CUCode_GBA : public IUCode +{ + CUCode_GBA(CMailHandler& _rMailHandler); + virtual ~CUCode_GBA(); + + void HandleMail(u32 _uMail); + void Update(int cycles); +}; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -22,9 +22,6 @@ CUCode_InitAudioSystem::CUCode_InitAudioSystem(CMailHandler& _rMailHandler) : IUCode(_rMailHandler) - , m_BootTask_numSteps(0) - , m_NextParameter(0) - , IsInitialized(false) { DEBUG_LOG(DSPHLE, "CUCode_InitAudioSystem - initialized"); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_InitAudioSystem.h 2010-08-18 03:25:22.000000000 +0100 @@ -29,25 +29,6 @@ void HandleMail(u32 _uMail); void Update(int cycles); void Init(); - -private: - struct SUCode - { - u32 m_RAMAddress; - u32 m_Length; - u32 m_IMEMAddress; - u32 m_DMEMLength; - u32 m_StartPC; - }; - - SUCode m_CurrentUCode; - int m_BootTask_numSteps; - - u32 m_NextParameter; - - bool IsInitialized; - - void BootUCode(); }; #endif diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -19,9 +19,11 @@ #include "../DSPHandler.h" #include "UCodes.h" #include "UCode_ROM.h" +#include "Hash.h" CUCode_Rom::CUCode_Rom(CMailHandler& _rMailHandler) : IUCode(_rMailHandler) + , m_CurrentUCode() , m_BootTask_numSteps(0) , m_NextParameter(0) { @@ -60,23 +62,23 @@ break; case 0x80F3A002: - m_CurrentUCode.m_Length = _uMail; + m_CurrentUCode.m_Length = _uMail & 0xffff; break; case 0x80F3C002: - m_CurrentUCode.m_IMEMAddress = _uMail; + m_CurrentUCode.m_IMEMAddress = _uMail & 0xffff; break; case 0x80F3B002: - m_CurrentUCode.m_DMEMLength = _uMail; - if (_uMail) { - NOTICE_LOG(DSPHLE,"Game wanted to DMA sth to DSP DRAM."); + m_CurrentUCode.m_DMEMLength = _uMail & 0xffff; + if (m_CurrentUCode.m_DMEMLength) { + NOTICE_LOG(DSPHLE,"m_CurrentUCode.m_DMEMLength = 0x%04x.", m_CurrentUCode.m_DMEMLength); } break; case 0x80F3D001: { - m_CurrentUCode.m_StartPC = _uMail; + m_CurrentUCode.m_StartPC = _uMail & 0xffff; BootUCode(); return; // Important! BootUCode indirectly does "delete this;". Must exit immediately. } @@ -93,25 +95,31 @@ void CUCode_Rom::BootUCode() { - // simple non-scientific crc invented by ector :P - // too annoying to change now, and probably good enough anyway - u32 crc = 0; - for (u32 i = 0; i < m_CurrentUCode.m_Length; i++) + u32 ector_crc = HashEctor( + (u8*)Memory_Get_Pointer(m_CurrentUCode.m_RAMAddress), + m_CurrentUCode.m_Length); + +#if defined(_DEBUG) || defined(DEBUGFAST) + char binFile[MAX_PATH]; + sprintf(binFile, "%sDSP_UC_%08X.bin", File::GetUserPath(D_DUMPDSP_IDX), ector_crc); + + FILE* pFile = fopen(binFile, "wb"); + if (pFile) { - crc ^= Memory_Read_U8(m_CurrentUCode.m_RAMAddress + i); - //let's rol - crc = (crc << 3) | (crc >> 29); + fwrite((u8*)Memory_Get_Pointer(m_CurrentUCode.m_RAMAddress), m_CurrentUCode.m_Length, 1, pFile); + fclose(pFile); } +#endif DEBUG_LOG(DSPHLE, "CurrentUCode SOURCE Addr: 0x%08x", m_CurrentUCode.m_RAMAddress); DEBUG_LOG(DSPHLE, "CurrentUCode Length: 0x%08x", m_CurrentUCode.m_Length); DEBUG_LOG(DSPHLE, "CurrentUCode DEST Addr: 0x%08x", m_CurrentUCode.m_IMEMAddress); DEBUG_LOG(DSPHLE, "CurrentUCode DMEM Length: 0x%08x", m_CurrentUCode.m_DMEMLength); DEBUG_LOG(DSPHLE, "CurrentUCode init_vector: 0x%08x", m_CurrentUCode.m_StartPC); - DEBUG_LOG(DSPHLE, "CurrentUCode CRC: 0x%08x", crc); + DEBUG_LOG(DSPHLE, "CurrentUCode CRC: 0x%08x", ector_crc); DEBUG_LOG(DSPHLE, "BootTask - done"); - CDSPHandler::GetInstance().SetUCode(crc); + CDSPHandler::GetInstance().SetUCode(ector_crc); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_ROM.h 2010-08-18 03:25:22.000000000 +0100 @@ -38,7 +38,6 @@ u32 m_DMEMLength; u32 m_StartPC; }; - SUCode m_CurrentUCode; int m_BootTask_numSteps; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -25,6 +25,9 @@ #include "UCode_ROM.h" #include "UCode_CARD.h" #include "UCode_InitAudioSystem.h" +#include "UCode_GBA.h" +#include "Hash.h" +#include "../DSPHandler.h" IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler) { @@ -42,14 +45,18 @@ INFO_LOG(DSPHLE, "Switching to CARD ucode"); return new CUCode_CARD(_rMailHandler); + case 0xdd7e72d5: + INFO_LOG(DSPHLE, "Switching to GBA ucode"); + return new CUCode_GBA(_rMailHandler); + case 0x3ad3b7ac: // Naruto3, Paper Mario - The Thousand Year Door case 0x3daf59b9: // Alien Hominid case 0x4e8a8b21: // spdemo, ctaxi, 18 wheeler, disney, monkeyball 1/2,cubivore,puzzlecollection,wario, - // capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat, - // smugglers run warzone, smash brothers, sonic mega collection, ZooCube - // nddemo, starfox + // capcom vs snk, naruto2, lost kingdoms, star fox, mario party 4, mortal kombat, + // smugglers run warzone, smash brothers, sonic mega collection, ZooCube + // nddemo, starfox case 0x07f88145: // bustamove, ikaruga, fzero, robotech battle cry, star soldier, soul calibur2, - // Zelda:OOT, Tony hawk, viewtiful joe + // Zelda:OOT, Tony hawk, viewtiful joe case 0xe2136399: // billy hatcher, dragonballz, mario party 5, TMNT, ava1080 INFO_LOG(DSPHLE, "CRC %08x: AX ucode chosen", _CRC); return new CUCode_AX(_rMailHandler); @@ -103,4 +110,77 @@ return NULL; } +bool IUCode::NeedsResumeMail() +{ + if (m_NeedsResumeMail) + { + m_NeedsResumeMail = false; + return true; + } + return false; +} + +void IUCode::PrepareBootUCode(u32 mail) +{ + switch (m_NextUCode_steps) + { + case 0: m_NextUCode.mram_dest_addr = mail; break; + case 1: m_NextUCode.mram_size = mail & 0xffff; break; + case 2: m_NextUCode.mram_dram_addr = mail & 0xffff; break; + case 3: m_NextUCode.iram_mram_addr = mail; break; + case 4: m_NextUCode.iram_size = mail & 0xffff; break; + case 5: m_NextUCode.iram_dest = mail & 0xffff; break; + case 6: m_NextUCode.iram_startpc = mail & 0xffff; break; + case 7: m_NextUCode.dram_mram_addr = mail; break; + case 8: m_NextUCode.dram_size = mail & 0xffff; break; + case 9: m_NextUCode.dram_dest = mail & 0xffff; break; + } + m_NextUCode_steps++; + + if (m_NextUCode_steps == 10) + { + m_NextUCode_steps = 0; + m_NeedsResumeMail = true; + m_UploadSetupInProgress = false; + + u32 ector_crc = HashEctor( + (u8*)Memory_Get_Pointer(m_NextUCode.iram_mram_addr), + m_NextUCode.iram_size); + +#if defined(_DEBUG) || defined(DEBUGFAST) + char binFile[MAX_PATH]; + sprintf(binFile, "%sDSP_UC_%08X.bin", File::GetUserPath(D_DUMPDSP_IDX), ector_crc); + + FILE* pFile = fopen(binFile, "wb"); + if (pFile) + { + fwrite((u8*)Memory_Get_Pointer(m_NextUCode.iram_mram_addr), m_NextUCode.iram_size, 1, pFile); + fclose(pFile); + } +#endif + + DEBUG_LOG(DSPHLE, "PrepareBootUCode 0x%08x", ector_crc); + DEBUG_LOG(DSPHLE, "DRAM -> MRAM: src %04x dst %08x size %04x", + m_NextUCode.mram_dram_addr, m_NextUCode.mram_dest_addr, + m_NextUCode.mram_size); + DEBUG_LOG(DSPHLE, "MRAM -> IRAM: src %08x dst %04x size %04x startpc %04x", + m_NextUCode.iram_mram_addr, m_NextUCode.iram_dest, + m_NextUCode.iram_size, m_NextUCode.iram_startpc); + DEBUG_LOG(DSPHLE, "MRAM -> DRAM: src %08x dst %04x size %04x", + m_NextUCode.dram_mram_addr, m_NextUCode.dram_dest, + m_NextUCode.dram_size); + if (m_NextUCode.mram_size) + { + WARN_LOG(DSPHLE, + "Trying to boot new ucode with dram download - not implemented"); + } + if (m_NextUCode.dram_size) + { + WARN_LOG(DSPHLE, + "Trying to boot new ucode with dram upload - not implemented"); + } + + CDSPHandler::GetInstance().SwapUCode(ector_crc); + } +} diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.h 2010-08-18 03:25:22.000000000 +0100 @@ -32,6 +32,10 @@ public: IUCode(CMailHandler& _rMailHandler) : m_rMailHandler(_rMailHandler) + , m_UploadSetupInProgress(false) + , m_NextUCode() + , m_NextUCode_steps(0) + , m_NeedsResumeMail(false) {} virtual ~IUCode() @@ -46,6 +50,13 @@ virtual void DoState(PointerWrap &p) {} protected: + void PrepareBootUCode(u32 mail); + + // Some ucodes (notably zelda) require a resume mail to be + // sent if they are be started via PrepareBootUCode. + // The HLE can use this to + bool NeedsResumeMail(); + CMailHandler& m_rMailHandler; Common::CriticalSection m_csMix; @@ -58,6 +69,29 @@ DSP_SYNC = 0xDCD10004, DSP_FRAME_END = 0xDCD10005, }; + + // UCode is forwarding mails to PrepareBootUCode + // UCode only needs to set this to true, IUCode will set to false when done! + bool m_UploadSetupInProgress; + +private: + struct SUCode + { + u32 mram_dest_addr; + u16 mram_size; + u16 mram_dram_addr; + u32 iram_mram_addr; + u16 iram_size; + u16 iram_dest; + u16 iram_startpc; + u32 dram_mram_addr; + u16 dram_size; + u16 dram_dest; + }; + SUCode m_NextUCode; + int m_NextUCode_steps; + + bool m_NeedsResumeMail; }; extern IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -28,6 +28,8 @@ #include "Mixer.h" #include "WaveFile.h" +#include "../DSPHandler.h" + CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler, u32 _CRC) : @@ -118,6 +120,12 @@ if (m_rMailHandler.GetNextMail() == DSP_FRAME_END) g_dspInitialize.pGenerateDSPInterrupt(); } + + if (NeedsResumeMail()) + { + m_rMailHandler.PushMail(DSP_RESUME); + g_dspInitialize.pGenerateDSPInterrupt(); + } } void CUCode_Zelda::HandleMail(u32 _uMail) @@ -169,7 +177,7 @@ m_step = 0; } - if (m_step < 0 || m_step >= sizeof(m_Buffer) / 4) + if (m_step >= sizeof(m_Buffer) / 4) PanicAlert("m_step out of range"); ((u32*)m_Buffer)[m_step] = _uMail; @@ -226,7 +234,7 @@ if (m_bListInProgress) { - if (m_step < 0 || m_step >= sizeof(m_Buffer) / 4) + if (m_step >= sizeof(m_Buffer) / 4) PanicAlert("m_step out of range"); ((u32*)m_Buffer)[m_step] = _uMail; @@ -284,6 +292,13 @@ void CUCode_Zelda::HandleMail_NormalVersion(u32 _uMail) { // WARN_LOG(DSPHLE, "Zelda uCode: Handle mail %08X", _uMail); + + if (m_UploadSetupInProgress) // evaluated first! + { + PrepareBootUCode(_uMail); + return; + } + if (m_bSyncInProgress) { if (m_bSyncCmdPending) @@ -349,7 +364,7 @@ if (m_bListInProgress) { - if (m_step < 0 || m_step >= sizeof(m_Buffer) / 4) + if (m_step >= sizeof(m_Buffer) / 4) PanicAlert("m_step out of range"); ((u32*)m_Buffer)[m_step] = _uMail; @@ -381,23 +396,31 @@ m_numSteps = _uMail; m_step = 0; } - else if ((_uMail >> 16) == 0xCDD1) // A 0xCDD1000X mail should come right after we send a DSP_SYNCEND mail + else if ((_uMail >> 16) == 0xCDD1) // A 0xCDD1000X mail should come right after we send a DSP_FRAME_END mail { // The low part of the mail tells the operation to perform // Seeing as every possible operation number halts the uCode, // except 3, that thing seems to be intended for debugging switch (_uMail & 0xFFFF) { - case 0x0003: // Do nothing + case 0x0003: // Do nothing - continue normally return; - case 0x0000: // Halt - case 0x0001: // Dump memory? and halt - case 0x0002: // Do something and halt + case 0x0001: // accepts params to either dma to iram and/or dram (used for hotbooting a new ucode) + // TODO find a better way to protect from HLEMixer? + soundStream->GetMixer()->SetHLEReady(false); + m_UploadSetupInProgress = true; + return; + + case 0x0002: // Let IROM play us off + CDSPHandler::GetInstance().SetUCode(UCODE_ROM); + return; + + case 0x0000: // Halt WARN_LOG(DSPHLE, "Zelda uCode: received halting operation %04X", _uMail & 0xFFFF); return; - default: // Invalid (the real ucode would likely crash) + default: // Invalid (the real ucode would likely crash) WARN_LOG(DSPHLE, "Zelda uCode: received invalid operation %04X", _uMail & 0xFFFF); return; } @@ -594,6 +617,8 @@ p.Do(m_PBAddress); p.Do(m_PBAddress2); + p.Do(m_UploadSetupInProgress); + m_rMailHandler.DoState(p); m_csMix.Leave(); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_Voice.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -579,9 +579,6 @@ break; } } - - // Necessary for SMG, not for Zelda. Weird. Where's it from? - PB.NeedsReset = 0; ContinueWithBlock: @@ -733,6 +730,10 @@ addr++; } } + // 03b2, this is the reason of using PB.NeedsReset. Seems to be necessary for SMG, and maybe other games. + if (PB.IsBlank == 0){ + PB.NeedsReset = 0; + } } // size is in stereo samples. diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPDebugWindow.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPDebugWindow.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPDebugWindow.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPDebugWindow.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -32,10 +32,11 @@ void Host_NotifyMapLoaded() {} void Host_UpdateBreakPointView() {} +DSPDebuggerLLE* m_DebuggerFrame = NULL; + BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxPanel) EVT_CLOSE(DSPDebuggerLLE::OnClose) - EVT_MENU_RANGE(ID_RUNTOOL, ID_STEPTOOL, DSPDebuggerLLE::OnChangeState) - EVT_MENU(ID_SHOWPCTOOL, DSPDebuggerLLE::OnShowPC) + EVT_MENU_RANGE(ID_RUNTOOL, ID_SHOWPCTOOL, DSPDebuggerLLE::OnChangeState) EVT_TEXT_ENTER(ID_ADDRBOX, DSPDebuggerLLE::OnAddrBoxChange) EVT_LISTBOX(ID_SYMBOLLIST, DSPDebuggerLLE::OnSymbolListChange) END_EVENT_TABLE() @@ -109,18 +110,17 @@ UpdateState(); m_mgr.Update(); - - Show(); } DSPDebuggerLLE::~DSPDebuggerLLE() { m_mgr.UnInit(); + m_DebuggerFrame = NULL; } void DSPDebuggerLLE::OnClose(wxCloseEvent& event) { - Hide(); + event.Skip(); } void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event) @@ -154,19 +154,21 @@ m_mgr.Update(); } -void DSPDebuggerLLE::OnShowPC(wxCommandEvent& event) -{ - // UpdateDisAsmListView will focus on PC - Refresh(); -} - void DSPDebuggerLLE::Refresh() { +#ifdef __linux__ + if (!wxIsMainThread()) + wxMutexGuiEnter(); +#endif UpdateSymbolMap(); UpdateDisAsmListView(); UpdateRegisterFlags(); UpdateState(); m_mgr.Update(); +#ifdef __linux__ + if (!wxIsMainThread()) + wxMutexGuiLeave(); +#endif } void DSPDebuggerLLE::FocusOnPC() @@ -176,12 +178,15 @@ void DSPDebuggerLLE::UpdateState() { - if (DSPCore_GetState() == DSPCORE_RUNNING) { + if (DSPCore_GetState() == DSPCORE_RUNNING) + { m_Toolbar->SetToolLabel(ID_RUNTOOL, wxT("Pause")); m_Toolbar->SetToolBitmap(ID_RUNTOOL, wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_OTHER, wxSize(10,10))); m_Toolbar->EnableTool(ID_STEPTOOL, false); - } else { + } + else + { m_Toolbar->SetToolLabel(ID_RUNTOOL, wxT("Run")); m_Toolbar->SetToolBitmap(ID_RUNTOOL, wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_OTHER, wxSize(10,10))); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPDebugWindow.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPDebugWindow.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPDebugWindow.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPDebugWindow.h 2010-08-18 03:25:22.000000000 +0100 @@ -90,7 +90,6 @@ void OnClose(wxCloseEvent& event); void OnChangeState(wxCommandEvent& event); - void OnShowPC(wxCommandEvent& event); void OnRightClick(wxListEvent& event); void OnDoubleClick(wxListEvent& event); void OnAddrBoxChange(wxCommandEvent& event); @@ -102,4 +101,6 @@ void UnselectAll(); }; +extern DSPDebuggerLLE* m_DebuggerFrame; + #endif //_DSP_DEBUGGER_LLE_H diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPRegisterView.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPRegisterView.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPRegisterView.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Debugger/DSPRegisterView.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -89,6 +89,6 @@ void DSPRegisterView::Update() { - ForceRefresh(); ((CRegTable *)GetTable())->UpdateCachedRegs(); + ForceRefresh(); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -64,7 +64,7 @@ m_buttonEnableJIT->SetToolTip(wxT("Enables dynamic recompilation of DSP code.\n") wxT("Changing this will have no effect while the emulator is running!")); m_BackendSelection->SetToolTip(wxT("Changing this will have no effect while the emulator is running!")); - m_volumeSlider->SetToolTip(wxT("This setting only affects DSound and OpenAL.")); + m_volumeSlider->SetToolTip(wxT("This setting only affects DSound, OpenAL, and PulseAudio.")); // Create sizer and add items to dialog wxBoxSizer *sMain = new wxBoxSizer(wxVERTICAL); @@ -80,7 +80,7 @@ sBackend->Add(m_BackendSelection, 0, wxALL, 1); sbSettings->Add(sBackend, 0, wxALL, 2); - sbSettingsV->Add(m_volumeSlider, 0, wxLEFT|wxRIGHT|wxALIGN_CENTER, 6); + sbSettingsV->Add(m_volumeSlider, 1, wxLEFT|wxRIGHT|wxALIGN_CENTER, 6); sbSettingsV->Add(m_volumeText, 0, wxALL|wxALIGN_LEFT, 4); sSettings->Add(sbSettings, 0, wxALL|wxEXPAND, 4); @@ -151,7 +151,8 @@ // but getting the backend from string etc. is probably // too much just to enable/disable a stupid slider... return (backend == BACKEND_DIRECTSOUND || - backend == BACKEND_OPENAL); + backend == BACKEND_OPENAL || + backend == BACKEND_PULSEAUDIO); } void DSPConfigDialogLLE::BackendChanged(wxCommandEvent& event) diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/DSPHost.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -65,20 +65,16 @@ u32 DSPHost_CodeLoaded(const u8 *ptr, int size) { - u32 crc = GenerateCRC(ptr, size); + u32 ector_crc = HashEctor(ptr, size); #if defined(_DEBUG) || defined(DEBUGFAST) - DumpDSPCode(ptr, size, crc); + DumpDSPCode(ptr, size, ector_crc); #endif - // HLE plugin uses this crc method - u32 ector_crc = HashEctor(ptr, size); - DSPSymbols::Clear(); // Auto load text file - if none just disassemble. - // TODO: Don't hardcode for Zelda. NOTICE_LOG(DSPLLE, "ector_crc: %08x", ector_crc); DSPSymbols::Clear(); @@ -87,11 +83,14 @@ { case 0x86840740: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Zelda.txt"); break; case 0x42f64ac4: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Luigi.txt"); break; - case 0x07f88145: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_4CB8233B.txt"); break; - case 0x3ad3b7ac: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_8A7A05E2.txt"); break; - case 0x3daf59b9: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_D9D066EA.txt"); break; - case 0x4e8a8b21: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_6A696CE7.txt"); break; - case 0xe2136399: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_EB79C705.txt"); break; + case 0x07f88145: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX_07F88145.txt"); break; + case 0x3ad3b7ac: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX_3AD3B7AC.txt"); break; + case 0x3daf59b9: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX_3DAF59B9.txt"); break; + case 0x4e8a8b21: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX_4E8A8B21.txt"); break; + case 0xe2136399: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX_E2136399.txt"); break; + case 0xdd7e72d5: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_GBA.txt"); break; + case 0x347112BA: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AXWii.txt"); break; + case 0xD643001F: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_SuperMarioGalaxy.txt"); break; default: success = false; break; } @@ -105,7 +104,7 @@ if (m_DebuggerFrame) m_DebuggerFrame->Refresh(); #endif - return crc; + return ector_crc; } void DSPHost_UpdateDebugger() diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -41,7 +41,6 @@ #include "DSPConfigDlgLLE.h" DSPConfigDialogLLE* m_ConfigFrame = NULL; #include "Debugger/DSPDebugWindow.h" -DSPDebuggerLLE* m_DebuggerFrame = NULL; #endif PLUGIN_GLOBALS* globals = NULL; @@ -96,22 +95,6 @@ } #endif -#if defined(HAVE_WX) && HAVE_WX -wxWindow* GetParentedWxWindow(HWND Parent) -{ -#ifdef _WIN32 - wxSetInstance((HINSTANCE)g_hInstance); -#endif - wxWindow *win = new wxWindow(); -#ifdef _WIN32 - win->SetHWND((WXHWND)Parent); - win->AdoptAttributesFromHWND(); -#endif - return win; -} -#endif - - void GetDllInfo(PLUGIN_INFO* _PluginInfo) { _PluginInfo->Version = 0x0100; @@ -134,11 +117,10 @@ LogManager::SetInstance((LogManager *)globals->logManager); } -void DllConfig(HWND _hParent) +void DllConfig(void *_hParent) { #if defined(HAVE_WX) && HAVE_WX - wxWindow *frame = GetParentedWxWindow(_hParent); - m_ConfigFrame = new DSPConfigDialogLLE(frame); + m_ConfigFrame = new DSPConfigDialogLLE((wxWindow *)_hParent); // add backends std::vector backends = AudioCommon::GetSoundBackends(); @@ -149,23 +131,9 @@ m_ConfigFrame->AddBackend((*iter).c_str()); } - // Only allow one open at a time -#ifdef _WIN32 - frame->Disable(); - m_ConfigFrame->ShowModal(); - frame->Enable(); -#else m_ConfigFrame->ShowModal(); -#endif - -#ifdef _WIN32 - frame->SetFocus(); - frame->SetHWND(NULL); -#endif m_ConfigFrame->Destroy(); - m_ConfigFrame = NULL; - frame->Destroy(); #endif } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Tools.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Tools.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Tools.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Tools.cpp 2010-08-18 03:25:22.000000000 +0100 @@ -67,28 +67,6 @@ return File::WriteStringToFile(true, text, txtFile); } -u32 GenerateCRC(const unsigned char* _pBuffer, int _pLength) -{ - unsigned long CRC = 0xFFFFFFFF; - - while (_pLength--) - { - unsigned long Temp = (unsigned long)((CRC & 0xFF) ^ *_pBuffer++); - - for (int j = 0; j < 8; j++) - { - if (Temp & 0x1) - Temp = (Temp >> 1) ^ 0xEDB88320; - else - Temp >>= 1; - } - - CRC = (CRC >> 8) ^ Temp; - } - - return CRC ^ 0xFFFFFFFF; -} - // TODO make this useful :p bool DumpCWCode(u32 _Address, u32 _Length) { diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Tools.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Tools.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_DSP_LLE/Src/Tools.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_DSP_LLE/Src/Tools.h 2010-08-18 03:25:22.000000000 +0100 @@ -19,7 +19,6 @@ #define _DSPLLE_TOOLS_H bool DumpDSPCode(const u8 *code_be, int size_in_bytes, u32 crc); -u32 GenerateCRC(const unsigned char* _pBuffer, int _pLength); bool DumpCWCode(u32 _Address, u32 _Length); #endif //_DSPLLE_TOOLS_H diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/main.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/main.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/main.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/main.cpp 2010-08-18 03:25:23.000000000 +0100 @@ -96,15 +96,6 @@ // This is used for the functions right below here which use wxwidgets #if defined(HAVE_WX) && HAVE_WX WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); - -wxWindow* GetParentedWxWindow(HWND Parent) -{ - wxSetInstance((HINSTANCE)g_hInstance); - wxWindow* win = new wxWindow(); - win->SetHWND((WXHWND)Parent); - win->AdoptAttributesFromHWND(); - return win; -} #endif void *DllDebugger(void *_hParent, bool Show) @@ -186,9 +177,9 @@ MessageBoxA(NULL, "DllAbout not implemented, how did you come here? Anyway, report this to the devs.", "Error!", MB_OK); } -void DllConfig(HWND _hParent) +void DllConfig(void *_hParent) { - DlgSettings_Show(g_hInstance, _hParent); + DlgSettings_Show(g_hInstance, (HWND)((wxWindow *)_hParent)->GetHandle()); } void Initialize(void* init) @@ -418,6 +409,10 @@ return 0; } +void VideoFifo_CheckAsyncRequest() { + VideoFifo_CheckSwapRequest(); + VideoFifo_CheckEFBAccess(); +} void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address) { @@ -458,3 +453,8 @@ { return CommandProcessor::isFifoBusy; } + +void Video_AbortFrame(void) +{ + CommandProcessor::AbortFrame(); +} \ No newline at end of file diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/main.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/main.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/main.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/main.h 2010-08-18 03:25:23.000000000 +0100 @@ -23,5 +23,7 @@ extern SVideoInitialize g_VideoInitialize; extern volatile u32 s_swapRequested; +void VideoFifo_CheckEFBAccess(); +void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight); #endif diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp 2010-08-18 03:25:23.000000000 +0100 @@ -1004,11 +1004,11 @@ // update FPS counter static int fpscount = 0; - static unsigned long lasttime = Common::Timer::GetTimeMs(); + static unsigned long lasttime = 0; if (Common::Timer::GetTimeMs() - lasttime >= 1000) { lasttime = Common::Timer::GetTimeMs(); - s_fps = fpscount-1; + s_fps = fpscount; fpscount = 0; } if (XFBWrited) ++fpscount; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/resource.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/resource.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/resource.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/resource.h 2010-08-18 03:25:23.000000000 +0100 @@ -7,7 +7,6 @@ #define IDD_ADVANCED 105 #define IDC_ADAPTER 1001 //#define IDC_ANTIALIASMODE 1002 -//#define IDC_RESOLUTION 1003 #define IDC_VSYNC 1006 #define IDC_ASPECT_16_9 1008 #define IDC_ASPECT_4_3 1009 diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp 2010-08-18 03:25:23.000000000 +0100 @@ -35,6 +35,7 @@ #include "NativeVertexFormat.h" #include "NativeVertexWriter.h" #include "TextureCache.h" +#include "main.h" #include "BPStructs.h" #include "XFStructs.h" diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -155,7 +155,7 @@ bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA; // Add SuperSamples modes - a.aa_levels.push_back(AALevel("NONE", D3DMULTISAMPLE_NONE, 0)); + a.aa_levels.push_back(AALevel("None", D3DMULTISAMPLE_NONE, 0)); a.aa_levels.push_back(AALevel("4x SSAA", D3DMULTISAMPLE_NONE, 0)); a.aa_levels.push_back(AALevel("9x SSAA", D3DMULTISAMPLE_NONE, 0)); //Add multisample modes diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -84,7 +84,7 @@ // --------------- GFXConfigDialogDX::~GFXConfigDialogDX() { - INFO_LOG(CONSOLE, "GFXConfigDialogDX Closed"); + INFO_LOG(CONSOLE, "GFXConfigDialogDX closed"); } void GFXConfigDialogDX::OnClose(wxCloseEvent& event) @@ -182,12 +182,12 @@ const D3D::Adapter &adapter = D3D::GetAdapter(g_Config.iAdapter); m_AdapterCB = new wxChoice( m_PageDirect3D, ID_ADAPTER, wxDefaultPosition, wxDefaultSize, arrayStringFor_AdapterCB, 0); - m_VSync = new wxCheckBox( m_PageDirect3D, ID_VSYNC, wxT("Vsync"), wxPoint( -1,-1 ), wxDefaultSize, 0 ); - m_WidescreenHack = new wxCheckBox( m_PageDirect3D, ID_WIDESCREEN_HACK, wxT("Widescreen Hack"), wxPoint( -1,-1 ), wxDefaultSize, 0 ); + m_VSync = new wxCheckBox( m_PageDirect3D, ID_VSYNC, wxT("V-sync"), wxPoint( -1,-1 ), wxDefaultSize, 0 ); + m_WidescreenHack = new wxCheckBox( m_PageDirect3D, ID_WIDESCREEN_HACK, wxT("Widescreen hack"), wxPoint( -1,-1 ), wxDefaultSize, 0 ); - m_staticARText = new wxStaticText( m_PageDirect3D, wxID_ANY, wxT("Aspect Ratio:"), wxPoint( -1,-1 ), wxDefaultSize, 0 ); + m_staticARText = new wxStaticText( m_PageDirect3D, wxID_ANY, wxT("Aspect ratio:"), wxPoint( -1,-1 ), wxDefaultSize, 0 ); m_staticARText->Wrap( -1 ); - wxString m_KeepARChoices[] = { wxT("Auto"), wxT("Force 16:9 Widescreen"), wxT("Force 4:3 Standart"), wxT("Stretch to Window") }; + wxString m_KeepARChoices[] = { wxT("Auto"), wxT("Force 16:9 (widescreen)"), wxT("Force 4:3 (standard)"), wxT("Stretch to window") }; int m_KeepARNChoices = sizeof( m_KeepARChoices ) / sizeof( wxString ); m_KeepAR = new wxChoice( m_PageDirect3D, ID_ASPECT, wxPoint( -1,-1 ), wxDefaultSize, m_KeepARNChoices, m_KeepARChoices, 0 ); m_KeepAR->SetSelection( 0 ); @@ -200,20 +200,20 @@ arrayStringFor_MSAAModeCB.Add(wxString::FromAscii(adapter.aa_levels[i].name)); } m_MSAAModeCB = new wxChoice( m_PageDirect3D, ID_ANTIALIASMODE, wxPoint( -1,-1 ), wxDefaultSize, arrayStringFor_MSAAModeCB, 0); - m_EFBScaleText = new wxStaticText( m_PageDirect3D, wxID_ANY, wxT("EFB Scale:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_EFBScaleText = new wxStaticText( m_PageDirect3D, wxID_ANY, wxT("EFB scale:"), wxDefaultPosition, wxDefaultSize, 0 ); m_EFBScaleText->Wrap( -1 ); - wxString m_EFBScaleModeChoices[] = { wxT("Auto (Fractional)"), wxT("Auto (Integral)"), wxT("1x"), wxT("2x"), wxT("3x") }; + wxString m_EFBScaleModeChoices[] = { wxT("Auto (fractional)"), wxT("Auto (integral)"), wxT("1x"), wxT("2x"), wxT("3x") }; int m_EFBScaleModeNChoices = sizeof( m_EFBScaleModeChoices ) / sizeof( wxString ); m_EFBScaleMode = new wxChoice( m_PageDirect3D, ID_EFBSCALEMODE, wxDefaultPosition, wxDefaultSize, m_EFBScaleModeNChoices, m_EFBScaleModeChoices, 0 ); m_EnableEFBAccess = new wxCheckBox( m_PageDirect3D, ID_EFB_ACCESS_ENABLE, wxT("Enable CPU->EFB access"), wxDefaultPosition, wxDefaultSize, 0 ); wxStaticBoxSizer* sbSTC; - sbSTC = new wxStaticBoxSizer( new wxStaticBox( m_PageDirect3D, wxID_ANY, wxT("Safe Texture Cache") ), wxVERTICAL ); - m_SafeTextureCache = new wxCheckBox( m_PageDirect3D, ID_SAFETEXTURECACHE, wxT("Use Safe Texture Cache"), wxDefaultPosition, wxDefaultSize, 0 ); - m_Radio_SafeTextureCache_Safe = new wxRadioButton( m_PageDirect3D, ID_RADIO_SAFETEXTURECACHE_SAFE, wxT("Safe"), wxDefaultPosition, wxDefaultSize, 0 ); - m_Radio_SafeTextureCache_Normal = new wxRadioButton( m_PageDirect3D, ID_RADIO_SAFETEXTURECACHE_NORMAL, wxT("Normal"), wxDefaultPosition, wxDefaultSize, 0 ); - m_Radio_SafeTextureCache_Fast = new wxRadioButton( m_PageDirect3D, ID_RADIO_SAFETEXTURECACHE_FAST, wxT("Fast"), wxDefaultPosition, wxDefaultSize, 0 ); + sbSTC = new wxStaticBoxSizer( new wxStaticBox( m_PageDirect3D, wxID_ANY, wxT("Safe texture cache") ), wxVERTICAL ); + m_SafeTextureCache = new wxCheckBox( m_PageDirect3D, ID_SAFETEXTURECACHE, wxT("Use safe texture cache"), wxDefaultPosition, wxDefaultSize, 0 ); + m_Radio_SafeTextureCache_Safe = new wxRadioButton( m_PageDirect3D, ID_RADIO_SAFETEXTURECACHE_SAFE, wxT("safe"), wxDefaultPosition, wxDefaultSize, 0 ); + m_Radio_SafeTextureCache_Normal = new wxRadioButton( m_PageDirect3D, ID_RADIO_SAFETEXTURECACHE_NORMAL, wxT("normal"), wxDefaultPosition, wxDefaultSize, 0 ); + m_Radio_SafeTextureCache_Fast = new wxRadioButton( m_PageDirect3D, ID_RADIO_SAFETEXTURECACHE_FAST, wxT("fast"), wxDefaultPosition, wxDefaultSize, 0 ); // Sizers wxGridBagSizer* sBasic; @@ -252,18 +252,18 @@ m_PageDirect3D->SetSizer( sGeneral ); m_PageDirect3D->Layout(); sGeneral->Fit( m_PageDirect3D ); - m_Notebook->AddPage( m_PageDirect3D, wxT("Direct3D"), true ); + m_Notebook->AddPage( m_PageDirect3D, wxT("General"), true ); //Enhancements Tab wxStaticBoxSizer* sbTextureFilter; - sbTextureFilter = new wxStaticBoxSizer( new wxStaticBox( m_PageEnhancements, wxID_ANY, wxT("Texture Filtering") ), wxVERTICAL ); - m_ForceFiltering = new wxCheckBox( m_PageEnhancements, ID_FORCEFILTERING, wxT("Force bi/trilinear filtering (Breaks video in several Wii games )"), wxDefaultPosition, wxDefaultSize, 0 ); - m_MaxAnisotropy = new wxCheckBox( m_PageEnhancements, ID_FORCEANISOTROPY, wxT("Enable 16x Anisotropy filtering"), wxDefaultPosition, wxDefaultSize, 0 ); - m_HiresTextures = new wxCheckBox( m_PageEnhancements, ID_LOADHIRESTEXTURES, wxT("Enable hires Texture loading"), wxDefaultPosition, wxDefaultSize, 0 ); + sbTextureFilter = new wxStaticBoxSizer( new wxStaticBox( m_PageEnhancements, wxID_ANY, wxT("Texture filtering") ), wxVERTICAL ); + m_ForceFiltering = new wxCheckBox( m_PageEnhancements, ID_FORCEFILTERING, wxT("Force bi/trilinear filtering (breaks video in several Wii games)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_MaxAnisotropy = new wxCheckBox( m_PageEnhancements, ID_FORCEANISOTROPY, wxT("Enable 16x anisotropic filtering"), wxDefaultPosition, wxDefaultSize, 0 ); + m_HiresTextures = new wxCheckBox( m_PageEnhancements, ID_LOADHIRESTEXTURES, wxT("Enable hires texture loading"), wxDefaultPosition, wxDefaultSize, 0 ); wxStaticBoxSizer* sbEFBHacks; - sbEFBHacks = new wxStaticBoxSizer( new wxStaticBox( m_PageEnhancements, wxID_ANY, wxT("EFB Hacks") ), wxVERTICAL ); - m_EFBScaledCopy = new wxCheckBox( m_PageEnhancements, ID_EFBSCALEDCOPY, wxT("EFB Scaled Copy"), wxDefaultPosition, wxDefaultSize, 0 ); + sbEFBHacks = new wxStaticBoxSizer( new wxStaticBox( m_PageEnhancements, wxID_ANY, wxT("EFB hacks") ), wxVERTICAL ); + m_EFBScaledCopy = new wxCheckBox( m_PageEnhancements, ID_EFBSCALEDCOPY, wxT("EFB scaled copy"), wxDefaultPosition, wxDefaultSize, 0 ); // Sizers wxBoxSizer* sEnhancements; @@ -294,29 +294,29 @@ //Advanced Tab wxStaticBoxSizer* sbSettings; sbSettings = new wxStaticBoxSizer( new wxStaticBox( m_PageAdvanced, wxID_ANY, wxT("Settings") ), wxVERTICAL ); - m_DisableFog = new wxCheckBox( m_PageAdvanced, ID_DISABLEFOG, wxT("Disable Fog"), wxDefaultPosition, wxDefaultSize, 0 ); - m_OverlayFPS = new wxCheckBox( m_PageAdvanced, ID_OVERLAYFPS, wxT("Overlay FPS Counter"), wxDefaultPosition, wxDefaultSize, 0 ); - m_CopyEFB = new wxCheckBox( m_PageAdvanced, ID_ENABLEEFBCOPY, wxT("Enable EFB Copy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_EnableHotkeys = new wxCheckBox( m_PageAdvanced, ID_ENABLEHOTKEY, wxT("Enable Hotkey"), wxDefaultPosition, wxDefaultSize, 0 ); + m_DisableFog = new wxCheckBox( m_PageAdvanced, ID_DISABLEFOG, wxT("Disable fog"), wxDefaultPosition, wxDefaultSize, 0 ); + m_OverlayFPS = new wxCheckBox( m_PageAdvanced, ID_OVERLAYFPS, wxT("Overlay FPS counter"), wxDefaultPosition, wxDefaultSize, 0 ); + m_CopyEFB = new wxCheckBox( m_PageAdvanced, ID_ENABLEEFBCOPY, wxT("Enable EFB copy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_EnableHotkeys = new wxCheckBox( m_PageAdvanced, ID_ENABLEHOTKEY, wxT("Enable hotkey"), wxDefaultPosition, wxDefaultSize, 0 ); m_Radio_CopyEFBToRAM = new wxRadioButton( m_PageAdvanced, ID_EFBTORAM, wxT("To RAM (accuracy)"), wxDefaultPosition, wxDefaultSize, 0 ); - m_Radio_CopyEFBToGL = new wxRadioButton( m_PageAdvanced, ID_EFBTOTEX, wxT("To Texture (performance, resolution)"), wxDefaultPosition, wxDefaultSize, 0 ); - m_WireFrame = new wxCheckBox( m_PageAdvanced, ID_WIREFRAME, wxT("Enable Wireframe"), wxDefaultPosition, wxDefaultSize, 0 ); - m_EnableRealXFB = new wxCheckBox( m_PageAdvanced, ID_ENABLEREALXFB, wxT("Enable Real XFB"), wxDefaultPosition, wxDefaultSize, 0 ); + m_Radio_CopyEFBToGL = new wxRadioButton( m_PageAdvanced, ID_EFBTOTEX, wxT("To texture (performance, resolution)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_WireFrame = new wxCheckBox( m_PageAdvanced, ID_WIREFRAME, wxT("Enable wireframe"), wxDefaultPosition, wxDefaultSize, 0 ); + m_EnableRealXFB = new wxCheckBox( m_PageAdvanced, ID_ENABLEREALXFB, wxT("Enable real XFB"), wxDefaultPosition, wxDefaultSize, 0 ); m_EnableXFB = new wxCheckBox( m_PageAdvanced, ID_ENABLEXFB, wxT("Enable XFB"), wxDefaultPosition, wxDefaultSize, 0 ); - m_UseNativeMips = new wxCheckBox( m_PageAdvanced, ID_USENATIVEMIPS, wxT("Use Native Mips"), wxDefaultPosition, wxDefaultSize, 0 ); + m_UseNativeMips = new wxCheckBox( m_PageAdvanced, ID_USENATIVEMIPS, wxT("Use native mipmaps"), wxDefaultPosition, wxDefaultSize, 0 ); wxStaticBoxSizer* sbDataDumping; - sbDataDumping = new wxStaticBoxSizer( new wxStaticBox( m_PageAdvanced, wxID_ANY, wxT("Data Dumping") ), wxVERTICAL ); - m_DumpTextures = new wxCheckBox( m_PageAdvanced, ID_TEXDUMP, wxT("Dump Textures"), wxDefaultPosition, wxDefaultSize, 0 ); - m_DumpFrames = new wxCheckBox( m_PageAdvanced, ID_DUMPFRAMES, wxT("Dump Frames To User/Dump/Frames"), wxDefaultPosition, wxDefaultSize, 0 ); + sbDataDumping = new wxStaticBoxSizer( new wxStaticBox( m_PageAdvanced, wxID_ANY, wxT("Data dumping") ), wxVERTICAL ); + m_DumpTextures = new wxCheckBox( m_PageAdvanced, ID_TEXDUMP, wxT("Dump textures"), wxDefaultPosition, wxDefaultSize, 0 ); + m_DumpFrames = new wxCheckBox( m_PageAdvanced, ID_DUMPFRAMES, wxT("Dump frames To User/Dump/Frames"), wxDefaultPosition, wxDefaultSize, 0 ); wxStaticBoxSizer* sbDebuggingTools; sbDebuggingTools = new wxStaticBoxSizer( new wxStaticBox( m_PageAdvanced, wxID_ANY, wxT("Debugging tools") ), wxVERTICAL ); - m_OverlayStats = new wxCheckBox( m_PageAdvanced, ID_OVERLAYSTATS, wxT("Overlay Some Statics"), wxDefaultPosition, wxDefaultSize, 0 ); - m_ShaderErrors = new wxCheckBox( m_PageAdvanced, ID_SHADERERRORS, wxT("Show Shader Compilation Errors"), wxDefaultPosition, wxDefaultSize, 0 ); - m_TexfmtOverlay = new wxCheckBox( m_PageAdvanced, ID_TEXFMT_OVERLAY, wxT("Enable TexFmt Overlay"), wxDefaultPosition, wxDefaultSize, 0 ); + m_OverlayStats = new wxCheckBox( m_PageAdvanced, ID_OVERLAYSTATS, wxT("Overlay some statistics"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ShaderErrors = new wxCheckBox( m_PageAdvanced, ID_SHADERERRORS, wxT("Show shader compilation errors"), wxDefaultPosition, wxDefaultSize, 0 ); + m_TexfmtOverlay = new wxCheckBox( m_PageAdvanced, ID_TEXFMT_OVERLAY, wxT("Enable texture format overlay"), wxDefaultPosition, wxDefaultSize, 0 ); m_TexfmtCenter = new wxCheckBox( m_PageAdvanced, ID_TEXFMT_CENTER, wxT("Centered"), wxDefaultPosition, wxDefaultSize, 0 ); - m_ProjStats = new wxCheckBox( m_PageAdvanced, wxID_ANY, wxT("Overlay Projection Stats"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ProjStats = new wxCheckBox( m_PageAdvanced, wxID_ANY, wxT("Overlay projection stats"), wxDefaultPosition, wxDefaultSize, 0 ); // Sizers wxBoxSizer* sAdvanced; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -97,7 +97,7 @@ { hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface); } - CHECK(hr, "Create Color Texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); + CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format, D3DPOOL_DEFAULT, &s_efb_colorRead_texture, NULL); CHECK(hr, "Create Color Read Texture (hr=%#x)", hr); @@ -107,71 +107,61 @@ } // Create an offscreen surface that we can lock to retrieve the data hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL); - CHECK(hr, "Create Color offScreen Surface (hr=%#x)", hr); - - // Select Zbuffer format supported by hardware. - if (g_ActiveConfig.bEFBAccessEnable) - { - D3DFORMAT *DepthTexFormats = new D3DFORMAT[5]; - DepthTexFormats[0] = FOURCC_INTZ; - DepthTexFormats[1] = FOURCC_DF24; - DepthTexFormats[2] = FOURCC_RAWZ; - DepthTexFormats[3] = FOURCC_DF16; - DepthTexFormats[4] = D3DFMT_D24X8; + CHECK(hr, "Create offscreen color surface (hr=%#x)", hr); - for(int i = 0; i < 5; i++) - { - s_efb_depth_surface_Format = DepthTexFormats[i]; - // Get the framebuffer Depth texture - hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format, - D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL); - if (!FAILED(hr)) - break; - } - CHECK(hr, "Depth Color Texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); - // Get the Surface - if(s_efb_depth_texture) - { - s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface); - } - // Create a 4x4 pixel texture to work as a buffer for peeking - if(s_efb_depth_surface_Format == FOURCC_RAWZ || s_efb_depth_surface_Format == D3DFMT_D24X8) - { - DepthTexFormats[0] = D3DFMT_A8R8G8B8; - } - else - { - DepthTexFormats[0] = D3DFMT_R32F; - } - DepthTexFormats[1] = D3DFMT_A8R8G8B8; - - for(int i = 0; i < 2; i++) - { - s_efb_depth_ReadBuffer_Format = DepthTexFormats[i]; - // Get the framebuffer Depth texture - hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_ReadBuffer_Format, - D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL); - if (!FAILED(hr)) - break; - } - - CHECK(hr, "Create Depth Read texture (hr=%#x)", hr); - if(s_efb_depthRead_texture) - { - s_efb_depthRead_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer); - } - // Create an offscreen surface that we can lock to retrieve the data - hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb_depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL); - CHECK(hr, "Create Depth offScreen Surface (hr=%#x)", hr); - delete [] DepthTexFormats; + // Select a Z-buffer format with hardware support + D3DFORMAT *DepthTexFormats = new D3DFORMAT[5]; + DepthTexFormats[0] = FOURCC_INTZ; + DepthTexFormats[1] = FOURCC_DF24; + DepthTexFormats[2] = FOURCC_RAWZ; + DepthTexFormats[3] = FOURCC_DF16; + DepthTexFormats[4] = D3DFMT_D24X8; + + for(int i = 0; i < 5; i++) + { + s_efb_depth_surface_Format = DepthTexFormats[i]; + // Create the framebuffer depth texture + hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_DEPTHSTENCIL, s_efb_depth_surface_Format, + D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL); + if (!FAILED(hr)) + break; + } + CHECK(hr, "Framebuffer depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); + // Get the Surface + if(s_efb_depth_texture) + { + s_efb_depth_texture->GetSurfaceLevel(0, &s_efb_depth_surface); + } + // Create a 4x4 pixel texture to work as a buffer for peeking + if(s_efb_depth_surface_Format == FOURCC_RAWZ || s_efb_depth_surface_Format == D3DFMT_D24X8) + { + DepthTexFormats[0] = D3DFMT_A8R8G8B8; } else { - s_efb_depth_surface_Format = D3DFMT_D24X8; - hr = D3D::dev->CreateDepthStencilSurface(target_width, target_height, s_efb_depth_surface_Format, - D3DMULTISAMPLE_NONE, 0, FALSE, &s_efb_depth_surface, NULL); - CHECK(hr, "CreateDepthStencilSurface (hr=%#x)", hr); + DepthTexFormats[0] = D3DFMT_R32F; } + DepthTexFormats[1] = D3DFMT_A8R8G8B8; + + for(int i = 0; i < 2; i++) + { + s_efb_depth_ReadBuffer_Format = DepthTexFormats[i]; + // Get the framebuffer Depth texture + hr = D3D::dev->CreateTexture(4, 4, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_ReadBuffer_Format, + D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL); + if (!FAILED(hr)) + break; + } + + CHECK(hr, "Create depth read texture (hr=%#x)", hr); + if(s_efb_depthRead_texture) + { + s_efb_depthRead_texture->GetSurfaceLevel(0, &s_efb_depth_ReadBuffer); + } + // Create an offscreen surface that we can lock to retrieve the data + hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb_depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL); + CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr); + delete [] DepthTexFormats; } void FramebufferManager::Destroy() diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/main.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/main.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/main.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/main.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -85,15 +85,6 @@ // This is used for the functions right below here which use wxwidgets #if defined(HAVE_WX) && HAVE_WX WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); - -wxWindow* GetParentedWxWindow(HWND Parent) -{ - wxSetInstance((HINSTANCE)g_hInstance); - wxWindow *win = new wxWindow(); - win->SetHWND((WXHWND)Parent); - win->AdoptAttributesFromHWND(); - return win; -} #endif void *DllDebugger(void *_hParent, bool Show) @@ -187,7 +178,7 @@ //DialogBox(g_hInstance,(LPCTSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc); } -void DllConfig(HWND _hParent) +void DllConfig(void *_hParent) { // If not initialized, only init D3D so we can enumerate resolutions. if (!s_PluginInitialized) @@ -196,21 +187,11 @@ g_Config.GameIniLoad(globals->game_ini); UpdateActiveConfig(); #if defined(HAVE_WX) && HAVE_WX - wxWindow *frame = GetParentedWxWindow(_hParent); - m_ConfigFrame = new GFXConfigDialogDX(frame); + m_ConfigFrame = new GFXConfigDialogDX((wxWindow *)_hParent); - // Prevent user to show more than 1 config window at same time - frame->Disable(); m_ConfigFrame->CreateGUIControls(); m_ConfigFrame->ShowModal(); - frame->Enable(); - - frame->SetFocus(); - frame->SetHWND(NULL); - m_ConfigFrame->Destroy(); - m_ConfigFrame = NULL; - frame->Destroy(); #endif if (!s_PluginInitialized) D3D::Shutdown(); @@ -454,6 +435,10 @@ return 0; } +void VideoFifo_CheckAsyncRequest() { + VideoFifo_CheckSwapRequest(); + VideoFifo_CheckEFBAccess(); +} void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address) { @@ -494,3 +479,8 @@ { return CommandProcessor::isFifoBusy; } + +void Video_AbortFrame(void) +{ + CommandProcessor::AbortFrame(); +} diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/main.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/main.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/main.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/main.h 2010-08-18 03:25:21.000000000 +0100 @@ -23,5 +23,7 @@ extern SVideoInitialize g_VideoInitialize; extern volatile u32 s_swapRequested; +void VideoFifo_CheckEFBAccess(); +void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight); #endif diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -44,8 +44,6 @@ static LinearDiskCache g_ps_disk_cache; static std::set unique_shaders; -static float lastPSconstants[C_COLORMATRIX+16][4]; - #define MAX_SSAA_SHADERS 3 static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram[MAX_SSAA_SHADERS]; @@ -75,32 +73,18 @@ void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { - if (lastPSconstants[const_number][0] != f1 || lastPSconstants[const_number][1] != f2 || - lastPSconstants[const_number][2] != f3 || lastPSconstants[const_number][3] != f4) - { - lastPSconstants[const_number][0] = f1; - lastPSconstants[const_number][1] = f2; - lastPSconstants[const_number][2] = f3; - lastPSconstants[const_number][3] = f4; - D3D::dev->SetPixelShaderConstantF(const_number, lastPSconstants[const_number], 1); - - } + float f[4] = { f1, f2, f3, f4 }; + D3D::dev->SetPixelShaderConstantF(const_number, f, 1); } void SetPSConstant4fv(unsigned int const_number, const float *f) { - if (memcmp(&lastPSconstants[const_number], f, sizeof(float) * 4)) { - memcpy(&lastPSconstants[const_number], f, sizeof(float) * 4); - D3D::dev->SetPixelShaderConstantF(const_number, f, 1); - } + D3D::dev->SetPixelShaderConstantF(const_number, f, 1); } void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f) { - if (memcmp(&lastPSconstants[const_number], f, count * sizeof(float) * 4)) { - memcpy(&lastPSconstants[const_number], f, count * sizeof(float) * 4); - D3D::dev->SetPixelShaderConstantF(const_number, f, count); - } + D3D::dev->SetPixelShaderConstantF(const_number, f, count); } class PixelShaderCacheInserter : public LinearDiskCacheReader { @@ -266,8 +250,6 @@ iter->second.Destroy(); PixelShaders.clear(); - for (int i = 0; i < C_PENVCONST_END * 4; i++) - lastPSconstants[i / 4][i % 4] = -100000000.0f; memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid)); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -1271,16 +1271,16 @@ // --------------------------------------------------------------------- // Count FPS. // ------------- - static int fpscount = 1; - static unsigned long lasttime; - if (XFBWrited) - ++fpscount; - if (Common::Timer::GetTimeMs() - lasttime > 1000) + static int fpscount = 0; + static unsigned long lasttime = 0; + if (Common::Timer::GetTimeMs() - lasttime >= 1000) { lasttime = Common::Timer::GetTimeMs(); - s_fps = fpscount - 1; - fpscount = 1; + s_fps = fpscount; + fpscount = 0; } + if (XFBWrited) + ++fpscount; // Begin new frame // Set default viewport and scissor, for the clear to work correctly diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -32,6 +32,7 @@ #include "NativeVertexFormat.h" #include "NativeVertexWriter.h" #include "TextureCache.h" +#include "main.h" #include "BPStructs.h" #include "XFStructs.h" diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp 2010-08-18 03:25:21.000000000 +0100 @@ -37,7 +37,6 @@ VertexShaderCache::VSCache VertexShaderCache::vshaders; const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry; -static float GC_ALIGNED16(lastVSconstants[C_VENVCONST_END][4]); #define MAX_SSAA_SHADERS 3 static LPDIRECT3DVERTEXSHADER9 SimpleVertexShader[MAX_SSAA_SHADERS]; @@ -58,59 +57,31 @@ void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { - if (lastVSconstants[const_number][0] != f1 || - lastVSconstants[const_number][1] != f2 || - lastVSconstants[const_number][2] != f3 || - lastVSconstants[const_number][3] != f4) - { - lastVSconstants[const_number][0] = f1; - lastVSconstants[const_number][1] = f2; - lastVSconstants[const_number][2] = f3; - lastVSconstants[const_number][3] = f4; - D3D::dev->SetVertexShaderConstantF(const_number, lastVSconstants[const_number], 1); - } + const float f[4] = { f1, f2, f3, f4 }; + D3D::dev->SetVertexShaderConstantF(const_number, f, 1); } void SetVSConstant4fv(unsigned int const_number, const float *f) { - if (memcmp(&lastVSconstants[const_number], f, sizeof(float) * 4)) { - memcpy(&lastVSconstants[const_number], f, sizeof(float) * 4); - D3D::dev->SetVertexShaderConstantF(const_number, lastVSconstants[const_number], 1); - } + D3D::dev->SetVertexShaderConstantF(const_number, f, 1); } void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f) { - bool change = false; + float buf[4*C_VENVCONST_END]; for (unsigned int i = 0; i < count; i++) { - if (lastVSconstants[const_number + i][0] != f[0 + i*3] || - lastVSconstants[const_number + i][1] != f[1 + i*3] || - lastVSconstants[const_number + i][2] != f[2 + i*3]) - { - change = true; - break; - } - } - if (change) - { - for (unsigned int i = 0; i < count; i++) - { - lastVSconstants[const_number + i][0] = f[0 + i*3]; - lastVSconstants[const_number + i][1] = f[1 + i*3]; - lastVSconstants[const_number + i][2] = f[2 + i*3]; - lastVSconstants[const_number + i][3] = 0.0f; - } - D3D::dev->SetVertexShaderConstantF(const_number, lastVSconstants[const_number], count); + buf[4*i ] = *f++; + buf[4*i+1] = *f++; + buf[4*i+2] = *f++; + buf[4*i+3] = 0.f; } + D3D::dev->SetVertexShaderConstantF(const_number, buf, count); } void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f) { - if (memcmp(&lastVSconstants[const_number], f, count * sizeof(float) * 4)) { - memcpy(&lastVSconstants[const_number], f, count * sizeof(float) * 4); - D3D::dev->SetVertexShaderConstantF(const_number, lastVSconstants[const_number], count); - } + D3D::dev->SetVertexShaderConstantF(const_number, f, count); } class VertexShaderCacheInserter : public LinearDiskCacheReader { @@ -218,8 +189,6 @@ iter->second.Destroy(); vshaders.clear(); - for (int i = 0; i < (C_VENVCONST_END * 4); i++) - lastVSconstants[i / 4][i % 4] = -100000000.0f; memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid)); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -115,8 +115,7 @@ // Setup window attributes GLWin.attr.colormap = XCreateColormap(GLWin.dpy, GLWin.parent, GLWin.vi->visual, AllocNone); - GLWin.attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | - StructureNotifyMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask; + GLWin.attr.event_mask = KeyPressMask | StructureNotifyMask | FocusChangeMask; GLWin.attr.background_pixel = BlackPixel(GLWin.dpy, GLWin.screen); GLWin.attr.border_pixel = 0; @@ -348,7 +347,6 @@ GLWin.screen = DefaultScreen(GLWin.dpy); if (GLWin.parent == 0) GLWin.parent = RootWindow(GLWin.dpy, GLWin.screen); - XkbSetDetectableAutoRepeat(GLWin.dpy, True, NULL); glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion); NOTICE_LOG(VIDEO, "glX-Version %d.%d", glxMajorVersion, glxMinorVersion); @@ -404,8 +402,10 @@ #elif defined(_WIN32) return wglMakeCurrent(hDC,hRC) ? true : false; #elif defined(HAVE_X11) && HAVE_X11 +#if defined(HAVE_WX) && (HAVE_WX) g_VideoInitialize.pRequestWindowSize(GLWin.x, GLWin.y, (int&)GLWin.width, (int&)GLWin.height); XMoveResizeWindow(GLWin.dpy, GLWin.win, GLWin.x, GLWin.y, GLWin.width, GLWin.height); +#endif return glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); #endif return true; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h 2010-08-18 03:25:24.000000000 +0100 @@ -40,7 +40,6 @@ #elif defined(HAVE_X11) && HAVE_X11 #include -#include #include #include #include "Thread.h" @@ -67,7 +66,6 @@ #ifndef _WIN32 -#include #include typedef struct { @@ -117,20 +115,16 @@ GLuint OpenGL_ReportGLError(const char *function, const char *file, int line); bool OpenGL_ReportFBOError(const char *function, const char *file, int line); -#if 1 -#define GL_REPORT_ERROR() OpenGL_ReportGLError (__FUNCTION__, __FILE__, __LINE__) +#if defined(_DEBUG) || defined(DEBUGFAST) +#define GL_REPORT_ERROR() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__) +#define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__) +#define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError(__FUNCTION__, __FILE__, __LINE__) #define GL_REPORT_PROGRAM_ERROR() OpenGL_ReportARBProgramError() -#define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError (__FUNCTION__, __FILE__, __LINE__) #else #define GL_REPORT_ERROR() GL_NO_ERROR -#define GL_REPORT_PROGRAM_ERROR() -#define GL_REPORT_FBO_ERROR() -#endif - -#if defined(_DEBUG) || defined(DEBUGFAST) -#define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__) -#else -#define GL_REPORT_ERRORD() +#define GL_REPORT_ERRORD() (void)GL_NO_ERROR +#define GL_REPORT_FBO_ERROR() (void)true +#define GL_REPORT_PROGRAM_ERROR() (void)0 #endif #if defined __APPLE__ || defined __linux__ || defined _WIN32 diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/GUI/ConfigDlg.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -529,9 +529,7 @@ InitializeGUITooltips(); Fit(); -#ifndef __APPLE__ - Center(); //it seems to cause problems on macs with small screens -#endif + Center(); UpdateGUI(); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/main.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/main.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/main.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/main.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -103,6 +103,9 @@ static bool s_PluginInitialized = false; volatile u32 s_swapRequested = FALSE; +#if defined(HAVE_X11) && HAVE_X11 +static volatile u32 s_doStateRequested = FALSE; +#endif static u32 s_efbAccessRequested = FALSE; static volatile u32 s_FifoShuttingDown = FALSE; @@ -136,19 +139,6 @@ WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst); extern HINSTANCE g_hInstance; #endif - -wxWindow* GetParentedWxWindow(HWND Parent) -{ -#ifdef _WIN32 - wxSetInstance((HINSTANCE)g_hInstance); -#endif - wxWindow *win = new wxWindow(); -#ifdef _WIN32 - win->SetHWND((WXHWND)Parent); - win->AdoptAttributesFromHWND(); -#endif - return win; -} #endif void *DllDebugger(void *_hParent, bool Show) @@ -160,35 +150,18 @@ #endif } -void DllConfig(HWND _hParent) +void DllConfig(void *_hParent) { g_Config.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str()); g_Config.GameIniLoad(globals->game_ini); g_Config.UpdateProjectionHack(); UpdateActiveConfig(); #if defined(HAVE_WX) && HAVE_WX - wxWindow *frame = GetParentedWxWindow(_hParent); - m_ConfigFrame = new GFXConfigDialogOGL(frame); + m_ConfigFrame = new GFXConfigDialogOGL((wxWindow *)_hParent); - // Prevent user to show more than 1 config window at same time -#ifdef _WIN32 - frame->Disable(); - m_ConfigFrame->CreateGUIControls(); - m_ConfigFrame->ShowModal(); - frame->Enable(); -#else m_ConfigFrame->CreateGUIControls(); m_ConfigFrame->ShowModal(); -#endif - -#ifdef _WIN32 - frame->SetFocus(); - frame->SetHWND(NULL); -#endif - m_ConfigFrame->Destroy(); - m_ConfigFrame = NULL; - frame->Destroy(); #endif } @@ -204,10 +177,6 @@ g_Config.GameIniLoad(globals->game_ini); g_Config.UpdateProjectionHack(); -#if defined(HAVE_WX) && HAVE_WX - // Enable support for PNG screenshots. - wxImage::AddHandler( new wxPNGHandler ); -#endif UpdateActiveConfig(); if (!OpenGL_Create(g_VideoInitialize, 640, 480)) @@ -225,24 +194,53 @@ OSD::AddMessage("Dolphin OpenGL Video Plugin", 5000); } -void DoState(unsigned char **ptr, int mode) +static volatile struct { + unsigned char **ptr; + int mode; +} s_doStateArgs; + +// Run from the GPU thread on X11, CPU thread on the rest +static void check_DoState() { #if defined(HAVE_X11) && HAVE_X11 - OpenGL_MakeCurrent(); + if (Common::AtomicLoadAcquire(s_doStateRequested)) + { #endif - // Clear all caches that touch RAM - TextureMngr::Invalidate(false); - VertexLoaderManager::MarkAllDirty(); - - PointerWrap p(ptr, mode); - VideoCommon_DoState(p); - - // Refresh state. - if (mode == PointerWrap::MODE_READ) + // Clear all caches that touch RAM + TextureMngr::Invalidate(false); + VertexLoaderManager::MarkAllDirty(); + + PointerWrap p(s_doStateArgs.ptr, s_doStateArgs.mode); + VideoCommon_DoState(p); + + // Refresh state. + if (s_doStateArgs.mode == PointerWrap::MODE_READ) + { + BPReload(); + RecomputeCachedArraybases(); + } + +#if defined(HAVE_X11) && HAVE_X11 + Common::AtomicStoreRelease(s_doStateRequested, FALSE); + } +#endif +} + +// Run from the CPU thread +void DoState(unsigned char **ptr, int mode) { + s_doStateArgs.ptr = ptr; + s_doStateArgs.mode = mode; +#if defined(HAVE_X11) && HAVE_X11 + Common::AtomicStoreRelease(s_doStateRequested, TRUE); + if (g_VideoInitialize.bOnThread) { - BPReload(); - RecomputeCachedArraybases(); + while (Common::AtomicLoadAcquire(s_doStateRequested) && !s_FifoShuttingDown) + //Common::SleepCurrentThread(1); + Common::YieldCPU(); } + else +#endif + check_DoState(); } void EmuStateChange(PLUGIN_EMUSTATE newState) @@ -250,7 +248,8 @@ Fifo_RunLoop((newState == PLUGIN_EMUSTATE_PLAY) ? true : false); } -// This is called after Video_Initialize() from the Core +// This is called after Initialize() from the Core +// Run from the graphics thread void Video_Prepare(void) { OpenGL_MakeCurrent(); @@ -369,7 +368,7 @@ } } -inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper) +static inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper) { return !((aLower >= bUpper) || (bLower >= aUpper)); } @@ -464,6 +463,14 @@ return 0; } +void VideoFifo_CheckAsyncRequest() { + VideoFifo_CheckSwapRequest(); + VideoFifo_CheckEFBAccess(); +#if defined(HAVE_X11) && HAVE_X11 + check_DoState(); +#endif +} + void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address) { CommandProcessor::Read16(_rReturnValue, _Address); @@ -503,3 +510,8 @@ { return CommandProcessor::isFifoBusy; } + +void Video_AbortFrame(void) +{ + CommandProcessor::AbortFrame(); +} diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/main.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/main.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/main.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/main.h 2010-08-18 03:25:24.000000000 +0100 @@ -22,5 +22,7 @@ extern SVideoInitialize g_VideoInitialize; extern volatile u32 s_swapRequested; +void VideoFifo_CheckEFBAccess(); +void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight); #endif // _MAIN_H_ diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -76,8 +76,6 @@ } extern bool gShowDebugger; -int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0; - // --------------------------------------------------------------------- // OSD Menu diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -42,41 +42,23 @@ bool PixelShaderCache::ShaderEnabled; static FRAGMENTSHADER* pShaderLast = NULL; -static float lastPSconstants[C_PENVCONST_END][4]; void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { - if (lastPSconstants[const_number][0] != f1 || lastPSconstants[const_number][1] != f2 || - lastPSconstants[const_number][2] != f3 || lastPSconstants[const_number][3] != f4) - { - lastPSconstants[const_number][0] = f1; - lastPSconstants[const_number][1] = f2; - lastPSconstants[const_number][2] = f3; - lastPSconstants[const_number][3] = f4; - glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, lastPSconstants[const_number]); - - } + float f[4] = { f1, f2, f3, f4 }; + glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f); } void SetPSConstant4fv(unsigned int const_number, const float *f) { - if (memcmp(&lastPSconstants[const_number], f, sizeof(float) * 4)) { - memcpy(&lastPSconstants[const_number], f, sizeof(float) * 4); - glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f); - } + glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f); } void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f) { - const float *f0 = f; - for (unsigned int i = 0; i < count ;i++,f0+=4) - { - if (memcmp(&lastPSconstants[const_number + i], f0, sizeof(float) * 4)) { - memcpy(&lastPSconstants[const_number + i], f0, sizeof(float) * 4); - glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number + i, lastPSconstants[const_number + i]); - } - } + for (unsigned int i = 0; i < count; i++,f+=4) + glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number + i, f); } void PixelShaderCache::Init() @@ -86,8 +68,6 @@ CurrentShader = 0; GL_REPORT_ERRORD(); - for (unsigned int i = 0; i < (C_PENVCONST_END) * 4; i++) - lastPSconstants[i/4][i%4] = -100000000.0f; memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid)); s_displayCompileAlert = true; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -15,7 +15,6 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ - #include "Globals.h" #include "Thread.h" #include "Atomic.h" @@ -119,16 +118,15 @@ static float xScale; static float yScale; -static int EFBxScale; -static int EFByScale; +static float EFBxScale; +static float EFByScale; static bool s_skipSwap = false; -#ifndef _WIN32 int OSDChoice = 0 , OSDTime = 0, OSDInternalW = 0, OSDInternalH = 0; -#endif -namespace { +namespace +{ #if defined(HAVE_WX) && HAVE_WX // Screenshot thread struct @@ -147,19 +145,19 @@ GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; static const GLenum glDestFactors[8] = { - GL_ZERO, - GL_ONE, - GL_SRC_COLOR, + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; @@ -181,7 +179,7 @@ GL_COPY, GL_AND_INVERTED, GL_NOOP, - GL_XOR, + GL_XOR, GL_OR, GL_NOR, GL_EQUIV, @@ -198,7 +196,8 @@ // Set some standard texture filter modes. glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (glGetError() != GL_NO_ERROR) { + if (GL_REPORT_ERROR() != GL_NO_ERROR) + { glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); GL_REPORT_ERRORD(); @@ -212,9 +211,8 @@ { DEBUG_LOG(VIDEO, "Cg error: %s", cgGetErrorString(err)); const char* listing = cgGetLastListing(g_cgcontext); - if (listing != NULL) { + if (listing != NULL) DEBUG_LOG(VIDEO, " last listing: %s", listing); - } } #endif @@ -224,7 +222,6 @@ ::UpdateProjectionHack(g_Config.iPhackvalue); } - // Init functions bool Renderer::Init() { @@ -240,10 +237,14 @@ case MULTISAMPLE_2X: s_MSAASamples = 2; break; case MULTISAMPLE_4X: s_MSAASamples = 4; break; case MULTISAMPLE_8X: s_MSAASamples = 8; break; - case MULTISAMPLE_CSAA_8X: s_MSAASamples = 4; s_MSAACoverageSamples = 8; break; - case MULTISAMPLE_CSAA_8XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 8; break; - case MULTISAMPLE_CSAA_16X: s_MSAASamples = 4; s_MSAACoverageSamples = 16; break; - case MULTISAMPLE_CSAA_16XQ: s_MSAASamples = 8; s_MSAACoverageSamples = 16; break; + case MULTISAMPLE_CSAA_8X: + s_MSAASamples = 4; s_MSAACoverageSamples = 8; break; + case MULTISAMPLE_CSAA_8XQ: + s_MSAASamples = 8; s_MSAACoverageSamples = 8; break; + case MULTISAMPLE_CSAA_16X: + s_MSAASamples = 4; s_MSAACoverageSamples = 16; break; + case MULTISAMPLE_CSAA_16XQ: + s_MSAASamples = 8; s_MSAACoverageSamples = 16; break; default: s_MSAASamples = 1; } @@ -259,9 +260,8 @@ if (!ptoken) { PanicAlert("Your OpenGL Driver seems to be not working.\n" - "Please make sure your drivers are up-to-date and\n" - "that your video hardware is OpenGL 2.x compatible " - ); + "Please make sure your drivers are up-to-date and\n" + "that your video hardware is OpenGL 2.x compatible."); return false; } @@ -269,35 +269,48 @@ INFO_LOG(VIDEO, ptoken); // write to the log file INFO_LOG(VIDEO, ""); - OSD::AddMessage(StringFromFormat("Video Info: %s, %s, %s", (const char*)glGetString(GL_VENDOR), - (const char*)glGetString(GL_RENDERER), - (const char*)glGetString(GL_VERSION)).c_str(), 5000); + OSD::AddMessage(StringFromFormat("Video Info: %s, %s, %s", + glGetString(GL_VENDOR), + glGetString(GL_RENDERER), + glGetString(GL_VERSION)).c_str(), 5000); glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &numvertexattribs); - if (numvertexattribs < 11) { - ERROR_LOG(VIDEO, "*********\nGPU: OGL ERROR: Number of attributes %d not enough\nGPU: *********Does your video card support OpenGL 2.x?", numvertexattribs); + if (numvertexattribs < 11) + { + ERROR_LOG(VIDEO, "GPU: OGL ERROR: Number of attributes %d not enough.\n" + "GPU: Does your video card support OpenGL 2.x?", + numvertexattribs); bSuccess = false; } // Init extension support. - if (glewInit() != GLEW_OK) { - ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?"); + if (glewInit() != GLEW_OK) + { + ERROR_LOG(VIDEO, "glewInit() failed! Does your video card support OpenGL 2.x?"); return false; } - if (!GLEW_EXT_framebuffer_object) { - ERROR_LOG(VIDEO, "*********\nGPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nGPU: *********Does your video card support OpenGL 2.x?"); + + if (!GLEW_EXT_framebuffer_object) + { + ERROR_LOG(VIDEO, "GPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets.\n" + "GPU: Does your video card support OpenGL 2.x?"); bSuccess = false; } - if (!GLEW_EXT_secondary_color) { - ERROR_LOG(VIDEO, "*********\nGPU: OGL ERROR: Need GL_EXT_secondary_color\nGPU: *********Does your video card support OpenGL 2.x?"); + + if (!GLEW_EXT_secondary_color) + { + ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_EXT_secondary_color.\n" + "GPU: Does your video card support OpenGL 2.x?"); bSuccess = false; } + s_bHaveFramebufferBlit = strstr(ptoken, "GL_EXT_framebuffer_blit") != NULL; if (!s_bHaveFramebufferBlit) { // MSAA ain't gonna work. turn it off if enabled. s_MSAASamples = 1; } + s_bHaveCoverageMSAA = strstr(ptoken, "GL_NV_framebuffer_multisample_coverage") != NULL; if (!s_bHaveCoverageMSAA) { @@ -314,30 +327,29 @@ if (WGLEW_EXT_swap_control) wglSwapIntervalEXT(g_ActiveConfig.bVSync ? 1 : 0); else - ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)Does your video card support OpenGL 2.x?"); + ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate)."); #elif defined(HAVE_X11) && HAVE_X11 if (glXSwapIntervalSGI) glXSwapIntervalSGI(g_ActiveConfig.bVSync ? 1 : 0); else - ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)"); + ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate)."); #endif // check the max texture width and height GLint max_texture_size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&max_texture_size); - if (max_texture_size < 1024) { - ERROR_LOG(VIDEO, "GL_MAX_TEXTURE_SIZE too small at %i - must be at least 1024", max_texture_size); - } + if (max_texture_size < 1024) + ERROR_LOG(VIDEO, "GL_MAX_TEXTURE_SIZE too small at %i - must be at least 1024.", + max_texture_size); if (GL_REPORT_ERROR() != GL_NO_ERROR) bSuccess = false; if (glDrawBuffers == NULL && !GLEW_ARB_draw_buffers) glDrawBuffers = glDrawBuffersARB; - - if (!GLEW_ARB_texture_non_power_of_two) { + + if (!GLEW_ARB_texture_non_power_of_two) WARN_LOG(VIDEO, "ARB_texture_non_power_of_two not supported."); - } // Decide frambuffer size int W = (int)OpenGL_GetBackbufferWidth(), H = (int)OpenGL_GetBackbufferHeight(); @@ -364,8 +376,7 @@ yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height; } } - - + EFBxScale = ceilf(xScale); EFByScale = ceilf(yScale); @@ -376,14 +387,16 @@ m_CustomWidth = W; m_CustomHeight = H; - // Because of the fixed framebuffer size we need to disable the resolution options while running + // Because of the fixed framebuffer size we need to disable the resolution + // options while running g_Config.bRunning = true; if (GL_REPORT_ERROR() != GL_NO_ERROR) bSuccess = false; // Initialize the FramebufferManager - g_framebufferManager.Init(m_FrameBufferWidth, m_FrameBufferHeight, s_MSAASamples, s_MSAACoverageSamples); + g_framebufferManager.Init(m_FrameBufferWidth, m_FrameBufferHeight, + s_MSAASamples, s_MSAACoverageSamples); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); @@ -394,12 +407,14 @@ #if defined HAVE_CG && HAVE_CG // load the effect, find the best profiles (if any) - if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE) { + if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE) + { ERROR_LOG(VIDEO, "arbvp1 not supported"); return false; } - if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE) { + if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE) + { ERROR_LOG(VIDEO, "arbfp1 not supported"); return false; } @@ -411,24 +426,31 @@ // so this will not work on ATI. ATI returns MAXINT = 2147483647 (0x7fffffff) // which is correct in OpenGL but Cg fails to handle it properly. As a result // -1 is used by Cg resulting (signedness incorrect) and compilation fails. - if (strstr((const char*)glGetString(GL_VENDOR), "ATI") == NULL) + if (strstr((const char*)glGetString(GL_VENDOR), "ATI") == NULL) +#endif { cgGLSetOptimalOptions(g_cgvProf); cgGLSetOptimalOptions(g_cgfProf); } -#else - cgGLSetOptimalOptions(g_cgvProf); - cgGLSetOptimalOptions(g_cgfProf); -#endif #endif // HAVE_CG int nenvvertparams, nenvfragparams, naddrregisters[2]; - glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvvertparams); - glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvfragparams); - glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[0]); - glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[1]); - DEBUG_LOG(VIDEO, "Max program env parameters: vert=%d, frag=%d", nenvvertparams, nenvfragparams); - DEBUG_LOG(VIDEO, "Max program address register parameters: vert=%d, frag=%d", naddrregisters[0], naddrregisters[1]); + glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, + GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, + (GLint *)&nenvvertparams); + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, + GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, + (GLint *)&nenvfragparams); + glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, + GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, + (GLint *)&naddrregisters[0]); + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, + GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, + (GLint *)&naddrregisters[1]); + DEBUG_LOG(VIDEO, "Max program env parameters: vert=%d, frag=%d", + nenvvertparams, nenvfragparams); + DEBUG_LOG(VIDEO, "Max program address register parameters: vert=%d, frag=%d", + naddrregisters[0], naddrregisters[1]); if (nenvvertparams < 238) ERROR_LOG(VIDEO, "Not enough vertex shader environment constants!!"); @@ -441,7 +463,7 @@ cgGLSetDebugMode(GL_FALSE); #endif #endif - + glStencilFunc(GL_ALWAYS, 0, 0); glBlendFunc(GL_ONE, GL_ONE); @@ -458,9 +480,9 @@ glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDepthFunc(GL_LEQUAL); - + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment - + glDisable(GL_STENCIL_TEST); glEnable(GL_SCISSOR_TEST); @@ -479,7 +501,7 @@ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); UpdateActiveConfig(); - return glGetError() == GL_NO_ERROR && bSuccess; + return GL_REPORT_ERROR() == GL_NO_ERROR && bSuccess; } void Renderer::Shutdown(void) @@ -490,22 +512,26 @@ s_pfont = 0; #if defined HAVE_CG && HAVE_CG - if (g_cgcontext) { + if (g_cgcontext) + { cgDestroyContext(g_cgcontext); g_cgcontext = 0; } #endif +#if defined(HAVE_WX) && HAVE_WX + if (scrshotThread) + delete scrshotThread; +#endif + g_framebufferManager.Shutdown(); #ifdef _WIN32 - if(s_bAVIDumping) { + if(s_bAVIDumping) AVIDump::Stop(); - } #else - if(f_pFrameDump != NULL) { + if(f_pFrameDump != NULL) fclose(f_pFrameDump); - } #endif } @@ -517,6 +543,7 @@ else return false; } + bool Renderer::AllowCustom() { if (GetCustomWidth() <= GetFrameBufferWidth() && GetCustomHeight() <= GetFrameBufferHeight()) @@ -530,28 +557,34 @@ { return m_FrameBufferWidth; } + int Renderer::GetFrameBufferHeight() { return m_FrameBufferHeight; } + // Return the custom resolution int Renderer::GetCustomWidth() { return m_CustomWidth; } + int Renderer::GetCustomHeight() { return m_CustomHeight; } + // Return the rendering target width and height int Renderer::GetTargetWidth() { return m_FrameBufferWidth; } + int Renderer::GetTargetHeight() { return m_FrameBufferHeight; } + float Renderer::GetTargetScaleX() { return EFBxScale; @@ -562,16 +595,21 @@ return EFByScale; } +float Renderer::GetXFBScaleX() +{ + return xScale; +} -float Renderer::GetXFBScaleX() { return xScale; } -float Renderer::GetXFBScaleY() { return yScale; } +float Renderer::GetXFBScaleY() +{ + return yScale; +} TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) { return g_framebufferManager.ConvertEFBRectangle(rc); } - void Renderer::ResetAPIState() { // Gets us to a reasonably sane state where it's possible to do things like @@ -615,7 +653,7 @@ } void Renderer::SetBlendMode(bool forceUpdate) -{ +{ // blend mode bit mask // 0 - blend enable // 2 - reverse subtract enable (else add) @@ -624,30 +662,28 @@ u32 newval = bpmem.blendmode.subtract << 2; - if (bpmem.blendmode.subtract) { + if (bpmem.blendmode.subtract) newval |= 0x0049; // enable blending src 1 dst 1 - } else if (bpmem.blendmode.blendenable) { + else if (bpmem.blendmode.blendenable) + { newval |= 1; // enable blending newval |= bpmem.blendmode.srcfactor << 3; newval |= bpmem.blendmode.dstfactor << 6; } - + u32 changes = forceUpdate ? 0xFFFFFFFF : newval ^ s_blendMode; - if (changes & 1) { + if (changes & 1) // blend enable change (newval & 1) ? glEnable(GL_BLEND) : glDisable(GL_BLEND); - } - if (changes & 4) { + if (changes & 4) // subtract enable change glBlendEquation(newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD); - } - if (changes & 0x1F8) { + if (changes & 0x1F8) // blend RGB change glBlendFunc(glSrcFactors[(newval >> 3) & 7], glDestFactors[(newval >> 6) & 7]); - } s_blendMode = newval; } @@ -755,10 +791,9 @@ float rc_top = (float)bpmem.scissorTL.y - yoff - 342; // right = 0 if (rc_top < 0) rc_top = 0; - + float rc_right = (float)bpmem.scissorBR.x - xoff - 341; // right = 640 if (rc_right > EFB_WIDTH) rc_right = EFB_WIDTH; - float rc_bottom = (float)bpmem.scissorBR.y - yoff - 341; // bottom = 480 if (rc_bottom > EFB_HEIGHT) rc_bottom = EFB_HEIGHT; @@ -776,7 +811,6 @@ rc_top = temp; } - // Check that the coordinates are good if (rc_right != rc_left && rc_bottom != rc_top) { @@ -785,7 +819,7 @@ (int)((EFB_HEIGHT - rc_bottom) * EFByScale), // y = 0 for example (int)((rc_right - rc_left)* EFBxScale), // width = 640 for example (int)((rc_bottom - rc_top) * EFByScale) // height = 480 for example - ); + ); return true; } else @@ -793,24 +827,22 @@ glScissor( 0, 0, - Renderer::GetTargetWidth(), + Renderer::GetTargetWidth(), Renderer::GetTargetHeight() ); } return false; } -void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) +void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, + bool alphaEnable, bool zEnable, u32 color, u32 z) { - // Update the view port for clearing the picture TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc); glViewport(targetRc.left, targetRc.bottom, targetRc.GetWidth(), targetRc.GetHeight()); glScissor(targetRc.left, targetRc.bottom, targetRc.GetWidth(), targetRc.GetHeight()); - // Always set the scissor in case it was set by the game and has not been reset - VertexShaderManager::SetViewportChanged(); @@ -835,6 +867,7 @@ glClear(bits); SetScissorRect(); } + static bool XFBWrited = false; void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc) { @@ -847,9 +880,7 @@ // XXX: Without the VI, how would we know what kind of field this is? So // just use progressive. if (g_ActiveConfig.bUseXFB) - { g_framebufferManager.CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc); - } else { Renderer::Swap(xfbAddr, FIELD_PROGRESSIVE, fbWidth, fbHeight,sourceRc); @@ -898,7 +929,6 @@ // Copy the framebuffer to screen. - // Texture map s_xfbTexture onto the main buffer glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_RECTANGLE_ARB); @@ -969,32 +999,51 @@ drawRc.left = -1; drawRc.right = 1; } - + // Tell the OSD Menu about the current internal resolution OSDInternalW = xfbSource->sourceRc.GetWidth(); OSDInternalH = xfbSource->sourceRc.GetHeight(); // Texture map xfbSource->texture onto the main buffer glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbSource->texture); - // We must call ApplyShader here even if no post proc is selected - it takes - // care of disabling it in that case. It returns false in case of no post processing. + // We must call ApplyShader here even if no post proc is selected. + // It takes care of disabling it in that case. It returns false in + // case of no post processing. if (applyShader) { glBegin(GL_QUADS); - glTexCoord2f(sourceRc.left, sourceRc.bottom); glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0); glVertex2f(drawRc.left, drawRc.bottom); - glTexCoord2f(sourceRc.left, sourceRc.top); glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1); glVertex2f(drawRc.left, drawRc.top); - glTexCoord2f(sourceRc.right, sourceRc.top); glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1); glVertex2f(drawRc.right, drawRc.top); - glTexCoord2f(sourceRc.right, sourceRc.bottom); glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0); glVertex2f(drawRc.right, drawRc.bottom); + glTexCoord2f(sourceRc.left, sourceRc.bottom); + glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0); + glVertex2f(drawRc.left, drawRc.bottom); + + glTexCoord2f(sourceRc.left, sourceRc.top); + glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1); + glVertex2f(drawRc.left, drawRc.top); + + glTexCoord2f(sourceRc.right, sourceRc.top); + glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1); + glVertex2f(drawRc.right, drawRc.top); + + glTexCoord2f(sourceRc.right, sourceRc.bottom); + glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0); + glVertex2f(drawRc.right, drawRc.bottom); glEnd(); PixelShaderCache::DisableShader(); } else { glBegin(GL_QUADS); - glTexCoord2f(sourceRc.left, sourceRc.bottom); glVertex2f(drawRc.left, drawRc.bottom); - glTexCoord2f(sourceRc.left, sourceRc.top); glVertex2f(drawRc.left, drawRc.top); - glTexCoord2f(sourceRc.right, sourceRc.top); glVertex2f(drawRc.right, drawRc.top); - glTexCoord2f(sourceRc.right, sourceRc.bottom); glVertex2f(drawRc.right, drawRc.bottom); + glTexCoord2f(sourceRc.left, sourceRc.bottom); + glVertex2f(drawRc.left, drawRc.bottom); + + glTexCoord2f(sourceRc.left, sourceRc.top); + glVertex2f(drawRc.left, drawRc.top); + + glTexCoord2f(sourceRc.right, sourceRc.top); + glVertex2f(drawRc.right, drawRc.top); + + glTexCoord2f(sourceRc.right, sourceRc.bottom); + glVertex2f(drawRc.right, drawRc.bottom); glEnd(); } @@ -1011,24 +1060,41 @@ if (applyShader) { glBegin(GL_QUADS); - glTexCoord2f(targetRc.left, targetRc.bottom); glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0); glVertex2f(-1, -1); - glTexCoord2f(targetRc.left, targetRc.top); glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1); glVertex2f(-1, 1); - glTexCoord2f(targetRc.right, targetRc.top); glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1); glVertex2f( 1, 1); - glTexCoord2f(targetRc.right, targetRc.bottom); glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0); glVertex2f( 1, -1); + glTexCoord2f(targetRc.left, targetRc.bottom); + glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0); + glVertex2f(-1, -1); + + glTexCoord2f(targetRc.left, targetRc.top); + glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1); + glVertex2f(-1, 1); + + glTexCoord2f(targetRc.right, targetRc.top); + glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1); + glVertex2f( 1, 1); + + glTexCoord2f(targetRc.right, targetRc.bottom); + glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0); + glVertex2f( 1, -1); glEnd(); PixelShaderCache::DisableShader(); } else { glBegin(GL_QUADS); - glTexCoord2f(targetRc.left, targetRc.bottom); glVertex2f(-1, -1); - glTexCoord2f(targetRc.left, targetRc.top); glVertex2f(-1, 1); - glTexCoord2f(targetRc.right, targetRc.top); glVertex2f( 1, 1); - glTexCoord2f(targetRc.right, targetRc.bottom); glVertex2f( 1, -1); + glTexCoord2f(targetRc.left, targetRc.bottom); + glVertex2f(-1, -1); + + glTexCoord2f(targetRc.left, targetRc.top); + glVertex2f(-1, 1); + + glTexCoord2f(targetRc.right, targetRc.top); + glVertex2f( 1, 1); + + glTexCoord2f(targetRc.right, targetRc.bottom); + glVertex2f( 1, -1); glEnd(); } - - + } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); TextureMngr::DisableStage(0); @@ -1046,7 +1112,7 @@ // Reset settings s_sScreenshotName = ""; s_bScreenshot = false; - s_criticalScreenshot.Leave(); + s_criticalScreenshot.Leave(); } // Frame dumps are handled a little differently in Windows @@ -1059,17 +1125,18 @@ u8 *data = (u8 *) malloc(3 * w * h); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(back_rc.left, back_rc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); - if (glGetError() == GL_NO_ERROR && w > 0 && h > 0) + if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0) { if (!s_bLastFrameDumped) { s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h); - if (!s_bAVIDumping) + if (!s_bAVIDumping) OSD::AddMessage("AVIDump Start failed", 2000); else { OSD::AddMessage(StringFromFormat( - "Dumping Frames to \"%sframedump0.avi\" (%dx%d RGB24)", File::GetUserPath(D_DUMPFRAMES_IDX), w, h).c_str(), 2000); + "Dumping Frames to \"%sframedump0.avi\" (%dx%d RGB24)", + File::GetUserPath(D_DUMPFRAMES_IDX), w, h).c_str(), 2000); } } if (s_bAVIDumping) @@ -1078,11 +1145,10 @@ s_bLastFrameDumped = true; } else - { NOTICE_LOG(VIDEO, "Error reading framebuffer"); - } + free(data); - s_criticalScreenshot.Leave(); + s_criticalScreenshot.Leave(); } else { @@ -1095,7 +1161,8 @@ s_bLastFrameDumped = false; } #else - if (g_ActiveConfig.bDumpFrames) { + if (g_ActiveConfig.bDumpFrames) + { s_criticalScreenshot.Enter(); char movie_file_name[255]; int w = back_rc.GetWidth(); @@ -1103,33 +1170,40 @@ u8 *data = (u8 *) malloc(3 * w * h); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(back_rc.left, back_rc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); - if (glGetError() == GL_NO_ERROR) { - if (!s_bLastFrameDumped) { + if (GL_REPORT_ERROR() == GL_NO_ERROR) + { + if (!s_bLastFrameDumped) + { sprintf(movie_file_name, "%sframedump.raw", File::GetUserPath(D_DUMPFRAMES_IDX)); f_pFrameDump = fopen(movie_file_name, "wb"); - if (f_pFrameDump == NULL) { - PanicAlert("Error opening framedump.raw for writing."); - } else { + if (f_pFrameDump == NULL) + OSD::AddMessage("Error opening framedump.raw for writing.", 2000); + else + { char msg [255]; sprintf(msg, "Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name, w, h); OSD::AddMessage(msg, 2000); } } - if (f_pFrameDump != NULL) { + if (f_pFrameDump != NULL) + { FlipImageData(data, w, h); fwrite(data, w * 3, h, f_pFrameDump); fflush(f_pFrameDump); } s_bLastFrameDumped = true; } + free(data); s_criticalScreenshot.Leave(); - } else { - if (s_bLastFrameDumped && f_pFrameDump != NULL) { + } + else + { + if (s_bLastFrameDumped && f_pFrameDump != NULL) + { fclose(f_pFrameDump); f_pFrameDump = NULL; } - s_bLastFrameDumped = false; } #endif @@ -1156,7 +1230,6 @@ m_CustomHeight = H; } - if( xfbchanged || WindowResized) { TargetRectangle dst_rect; @@ -1178,23 +1251,24 @@ yScale = (float)(dst_rect.bottom - dst_rect.top) / (float)s_XFB_height; } } - - + EFBxScale = ceilf(xScale); EFByScale = ceilf(yScale); int m_newFrameBufferWidth = EFB_WIDTH * EFBxScale; int m_newFrameBufferHeight = EFB_HEIGHT * EFByScale; - if(m_newFrameBufferWidth != m_FrameBufferWidth || m_newFrameBufferHeight != m_FrameBufferHeight ) + if(m_newFrameBufferWidth != m_FrameBufferWidth || + m_newFrameBufferHeight != m_FrameBufferHeight ) { m_FrameBufferWidth = m_newFrameBufferWidth; m_FrameBufferHeight = m_newFrameBufferHeight; g_framebufferManager.Shutdown(); - g_framebufferManager.Init(m_FrameBufferWidth, m_FrameBufferHeight, s_MSAASamples, s_MSAACoverageSamples); + g_framebufferManager.Init(m_FrameBufferWidth, m_FrameBufferHeight, + s_MSAASamples, s_MSAACoverageSamples); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); } - + } // Place messages on the picture, then copy it to the screen @@ -1202,17 +1276,17 @@ // Count FPS. // ------------- static int fpscount = 0; - static unsigned long lasttime; - ++fpscount; - if (Common::Timer::GetTimeMs() - lasttime > 1000) + static unsigned long lasttime = 0; + if (Common::Timer::GetTimeMs() - lasttime >= 1000) { lasttime = Common::Timer::GetTimeMs(); - s_fps = fpscount - 1; + s_fps = fpscount; fpscount = 0; } + ++fpscount; // --------------------------------------------------------------------- GL_REPORT_ERRORD(); - + DrawDebugText(); GL_REPORT_ERRORD(); @@ -1224,21 +1298,25 @@ if (blend_enabled) glEnable(GL_BLEND); GL_REPORT_ERRORD(); + #if defined(DVPROFILE) - if (g_bWriteProfile) { + if (g_bWriteProfile) + { //g_bWriteProfile = 0; static int framenum = 0; const int UPDATE_FRAMES = 8; - if (++framenum >= UPDATE_FRAMES) { + if (++framenum >= UPDATE_FRAMES) + { DVProfWrite("prof.txt", UPDATE_FRAMES); DVProfClear(); framenum = 0; } } #endif + // Copy the rendered frame to the real window OpenGL_SwapBuffers(); - + GL_REPORT_ERRORD(); // Clear framebuffer @@ -1273,10 +1351,10 @@ // For testing zbuffer targets. // Renderer::SetZBufferRender(); - // SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, s_FakeZTarget, GetTargetWidth(), GetTargetHeight()); - g_VideoInitialize.pCopiedToXFB(XFBWrited || g_ActiveConfig.bUseRealXFB); + // SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, s_FakeZTarget, + // GetTargetWidth(), GetTargetHeight()); + g_VideoInitialize.pCopiedToXFB(XFBWrited || g_ActiveConfig.bUseRealXFB); XFBWrited = false; - } // Create On-Screen-Messages @@ -1304,7 +1382,8 @@ glBegin(GL_LINES); // Draw EFB copy regions rectangles - for (std::vector::const_iterator it = stats.efb_regions.begin(); it != stats.efb_regions.end(); ++it) + for (std::vector::const_iterator it = stats.efb_regions.begin(); + it != stats.efb_regions.end(); ++it) { GLfloat halfWidth = EFB_WIDTH / 2.0f; GLfloat halfHeight = EFB_HEIGHT / 2.0f; @@ -1338,14 +1417,10 @@ } if (g_ActiveConfig.bOverlayStats) - { p = Statistics::ToString(p); - } if (g_ActiveConfig.bOverlayProjStats) - { p = Statistics::ToStringProj(p); - } // Render a shadow, and then the text. if (p != debugtext_buffer) @@ -1372,8 +1447,8 @@ H = OpenGL_GetBackbufferHeight(); std::string OSDM1 = - g_ActiveConfig.bNativeResolution || g_ActiveConfig.b2xResolution ? - (g_ActiveConfig.bNativeResolution ? + g_ActiveConfig.bNativeResolution || g_ActiveConfig.b2xResolution ? + (g_ActiveConfig.bNativeResolution ? StringFromFormat("%i x %i (native)", OSDInternalW, OSDInternalH) : StringFromFormat("%i x %i (2x)", OSDInternalW, OSDInternalH)) : StringFromFormat("%i x %i (custom)", W, H); @@ -1403,11 +1478,16 @@ { T1 += "\n\n"; T2 += "\n\n"; } // The rows - T0.push_back(StringFromFormat("3: Internal Resolution: %s\n", OSDM1.c_str())); - T0.push_back(StringFromFormat("4: Aspect Ratio: %s%s\n", OSDM21.c_str(), OSDM22.c_str())); - T0.push_back(StringFromFormat("5: Copy EFB: %s\n", OSDM3.c_str())); - T0.push_back(StringFromFormat("6: Fog: %s\n", g_ActiveConfig.bDisableFog ? "Disabled" : "Enabled")); - T0.push_back(StringFromFormat("7: Material Lighting: %s\n", g_ActiveConfig.bDisableLighting ? "Disabled" : "Enabled")); + T0.push_back(StringFromFormat("3: Internal Resolution: %s\n", + OSDM1.c_str())); + T0.push_back(StringFromFormat("4: Aspect Ratio: %s%s\n", + OSDM21.c_str(), OSDM22.c_str())); + T0.push_back(StringFromFormat("5: Copy EFB: %s\n", + OSDM3.c_str())); + T0.push_back(StringFromFormat("6: Fog: %s\n", + g_ActiveConfig.bDisableFog ? "Disabled" : "Enabled")); + T0.push_back(StringFromFormat("7: Material Lighting: %s\n", + g_ActiveConfig.bDisableLighting ? "Disabled" : "Enabled")); // The latest changed setting in yellow T1 += (OSDChoice == -1) ? T0.at(0) : "\n"; @@ -1431,15 +1511,16 @@ } } } + void Renderer::RenderText(const char* pstr, int left, int top, u32 color) { int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth(); int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight(); - glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f, + glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f, ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f); - s_pfont->printMultilineText(pstr, - left * 2.0f / (float)nBackbufferWidth - 1, - 1 - top * 2.0f / (float)nBackbufferHeight, + s_pfont->printMultilineText(pstr, + left * 2.0f / (float)nBackbufferWidth - 1, + 1 - top * 2.0f / (float)nBackbufferHeight, 0, nBackbufferWidth, nBackbufferHeight); GL_REPORT_ERRORD(); } @@ -1457,7 +1538,7 @@ THREAD_RETURN TakeScreenshot(void *pArgs) { ScrStrct *threadStruct = (ScrStrct *)pArgs; - + // These will contain the final image size float FloatW = (float)threadStruct->W; float FloatH = (float)threadStruct->H; @@ -1466,33 +1547,35 @@ if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) { bool use16_9 = g_VideoInitialize.bAutoAspectIs16_9; - + // Check for force-settings and override. if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9) use16_9 = true; else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3) use16_9 = false; - + float Ratio = (FloatW / FloatH) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f)); - + // If ratio > 1 the picture is too wide and we have to limit the width. if (Ratio > 1) FloatW /= Ratio; // ratio == 1 or the image is too high, we have to limit the height. else FloatH *= Ratio; - + // This is a bit expensive on high resolutions threadStruct->img->Rescale((int)FloatW, (int)FloatH, wxIMAGE_QUALITY_HIGH); } // Save the screenshot and finally kill the wxImage object // This is really expensive when saving to PNG, but not at all when using BMP - threadStruct->img->SaveFile(wxString::FromAscii(threadStruct->filename.c_str()), wxBITMAP_TYPE_PNG); + threadStruct->img->SaveFile(wxString::FromAscii(threadStruct->filename.c_str()), + wxBITMAP_TYPE_PNG); threadStruct->img->Destroy(); - + // Show success messages - OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH, threadStruct->filename.c_str()).c_str(), 2000); + OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH, + threadStruct->filename.c_str()).c_str(), 2000); delete threadStruct; return 0; @@ -1519,53 +1602,50 @@ u32 H = back_rc.GetHeight(); u8 *data = (u8 *)malloc(3 * W * H); glPixelStorei(GL_PACK_ALIGNMENT, 1); - + glReadPixels(back_rc.left, back_rc.bottom, W, H, GL_RGB, GL_UNSIGNED_BYTE, data); - + // Show failure message - if (glGetError() != GL_NO_ERROR) + if (GL_REPORT_ERROR() != GL_NO_ERROR) { OSD::AddMessage("Error capturing or saving screenshot.", 2000); return false; } - + // Turn image upside down FlipImageData(data, W, H); - + #if defined(HAVE_WX) && HAVE_WX // Create wxImage wxImage *a = new wxImage(W, H, data); - + if (scrshotThread) { delete scrshotThread; scrshotThread = NULL; } - + ScrStrct *threadStruct = new ScrStrct; threadStruct->filename = std::string(filename); threadStruct->img = a; threadStruct->H = H; threadStruct->W = W; - + scrshotThread = new Common::Thread(TakeScreenshot, threadStruct); #ifdef _WIN32 scrshotThread->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); #endif bool result = true; - + OSD::AddMessage("Saving Screenshot... ", 2000); - + #else bool result = SaveTGA(filename, W, H, data); free(data); #endif - + return result; } - - - // Called from VertexShaderManager void UpdateViewport() { @@ -1576,14 +1656,17 @@ // [3] = xorig + width/2 + 342 // [4] = yorig + height/2 + 342 // [5] = 16777215 * farz - int scissorXOff = bpmem.scissorOffset.x * 2; // 342 - int scissorYOff = bpmem.scissorOffset.y * 2; // 342 - + float scissorXOff = float(bpmem.scissorOffset.x) * 2.0f; // 342 + float scissorYOff = float(bpmem.scissorOffset.y) * 2.0f; // 342 + // Stretch picture with increased internal resolution - int GLx = (int)ceil((xfregs.rawViewport[3] - xfregs.rawViewport[0] - scissorXOff) * EFBxScale); - int GLy = (int)ceil((float)((int)(EFB_HEIGHT - xfregs.rawViewport[4] + xfregs.rawViewport[1] + scissorYOff)) * EFByScale); - int GLWidth = (int)ceil((float)(2 * xfregs.rawViewport[0]) * EFBxScale); - int GLHeight = (int)ceil((float)(-2 * xfregs.rawViewport[1]) * EFByScale); + int GLx = (int)ceil((xfregs.rawViewport[3] - xfregs.rawViewport[0] - scissorXOff) * + EFBxScale); + int GLy = (int)ceil( + (float(EFB_HEIGHT) - xfregs.rawViewport[4] + xfregs.rawViewport[1] + scissorYOff) * + EFByScale); + int GLWidth = (int)ceil(2.0f * xfregs.rawViewport[0] * EFBxScale); + int GLHeight = (int)ceil(-2.0f * xfregs.rawViewport[1] * EFByScale); double GLNear = (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777216.0f; double GLFar = xfregs.rawViewport[5] / 16777216.0f; if(GLWidth < 0) @@ -1648,12 +1731,13 @@ glDisable(GL_DITHER); } - void Renderer::SetLineWidth() { - float fratio = xfregs.rawViewport[0] != 0 ? ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f; + float fratio = xfregs.rawViewport[0] != 0 ? + ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f; if (bpmem.lineptwidth.linesize > 0) - glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths + // scale by ratio of widths + glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); if (bpmem.lineptwidth.pointsize > 0) glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -583,13 +583,12 @@ entry.SetTextureParameters(tm0,tm1); if (g_ActiveConfig.bDumpTextures) // dump texture to file { - char szTemp[MAX_PATH]; char szDir[MAX_PATH]; const char* uniqueId = globals->unique_id; - bool bCheckedDumpDir = false; + static bool bCheckedDumpDir = false; - sprintf(szDir,"%s%s",File::GetUserPath(D_DUMPTEXTURES_IDX), uniqueId); + sprintf(szDir,"%s%s", File::GetUserPath(D_DUMPTEXTURES_IDX), uniqueId); if(!bCheckedDumpDir) { @@ -599,11 +598,9 @@ bCheckedDumpDir = true; } - sprintf(szTemp, "%s/%s_%08x_%i.tga",szDir, uniqueId, (unsigned int) texHash, tex_format); + sprintf(szTemp, "%s/%s_%08x_%i.tga", szDir, uniqueId, (unsigned int) texHash, tex_format); if (!File::Exists(szTemp)) - { - SaveTexture(szTemp, target, entry.texture, expandedWidth, expandedHeight); - } + SaveTexture(szTemp, target, entry.texture, entry.w, entry.h); } INCSTAT(stats.numTexturesCreated); @@ -792,7 +789,7 @@ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (glGetError() != GL_NO_ERROR) { + if (GL_REPORT_ERROR() != GL_NO_ERROR) { glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); GL_REPORT_ERRORD(); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -41,6 +41,8 @@ #include "OpcodeDecoding.h" #include "FileUtil.h" +#include "main.h" + // internal state for loading vertices extern NativeVertexFormat *g_nativeVertexFmt; @@ -144,7 +146,7 @@ { if (numvertices <= 0) return; - GL_REPORT_ERROR(); + (void)GL_REPORT_ERROR(); switch (primitive) { case GX_DRAW_QUADS: @@ -233,9 +235,7 @@ DVSTARTPROFILE(); - GL_REPORT_ERROR(); - - + (void)GL_REPORT_ERROR(); glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]); glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - LocalVBuffer, LocalVBuffer, GL_STREAM_DRAW); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -41,58 +41,34 @@ static VERTEXSHADER *pShaderLast = NULL; static int s_nMaxVertexInstructions; -static float GC_ALIGNED16(lastVSconstants[C_VENVCONST_END][4]); void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4) { - if ( lastVSconstants[const_number][0] != f1 || - lastVSconstants[const_number][1] != f2 || - lastVSconstants[const_number][2] != f3 || - lastVSconstants[const_number][3] != f4) - { - lastVSconstants[const_number][0] = f1; - lastVSconstants[const_number][1] = f2; - lastVSconstants[const_number][2] = f3; - lastVSconstants[const_number][3] = f4; - glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, lastVSconstants[const_number]); - } + float f[4] = { f1, f2, f3, f4 }; + glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f); } void SetVSConstant4fv(unsigned int const_number, const float *f) { - if (memcmp(&lastVSconstants[const_number], f, sizeof(float) * 4)) { - memcpy(&lastVSconstants[const_number], f, sizeof(float) * 4); - glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, lastVSconstants[const_number]); - } + glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f); } void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f) { - const float *f0 = f; - for (unsigned int i = 0; i < count; i++,f0+=4) - { - if (memcmp(&lastVSconstants[const_number + i], f0, sizeof(float) * 4)) { - memcpy(&lastVSconstants[const_number + i], f0, sizeof(float) * 4); - glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, lastVSconstants[const_number + i]); - } - } + for (unsigned int i = 0; i < count; i++,f+=4) + glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, f); } void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f) { for (unsigned int i = 0; i < count; i++) { - if (lastVSconstants[const_number + i][0] != f[0 + i*3] || - lastVSconstants[const_number + i][1] != f[1 + i*3] || - lastVSconstants[const_number + i][2] != f[2 + i*3] || - lastVSconstants[const_number + i][3] != 0.0f) - { - lastVSconstants[const_number + i][0] = f[0 + i*3]; - lastVSconstants[const_number + i][1] = f[1 + i*3]; - lastVSconstants[const_number + i][2] = f[2 + i*3]; - lastVSconstants[const_number + i][3] = 0.0f; - glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, lastVSconstants[const_number + i]); - } + float buf[4]; + buf[0] = *f++; + buf[1] = *f++; + buf[2] = *f++; + buf[3] = 0.f; + glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number + i, buf); } } @@ -102,8 +78,6 @@ glEnable(GL_VERTEX_PROGRAM_ARB); ShaderEnabled = true; CurrentShader = 0; - for (int i = 0; i < (C_VENVCONST_END * 4); i++) - lastVSconstants[i / 4][i % 4] = -100000000.0f; memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid)); s_displayCompileAlert = true; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoSoftware/Src/GLUtil.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoSoftware/Src/GLUtil.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoSoftware/Src/GLUtil.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoSoftware/Src/GLUtil.h 2010-08-18 03:25:23.000000000 +0100 @@ -66,7 +66,6 @@ #ifndef _WIN32 -#include #include typedef struct { @@ -111,19 +110,15 @@ GLuint OpenGL_ReportGLError(const char *function, const char *file, int line); bool OpenGL_ReportFBOError(const char *function, const char *file, int line); -#if 1 +#if defined(_DEBUG) || defined(DEBUGFAST) #define GL_REPORT_ERROR() OpenGL_ReportGLError (__FUNCTION__, __FILE__, __LINE__) #define GL_REPORT_PROGRAM_ERROR() OpenGL_ReportARBProgramError() #define GL_REPORT_FBO_ERROR() OpenGL_ReportFBOError (__FUNCTION__, __FILE__, __LINE__) +#define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__) #else #define GL_REPORT_ERROR() GL_NO_ERROR #define GL_REPORT_PROGRAM_ERROR() #define GL_REPORT_FBO_ERROR() -#endif - -#if defined(_DEBUG) || defined(DEBUGFAST) -#define GL_REPORT_ERRORD() OpenGL_ReportGLError(__FUNCTION__, __FILE__, __LINE__) -#else #define GL_REPORT_ERRORD() #endif diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoSoftware/Src/main.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoSoftware/Src/main.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoSoftware/Src/main.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoSoftware/Src/main.cpp 2010-08-18 03:25:23.000000000 +0100 @@ -66,7 +66,7 @@ return NULL; } -void DllConfig(HWND _hParent) +void DllConfig(void *_hParent) { } @@ -220,3 +220,7 @@ { return false; } + +void Video_AbortFrame(void) +{ +} diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_VideoSoftware/Src/Vec3.h 2010-08-18 03:25:23.000000000 +0100 @@ -96,7 +96,7 @@ { return *((&x) + i); } - const float operator [] (const int i) const + float operator [] (const int i) const { return *((&x) + i); } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -24,7 +24,7 @@ #include "Config.h" #include "EmuDefinitions.h" // for joyinfo -BEGIN_EVENT_TABLE(WiimotePadConfigDialog,wxDialog) +BEGIN_EVENT_TABLE(WiimotePadConfigDialog, wxDialog) EVT_CLOSE(WiimotePadConfigDialog::OnClose) EVT_BUTTON(wxID_CLOSE, WiimotePadConfigDialog::CloseClick) @@ -49,7 +49,7 @@ EVT_CHECKBOX(IDC_TILT_PITCH_SWING, WiimotePadConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(IDC_TILT_ROLL_INVERT, WiimotePadConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(IDC_TILT_PITCH_INVERT, WiimotePadConfigDialog::GeneralSettingsChanged) - EVT_CHOICE(IDC_TRIGGER_TYPE, WiimotePadConfigDialog::GeneralSettingsChanged) + EVT_CHOICE(IDC_TRIGGER_TYPE, WiimotePadConfigDialog::GeneralSettingsChanged) EVT_CHOICE(IDC_NUNCHUCK_STICK, WiimotePadConfigDialog::GeneralSettingsChanged) EVT_CHOICE(IDC_CC_LEFT_STICK, WiimotePadConfigDialog::GeneralSettingsChanged) EVT_CHOICE(IDC_CC_RIGHT_STICK, WiimotePadConfigDialog::GeneralSettingsChanged) @@ -57,37 +57,72 @@ EVT_CHOICE(IDC_GH3_ANALOG, WiimotePadConfigDialog::GeneralSettingsChanged) // Analog - EVT_BUTTON(IDB_ANALOG_LEFT_X, WiimotePadConfigDialog::OnAxisClick) EVT_BUTTON(IDB_ANALOG_LEFT_Y, WiimotePadConfigDialog::OnAxisClick) - EVT_BUTTON(IDB_ANALOG_RIGHT_X, WiimotePadConfigDialog::OnAxisClick) EVT_BUTTON(IDB_ANALOG_RIGHT_Y, WiimotePadConfigDialog::OnAxisClick) - EVT_BUTTON(IDB_TRIGGER_L, WiimotePadConfigDialog::OnAxisClick) EVT_BUTTON(IDB_TRIGGER_R, WiimotePadConfigDialog::OnAxisClick) + EVT_BUTTON(IDB_ANALOG_LEFT_X, WiimotePadConfigDialog::OnAxisClick) + EVT_BUTTON(IDB_ANALOG_LEFT_Y, WiimotePadConfigDialog::OnAxisClick) + EVT_BUTTON(IDB_ANALOG_RIGHT_X, WiimotePadConfigDialog::OnAxisClick) + EVT_BUTTON(IDB_ANALOG_RIGHT_Y, WiimotePadConfigDialog::OnAxisClick) + EVT_BUTTON(IDB_TRIGGER_L, WiimotePadConfigDialog::OnAxisClick) + EVT_BUTTON(IDB_TRIGGER_R, WiimotePadConfigDialog::OnAxisClick) // Wiimote - EVT_BUTTON(IDB_WM_A, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_WM_B, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_WM_1, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_WM_2, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_WM_P, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_WM_M, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_A, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_B, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_1, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_2, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_P, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_M, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_WM_H, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_WM_L, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_WM_R, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_WM_U, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_WM_D, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_WM_ROLL_L, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_WM_ROLL_R, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_WM_PITCH_U, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_WM_PITCH_D, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_L, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_R, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_U, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_D, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_ROLL_L, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_ROLL_R, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_PITCH_U, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_WM_PITCH_D, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_WM_SHAKE, WiimotePadConfigDialog::OnButtonClick) // Nunchuck - EVT_BUTTON(IDB_NC_Z, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_NC_C, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_NC_L, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_NC_R, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_NC_U, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_NC_D, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_NC_ROLL_L, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_NC_ROLL_R, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_NC_PITCH_U, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_NC_PITCH_D, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_NC_SHAKE, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_Z, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_C, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_L, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_R, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_U, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_D, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_ROLL_L, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_ROLL_R, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_PITCH_U, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_NC_PITCH_D, WiimotePadConfigDialog::OnButtonClick) +EVT_BUTTON(IDB_NC_SHAKE, WiimotePadConfigDialog::OnButtonClick) // Classic Controller - EVT_BUTTON(IDB_CC_A, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_B, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_X, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_Y, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_CC_P, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_M, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_H, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_CC_TL, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_ZL, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_ZR, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_TR, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_CC_DL, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_DU, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_DR, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_DD, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_CC_DL, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_DU, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_DR, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_DD, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_CC_LL, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_LU, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_LR, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_LD, WiimotePadConfigDialog::OnButtonClick) - EVT_BUTTON(IDB_CC_RL, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_RU, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_RR, WiimotePadConfigDialog::OnButtonClick) EVT_BUTTON(IDB_CC_RD, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_A, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_B, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_X, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_Y, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_P, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_M, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_H, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_TL, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_ZL, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_ZR, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_TR, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_DL, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_DU, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_DR, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_DD, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_DL, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_DU, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_DR, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_DD, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_LL, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_LU, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_LR, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_LD, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_RL, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_RU, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_RR, WiimotePadConfigDialog::OnButtonClick) + EVT_BUTTON(IDB_CC_RD, WiimotePadConfigDialog::OnButtonClick) // Guitar Hero 3 EVT_BUTTON(IDB_GH3_GREEN, WiimotePadConfigDialog::OnButtonClick) @@ -107,8 +142,8 @@ END_EVENT_TABLE() -WiimotePadConfigDialog::WiimotePadConfigDialog(wxWindow *parent, wxWindowID id, const wxString &title, - const wxPoint &position, const wxSize& size, long style) +WiimotePadConfigDialog::WiimotePadConfigDialog(wxWindow *parent, wxWindowID id, + const wxString &title, const wxPoint &position, const wxSize& size, long style) : wxDialog(parent, id, title, position, size, style) { m_ControlsCreated = false;; @@ -327,7 +362,9 @@ wxBitmap WiimotePadConfigDialog::CreateBitmapDeadZone(int Radius) { - wxBitmap bitmap(Radius*2, Radius*2); + int _Radius = Radius ? Radius : 1; + + wxBitmap bitmap(_Radius * 2, _Radius * 2); wxMemoryDC dc; dc.SelectObject(bitmap); @@ -506,7 +543,6 @@ // Configuration controls sizes static const int BtW = 70, BtH = 20; -// static const int TxtW = 50, TxtH = 20; // These are never used. Will they ever be? // A small type font wxFont m_SmallFont(7, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); @@ -514,426 +550,502 @@ for (int i = 0; i < MAX_WIIMOTES; i++) { - m_Controller[i] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1 + i, wxDefaultPosition, wxDefaultSize); - m_Notebook->AddPage(m_Controller[i], wxString::Format(wxT("Wiimote %d"), i+1)); + wxPanel *m_Controller = + new wxPanel(m_Notebook, ID_CONTROLLERPAGE1 + i, wxDefaultPosition, wxDefaultSize); + m_Notebook->AddPage(m_Controller, wxString::Format(wxT("Wiimote %d"), i+1)); // Controller - m_Joyname[i] = new wxChoice(m_Controller[i], IDC_JOYNAME, wxDefaultPosition, wxSize(200, -1), StrJoyname, 0, wxDefaultValidator, StrJoyname[0]); + m_Joyname[i] = new wxChoice(m_Controller, IDC_JOYNAME, wxDefaultPosition, + wxSize(200, -1), StrJoyname, 0, wxDefaultValidator, StrJoyname[0]); m_Joyname[i]->SetToolTip(wxT("Save your settings and configure another joypad")); // Dead zone - m_ComboDeadZoneLabel[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Dead Zone")); - m_ComboDeadZoneLeft[i] = new wxChoice(m_Controller[i], IDC_DEAD_ZONE_LEFT, wxDefaultPosition, wxSize(50, -1), TextDeadZone, 0, wxDefaultValidator, TextDeadZone[0]); - m_ComboDeadZoneRight[i] = new wxChoice(m_Controller[i], IDC_DEAD_ZONE_RIGHT, wxDefaultPosition, wxSize(50, -1), TextDeadZone, 0, wxDefaultValidator, TextDeadZone[0]); + wxStaticText *m_ComboDeadZoneLabel = new wxStaticText(m_Controller, wxID_ANY, wxT("Dead Zone")); + m_ComboDeadZoneLeft[i] = new wxChoice(m_Controller, IDC_DEAD_ZONE_LEFT, + wxDefaultPosition, wxSize(50, -1), TextDeadZone, 0, wxDefaultValidator, TextDeadZone[0]); + m_ComboDeadZoneRight[i] = new wxChoice(m_Controller, IDC_DEAD_ZONE_RIGHT, + wxDefaultPosition, wxSize(50, -1), TextDeadZone, 0, wxDefaultValidator, TextDeadZone[0]); // Circle to square - m_CheckC2S[i] = new wxCheckBox(m_Controller[i], IDC_STICK_C2S, wxT("Circle To Square")); + m_CheckC2S[i] = new wxCheckBox(m_Controller, IDC_STICK_C2S, wxT("Circle To Square")); m_CheckC2S[i]->SetToolTip(wxT("This will convert a circular stick radius to a square stick radius.\n") wxT("This can be useful for the pitch and roll emulation.")); // The drop down menu for the circle to square adjustment - m_DiagonalLabel[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Diagonal")); - m_DiagonalLabel[i]->SetToolTip(wxT("To produce a perfect square circle in the 'Out' window you have to manually set\n") - wxT("your diagonal values here from what is shown in the 'In' window.")); - m_ComboDiagonal[i] = new wxChoice(m_Controller[i], IDC_STICK_DIAGONAL, wxDefaultPosition, wxSize(50, -1), StrDiagonal, 0, wxDefaultValidator, StrDiagonal[0]); + wxStaticText *m_DiagonalLabel = new wxStaticText(m_Controller, wxID_ANY, wxT("Diagonal")); + m_DiagonalLabel->SetToolTip(wxT("To produce a perfect square circle in the ") + wxT("'Out' window you have to manually set\n") + wxT("your diagonal values here from what is shown in the 'In' window.")); + m_ComboDiagonal[i] = new wxChoice(m_Controller, IDC_STICK_DIAGONAL, + wxDefaultPosition, wxSize(50, -1), StrDiagonal, 0, wxDefaultValidator, StrDiagonal[0]); // Rumble - m_CheckRumble[i] = new wxCheckBox(m_Controller[i], IDC_RUMBLE, wxT("Rumble")); - m_RumbleStrengthLabel[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Strength")); - m_RumbleStrength[i] = new wxChoice(m_Controller[i], IDC_RUMBLE_STRENGTH, wxDefaultPosition, wxSize(50, -1), StrRumble, 0, wxDefaultValidator, StrRumble[0]); + m_CheckRumble[i] = new wxCheckBox(m_Controller, IDC_RUMBLE, wxT("Rumble")); + wxStaticText *m_RumbleStrengthLabel = new wxStaticText(m_Controller, wxID_ANY, wxT("Strength")); + m_RumbleStrength[i] = new wxChoice(m_Controller, IDC_RUMBLE_STRENGTH, + wxDefaultPosition, wxSize(50, -1), StrRumble, 0, wxDefaultValidator, StrRumble[0]); // Sizers - m_sDeadZoneHoriz[i] = new wxBoxSizer(wxHORIZONTAL); - m_sDeadZoneHoriz[i]->Add(m_ComboDeadZoneLeft[i], 0, (wxUP), 0); - m_sDeadZoneHoriz[i]->Add(m_ComboDeadZoneRight[i], 0, (wxUP), 0); - - m_sDeadZone[i] = new wxBoxSizer(wxVERTICAL); - m_sDeadZone[i]->Add(m_ComboDeadZoneLabel[i], 0, wxALIGN_CENTER | (wxUP), 0); - m_sDeadZone[i]->Add(m_sDeadZoneHoriz[i], 0, wxALIGN_CENTER | (wxUP), 2); - - m_sDiagonal[i] = new wxBoxSizer(wxHORIZONTAL); - m_sDiagonal[i]->Add(m_DiagonalLabel[i], 0, (wxUP), 4); - m_sDiagonal[i]->Add(m_ComboDiagonal[i], 0, (wxLEFT), 2); - - m_sCircle2Square[i] = new wxBoxSizer(wxVERTICAL); - m_sCircle2Square[i]->Add(m_CheckC2S[i], 0, wxALIGN_CENTER | (wxUP), 0); - m_sCircle2Square[i]->Add(m_sDiagonal[i], 0, wxALIGN_CENTER | (wxUP), 2); - - m_sC2SDeadZone[i] = new wxBoxSizer(wxHORIZONTAL); - m_sC2SDeadZone[i]->Add(m_sDeadZone[i], 0, (wxUP), 0); - m_sC2SDeadZone[i]->Add(m_sCircle2Square[i], 0, (wxLEFT), 8); - - m_sJoyname[i] = new wxBoxSizer(wxVERTICAL); - m_sJoyname[i]->Add(m_Joyname[i], 0, wxALIGN_CENTER | (wxUP | wxDOWN), 4); - m_sJoyname[i]->Add(m_sC2SDeadZone[i], 0, (wxUP | wxDOWN), 4); - - m_sRumble[i] = new wxBoxSizer(wxVERTICAL); - m_sRumble[i]->Add(m_CheckRumble[i], 0, wxALIGN_CENTER | (wxUP | wxDOWN), 8); - m_sRumble[i]->Add(m_RumbleStrengthLabel[i], 0, wxALIGN_CENTER | (wxUP), 4); - m_sRumble[i]->Add(m_RumbleStrength[i], 0, (wxUP | wxDOWN), 2); - - m_gJoyPad[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Gamepad")); - m_gJoyPad[i]->AddStretchSpacer(); - m_gJoyPad[i]->Add(m_sJoyname[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); - m_gJoyPad[i]->Add(m_sRumble[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); - m_gJoyPad[i]->AddStretchSpacer(); + wxBoxSizer *m_sDeadZoneHoriz = new wxBoxSizer(wxHORIZONTAL); + m_sDeadZoneHoriz->Add(m_ComboDeadZoneLeft[i], 0, (wxUP), 0); + m_sDeadZoneHoriz->Add(m_ComboDeadZoneRight[i], 0, (wxUP), 0); + + wxBoxSizer *m_sDeadZone = new wxBoxSizer(wxVERTICAL); + m_sDeadZone->Add(m_ComboDeadZoneLabel, 0, wxALIGN_CENTER | (wxUP), 0); + m_sDeadZone->Add(m_sDeadZoneHoriz, 0, wxALIGN_CENTER | (wxUP), 2); + + wxBoxSizer *m_sDiagonal = new wxBoxSizer(wxHORIZONTAL); + m_sDiagonal->Add(m_DiagonalLabel, 0, (wxUP), 4); + m_sDiagonal->Add(m_ComboDiagonal[i], 0, (wxLEFT), 2); + + wxBoxSizer *m_sCircle2Square = new wxBoxSizer(wxVERTICAL); + m_sCircle2Square->Add(m_CheckC2S[i], 0, wxALIGN_CENTER | (wxUP), 0); + m_sCircle2Square->Add(m_sDiagonal, 0, wxALIGN_CENTER | (wxUP), 2); + + wxBoxSizer *m_sC2SDeadZone = new wxBoxSizer(wxHORIZONTAL); + m_sC2SDeadZone->Add(m_sDeadZone, 0, (wxUP), 0); + m_sC2SDeadZone->Add(m_sCircle2Square, 0, (wxLEFT), 8); + + wxBoxSizer *m_sJoyname = new wxBoxSizer(wxVERTICAL); + m_sJoyname->Add(m_Joyname[i], 0, wxALIGN_CENTER | (wxUP | wxDOWN), 4); + m_sJoyname->Add(m_sC2SDeadZone, 0, (wxUP | wxDOWN), 4); + + wxBoxSizer *m_sRumble = new wxBoxSizer(wxVERTICAL); + m_sRumble->Add(m_CheckRumble[i], 0, wxALIGN_CENTER | (wxUP | wxDOWN), 8); + m_sRumble->Add(m_RumbleStrengthLabel, 0, wxALIGN_CENTER | (wxUP), 4); + m_sRumble->Add(m_RumbleStrength[i], 0, (wxUP | wxDOWN), 2); + + wxStaticBoxSizer *m_gJoyPad = + new wxStaticBoxSizer (wxHORIZONTAL, m_Controller, wxT("Gamepad")); + m_gJoyPad->AddStretchSpacer(); + m_gJoyPad->Add(m_sJoyname, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); + m_gJoyPad->Add(m_sRumble, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); + m_gJoyPad->AddStretchSpacer(); // Tilt Wiimote - m_tTiltTypeWM[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Wiimote")); - m_tTiltTypeNC[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Nunchuck")); + wxStaticText *m_tTiltTypeWM = new wxStaticText(m_Controller, wxID_ANY, wxT("Wiimote")); + wxStaticText *m_tTiltTypeNC = new wxStaticText(m_Controller, wxID_ANY, wxT("Nunchuck")); - m_TiltTypeWM[i] = new wxChoice(m_Controller[i], IDC_TILT_TYPE_WM, wxDefaultPosition, wxSize(70, -1), StrTilt, 0, wxDefaultValidator, StrTilt[0]); + m_TiltTypeWM[i] = new wxChoice(m_Controller, IDC_TILT_TYPE_WM, + wxDefaultPosition, wxSize(70, -1), StrTilt, 0, wxDefaultValidator, StrTilt[0]); m_TiltTypeWM[i]->SetToolTip(wxT("Control Wiimote tilting by keyboard or stick or trigger")); - m_TiltTypeNC[i] = new wxChoice(m_Controller[i], IDC_TILT_TYPE_NC, wxDefaultPosition, wxSize(70, -1), StrTilt, 0, wxDefaultValidator, StrTilt[0]); + m_TiltTypeNC[i] = new wxChoice(m_Controller, IDC_TILT_TYPE_NC, + wxDefaultPosition, wxSize(70, -1), StrTilt, 0, wxDefaultValidator, StrTilt[0]); m_TiltTypeNC[i]->SetToolTip(wxT("Control Nunchuck tilting by keyboard or stick or trigger")); - m_TiltTextRoll[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Roll Left/Right")); - m_TiltTextPitch[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Pitch Up/Down")); + wxStaticText *m_TiltTextRoll = new wxStaticText(m_Controller, wxID_ANY, wxT("Roll Left/Right")); + wxStaticText *m_TiltTextPitch = new wxStaticText(m_Controller, wxID_ANY, wxT("Pitch Up/Down")); - m_TiltComboRangeRoll[i] = new wxChoice(m_Controller[i], IDC_TILT_ROLL, wxDefaultPosition, wxSize(50, -1), StrTiltRangeRoll, 0, wxDefaultValidator, StrTiltRangeRoll[0]); + m_TiltComboRangeRoll[i] = new wxChoice(m_Controller, IDC_TILT_ROLL, + wxDefaultPosition, wxSize(50, -1), StrTiltRangeRoll, 0, + wxDefaultValidator, StrTiltRangeRoll[0]); m_TiltComboRangeRoll[i]->SetToolTip(wxT("The maximum Left/Righ Roll in degrees")); - m_TiltComboRangePitch[i] = new wxChoice(m_Controller[i], IDC_TILT_PITCH, wxDefaultPosition, wxSize(50, -1), StrTiltRangePitch, 0, wxDefaultValidator, StrTiltRangePitch[0]); + m_TiltComboRangePitch[i] = new wxChoice(m_Controller, IDC_TILT_PITCH, + wxDefaultPosition, wxSize(50, -1), StrTiltRangePitch, 0, + wxDefaultValidator, StrTiltRangePitch[0]); m_TiltComboRangePitch[i]->SetToolTip(wxT("The maximum Up/Down Pitch in degrees")); - m_TiltRollSwing[i] = new wxCheckBox(m_Controller[i], IDC_TILT_ROLL_SWING, wxT("Swing")); + m_TiltRollSwing[i] = new wxCheckBox(m_Controller, IDC_TILT_ROLL_SWING, wxT("Swing")); m_TiltRollSwing[i]->SetToolTip(wxT("Emulate Swing Left/Right instead of Roll Left/Right")); - m_TiltPitchSwing[i] = new wxCheckBox(m_Controller[i], IDC_TILT_PITCH_SWING, wxT("Swing")); + m_TiltPitchSwing[i] = new wxCheckBox(m_Controller, IDC_TILT_PITCH_SWING, wxT("Swing")); m_TiltPitchSwing[i]->SetToolTip(wxT("Emulate Swing Up/Down instead of Pitch Up/Down")); - m_TiltRollInvert[i] = new wxCheckBox(m_Controller[i], IDC_TILT_ROLL_INVERT, wxT("Invert")); - m_TiltRollInvert[i]->SetToolTip(wxT("Invert Left/Right direction (only effective for stick and trigger)")); - m_TiltPitchInvert[i] = new wxCheckBox(m_Controller[i], IDC_TILT_PITCH_INVERT, wxT("Invert")); - m_TiltPitchInvert[i]->SetToolTip(wxT("Invert Up/Down direction (only effective for stick and trigger)")); + m_TiltRollInvert[i] = new wxCheckBox(m_Controller, IDC_TILT_ROLL_INVERT, wxT("Invert")); + m_TiltRollInvert[i]-> + SetToolTip(wxT("Invert Left/Right direction (only effective for stick and trigger)")); + m_TiltPitchInvert[i] = new wxCheckBox(m_Controller, IDC_TILT_PITCH_INVERT, wxT("Invert")); + m_TiltPitchInvert[i]-> + SetToolTip(wxT("Invert Up/Down direction (only effective for stick and trigger)")); // Sizers - m_sTiltType[i] = new wxBoxSizer(wxHORIZONTAL); - m_sTiltType[i]->Add(m_tTiltTypeWM[i], 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 4); - m_sTiltType[i]->Add(m_TiltTypeWM[i], 0, wxEXPAND | (wxDOWN | wxRIGHT), 4); - m_sTiltType[i]->Add(m_tTiltTypeNC[i], 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 4); - m_sTiltType[i]->Add(m_TiltTypeNC[i], 0, wxEXPAND | (wxDOWN | wxLEFT), 4); - - m_sGridTilt[i] = new wxGridBagSizer(0, 0); - m_sGridTilt[i]->Add(m_TiltTextRoll[i], wxGBPosition(0, 0), wxGBSpan(1, 1), (wxUP | wxRIGHT), 4); - m_sGridTilt[i]->Add(m_TiltComboRangeRoll[i], wxGBPosition(0, 1), wxGBSpan(1, 1), (wxLEFT | wxRIGHT), 4); - m_sGridTilt[i]->Add(m_TiltRollSwing[i], wxGBPosition(0, 2), wxGBSpan(1, 1), (wxUP | wxLEFT | wxRIGHT), 4); - m_sGridTilt[i]->Add(m_TiltRollInvert[i], wxGBPosition(0, 3), wxGBSpan(1, 1), (wxUP | wxLEFT), 4); - m_sGridTilt[i]->Add(m_TiltTextPitch[i], wxGBPosition(1, 0), wxGBSpan(1, 1), (wxUP | wxRIGHT), 4); - m_sGridTilt[i]->Add(m_TiltComboRangePitch[i], wxGBPosition(1, 1), wxGBSpan(1, 1), (wxLEFT | wxRIGHT), 4); - m_sGridTilt[i]->Add(m_TiltPitchSwing[i], wxGBPosition(1, 2), wxGBSpan(1, 1), (wxUP | wxLEFT | wxRIGHT), 4); - m_sGridTilt[i]->Add(m_TiltPitchInvert[i], wxGBPosition(1, 3), wxGBSpan(1, 1), (wxUP | wxLEFT), 4); - - m_gTilt[i] = new wxStaticBoxSizer (wxVERTICAL, m_Controller[i], wxT("Tilt and Swing")); - m_gTilt[i]->AddStretchSpacer(); - m_gTilt[i]->Add(m_sTiltType[i], 0, wxEXPAND | (wxLEFT | wxDOWN), 5); - m_gTilt[i]->Add(m_sGridTilt[i], 0, wxEXPAND | (wxLEFT), 5); - m_gTilt[i]->AddStretchSpacer(); + wxBoxSizer *m_sTiltType = new wxBoxSizer(wxHORIZONTAL); + m_sTiltType->Add(m_tTiltTypeWM, 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 4); + m_sTiltType->Add(m_TiltTypeWM[i], 0, wxEXPAND | (wxDOWN | wxRIGHT), 4); + m_sTiltType->Add(m_tTiltTypeNC, 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 4); + m_sTiltType->Add(m_TiltTypeNC[i], 0, wxEXPAND | (wxDOWN | wxLEFT), 4); + + wxGridBagSizer *m_sGridTilt = new wxGridBagSizer(0, 0); + m_sGridTilt->Add(m_TiltTextRoll, wxGBPosition(0, 0), wxGBSpan(1, 1), + (wxUP | wxRIGHT), 4); + m_sGridTilt->Add(m_TiltComboRangeRoll[i], wxGBPosition(0, 1), wxGBSpan(1, 1), + (wxLEFT | wxRIGHT), 4); + m_sGridTilt->Add(m_TiltRollSwing[i], wxGBPosition(0, 2), wxGBSpan(1, 1), + (wxUP | wxLEFT | wxRIGHT), 4); + m_sGridTilt->Add(m_TiltRollInvert[i], wxGBPosition(0, 3), wxGBSpan(1, 1), + (wxUP | wxLEFT), 4); + m_sGridTilt->Add(m_TiltTextPitch, wxGBPosition(1, 0), wxGBSpan(1, 1), + (wxUP | wxRIGHT), 4); + m_sGridTilt->Add(m_TiltComboRangePitch[i], wxGBPosition(1, 1), wxGBSpan(1, 1), + (wxLEFT | wxRIGHT), 4); + m_sGridTilt->Add(m_TiltPitchSwing[i], wxGBPosition(1, 2), wxGBSpan(1, 1), + (wxUP | wxLEFT | wxRIGHT), 4); + m_sGridTilt->Add(m_TiltPitchInvert[i], wxGBPosition(1, 3), wxGBSpan(1, 1), + (wxUP | wxLEFT), 4); + + wxStaticBoxSizer *m_gTilt = new wxStaticBoxSizer (wxVERTICAL, m_Controller, wxT("Tilt and Swing")); + m_gTilt->AddStretchSpacer(); + m_gTilt->Add(m_sTiltType, 0, wxEXPAND | (wxLEFT | wxDOWN), 5); + m_gTilt->Add(m_sGridTilt, 0, wxEXPAND | (wxLEFT), 5); + m_gTilt->AddStretchSpacer(); // Row 1 Sizers: Connected pads, tilt - m_sHorizController[i] = new wxBoxSizer(wxHORIZONTAL); - m_sHorizController[i]->Add(m_gJoyPad[i], 0, wxEXPAND | (wxLEFT), 5); - m_sHorizController[i]->Add(m_gTilt[i], 0, wxEXPAND | (wxLEFT), 5); - + wxBoxSizer *m_sHorizController = new wxBoxSizer(wxHORIZONTAL); + m_sHorizController->Add(m_gJoyPad, 0, wxEXPAND | (wxLEFT), 5); + m_sHorizController->Add(m_gTilt, 0, wxEXPAND | (wxLEFT), 5); // Stick Status Panels - m_tStatusLeftIn[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Not connected")); - m_tStatusLeftOut[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Not connected")); - m_tStatusRightIn[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Not connected")); - m_tStatusRightOut[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Not connected")); - - m_pLeftInStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_bmpSquareLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); - m_bmpDeadZoneLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus[i], wxID_ANY, CreateBitmapDeadZone(0), wxDefaultPosition, wxDefaultSize); - m_bmpDotLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); - - m_pLeftOutStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_bmpSquareLeftOut[i] = new wxStaticBitmap(m_pLeftOutStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); - m_bmpDotLeftOut[i] = new wxStaticBitmap(m_pLeftOutStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); - - m_pRightInStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_bmpSquareRightIn[i] = new wxStaticBitmap(m_pRightInStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); - m_bmpDeadZoneRightIn[i] = new wxStaticBitmap(m_pRightInStatus[i], wxID_ANY, CreateBitmapDeadZone(0), wxDefaultPosition, wxDefaultSize); - m_bmpDotRightIn[i] = new wxStaticBitmap(m_pRightInStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); - - m_pRightOutStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_bmpSquareRightOut[i] = new wxStaticBitmap(m_pRightOutStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); - m_bmpDotRightOut[i] = new wxStaticBitmap(m_pRightOutStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); + m_tStatusLeftIn[i] = new wxStaticText(m_Controller, wxID_ANY, wxT("Not connected")); + m_tStatusLeftOut[i] = new wxStaticText(m_Controller, wxID_ANY, wxT("Not connected")); + m_tStatusRightIn[i] = new wxStaticText(m_Controller, wxID_ANY, wxT("Not connected")); + m_tStatusRightOut[i] = new wxStaticText(m_Controller, wxID_ANY, wxT("Not connected")); + + wxPanel *m_pLeftInStatus = new wxPanel(m_Controller, wxID_ANY, + wxDefaultPosition, wxDefaultSize); + m_bmpSquareLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus, wxID_ANY, + CreateBitmap(), wxDefaultPosition, wxDefaultSize); + m_bmpDeadZoneLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus, wxID_ANY, + CreateBitmapDeadZone(0), wxDefaultPosition, wxDefaultSize); + m_bmpDotLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus, wxID_ANY, + CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); + + wxPanel *m_pLeftOutStatus = new wxPanel(m_Controller, wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_bmpSquareLeftOut[i] = new wxStaticBitmap(m_pLeftOutStatus, wxID_ANY, + CreateBitmap(), wxDefaultPosition, wxDefaultSize); + m_bmpDotLeftOut[i] = new wxStaticBitmap(m_pLeftOutStatus, wxID_ANY, + CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); + + wxPanel *m_pRightInStatus = new wxPanel(m_Controller, wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_bmpSquareRightIn[i] = new wxStaticBitmap(m_pRightInStatus, wxID_ANY, + CreateBitmap(), wxDefaultPosition, wxDefaultSize); + m_bmpDeadZoneRightIn[i] = new wxStaticBitmap(m_pRightInStatus, wxID_ANY, + CreateBitmapDeadZone(0), wxDefaultPosition, wxDefaultSize); + m_bmpDotRightIn[i] = new wxStaticBitmap(m_pRightInStatus, wxID_ANY, + CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); + + wxPanel *m_pRightOutStatus = new wxPanel(m_Controller, wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_bmpSquareRightOut[i] = new wxStaticBitmap(m_pRightOutStatus, wxID_ANY, + CreateBitmap(), wxDefaultPosition, wxDefaultSize); + m_bmpDotRightOut[i] = new wxStaticBitmap(m_pRightOutStatus, wxID_ANY, + CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); // Sizers - m_sGridStickLeft[i] = new wxGridBagSizer(0, 0); - m_sGridStickLeft[i]->Add(m_pLeftInStatus[i], wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0); - m_sGridStickLeft[i]->Add(m_pLeftOutStatus[i], wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 10); - m_sGridStickLeft[i]->Add(m_tStatusLeftIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0); - m_sGridStickLeft[i]->Add(m_tStatusLeftOut[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxLEFT, 10); - - m_sGridStickRight[i] = new wxGridBagSizer(0, 0); - m_sGridStickRight[i]->Add(m_pRightInStatus[i], wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0); - m_sGridStickRight[i]->Add(m_pRightOutStatus[i], wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 10); - m_sGridStickRight[i]->Add(m_tStatusRightIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0); - m_sGridStickRight[i]->Add(m_tStatusRightOut[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxLEFT, 10); - - m_gStickLeft[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog 1 Status (In) (Out)")); - m_gStickLeft[i]->Add(m_sGridStickLeft[i], 0, (wxLEFT | wxRIGHT), 5); - - m_gStickRight[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog 2 Status (In) (Out)")); - m_gStickRight[i]->Add(m_sGridStickRight[i], 0, (wxLEFT | wxRIGHT), 5); + wxGridBagSizer *m_sGridStickLeft = new wxGridBagSizer(0, 0); + m_sGridStickLeft->Add(m_pLeftInStatus, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0); + m_sGridStickLeft->Add(m_pLeftOutStatus, wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 10); + m_sGridStickLeft->Add(m_tStatusLeftIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0); + m_sGridStickLeft->Add(m_tStatusLeftOut[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxLEFT, 10); + + wxGridBagSizer *m_sGridStickRight = new wxGridBagSizer(0, 0); + m_sGridStickRight->Add(m_pRightInStatus, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0); + m_sGridStickRight->Add(m_pRightOutStatus, wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 10); + m_sGridStickRight->Add(m_tStatusRightIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0); + m_sGridStickRight->Add(m_tStatusRightOut[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxLEFT, 10); + + wxStaticBoxSizer *m_gStickLeft = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller, + wxT("Analog 1 Status (In) (Out)")); + m_gStickLeft->Add(m_sGridStickLeft, 0, (wxLEFT | wxRIGHT), 5); + + wxStaticBoxSizer *m_gStickRight = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller, + wxT("Analog 2 Status (In) (Out)")); + m_gStickRight->Add(m_sGridStickRight, 0, (wxLEFT | wxRIGHT), 5); // Trigger Status Panels - m_TriggerL[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Left: ")); - m_TriggerR[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Right: ")); - m_TriggerStatusL[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("000"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); - m_TriggerStatusR[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("000"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); - m_tTriggerSource[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Trigger Source")); - m_TriggerType[i] = new wxChoice(m_Controller[i], IDC_TRIGGER_TYPE, wxDefaultPosition, wxSize(70, -1), StrTriggerType, 0, wxDefaultValidator, StrTriggerType[0]); + wxStaticText *m_TriggerL = new wxStaticText(m_Controller, wxID_ANY, wxT("Left:")); + wxStaticText *m_TriggerR = new wxStaticText(m_Controller, wxID_ANY, wxT("Right:")); + m_TriggerStatusL[i] = new wxStaticText(m_Controller, wxID_ANY, wxT("000"), + wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); + m_TriggerStatusR[i] = new wxStaticText(m_Controller, wxID_ANY, wxT("000"), + wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); + wxStaticText *m_tTriggerSource = new wxStaticText(m_Controller, wxID_ANY, wxT("Trigger Source")); + m_TriggerType[i] = new wxChoice(m_Controller, IDC_TRIGGER_TYPE, + wxDefaultPosition, wxSize(70, -1), StrTriggerType, 0, + wxDefaultValidator, StrTriggerType[0]); // Sizers - m_sGridTrigger[i] = new wxGridBagSizer(0, 0); - m_sGridTrigger[i]->Add(m_TriggerL[i], wxGBPosition(0, 0), wxGBSpan(1, 1), (wxTOP), 4); - m_sGridTrigger[i]->Add(m_TriggerStatusL[i], wxGBPosition(0, 1), wxGBSpan(1, 1), (wxLEFT | wxTOP), 4); - m_sGridTrigger[i]->Add(m_TriggerR[i], wxGBPosition(1, 0), wxGBSpan(1, 1), (wxTOP), 4); - m_sGridTrigger[i]->Add(m_TriggerStatusR[i], wxGBPosition(1, 1), wxGBSpan(1, 1), (wxLEFT | wxTOP), 4); - - m_gTriggers[i] = new wxStaticBoxSizer (wxVERTICAL, m_Controller[i], wxT("Triggers Status")); - m_gTriggers[i]->AddStretchSpacer(); - m_gTriggers[i]->Add(m_sGridTrigger[i], 0, wxEXPAND | (wxLEFT | wxRIGHT), 5); - m_gTriggers[i]->Add(m_tTriggerSource[i], 0, wxEXPAND | (wxUP | wxLEFT | wxRIGHT), 5); - m_gTriggers[i]->Add(m_TriggerType[i], 0, wxEXPAND | (wxUP | wxLEFT | wxRIGHT), 5); - m_gTriggers[i]->AddStretchSpacer(); + wxGridBagSizer *m_sGridTrigger = new wxGridBagSizer(0, 0); + m_sGridTrigger->Add(m_TriggerL, wxGBPosition(0, 0), wxGBSpan(1, 1), (wxTOP), 4); + m_sGridTrigger->Add(m_TriggerStatusL[i], wxGBPosition(0, 1), wxGBSpan(1, 1), + (wxLEFT | wxTOP), 4); + m_sGridTrigger->Add(m_TriggerR, wxGBPosition(1, 0), wxGBSpan(1, 1), (wxTOP), 4); + m_sGridTrigger->Add(m_TriggerStatusR[i], wxGBPosition(1, 1), wxGBSpan(1, 1), + (wxLEFT | wxTOP), 4); + + wxStaticBoxSizer *m_gTriggers = + new wxStaticBoxSizer (wxVERTICAL, m_Controller, wxT("Triggers Status")); + m_gTriggers->AddStretchSpacer(); + m_gTriggers->Add(m_sGridTrigger, 0, wxEXPAND | (wxLEFT | wxRIGHT), 5); + m_gTriggers->Add(m_tTriggerSource, 0, wxEXPAND | (wxUP | wxLEFT | wxRIGHT), 5); + m_gTriggers->Add(m_TriggerType[i], 0, wxEXPAND | (wxUP | wxLEFT | wxRIGHT), 5); + m_gTriggers->AddStretchSpacer(); // Row 2 Sizers: Analog status - m_sHorizStatus[i] = new wxBoxSizer(wxHORIZONTAL); - m_sHorizStatus[i]->Add(m_gStickLeft[i], 0, wxEXPAND | (wxLEFT), 5); - m_sHorizStatus[i]->Add(m_gStickRight[i], 0, wxEXPAND | (wxLEFT), 5); - m_sHorizStatus[i]->Add(m_gTriggers[i], 0, wxEXPAND | (wxLEFT), 5); - + wxBoxSizer *m_sHorizStatus = new wxBoxSizer(wxHORIZONTAL); + m_sHorizStatus->Add(m_gStickLeft, 0, wxEXPAND | (wxLEFT), 5); + m_sHorizStatus->Add(m_gStickRight, 0, wxEXPAND | (wxLEFT), 5); + m_sHorizStatus->Add(m_gTriggers, 0, wxEXPAND | (wxLEFT), 5); // Analog Axes and Triggers Mapping - m_sAnalogLeft[i] = new wxBoxSizer(wxVERTICAL); - m_sAnalogMiddle[i] = new wxBoxSizer(wxVERTICAL); - m_sAnalogRight[i] = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *m_sAnalogLeft = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *m_sAnalogMiddle = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *m_sAnalogRight = new wxBoxSizer(wxVERTICAL); for (int x = 0; x < 6; x++) { - m_statictext_Analog[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, anText[x]); - m_Button_Analog[x][i] = new wxButton(m_Controller[i], x + IDB_ANALOG_LEFT_X, wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); + wxStaticText *m_statictext_Analog = + new wxStaticText(m_Controller, wxID_ANY, anText[x]); + m_Button_Analog[x][i] = new wxButton(m_Controller, x + IDB_ANALOG_LEFT_X, + wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); m_Button_Analog[x][i]->SetFont(m_SmallFont); - m_Sizer_Analog[x][i] = new wxBoxSizer(wxHORIZONTAL); - m_Sizer_Analog[x][i]->Add(m_statictext_Analog[x][i], 0, (wxUP), 4); - m_Sizer_Analog[x][i]->Add(m_Button_Analog[x][i], 0, (wxLEFT), 2); + wxBoxSizer *m_Sizer_Analog = new wxBoxSizer(wxHORIZONTAL); + m_Sizer_Analog->Add(m_statictext_Analog, 0, (wxUP), 4); + m_Sizer_Analog->Add(m_Button_Analog[x][i], 0, (wxLEFT), 2); if (x < 2) // Make some balance - m_sAnalogLeft[i]->Add(m_Sizer_Analog[x][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sAnalogLeft->Add(m_Sizer_Analog, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); else if (x < 4) - m_sAnalogMiddle[i]->Add(m_Sizer_Analog[x][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sAnalogMiddle->Add(m_Sizer_Analog, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); else - m_sAnalogRight[i]->Add(m_Sizer_Analog[x][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sAnalogRight->Add(m_Sizer_Analog, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); } - m_gAnalog[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog Axes and Triggers")); - m_gAnalog[i]->Add(m_sAnalogLeft[i], 0, wxALIGN_RIGHT | (wxALL), 0); - m_gAnalog[i]->Add(m_sAnalogMiddle[i], 0, wxALIGN_RIGHT | (wxLEFT), 5); - m_gAnalog[i]->Add(m_sAnalogRight[i], 0, wxALIGN_RIGHT | (wxLEFT), 5); - m_gAnalog[i]->AddSpacer(1); + wxStaticBoxSizer *m_gAnalog = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller, + wxT("Analog Axes and Triggers")); + m_gAnalog->Add(m_sAnalogLeft, 0, wxALIGN_RIGHT | (wxALL), 0); + m_gAnalog->Add(m_sAnalogMiddle, 0, wxALIGN_RIGHT | (wxLEFT), 5); + m_gAnalog->Add(m_sAnalogRight, 0, wxALIGN_RIGHT | (wxLEFT), 5); + m_gAnalog->AddSpacer(1); // Row 3 Sizes: Analog Mapping - m_sHorizAnalogMapping[i] = new wxBoxSizer(wxHORIZONTAL); - m_sHorizAnalogMapping[i]->Add(m_gAnalog[i], 0, (wxLEFT), 5); - + wxBoxSizer *m_sHorizAnalogMapping = new wxBoxSizer(wxHORIZONTAL); + m_sHorizAnalogMapping->Add(m_gAnalog, 0, (wxLEFT), 5); // Wiimote Mapping - m_sWmVertLeft[i] = new wxBoxSizer(wxVERTICAL); - m_sWmVertRight[i] = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *m_sWmVertLeft = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *m_sWmVertRight = new wxBoxSizer(wxVERTICAL); for (int x = 0; x <= IDB_WM_SHAKE - IDB_WM_A; x++) { - m_statictext_Wiimote[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, wmText[x]); - m_Button_Wiimote[x][i] = new wxButton(m_Controller[i], x + IDB_WM_A, wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); - m_Button_Wiimote[x][i]->SetFont(m_SmallFont); - m_Sizer_Wiimote[x][i] = new wxBoxSizer(wxHORIZONTAL); - m_Sizer_Wiimote[x][i]->Add(m_statictext_Wiimote[x][i], 0, (wxUP), 4); - m_Sizer_Wiimote[x][i]->Add(m_Button_Wiimote[x][i], 0, (wxLEFT), 2); - if (x < 7 || x == IDB_WM_SHAKE - IDB_WM_A) // Make some balance - m_sWmVertLeft[i]->Add(m_Sizer_Wiimote[x][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - else - m_sWmVertRight[i]->Add(m_Sizer_Wiimote[x][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + wxStaticText *m_statictext_Wiimote = new wxStaticText(m_Controller, wxID_ANY, wmText[x]); + m_Button_Wiimote[x][i] = new wxButton(m_Controller, x + IDB_WM_A, + wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); + m_Button_Wiimote[x][i]->SetFont(m_SmallFont); + wxBoxSizer *m_Sizer_Wiimote = new wxBoxSizer(wxHORIZONTAL); + m_Sizer_Wiimote->Add(m_statictext_Wiimote, 0, (wxUP), 4); + m_Sizer_Wiimote->Add(m_Button_Wiimote[x][i], 0, (wxLEFT), 2); + if (x < 7 || x == IDB_WM_SHAKE - IDB_WM_A) // Make some balance + m_sWmVertLeft->Add(m_Sizer_Wiimote, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + else + m_sWmVertRight->Add(m_Sizer_Wiimote, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); } - m_gWiimote[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Wiimote")); - m_gWiimote[i]->Add(m_sWmVertLeft[i], 0, (wxLEFT | wxRIGHT | wxDOWN), 1); - m_gWiimote[i]->Add(m_sWmVertRight[i], 0, (wxLEFT | wxRIGHT | wxDOWN), 1); + wxStaticBoxSizer *m_gWiimote = + new wxStaticBoxSizer (wxHORIZONTAL, m_Controller, wxT("Wiimote")); + m_gWiimote->Add(m_sWmVertLeft, 0, (wxLEFT | wxRIGHT | wxDOWN), 1); + m_gWiimote->Add(m_sWmVertRight, 0, (wxLEFT | wxRIGHT | wxDOWN), 1); + + // Row 4 Sizers: Wiimote and Extension Mapping + wxBoxSizer *m_sHorizControllerMapping = new wxBoxSizer(wxHORIZONTAL); + m_sHorizControllerMapping->Add(m_gWiimote, 0, (wxLEFT), 5); // Extension Mapping if(WiiMoteEmu::WiiMapping[i].iExtensionConnected == WiiMoteEmu::EXT_NUNCHUK) { // Stick controls - m_NunchuckTextStick[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Stick")); - m_NunchuckComboStick[i] = new wxChoice(m_Controller[i], IDC_NUNCHUCK_STICK, wxDefaultPosition, wxSize(70, -1), StrNunchuck, 0, wxDefaultValidator, StrNunchuck[0]); + wxStaticText *m_NunchuckTextStick = + new wxStaticText(m_Controller, wxID_ANY, wxT("Stick")); + m_NunchuckComboStick[i] = new wxChoice(m_Controller, IDC_NUNCHUCK_STICK, + wxDefaultPosition, wxSize(70, -1), StrNunchuck, 0, wxDefaultValidator, StrNunchuck[0]); + // Sizers + wxBoxSizer *m_sNunchuckStick = new wxBoxSizer(wxHORIZONTAL); + m_sNunchuckStick->Add(m_NunchuckTextStick, 0, (wxUP), 4); + m_sNunchuckStick->Add(m_NunchuckComboStick[i], 0, (wxLEFT), 2); + + wxBoxSizer *m_sNCVertLeft = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *m_sNCVertRight = new wxBoxSizer(wxVERTICAL); + m_sNCVertRight->Add(m_sNunchuckStick, 0, wxALIGN_RIGHT | (wxALL), 2); + m_sNCVertRight->AddSpacer(2); + for (int x = 0; x <= IDB_NC_SHAKE - IDB_NC_Z; x++) { - m_statictext_Nunchuk[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, ncText[x]); - m_Button_NunChuck[x][i] = new wxButton(m_Controller[i], x + IDB_NC_Z, wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); + wxStaticText *m_statictext_Nunchuk = + new wxStaticText(m_Controller, wxID_ANY, ncText[x]); + m_Button_NunChuck[x][i] = new wxButton(m_Controller, x + IDB_NC_Z, + wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); m_Button_NunChuck[x][i]->SetFont(m_SmallFont); - m_Sizer_NunChuck[x][i] = new wxBoxSizer(wxHORIZONTAL); - m_Sizer_NunChuck[x][i]->Add(m_statictext_Nunchuk[x][i], 0, (wxUP), 4); - m_Sizer_NunChuck[x][i]->Add(m_Button_NunChuck[x][i], 0, (wxLEFT), 2); - } - - // Sizers - m_sNunchuckStick[i] = new wxBoxSizer(wxHORIZONTAL); - m_sNunchuckStick[i]->Add(m_NunchuckTextStick[i], 0, (wxUP), 4); - m_sNunchuckStick[i]->Add(m_NunchuckComboStick[i], 0, (wxLEFT), 2); - - m_sNCVertLeft[i] = new wxBoxSizer(wxVERTICAL); - m_sNCVertRight[i] = new wxBoxSizer(wxVERTICAL); - m_sNCVertRight[i]->Add(m_sNunchuckStick[i], 0, wxALIGN_RIGHT | (wxALL), 2); - m_sNCVertRight[i]->AddSpacer(2); - - for (int x = IDB_NC_Z ; x <= IDB_NC_SHAKE; x++) - if (x < IDB_NC_ROLL_L) // Make some balance - m_sNCVertLeft[i]->Add(m_Sizer_NunChuck[x - IDB_NC_Z][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + wxBoxSizer *m_Sizer_NunChuck = new wxBoxSizer(wxHORIZONTAL); + m_Sizer_NunChuck->Add(m_statictext_Nunchuk, 0, (wxUP), 4); + m_Sizer_NunChuck->Add(m_Button_NunChuck[x][i], 0, (wxLEFT), 2); + + if (x < IDB_NC_ROLL_L - IDB_NC_Z) // Make some balance + m_sNCVertLeft->Add(m_Sizer_NunChuck, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); else - m_sNCVertRight[i]->Add(m_Sizer_NunChuck[x - IDB_NC_Z][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sNCVertRight->Add(m_Sizer_NunChuck, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + } - m_gNunchuck[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Nunchuck")); - m_gNunchuck[i]->Add(m_sNCVertLeft[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - m_gNunchuck[i]->Add(m_sNCVertRight[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + wxStaticBoxSizer *m_gNunchuck = + new wxStaticBoxSizer (wxHORIZONTAL, m_Controller, wxT("Nunchuck")); + m_gNunchuck->Add(m_sNCVertLeft, 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_gNunchuck->Add(m_sNCVertRight, 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sHorizControllerMapping->Add(m_gNunchuck, 0, (wxLEFT), 5); } else if(WiiMoteEmu::WiiMapping[i].iExtensionConnected == WiiMoteEmu::EXT_CLASSIC_CONTROLLER) { // Stick controls - m_CcTextLeftStick[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Left stick")); - m_CcComboLeftStick[i] = new wxChoice(m_Controller[i], IDC_CC_LEFT_STICK, wxDefaultPosition, wxSize(70, -1), StrNunchuck, 0, wxDefaultValidator, StrNunchuck[0]); - m_CcTextRightStick[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Right stick")); - m_CcComboRightStick[i] = new wxChoice(m_Controller[i], IDC_CC_RIGHT_STICK, wxDefaultPosition, wxSize(70, -1), StrNunchuck, 0, wxDefaultValidator, StrNunchuck[0]); - m_CcTextTriggers[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Triggers")); - m_CcComboTriggers[i] = new wxChoice(m_Controller[i], IDC_CC_TRIGGERS, wxDefaultPosition, wxSize(70, -1), StrCcTriggers, 0, wxDefaultValidator, StrCcTriggers[0]); + wxStaticText *m_CcTextLeftStick = + new wxStaticText(m_Controller, wxID_ANY, wxT("Left stick")); + m_CcComboLeftStick[i] = new wxChoice(m_Controller, IDC_CC_LEFT_STICK, + wxDefaultPosition, wxSize(70, -1), StrNunchuck, 0, wxDefaultValidator, StrNunchuck[0]); + wxStaticText *m_CcTextRightStick = + new wxStaticText(m_Controller, wxID_ANY, wxT("Right stick")); + m_CcComboRightStick[i] = new wxChoice(m_Controller, IDC_CC_RIGHT_STICK, + wxDefaultPosition, wxSize(70, -1), StrNunchuck, 0, wxDefaultValidator, StrNunchuck[0]); + wxStaticText *m_CcTextTriggers = + new wxStaticText(m_Controller, wxID_ANY, wxT("Triggers")); + m_CcComboTriggers[i] = new wxChoice(m_Controller, IDC_CC_TRIGGERS, + wxDefaultPosition, wxSize(70, -1), StrCcTriggers, 0, wxDefaultValidator, StrCcTriggers[0]); for (int x = 0; x <= IDB_CC_RD - IDB_CC_A; x++) { - m_statictext_Classic[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, classicText[x]); - m_Button_Classic[x][i] = new wxButton(m_Controller[i], x + IDB_CC_A, wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); + wxStaticText *m_statictext_Classic = + new wxStaticText(m_Controller, wxID_ANY, classicText[x]); + m_Button_Classic[x][i] = new wxButton(m_Controller, x + IDB_CC_A, + wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); m_Button_Classic[x][i]->SetFont(m_SmallFont); m_Sizer_Classic[x][i] = new wxBoxSizer(wxHORIZONTAL); - m_Sizer_Classic[x][i]->Add(m_statictext_Classic[x][i], 0, wxALIGN_RIGHT | (wxUP), 4); + m_Sizer_Classic[x][i]->Add(m_statictext_Classic, 0, wxALIGN_RIGHT | (wxUP), 4); m_Sizer_Classic[x][i]->Add(m_Button_Classic[x][i], 0, wxALIGN_RIGHT | (wxLEFT), 2); } // Sizers - m_sCcLeftStick[i] = new wxBoxSizer(wxHORIZONTAL); - m_sCcLeftStick[i]->Add(m_CcTextLeftStick[i], 0, (wxUP), 4); - m_sCcLeftStick[i]->Add(m_CcComboLeftStick[i], 0, (wxLEFT), 2); + wxBoxSizer *m_sCcLeftStick = new wxBoxSizer(wxHORIZONTAL); + m_sCcLeftStick->Add(m_CcTextLeftStick, 0, (wxUP), 4); + m_sCcLeftStick->Add(m_CcComboLeftStick[i], 0, (wxLEFT), 2); - m_sCcRightStick[i] = new wxBoxSizer(wxHORIZONTAL); - m_sCcRightStick[i]->Add(m_CcTextRightStick[i], 0, (wxUP), 4); - m_sCcRightStick[i]->Add(m_CcComboRightStick[i], 0, (wxLEFT), 2); - - m_sCcTriggers[i] = new wxBoxSizer(wxHORIZONTAL); - m_sCcTriggers[i]->Add(m_CcTextTriggers[i], 0, (wxUP), 4); - m_sCcTriggers[i]->Add(m_CcComboTriggers[i], 0, (wxLEFT), 2); - - m_sCcVertLeft[i] = new wxBoxSizer(wxVERTICAL); - m_sCcVertLeft[i]->Add(m_sCcLeftStick[i], 0, wxALIGN_RIGHT | (wxALL), 2); - m_sCcVertLeft[i]->AddSpacer(2); + wxBoxSizer *m_sCcRightStick = new wxBoxSizer(wxHORIZONTAL); + m_sCcRightStick->Add(m_CcTextRightStick, 0, (wxUP), 4); + m_sCcRightStick->Add(m_CcComboRightStick[i], 0, (wxLEFT), 2); + + wxBoxSizer *m_sCcTriggers = new wxBoxSizer(wxHORIZONTAL); + m_sCcTriggers->Add(m_CcTextTriggers, 0, (wxUP), 4); + m_sCcTriggers->Add(m_CcComboTriggers[i], 0, (wxLEFT), 2); + + wxBoxSizer *m_sCcVertLeft = new wxBoxSizer(wxVERTICAL); + m_sCcVertLeft->Add(m_sCcLeftStick, 0, wxALIGN_RIGHT | (wxALL), 2); + m_sCcVertLeft->AddSpacer(2); for (int x = IDB_CC_LL; x <= IDB_CC_LD; x++) - m_sCcVertLeft[i]->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sCcVertLeft->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); for (int x = IDB_CC_DL; x <= IDB_CC_DD; x++) - m_sCcVertLeft[i]->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sCcVertLeft->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - m_sCcVertMiddle[i] = new wxBoxSizer(wxVERTICAL); - m_sCcVertMiddle[i]->Add(m_sCcRightStick[i], 0, wxALIGN_RIGHT | (wxALL), 2); - m_sCcVertMiddle[i]->AddSpacer(2); + wxBoxSizer *m_sCcVertMiddle = new wxBoxSizer(wxVERTICAL); + m_sCcVertMiddle->Add(m_sCcRightStick, 0, wxALIGN_RIGHT | (wxALL), 2); + m_sCcVertMiddle->AddSpacer(2); for (int x = IDB_CC_RL; x <= IDB_CC_RD; x++) - m_sCcVertMiddle[i]->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sCcVertMiddle->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); for (int x = IDB_CC_A; x <= IDB_CC_Y; x++) - m_sCcVertMiddle[i]->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sCcVertMiddle->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - m_sCcVertRight[i] = new wxBoxSizer(wxVERTICAL); - m_sCcVertRight[i]->Add(m_sCcTriggers[i], 0, wxALIGN_RIGHT | (wxALL), 2); - m_sCcVertRight[i]->AddSpacer(2); + wxBoxSizer *m_sCcVertRight = new wxBoxSizer(wxVERTICAL); + m_sCcVertRight->Add(m_sCcTriggers, 0, wxALIGN_RIGHT | (wxALL), 2); + m_sCcVertRight->AddSpacer(2); for (int x = IDB_CC_TL; x <= IDB_CC_ZR; x++) - m_sCcVertRight[i]->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sCcVertRight->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); for (int x = IDB_CC_P; x <= IDB_CC_H; x++) - m_sCcVertRight[i]->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_sCcVertRight->Add(m_Sizer_Classic[x - IDB_CC_A][i], 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - m_gClassicController[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Classic Controller")); - m_gClassicController[i]->Add(m_sCcVertLeft[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - m_gClassicController[i]->Add(m_sCcVertMiddle[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - m_gClassicController[i]->Add(m_sCcVertRight[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + wxStaticBoxSizer *m_gClassicController = new wxStaticBoxSizer (wxHORIZONTAL, + m_Controller, wxT("Classic Controller")); + m_gClassicController->Add(m_sCcVertLeft, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_gClassicController->Add(m_sCcVertMiddle, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_gClassicController->Add(m_sCcVertRight, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + + m_sHorizControllerMapping->Add(m_gClassicController, 0, (wxLEFT), 5); } else if(WiiMoteEmu::WiiMapping[i].iExtensionConnected == WiiMoteEmu::EXT_GUITARHERO) { // Stick controls - m_tGH3Analog[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Stick")); - m_GH3ComboAnalog[i] = new wxChoice(m_Controller[i], IDC_GH3_ANALOG, wxDefaultPosition, wxSize(70, -1), StrAnalogArray, 0, wxDefaultValidator, StrAnalogArray[0]); + wxStaticText *m_tGH3Analog = + new wxStaticText(m_Controller, wxID_ANY, wxT("Stick")); + m_GH3ComboAnalog[i] = new wxChoice(m_Controller, IDC_GH3_ANALOG, + wxDefaultPosition, wxSize(70, -1), StrAnalogArray, 0, + wxDefaultValidator, StrAnalogArray[0]); + + // Sizers + wxBoxSizer *m_sGH3Analog = new wxBoxSizer(wxHORIZONTAL); + m_sGH3Analog->Add(m_tGH3Analog, 0, (wxUP), 4); + m_sGH3Analog->Add(m_GH3ComboAnalog[i], 0, (wxLEFT), 2); + + wxBoxSizer *m_sGH3VertLeft = new wxBoxSizer(wxVERTICAL); + m_sGH3VertLeft->Add(m_sGH3Analog, 0, wxALIGN_RIGHT | (wxALL), 2); + m_sGH3VertLeft->AddSpacer(2); + wxBoxSizer *m_sGH3VertRight = new wxBoxSizer(wxVERTICAL); for (int x = 0; x <= IDB_GH3_STRUM_DOWN - IDB_GH3_GREEN; x++) { - m_statictext_GH3[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, gh3Text[x]); - m_Button_GH3[x][i] = new wxButton(m_Controller[i], x, wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); + wxStaticText *m_statictext_GH3 = + new wxStaticText(m_Controller, wxID_ANY, gh3Text[x]); + m_Button_GH3[x][i] = new wxButton(m_Controller, x, + wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); m_Button_GH3[x][i]->SetFont(m_SmallFont); - m_Sizer_GH3[x][i] = new wxBoxSizer(wxHORIZONTAL); - m_Sizer_GH3[x][i]->Add(m_statictext_GH3[x][i], 0, (wxUP), 4); - m_Sizer_GH3[x][i]->Add(m_Button_GH3[x][i], 0, (wxLEFT), 2); + wxBoxSizer *m_Sizer_GH3 = new wxBoxSizer(wxHORIZONTAL); + m_Sizer_GH3->Add(m_statictext_GH3, 0, (wxUP), 4); + m_Sizer_GH3->Add(m_Button_GH3[x][i], 0, (wxLEFT), 2); + + if (x < IDB_GH3_ANALOG_LEFT - IDB_GH3_GREEN) + m_sGH3VertRight->Add(m_Sizer_GH3, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + else + m_sGH3VertLeft->Add(m_Sizer_GH3, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); } - // Sizers - m_sGH3Analog[i] = new wxBoxSizer(wxHORIZONTAL); - m_sGH3Analog[i]->Add(m_tGH3Analog[i], 0, (wxUP), 4); - m_sGH3Analog[i]->Add(m_GH3ComboAnalog[i], 0, (wxLEFT), 2); - - m_sGH3VertLeft[i] = new wxBoxSizer(wxVERTICAL); - m_sGH3VertLeft[i]->Add(m_sGH3Analog[i], 0, wxALIGN_RIGHT | (wxALL), 2); - m_sGH3VertLeft[i]->AddSpacer(2); - for (int x = IDB_GH3_ANALOG_LEFT; x <= IDB_GH3_STRUM_DOWN; x++) - m_sGH3VertLeft[i]->Add(m_Sizer_GH3[x - IDB_GH3_GREEN][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - - m_sGH3VertRight[i] = new wxBoxSizer(wxVERTICAL); - for (int x = IDB_GH3_GREEN; x <= IDB_GH3_WHAMMY; x++) - m_sGH3VertRight[i]->Add(m_Sizer_GH3[x - IDB_GH3_GREEN][i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - - m_gGuitarHero3Controller[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Guitar Hero 3 Controller")); - m_gGuitarHero3Controller[i]->Add(m_sGH3VertLeft[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - m_gGuitarHero3Controller[i]->Add(m_sGH3VertRight[i], 0, wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - } + wxStaticBoxSizer *m_gGuitarHero3Controller = new wxStaticBoxSizer (wxHORIZONTAL, + m_Controller, wxT("Guitar Hero 3 Controller")); + m_gGuitarHero3Controller->Add(m_sGH3VertLeft, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); + m_gGuitarHero3Controller->Add(m_sGH3VertRight, 0, + wxALIGN_RIGHT | (wxLEFT | wxRIGHT | wxDOWN), 1); - // Row 4 Sizers: Wiimote and Extension Mapping - m_sHorizControllerMapping[i] = new wxBoxSizer(wxHORIZONTAL); - m_sHorizControllerMapping[i]->Add(m_gWiimote[i], 0, (wxLEFT), 5); - switch(WiiMoteEmu::WiiMapping[i].iExtensionConnected) - { - case WiiMoteEmu::EXT_NUNCHUK: - m_sHorizControllerMapping[i]->Add(m_gNunchuck[i], 0, (wxLEFT), 5); - break; - case WiiMoteEmu::EXT_CLASSIC_CONTROLLER: - m_sHorizControllerMapping[i]->Add(m_gClassicController[i], 0, (wxLEFT), 5); - break; - case WiiMoteEmu::EXT_GUITARHERO: - m_sHorizControllerMapping[i]->Add(m_gGuitarHero3Controller[i], 0, (wxLEFT), 5); - break; - default: - break; + m_sHorizControllerMapping->Add(m_gGuitarHero3Controller, 0, (wxLEFT), 5); } // Set up sizers and layout // The sizer m_sMain will be expanded inside m_Controller - m_sMain[i] = new wxBoxSizer(wxVERTICAL); - m_sMain[i]->Add(m_sHorizController[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); - m_sMain[i]->Add(m_sHorizStatus[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); - m_sMain[i]->Add(m_sHorizAnalogMapping[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); - m_sMain[i]->Add(m_sHorizControllerMapping[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); + wxBoxSizer *m_sMain = new wxBoxSizer(wxVERTICAL); + m_sMain->Add(m_sHorizController, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); + m_sMain->Add(m_sHorizStatus, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); + m_sMain->Add(m_sHorizAnalogMapping, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); + m_sMain->Add(m_sHorizControllerMapping, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); // Set the main sizer - m_Controller[i]->SetSizer(m_sMain[i]); + m_Controller->SetSizer(m_sMain); } -// m_Apply = new wxButton(this, wxID_APPLY, wxT("Apply")); - m_Close = new wxButton(this, wxID_CLOSE, wxT("Close")); +// wxButton *m_Apply = new wxButton(this, wxID_APPLY, wxT("Apply")); + wxButton *m_Close = new wxButton(this, wxID_CLOSE, wxT("Close")); wxBoxSizer* sButtons = new wxBoxSizer(wxHORIZONTAL); sButtons->AddStretchSpacer(); // sButtons->Add(m_Apply, 0, (wxALL), 0); - sButtons->Add(m_Close, 0, (wxLEFT), 5); + sButtons->Add(m_Close, 0, (wxLEFT), 5); - m_MainSizer = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *m_MainSizer = new wxBoxSizer(wxVERTICAL); m_MainSizer->Add(m_Notebook, 1, wxEXPAND | wxALL, 5); m_MainSizer->Add(sButtons, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); @@ -1057,9 +1169,11 @@ m_TriggerType[m_Page]->SetSelection(WiiMoteEmu::WiiMapping[m_Page].TriggerType); m_TiltTypeWM[m_Page]->SetSelection(WiiMoteEmu::WiiMapping[m_Page].Tilt.InputWM); m_TiltTypeNC[m_Page]->SetSelection(WiiMoteEmu::WiiMapping[m_Page].Tilt.InputNC); - m_TiltComboRangeRoll[m_Page]->SetSelection(WiiMoteEmu::WiiMapping[m_Page].Tilt.RollDegree / 5 - 1); // 5 to 180, step 5 + m_TiltComboRangeRoll[m_Page]-> + SetSelection(WiiMoteEmu::WiiMapping[m_Page].Tilt.RollDegree / 5 - 1); // 5 to 180, step 5 m_TiltComboRangeRoll[m_Page]->Enable(!WiiMoteEmu::WiiMapping[m_Page].Tilt.RollSwing); - m_TiltComboRangePitch[m_Page]->SetSelection(WiiMoteEmu::WiiMapping[m_Page].Tilt.PitchDegree / 5 - 1); // 5 to 180, step 5 + m_TiltComboRangePitch[m_Page]-> + SetSelection(WiiMoteEmu::WiiMapping[m_Page].Tilt.PitchDegree / 5 - 1); // 5 to 180, step 5 m_TiltComboRangePitch[m_Page]->Enable(!WiiMoteEmu::WiiMapping[m_Page].Tilt.PitchSwing); m_TiltRollSwing[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].Tilt.RollSwing); m_TiltPitchSwing[m_Page]->SetValue(WiiMoteEmu::WiiMapping[m_Page].Tilt.PitchSwing); @@ -1198,4 +1312,3 @@ DoChangeDeadZone(); } - diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h 2010-08-18 03:25:24.000000000 +0100 @@ -151,12 +151,6 @@ wxNotebook *m_Notebook; - wxPanel *m_Controller[MAX_WIIMOTES], - *m_pLeftInStatus[MAX_WIIMOTES], - *m_pLeftOutStatus[MAX_WIIMOTES], - *m_pRightInStatus[MAX_WIIMOTES], - *m_pRightOutStatus[MAX_WIIMOTES]; - wxStaticBitmap *m_bmpSquareLeftIn[MAX_WIIMOTES], *m_bmpSquareLeftOut[MAX_WIIMOTES], *m_bmpSquareRightIn[MAX_WIIMOTES], @@ -169,7 +163,7 @@ *m_TiltRollInvert[MAX_WIIMOTES], *m_TiltPitchInvert[MAX_WIIMOTES]; - wxButton *m_Close, *m_Apply, *ClickedButton, + wxButton *ClickedButton, *m_Button_Analog[IDB_TRIGGER_R - IDB_ANALOG_LEFT_X + 1][MAX_WIIMOTES], *m_Button_Wiimote[IDB_WM_SHAKE - IDB_WM_A + 1][MAX_WIIMOTES], *m_Button_NunChuck[IDB_NC_SHAKE - IDB_NC_Z + 1][MAX_WIIMOTES], @@ -192,79 +186,12 @@ *m_CcComboTriggers[MAX_WIIMOTES], *m_GH3ComboAnalog[MAX_WIIMOTES]; - wxGridBagSizer *m_sGridTilt[MAX_WIIMOTES], - *m_sGridStickLeft[MAX_WIIMOTES], - *m_sGridStickRight[MAX_WIIMOTES], - *m_sGridTrigger[MAX_WIIMOTES]; - - wxBoxSizer *m_MainSizer, - *m_sMain[MAX_WIIMOTES], - *m_sDeadZoneHoriz[MAX_WIIMOTES], - *m_sDeadZone[MAX_WIIMOTES], - *m_sDiagonal[MAX_WIIMOTES], - *m_sCircle2Square[MAX_WIIMOTES], - *m_sC2SDeadZone[MAX_WIIMOTES], - *m_sJoyname[MAX_WIIMOTES], - *m_sRumble[MAX_WIIMOTES], - *m_sTiltType[MAX_WIIMOTES], - *m_sHorizController[MAX_WIIMOTES], - *m_sHorizStatus[MAX_WIIMOTES], - *m_Sizer_Analog[IDB_TRIGGER_R - IDB_ANALOG_LEFT_X + 1][MAX_WIIMOTES], - *m_sAnalogLeft[MAX_WIIMOTES], - *m_sAnalogMiddle[MAX_WIIMOTES], - *m_sAnalogRight[MAX_WIIMOTES], - *m_sHorizAnalogMapping[MAX_WIIMOTES], - *m_Sizer_Wiimote[IDB_WM_SHAKE - IDB_WM_A + 1][MAX_WIIMOTES], - *m_sWmVertLeft[MAX_WIIMOTES], - *m_sWmVertRight[MAX_WIIMOTES], - *m_Sizer_NunChuck[IDB_NC_SHAKE - IDB_NC_Z + 1][MAX_WIIMOTES], - *m_sNunchuckStick[MAX_WIIMOTES], - *m_sNCVertLeft[MAX_WIIMOTES], - *m_sNCVertRight[MAX_WIIMOTES], - *m_Sizer_Classic[IDB_CC_RD - IDB_CC_A + 1][MAX_WIIMOTES], - *m_sCcLeftStick[MAX_WIIMOTES], - *m_sCcRightStick[MAX_WIIMOTES], - *m_sCcTriggers[MAX_WIIMOTES], - *m_sCcVertLeft[MAX_WIIMOTES], - *m_sCcVertMiddle[MAX_WIIMOTES], - *m_sCcVertRight[MAX_WIIMOTES], - *m_Sizer_GH3[IDB_GH3_STRUM_DOWN - IDB_GH3_GREEN + 1][MAX_WIIMOTES], - *m_sGH3Analog[MAX_WIIMOTES], - *m_sGH3VertLeft[MAX_WIIMOTES], - *m_sGH3VertRight[MAX_WIIMOTES], - *m_sHorizControllerMapping[MAX_WIIMOTES]; - - wxStaticBoxSizer *m_gJoyPad[MAX_WIIMOTES], - *m_gTilt[MAX_WIIMOTES], - *m_gStickLeft[MAX_WIIMOTES], - *m_gStickRight[MAX_WIIMOTES], - *m_gTriggers[MAX_WIIMOTES], - *m_gAnalog[MAX_WIIMOTES], - *m_gWiimote[MAX_WIIMOTES], - *m_gNunchuck[MAX_WIIMOTES], - *m_gClassicController[MAX_WIIMOTES], - *m_gGuitarHero3Controller[MAX_WIIMOTES]; - - wxStaticText *m_ComboDeadZoneLabel[MAX_WIIMOTES], - *m_DiagonalLabel[MAX_WIIMOTES], - *m_RumbleStrengthLabel[MAX_WIIMOTES], - *m_tTiltTypeWM[MAX_WIIMOTES], *m_tTiltTypeNC[MAX_WIIMOTES], - *m_TiltTextRoll[MAX_WIIMOTES], *m_TiltTextPitch[MAX_WIIMOTES], + wxBoxSizer *m_Sizer_Classic[IDB_CC_RD - IDB_CC_A + 1][MAX_WIIMOTES]; + + wxStaticText *m_tStatusLeftIn[MAX_WIIMOTES], *m_tStatusLeftOut[MAX_WIIMOTES], *m_tStatusRightIn[MAX_WIIMOTES], *m_tStatusRightOut[MAX_WIIMOTES], - *m_TriggerL[MAX_WIIMOTES], *m_TriggerR[MAX_WIIMOTES], - *m_TriggerStatusL[MAX_WIIMOTES], *m_TriggerStatusR[MAX_WIIMOTES], - *m_tTriggerSource[MAX_WIIMOTES], - *m_statictext_Analog[IDB_TRIGGER_R - IDB_ANALOG_LEFT_X + 1][MAX_WIIMOTES], - *m_statictext_Wiimote[IDB_WM_SHAKE - IDB_WM_A + 1][MAX_WIIMOTES], - *m_statictext_Nunchuk[IDB_NC_SHAKE - IDB_NC_Z + 1][MAX_WIIMOTES], - *m_statictext_Classic[IDB_CC_RD - IDB_CC_A + 1][MAX_WIIMOTES], - *m_statictext_GH3[IDB_GH3_STRUM_DOWN - IDB_GH3_GREEN + 1][MAX_WIIMOTES], - *m_NunchuckTextStick[5], - *m_CcTextLeftStick[MAX_WIIMOTES], - *m_CcTextRightStick[MAX_WIIMOTES], - *m_CcTextTriggers[MAX_WIIMOTES], - *m_tGH3Analog[MAX_WIIMOTES]; + *m_TriggerStatusL[MAX_WIIMOTES], *m_TriggerStatusR[MAX_WIIMOTES]; wxBitmap CreateBitmap(); wxBitmap CreateBitmapDot(); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -213,11 +213,11 @@ // Get the cursor position for the entire screen GetCursorPos(&point); // Get the cursor position relative to the upper left corner of the rendering window - ScreenToClient(g_WiimoteInitialize.hWnd, &point); + ScreenToClient((HWND)g_WiimoteInitialize.hWnd, &point); // Get the size of the rendering window. (In my case Rect.top and Rect.left was zero.) RECT Rect; - GetClientRect(g_WiimoteInitialize.hWnd, &Rect); + GetClientRect((HWND)g_WiimoteInitialize.hWnd, &Rect); // Width and height is the size of the rendering window float WinWidth = (float)(Rect.right - Rect.left); float WinHeight = (float)(Rect.bottom - Rect.top); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/main.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/main.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/main.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/main.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -115,21 +115,6 @@ } #endif -#if defined(HAVE_WX) && HAVE_WX -wxWindow* GetParentedWxWindow(HWND Parent) -{ -#ifdef _WIN32 - wxSetInstance((HINSTANCE)g_hInstance); -#endif - wxWindow *win = new wxWindow(); -#ifdef _WIN32 - win->SetHWND((WXHWND)Parent); - win->AdoptAttributesFromHWND(); -#endif - return win; -} -#endif - // Exports void GetDllInfo(PLUGIN_INFO* _PluginInfo) { @@ -157,7 +142,7 @@ return NULL; } -void DllConfig(HWND _hParent) +void DllConfig(void *_hParent) { #ifdef _WIN32 if (WiiMoteReal::g_AutoPairUpInvisibleWindow == NULL) @@ -177,24 +162,9 @@ #if defined(HAVE_WX) && HAVE_WX - wxWindow *frame = GetParentedWxWindow(_hParent); - m_BasicConfigFrame = new WiimoteBasicConfigDialog(frame); -#ifdef _WIN32 - frame->Disable(); - m_BasicConfigFrame->ShowModal(); - frame->Enable(); -#else + m_BasicConfigFrame = new WiimoteBasicConfigDialog((wxWindow *)_hParent); m_BasicConfigFrame->ShowModal(); -#endif - -#ifdef _WIN32 - frame->SetFocus(); - frame->SetHWND(NULL); -#endif - m_BasicConfigFrame->Destroy(); - m_BasicConfigFrame = NULL; - frame->Destroy(); #endif } @@ -347,7 +317,7 @@ WiiMoteEmu::g_ReportingAuto[_number] = false; WARN_LOG(WIIMOTE, "Wiimote: #%i Disconnected", _number); #ifdef _WIN32 - PostMessage(g_WiimoteInitialize.hWnd, WM_USER, WIIMOTE_DISCONNECT, _number); + PostMessage((HWND)g_WiimoteInitialize.hWnd, WM_USER, WIIMOTE_DISCONNECT, _number); #endif return; } diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp 2010-08-18 03:25:24.000000000 +0100 @@ -794,7 +794,7 @@ void ToggleEmulatorState(bool stop) { - PostMessage(GetParent(g_WiimoteInitialize.hWnd), WM_USER, WM_USER_PAUSE, 0); + PostMessage(GetParent((HWND)g_WiimoteInitialize.hWnd), WM_USER, WM_USER_PAUSE, 0); if (stop) { while (g_EmulatorState != PLUGIN_EMUSTATE_PLAY) Sleep(50); } @@ -832,7 +832,7 @@ Allocate(); ToggleEmulatorState(false); if (addwiimote) - PostMessage(GetParent(g_WiimoteInitialize.hWnd), WM_USER, WM_USER_KEYDOWN, (3 + connectslot)); + PostMessage(GetParent((HWND)g_WiimoteInitialize.hWnd), WM_USER, WM_USER_KEYDOWN, (3 + connectslot)); } return 0; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp 2010-08-18 03:25:23.000000000 +0100 @@ -13,6 +13,7 @@ m_input_src_choice->Append(wxT("None")); m_input_src_choice->Append(wxT("Emulated Wiimote")); m_input_src_choice->Append(wxT("Real Wiimote")); + m_input_src_choice->Append(wxT("Hybrid Wiimote")); m_input_src_choice->Select(g_wiimote_sources[m_index]); _connect_macro_(m_input_src_choice, WiimoteConfigPage::SelectSource, wxEVT_COMMAND_CHOICE_SELECTED, this); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp 2010-08-18 03:25:23.000000000 +0100 @@ -38,23 +38,21 @@ #include "pluginspecs_wiimote.h" #include "WiimoteEmu.h" +#include "WiimoteHid.h" +#include "../WiimoteReal/WiimoteReal.h" + #include "Attachment/Attachment.h" /* Bit shift conversions */ -u32 convert24bit(const u8* src) +u32 swap24(const u8* src) { return (src[0] << 16) | (src[1] << 8) | src[2]; } -u16 convert16bit(const u8* src) -{ - return (src[0] << 8) | src[1]; -} - namespace WiimoteEmu { -void Wiimote::ReportMode(const u16 _channelID, wm_report_mode* dr) +void Wiimote::ReportMode(const wm_report_mode* const dr) { //INFO_LOG(WIIMOTE, "Set data report mode"); //DEBUG_LOG(WIIMOTE, " Rumble: %x", dr->rumble); @@ -73,7 +71,7 @@ if (false == m_reporting_auto) PanicAlert("Wiimote: Reporting is set to OFF! Everything should be fine, but games never do this."); - if (dr->mode >= WM_REPORT_INTERLEAVE1) + if (dr->mode > 0x37) PanicAlert("Wiimote: Unsupported Reporting mode."); else if (dr->mode < WM_REPORT_CORE) PanicAlert("Wiimote: Reporting mode < 0x30."); @@ -92,9 +90,9 @@ The IR enable/disable and speaker enable/disable and mute/unmute values are bit2: 0 = Disable (0x02), 1 = Enable (0x06) */ -void Wiimote::HidOutputReport(const u16 _channelID, wm_report* sr) +void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack) { - INFO_LOG(WIIMOTE, "HidOutputReport (page: %i, cid: 0x%02x, wm: 0x%02x)", m_index, _channelID, sr->wm); + INFO_LOG(WIIMOTE, "HidOutputReport (page: %i, cid: 0x%02x, wm: 0x%02x)", m_index, m_reporting_channel, sr->wm); // wiibrew: // In every single Output Report, bit 0 (0x01) of the first byte controls the Rumble feature. @@ -113,7 +111,7 @@ break; case WM_REPORT_MODE : // 0x12 - ReportMode(_channelID, (wm_report_mode*)sr->data); + ReportMode((wm_report_mode*)sr->data); break; case WM_IR_PIXEL_CLOCK : // 0x13 @@ -128,16 +126,16 @@ break; case WM_REQUEST_STATUS : // 0x15 - RequestStatus(_channelID, (wm_request_status*)sr->data); + RequestStatus((wm_request_status*)sr->data); return; // sends its own ack break; case WM_WRITE_DATA : // 0x16 - WriteData(_channelID, (wm_write_data*)sr->data); + WriteData((wm_write_data*)sr->data); break; case WM_READ_DATA : // 0x17 - ReadData(_channelID, (wm_read_data*)sr->data); + ReadData((wm_read_data*)sr->data); return; // sends its own ack break; @@ -175,7 +173,8 @@ } // send ack - SendAck(_channelID, sr->wm); + if (send_ack) + SendAck(sr->wm); } /* This will generate the 0x22 acknowledgement for most Input reports. @@ -183,7 +182,7 @@ The first two bytes are the core buttons data, 00 00 means nothing is pressed. The last byte is the success code 00. */ -void Wiimote::SendAck(const u16 _channelID, u8 _reportID) +void Wiimote::SendAck(u8 _reportID) { u8 data[6]; @@ -196,23 +195,16 @@ ack->reportID = _reportID; ack->errorID = 0; - g_WiimoteInitialize.pWiimoteInterruptChannel( m_index, _channelID, data, sizeof(data)); + g_WiimoteInitialize.pWiimoteInterruptChannel( m_index, m_reporting_channel, data, sizeof(data)); } -// old comment -/* Here we produce a 0x20 status report to send to the Wii. We currently ignore - the status request rs and all its eventual instructions it may include (for - example turn off rumble or something else) and just send the status - report. */ -void Wiimote::RequestStatus(const u16 _channelID, wm_request_status* rs) +void Wiimote::HandleExtensionSwap() { - //if (rs) - // handle switch extension - if ( m_extension->active_extension != m_extension->switch_extension ) + if (m_extension->active_extension != m_extension->switch_extension) { // if an extension is currently connected and we want to switch to a different extension - if ( (m_extension->active_extension > 0) && m_extension->switch_extension ) + if ((m_extension->active_extension > 0) && m_extension->switch_extension) // detach extension first, wait til next Update() or RequestStatus() call to change to the new extension m_extension->active_extension = 0; else @@ -223,8 +215,18 @@ m_status.extension = m_extension->active_extension ? 1 : 0; // set register, I hate this line - m_register[ 0xa40000 ] = ((WiimoteEmu::Attachment*)m_extension->attachments[ m_extension->active_extension ])->reg; + m_register[0xa40000] = ((WiimoteEmu::Attachment*)m_extension->attachments[m_extension->active_extension])->reg; } +} + +// old comment +/* Here we produce a 0x20 status report to send to the Wii. We currently ignore + the status request rs and all its eventual instructions it may include (for + example turn off rumble or something else) and just send the status + report. */ +void Wiimote::RequestStatus(const wm_request_status* const rs) +{ + HandleExtensionSwap(); // set up report u8 data[8]; @@ -234,14 +236,31 @@ // status values *(wm_status_report*)(data + 2) = m_status; + // hybrid wiimote stuff + if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index] && (m_extension->switch_extension <= 0)) + { + using namespace WiimoteReal; + + g_refresh_critsec.Enter(); + if (g_wiimotes[m_index]) + { + wm_request_status rpt; + rpt.rumble = 0; + g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); + } + g_refresh_critsec.Leave(); + + return; + } + // send report - g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, _channelID, data, sizeof(data)); + g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, sizeof(data)); } /* Write data to Wiimote and Extensions registers. */ -void Wiimote::WriteData(const u16 _channelID, wm_write_data* wd) +void Wiimote::WriteData(const wm_write_data* const wd) { - u32 address = convert24bit(wd->address); + u32 address = swap24(wd->address); // ignore the 0x010000 bit address &= 0xFEFFFF; @@ -324,14 +343,24 @@ } /* Read data from Wiimote and Extensions registers. */ -void Wiimote::ReadData(const u16 _channelID, wm_read_data* rd) +void Wiimote::ReadData(const wm_read_data* const rd) { - u32 address = convert24bit(rd->address); - u16 size = convert16bit(rd->size); + u32 address = swap24(rd->address); + u16 size = Common::swap16(rd->size); // ignore the 0x010000 bit address &= 0xFEFFFF; + // hybrid wiimote stuff + // relay the read data request to real-wiimote + if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index] && ((0xA4 != (address >> 16)) || (m_extension->switch_extension <= 0))) + { + WiimoteReal::InterruptChannel(m_index, m_reporting_channel, ((u8*)rd) - 2, sizeof(wm_read_data) + 2); // hacky + + // don't want emu-wiimote to send reply + return; + } + ReadRequest rr; u8* block = new u8[size]; @@ -416,14 +445,14 @@ } // want the requested address, not the above modified one - rr.address = convert24bit(rd->address); + rr.address = swap24(rd->address); rr.size = size; //rr.channel = _channelID; rr.position = 0; rr.data = block; // send up to 16 bytes - SendReadDataReply( _channelID, rr ); + SendReadDataReply(rr); // if there is more data to be sent, add it to the queue if (rr.size) @@ -440,7 +469,7 @@ bytes in the message, the 0 means no error, the 00 20 means that the message is at the 00 20 offest in the registry that was read. */ -void Wiimote::SendReadDataReply(const u16 _channelID, ReadRequest& _request) +void Wiimote::SendReadDataReply(ReadRequest& _request) { u8 data[23]; data[0] = 0xA1; @@ -488,7 +517,7 @@ } // Send a piece - g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, _channelID, data, sizeof(data)); + g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, sizeof(data)); } void Wiimote::DoState(PointerWrap& p) diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp 2010-08-18 03:25:23.000000000 +0100 @@ -7,8 +7,10 @@ #include "WiimoteEmu.h" #include "WiimoteHid.h" -#include -#include +#include "../WiimoteReal/WiimoteReal.h" + +#include "Timer.h" +#include "Common.h" #include "UDPTLayer.h" @@ -38,10 +40,7 @@ #define SWING_INTENSITY 0x40 -static struct ReportFeatures -{ - u8 core, accel, ir, ext, size; -} const reporting_mode_features[] = +const ReportFeatures reporting_mode_features[] = { //0x30: Core Buttons { 2, 0, 0, 0, 4 }, @@ -59,11 +58,6 @@ { 2, 0, 4, 14, 23 }, //0x37: Core Buttons and Accelerometer with 10 IR bytes and 6 Extension Bytes { 2, 4, 7, 17, 23 }, - //0x3d: 21 Extension Bytes - { 0, 0, 0, 2, 23 }, - //0x3e / 0x3f: Interleaved Core Buttons and Accelerometer with 36 IR bytes - // UNSUPPORTED - { 0, 0, 0, 0, 23 }, }; void EmulateShake( u8* const accel @@ -324,68 +318,35 @@ return std::string("Wiimote") + char('1'+m_index); } -void Wiimote::Update() -{ - const bool is_sideways = m_options->settings[1]->value > 0; - const bool is_upright = m_options->settings[2]->value > 0; +// if windows is focused or background input is enabled +#define HAS_FOCUS (g_WiimoteInitialize.pRendererHasFocus() || (m_options->settings[0]->value != 0)) - // if windows is focused or background input is enabled - const bool is_focus = g_WiimoteInitialize.pRendererHasFocus() || (m_options->settings[0]->value != 0); +bool Wiimote::Step() +{ + const bool has_focus = HAS_FOCUS; + const bool is_sideways = m_options->settings[1]->value != 0; // no rumble if no focus - if (false == is_focus) + if (false == has_focus) m_rumble_on = false; - m_rumble->controls[0]->control_ref->State(m_rumble_on); - - // ----speaker---- -#ifdef USE_WIIMOTE_EMU_SPEAKER - - ALint processed = 0; - alGetSourcei(m_audio_source, AL_BUFFERS_PROCESSED, &processed); - - while (processed--) - { - //PanicAlert("Buffer Processed"); - alSourceUnqueueBuffers(m_audio_source, 1, &m_audio_buffers.front().buffer); - alDeleteBuffers(1, &m_audio_buffers.front().buffer); - delete[] m_audio_buffers.front().samples; - m_audio_buffers.pop(); - } - - // testing speaker crap - //m_rumble->controls[0]->control_ref->State( m_speaker_data.size() > 0 ); - //if ( m_speaker_data.size() ) - //m_speaker_data.pop(); - //while ( m_speaker_data.size() ) - //{ - // std::ofstream file; - // file.open( "test.pcm", std::ios::app | std::ios::out | std::ios::binary ); - // file.put(m_speaker_data.front()); - // file.close(); - // m_speaker_data.pop(); - //} -#endif + m_rumble->controls[0]->control_ref->State(m_rumble_on); // update buttons in status struct m_status.buttons = 0; - if (is_focus) + if (has_focus) { m_buttons->GetState(&m_status.buttons, button_bitmasks); m_dpad->GetState(&m_status.buttons, is_sideways ? dpad_sideways_bitmasks : dpad_bitmasks); UDPTLayer::GetButtons(m_udp, &m_status.buttons); } - - // no channel == not connected i guess - if (0 == m_reporting_channel) - return; // check if there is a read data request if (m_read_requests.size()) { ReadRequest& rr = m_read_requests.front(); // send up to 16 bytes to the wii - SendReadDataReply(m_reporting_channel, rr); + SendReadDataReply(rr); //SendReadDataReply(rr.channel, rr); // if there is no more data, remove from queue @@ -396,179 +357,317 @@ } // dont send any other reports - return; + return true; } - // -- maybe this should happen before the read request stuff? // check if a status report needs to be sent // this happens on wiimote sync and when extensions are switched if (m_extension->active_extension != m_extension->switch_extension) { - RequestStatus(m_reporting_channel); + RequestStatus(); // Wiibrew: Following a connection or disconnection event on the Extension Port, // data reporting is disabled and the Data Reporting Mode must be reset before new data can arrive. // after a game receives an unrequested status report, // it expects data reports to stop until it sets the reporting mode again m_reporting_auto = false; + + return true; } - if (false == m_reporting_auto) - return; + return false; +} - // figure out what data we need - const ReportFeatures& rpt = reporting_mode_features[m_reporting_mode - WM_REPORT_CORE]; +void Wiimote::GetCoreData(u8* const data) +{ + *(wm_core*)data |= m_status.buttons; +} - // what does the real wiimote do when put in a reporting mode with extension data, - // but with no extension attached? should i just send zeros? sure - //if (rpt.ext && (m_extension->active_extension <= 0)) - //{ - // m_reporting_auto = false; - // return; - //} +void Wiimote::GetAccelData(u8* const data) +{ + const bool has_focus = HAS_FOCUS; + const bool is_sideways = m_options->settings[1]->value != 0; + const bool is_upright = m_options->settings[2]->value != 0; - // set up output report - // made data bigger than needed in case the wii specifies the wrong ir mode for a reporting mode - u8 data[46]; - memset( data, 0, sizeof(data) ); + // ----TILT---- + EmulateTilt((wm_accel*)data, m_tilt, (accel_cal*)&m_eeprom[0x16], has_focus, is_sideways, is_upright); - data[0] = 0xA1; - data[1] = m_reporting_mode; + // ----SWING---- + // ----SHAKE---- + if (has_focus) + { + EmulateSwing((wm_accel*)data, m_swing, (accel_cal*)&m_eeprom[0x16], is_sideways, is_upright); + EmulateShake(data, m_shake, m_shake_step); + // UDP Wiimote + UDPTLayer::GetAcceleration(m_udp, (wm_accel*)data, (accel_cal*)&m_eeprom[0x16]); + } +} - // core buttons - if (rpt.core) - *(wm_core*)(data + rpt.core) = m_status.buttons; +void Wiimote::GetIRData(u8* const data) +{ + const bool has_focus = HAS_FOCUS; + + u16 x[4], y[4]; + memset(x, 0xFF, sizeof(x)); - // ----accelerometer---- - if (rpt.accel) + if (has_focus) { - // ----TILT---- - EmulateTilt((wm_accel*)&data[rpt.accel], m_tilt, (accel_cal*)&m_eeprom[0x16], is_focus, is_sideways, is_upright); + float xx = 10000, yy = 0, zz = 0; + float tx, ty; + + m_ir->GetState(&xx, &yy, &zz, true); + UDPTLayer::GetIR(m_udp, &xx, &yy, &zz); + + m_tilt->GetState(&tx, &ty, 0, PI/2, false); + + // disabled cause my math still fails + const float rsin = 0;//sin(tx); + const float rcos = 1;//cos(tx); - // ----SWING---- - // ----SHAKE---- - if (is_focus) { - EmulateSwing((wm_accel*)&data[rpt.accel], m_swing, (accel_cal*)&m_eeprom[0x16], is_sideways, is_upright); - EmulateShake(data + rpt.accel, m_shake, m_shake_step); - // UDP Wiimote - UDPTLayer::GetAcceleration(m_udp, (wm_accel*)&data[rpt.accel], (accel_cal*)&m_eeprom[0x16]); + const float xxx = (xx * -256 * 0.95f); + const float yyy = (yy * -256 * 0.90f); + + xx = 512 + xxx * rcos + (144 + yyy) * rsin; + yy = 384 + (108 + yyy) * rcos - xxx * rsin; } + + // dot distance of 25 is too little + const unsigned int distance = (unsigned int)(150 + 100 * zz); + + x[0] = (unsigned int)(xx - distance * rcos); + x[1] = (unsigned int)(xx + distance * rcos); + x[2] = (unsigned int)(xx - 1.2f * distance * rcos); + x[3] = (unsigned int)(xx + 1.2f * distance * rcos); + + y[0] = (unsigned int)(yy - 0.75 * distance * rsin); + y[1] = (unsigned int)(yy + 0.75 * distance * rsin); + y[2] = (unsigned int)(yy - 0.75 * 1.2f * distance * rsin); + y[3] = (unsigned int)(yy + 0.75 * 1.2f * distance * rsin); + } - // ----ir---- - if (rpt.ir) + // Fill report with valid data when full handshake was done + if (m_reg_ir->data[0x30]) + // ir mode + switch (m_reg_ir->mode) { - float xx = 10000, yy = 0, zz = 0; - unsigned int x[4], y[4]; + // basic + case 1 : + { + memset(data, 0xFF, 10); + wm_ir_basic* const irdata = (wm_ir_basic*)data; + for (unsigned int i=0; i<2; ++i) + { + if (x[i*2] < 1024 && y[i*2] < 768) + { + irdata[i].x1 = u8(x[i*2]); + irdata[i].x1hi = x[i*2] >> 8; - if (is_focus) + irdata[i].y1 = u8(y[i*2]); + irdata[i].y1hi = y[i*2] >> 8; + } + if (x[i*2+1] < 1024 && y[i*2+1] < 768) + { + irdata[i].x2 = u8(x[i*2+1]); + irdata[i].x2hi = x[i*2+1] >> 8; + + irdata[i].y2 = u8(y[i*2+1]); + irdata[i].y2hi = y[i*2+1] >> 8; + } + } + } + break; + // extended + case 3 : { - m_ir->GetState(&xx, &yy, &zz, true); - UDPTLayer::GetIR(m_udp, &xx, &yy, &zz); + memset(data, 0xFF, 12); + wm_ir_extended* const irdata = (wm_ir_extended*)data; + for (unsigned int i=0; i<4; ++i) + if (x[i] < 1024 && y[i] < 768) + { + irdata[i].x = u8(x[i]); + irdata[i].xhi = x[i] >> 8; - float tx, ty; - m_tilt->GetState(&tx, &ty, 0, 1, false); + irdata[i].y = u8(y[i]); + irdata[i].yhi = y[i] >> 8; - // TODO: fix tilt math stuff + irdata[i].size = 10; + } + } + break; + // full + case 5 : + // UNSUPPORTED + break; + } +} - const float rtan = tan(0.0f/*tx*/); // disabled cause my math fails - const float rsin = sin(rtan); - const float rcos = cos(rtan); +void Wiimote::GetExtData(u8* const data) +{ + m_extension->GetState(data, HAS_FOCUS); - { - const float xxx = (xx * -256 * 0.95f); - const float yyy = (yy * -256 * 0.90f); + // i dont think anything accesses the extension data like this, but ill support it. Indeed, commercial games don't do this. + // i think it should be unencrpyted in the register, encrypted when read. + memcpy(m_reg_ext->controller_data, data, sizeof(wm_extension)); - xx = 512 + xxx * rcos + yyy * rsin; - yy = 490 + yyy * rcos + xxx * rsin; - } + if (0xAA == m_reg_ext->encryption) + wiimote_encrypt(&m_ext_key, data, 0x00, sizeof(wm_extension)); +} - const unsigned int distance = (unsigned int)(200 + 100 * zz); +void Wiimote::Update() +{ + // no channel == not connected i guess + if (0 == m_reporting_channel) + return; - x[0] = (unsigned int)(xx - distance * rcos); - x[1] = (unsigned int)(xx + distance * rcos); - x[2] = (unsigned int)(xx - 1.2f * distance * rcos); - x[3] = (unsigned int)(xx + 1.2f * distance * rcos); + // returns true if a report was sent + if (Step()) + return; - y[0] = (unsigned int)(yy - 0.75 * distance * rsin); - y[1] = (unsigned int)(yy + 0.75 * distance * rsin); - y[2] = (unsigned int)(yy - 0.75 * 1.2f * distance * rsin); - y[3] = (unsigned int)(yy + 0.75 * 1.2f * distance * rsin); + // ----speaker---- +#ifdef USE_WIIMOTE_EMU_SPEAKER - } + ALint processed = 0; + alGetSourcei(m_audio_source, AL_BUFFERS_PROCESSED, &processed); - // Fill report with valid data when full handshake was done - if (m_reg_ir->data[0x30]) - // ir mode - switch (m_reg_ir->mode) + while (processed--) + { + //PanicAlert("Buffer Processed"); + alSourceUnqueueBuffers(m_audio_source, 1, &m_audio_buffers.front().buffer); + alDeleteBuffers(1, &m_audio_buffers.front().buffer); + delete[] m_audio_buffers.front().samples; + m_audio_buffers.pop(); + } + + // testing speaker crap + //m_rumble->controls[0]->control_ref->State( m_speaker_data.size() > 0 ); + //if ( m_speaker_data.size() ) + //m_speaker_data.pop(); + + //while ( m_speaker_data.size() ) + //{ + // std::ofstream file; + // file.open( "test.pcm", std::ios::app | std::ios::out | std::ios::binary ); + // file.put(m_speaker_data.front()); + // file.close(); + // m_speaker_data.pop(); + //} +#endif + + u8 data[MAX_PAYLOAD]; + memset(data, 0, sizeof(data)); + data[0] = 0xA1; + data[1] = m_reporting_mode; + + // figure out what data we need + const ReportFeatures& rptf = reporting_mode_features[m_reporting_mode - WM_REPORT_CORE]; + s8 rptf_size = rptf.size; + + // core buttons + if (rptf.core) + GetCoreData(data + rptf.core); + + // acceleration + if (rptf.accel) + GetAccelData(data + rptf.accel); + + // IR + if (rptf.ir) + GetIRData(data + rptf.ir); + + // extension + if (rptf.ext) + GetExtData(data + rptf.ext); + + // hybrid wiimote stuff + if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index]) + { + using namespace WiimoteReal; + + g_refresh_critsec.Enter(); + if (g_wiimotes[m_index]) { - // basic - case 1 : + u8* const real_data = g_wiimotes[m_index]->ProcessReadQueue(); + if (real_data) { - memset(data + rpt.ir, 0xFF, 10); - wm_ir_basic* const irdata = (wm_ir_basic*)(data + rpt.ir); - for (unsigned int i=0; i<2; ++i) - { - if (x[i*2] < 1024 && y[i*2] < 768) + switch (real_data[1]) { - irdata[i].x1 = u8(x[i*2]); - irdata[i].x1hi = x[i*2] >> 8; + // use data reports + default: + if (real_data[1] >= WM_REPORT_CORE) + { + const ReportFeatures& real_rptf = reporting_mode_features[real_data[1] - WM_REPORT_CORE]; + + // force same report type from real-wiimote + if (&real_rptf != &rptf) + rptf_size = 0; + + // core + // mix real-buttons with emu-buttons in the status struct, and in the report + if (real_rptf.core && rptf.core) + { + m_status.buttons |= *(wm_core*)(real_data + real_rptf.core); + *(wm_core*)(data + rptf.core) = m_status.buttons; + } + + // accel + // use real-accel data always i guess + if (real_rptf.accel && rptf.accel) + memcpy(data + rptf.accel, real_data + real_rptf.accel, sizeof(wm_accel)); + + // ir + // TODO + + // ext + // use real-ext data if an emu-extention isn't chosen + if (real_rptf.ext && rptf.ext && (0 == m_extension->switch_extension)) + memcpy(data + rptf.ext, real_data + real_rptf.ext, sizeof(wm_extension)); + } + else if (WM_ACK_DATA != real_data[1] || m_extension->active_extension > 0) + rptf_size = 0; + else + // use real-acks if an emu-extension isn't chosen + rptf_size = -1; + break; + + // use all status reports, after modification of the extension bit + case WM_STATUS_REPORT : + //if (m_extension->switch_extension) + //((wm_status_report*)(real_data + 2))->extension = (m_extension->active_extension > 0); + if (m_extension->active_extension) + ((wm_status_report*)(real_data + 2))->extension = 1; + rptf_size = -1; + break; + + // use all read-data replies + case WM_READ_DATA_REPLY: + rptf_size = -1; + break; - irdata[i].y1 = u8(y[i*2]); - irdata[i].y1hi = y[i*2] >> 8; } - if (x[i*2+1] < 1024 && y[i*2+1] < 768) - { - irdata[i].x2 = u8(x[i*2+1]); - irdata[i].x2hi = x[i*2+1] >> 8; - irdata[i].y2 = u8(y[i*2+1]); - irdata[i].y2hi = y[i*2+1] >> 8; - } - } - } - break; - // extended - case 3 : - { - memset(data + rpt.ir, 0xFF, 12); - wm_ir_extended* const irdata = (wm_ir_extended*)(data + rpt.ir); - for (unsigned int i=0; i<4; ++i) - if (x[i] < 1024 && y[i] < 768) + // copy over report from real-wiimote + if (-1 == rptf_size) { - irdata[i].x = u8(x[i]); - irdata[i].xhi = x[i] >> 8; - - irdata[i].y = u8(y[i]); - irdata[i].yhi = y[i] >> 8; - - irdata[i].size = 10; + memcpy(data, real_data, MAX_PAYLOAD); + rptf_size = MAX_PAYLOAD; } + + if (real_data != g_wiimotes[m_index]->m_last_data_report) + delete[] real_data; } - break; - // full - case 5 : - // UNSUPPORTED - break; } + g_refresh_critsec.Leave(); } - // ----extension---- - if (rpt.ext) - { - m_extension->GetState(data + rpt.ext, is_focus); - - // i dont think anything accesses the extension data like this, but ill support it. Indeed, commercial games don't do this. - // i think it should be unencrpyted in the register, encrypted when read. - memcpy(m_reg_ext->controller_data, data + rpt.ext, sizeof(wm_extension)); + // don't send a data report if auto reporting is off + if (false == m_reporting_auto && data[2] >= WM_REPORT_CORE) + return; - if (0xAA == m_reg_ext->encryption) { - wiimote_encrypt(&m_ext_key, data + rpt.ext, 0x00, sizeof(wm_extension)); - } - } // send data report - g_WiimoteInitialize.pWiimoteInterruptChannel( m_index, m_reporting_channel, data, rpt.size ); + if (rptf_size) + g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, rptf_size); } void Wiimote::ControlChannel(const u16 _channelID, const void* _pData, u32 _Size) @@ -587,7 +686,7 @@ // this all good? m_reporting_channel = _channelID; - hid_packet* hidp = (hid_packet*)_pData; + const hid_packet* const hidp = (hid_packet*)_pData; INFO_LOG(WIIMOTE, "Emu ControlChannel (page: %i, type: 0x%02x, param: 0x%02x)", m_index, hidp->type, hidp->param); @@ -606,7 +705,7 @@ { // AyuanX: My experiment shows Control Channel is never used // shuffle2: but homebrew uses this, so we'll do what we must :) - HidOutputReport(_channelID, (wm_report*)hidp->data); + HidOutputReport((wm_report*)hidp->data); u8 handshake = HID_HANDSHAKE_SUCCESS; g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, _channelID, &handshake, 1); @@ -631,7 +730,7 @@ // this all good? m_reporting_channel = _channelID; - hid_packet* hidp = (hid_packet*)_pData; + const hid_packet* const hidp = (hid_packet*)_pData; switch (hidp->type) { @@ -640,8 +739,26 @@ { case HID_PARAM_OUTPUT : { - wm_report* sr = (wm_report*)hidp->data; - HidOutputReport(_channelID, sr); + const wm_report* const sr = (wm_report*)hidp->data; + + if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index]) + { + switch (sr->wm) + { + // these two types are handled in RequestStatus() & ReadData() + case WM_REQUEST_STATUS : + case WM_READ_DATA : + break; + + default : + WiimoteReal::InterruptChannel(m_index, _channelID, _pData, _Size); + break; + } + + HidOutputReport(sr, m_extension->switch_extension > 0); + } + else + HidOutputReport(sr); } break; @@ -762,7 +879,7 @@ } // TODO: i need to test this -void Wiimote::Register::Write( size_t address, void* src, size_t length ) +void Wiimote::Register::Write( size_t address, const void* src, size_t length ) { iterator i = begin(); const const_iterator e = end(); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h 2010-08-18 03:25:23.000000000 +0100 @@ -8,7 +8,7 @@ // just used to get the OpenAL includes :p //#include -#include +#include "ControllerEmu.h" #include "ChunkFile.h" #include "WiimoteHid.h" @@ -32,6 +32,13 @@ namespace WiimoteEmu { +struct ReportFeatures +{ + u8 core, accel, ir, ext, size; +}; + +extern const ReportFeatures reporting_mode_features[]; + void EmulateShake(u8* const accel_data , ControllerEmu::Buttons* const buttons_group , unsigned int* const shake_step); @@ -77,6 +84,19 @@ void LoadDefaults(const ControllerInterface& ciface); +protected: + bool Step(); + void HidOutputReport(const wm_report* const sr, const bool send_ack = true); + void HandleExtensionSwap(); + + void GetCoreData(u8* const data); + void GetAccelData(u8* const data); + void GetIRData(u8* const data); + void GetExtData(u8* const data); + + bool HaveExtension() const { return m_extension->active_extension > 0; } + bool WantExtension() const { return m_extension->switch_extension != 0; } + private: struct ReadRequest { @@ -87,14 +107,12 @@ void Reset(); - void ReportMode(const u16 _channelID, wm_report_mode* dr); - void HidOutputReport(const u16 _channelID, wm_report* sr); - void SendAck(const u16 _channelID, u8 _reportID); - void RequestStatus(const u16 _channelID, wm_request_status* rs = NULL); - - void WriteData(const u16 _channelID, wm_write_data* wd); - void ReadData(const u16 _channelID, wm_read_data* rd); - void SendReadDataReply(const u16 _channelID, ReadRequest& _request); + void ReportMode(const wm_report_mode* const dr); + void SendAck(const u8 _reportID); + void RequestStatus(const wm_request_status* const rs = NULL); + void ReadData(const wm_read_data* const rd); + void WriteData(const wm_write_data* const wd); + void SendReadDataReply(ReadRequest& _request); #ifdef USE_WIIMOTE_EMU_SPEAKER void SpeakerData(wm_speaker_data* sd); @@ -131,7 +149,7 @@ class Register : public std::map< size_t, std::vector > { public: - void Write( size_t address, void* src, size_t length ); + void Write( size_t address, const void* src, size_t length ); void Read( size_t address, void* dst, size_t length ); } m_register; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h 2010-08-18 03:25:23.000000000 +0100 @@ -205,7 +205,7 @@ u8 space : 2; //see WM_SPACE_* u8 : 5; u8 address[3]; - u8 size[2]; + u16 size; }; #define WM_SPACE_EEPROM 0 diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp 2010-08-18 03:25:23.000000000 +0100 @@ -3,9 +3,9 @@ #include "pluginspecs_wiimote.h" #include "WiimoteReal/WiimoteReal.h" +#include "WiimoteEmu/WiimoteEmu.h" #include "ControllerInterface/ControllerInterface.h" -#include "WiimoteEmu/WiimoteEmu.h" #if defined(HAVE_WX) && HAVE_WX #include "WiimoteConfigDiag.h" @@ -53,23 +53,6 @@ HINSTANCE g_hInstance; #endif -// copied from GCPad -#if defined(HAVE_WX) && HAVE_WX -wxWindow* GetParentedWxWindow(HWND Parent) -{ -#ifdef _WIN32 - wxSetInstance((HINSTANCE)g_hInstance); -#endif - wxWindow *win = new wxWindow(); -#ifdef _WIN32 - win->SetHWND((WXHWND)Parent); - win->AdoptAttributesFromHWND(); -#endif - return win; -} -#endif -// / - #ifdef _WIN32 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) { @@ -144,15 +127,11 @@ // void Wiimote_ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size) { - switch (g_wiimote_sources[_number]) - { - case WIIMOTE_SRC_REAL : + if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number]) + ((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->ControlChannel(_channelID, _pData, _Size); + + if (WIIMOTE_SRC_REAL & g_wiimote_sources[_number]) WiimoteReal::ControlChannel(_number, _channelID, _pData, _Size); - break; - case WIIMOTE_SRC_EMU : - ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->ControlChannel( _channelID, _pData, _Size ); - break; - } } // __________________________________________________________________________________________________ @@ -186,15 +165,10 @@ // void Wiimote_InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size) { - switch (g_wiimote_sources[_number]) - { - case WIIMOTE_SRC_REAL : + if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number]) + ((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->InterruptChannel(_channelID, _pData, _Size); + else WiimoteReal::InterruptChannel(_number, _channelID, _pData, _Size); - break; - case WIIMOTE_SRC_EMU : - ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->InterruptChannel( _channelID, _pData, _Size ); - break; - } } // __________________________________________________________________________________________________ @@ -218,15 +192,10 @@ } _last_number = _number; - switch (g_wiimote_sources[_number]) - { - case WIIMOTE_SRC_REAL : - WiimoteReal::Update(_number); - break; - case WIIMOTE_SRC_EMU : + if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number]) ((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->Update(); - break; - } + else + WiimoteReal::Update(_number); g_plugin.controls_crit.Leave(); } @@ -271,7 +240,7 @@ // input: A handle to the window that calls this function // output: none // -void DllConfig(HWND _hParent) +void DllConfig(void *_hParent) { #if defined(HAVE_WX) && HAVE_WX const bool was_init = g_plugin.controller_interface.IsInit(); @@ -279,34 +248,18 @@ if (false == was_init) { #if defined(HAVE_X11) && HAVE_X11 - Window win = GDK_WINDOW_XID(GTK_WIDGET(_hParent)->window); + Window win = GDK_WINDOW_XID(GTK_WIDGET(((wxWindow *)_hParent)->GetHandle())->window); InitPlugin((void *)win); #else - InitPlugin(_hParent); + InitPlugin(((wxWindow *)_hParent)->GetHandle()); #endif } - wxWindow *frame = GetParentedWxWindow(_hParent); - WiimoteConfigDiag* const m_ConfigFrame = new WiimoteConfigDiag(frame, g_plugin); - //InputConfigDialog* const m_ConfigFrame = new InputConfigDialog(frame, g_plugin, PLUGIN_FULL_NAME); + WiimoteConfigDiag* const m_ConfigFrame = new WiimoteConfigDiag((wxWindow *)_hParent, g_plugin); -#ifdef _WIN32 - frame->Disable(); - m_ConfigFrame->ShowModal(); - frame->Enable(); -#else m_ConfigFrame->ShowModal(); -#endif - -#ifdef _WIN32 - wxMilliSleep(50); // hooray for hacks - frame->SetFocus(); - frame->SetHWND(NULL); -#endif m_ConfigFrame->Destroy(); - frame->Destroy(); - // / if (false == was_init) DeInitPlugin(); diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp 2010-08-18 03:25:23.000000000 +0100 @@ -19,7 +19,6 @@ #include "Common.h" #include "IniFile.h" -#include "Thread.h" #include "StringUtil.h" #include "Timer.h" #include "pluginspecs_wiimote.h" @@ -37,118 +36,80 @@ bool g_real_wiimotes_initialized = false; wiimote_t** g_wiimotes_from_wiiuse = NULL; unsigned int g_wiimotes_found = 0; -volatile unsigned int g_wiimotes_lastfound = 0; +// removed g_wiimotes_lastfound because Refresh() isn't taking advantage of it volatile bool g_run_wiimote_thread = false; -Common::Thread *g_wiimote_thread = NULL; -Common::CriticalSection g_wiimote_critsec; +Common::Thread *g_wiimote_threads[MAX_WIIMOTES] = {}; +Common::CriticalSection g_refresh_critsec; -THREAD_RETURN WiimoteThreadFunc(void* arg); - -// silly, copying data n stuff, o well, don't use this too often -void SendPacket(wiimote_t* const wm, const u8 rpt_id, const void* const data, const unsigned int size) -{ - u8* const rpt = new u8[size + 2]; - rpt[0] = 0xA1; - rpt[1] = rpt_id; - memcpy(rpt + 2, data, size); - wiiuse_io_write(wm, (byte*)rpt, size + 2); - delete[] rpt; -} - -class Wiimote -{ -public: - Wiimote(wiimote_t* const wm, const unsigned int index); - ~Wiimote(); - void ControlChannel(const u16 channel, const void* const data, const u32 size); - void InterruptChannel(const u16 channel, const void* const data, const u32 size); - void Update(); - - void Read(); - void Disconnect(); - void DisableDataReporting(); +THREAD_RETURN WiimoteThreadFunc(void* arg); +void StartWiimoteThreads(); +void StopWiimoteThreads(); -private: - void ClearReports(); +Wiimote *g_wiimotes[MAX_WIIMOTES]; - wiimote_t* const m_wiimote; - const unsigned int m_index; - - u16 m_channel; - u8 m_last_data_report[MAX_PAYLOAD]; - bool m_last_data_report_valid; - - std::queue m_reports; -}; - -Wiimote::Wiimote(wiimote_t* const wm, const unsigned int index) - : m_wiimote(wm) - , m_index(index) +Wiimote::Wiimote(wiimote_t* const _wiimote, const unsigned int _index) + : index(_index) + , wiimote(_wiimote) + , m_last_data_report(NULL) , m_channel(0) - , m_last_data_report_valid(false) { // disable reporting DisableDataReporting(); - // clear all msgs, silly maybe - // - cleared on first InterruptChannel call - //while (wiiuse_io_read(m_wiimote)); - - //{ - // LEDs test - //wm_leds rpt = wm_leds(); - //rpt.leds = 1 << i; - //SendPacket(g_wiimotes_from_wiiuse[i], WM_LEDS, &rpt, sizeof(rpt)); - //} - - // Rumble briefly - wiiuse_rumble(m_wiimote, 1); - SLEEP(200); - wiiuse_rumble(m_wiimote, 0); - // set LEDs - wiiuse_set_leds(m_wiimote, WIIMOTE_LED_1 << m_index); + wiiuse_set_leds(wiimote, WIIMOTE_LED_1 << index); // TODO: make Dolphin connect wiimote, maybe } Wiimote::~Wiimote() { - ClearReports(); + ClearReadQueue(); + + // clear write queue + Report rpt; + while (m_write_reports.Pop(rpt)) + delete[] rpt.first; // disable reporting / wiiuse might do this on shutdown anyway, o well, don't know for sure DisableDataReporting(); +} - // send disconnect message to wii, maybe, i hope, naw shit messes up on emu-stop - //if (g_WiimoteInitialize.pWiimoteInterruptChannel) - //{ - // //u8* const rpt = new u8[2]; - // //rpt[0] = 0XA1; rpt[1] = 0x15; - // //m_reports.push(rpt); - // //Update(); - - // const u8 rpt[] = { 0xA1, 0x15 }; - // g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_channel, rpt, sizeof(rpt)); - //} +// silly, copying data n stuff, o well, don't use this too often +void Wiimote::SendPacket(const u8 rpt_id, const void* const data, const unsigned int size) +{ + Report rpt; + rpt.second = size + 2; + rpt.first = new u8[rpt.second]; + rpt.first[0] = 0xA1; + rpt.first[1] = rpt_id; + memcpy(rpt.first + 2, data, size); + m_write_reports.Push(rpt); } void Wiimote::DisableDataReporting() { - wm_report_mode rpt = wm_report_mode(); + wm_report_mode rpt; rpt.mode = WM_REPORT_CORE; - SendPacket(m_wiimote, WM_REPORT_MODE, &rpt, sizeof(rpt)); + rpt.all_the_time = 0; + rpt.continuous = 0; + rpt.rumble = 0; + SendPacket(WM_REPORT_MODE, &rpt, sizeof(rpt)); } -void Wiimote::ClearReports() +void Wiimote::ClearReadQueue() { - m_last_data_report_valid = false; - while (m_reports.size()) + if (m_last_data_report) { - delete[] m_reports.front(); - m_reports.pop(); + delete[] m_last_data_report; + m_last_data_report = NULL; } + + u8 *rpt; + while (m_read_reports.Pop(rpt)) + delete[] rpt; } void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size) @@ -164,57 +125,104 @@ { if (0 == m_channel) // first interrupt/control channel sent { - // clear all msgs, silly maybe - while (wiiuse_io_read(m_wiimote)); + ClearReadQueue(); // request status - wm_request_status rpt = wm_request_status(); - SendPacket(m_wiimote, WM_REQUEST_STATUS, &rpt, sizeof(rpt)); + wm_request_status rpt; + rpt.rumble = 0; + SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); } - m_channel = channel; - wiiuse_io_write(m_wiimote, (byte*)data, size); -} + m_channel = channel; // this right? -void Wiimote::Read() -{ - // if not connected to Dolphin, don't do anything, to keep sanchez happy :p - if (0 == m_channel) - return; + Wiimote::Report rpt; + rpt.first = new u8[size]; + rpt.second = (u8)size; + memcpy(rpt.first, (u8*)data, size); - if (wiiuse_io_read(m_wiimote)) + // some hax, since we just send the last data report to Dolphin on each Update() call + // , make the wiimote only send updated data reports when data changes + // == less bt traffic, eliminates some unneeded packets + if (WM_REPORT_MODE == ((u8*)data)[1]) { - // a data report, save it - if (m_wiimote->event_buf[1] >= 0x30) + // also delete the last data report + if (m_last_data_report) { - memcpy(m_last_data_report, m_wiimote->event_buf, MAX_PAYLOAD); - m_last_data_report_valid = true; + delete[] m_last_data_report; + m_last_data_report = NULL; } - else + + // nice var names :p, this seems to be this one + ((wm_report_mode*)(rpt.first + 2))->all_the_time = false; + //((wm_report_mode*)(data + 2))->continuous = false; + } + + m_write_reports.Push(rpt); +} + +bool Wiimote::Read() +{ + if (wiiuse_io_read(wiimote)) + { + if (m_channel) { - // some other report, add it to queue + // add it to queue u8* const rpt = new u8[MAX_PAYLOAD]; - memcpy(rpt, m_wiimote->event_buf, MAX_PAYLOAD); - m_reports.push(rpt); + memcpy(rpt, wiimote->event_buf, MAX_PAYLOAD); + m_read_reports.Push(rpt); } + + return true; } + + return false; } -void Wiimote::Update() +bool Wiimote::Write() { - // do we have some queued reports - if (m_reports.size()) + Report rpt; + if (m_write_reports.Pop(rpt)) { - u8* const rpt = m_reports.front(); - m_reports.pop(); - g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_channel, rpt, MAX_PAYLOAD); - delete[] rpt; + wiiuse_io_write(wiimote, rpt.first, rpt.second); + delete[] rpt.first; + + return true; } - else if (m_last_data_report_valid) + + return false; +} + +// returns the next report that should be sent +u8* Wiimote::ProcessReadQueue() +{ + // pop through the queued reports + u8* rpt = m_last_data_report; + while (m_read_reports.Pop(rpt)) { - // otherwise send the last data report, if there is one - g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_channel, m_last_data_report, MAX_PAYLOAD); - } + // a data report + if (rpt[1] >= WM_REPORT_CORE) + m_last_data_report = rpt; + // some other kind of report + else + return rpt; + } + + // the queue was empty, or there were only data reports + return rpt; +} + +void Wiimote::Update() +{ + // pop through the queued reports + u8* const rpt = ProcessReadQueue(); + + // send the report + if (rpt && m_channel) + g_WiimoteInitialize.pWiimoteInterruptChannel(index, m_channel, rpt, MAX_PAYLOAD); + + // delete the data if it isn't also the last data rpt + if (rpt != m_last_data_report) + delete[] rpt; } void Wiimote::Disconnect() @@ -223,16 +231,8 @@ // disable reporting DisableDataReporting(); - - // clear queue - ClearReports(); - - // clear out wiiuse queue, or maybe not, silly? idk - while (wiiuse_io_read(m_wiimote)); } -Wiimote* g_wiimotes[4]; - void LoadSettings() { std::string ini_filename = (std::string(File::GetUserPath(D_CONFIG_IDX)) + g_plugin.ini_name + ".ini" ); @@ -261,7 +261,7 @@ // only call wiiuse_find with the number of slots configured for real wiimotes unsigned int wanted_wiimotes = 0; for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (WIIMOTE_SRC_REAL == g_wiimote_sources[i]) + if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]) ++wanted_wiimotes; // don't bother initializing wiiuse if we don't want any real wiimotes @@ -274,44 +274,34 @@ // initialized g_real_wiimotes_initialized = true; - -#ifdef WIN32 +#ifdef _WIN32 // Alloc memory for wiimote structure only if we're starting fresh if(!g_wiimotes_from_wiiuse) g_wiimotes_from_wiiuse = wiiuse_init(MAX_WIIMOTES); // on windows wiiuse_find() expects as a 3rd parameter the amount of last connected wiimotes instead of the timeout, // a timeout parameter is useless on win32 here, since at this points we already have the wiimotes discovered and paired up, just not connected. - g_wiimotes_found = wiiuse_find(g_wiimotes_from_wiiuse, wanted_wiimotes, g_wiimotes_lastfound); + g_wiimotes_found = wiiuse_find(g_wiimotes_from_wiiuse, wanted_wiimotes, 0); #else g_wiimotes_from_wiiuse = wiiuse_init(MAX_WIIMOTES); g_wiimotes_found = wiiuse_find(g_wiimotes_from_wiiuse, wanted_wiimotes, 5); #endif - g_wiimotes_lastfound = g_wiimotes_found; - DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted and %i previously found", g_wiimotes_found, wanted_wiimotes, g_wiimotes_lastfound); + DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted", + g_wiimotes_found, wanted_wiimotes); g_wiimotes_found = wiiuse_connect(g_wiimotes_from_wiiuse, g_wiimotes_found); DEBUG_LOG(WIIMOTE, "Connected to %i Real Wiimotes", g_wiimotes_found); - g_wiimote_critsec.Enter(); // enter - // create real wiimote class instances, assign wiimotes - for (unsigned int i = 0, w = 0; iWaitForDeath(); - delete g_wiimote_thread; - g_wiimote_thread = NULL; - } - - g_wiimote_critsec.Enter(); // enter + StopWiimoteThreads(); // delete wiimotes for (unsigned int i=0; iall_the_time = false; - //((wm_report_mode*)(data + 2))->continuous = false; - } + g_refresh_critsec.Enter(); if (g_wiimotes[_WiimoteNumber]) - g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, data, _Size); - - g_wiimote_critsec.Leave(); // leave + g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size); - if (data != _pData) - delete[] data; + g_refresh_critsec.Leave(); } void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { - g_wiimote_critsec.Enter(); // enter + g_refresh_critsec.Enter(); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size); - g_wiimote_critsec.Leave(); // leave + g_refresh_critsec.Leave(); } // Read the Wiimote once void Update(int _WiimoteNumber) { - g_wiimote_critsec.Enter(); // enter + g_refresh_critsec.Enter(); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->Update(); - g_wiimote_critsec.Leave(); // leave + g_refresh_critsec.Leave(); } void StateChange(PLUGIN_EMUSTATE newState) { - g_wiimote_critsec.Enter(); // enter + //g_refresh_critsec.Enter(); // enter // TODO: disable/enable auto reporting, maybe - g_wiimote_critsec.Leave(); // leave + //g_refresh_critsec.Leave(); // leave +} + +void StartWiimoteThreads() +{ + g_run_wiimote_thread = true; + for (unsigned int i=0; iWaitForDeath(); + delete g_wiimote_threads[i]; + g_wiimote_threads[i] = NULL; + } } THREAD_RETURN WiimoteThreadFunc(void* arg) { - Common::SetCurrentThreadName("Wiimote Read"); + Wiimote* const wiimote = (Wiimote*)arg; - while (g_run_wiimote_thread) { - g_wiimote_critsec.Enter(); // enter - - for (unsigned int i=0; iRead(); + char thname[] = "Wiimote # Thread"; + thname[8] = (char)('1' + wiimote->index); + Common::SetCurrentThreadName(thname); + } - g_wiimote_critsec.Leave(); // leave + // rumble briefly + wiiuse_rumble(wiimote->wiimote, 1); + SLEEP(200); + wiiuse_rumble(wiimote->wiimote, 0); - // hmmm, i get occasional lockups without this :/ - Common::SleepCurrentThread(1); + // main loop + while (g_run_wiimote_thread) + { + wiimote->Write(); + if (false == wiimote->Read()) + Common::SleepCurrentThread(1); // sleep if there was nothing to read } return 0; diff -Nru dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h --- dolphin-emu-2.0+svn5985/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h 2010-08-18 03:25:23.000000000 +0100 @@ -21,6 +21,9 @@ #include "wiiuse.h" #include "ChunkFile.h" +#include "Thread.h" +#include "FifoQueue.h" +#include "../WiimoteEmu/WiimoteEmu.h" #include "../../InputCommon/Src/InputConfig.h" @@ -33,13 +36,54 @@ enum { WIIMOTE_SRC_NONE = 0, - WIIMOTE_SRC_EMU, - WIIMOTE_SRC_REAL, + WIIMOTE_SRC_EMU = 1, + WIIMOTE_SRC_REAL = 2, + WIIMOTE_SRC_HYBRID = 3, // emu + real }; namespace WiimoteReal { +class Wiimote +{ + friend class WiimoteEmu::Wiimote; +public: + Wiimote(wiimote_t* const wm, const unsigned int index); + ~Wiimote(); + + void ControlChannel(const u16 channel, const void* const data, const u32 size); + void InterruptChannel(const u16 channel, const void* const data, const u32 size); + void Update(); + + u8* ProcessReadQueue(); + + bool Read(); + bool Write(); + void Disconnect(); + void DisableDataReporting(); + + void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size); + + // pointer to data, and size of data + typedef std::pair Report; + + const unsigned int index; + wiimote_t* const wiimote; + +protected: + u8 *m_last_data_report; + u16 m_channel; + +private: + void ClearReadQueue(); + + Common::FifoQueue m_read_reports; + Common::FifoQueue m_write_reports; +}; + +extern Common::CriticalSection g_refresh_critsec; +extern Wiimote *g_wiimotes[4]; + unsigned int Initialize(); void Shutdown(); void Refresh(); diff -Nru dolphin-emu-2.0+svn5985/Source/PluginSpecs/PluginSpecs.h dolphin-emu-2.0+svn6107/Source/PluginSpecs/PluginSpecs.h --- dolphin-emu-2.0+svn5985/Source/PluginSpecs/PluginSpecs.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/PluginSpecs/PluginSpecs.h 2010-08-18 03:25:25.000000000 +0100 @@ -42,10 +42,6 @@ #define TRUE 1 #define FALSE 0 #endif - - // simulate something that looks like win32 - // long term, kill these - #define HWND void* #endif #if defined(__cplusplus) @@ -116,7 +112,7 @@ // input: A handle to the window that calls this function // output: none // -EXPORT void CALL DllConfig(HWND _hParent); +EXPORT void CALL DllConfig(void *_hParent); // ___________________________________________________________________________ // Function: DllDebugger diff -Nru dolphin-emu-2.0+svn5985/Source/PluginSpecs/pluginspecs_video.h dolphin-emu-2.0+svn6107/Source/PluginSpecs/pluginspecs_video.h --- dolphin-emu-2.0+svn5985/Source/PluginSpecs/pluginspecs_video.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/PluginSpecs/pluginspecs_video.h 2010-08-18 03:25:25.000000000 +0100 @@ -14,6 +14,7 @@ typedef void (*TSetInterrupt)(u32 _causemask, bool _bSet); typedef int (*TRegisterEvent)(const char *name, TimedCallback callback); typedef void (*TScheduleEvent_Threadsafe)(int cyclesIntoFuture, int event_type, u64 userdata, bool fifoWait); +typedef void (*TRemoveEvent)(int event_type); typedef unsigned char* (*TGetMemoryPointer)(const unsigned int _iAddress); typedef void (*TVideoLog)(const char* _pMessage, int _bBreak); typedef void (*TSysMessage)(const char *fmt, ...); @@ -74,6 +75,7 @@ TSetInterrupt pSetInterrupt; TRegisterEvent pRegisterEvent; TScheduleEvent_Threadsafe pScheduleEvent_Threadsafe; + TRemoveEvent pRemoveEvent; TGetMemoryPointer pGetMemoryPointer; TVideoLog pLog; TSysMessage pSysMessage; @@ -187,5 +189,7 @@ // EXPORT bool CALL Video_IsFifoBusy(void); +EXPORT void CALL Video_AbortFrame(void); + #include "ExportEpilog.h" #endif diff -Nru dolphin-emu-2.0+svn5985/Source/PluginSpecs/pluginspecs_wiimote.h dolphin-emu-2.0+svn6107/Source/PluginSpecs/pluginspecs_wiimote.h --- dolphin-emu-2.0+svn5985/Source/PluginSpecs/pluginspecs_wiimote.h 2010-07-28 02:30:17.000000000 +0100 +++ dolphin-emu-2.0+svn6107/Source/PluginSpecs/pluginspecs_wiimote.h 2010-08-18 03:25:24.000000000 +0100 @@ -18,7 +18,7 @@ // This data is passed from the core on initialization. typedef struct { - HWND hWnd; + void *hWnd; u32 ISOId; TLogv pLog; TWiimoteInterruptChannel pWiimoteInterruptChannel;