public int Read_2352(byte[] buffer, int offset) { //user data int read = Blob.BaseBlob.Read(Offset, buffer, offset + 16, 2048); //if we read the 2048 physical bytes OK, then return the complete sector if (read == 2048 && has_extra_data) { Buffer.BlockCopy(extra_data, 0, buffer, offset, 16); Buffer.BlockCopy(extra_data, 16, buffer, offset + 2064, 4 + 8 + 172 + 104); return(2352); } //sync buffer[offset + 0] = 0x00; buffer[offset + 1] = 0xFF; buffer[offset + 2] = 0xFF; buffer[offset + 3] = 0xFF; buffer[offset + 4] = 0xFF; buffer[offset + 5] = 0xFF; buffer[offset + 6] = 0xFF; buffer[offset + 7] = 0xFF; buffer[offset + 8] = 0xFF; buffer[offset + 9] = 0xFF; buffer[offset + 10] = 0xFF; buffer[offset + 11] = 0x00; //sector address buffer[offset + 12] = bcd_aba_min; buffer[offset + 13] = bcd_aba_sec; buffer[offset + 14] = bcd_aba_frac; //mode 1 buffer[offset + 15] = 1; //calculate EDC and poke into the sector uint edc = ECM.EDC_Calc(buffer, offset, 2064); ECM.PokeUint(buffer, 2064, edc); //intermediate for (int i = 0; i < 8; i++) { buffer[offset + 2068 + i] = 0; } //ECC 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) { extra_data = new byte[16 + 4 + 8 + 172 + 104]; Buffer.BlockCopy(buffer, 0, extra_data, 0, 16); Buffer.BlockCopy(buffer, 2064, extra_data, 16, 4 + 8 + 172 + 104); has_extra_data = true; return(2352); } //otherwise, return a smaller value to indicate an error else { return(read); } }
void Reconstruct(byte[] secbuf, int type) { //sync secbuf[0] = 0; for (int i = 1; i <= 10; i++) { secbuf[i] = 0xFF; } secbuf[11] = 0x00; //misc stuff switch (type) { case 1: //mode 1 secbuf[15] = 0x01; //reserved for (int i = 0x814; i <= 0x81B; i++) { secbuf[i] = 0x00; } break; case 2: case 3: //mode 2 secbuf[15] = 0x02; //flags - apparently CD XA specifies two copies of these 4bytes of flags. ECM didnt store the first copy; so we clone the second copy which was stored down to the spot for the first copy. secbuf[0x10] = secbuf[0x14]; secbuf[0x11] = secbuf[0x15]; secbuf[0x12] = secbuf[0x16]; secbuf[0x13] = secbuf[0x17]; break; } //edc switch (type) { case 1: ECM.PokeUint(secbuf, 0x810, ECM.EDC_Calc(secbuf, 0, 0x810)); break; case 2: ECM.PokeUint(secbuf, 0x818, ECM.EDC_Calc(secbuf, 16, 0x808)); break; case 3: ECM.PokeUint(secbuf, 0x92C, ECM.EDC_Calc(secbuf, 16, 0x91C)); break; } //ecc switch (type) { case 1: ECM.ECC_Populate(secbuf, 0, secbuf, 0, false); break; case 2: ECM.ECC_Populate(secbuf, 0, secbuf, 0, true); break; } }
/// <summary> /// Synthesizes the complete ECM data (EDC + ECC) for a Mode 1 data sector (and puts it in place) /// Make sure everything else in the sector userdata is done before calling this /// </summary> public static void ECM_Mode1(byte[] buf2352, int offset, int LBA) { //EDC uint edc = ECM.EDC_Calc(buf2352, offset, 2064); ECM.PokeUint(buf2352, offset + 2064, edc); //reserved, zero for (int i = 0; i < 8; i++) { buf2352[offset + 2068 + i] = 0; } //ECC ECM.ECC_Populate(buf2352, offset, buf2352, offset, false); }
/// <summary> /// Synthesizes the EDC checksum for a Mode 2 Form 2 data sector (and puts it in place) /// </summary> public static void EDC_Mode2_Form2(byte[] buf2352, int offset) { uint edc = ECM.EDC_Calc(buf2352, offset + 16, 2324 + 8); ECM.PokeUint(buf2352, offset + 2348, edc); }
/// <summary> /// Synthesizes the EDC checksum for a Mode 2 Form 1 data sector (and puts it in place) /// </summary> public static void EDC_Mode2_Form1(byte[] buf2352, int offset) { uint edc = ECM.EDC_Calc(buf2352, offset + 16, 2048 + 8); ECM.PokeUint(buf2352, offset + 2072, edc); }