Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/psx/octoshock/cdrom/recover-raw.cpp
2 views
1
/* dvdisaster: Additional error correction for optical media.
2
* Copyright (C) 2004-2007 Carsten Gnoerlich.
3
* Project home page: http://www.dvdisaster.com
4
* Email: [email protected] -or- [email protected]
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
19
* or direct your browser at http://www.gnu.org.
20
*/
21
22
#include "dvdisaster.h"
23
24
static GaloisTables *gt = NULL; /* for L-EC Reed-Solomon */
25
static ReedSolomonTables *rt = NULL;
26
27
bool Init_LEC_Correct(void)
28
{
29
gt = CreateGaloisTables(0x11d);
30
rt = CreateReedSolomonTables(gt, 0, 1, 10);
31
32
return(1);
33
}
34
35
void Kill_LEC_Correct(void)
36
{
37
FreeGaloisTables(gt);
38
FreeReedSolomonTables(rt);
39
}
40
41
/***
42
*** CD level CRC calculation
43
***/
44
45
/*
46
* Test raw sector against its 32bit CRC.
47
* Returns TRUE if frame is good.
48
*/
49
50
int CheckEDC(const unsigned char *cd_frame, bool xa_mode)
51
{
52
unsigned int expected_crc, real_crc;
53
unsigned int crc_base = xa_mode ? 2072 : 2064;
54
55
expected_crc = cd_frame[crc_base + 0] << 0;
56
expected_crc |= cd_frame[crc_base + 1] << 8;
57
expected_crc |= cd_frame[crc_base + 2] << 16;
58
expected_crc |= cd_frame[crc_base + 3] << 24;
59
60
if(xa_mode)
61
real_crc = EDCCrc32(cd_frame+16, 2056);
62
else
63
real_crc = EDCCrc32(cd_frame, 2064);
64
65
if(expected_crc == real_crc)
66
return(1);
67
else
68
{
69
//printf("Bad EDC CRC: Calculated: %08x, Recorded: %08x\n", real_crc, expected_crc);
70
return(0);
71
}
72
}
73
74
/***
75
*** A very simple L-EC error correction.
76
***
77
* Perform just one pass over the Q and P vectors to see if everything
78
* is okay respectively correct minor errors. This is pretty much the
79
* same stuff the drive is supposed to do in the final L-EC stage.
80
*/
81
82
static int simple_lec(unsigned char *frame)
83
{
84
unsigned char byte_state[2352];
85
unsigned char p_vector[P_VECTOR_SIZE];
86
unsigned char q_vector[Q_VECTOR_SIZE];
87
unsigned char p_state[P_VECTOR_SIZE];
88
int erasures[Q_VECTOR_SIZE], erasure_count;
89
int ignore[2];
90
int p_failures, q_failures;
91
int p_corrected, q_corrected;
92
int p,q;
93
94
/* Setup */
95
96
memset(byte_state, 0, 2352);
97
98
p_failures = q_failures = 0;
99
p_corrected = q_corrected = 0;
100
101
/* Perform Q-Parity error correction */
102
103
for(q=0; q<N_Q_VECTORS; q++)
104
{ int err;
105
106
/* We have no erasure information for Q vectors */
107
108
GetQVector(frame, q_vector, q);
109
err = DecodePQ(rt, q_vector, Q_PADDING, ignore, 0);
110
111
/* See what we've got */
112
113
if(err < 0) /* Uncorrectable. Mark bytes are erasure. */
114
{ q_failures++;
115
FillQVector(byte_state, 1, q);
116
}
117
else /* Correctable */
118
{ if(err == 1 || err == 2) /* Store back corrected vector */
119
{ SetQVector(frame, q_vector, q);
120
q_corrected++;
121
}
122
}
123
}
124
125
/* Perform P-Parity error correction */
126
127
for(p=0; p<N_P_VECTORS; p++)
128
{ int err,i;
129
130
/* Try error correction without erasure information */
131
132
GetPVector(frame, p_vector, p);
133
err = DecodePQ(rt, p_vector, P_PADDING, ignore, 0);
134
135
/* If unsuccessful, try again using erasures.
136
Erasure information is uncertain, so try this last. */
137
138
if(err < 0 || err > 2)
139
{ GetPVector(byte_state, p_state, p);
140
erasure_count = 0;
141
142
for(i=0; i<P_VECTOR_SIZE; i++)
143
if(p_state[i])
144
erasures[erasure_count++] = i;
145
146
if(erasure_count > 0 && erasure_count <= 2)
147
{ GetPVector(frame, p_vector, p);
148
err = DecodePQ(rt, p_vector, P_PADDING, erasures, erasure_count);
149
}
150
}
151
152
/* See what we've got */
153
154
if(err < 0) /* Uncorrectable. */
155
{ p_failures++;
156
}
157
else /* Correctable. */
158
{ if(err == 1 || err == 2) /* Store back corrected vector */
159
{ SetPVector(frame, p_vector, p);
160
p_corrected++;
161
}
162
}
163
}
164
165
/* Sum up */
166
167
if(q_failures || p_failures || q_corrected || p_corrected)
168
{
169
return 1;
170
}
171
172
return 0;
173
}
174
175
/***
176
*** Validate CD raw sector
177
***/
178
179
int ValidateRawSector(unsigned char *frame, bool xaMode)
180
{
181
int lec_did_sth = FALSE_0;
182
183
/* Do simple L-EC.
184
It seems that drives stop their internal L-EC as soon as the
185
EDC is okay, so we may see uncorrected errors in the parity bytes.
186
Since we are also interested in the user data only and doing the
187
L-EC is expensive, we skip our L-EC as well when the EDC is fine. */
188
189
if(!CheckEDC(frame, xaMode))
190
{
191
lec_did_sth = simple_lec(frame);
192
}
193
/* Test internal sector checksum again */
194
195
if(!CheckEDC(frame, xaMode))
196
{
197
/* EDC failure in RAW sector */
198
return FALSE_0;
199
}
200
201
return TRUE_1;
202
}
203
204
205