Skip to content

Commit f5a02ed

Browse files
committed
Added partially decompiled AP module
1 parent 1357488 commit f5a02ed

File tree

1 file changed

+334
-0
lines changed

1 file changed

+334
-0
lines changed

docs/antipiracy.c

Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
2+
inline uint8_t bcd_to_binary(uint8_t val) {
3+
return (val >> 4) * 10 + (val & 0xF);
4+
}
5+
6+
inline uint8_t binary_to_bcd(uint8_t val) {
7+
return (val / 10) << 4 | (val % 10);
8+
}
9+
10+
enum {
11+
CD_RET_TRAY_OPEN = -2,
12+
CD_RET_FAIL = -1,
13+
CD_RET_CONTINUE = 0,
14+
CD_RET_SUCCESS = 1
15+
};
16+
17+
volatile uint8_t * const CD_REGS = (volatile uint8_t *) 0x1F801800;
18+
19+
struct cd_operation_t {
20+
uint8_t command;
21+
uint8_t req_len;
22+
uint8_t reply_len;
23+
uint8_t expected_ints;
24+
};
25+
26+
enum {
27+
CD_OP_GET_STATUS = 0,
28+
CD_OP_GET_TN = 1,
29+
CD_OP_GET_TD = 2,
30+
CD_OP_SET_LOCATION = 3,
31+
CD_OP_SEEK_AUDIO = 4,
32+
CD_OP_SET_MODE = 5,
33+
CD_OP_INIT = 6,
34+
CD_OP_MUTE = 7,
35+
CD_OP_PLAY = 8,
36+
CD_OP_SUBFUNC_X = 9,
37+
CD_OP_SUBFUNC_Y = 10,
38+
CD_OP_PAUSE = 11,
39+
CD_OP_READ_TOC = 12,
40+
CD_OP_GET_ID = 13
41+
};
42+
43+
const struct cd_operation_t[] CD_OPERATIONS = {
44+
{ 0x01, 0x00, 0x01, 0x03 }, // CD_OP_GETSTAT
45+
{ 0x13, 0x00, 0x03, 0x03 }, // CD_OP_GET_TN
46+
{ 0x14, 0x01, 0x03, 0x03 }, // CD_OP_GET_TD
47+
{ 0x02, 0x03, 0x01, 0x03 }, // CD_OP_SET_LOCATION
48+
{ 0x16, 0x00, 0x01, 0x05 }, // CD_OP_SEEK_AUDIO
49+
{ 0x0E, 0x01, 0x01, 0x03 }, // CD_OP_SET_MODE
50+
{ 0x0A, 0x00, 0x01, 0x05 }, // CD_OP_INIT
51+
{ 0x0B, 0x00, 0x01, 0x03 }, // CD_OP_MUTE
52+
{ 0x03, 0x00, 0x01, 0x03 }, // CD_OP_PLAY
53+
{ 0x19, 0x01, 0x01, 0x03 }, // CD_OP_SUBFUNC_X
54+
{ 0x19, 0x01, 0x02, 0x03 }, // CD_OP_SUBFUNC_Y
55+
{ 0x09, 0x00, 0x01, 0x05 }, // CD_OP_PAUSE
56+
{ 0x1E, 0x00, 0x01, 0x05 }, // CD_OP_READ_TOC
57+
{ 0x1A, 0x00, 0x01, 0x05 } // CD_OP_GET_ID
58+
};
59+
60+
uint8_t cd_req_buffer[3];
61+
uint32_t cd_ackd_ints = 0;
62+
63+
void cd_start_op(int op) {
64+
// Clear all interrupts
65+
CD_REGS[0] = 0x01;
66+
CD_REGS[3] = 0x07;
67+
68+
// Waste some cycles
69+
for (int i = 0; i < 4; i++) {
70+
*((uint32_t *) 0) = i;
71+
}
72+
73+
// Disable interrupts for responses so we can check them synchronously
74+
CD_REGS[0] = 0x01;
75+
CD_REGS[2] = 0x18;
76+
77+
// Write the request bytes (if any)
78+
CD_REGS[0] = 0x00;
79+
for (int i = 0; i < CD_OPERATIONS[op].req_len; i++) {
80+
CD_REGS[2] = cd_req_buffer[i];
81+
}
82+
83+
// Start the operation
84+
CD_REGS[0] = 0x00;
85+
CD_REGS[1] = CD_OPERATIONS[op].command;
86+
}
87+
88+
int cd_check_op(int op) {
89+
// Check current interrupts
90+
CD_REGS[0] = 0x01;
91+
int curints = CD_REGS[3] & 7;
92+
int curints2 = CD_REGS[3] & 7;
93+
if (curints != curints2 || curints == 0) {
94+
return 0;
95+
}
96+
97+
// Shouldn't this be an OR?
98+
cd_ackd_ints += curlen;
99+
100+
// Acknowledge all of them
101+
CD_REGS[0] = 0x01;
102+
CD_REGS[3] = 0x07;
103+
104+
// Waste some cycles
105+
for (i = 0; i < 4; i++) {
106+
*((uint32_t *) 0) = i;
107+
}
108+
109+
// This is really bizarre, why a less than?
110+
if (cd_ackd_ints < CD_OPERATIONS[op].expected_ints) {
111+
return 0;
112+
}
113+
cd_ackd_ints = 0;
114+
115+
// An INT5 means a fail
116+
if (curints == 5) {
117+
// Read fail reason
118+
cd_reply_buf[0] = CD_REGS[1];
119+
cd_reply_buf[1] = CD_REGS[1];
120+
121+
// Restore all interrupts
122+
CD_REGS[0] = 0x01;
123+
CD_REGS[2] = 0x1F;
124+
125+
// Check the status byte, and if the lid is open then fail
126+
if (cd_reply_buf[0] & 0x10) {
127+
// Failed because of an open lid
128+
return CD_RET_TRAY_OPEN;
129+
}
130+
131+
// Unknown
132+
return CD_RET_FAIL;
133+
} else {
134+
// Read the reply
135+
for (int i = 0; i < CD_OPERATIONS[op].reply_len; i++) {
136+
cd_reply_buf[i] = CD_REGS[1];
137+
}
138+
139+
// Restore all interrupts
140+
CD_REGS[0] = 0x01;
141+
CD_REGS[2] = 0x1F;
142+
143+
// Check the status byte
144+
if (op != 0x0A && (cd_reply_buf[0] & 0x10) != 0) {
145+
// Failed because of an open lid
146+
return CD_RET_TRAY_OPEN;
147+
}
148+
149+
// Succeeded
150+
return CD_RET_SUCCESS;
151+
}
152+
}
153+
154+
int ap_current_step;
155+
int ap_track_count;
156+
uint8_t ap_center_mm, ap_center_ss;
157+
158+
void antipiracy_main(int blocking) {
159+
int retval = 0;
160+
int mm, ss, center;
161+
162+
do {
163+
switch (ap_current_step) {
164+
case 0:
165+
retval = 0;
166+
break;
167+
168+
case 1:
169+
cd_start_op(CD_OP_GET_TN);
170+
ap_cur_step = 2;
171+
retval = 1;
172+
break;
173+
174+
case 2:
175+
switch (cd_read_reply(CD_OP_GET_TN)) {
176+
case CD_RET_FAIL:
177+
cd_start_op(CD_OP_GET_TN);
178+
break;
179+
180+
case CD_RET_TRAY_OPEN:
181+
cd_start_op(CD_OP_GET_STATUS);
182+
ap_cur_step = 17;
183+
break;
184+
185+
case CD_RET_SUCCESS:
186+
ap_track_count = cd_reply_buf[2];
187+
cd_start_op(CD_OP_INIT);
188+
ap_cur_step = 3;
189+
break;
190+
}
191+
192+
retval = 2;
193+
break;
194+
195+
case 3:
196+
switch (cd_read_reply(CD_OP_INIT)) {
197+
case CD_RET_FAIL:
198+
ap_cur_step = 1;
199+
break;
200+
201+
case CD_RET_TRAY_OPEN:
202+
cd_start_op(CD_OP_GET_STATUS);
203+
ap_cur_step = 17;
204+
break;
205+
206+
case CD_RET_SUCCESS:
207+
// Request end of first track
208+
cd_req_buffer[0] = ap_track_count < 2 ? 0 : 2;
209+
cd_start_op(CD_OP_GET_TD);
210+
ap_cur_step = 4;
211+
break;
212+
}
213+
214+
retval = 3;
215+
break;
216+
217+
case 4:
218+
switch (cd_read_reply(CD_OP_GET_TD)) {
219+
case CD_RET_FAIL:
220+
ap_cur_step = 1;
221+
break;
222+
223+
case CD_RET_TRAY_OPEN:
224+
cd_start_op(CD_OP_GET_STATUS);
225+
ap_cur_step = 17;
226+
break;
227+
228+
case CD_RET_SUCCESS:
229+
// Calculate center of data track
230+
mm = bcd_to_binary(cd_reply_buf[1]);
231+
ss = bcd_to_binary(cd_reply_buf[2]);
232+
center = (60 * mm + ss) / 2;
233+
234+
// Convert back into minutes and seconds
235+
ap_center_mm = binary_to_bcd(center / 60);
236+
ap_center_ss = binary_to_bcd(center % 60);
237+
238+
cd_start_op(CD_OP_READ_TOC);
239+
ap_cur_step = 5;
240+
break;
241+
}
242+
243+
retval = 7;
244+
break;
245+
246+
case 5:
247+
retval = cd_read_reply(CD_OP_READ_TOC);
248+
249+
switch (retval) {
250+
case CD_RET_FAIL:
251+
if ((cd_reply_buf[0] & 1) == 0) {
252+
ap_cur_step = 1;
253+
} else if ((cd_reply_buf[1] & 0x40) != 0) {
254+
cd_req_buffer[0] = ap_center_mm;
255+
cd_req_buffer[1] = ap_center_ss;
256+
cd_req_buffer[2] = 0;
257+
cd_start_op(CD_OP_SET_LOCATION);
258+
ap_cur_step = 7;
259+
retval = 5;
260+
}
261+
break;
262+
263+
case CD_RET_TRAY_OPEN:
264+
cd_start_op(CD_OP_GET_STATUS);
265+
ap_cur_step = 17;
266+
retval = 5;
267+
break;
268+
269+
case CD_RET_SUCCESS:
270+
cd_start_op(CD_OP_GET_ID);
271+
ap_cur_step = 7;
272+
retval = 5;
273+
break;
274+
275+
default:
276+
retval = 5;
277+
}
278+
break;
279+
280+
case 6:
281+
retval = cd_read_reply(CD_OP_GET_ID);
282+
283+
switch (retval) {
284+
case CD_RET_FAIL:
285+
antipiracy_triggered();
286+
break;
287+
288+
case CD_RET_TRAY_OPEN:
289+
cd_start_op(CD_OP_GET_STATUS);
290+
ap_cur_step = 17;
291+
retval = 6;
292+
break;
293+
294+
case CD_RET_SUCCESS:
295+
cd_req_buffer[0] = ap_center_mm;
296+
cd_req_buffer[1] = ap_center_ss;
297+
cd_req_buffer[2] = 0;
298+
cd_start_op(CD_OP_SET_LOCATION);
299+
ap_cur_step = 7;
300+
retval = 6;
301+
break;
302+
303+
default:
304+
retval = 6;
305+
}
306+
307+
case 7:
308+
retval = cd_read_reply(CD_OP_SET_LOCATION);
309+
310+
switch (retval) {
311+
case CD_RET_FAIL:
312+
ap_cur_step = 1;
313+
break;
314+
315+
case CD_RET_TRAY_OPEN:
316+
cd_start_op(CD_OP_GET_STATUS);
317+
ap_cur_step = 17;
318+
retval = 7;
319+
break;
320+
321+
case CD_RET_SUCCESS:
322+
cd_req_buf[0] = 1;
323+
cd_start_op(CD_OP_SET_MODE);
324+
ap_cur_step = 8;
325+
retval = 7;
326+
break;
327+
328+
default:
329+
retval = 7;
330+
}
331+
} while (blocking && retval != 0);
332+
333+
return retval;
334+
}

0 commit comments

Comments
 (0)