/* dvdisaster: Additional error correction for optical media.1* Copyright (C) 2004-2007 Carsten Gnoerlich.2* Project home page: http://www.dvdisaster.com3* Email: [email protected] -or- [email protected]4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,18* or direct your browser at http://www.gnu.org.19*/2021#include "dvdisaster.h"2223static GaloisTables *gt = NULL; /* for L-EC Reed-Solomon */24static ReedSolomonTables *rt = NULL;2526bool Init_LEC_Correct(void)27{28gt = CreateGaloisTables(0x11d);29rt = CreateReedSolomonTables(gt, 0, 1, 10);3031return(1);32}3334void Kill_LEC_Correct(void)35{36FreeGaloisTables(gt);37FreeReedSolomonTables(rt);38}3940/***41*** CD level CRC calculation42***/4344/*45* Test raw sector against its 32bit CRC.46* Returns TRUE if frame is good.47*/4849int CheckEDC(const unsigned char *cd_frame, bool xa_mode)50{51unsigned int expected_crc, real_crc;52unsigned int crc_base = xa_mode ? 2072 : 2064;5354expected_crc = cd_frame[crc_base + 0] << 0;55expected_crc |= cd_frame[crc_base + 1] << 8;56expected_crc |= cd_frame[crc_base + 2] << 16;57expected_crc |= cd_frame[crc_base + 3] << 24;5859if(xa_mode)60real_crc = EDCCrc32(cd_frame+16, 2056);61else62real_crc = EDCCrc32(cd_frame, 2064);6364if(expected_crc == real_crc)65return(1);66else67{68//printf("Bad EDC CRC: Calculated: %08x, Recorded: %08x\n", real_crc, expected_crc);69return(0);70}71}7273/***74*** A very simple L-EC error correction.75***76* Perform just one pass over the Q and P vectors to see if everything77* is okay respectively correct minor errors. This is pretty much the78* same stuff the drive is supposed to do in the final L-EC stage.79*/8081static int simple_lec(unsigned char *frame)82{83unsigned char byte_state[2352];84unsigned char p_vector[P_VECTOR_SIZE];85unsigned char q_vector[Q_VECTOR_SIZE];86unsigned char p_state[P_VECTOR_SIZE];87int erasures[Q_VECTOR_SIZE], erasure_count;88int ignore[2];89int p_failures, q_failures;90int p_corrected, q_corrected;91int p,q;9293/* Setup */9495memset(byte_state, 0, 2352);9697p_failures = q_failures = 0;98p_corrected = q_corrected = 0;99100/* Perform Q-Parity error correction */101102for(q=0; q<N_Q_VECTORS; q++)103{ int err;104105/* We have no erasure information for Q vectors */106107GetQVector(frame, q_vector, q);108err = DecodePQ(rt, q_vector, Q_PADDING, ignore, 0);109110/* See what we've got */111112if(err < 0) /* Uncorrectable. Mark bytes are erasure. */113{ q_failures++;114FillQVector(byte_state, 1, q);115}116else /* Correctable */117{ if(err == 1 || err == 2) /* Store back corrected vector */118{ SetQVector(frame, q_vector, q);119q_corrected++;120}121}122}123124/* Perform P-Parity error correction */125126for(p=0; p<N_P_VECTORS; p++)127{ int err,i;128129/* Try error correction without erasure information */130131GetPVector(frame, p_vector, p);132err = DecodePQ(rt, p_vector, P_PADDING, ignore, 0);133134/* If unsuccessful, try again using erasures.135Erasure information is uncertain, so try this last. */136137if(err < 0 || err > 2)138{ GetPVector(byte_state, p_state, p);139erasure_count = 0;140141for(i=0; i<P_VECTOR_SIZE; i++)142if(p_state[i])143erasures[erasure_count++] = i;144145if(erasure_count > 0 && erasure_count <= 2)146{ GetPVector(frame, p_vector, p);147err = DecodePQ(rt, p_vector, P_PADDING, erasures, erasure_count);148}149}150151/* See what we've got */152153if(err < 0) /* Uncorrectable. */154{ p_failures++;155}156else /* Correctable. */157{ if(err == 1 || err == 2) /* Store back corrected vector */158{ SetPVector(frame, p_vector, p);159p_corrected++;160}161}162}163164/* Sum up */165166if(q_failures || p_failures || q_corrected || p_corrected)167{168return 1;169}170171return 0;172}173174/***175*** Validate CD raw sector176***/177178int ValidateRawSector(unsigned char *frame, bool xaMode)179{180int lec_did_sth = FALSE_0;181182/* Do simple L-EC.183It seems that drives stop their internal L-EC as soon as the184EDC is okay, so we may see uncorrected errors in the parity bytes.185Since we are also interested in the user data only and doing the186L-EC is expensive, we skip our L-EC as well when the EDC is fine. */187188if(!CheckEDC(frame, xaMode))189{190lec_did_sth = simple_lec(frame);191}192/* Test internal sector checksum again */193194if(!CheckEDC(frame, xaMode))195{196/* EDC failure in RAW sector */197return FALSE_0;198}199200return TRUE_1;201}202203204205