PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
spu.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "libspu2_internal.h"
12
13vu16 *_spu_RXX = (vu16 *)0xBF900000;
14u32 _spu_tsa[2] = {0u, 0u};
15u32 _spu_transMode = 0u;
16u32 _spu_inTransfer = 1u;
17SpuTransferCallbackProc _spu_transferCallback = NULL;
18SpuTransferCallbackProc _spu_AutoDMACallback = NULL;
19SpuIRQCallbackProc _spu_IRQCallback = NULL;
20static int g_DmaCoreIndex = 0;
21static int _spu_dma_mode = 0;
22static int _spu_transfer_startaddr = 0;
23static int _spu_transfer_time = 0;
24
25static int gMode;
26static int gWhichBuff;
27static u8 *gHostAddr;
28static int gBufferSize48;
29
30u16 _spu_RQ[16];
31
32static void _spu_FsetDelayW(int flag);
33static void _spu_FsetDelayR(int flag);
34
35int _spu_init(int flag)
36{
37 if ( !flag )
38 {
39 vu16 *v2;
40
41 *((vu32 *)0xBF8010F0) |= 0xB0000u;
42 v2 = &_spu_RXX[20 * _spu_core];
43 v2[944] = 0;
44 v2[945] = 0;
45 v2[1456] = 0;
46 v2[1457] = 0;
47#ifndef LIB_1300
48 // Added in OSDSND 110U
49 *((vu16 *)0xBF9007C0) = 0;
50 _spu_Fw1ts();
51 _spu_Fw1ts();
52 *((vu16 *)0xBF9007C0) = 0x8000;
53 _spu_Fw1ts();
54#endif
55 for ( _spu_core = 0; (unsigned int)_spu_core < 2; _spu_core += 1 )
56 {
57 vu16 *v7;
58 vu16 *v8;
59 unsigned int v9;
60 vu16 *v11;
61 vu16 *v12;
62 int v13;
63
64 _spu_transMode = 0;
65 _spu_tsa[_spu_core] = 0;
66#ifndef LIB_1300
67 // Added in OSDSND 110U
68 *(u16 *)((_spu_core << 10) + 0xbf9001b0) = 0;
69#endif
70 _spu_RXX[512 * _spu_core + 205] = 0;
71 _spu_Fw1ts();
72 _spu_Fw1ts();
73 v7 = &_spu_RXX[512 * _spu_core];
74 v7[205] = 0x8000;
75 v8 = &_spu_RXX[20 * _spu_core];
76 v8[944] = 0;
77 v8[945] = 0;
78 v9 = 1;
79 while ( (v7[418] & 0x7FF) != 0 )
80 {
81 if ( v9 >= 0xF01 )
82 {
83 printf("SPU:T/O [%s]\n", "wait (reset)");
84 break;
85 }
86 v9 += 1;
87 }
88 v11 = &_spu_RXX[20 * _spu_core];
89 v12 = &_spu_RXX[512 * _spu_core];
90 v11[946] = 0;
91 v11[947] = 0;
92 v12[210] = -1;
93 v12[211] = -1;
94 _spu_RXX[205] &= ~0x80u;
95 for ( v13 = 0; v13 < 10; v13 += 1 )
96 {
97 _spu_RQ[v13] = 0;
98 }
99 }
100 for ( _spu_core = 0; (unsigned int)_spu_core < 2; _spu_core += 1 )
101 {
102 vu16 *v17;
103 vu16 *v18;
104
105 v17 = &_spu_RXX[512 * _spu_core];
106 v17[192] = 0;
107 v17[193] = 0;
108 v17[194] = 0;
109 v17[195] = 0;
110 v18 = &_spu_RXX[20 * _spu_core];
111 v18[968] = 0;
112 v18[969] = 0;
113 v18[970] = 0;
114 v18[971] = 0;
115 }
116 }
117 _spu_core = 0;
118 SpuStopFreeRun();
119 _spu_inTransfer = 1;
120 _spu_transferCallback = 0;
121 _spu_IRQCallback = 0;
122 return 0;
123}
124
125int spu_do_set_DmaCoreIndex(int dma_core_index)
126{
127 int (*v1)(void *);
128
129 g_DmaCoreIndex = dma_core_index;
130 if ( dma_core_index )
131 {
132 _SpuDataCallback(_spu_FiAutoDMA);
133 v1 = _spu_FiDMA;
134 }
135 else
136 {
137 _SpuDataCallback(_spu_FiDMA);
138 v1 = _spu_FiAutoDMA;
139 }
140 _SpuAutoDMACallback(v1);
141 return g_DmaCoreIndex;
142}
143
144int spu_do_get_DmaCoreIndex(void)
145{
146 return g_DmaCoreIndex;
147}
148
149static void _spu_FwriteByIO(void *addr, u32 size)
150{
151 _spu_RXX[725] = _spu_tsa[1];
152 _spu_RXX[724] = (_spu_tsa[1] >> 16) & 0xFFFF;
153 while ( size )
154 {
155 s32 v6;
156 s32 i;
157 unsigned int v9;
158
159 v6 = 64;
160 if ( size <= 64 )
161 v6 = size;
162 for ( i = 0; i < v6; i += 2 )
163 {
164 *((vu16 *)0xBF9001AC) = *(u16 *)((char *)addr + 2 * i);
165 }
166 *((vu16 *)0xBF90019A) = (*((vu16 *)0xBF90019A) & ~0x30) | 0x10;
167 v9 = 1;
168 while ( (*((vu16 *)0xBF900344) & 0x400) != 0 )
169 {
170 if ( v9 >= 0xF01 )
171 {
172 printf("SPU:T/O [%s]\n", "wait (SPU2_STATX_WRDY_M)");
173 break;
174 }
175 v9 += 1;
176 }
177 size -= v6;
178 }
179 *((vu16 *)0xBF90019A) &= ~0x30;
180}
181
182int _spu_FiDMA(void *userdata)
183{
184 int v1;
185 unsigned int v3;
186
187 (void)userdata;
188
189 v1 = 1;
190 while ( (*((vu16 *)0xBF900744) & 0x80) != 0 )
191 {
192 if ( v1 > 0x1000000 )
193 {
194 printf("SPU:T/O [%s]\n", "wait (SPU2_STATX_DREQ)");
195 break;
196 }
197 v1 += 1;
198 }
199 _spu_RXX[717] &= ~0x30;
200 v3 = 1;
201 while ( (_spu_RXX[717] & 0x30) != 0 )
202 {
203 if ( v3 >= 0xF01 )
204 break;
205 v3 += 1;
206 }
207 if ( _spu_transferCallback )
208 _spu_transferCallback();
209 else
210 gDMADeliverEvent = 1;
211 FlushDcache();
212 return 1;
213}
214
215int _spu_FiAutoDMA(void *userdata)
216{
217 (void)userdata;
218
219#ifdef LIB_1600
220 if ( gMode != SPU_AUTODMA_ONESHOT )
221 {
222 gWhichBuff = 1 - gWhichBuff;
223 if ( gWhichBuff )
224 *((vu32 *)0xBF8010C0) = (u32)&gHostAddr[512 * (gBufferSize48 / 512)];
225 else
226 *((vu32 *)0xBF8010C0) = (u32)&gHostAddr[0];
227 if ( gWhichBuff )
228 {
229 int v1;
230 int v2;
231
232 v1 = (gBufferSize48 / 512) << 9;
233 v2 = (2 * gBufferSize48 - v1) >> 6;
234 if ( 2 * gBufferSize48 - v1 < 0 )
235 v2 = (2 * gBufferSize48 - v1 + 63) >> 6;
236 *((vu16 *)0xBF8010C6) = v2 + ((2 * gBufferSize48 - ((gBufferSize48 / 512) << 9)) % 64 > 0);
237 }
238 else
239 {
240 *((vu16 *)0xBF8010C6) = 8 * (gBufferSize48 / 512);
241 }
242 *((vu32 *)0xBF8010C8) = 0x1000201;
243 }
244#else
245 if ( (gMode & SPU_AUTODMA_LOOP) != 0 )
246 {
247 gWhichBuff = 1 - gWhichBuff;
248 if ( gWhichBuff )
249 *(u32 *)(1088 * g_DmaCoreIndex + 0xBF8010C0) = (u32)&gHostAddr[512 * (gBufferSize48 / 512)];
250 else
251 *(u32 *)(1088 * g_DmaCoreIndex + 0xBF8010C0) = (u32)gHostAddr;
252 if ( gWhichBuff )
253 *(u16 *)(1088 * g_DmaCoreIndex + 0xBF8010C6) = (2 * gBufferSize48 - ((gBufferSize48 / 512) << 9)) / 64
254 + ((2 * gBufferSize48 - ((gBufferSize48 / 512) << 9)) % 64 > 0);
255 else
256 *(u16 *)(1088 * g_DmaCoreIndex + 0xBF8010C6) = 8 * (gBufferSize48 / 512);
257 *(u32 *)(1088 * g_DmaCoreIndex + 0xBF8010C8) = 0x1000201;
258 }
259#endif
260 else
261 {
262 *((vu16 *)0xBF90019A) &= ~0x30;
263 *((vu16 *)0xBF900198) &= ~0xc0;
264 *((vu16 *)0xBF9001B0) = 0;
265 }
266 if ( _spu_AutoDMACallback )
267 _spu_AutoDMACallback();
268 FlushDcache();
269 return 1;
270}
271
272void _spu_Fr_(void *data, int addr, u32 size)
273{
274 _spu_RXX[725] = addr;
275 _spu_RXX[724] = (addr >> 16) & 0xFFFF;
276 _spu_RXX[717] |= 0x30u;
277 _spu_FsetDelayR(1);
278 *((vu32 *)0xBF8010C0) = (vu32)data;
279 *((vu32 *)0xBF8010C4) = (size << 16) | 0x10;
280 _spu_dma_mode = 1;
281 *((vu32 *)0xBF8010C8) = 16777728;
282}
283
284int _spu_t(int count, ...)
285{
286 u32 v6;
287 int spu_tmp;
288 unsigned int ck;
289 va_list va;
290
291 va_start(va, count);
292 spu_tmp = va_arg(va, u32);
293 ck = va_arg(va, u32);
294 va_end(va);
295 switch ( count )
296 {
297 case 0:
298 _spu_dma_mode = 1;
299 _spu_RXX[717] = _spu_RXX[717] | 0x30;
300 break;
301 case 1:
302 _spu_dma_mode = 0;
303 _spu_RXX[717] = (_spu_RXX[717] & ~0x30) | 0x20;
304 break;
305 case 2:
306 _spu_tsa[1] = spu_tmp;
307 _spu_RXX[725] = spu_tmp;
308 _spu_RXX[724] = (_spu_tsa[1] >> 16) & 0xFFFF;
309 break;
310 case 3:
311 if ( _spu_dma_mode == 1 )
312 _spu_FsetDelayR(1);
313 else
314 _spu_FsetDelayW(1);
315 _spu_transfer_startaddr = spu_tmp;
316 _spu_transfer_time = (ck >> 6) + ((ck & 0x3F) != 0);
317 ((vu32 *)0xBF8010C0)[272] = spu_tmp;
318 ((vu32 *)0xBF8010C4)[272] = (_spu_transfer_time << 16) | 0x10;
319 v6 = 0x1000201;
320 if ( _spu_dma_mode == 1 )
321 v6 = 16777728;
322 ((vu32 *)0xBF8010C8)[272] = v6;
323 break;
324 default:
325 break;
326 }
327 return 0;
328}
329
330int _spu_Fw(void *addr, u32 size)
331{
332 if ( _spu_transMode )
333 {
334 _spu_FwriteByIO(addr, size);
335 }
336 else
337 {
338 _spu_t(2, _spu_tsa[1]);
339 _spu_t(1);
340 _spu_t(3, addr, size);
341 }
342 return size;
343}
344
345int _spu_StopAutoDMA(void)
346{
347#ifdef LIB_1300
348 *((vu16 *)0xBF90019A) &= ~0x30;
349#else
350 int v0;
351
352 v0 = 0;
353#ifdef LIB_1600
354 if ( *((vu16 *)0xBF9001B0) )
355 v0 = *((vu32 *)0xBF8010C0);
356 *((vu32 *)0xBF8010C8) &= ~0x1000000u;
357#else
358 int do_set_dmacoreindex;
359 u16 *v2;
360
361 do_set_dmacoreindex = 0;
362 if ( (*((vu16 *)0xBF9007C0) & 4) != 0 )
363 {
364 do_set_dmacoreindex = 1;
365 *((vu16 *)0xBF9007C0) &= ~0xc0;
366 }
367 v2 = (u16 *)((g_DmaCoreIndex << 10) + 0xBF9001B0);
368 if ( *v2 )
369 v0 = *(u32 *)(1088 * g_DmaCoreIndex + 0xBF8010C0);
370 *(u32 *)(1088 * g_DmaCoreIndex + 0xBF8010C8) &= ~0x1000000u;
371#endif
372#endif
373#ifdef LIB_1600
374 *((vu16 *)0xBF900198) &= ~0xf0;
375 *((vu16 *)0xBF9001B0) = 0;
376 *((vu16 *)0xBF90076E) = 0;
377 *((vu16 *)0xBF90076C) = 0;
378#else
379 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF900198) &= ~0xf0;
380 *v2 = 0;
381 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF90076E) = 0;
382 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF90076C) = *(u16 *)((g_DmaCoreIndex << 10) + 0xBF90076E);
383 if ( (*((vu16 *)0xBF9007C0) & 4) != 0 )
384 *((vu16 *)0xBF9007C0) &= ~0xc4;
385 if ( do_set_dmacoreindex )
386 spu_do_set_DmaCoreIndex(0);
387#endif
388#ifdef LIB_1300
389 return 0;
390#else
391 return (gWhichBuff << 24) | (v0 & 0xFFFFFF);
392#endif
393}
394
395int _spu_AutoDMAGetStatus(void)
396{
397 int v0;
398
399 v0 = 0;
400#ifdef LIB_1600
401 if ( *((vu16 *)0xBF9001B0) )
402 v0 = *((vu32 *)0xBF8010C0);
403#else
404 if ( *(u16 *)((g_DmaCoreIndex << 10) + 0xBF9001B0) )
405 v0 = *(u32 *)(1088 * g_DmaCoreIndex + 0xBF8010C0);
406#endif
407 return (gWhichBuff << 24) | (v0 & 0xFFFFFF);
408}
409
410unsigned int _spu_FwAutoDMA(u8 *addr, unsigned int size, int mode)
411{
412 gHostAddr = addr;
413 gWhichBuff = 0;
414 gBufferSize48 = size;
415 gMode = mode;
416#ifdef LIB_1600
417 *((vu16 *)0xBF90019A) &= ~0x30;
418 *((vu16 *)0xBF9001A8) = 0;
419 *((vu16 *)0xBF9001AA) = 0;
420 *((vu16 *)0xBF9001B0) = 1;
421 *((vu32 *)0xBF8010C0) = (u32)addr;
422 *((vu32 *)0xBF8010C4) = 16;
423 *((vu16 *)0xBF8010C6) = 8 * ((int)size / 512);
424 *((vu32 *)0xBF8010C8) = 0x1000201;
425 *((vu16 *)0xBF900198) |= 0xC0u;
426 *((vu16 *)0xBF90076E) = 0x7FFF;
427 *((vu16 *)0xBF90076C) = 0x7FFF;
428#else
429 if ( (mode & (SPU_AUTODMA_BIT4 | SPU_AUTODMA_LOOP)) != 0 )
430 {
431 spu_do_set_DmaCoreIndex(1);
432 *((vu16 *)0xBF9007C0) |= 4u;
433 }
434 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF90019A) &= ~0x30;
435 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF9001A8) = 0;
436 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF9001AA) = 0;
437 if ( g_DmaCoreIndex != 0 )
438 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF9001B0) = 2;
439 else
440 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF9001B0) = 1;
441 _spu_FsetDelayW(g_DmaCoreIndex);
442 *(u32 *)((1088 * g_DmaCoreIndex) + 0xBF8010C0) = (u32)addr;
443 *(u16 *)((1088 * g_DmaCoreIndex) + 0xBF8010C4) = 16;
444 *(u16 *)((1088 * g_DmaCoreIndex) + 0xBF8010C6) = 8 * ((int)size / 512);
445 if ( (mode & (SPU_AUTODMA_BIT4 | SPU_AUTODMA_LOOP)) != 0 )
446 {
447 *((vu16 *)0xBF9007C0) |= (mode & SPU_AUTODMA_BIT6) | (mode & SPU_AUTODMA_BIT7);
448 }
449 *(u32 *)((1088 * g_DmaCoreIndex) + 0xBF8010C8) = 0x1000201;
450 if ( (mode & SPU_AUTODMA_BIT4) == 0 )
451 {
452 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF900198) |= 0xC0u;
453 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF90076E) = 0x7FFF;
454 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF90076C) = 0x7FFF;
455 }
456#endif
457 return size;
458}
459
460unsigned int _spu_FwAutoDMAfrom(u8 *addr, unsigned int size, int mode, u8 *unk_a4)
461{
462 u8 *v4;
463 int v5;
464#ifdef LIB_1600
465 int v7;
466#endif
467
468 v4 = unk_a4;
469 if ( !unk_a4 )
470 v4 = addr;
471 gHostAddr = addr;
472 gWhichBuff = 0;
473 gBufferSize48 = size;
474 gMode = mode;
475 v5 = size - (v4 - addr);
476 if ( (unsigned int)(v4 - addr) >= size )
477 {
478#ifdef LIB_1600
479 if ( mode != SPU_AUTODMA_LOOP )
480#else
481 if ( (mode & SPU_AUTODMA_LOOP) == 0 )
482#endif
483 return 0;
484 gWhichBuff += 1;
485 v5 = size - (v4 - addr - size);
486 }
487 if ( v5 % 1024 > 0 )
488 {
489 v5 = (v5 / 1024 + 1) << 10;
490 v4 = &addr[gWhichBuff * size + size - v5];
491 }
492#ifdef LIB_1600
493 *((vu16 *)0xBF90019A) &= ~0x30;
494 *((vu16 *)0xBF9001A8) = 0;
495 *((vu16 *)0xBF9001AA) = 0;
496 *((vu16 *)0xBF9001B0) = 1;
497 *((vu32 *)0xBF8010C0) = (u32)v4;
498 *((vu32 *)0xBF8010C4) = 16;
499 v7 = v5 >> 6;
500 if ( v5 < 0 )
501 v7 = (v5 + 63) >> 6;
502 *((vu16 *)0xBF8010C6) = v7 + (v5 - (v7 << 6) > 0);
503 *((vu32 *)0xBF8010C8) = 0x1000201;
504 *((vu16 *)0xBF900198) |= 0xC0u;
505 *((vu16 *)0xBF90076E) = 0x7FFF;
506 *((vu16 *)0xBF90076C) = 0x7FFF;
507#else
508 if ( (mode & (SPU_AUTODMA_BIT4 | SPU_AUTODMA_LOOP)) != 0 )
509 {
510 spu_do_set_DmaCoreIndex(1);
511 *((vu16 *)0xBF9007C0) |= 4u;
512 }
513 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF90019A) &= ~0x30;
514 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF9001A8) = 0;
515 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF9001AA) = 0;
516 if ( g_DmaCoreIndex != 0 )
517 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF9001B0) = 2;
518 else
519 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF9001B0) = 1;
520 *(u32 *)((1088 * g_DmaCoreIndex) + 0xBF8010C0) = (u32)v4;
521 *(u16 *)((1088 * g_DmaCoreIndex) + 0xBF8010C4) = 16;
522 *(u16 *)((1088 * g_DmaCoreIndex) + 0xBF8010C6) = v5 / 64 + (v5 % 64 > 0);
523 if ( (mode & (SPU_AUTODMA_BIT4 | SPU_AUTODMA_LOOP)) != 0 )
524 {
525 *((vu16 *)0xBF9007C0) |= (mode & SPU_AUTODMA_BIT6) | (mode & SPU_AUTODMA_BIT7);
526 }
527 *(u32 *)(1088 * g_DmaCoreIndex + 0xBF8010C8) = 0x1000201;
528 if ( (mode & SPU_AUTODMA_BIT4) == 0 )
529 {
530 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF900198) |= 0xC0u;
531 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF90076E) = 0x7FFF;
532 *(u16 *)((g_DmaCoreIndex << 10) + 0xBF90076C) = 0x7FFF;
533 }
534#endif
535 return size;
536}
537
538void _spu_Fr(void *addr, u32 size)
539{
540 _spu_t(2, _spu_tsa[1]);
541 _spu_t(0);
542 _spu_t(3, addr, size);
543}
544
545void _spu_MGFsetRXX2(int offset, int value)
546{
547 int v2;
548 vu16 *v3;
549
550 v2 = 4 * value;
551 v3 = &_spu_RXX[512 * _spu_core + offset];
552 *v3 = (v2 >> 16) & 0xFFFF;
553 v3[1] = v2;
554}
555
556void _spu_FsetRXX(int l, u32 addr, int flag)
557{
558 vu16 *v3;
559
560 v3 = &_spu_RXX[512 * _spu_core + l];
561 if ( flag )
562 {
563 *v3 = addr >> 17;
564 v3[1] = addr >> 1;
565 }
566 else
567 {
568 *v3 = addr >> 14;
569 v3[1] = 4 * addr;
570 }
571}
572
573int _spu_FsetRXXa(int l, u32 flag)
574{
575 if ( l == -2 )
576 return flag;
577 if ( l == -1 )
578 return flag >> 1;
579 _spu_RXX[512 * _spu_core + l] = flag >> 1;
580 return flag;
581}
582
583int _spu_MGFgetRXX2(int offset)
584{
585 return 2 * (_spu_RXX[512 * _spu_core + 1 + offset] | (_spu_RXX[512 * _spu_core + offset] << 16));
586}
587
588void _spu_FsetPCR(int flag)
589{
590 (void)flag;
591}
592
593static void _spu_FsetDelayW(int flag)
594{
595 ((vu32 *)0xBF801014)[256 * flag] = (((vu32 *)0xBF801014)[256 * flag] & ~0x2f000000) | 0x20000000;
596}
597
598static void _spu_FsetDelayR(int flag)
599{
600 ((vu32 *)0xBF801014)[256 * flag] = (((vu32 *)0xBF801014)[256 * flag] & ~0x2f000000) | 0x22000000;
601}
602
603void __attribute__((optimize("no-unroll-loops"))) _spu_Fw1ts(void)
604{
605 int i;
606 int v1;
607
608 v1 = 13;
609 for ( i = 0; i < 60; i += 1 )
610 {
611 v1 *= 13;
612 __asm__ __volatile__("" : "+g"(v1) : :);
613 }
614}
typedef __attribute__
Definition tlbfunc.c:60
u32 count
start sector of fragmented bd/file