Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/psx/mednadisc/cdrom/CDUtility.h
2 views
1
#ifndef __MDFN_CDROM_CDUTILITY_H
2
#define __MDFN_CDROM_CDUTILITY_H
3
4
namespace CDUtility
5
{
6
// Call once at app startup before creating any threads that could potentially cause re-entrancy to these functions.
7
// It will also be called automatically if needed for the first time a function in this namespace that requires
8
// the initialization function to be called is called, for potential
9
// usage in constructors of statically-declared objects.
10
void CDUtility_Init(void);
11
12
// Quick definitions here:
13
//
14
// ABA - Absolute block address, synonymous to absolute MSF
15
// aba = (m_a * 60 * 75) + (s_a * 75) + f_a
16
//
17
// LBA - Logical block address(related: data CDs are required to have a pregap of 2 seconds, IE 150 frames/sectors)
18
// lba = aba - 150
19
20
21
enum
22
{
23
ADR_NOQINFO = 0x00,
24
ADR_CURPOS = 0x01,
25
ADR_MCN = 0x02,
26
ADR_ISRC = 0x03
27
};
28
29
30
struct TOC_Track
31
{
32
uint8 adr;
33
uint8 control;
34
uint32 lba;
35
bool valid; // valid/present; oh CD-i...
36
};
37
38
// SubQ control field flags.
39
enum
40
{
41
SUBQ_CTRLF_PRE = 0x01, // With 50/15us pre-emphasis.
42
SUBQ_CTRLF_DCP = 0x02, // Digital copy permitted.
43
SUBQ_CTRLF_DATA = 0x04, // Data track.
44
SUBQ_CTRLF_4CH = 0x08, // 4-channel CD-DA.
45
};
46
47
enum
48
{
49
DISC_TYPE_CDDA_OR_M1 = 0x00,
50
DISC_TYPE_CD_I = 0x10,
51
DISC_TYPE_CD_XA = 0x20
52
};
53
54
struct TOC
55
{
56
INLINE TOC()
57
{
58
Clear();
59
}
60
61
INLINE void Clear(void)
62
{
63
first_track = last_track = 0;
64
disc_type = 0;
65
66
memset(tracks, 0, sizeof(tracks)); // FIXME if we change TOC_Track to non-POD type.
67
}
68
69
INLINE int FindTrackByLBA(uint32 LBA) const
70
{
71
int32 lvt = 0;
72
73
for(int32 track = 1; track <= 100; track++)
74
{
75
if(!tracks[track].valid)
76
continue;
77
78
if(LBA < tracks[track].lba)
79
break;
80
81
lvt = track;
82
}
83
84
return(lvt);
85
}
86
87
uint8 first_track;
88
uint8 last_track;
89
uint8 disc_type;
90
TOC_Track tracks[100 + 1]; // [0] is unused, [100] is for the leadout track.
91
};
92
93
//
94
// Address conversion functions.
95
//
96
static INLINE uint32 AMSF_to_ABA(int32 m_a, int32 s_a, int32 f_a)
97
{
98
return(f_a + 75 * s_a + 75 * 60 * m_a);
99
}
100
101
static INLINE void ABA_to_AMSF(uint32 aba, uint8 *m_a, uint8 *s_a, uint8 *f_a)
102
{
103
*m_a = aba / 75 / 60;
104
*s_a = (aba - *m_a * 75 * 60) / 75;
105
*f_a = aba - (*m_a * 75 * 60) - (*s_a * 75);
106
}
107
108
static INLINE int32 ABA_to_LBA(uint32 aba)
109
{
110
return(aba - 150);
111
}
112
113
static INLINE uint32 LBA_to_ABA(int32 lba)
114
{
115
return(lba + 150);
116
}
117
118
static INLINE int32 AMSF_to_LBA(uint8 m_a, uint8 s_a, uint8 f_a)
119
{
120
return(ABA_to_LBA(AMSF_to_ABA(m_a, s_a, f_a)));
121
}
122
123
static INLINE void LBA_to_AMSF(int32 lba, uint8 *m_a, uint8 *s_a, uint8 *f_a)
124
{
125
ABA_to_AMSF(LBA_to_ABA(lba), m_a, s_a, f_a);
126
}
127
128
//
129
// BCD conversion functions
130
//
131
static INLINE bool BCD_is_valid(uint8 bcd_number)
132
{
133
if((bcd_number & 0xF0) >= 0xA0)
134
return(false);
135
136
if((bcd_number & 0x0F) >= 0x0A)
137
return(false);
138
139
return(true);
140
}
141
142
static INLINE uint8 BCD_to_U8(uint8 bcd_number)
143
{
144
return( ((bcd_number >> 4) * 10) + (bcd_number & 0x0F) );
145
}
146
147
static INLINE uint8 U8_to_BCD(uint8 num)
148
{
149
return( ((num / 10) << 4) + (num % 10) );
150
}
151
152
// should always perform the conversion, even if the bcd number is invalid.
153
static INLINE bool BCD_to_U8_check(uint8 bcd_number, uint8 *out_number)
154
{
155
*out_number = BCD_to_U8(bcd_number);
156
157
if(!BCD_is_valid(bcd_number))
158
return(false);
159
160
return(true);
161
}
162
163
//
164
// Sector data encoding functions(to full 2352 bytes raw sector).
165
//
166
// sector_data must be able to contain at least 2352 bytes.
167
void encode_mode0_sector(uint32 aba, uint8 *sector_data);
168
void encode_mode1_sector(uint32 aba, uint8 *sector_data); // 2048 bytes of user data at offset 16
169
void encode_mode2_sector(uint32 aba, uint8 *sector_data); // 2336 bytes of user data at offset 16
170
void encode_mode2_form1_sector(uint32 aba, uint8 *sector_data); // 2048+8 bytes of user data at offset 16
171
void encode_mode2_form2_sector(uint32 aba, uint8 *sector_data); // 2324+8 bytes of user data at offset 16
172
173
174
// User data area pre-pause(MSF 00:00:00 through 00:01:74), lba -150 through -1
175
// out_buf must be able to contain 2352+96 bytes.
176
// "mode" is not used if the area is to be encoded as audio.
177
// pass 0xFF for "mode" for "don't know", and to make guess based on the TOC.
178
void synth_udapp_sector_lba(uint8 mode, const TOC& toc, const int32 lba, int32 lba_subq_relative_offs, uint8* out_buf);
179
void subpw_synth_udapp_lba(const TOC& toc, const int32 lba, const int32 lba_subq_relative_offs, uint8* SubPWBuf);
180
181
// out_buf must be able to contain 2352+96 bytes.
182
// "mode" is not used if the area is to be encoded as audio.
183
// pass 0xFF for "mode" for "don't know", and to make guess based on the TOC.
184
void synth_leadout_sector_lba(uint8 mode, const TOC& toc, const int32 lba, uint8* out_buf);
185
void subpw_synth_leadout_lba(const TOC& toc, const int32 lba, uint8* SubPWBuf);
186
187
188
//
189
// User data error detection and correction
190
//
191
192
// Check EDC of a mode 1 or mode 2 form 1 sector.
193
// Returns "true" if checksum is ok(matches).
194
// Returns "false" if checksum mismatch.
195
// sector_data should contain 2352 bytes of raw sector data.
196
bool edc_check(const uint8 *sector_data, bool xa);
197
198
// Check EDC and L-EC data of a mode 1 or mode 2 form 1 sector, and correct bit errors if any exist.
199
// Returns "true" if errors weren't detected, or they were corrected succesfully.
200
// Returns "false" if errors couldn't be corrected.
201
// sector_data should contain 2352 bytes of raw sector data.
202
bool edc_lec_check_and_correct(uint8 *sector_data, bool xa);
203
204
//
205
// Subchannel(Q in particular) functions
206
//
207
208
// Returns false on checksum mismatch, true on match.
209
bool subq_check_checksum(const uint8 *subq_buf);
210
211
// Calculates the checksum of Q subchannel data(not including the checksum bytes of course ;)) from subq_buf, and stores it into the appropriate position
212
// in subq_buf.
213
void subq_generate_checksum(uint8 *subq_buf);
214
215
// Deinterleaves 12 bytes of subchannel Q data from 96 bytes of interleaved subchannel PW data.
216
void subq_deinterleave(const uint8 *subpw_buf, uint8 *subq_buf);
217
218
// Deinterleaves 96 bytes of subchannel P-W data from 96 bytes of interleaved subchannel PW data.
219
void subpw_deinterleave(const uint8 *in_buf, uint8 *out_buf);
220
221
// Interleaves 96 bytes of subchannel P-W data from 96 bytes of uninterleaved subchannel PW data.
222
void subpw_interleave(const uint8 *in_buf, uint8 *out_buf);
223
224
// Extrapolates Q subchannel current position data from subq_input, with frame/sector delta position_delta, and writes to subq_output.
225
// Only valid for ADR_CURPOS.
226
// subq_input must pass subq_check_checksum().
227
// TODO
228
//void subq_extrapolate(const uint8 *subq_input, int32 position_delta, uint8 *subq_output);
229
230
// (De)Scrambles data sector.
231
void scrambleize_data_sector(uint8 *sector_data);
232
}
233
234
#endif
235
236