Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/psx/octoshock/cdrom/CDUtility.h
2 views
1
#ifndef __MDFN_CDROM_CDUTILITY_H
2
#define __MDFN_CDROM_CDUTILITY_H
3
4
#include <string.h>
5
6
namespace CDUtility
7
{
8
// Call once at app startup before creating any threads that could potentially cause re-entrancy to these functions.
9
// It will also be called automatically if needed for the first time a function in this namespace that requires
10
// the initialization function to be called is called, for potential
11
// usage in constructors of statically-declared objects.
12
void CDUtility_Init(void);
13
14
// Quick definitions here:
15
//
16
// ABA - Absolute block address, synonymous to absolute MSF
17
// aba = (m_a * 60 * 75) + (s_a * 75) + f_a
18
//
19
// LBA - Logical block address(related: data CDs are required to have a pregap of 2 seconds, IE 150 frames/sectors)
20
// lba = aba - 150
21
22
23
enum
24
{
25
ADR_NOQINFO = 0x00,
26
ADR_CURPOS = 0x01,
27
ADR_MCN = 0x02,
28
ADR_ISRC = 0x03
29
};
30
31
32
struct TOC_Track
33
{
34
uint8 adr;
35
uint8 control;
36
uint32 lba;
37
};
38
39
// SubQ control field flags.
40
enum
41
{
42
SUBQ_CTRLF_PRE = 0x01, // With 50/15us pre-emphasis.
43
SUBQ_CTRLF_DCP = 0x02, // Digital copy permitted.
44
SUBQ_CTRLF_DATA = 0x04, // Data track.
45
SUBQ_CTRLF_4CH = 0x08, // 4-channel CD-DA.
46
};
47
48
enum
49
{
50
DISC_TYPE_CDDA_OR_M1 = 0x00,
51
DISC_TYPE_CD_I = 0x10,
52
DISC_TYPE_CD_XA = 0x20
53
};
54
55
struct TOC
56
{
57
INLINE TOC()
58
{
59
Clear();
60
}
61
62
INLINE void Clear(void)
63
{
64
first_track = last_track = 0;
65
disc_type = 0;
66
67
memset(tracks, 0, sizeof(tracks)); // FIXME if we change TOC_Track to non-POD type.
68
}
69
70
INLINE int FindTrackByLBA(uint32 LBA)
71
{
72
for(int32 track = first_track; track <= (last_track + 1); track++)
73
{
74
if(track == (last_track + 1))
75
{
76
if(LBA < tracks[100].lba)
77
return(track - 1);
78
}
79
else
80
{
81
if(LBA < tracks[track].lba)
82
return(track - 1);
83
}
84
}
85
return(0);
86
}
87
88
uint8 first_track;
89
uint8 last_track;
90
uint8 disc_type;
91
TOC_Track tracks[100 + 1]; // [0] is unused, [100] is for the leadout track.
92
// Also, for convenience, tracks[last_track + 1] will always refer
93
// to the leadout track(even if last_track < 99, IE the leadout track details are duplicated).
94
};
95
96
//
97
// Address conversion functions.
98
//
99
static INLINE uint32 AMSF_to_ABA(int32 m_a, int32 s_a, int32 f_a)
100
{
101
return(f_a + 75 * s_a + 75 * 60 * m_a);
102
}
103
104
static INLINE void ABA_to_AMSF(uint32 aba, uint8 *m_a, uint8 *s_a, uint8 *f_a)
105
{
106
*m_a = aba / 75 / 60;
107
*s_a = (aba - *m_a * 75 * 60) / 75;
108
*f_a = aba - (*m_a * 75 * 60) - (*s_a * 75);
109
}
110
111
static INLINE int32 ABA_to_LBA(uint32 aba)
112
{
113
return(aba - 150);
114
}
115
116
static INLINE uint32 LBA_to_ABA(int32 lba)
117
{
118
return(lba + 150);
119
}
120
121
static INLINE int32 AMSF_to_LBA(uint8 m_a, uint8 s_a, uint8 f_a)
122
{
123
return(ABA_to_LBA(AMSF_to_ABA(m_a, s_a, f_a)));
124
}
125
126
static INLINE void LBA_to_AMSF(int32 lba, uint8 *m_a, uint8 *s_a, uint8 *f_a)
127
{
128
ABA_to_AMSF(LBA_to_ABA(lba), m_a, s_a, f_a);
129
}
130
131
//
132
// BCD conversion functions
133
//
134
static INLINE bool BCD_is_valid(uint8 bcd_number)
135
{
136
if((bcd_number & 0xF0) >= 0xA0)
137
return(false);
138
139
if((bcd_number & 0x0F) >= 0x0A)
140
return(false);
141
142
return(true);
143
}
144
145
static INLINE uint8 BCD_to_U8(uint8 bcd_number)
146
{
147
return( ((bcd_number >> 4) * 10) + (bcd_number & 0x0F) );
148
}
149
150
static INLINE uint8 U8_to_BCD(uint8 num)
151
{
152
return( ((num / 10) << 4) + (num % 10) );
153
}
154
155
// Check EDC and L-EC data of a mode 1 or mode 2 form 1 sector, and correct bit errors if any exist.
156
// Returns "true" if errors weren't detected, or they were corrected succesfully.
157
// Returns "false" if errors couldn't be corrected.
158
// sector_data should contain 2352 bytes of raw sector data.
159
bool edc_lec_check_and_correct(uint8 *sector_data, bool xa);
160
161
// Returns false on checksum mismatch, true on match.
162
bool subq_check_checksum(const uint8 *subq_buf);
163
164
// Calculates the checksum of Q subchannel data(not including the checksum bytes of course ;)) from subq_buf, and stores it into the appropriate position
165
// in subq_buf.
166
void subq_generate_checksum(uint8 *subq_buf);
167
168
// Deinterleaves 96 bytes of subchannel P-W data from 96 bytes of interleaved subchannel PW data.
169
void subpw_deinterleave(const uint8 *in_buf, uint8 *out_buf);
170
171
// Interleaves 96 bytes of subchannel P-W data from 96 bytes of uninterleaved subchannel PW data.
172
void subpw_interleave(const uint8 *in_buf, uint8 *out_buf);
173
174
}
175
176
#endif
177
178