This repository has been archived by the owner on May 17, 2021. It is now read-only.
forked from higan-emu/higan
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathrspc.hpp
128 lines (118 loc) · 3.6 KB
/
rspc.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#pragma once
//reed-solomon product code
namespace nall::CD::RSPC {
inline auto encodeP(array_view<uint8_t> input, array_span<uint8_t> parity) -> bool {
ReedSolomon<26,24> s;
uint lo = 0, hi = 43 * 2;
for(uint x : range(43)) {
for(uint w : range(2)) { //16-bit words
uint z = 0;
for(uint y : range(24)) {
s[z++] = input[(y * 43 + x) * 2 + w];
}
s.generateParity();
parity[lo++] = s[z++];
parity[hi++] = s[z++];
}
}
return true;
}
inline auto encodeQ(array_view<uint8_t> input, array_span<uint8_t> parity) -> bool {
ReedSolomon<45,43> s;
uint lo = 0, hi = 26 * 2;
for(uint y : range(26)) {
for(uint w : range(2)) {
uint z = 0;
for(uint x : range(43)) {
s[z++] = input[((x * 44 + y * 43) * 2 + w) % (26 * 43 * 2)];
}
s.generateParity();
parity[lo++] = s[z++];
parity[hi++] = s[z++];
}
}
return true;
}
inline auto encodeMode1(array_span<uint8_t> sector) -> bool {
if(sector.size() != 2352) return false;
if(!encodeP({sector + 12, 2064}, {sector + 2076, 172})) return false;
if(!encodeQ({sector + 12, 2236}, {sector + 2248, 104})) return false;
return true;
}
//
inline auto decodeP(array_span<uint8_t> input, array_span<uint8_t> parity) -> int {
bool success = false;
bool failure = false;
ReedSolomon<26,24> s;
uint lo = 0, hi = 43 * 2;
for(uint x : range(43)) {
for(uint w : range(2)) {
uint z = 0;
for(uint y : range(24)) {
s[z++] = input[(y * 43 + x) * 2 + w];
}
s[z++] = parity[lo++];
s[z++] = parity[hi++];
auto count = s.correctErrors();
if(count < 0) {
failure = true;
}
if(count > 0) {
success = true;
z = 0;
for(uint y : range(24)) {
input[(y * 43 + x) * 2 + w] = s[z++];
}
parity[lo - 1] = s[z++];
parity[hi - 1] = s[z++];
}
}
}
if(!success && !failure) return 0; //no errors remaining
return success ? 1 : -1; //return success even if there are some failures
}
inline auto decodeQ(array_span<uint8_t> input, array_span<uint8_t> parity) -> int {
bool success = false;
bool failure = false;
ReedSolomon<45,43> s;
uint lo = 0, hi = 26 * 2;
for(uint y : range(26)) {
for(uint w : range(2)) {
uint z = 0;
for(uint x : range(43)) {
s[z++] = input[((x * 44 + y * 43) * 2 + w) % (26 * 43 * 2)];
}
s[z++] = parity[lo++];
s[z++] = parity[hi++];
auto count = s.correctErrors();
if(count < 0) {
failure = true;
}
if(count > 0) {
success = true;
z = 0;
for(uint x : range(43)) {
input[((x * 44 + y * 43) * 2 + w) % (26 * 43 * 2)] = s[z++];
}
parity[lo - 1] = s[z++];
parity[hi - 1] = s[z++];
}
}
}
if(!success && !failure) return 0;
return success ? 1 : -1;
}
inline auto decodeMode1(array_span<uint8_t> sector) -> bool {
if(sector.size() != 2352) return false;
//P corrections can allow Q corrections that previously failed to succeed, and vice versa.
//the more iterations, the more chances to correct errors, but the more computationally expensive it is.
//there must be a limit on the amount of retries, or this function may get stuck in an infinite loop.
for(uint attempt : range(4)) {
auto p = decodeP({sector + 12, 2064}, {sector + 2076, 172});
auto q = decodeQ({sector + 12, 2236}, {sector + 2248, 104});
if(p == 0 && q == 0) return true; //no errors remaining
if(p < 0 && q < 0) return false; //no more errors correctable
}
return false; //exhausted all retries with errors remaining
}
}