From 2ff12a9e3ac5cf474ae78377225bde25f6acb057 Mon Sep 17 00:00:00 2001 From: zeromus Date: Thu, 15 Nov 2012 08:03:23 +0000 Subject: [PATCH] add homemade cd-rom ECC/EDC code --- BizHawk.Emulation/BizHawk.Emulation.csproj | 1 + BizHawk.Emulation/Database/CRC32.cs | 5 +- BizHawk.Emulation/DiscSystem/Disc.cs | 17 +- BizHawk.Emulation/DiscSystem/ECM.cs | 384 ++++++++++++++++---- BizHawk.Emulation/DiscSystem/GPL_ECM.cs | 116 ++++++ BizHawk.Emulation/DiscSystem/docs/notes.txt | 35 ++ BizHawk.Emulation/Util.cs | 8 + 7 files changed, 483 insertions(+), 83 deletions(-) create mode 100644 BizHawk.Emulation/DiscSystem/GPL_ECM.cs create mode 100644 BizHawk.Emulation/DiscSystem/docs/notes.txt 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])); + } } ///