diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index 5fcaa2d28c..584d3c09eb 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -465,6 +465,7 @@
Code
+
Code
diff --git a/BizHawk.Emulation/Database/CRC32.cs b/BizHawk.Emulation/Database/CRC32.cs
index 8516ae9ca3..b2af5ff423 100644
--- a/BizHawk.Emulation/Database/CRC32.cs
+++ b/BizHawk.Emulation/Database/CRC32.cs
@@ -1,4 +1,7 @@
-namespace BizHawk
+//we could get a little list of crcs from here and make it clear which crc this class was for, and expose others
+//http://www.ross.net/crc/download/crc_v3.txt
+
+namespace BizHawk
{
public static class CRC32
{
diff --git a/BizHawk.Emulation/DiscSystem/Disc.cs b/BizHawk.Emulation/DiscSystem/Disc.cs
index 0bbd2d2d14..383d8f10ab 100644
--- a/BizHawk.Emulation/DiscSystem/Disc.cs
+++ b/BizHawk.Emulation/DiscSystem/Disc.cs
@@ -235,12 +235,23 @@ namespace BizHawk.DiscSystem
buffer[offset + 14] = bcd_aba_frac;
//mode 1
buffer[offset + 15] = 1;
- //EDC
- ECM.edc_computeblock(buffer, offset+2064, buffer, offset+2064);
+
+ //calculate EDC and poke into the sector
+ uint edc = ECM.EDC_Calc(buffer, offset);
+ buffer[offset + 2064 + 0] = (byte)((edc >> 0) & 0xFF);
+ buffer[offset + 2064 + 1] = (byte)((edc >> 8) & 0xFF);
+ buffer[offset + 2064 + 2] = (byte)((edc >> 16) & 0xFF);
+ buffer[offset + 2064 + 3] = (byte)((edc >> 24) & 0xFF);
//intermediate
for (int i = 0; i < 8; i++) buffer[offset + 2068 + i] = 0;
//ECC
- ECM.ecc_generate(buffer, offset, false, buffer, offset+2076);
+ ECM.ECC_Populate(buffer, offset, buffer, offset, false);
+
+ //VALIDATION - check our homemade algorithms against code derived from ECM
+ ////EDC
+ //GPL_ECM.edc_validateblock(buffer, 2064, buffer, offset + 2064);
+ ////ECC
+ //GPL_ECM.ecc_validate(buffer, offset, false);
//if we read the 2048 physical bytes OK, then return the complete sector
if (read == 2048)
diff --git a/BizHawk.Emulation/DiscSystem/ECM.cs b/BizHawk.Emulation/DiscSystem/ECM.cs
index daea805f5b..ca1cbeba2e 100644
--- a/BizHawk.Emulation/DiscSystem/ECM.cs
+++ b/BizHawk.Emulation/DiscSystem/ECM.cs
@@ -1,95 +1,321 @@
-//Currently, this is stolen somewhat from blargg's code. probably LGPL. I think? originally it came from mednafen, and then I think mednafen may have changed to use another.
-//sorry for the confusion! it'd be nice to have some nice MIT licensed CD algorithms codes.. at least, we can keep these bullshit licensed ones here to a/b test when rewriting.
+//Copyright (c) 2012 BizHawk team
+
+//Permission is hereby granted, free of charge, to any person obtaining a copy of
+//this software and associated documentation files (the "Software"), to deal in
+//the Software without restriction, including without limitation the rights to
+//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+//of the Software, and to permit persons to whom the Software is furnished to do
+//so, subject to the following conditions:
+
+//The above copyright notice and this permission notice shall be included in all
+//copies or substantial portions of the Software.
+
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+//SOFTWARE.
+
+//CD-ROM ECC/EDC related algorithms
+//Support for Neill Corlett's ECM file format (TBD)
+
+//todo - ecm sometimes sets the sector address to 0 before computing the ECC. i cant find any documentation to support this.
+//seems to only take effect for cd-xa (mode 2, form 1). need to ask about this or test further on a cd-xa test disc
+
+//regarding ECC:
+//it turns out mame's cdrom.c uses pretty much this exact thing, naming the tables mul2tab->ecclow and div3tab->ecchigh
+//Corlett's ECM uses our same fundamental approach as well.
+//I can't figure out what winUAE is doing.
namespace BizHawk.DiscSystem
{
static class ECM
{
- static byte[] ecc_f_lut = new byte[256];
- static byte[] ecc_b_lut = new byte[256];
- static uint[] edc_lut = new uint[256];
+ //EDC (crc) acceleration table
+ static uint[] edc_table = new uint[256];
+
+ //math acceleration tables over GF(2^8) with yellowbook specified primitive polynomial 0x11D
+ static byte[] mul2tab = new byte[256];
+ static byte[] div3tab = new byte[256];
static ECM()
{
- uint i, j, edc;
- for(i = 0; i < 256; i++)
+ Prep_EDC();
+ Prep_ECC();
+ }
+
+ ///
+ /// calculate EDC crc tables
+ ///
+ static void Prep_EDC()
+ {
+ //14.3 of yellowbook specifies EDC crc as P(x) = (x^16 + x^15 + x^2 + 1) . (x^16 + x^2 + x + 1)
+ //confirmation at http://cdmagediscussion.yuku.com/topic/742/EDC-calculation
+ //int Pa = 0x18005;
+ //int Pb = 0x10007;
+ //long Px = 0;
+ //for (int i = 0; i <= 16; i++)
+ // for (int j = 0; j <= 16; j++)
+ // {
+ // //multiply Pa[i] * Pb[j]
+ // int bit = (Pa >> i) & (Pb >> j) & 1;
+ // //xor into result, achieving modulo-2 thereby
+ // Px ^= (long)bit << (i + j);
+ // }
+ //uint edc_poly = (uint)Px;
+ uint edc_poly = (uint)0x8001801B;
+
+ //generate the CRC table
+ uint reverse_edc_poly = BITREV.reverse_32(edc_poly);
+ for (uint i = 0; i < 256; ++i)
{
- j = (uint)((i << 1) ^ (((i & 0x80) != 0) ? 0x11D : 0));
- ecc_f_lut[i] = (byte)j;
- ecc_b_lut[i ^ j] = (byte)i;
- edc = i;
- for (j = 0; j < 8; j++)
- edc = (edc >> 1) ^ (((edc & 1) != 0) ? 0xD8018001 : 0);
- edc_lut[i] = edc;
- }
- }
-
- static uint edc_partial_computeblock(uint edc, byte[] src, int count)
- {
- int i = 0;
- while (count-- != 0) edc = (edc >> 8) ^ edc_lut[(edc ^ (src[i++])) & 0xFF];
- return edc;
- }
-
- public static void edc_computeblock(byte[] src, int count, byte[] dest, int dest_offset)
- {
- uint edc = edc_partial_computeblock(0, src, count);
- dest[dest_offset + 0] = (byte)((edc >> 0) & 0xFF);
- dest[dest_offset + 1] = (byte)((edc >> 8) & 0xFF);
- dest[dest_offset + 2] = (byte)((edc >> 16) & 0xFF);
- dest[dest_offset + 3] = (byte)((edc >> 24) & 0xFF);
- }
-
- static void ecc_computeblock(byte[] src, int src_offset, uint major_count, uint minor_count,uint major_mult, uint minor_inc, byte[] dest, int dest_offset)
- {
- uint size = major_count * minor_count;
- uint major, minor;
- for (major = 0; major < major_count; major++)
- {
- uint index = (major >> 1) * major_mult + (major & 1);
- byte ecc_a = 0;
- byte ecc_b = 0;
- for (minor = 0; minor < minor_count; minor++)
+ uint crc = i;
+ for (int j = 8; j > 0; --j)
{
- byte temp = src[src_offset+index];
- index += minor_inc;
- if (index >= size) index -= size;
- ecc_a ^= temp;
- ecc_b ^= temp;
- ecc_a = ecc_f_lut[ecc_a];
- //System.Console.WriteLine("{0} {1}", ecc_a, ecc_b);
+ if ((crc & 1) == 1)
+ crc = ((crc >> 1) ^ reverse_edc_poly);
+ else
+ crc >>= 1;
}
- ecc_a = ecc_b_lut[ecc_f_lut[ecc_a] ^ ecc_b];
- dest[dest_offset + major] = ecc_a;
- dest[dest_offset + major + major_count] = (byte)(ecc_a ^ ecc_b);
+ edc_table[i] = crc;
}
}
- public unsafe static void ecc_generate(byte[] sector, int sector_offset, bool zeroaddress, byte[] dest, int dest_offset)
+ ///
+ /// calculate math lookup tables for ECC calculations.
+ ///
+ static void Prep_ECC()
{
- byte address0=0,address1=0,address2=0,address3=0;
- //byte i;
- /* Save the address and zero it out */
- if(zeroaddress)
- {
- address0 = sector[sector_offset + 12 + 0]; sector[sector_offset + 12 + 0] = 0;
- address1 = sector[sector_offset + 12 + 1]; sector[sector_offset + 12 + 1] = 0;
- address2 = sector[sector_offset + 12 + 2]; sector[sector_offset + 12 + 2] = 0;
- address3 = sector[sector_offset + 12 + 3]; sector[sector_offset + 12 + 3] = 0;
- }
- /* Compute ECC P code */
- ecc_computeblock(sector, sector_offset + 0xC, 86, 24, 2, 86, dest, dest_offset);
- /* Compute ECC Q code */
- ecc_computeblock(sector, sector_offset + 0xC, 52, 43, 86, 88, dest, dest_offset+172);
- /* Restore the address */
- if (zeroaddress)
- {
- sector[sector_offset + 12 + 0] = address0;
- sector[sector_offset + 12 + 3] = address1;
- sector[sector_offset + 12 + 2] = address2;
- sector[sector_offset + 12 + 1] = address3;
- }
- }
- }
+ //create a table implementing f(i) = i*2
+ for (int i = 0; i < 256; i++)
+ {
+ int n = i * 2;
+ int b = n & 0xFF;
+ if (n > 0xFF) b ^= 0x1D; //primitive polynomial x^8 + x^4 + x^3 + x^2 + 1 -> 0x11D
+ mul2tab[i] = (byte)b;
+ }
-}
\ No newline at end of file
+ //(here is a more straightforward way of doing it, just to check)
+ //byte[] mul2tab_B = new byte[256];
+ //for (int i = 1; i < 256; i++)
+ // mul2tab_B[i] = FFUtil.gf_mul((byte)i, (byte)2);
+
+ ////(make sure theyre the same)
+ //for (int i = 0; i < 256; i++)
+ // System.Diagnostics.Debug.Assert(mul2tab[i] == mul2tab_B[i]);
+
+ //create a table implementing f(i) = i/3
+ for (int i = 0; i < 256; i++)
+ {
+ byte x1 = (byte)i;
+ byte x2 = mul2tab[i];
+ byte x3 = (byte)(x2 ^ x1); //2x + x = 3x
+ //instead of dividing 1/3 we write the table backwards since its the inverse of multiplying by 3
+ //this idea was taken from Corlett's techniques; I know not from whence they came.
+ div3tab[x3] = x1;
+ }
+
+ //(here is a more straightforward way of doing it, just to check)
+ //byte[] div3tab_B = new byte[256];
+ //for (int i = 0; i < 256; i++)
+ // div3tab_B[i] = FFUtil.gf_div((byte)i, 3);
+
+ ////(make sure theyre the same)
+ //for (int i = 0; i < 256; i++)
+ // System.Diagnostics.Debug.Assert(div3tab[i] == div3tab_B[i]);
+ }
+
+ ///
+ /// Calculates ECC parity values for the specified data
+ /// see annex A of yellowbook
+ ///
+ public static void CalcECC(byte[] data, int base_offset, int addr_offset, int addr_add, int todo, out byte p0, out byte p1)
+ {
+ //let's take the P parity as an example. Q parity will differ by being a (45, 43) code instead of the (25, 23) illustrated here.
+ //
+ //we're supposed to multiply [ [ 1 1 1 ] [a^25 a^24 a^23 ..] ] by [ [d0] [d1] [d2] ..] and get 0
+ //where a is the primitive element a=2 and d0 is data[0]
+ //this multiplication yields a matrix equation:
+ //[ [d0 + d1 + d2] [d0*a^25 + d1*a^24 + d2*a^23] ] = [ [0] [0] ]
+ //so now we have equations:
+ //(d0 + d1 + d2 ..) + p0 + p1 = 0
+ //(d0*a^25 + d1*a^24 + d2*a^23 ..) + p0*a + p1 = 0
+ //lets rename these series expressions for convenience to add_accum and pow_accum, respectively. so we'd have:
+ //add_accum + p0 + p1 = 0
+ //(pow_accum + p0) * 2 + p1 = 0
+ //
+ //we can get pow_accum in iterations of multiplying by 2 and adding..
+ //
+ //I.
+ //pow_accum = d0 [add]
+ //pow_accum = d0*2 [mul]
+ //II.
+ //pow_accum = d0*2 + d1 [add]
+ //pow_accum = (d0*2 + d1)*2 [mul]
+ //
+ //.. and we can get add_accum in the obvious way in iterations by adding.
+ //
+ //now all that remains is to solve the equations:
+ //(pow_accum + p0) * 2 + p1 = 0
+ //(pow_accum + p0) * 2 + add_accum + p0 = 0
+ //2*pow_accum + 2*p0 + add_accum + p0 = 0
+ //3*p0 + p0 = -2*pow_accum - add_accum
+ //3*p0 = (2*pow_accum) ^ add_accum
+ //p0 = ((2*pow_accum) ^ add_accum) / 3
+ //..and..
+ //add_accum + p0 + p1 = 0
+ //p1 = - p0 - add_accum
+ //p1 = p0 ^ add_accum
+
+ byte pow_accum = 0;
+ byte add_accum = 0;
+ for (int i = 0; i < todo; i++)
+ {
+ addr_offset %= (1118 * 2); //modulo addressing is irrelevant for P-parity calculation but comes into play for Q-parity
+ byte d = data[base_offset + addr_offset];
+ addr_offset += addr_add;
+ add_accum ^= d;
+ pow_accum ^= d;
+ pow_accum = mul2tab[pow_accum];
+ }
+
+ p0 = div3tab[mul2tab[pow_accum] ^ add_accum];
+ p1 = (byte)(p0 ^ add_accum);
+ }
+
+ ///
+ /// calculates EDC checksum for bytes [0,2063] of a sector located at (offset(
+ /// see section 14.3 of yellowbook
+ ///
+ public static uint EDC_Calc(byte[] data, int offset)
+ {
+ uint crc = 0;
+ for (int i = 0; i <= 2063; i++)
+ {
+ byte b = data[offset + i];
+ int entry = ((int)crc ^ b) & 0xFF;
+ crc = edc_table[entry] ^ (crc >> 8);
+ }
+
+ return crc;
+ }
+
+ ///
+ /// returns the address from a sector. useful for saving it before zeroing it for ECC calculations
+ ///
+ static uint GetSectorAddress(byte[] sector, int sector_offset)
+ {
+ return (uint)(
+ (sector[sector_offset + 12 + 0] << 0)
+ | (sector[sector_offset + 12 + 1] << 8)
+ | (sector[sector_offset + 12 + 2] << 16)
+ | (sector[sector_offset + 12 + 3] << 24));
+ }
+
+ ///
+ /// sets the address for a sector. useful for restoring it after zeroing it for ECC calculations
+ ///
+ static void SetSectorAddress(byte[] sector, int sector_offset, uint address)
+ {
+ sector[sector_offset + 12 + 0] = (byte)((address >> 0) & 0xFF);
+ sector[sector_offset + 12 + 1] = (byte)((address >> 8) & 0xFF);
+ sector[sector_offset + 12 + 2] = (byte)((address >> 16) & 0xFF);
+ sector[sector_offset + 12 + 3] = (byte)((address >> 24) & 0xFF);
+ }
+
+
+
+ ///
+ /// populates a sector with valid ECC information.
+ /// it is safe to supply the same array for sector and dest.
+ ///
+ public static void ECC_Populate(byte[] src, int src_offset, byte[] dest, int dest_offset, bool zeroSectorAddress)
+ {
+ //save the old sector address, so we can restore it later. SOMETIMES ECC is supposed to be calculated without it? see TODO
+ uint address = GetSectorAddress(src, src_offset);
+ if (zeroSectorAddress) SetSectorAddress(src, src_offset, 0);
+
+ //all further work takes place relative to offset 12 in the sector
+ src_offset += 12;
+ dest_offset += 12;
+
+ //calculate P parity for 86 columns (twice 43 word-columns)
+ byte parity0, parity1;
+ for (int col = 0; col < 86; col++)
+ {
+ int offset = col;
+ CalcECC(src, src_offset, offset, 86, 24, out parity0, out parity1);
+ //store the parities in the sector; theyre read for the Q parity calculations
+ dest[dest_offset + 1032 * 2 + col] = parity0;
+ dest[dest_offset + 1032 * 2 + col + 43 * 2] = parity1;
+ }
+
+ //calculate Q parity for 52 diagonals (twice 26 word-diagonals)
+ //modulo addressing is taken care of in CalcECC
+ for (int d = 0; d < 26; d++)
+ {
+ for (int w = 0; w < 2; w++)
+ {
+ int offset = d * 86 + w;
+ CalcECC(src, src_offset, offset, 88, 43, out parity0, out parity1);
+ //store the parities in the sector; thats where theyve got to go anyway
+ dest[dest_offset + 1118 * 2 + d * 2 + w] = parity0;
+ dest[dest_offset + 1118 * 2 + d * 2 + w + 26 * 2] = parity1;
+ }
+ }
+
+ //unadjust the offset back to an absolute sector address, which SetSectorAddress expects
+ src_offset -= 12;
+ SetSectorAddress(src, src_offset, address);
+ }
+
+
+ /////
+ ///// Finite Field math helpers. Adapted from: http://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders
+ ///// Only used by alternative implementations of ECM techniques
+ /////
+ //static class FFUtil
+ //{
+ // public static byte gf_div(byte x, byte y)
+ // {
+ // if (y == 0)
+ // return 0; //? error ?
+ // if (x == 0)
+ // return 0;
+ // int q = gf_log[x] + 255 - gf_log[y];
+ // return gf_exp[q];
+ // }
+
+ // public static byte gf_mul(byte x, byte y)
+ // {
+ // if (x == 0 || y == 0)
+ // return 0;
+ // return gf_exp[gf_log[x] + gf_log[y]];
+ // }
+
+ // static byte[] gf_exp = new byte[512];
+ // static byte[] gf_log = new byte[256];
+ // static FFUtil()
+ // {
+ // for (int i = 0; i < 512; i++) gf_exp[i] = 1;
+ // for (int i = 0; i < 256; i++) gf_log[i] = 0;
+ // int x = 1;
+ // for (int i = 1; i < 255; i++)
+ // {
+ // x <<= 1;
+ // if ((x & 0x100) != 0)
+ // x ^= 0x11d; //yellowbook specified primitive polynomial
+ // gf_exp[i] = (byte)x;
+ // gf_log[x] = (byte)i;
+ // }
+ // for (int i = 255; i < 512; i++)
+ // gf_exp[i] = gf_exp[(byte)(i - 255)];
+ // }
+
+ //} //static class FFUtil
+
+ } //static class ECM
+
+}
diff --git a/BizHawk.Emulation/DiscSystem/GPL_ECM.cs b/BizHawk.Emulation/DiscSystem/GPL_ECM.cs
new file mode 100644
index 0000000000..bd8154072b
--- /dev/null
+++ b/BizHawk.Emulation/DiscSystem/GPL_ECM.cs
@@ -0,0 +1,116 @@
+////-------------------
+////WARNING GPL CODE
+////-------------------
+////
+////this is stolen somewhat from neill corlett's code. almost certainly some kind of GPL. originally it came from mednafen, and then I think mednafen may have changed to use another. sorry for the confusion!
+////
+////it's kept in this project so that we can readily a/b test it against new algorithms
+
+//using System.Diagnostics;
+
+//namespace BizHawk.DiscSystem
+//{
+// public static class GPL_ECM
+// {
+// static byte[] ecc_f_lut = new byte[256];
+// static byte[] ecc_b_lut = new byte[256];
+// static uint[] edc_lut = new uint[256];
+
+// static GPL_ECM()
+// {
+// uint i, j, edc;
+// for (i = 0; i < 256; i++)
+// {
+// j = (uint)((i << 1) ^ (((i & 0x80) != 0) ? 0x11D : 0));
+// ecc_f_lut[i] = (byte)j;
+// ecc_b_lut[i ^ j] = (byte)i;
+// edc = i;
+// for (j = 0; j < 8; j++)
+// edc = (edc >> 1) ^ (((edc & 1) != 0) ? 0xD8018001 : 0);
+// edc_lut[i] = edc;
+// }
+// }
+
+// public static uint edc_partial_computeblock(uint edc, byte[] src, int count)
+// {
+// int i = 0;
+// while (count-- != 0) edc = (edc >> 8) ^ edc_lut[(edc ^ (src[i++])) & 0xFF];
+// return edc;
+// }
+
+// public static void edc_computeblock(byte[] src, int count, byte[] dest, int dest_offset)
+// {
+// uint edc = edc_partial_computeblock(0, src, count);
+// dest[dest_offset + 0] = (byte)((edc >> 0) & 0xFF);
+// dest[dest_offset + 1] = (byte)((edc >> 8) & 0xFF);
+// dest[dest_offset + 2] = (byte)((edc >> 16) & 0xFF);
+// dest[dest_offset + 3] = (byte)((edc >> 24) & 0xFF);
+// }
+
+// public static void edc_validateblock(byte[] src, int count, byte[] dest, int dest_offset)
+// {
+// uint edc = edc_partial_computeblock(0, src, count);
+// Debug.Assert(dest[dest_offset + 0] == (byte)((edc >> 0) & 0xFF));
+// Debug.Assert(dest[dest_offset + 1] == (byte)((edc >> 8) & 0xFF));
+// Debug.Assert(dest[dest_offset + 2] == (byte)((edc >> 16) & 0xFF));
+// Debug.Assert(dest[dest_offset + 3] == (byte)((edc >> 24) & 0xFF));
+// }
+
+// public static void ecc_validateblock(byte[] src, int src_offset, uint major_count, uint minor_count, uint major_mult, uint minor_inc, byte[] dest, int dest_offset)
+// {
+// uint size = major_count * minor_count;
+// uint major, minor;
+// for (major = 0; major < major_count; major++)
+// {
+// uint index = (major >> 1) * major_mult + (major & 1);
+// byte ecc_a = 0;
+// byte ecc_b = 0;
+// for (minor = 0; minor < minor_count; minor++)
+// {
+// byte temp = src[src_offset + index];
+// if ((major >> 1) * major_mult + (major & 1) == 12 && minor_inc == 86)
+// System.Console.WriteLine(temp);
+// index += minor_inc;
+// if (index >= size) index -= size;
+// ecc_a ^= temp;
+// ecc_b ^= temp;
+// ecc_a = ecc_f_lut[ecc_a];
+// }
+// ecc_a = ecc_b_lut[ecc_f_lut[ecc_a] ^ ecc_b];
+// Debug.Assert(dest[dest_offset + major] == ecc_a);
+// Debug.Assert(dest[dest_offset + major + major_count] == (byte)(ecc_a ^ ecc_b));
+// }
+// }
+
+// public unsafe static void ecc_validate(byte[] sector, int sector_offset, bool zeroaddress)
+// {
+// byte[] dest = sector;
+// int dest_offset = sector_offset+2076;
+
+// byte address0 = 0, address1 = 0, address2 = 0, address3 = 0;
+// //byte i;
+// /* Save the address and zero it out */
+// if (zeroaddress)
+// {
+// address0 = sector[sector_offset + 12 + 0]; sector[sector_offset + 12 + 0] = 0;
+// address1 = sector[sector_offset + 12 + 1]; sector[sector_offset + 12 + 1] = 0;
+// address2 = sector[sector_offset + 12 + 2]; sector[sector_offset + 12 + 2] = 0;
+// address3 = sector[sector_offset + 12 + 3]; sector[sector_offset + 12 + 3] = 0;
+// }
+// /* Compute ECC P code */
+// ecc_validateblock(sector, sector_offset + 0xC, 86, 24, 2, 86, dest, dest_offset);
+// /* Compute ECC Q code */
+// ecc_validateblock(sector, sector_offset + 0xC, 52, 43, 86, 88, dest, dest_offset + 172);
+// /* Restore the address */
+// if (zeroaddress)
+// {
+// sector[sector_offset + 12 + 0] = address0;
+// sector[sector_offset + 12 + 3] = address1;
+// sector[sector_offset + 12 + 2] = address2;
+// sector[sector_offset + 12 + 1] = address3;
+// }
+// }
+// }
+
+//}
+
diff --git a/BizHawk.Emulation/DiscSystem/docs/notes.txt b/BizHawk.Emulation/DiscSystem/docs/notes.txt
new file mode 100644
index 0000000000..88db7db742
--- /dev/null
+++ b/BizHawk.Emulation/DiscSystem/docs/notes.txt
@@ -0,0 +1,35 @@
+//lets leave some notes here until we've rewritten every possible thing -- error recovery, ECM file format, ISO filesystem, etc.
+
+//here is a braindump of urls and stuff for future reference
+//check this for some iso stuff but seems like it ripped off corlett's code
+//http://lioneditor.googlecode.com/svn/trunk/utils/isopatcherv05/src/
+//http://code.ohloh.net/file?fid=185llKM04w3QCqwC2MdFgtUiQ94&cid=yPMRq_HKxUg&s=ecc_computeblock%28pSector%20%2B%200xC%2C%2052%2C%2043%2C%2086%2C%2088%2C%20pSector%20%2B%200x8C8%29&mp=1&ml=1&me=1&md=1&browser=Default#L106
+
+//more gpl edc/ecc
+//http://code.ohloh.net/file?fid=BEZeY2fWALJKXTgY3Oe9J988ubQ&cid=Xkpw3SKt7K8&s=edc%20ecc%20&pp=0&fl=C&ff=1&filterChecked=true&mp=1&ml=1&me=1&md=1&browser=Default#L13
+//still more.. comes from lxdream, which takes its code from cdrkit. cdrkit is gpl
+//http://code.ohloh.net/file?fid=asMhpC6ygBi47pIYaxYwhXJFptI&cid=T6ljN87aG7M&s=&browser=Default&pp=0&fl=NonCode&fl=C&fl=C%2B%2B&ff=1&mp=1&ml=1&me=1&md=1&filterChecked=true#L0
+
+//cdemu/cdrtools/dvdrtools/cdkit maybe useful libraries to reference but all gpl?
+//cdrdao is GPL as well
+//cdrtools is some weird license CDDL
+//cdrkit was forked from the last GPL version of cdrtools. cdrkit is definitely gpl
+//libedc was part of cdrtools; now part of cdrkit too when it forked. but it is GPL
+//dvdisaster is GPL too
+//one more thing http://www.gnu.org/software/libcdio/libcdio.html
+
+//entertaining debacle
+//https://bugzilla.novell.com/show_bug.cgi?id=672491#c7
+
+//this
+//https://github.com/tonioni/WinUAE/blob/master/cdrom.cpp
+//references this
+//http://www.ross.net/crc/download/crc_v3.txt
+
+//this code in mednafen's lec.cpp calculates the reed solomon crap. port it to c# and then a/b test against it
+//Gf8_Q_Coeffs_Results_01
+
+//assorted other helpful urls
+//http://www.cs.utsa.edu/~wagner/laws/FFM.html
+//http://www.cs.cmu.edu/afs/cs.cmu.edu/project/pscico-guyb/realworld/www/reedsolomon/reed_solomon_codes.html
+//http://en.wikipedia.org/wiki/Finite_field_arithmetic
diff --git a/BizHawk.Emulation/Util.cs b/BizHawk.Emulation/Util.cs
index 08f8aa0270..b33f2ee497 100644
--- a/BizHawk.Emulation/Util.cs
+++ b/BizHawk.Emulation/Util.cs
@@ -1054,6 +1054,14 @@ namespace BizHawk
byte_8[j++] = (byte)(byte_8[i] + a);
}
}
+
+ public static uint reverse_32(uint v)
+ {
+ return (uint)((byte_8[v & 0xff] << 24) |
+ (byte_8[(v >> 8) & 0xff] << 16) |
+ (byte_8[(v >> 16) & 0xff] << 8) |
+ (byte_8[(v >> 24) & 0xff]));
+ }
}
///