PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
libsd.c
Go to the documentation of this file.
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
16#include <irx_imports.h>
17
18#include <iop_mmio_hwport.h>
19#include <spu2_mmio_hwport.h>
20#include <libsd.h>
21#include <stdarg.h>
22
23IRX_ID("Sound_Device_Library", 3, 3);
24// Based on the module from SDK 3.1.0.
25
26#define SD_DMA_CS (1 << 9) // Continuous stream
27#define SD_DMA_START (1 << 24)
28#define SD_DMA_DIR_SPU2IOP 0
29#define SD_DMA_DIR_IOP2SPU 1
30
31extern struct irx_export_table _exp_libsd;
32
34{
35 u32 m_mode_flags;
36 u16 m_d_apf1_size;
37 u16 m_d_apf2_size;
38 u16 m_d_iir_vol;
39 u16 m_d_comb1_vol;
40 u16 m_d_comb2_vol;
41 u16 m_d_comb3_vol;
42 u16 m_d_comb4_vol;
43 u16 m_d_wall_vol;
44 u16 m_d_apf1_vol;
45 u16 m_d_apf2_vol;
46 u16 m_d_same_l_dst;
47 u16 m_d_same_r_dst;
48 u16 m_d_comb1_l_src;
49 u16 m_d_comb1_r_src;
50 u16 m_d_comb2_l_src;
51 u16 m_d_comb2_r_src;
52 u16 m_d_same_l_src;
53 u16 m_d_same_r_src;
54 u16 m_d_diff_l_dst;
55 u16 m_d_diff_r_dst;
56 u16 m_d_comb3_l_src;
57 u16 m_d_comb3_r_src;
58 u16 m_d_comb4_l_src;
59 u16 m_d_comb4_r_src;
60 u16 m_d_diff_l_src;
61 u16 m_d_diff_r_src;
62 u16 m_d_apf1_l_dst;
63 u16 m_d_apf1_r_dst;
64 u16 m_d_apf2_l_dst;
65 u16 m_d_apf2_r_dst;
66 u16 m_d_in_coef_l;
67 u16 m_d_in_coef_r;
68};
69
70typedef struct
71{
72 u32 m_mode;
73 void *m_data;
74} IntrData;
75
77{
78 sceSdBlockTransHandler m_cb;
79 void *m_userdata;
81
83{
84 u32 *m_spuaddr;
85 u32 m_size;
87
88typedef struct CleanRegionBuffer_
89{
90 CleanRegionBufferElement_t m_elements[97];
92
93typedef int (*SdCleanHandler)(int core);
94
95static int GetEEA(int core);
96static void InitSpu2_Inner(void);
97static void libsd_do_busyloop(int count);
98static u32 DmaStartStop(int mainarg, void *vararg2, u32 vararg3);
99static u32 VoiceTrans_Write_IOMode(const u16 *iopaddr, u32 size, int core);
100static u32 BlockTransWriteFrom(u8 *iopaddr, u32 size, int core, int mode, u8 *startaddr);
101static u32 BlockTransRead(u8 *iopaddr, u32 size, int core, u16 mode);
102static void reset_vars(void);
103
104// clang-format off
105static vu16 *const g_ParamRegList[] =
106{
107 (vu16 *)0xBF900000,
108 (vu16 *)0xBF900002,
109 (vu16 *)0xBF900004,
110 (vu16 *)0xBF900006,
111 (vu16 *)0xBF900008,
112 (vu16 *)0xBF90000A,
113 (vu16 *)0xBF90000C,
114 (vu16 *)0xBF90000E,
115 (vu16 *)0xBF900198,
116 (vu16 *)0xBF900760,
117 (vu16 *)0xBF900762,
118 (vu16 *)0xBF900764,
119 (vu16 *)0xBF900766,
120 (vu16 *)0xBF900768,
121 (vu16 *)0xBF90076A,
122 (vu16 *)0xBF90076C,
123 (vu16 *)0xBF90076E,
124 (vu16 *)0xBF900770,
125 (vu16 *)0xBF900772,
126 (vu16 *)0xBF900180,
127 (vu16 *)0xBF900184,
128 (vu16 *)0xBF9001A0,
129 (vu16 *)0xBF9001A4,
130 (vu16 *)0xBF900340,
131 (vu16 *)0xBF900188,
132 (vu16 *)0xBF90018C,
133 (vu16 *)0xBF900190,
134 (vu16 *)0xBF900194,
135 (vu16 *)0xBF9002E0,
136 (vu16 *)0xBF90033C,
137 (vu16 *)0xBF9001A8,
138 (vu16 *)0xBF90019C,
139 (vu16 *)0xBF9001C0,
140 (vu16 *)0xBF9001C4,
141 (vu16 *)0xBF9001C8,
142 (vu16 *)0xBF90019A,
143 (vu16 *)0xBF9001A8,
144 (vu16 *)0xBF9001AC,
145 // 1AE & 1B0 are both related to core attr & dma somehow
146 (vu16 *)0xBF9001AE,
147 (vu16 *)0xBF9001B0,
148 (vu16 *)0xBF900344,
149 NULL,
150 NULL,
151 NULL,
152};
153// The values are more or less the same as on PSX (SPU)
154static const u32 g_EffectSizes[] =
155{
156 0x2,
157 0x4d8,
158 0x3e8,
159 0x908,
160 0xdfc,
161 0x15bc,
162 0x1ed8,
163 0x3008,
164 0x3008,
165 0x780,
166};
167static const struct mode_data_struct g_EffectParams[] =
168{
169 // SD_EFFECT_MODE_OFF
170 {
171 0x0,
172 0x0,
173 0x0,
174 0x0,
175 0x0,
176 0x0,
177 0x0,
178 0x0,
179 0x0,
180 0x0,
181 0x0,
182 0x1,
183 0x1,
184 0x0,
185 0x0,
186 0x0,
187 0x0,
188 0x0,
189 0x0,
190 0x1,
191 0x1,
192 0x0,
193 0x0,
194 0x0,
195 0x0,
196 0x0,
197 0x0,
198 0x0,
199 0x0,
200 0x0,
201 0x0,
202 0x0,
203 0x0,
204 },
205 // SD_EFFECT_MODE_ROOM
206 {
207 0x0,
208 0x7d,
209 0x5b,
210 0x6d80,
211 0x54b8,
212 0xbed0,
213 0x0,
214 0x0,
215 0xba80,
216 0x5800,
217 0x5300,
218 0x4d6,
219 0x333,
220 0x3f0,
221 0x227,
222 0x374,
223 0x1ef,
224 0x336,
225 0x1b7,
226 0x335,
227 0x1b6,
228 0x334,
229 0x1b5,
230 0x334,
231 0x1b5,
232 0x334,
233 0x1b5,
234 0x1b4,
235 0x136,
236 0xb8,
237 0x5c,
238 0x8000,
239 0x8000,
240 },
241 // SD_EFFECT_MODE_STUDIO_1
242 {
243 0x0,
244 0x33,
245 0x25,
246 0x70f0,
247 0x4fa8,
248 0xbce0,
249 0x4410,
250 0xc0f0,
251 0x9c00,
252 0x5280,
253 0x4ec0,
254 0x3e4,
255 0x31b,
256 0x3a4,
257 0x2af,
258 0x372,
259 0x266,
260 0x31c,
261 0x25d,
262 0x25c,
263 0x18e,
264 0x22f,
265 0x135,
266 0x1d2,
267 0xb7,
268 0x18f,
269 0xb5,
270 0xb4,
271 0x80,
272 0x4c,
273 0x26,
274 0x8000,
275 0x8000,
276 },
277 // SD_EFFECT_MODE_STUDIO_2
278 {
279 0x0,
280 0xb1,
281 0x7f,
282 0x70f0,
283 0x4fa8,
284 0xbce0,
285 0x4510,
286 0xbef0,
287 0xb4c0,
288 0x5280,
289 0x4ec0,
290 0x904,
291 0x76b,
292 0x824,
293 0x65f,
294 0x7a2,
295 0x616,
296 0x76c,
297 0x5ed,
298 0x5ec,
299 0x42e,
300 0x50f,
301 0x305,
302 0x462,
303 0x2b7,
304 0x42f,
305 0x265,
306 0x264,
307 0x1b2,
308 0x100,
309 0x80,
310 0x8000,
311 0x8000,
312 },
313 // SD_EFFECT_MODE_STUDIO_3
314 {
315 0x0,
316 0xe3,
317 0xa9,
318 0x6f60,
319 0x4fa8,
320 0xbce0,
321 0x4510,
322 0xbef0,
323 0xa680,
324 0x5680,
325 0x52c0,
326 0xdfb,
327 0xb58,
328 0xd09,
329 0xa3c,
330 0xbd9,
331 0x973,
332 0xb59,
333 0x8da,
334 0x8d9,
335 0x5e9,
336 0x7ec,
337 0x4b0,
338 0x6ef,
339 0x3d2,
340 0x5ea,
341 0x31d,
342 0x31c,
343 0x238,
344 0x154,
345 0xaa,
346 0x8000,
347 0x8000,
348 },
349 // SD_EFFECT_MODE_HALL
350 {
351 0x0,
352 0x1a5,
353 0x139,
354 0x6000,
355 0x5000,
356 0x4c00,
357 0xb800,
358 0xbc00,
359 0xc000,
360 0x6000,
361 0x5c00,
362 0x15ba,
363 0x11bb,
364 0x14c2,
365 0x10bd,
366 0x11bc,
367 0xdc1,
368 0x11c0,
369 0xdc3,
370 0xdc0,
371 0x9c1,
372 0xbc4,
373 0x7c1,
374 0xa00,
375 0x6cd,
376 0x9c2,
377 0x5c1,
378 0x5c0,
379 0x41a,
380 0x274,
381 0x13a,
382 0x8000,
383 0x8000,
384 },
385 // SD_EFFECT_MODE_SPACE
386 {
387 0x0,
388 0x33d,
389 0x231,
390 0x7e00,
391 0x5000,
392 0xb400,
393 0xb000,
394 0x4c00,
395 0xb000,
396 0x6000,
397 0x5400,
398 0x1ed6,
399 0x1a31,
400 0x1d14,
401 0x183b,
402 0x1bc2,
403 0x16b2,
404 0x1a32,
405 0x15ef,
406 0x15ee,
407 0x1055,
408 0x1334,
409 0xf2d,
410 0x11f6,
411 0xc5d,
412 0x1056,
413 0xae1,
414 0xae0,
415 0x7a2,
416 0x464,
417 0x232,
418 0x8000,
419 0x8000,
420 },
421 // SD_EFFECT_MODE_ECHO
422 {
423 0x0,
424 0x3,
425 0x3,
426 0x7fff,
427 0x7fff,
428 0x0,
429 0x0,
430 0x0,
431 0x8100,
432 0x0,
433 0x0,
434 0x1ffd,
435 0xffd,
436 0x1009,
437 0x9,
438 0x0,
439 0x0,
440 0x1009,
441 0x9,
442 0x1fff,
443 0x1fff,
444 0x1ffe,
445 0x1ffe,
446 0x1ffe,
447 0x1ffe,
448 0x1ffe,
449 0x1ffe,
450 0x1008,
451 0x1004,
452 0x8,
453 0x4,
454 0x8000,
455 0x8000,
456 },
457 // SD_EFFECT_MODE_DELAY
458 {
459 0x0,
460 0x3,
461 0x3,
462 0x7fff,
463 0x7fff,
464 0x0,
465 0x0,
466 0x0,
467 0x0,
468 0x0,
469 0x0,
470 0x1ffd,
471 0xffd,
472 0x1009,
473 0x9,
474 0x0,
475 0x0,
476 0x1009,
477 0x9,
478 0x1fff,
479 0x1fff,
480 0x1ffe,
481 0x1ffe,
482 0x1ffe,
483 0x1ffe,
484 0x1ffe,
485 0x1ffe,
486 0x1008,
487 0x1004,
488 0x8,
489 0x4,
490 0x8000,
491 0x8000,
492 },
493 // SD_EFFECT_MODE_CLEAR
494 {
495 0x0,
496 0x17,
497 0x13,
498 0x70f0,
499 0x4fa8,
500 0xbce0,
501 0x4510,
502 0xbef0,
503 0x8500,
504 0x5f80,
505 0x54c0,
506 0x371,
507 0x2af,
508 0x2e5,
509 0x1df,
510 0x2b0,
511 0x1d7,
512 0x358,
513 0x26a,
514 0x1d6,
515 0x11e,
516 0x12d,
517 0xb1,
518 0x11f,
519 0x59,
520 0x1a0,
521 0xe3,
522 0x58,
523 0x40,
524 0x28,
525 0x14,
526 0x8000,
527 0x8000,
528 }
529};
530static const u16 g_NotePitchTable[] =
531{
532 0x8000,
533 0x879c,
534 0x8fac,
535 0x9837,
536 0xa145,
537 0xaadc,
538 0xb504,
539 0xbfc8,
540 0xcb2f,
541 0xd744,
542 0xe411,
543 0xf1a1,
544 0x8000,
545 0x800e,
546 0x801d,
547 0x802c,
548 0x803b,
549 0x804a,
550 0x8058,
551 0x8067,
552 0x8076,
553 0x8085,
554 0x8094,
555 0x80a3,
556 0x80b1,
557 0x80c0,
558 0x80cf,
559 0x80de,
560 0x80ed,
561 0x80fc,
562 0x810b,
563 0x811a,
564 0x8129,
565 0x8138,
566 0x8146,
567 0x8155,
568 0x8164,
569 0x8173,
570 0x8182,
571 0x8191,
572 0x81a0,
573 0x81af,
574 0x81be,
575 0x81cd,
576 0x81dc,
577 0x81eb,
578 0x81fa,
579 0x8209,
580 0x8218,
581 0x8227,
582 0x8236,
583 0x8245,
584 0x8254,
585 0x8263,
586 0x8272,
587 0x8282,
588 0x8291,
589 0x82a0,
590 0x82af,
591 0x82be,
592 0x82cd,
593 0x82dc,
594 0x82eb,
595 0x82fa,
596 0x830a,
597 0x8319,
598 0x8328,
599 0x8337,
600 0x8346,
601 0x8355,
602 0x8364,
603 0x8374,
604 0x8383,
605 0x8392,
606 0x83a1,
607 0x83b0,
608 0x83c0,
609 0x83cf,
610 0x83de,
611 0x83ed,
612 0x83fd,
613 0x840c,
614 0x841b,
615 0x842a,
616 0x843a,
617 0x8449,
618 0x8458,
619 0x8468,
620 0x8477,
621 0x8486,
622 0x8495,
623 0x84a5,
624 0x84b4,
625 0x84c3,
626 0x84d3,
627 0x84e2,
628 0x84f1,
629 0x8501,
630 0x8510,
631 0x8520,
632 0x852f,
633 0x853e,
634 0x854e,
635 0x855d,
636 0x856d,
637 0x857c,
638 0x858b,
639 0x859b,
640 0x85aa,
641 0x85ba,
642 0x85c9,
643 0x85d9,
644 0x85e8,
645 0x85f8,
646 0x8607,
647 0x8617,
648 0x8626,
649 0x8636,
650 0x8645,
651 0x8655,
652 0x8664,
653 0x8674,
654 0x8683,
655 0x8693,
656 0x86a2,
657 0x86b2,
658 0x86c1,
659 0x86d1,
660 0x86e0,
661 0x86f0,
662 0x8700,
663 0x870f,
664 0x871f,
665 0x872e,
666 0x873e,
667 0x874e,
668 0x875d,
669 0x876d,
670 0x877d,
671 0x878c,
672};
673// Enable/disable bits in SD_CORE_ATTR
674static const u16 g_CoreAttrShifts[] =
675{
676 0x7,
677 0x6,
678 0xe,
679 0x8,
680};
681static const u16 g_VoiceDataInit[] =
682{
683 0x700,
684 0x0,
685 0x0,
686 0x0,
687 0x0,
688 0x0,
689 0x0,
690 0x0,
691};
692// clang-format on
693
694// Unofficial: move to bss
695static const u32 g_ClearEffectData[256] __attribute__((__aligned__(16)));
696// Unofficial: move to bss
697static int g_VoiceTransStatus[2];
698// Unofficial: move to bss
699static int g_VoiceTransIoMode[2];
700// Unofficial: move to bss
701static int g_SpdifSettings;
702// Unofficial: move to bss
703static sceSdEffectAttr g_EffectAttr[2];
704// Unofficial: move to bss
705static int g_VoiceTransCompleteBool[2];
706// Unofficial: move to bss
707static int g_VoiceTransCompleteEf[2];
708// Unofficial: move to bss
709static int g_vars_inited;
710// Unofficial: move to bss
711static SdIntrCallback g_Spu2IrqCallback;
712// Unofficial: move to bss
713static sceSdSpu2IntrHandler g_Spu2IntrHandler;
714// Unofficial: move to bss
715static void *g_Spu2IntrHandlerData;
716// Unofficial: move to bss
717static sceSdTransIntrHandler g_TransIntrHandlers[2];
718// Unofficial: move to bss
719static BlockHandlerIntrData_t g_BlockHandlerIntrData[2];
720// Unofficial: move to bss
721static SdCleanHandler g_CleanHandlers[2];
722// Unofficial: move to bss
723static IntrData g_TransIntrData[2];
724static u32 g_CleanRegionMax[2];
725static u32 g_CleanRegionCur[2];
726static CleanRegionBuffer_t g_CleanRegionBuffer[2];
727static u32 g_BlockTransBuff[2];
728static u8 *g_BlockTransAddr[2];
729static u32 g_BlockTransSize[2];
730static u32 g_BatchData __attribute__((__aligned__(16)));
731static SdIntrCallback g_TransIntrCallbacks[2];
732static u32 g_EffectAddr[2];
733
734int _start(int ac, char **av)
735{
736 int regres;
737 int state;
738
739 (void)ac;
740 (void)av;
741 CpuSuspendIntr(&state);
742 regres = RegisterLibraryEntries(&_exp_libsd);
743 CpuResumeIntr(state);
744 if ( regres )
745 return MODULE_NO_RESIDENT_END;
746 InitSpu2_Inner();
747 reset_vars();
748 return MODULE_RESIDENT_END;
749}
750
751static void SetEffectRegisterPair(spu2_u16pair_t *pair, u32 val)
752{
753 val <<= 2;
754 // Unofficial: receive register pair instead of base+offset
755 pair->m_pair[0] = (val >> 16) & 0xFFFF;
756 pair->m_pair[1] = val;
757}
758
759static void SetEffectData(int core, const struct mode_data_struct *mode_data)
760{
761 int mode_flags;
762 // Unofficial: use local instead of global variable for SPU2 MMIO
763 USE_SPU2_MMIO_HWPORT();
764
765 mode_flags = mode_data->m_mode_flags;
766 if ( !mode_flags )
767 mode_flags = 0xFFFFFFFF;
768 if ( (mode_flags & 1) )
769 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf1_size, mode_data->m_d_apf1_size);
770 if ( (mode_flags & 2) )
771 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf2_size, mode_data->m_d_apf2_size);
772 if ( (mode_flags & 4) )
773 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_iir_vol = mode_data->m_d_iir_vol;
774 if ( (mode_flags & 8) )
775 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb1_vol = mode_data->m_d_comb1_vol;
776 if ( (mode_flags & 0x10) )
777 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb2_vol = mode_data->m_d_comb2_vol;
778 if ( (mode_flags & 0x20) )
779 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb3_vol = mode_data->m_d_comb3_vol;
780 if ( (mode_flags & 0x40) )
781 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb4_vol = mode_data->m_d_comb4_vol;
782 if ( (mode_flags & 0x80) )
783 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_wall_vol = mode_data->m_d_wall_vol;
784 if ( (mode_flags & 0x100) )
785 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_apf1_vol = mode_data->m_d_apf1_vol;
786 if ( (mode_flags & 0x200) )
787 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_apf2_vol = mode_data->m_d_apf2_vol;
788 if ( (mode_flags & 0x400) )
789 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_same_l_dst, mode_data->m_d_same_l_dst);
790 if ( (mode_flags & 0x800) )
791 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_same_r_dst, mode_data->m_d_same_r_dst);
792 if ( (mode_flags & 0x1000) )
793 SetEffectRegisterPair(
794 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb1_l_src, mode_data->m_d_comb1_l_src);
795 if ( (mode_flags & 0x2000) )
796 SetEffectRegisterPair(
797 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb1_r_src, mode_data->m_d_comb1_r_src);
798 if ( (mode_flags & 0x4000) )
799 SetEffectRegisterPair(
800 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb2_l_src, mode_data->m_d_comb2_l_src);
801 if ( (mode_flags & 0x8000) )
802 SetEffectRegisterPair(
803 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb2_r_src, mode_data->m_d_comb2_r_src);
804 if ( (mode_flags & 0x10000) )
805 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_same_l_src, mode_data->m_d_same_l_src);
806 if ( (mode_flags & 0x20000) )
807 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_same_r_src, mode_data->m_d_same_r_src);
808 if ( (mode_flags & 0x40000) )
809 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_diff_l_dst, mode_data->m_d_diff_l_dst);
810 if ( (mode_flags & 0x80000) )
811 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_diff_r_dst, mode_data->m_d_diff_r_dst);
812 if ( (mode_flags & 0x100000) )
813 SetEffectRegisterPair(
814 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb3_l_src, mode_data->m_d_comb3_l_src);
815 if ( (mode_flags & 0x200000) )
816 SetEffectRegisterPair(
817 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb3_r_src, mode_data->m_d_comb3_r_src);
818 if ( (mode_flags & 0x400000) )
819 SetEffectRegisterPair(
820 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb4_l_src, mode_data->m_d_comb4_l_src);
821 if ( (mode_flags & 0x800000) )
822 SetEffectRegisterPair(
823 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb4_r_src, mode_data->m_d_comb4_r_src);
824 if ( (mode_flags & 0x1000000) )
825 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_diff_l_src, mode_data->m_d_diff_l_src);
826 if ( (mode_flags & 0x2000000) )
827 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_diff_r_src, mode_data->m_d_diff_r_src);
828 if ( (mode_flags & 0x4000000) )
829 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf1_l_dst, mode_data->m_d_apf1_l_dst);
830 if ( (mode_flags & 0x8000000) )
831 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf1_r_dst, mode_data->m_d_apf1_r_dst);
832 if ( (mode_flags & 0x10000000) )
833 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf2_l_dst, mode_data->m_d_apf2_l_dst);
834 if ( (mode_flags & 0x20000000) )
835 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf2_r_dst, mode_data->m_d_apf2_r_dst);
836 if ( (mode_flags & 0x40000000) )
837 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_in_coef_l = mode_data->m_d_in_coef_l;
838 if ( (mode_flags & 0x80000000) )
839 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_in_coef_r = mode_data->m_d_in_coef_r;
840}
841
842int sceSdClearEffectWorkArea(int core, int channel, int effect_mode)
843{
844 u32 aligned_addr;
845 u32 effect_size;
846 u32 effect_addr;
847 int xferres;
848 SdIntrCallback callback_tmp;
849 sceSdTransIntrHandler handler_tmp;
850
851 effect_mode &= 0xFF;
852 if ( effect_mode > SD_EFFECT_MODE_PIPE )
853 return -100;
854 if ( !effect_mode )
855 return 0;
856 // Unofficial: restrict channel
857 channel &= 1;
858 if ( DmaStartStop((channel << 4) | 4, 0, 0) )
859 return -210;
860 if ( g_VoiceTransIoMode[channel] != 1 )
861 return -201;
862 if ( QueryIntrContext() )
863 return -202;
864 aligned_addr = 0;
865 effect_size = g_EffectSizes[effect_mode] << 3;
866 effect_addr = (GetEEA(core) - (effect_size - 1)) >> 1;
867 if ( (effect_size & 0x3F) )
868 {
869 effect_size &= 0x3FFFFFF;
870 aligned_addr = (GetEEA(core) - (effect_size - 1)) >> 1;
871 }
872 // Disable intr_handlers by removing them
873 handler_tmp = g_TransIntrHandlers[channel];
874 callback_tmp = g_TransIntrCallbacks[channel];
875 g_TransIntrHandlers[channel] = 0;
876 g_TransIntrCallbacks[channel] = 0;
877 xferres = 0;
878 if ( aligned_addr )
879 {
880 xferres = sceSdVoiceTrans(channel, 0, (u8 *)g_ClearEffectData, (u32 *)(effect_addr << 1), 0x40);
881 if ( xferres >= 0 )
882 xferres = sceSdVoiceTransStatus(channel, 1);
883 effect_addr = aligned_addr;
884 }
885 if ( xferres >= 0 )
886 {
887 int i;
888
889 for ( i = 0;; i += 1 )
890 {
891 u32 size;
892
893 size = (effect_size <= 0x400) ? effect_size : 0x400;
894 xferres = sceSdVoiceTrans(channel, 0, (u8 *)g_ClearEffectData, (u32 *)((effect_addr + (i << 9)) << 1), size);
895 if ( xferres < 0 )
896 break;
897 // Wait for completion
898 xferres = sceSdVoiceTransStatus(channel, 1);
899 if ( xferres < 0 )
900 break;
901 if ( effect_size <= 0x400 )
902 {
903 xferres = 0;
904 break;
905 }
906 effect_size -= 0x400;
907 }
908 }
909 // Enable intr_handlers by adding them again
910 g_TransIntrHandlers[channel] = handler_tmp;
911 g_TransIntrCallbacks[channel] = callback_tmp;
912 return xferres;
913}
914
915static int CleanHandler(int core)
916{
917 // Unofficial: restrict core
918 core &= 1;
919 g_CleanRegionCur[core] += 1;
920 if ( (int)g_CleanRegionCur[core] >= (int)(g_CleanRegionMax[core] - 1) )
921 g_CleanHandlers[core] = 0;
922 DmaStartStop((core << 4) | 2, g_CleanRegionBuffer[core].m_elements[g_CleanRegionCur[core]].m_spuaddr, 0);
923 DmaStartStop(
924 (core << 4) | 6, (u8 *)g_ClearEffectData, g_CleanRegionBuffer[core].m_elements[g_CleanRegionCur[core]].m_size);
925 return 0;
926}
927
928int sceSdCleanEffectWorkArea(int core, int channel, int effect_mode)
929{
930 u32 effect_size;
931 u32 effect_addr;
932 int xferres;
933 int i;
934
935 effect_mode &= 0xFF;
936 if ( effect_mode > SD_EFFECT_MODE_PIPE )
937 return -100;
938 if ( !effect_mode )
939 return 0;
940 // Unofficial: restrict channel
941 channel &= 1;
942 if ( DmaStartStop((channel << 4) | 4, 0, 0) )
943 return -210;
944 if ( g_VoiceTransIoMode[channel] != 1 )
945 return -201;
946 effect_size = g_EffectSizes[effect_mode] << 3;
947 effect_addr = GetEEA(core) - (effect_size - 1);
948 if ( (effect_size & 0x3F) )
949 {
950 effect_size &= 0x3FFFFFF;
951 xferres = sceSdVoiceTrans(channel, 8, (u8 *)g_ClearEffectData, (u32 *)effect_addr, 0x40);
952 if ( xferres < 0 )
953 return xferres;
954 effect_addr = GetEEA(core) - (effect_size - 1);
955 }
956 effect_addr += 0x100;
957 effect_size -= 0x400;
958 for ( i = 0;; i += 1 )
959 {
960 g_CleanRegionBuffer[channel].m_elements[i].m_spuaddr = (u32 *)effect_addr;
961 g_CleanRegionBuffer[channel].m_elements[i].m_size = (effect_size <= 0x400) ? effect_size : 0x400;
962 if ( effect_size <= 0x400 )
963 break;
964 effect_addr += 0x100;
965 effect_size -= 0x400;
966 }
967 g_CleanRegionMax[channel] = i + 1;
968 g_CleanHandlers[channel] = CleanHandler;
969 g_CleanRegionCur[channel] = 0;
970 xferres = sceSdVoiceTrans(channel, 0, (u8 *)g_ClearEffectData, (u32 *)effect_addr, 0x400);
971 if ( xferres >= 0 )
972 xferres = 0;
973 return xferres;
974}
975
976void sceSdGetEffectAttr(int core, sceSdEffectAttr *attr)
977{
978 USE_SPU2_MMIO_HWPORT();
979
980 attr->core = core;
981 attr->mode = g_EffectAttr[core].mode;
982 attr->delay = g_EffectAttr[core].delay;
983 attr->feedback = g_EffectAttr[core].feedback;
984 attr->depth_L = spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll;
985 attr->depth_R = spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr;
986}
987
988int sceSdSetEffectAttr(int core, const sceSdEffectAttr *attr)
989{
990 int clearram;
991 int channel;
992 int mode;
993 int effects_enabled;
994 int retval;
995 struct mode_data_struct mode_data;
996 int state;
997 int effect_mode;
998 USE_SPU2_MMIO_HWPORT();
999
1000 mode_data.m_mode_flags = 0;
1001 mode = attr->mode;
1002 clearram = !!(mode & SD_EFFECT_MODE_CLEAR);
1003 effect_mode = clearram ? g_EffectAttr[core].mode : 0;
1004 channel = clearram && !!(mode & 0x200);
1005 mode &= 0xFF;
1006 // Check if valid mode
1007 if ( mode > SD_EFFECT_MODE_PIPE )
1008 return -100;
1009 g_EffectAttr[core].mode = mode;
1010 g_EffectAddr[core] = GetEEA(core) - ((g_EffectSizes[mode] << 3) - 1);
1011 // Unoffical: use memcpy from sysclib
1012 memcpy(&mode_data, &g_EffectParams[mode], sizeof(mode_data));
1013 switch ( mode )
1014 {
1015 case SD_EFFECT_MODE_ECHO:
1016 g_EffectAttr[core].feedback = 0x80;
1017 g_EffectAttr[core].delay = 0x80;
1018 break;
1019 case SD_EFFECT_MODE_DELAY:
1020 g_EffectAttr[core].feedback = 0;
1021 g_EffectAttr[core].delay = 0x80;
1022 break;
1023 default:
1024 g_EffectAttr[core].feedback = 0;
1025 g_EffectAttr[core].delay = 0;
1026 break;
1027 }
1028 if ( mode >= SD_EFFECT_MODE_ECHO && mode <= SD_EFFECT_MODE_DELAY )
1029 {
1030 int delay;
1031
1032 delay = attr->delay;
1033 g_EffectAttr[core].delay = delay;
1034 g_EffectAttr[core].feedback = attr->feedback;
1035 delay += 1;
1036 delay &= 0xFFFF;
1037 mode_data.m_d_same_l_dst = (s16)((u16)delay << 6) - (s16)mode_data.m_d_apf1_size;
1038 delay <<= 5;
1039 delay &= 0xFFFF;
1040 mode_data.m_d_same_l_src = delay + mode_data.m_d_same_r_src;
1041 mode_data.m_d_same_r_dst = delay - mode_data.m_d_apf2_size;
1042 mode_data.m_d_comb1_l_src = delay + mode_data.m_d_comb1_r_src;
1043 mode_data.m_d_apf1_l_dst = delay + mode_data.m_d_apf2_l_dst;
1044 mode_data.m_d_apf1_r_dst = delay + mode_data.m_d_apf2_r_dst;
1045 mode_data.m_d_wall_vol = 0x102 * g_EffectAttr[core].feedback;
1046 }
1047 // Disable effects
1048 effects_enabled = (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 7) & 1;
1049 if ( effects_enabled )
1050 {
1051 CpuSuspendIntr(&state);
1052 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_ENABLE_EFFECTS;
1053 CpuResumeIntr(state);
1054 }
1055 // Clean up after last mode
1056 retval = (effects_enabled && clearram) ? sceSdClearEffectWorkArea(core, channel, effect_mode) : 0;
1057 if ( retval >= 0 )
1058 {
1059 // Depth / Volume
1060 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll = attr->depth_L;
1061 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr = attr->depth_R;
1062 SetEffectData(core, &mode_data);
1063 // Set effect start addr (ESA)
1064 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[0] = g_EffectAddr[core] >> 17;
1065 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[1] = g_EffectAddr[core] >> 1;
1066 retval = clearram ? sceSdClearEffectWorkArea(core, channel, mode) : 0;
1067 }
1068 // Enable effects
1069 if ( effects_enabled )
1070 {
1071 CpuSuspendIntr(&state);
1072 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr |= SD_ENABLE_EFFECTS;
1073 CpuResumeIntr(state);
1074 }
1075 return retval;
1076}
1077
1078static int GetEEA(int core)
1079{
1080 USE_SPU2_MMIO_HWPORT();
1081
1082 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_eea << 17) | 0x1FFFF;
1083}
1084
1085int sceSdSetEffectMode(int core, const sceSdEffectAttr *param)
1086{
1087 int clearram;
1088 int channel;
1089 u32 mode;
1090 int effects_enabled;
1091 struct mode_data_struct mode_data;
1092 int state;
1093 USE_SPU2_MMIO_HWPORT();
1094
1095 mode_data.m_mode_flags = 0;
1096 mode = param->mode;
1097 clearram = !!(mode & 0x100);
1098 channel = clearram && !!(mode & 0x200);
1099 mode &= 0xFF;
1100 if ( mode > SD_EFFECT_MODE_PIPE )
1101 return -100;
1102 g_EffectAttr[core].mode = mode;
1103 g_EffectAttr[core].delay = 0;
1104 g_EffectAttr[core].feedback = 0;
1105 g_EffectAddr[core] = GetEEA(core) - ((g_EffectSizes[mode] << 3) - 1);
1106 // Unoffical: don't use inlined memcpy
1107 memcpy(&mode_data, &g_EffectParams[mode], sizeof(mode_data));
1108 effects_enabled = (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 7) & 1;
1109 if ( effects_enabled )
1110 {
1111 CpuSuspendIntr(&state);
1112 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_ENABLE_EFFECTS;
1113 CpuResumeIntr(state);
1114 }
1115 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll = 0;
1116 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr = 0;
1117 SetEffectData(core, &mode_data);
1118 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[0] = g_EffectAddr[core] >> 17;
1119 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[1] = g_EffectAddr[core] >> 1;
1120 if ( effects_enabled )
1121 {
1122 CpuSuspendIntr(&state);
1123 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr |= SD_ENABLE_EFFECTS;
1124 CpuResumeIntr(state);
1125 }
1126 return clearram ? sceSdCleanEffectWorkArea(core, channel, mode) : 0;
1127}
1128
1129int sceSdSetEffectModeParams(int core, const sceSdEffectAttr *attr)
1130{
1131 int mode;
1132 struct mode_data_struct mode_data;
1133 USE_SPU2_MMIO_HWPORT();
1134
1135 mode = attr->mode;
1136 mode &= 0xFF;
1137 if ( mode > SD_EFFECT_MODE_PIPE )
1138 return -100;
1139 if ( g_EffectAttr[core].mode != mode )
1140 return -100;
1141 if ( mode >= SD_EFFECT_MODE_ECHO && mode <= SD_EFFECT_MODE_DELAY )
1142 {
1143 int delay;
1144
1145 // Unoffical: don't use inlined memcpy
1146 memcpy(&mode_data, &g_EffectParams[mode], sizeof(mode_data));
1147 mode_data.m_mode_flags = 0xC011C80;
1148 delay = attr->delay;
1149 g_EffectAttr[core].delay = delay;
1150 g_EffectAttr[core].feedback = attr->feedback;
1151 delay += 1;
1152 delay &= 0xFFFF;
1153 mode_data.m_d_same_l_dst = (s16)(((u16)delay << 6) - (s16)mode_data.m_d_apf1_size);
1154 delay <<= 5;
1155 delay &= 0xFFFF;
1156 mode_data.m_d_same_l_src = delay + mode_data.m_d_same_r_src;
1157 mode_data.m_d_same_r_dst = delay - mode_data.m_d_apf2_size;
1158 mode_data.m_d_comb1_l_src = delay + mode_data.m_d_comb1_r_src;
1159 mode_data.m_d_apf1_l_dst = delay + mode_data.m_d_apf2_l_dst;
1160 mode_data.m_d_apf1_r_dst = delay + mode_data.m_d_apf2_r_dst;
1161 mode_data.m_d_wall_vol = 0x102 * g_EffectAttr[core].feedback;
1162 SetEffectData(core, &mode_data);
1163 }
1164 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll = attr->depth_L;
1165 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr = attr->depth_R;
1166 return 0;
1167}
1168
1169static void InitSpu2_Inner(void)
1170{
1171 int state;
1172 USE_IOP_MMIO_HWPORT();
1173
1174 iop_mmio_hwport->ssbus2.ind_4_address = 0xBF900000;
1175 iop_mmio_hwport->ssbus2.ind_9_address = 0xBF900800;
1176 CpuSuspendIntr(&state);
1177 iop_mmio_hwport->dmac1.dpcr1 |= 0x80000;
1178 iop_mmio_hwport->dmac2.dpcr2 |= 8;
1179 CpuResumeIntr(state);
1180 iop_mmio_hwport->ssbus1.ind_4_delay = 0x200B31E1;
1181 iop_mmio_hwport->ssbus2.ind_9_delay = 0x200B31E1;
1182}
1183
1184static void InitSpu2(void)
1185{
1186 USE_SPU2_MMIO_HWPORT();
1187
1188 InitSpu2_Inner();
1189 spu2_mmio_hwport->m_u.m_e.m_spdif_mode = 0x0900;
1190 spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0x200;
1191 spu2_mmio_hwport->m_u.m_e.m_unknown7ca = 8;
1192}
1193
1194// Core / Volume Registers
1195static void InitCoreVolume(int flag)
1196{
1197 int i;
1198 USE_SPU2_MMIO_HWPORT();
1199
1200 spu2_mmio_hwport->m_u.m_e.m_spdif_out = 0xC032;
1201 // Unofficial: rerolled
1202 for ( i = 0; i < 2; i += 1 )
1203 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr =
1204 (flag ? SD_ENABLE_EFFECTS : 0) | (i ? SD_ENABLE_EX_INPUT : 0) | SD_MUTE | SD_SPU2_ON;
1205 // Unofficial: rerolled
1206 // HIgh is voices 0-15, Low is 16-23, representing voices 0..23 (24)
1207 for ( i = 0; i < 2; i += 1 )
1208 {
1209 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixl.m_pair[0] = 0xFFFF;
1210 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixl.m_pair[1] = 0xFF;
1211 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixel.m_pair[0] = 0xFFFF;
1212 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixel.m_pair[1] = 0x00FF;
1213 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixr.m_pair[0] = 0xFFFF;
1214 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixr.m_pair[1] = 0x00FF;
1215 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixer.m_pair[0] = 0xFFFF;
1216 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixer.m_pair[1] = 0x00FF;
1217 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_mmix = 0xFF0 + (i * 0xC);
1218 }
1219 if ( !flag )
1220 {
1221 // Unofficial: rerolled
1222 for ( i = 0; i < 2; i += 1 )
1223 {
1224 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvoll = 0;
1225 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvolr = 0;
1226 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_evoll = 0;
1227 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_evolr = 0;
1228 }
1229 // Unofficial: rerolled
1230 // Effect End Address, Upper part
1231 for ( i = 0; i < 2; i += 1 )
1232 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_eea = 14 + i;
1233 }
1234 // Unofficial: rerolled
1235 for ( i = 0; i < 2; i += 1 )
1236 {
1237 // Core 1 External Input Volume.
1238 // The external Input is Core 0's output.
1239 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_avoll = i ? 0x7FFF : 0;
1240 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_avolr = i ? 0x7FFF : 0;
1241 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_bvoll = 0;
1242 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_bvolr = 0;
1243 }
1244}
1245
1246int sceSdVoiceTrans(s16 chan, u16 mode, u8 *iopaddr, u32 *spuaddr, u32 size)
1247{
1248 int core;
1249
1250 core = chan & 1;
1251 if ( !size )
1252 return -100;
1253 if ( DmaStartStop((core << 4) | 4, 0, 0) )
1254 return -210;
1255 if ( g_VoiceTransIoMode[core] != 1 )
1256 return -201;
1257 switch ( mode & 3 )
1258 {
1259 case SD_TRANS_READ:
1260 g_TransIntrData[core].m_mode = core | 0x900;
1261 g_BlockHandlerIntrData[core].m_cb = 0;
1262 g_BlockHandlerIntrData[core].m_userdata = 0;
1263 g_VoiceTransStatus[core] = 0;
1264 DmaStartStop((core << 4) | 2, spuaddr, 0);
1265 if ( QueryIntrContext() )
1266 iClearEventFlag(g_VoiceTransCompleteEf[core], ~1);
1267 else
1268 ClearEventFlag(g_VoiceTransCompleteEf[core], ~1);
1269 g_VoiceTransIoMode[core] = 0;
1270 return DmaStartStop((core << 4) | 5, iopaddr, (size & 0x3FFFFFF) + ((size & 0x3F) ? 0x40 : 0));
1271 case SD_TRANS_WRITE:
1272 g_TransIntrData[core].m_mode = core | 0x500;
1273 g_BlockHandlerIntrData[core].m_cb = 0;
1274 g_BlockHandlerIntrData[core].m_userdata = 0;
1275 DmaStartStop((core << 4) | 2, spuaddr, 0);
1276 if ( QueryIntrContext() )
1277 iClearEventFlag(g_VoiceTransCompleteEf[core], ~1);
1278 else
1279 ClearEventFlag(g_VoiceTransCompleteEf[core], ~1);
1280 g_VoiceTransIoMode[core] = 0;
1281 if ( !(mode & SD_TRANS_MODE_IO) )
1282 {
1283 g_VoiceTransStatus[core] = 0;
1284 return DmaStartStop((core << 4) | 6, iopaddr, (size & 0x3FFFFFF) + ((size & 0x3F) ? 0x40 : 0));
1285 }
1286 g_VoiceTransStatus[core] = 1;
1287 return VoiceTrans_Write_IOMode((u16 *)iopaddr, (size & 0x3FFFFFF) + ((size & 0x3F) ? 0x40 : 0), core);
1288 default:
1289 return -100;
1290 }
1291}
1292
1293u32 sceSdVoiceTransStatus(s16 channel, s16 flag)
1294{
1295 u32 efres;
1296 int core;
1297
1298 core = channel & 1;
1299 if ( g_VoiceTransStatus[core] == 1 || g_VoiceTransIoMode[core] == 1 )
1300 return 1;
1301 switch ( flag )
1302 {
1303 case 0:
1304 if ( g_VoiceTransCompleteBool[core] )
1305 {
1306 g_VoiceTransCompleteBool[core] = 0;
1307 g_VoiceTransIoMode[core] = 1;
1308 }
1309 break;
1310 case 1:
1311 if ( QueryIntrContext() )
1312 return -202;
1313 WaitEventFlag(g_VoiceTransCompleteEf[core], 1, 0, &efres);
1314 g_VoiceTransCompleteBool[core] = 0;
1315 g_VoiceTransIoMode[core] = 1;
1316 break;
1317 default:
1318 break;
1319 }
1320 return g_VoiceTransIoMode[core];
1321}
1322
1323int sceSdStopTrans(int channel)
1324{
1325 int core;
1326
1327 core = channel & 1;
1328 g_TransIntrData[core].m_mode = core;
1329 g_BlockHandlerIntrData[core].m_cb = 0;
1330 g_BlockHandlerIntrData[core].m_userdata = 0;
1331 return DmaStartStop((core << 4) | 0xA, 0, 0);
1332}
1333
1334int sceSdBlockTrans(s16 chan, u16 mode, u8 *iopaddr, u32 size, ...)
1335{
1336 int core;
1337 u32 started;
1338 int transfer_dir;
1339 int retres_1;
1340 uiptr vararg_elm1;
1341 uiptr vararg_elm2;
1342 uiptr vararg_elm3;
1343 va_list va2;
1344
1345 va_start(va2, size);
1346 vararg_elm1 = va_arg(va2, uiptr);
1347 vararg_elm2 = va_arg(va2, uiptr);
1348 vararg_elm3 = va_arg(va2, uiptr);
1349 va_end(va2);
1350 core = chan & 1;
1351 started = DmaStartStop((core << 4) | 4, 0, 0);
1352 transfer_dir = mode & 3;
1353 switch ( transfer_dir )
1354 {
1355 case SD_TRANS_READ:
1356 if ( !size )
1357 return -100;
1358 if ( started )
1359 return -210;
1360 g_TransIntrData[core].m_mode = core | 0xA00;
1361 g_BlockHandlerIntrData[core].m_cb = 0;
1362 g_BlockHandlerIntrData[core].m_userdata = 0;
1363 if ( (mode & 0x80) )
1364 {
1365 if ( !vararg_elm1 )
1366 {
1367 g_TransIntrData[core].m_mode = core;
1368 return -100;
1369 }
1370 g_BlockHandlerIntrData[core].m_cb = (void *)vararg_elm1;
1371 g_BlockHandlerIntrData[core].m_userdata = (void *)vararg_elm2;
1372 g_TransIntrData[core].m_mode |= 0x8000;
1373 }
1374 else if ( (mode & SD_TRANS_LOOP) )
1375 {
1376 size >>= 1;
1377 g_TransIntrData[core].m_mode |= SD_TRANS_LOOP << 8;
1378 }
1379 retres_1 = BlockTransRead(iopaddr, size, core, mode);
1380 break;
1381 case SD_TRANS_STOP:
1382 g_BlockHandlerIntrData[core].m_cb = 0;
1383 g_BlockHandlerIntrData[core].m_userdata = 0;
1384 g_TransIntrData[core].m_mode = core;
1385 return DmaStartStop((core << 4) | 0xA, 0, 0);
1386 case SD_TRANS_WRITE:
1387 case SD_TRANS_WRITE_FROM:
1388 if ( !size )
1389 return -100;
1390 if ( started )
1391 return -210;
1392 g_TransIntrData[core].m_mode = core | 0x600;
1393 g_BlockHandlerIntrData[core].m_cb = 0;
1394 g_BlockHandlerIntrData[core].m_userdata = 0;
1395 if ( (mode & 0x80) )
1396 {
1397 if ( !vararg_elm2 )
1398 {
1399 g_TransIntrData[core].m_mode = core;
1400 return -100;
1401 }
1402 g_BlockHandlerIntrData[core].m_cb = (void *)vararg_elm2;
1403 g_BlockHandlerIntrData[core].m_userdata = (void *)vararg_elm3;
1404 g_TransIntrData[core].m_mode |= 0x8000;
1405 }
1406 else if ( (mode & SD_TRANS_LOOP) )
1407 {
1408 size >>= 1;
1409 g_TransIntrData[core].m_mode |= SD_TRANS_LOOP << 8;
1410 }
1411 retres_1 =
1412 BlockTransWriteFrom(iopaddr, size, chan, mode, (transfer_dir == SD_TRANS_WRITE_FROM) ? (void *)vararg_elm1 : 0);
1413 break;
1414 default:
1415 return -100;
1416 }
1417 if ( retres_1 < 0 )
1418 {
1419 g_BlockHandlerIntrData[core].m_cb = 0;
1420 g_BlockHandlerIntrData[core].m_userdata = 0;
1421 g_TransIntrData[core].m_mode = core;
1422 }
1423 return retres_1;
1424}
1425
1426u32 sceSdBlockTransStatus(s16 channel, s16 flag)
1427{
1428 int core;
1429 // Unofficial: inline thunk
1430 USE_IOP_MMIO_HWPORT();
1431 USE_SPU2_MMIO_HWPORT();
1432
1433 (void)flag;
1434 core = channel & 1;
1435 return (g_BlockTransBuff[core] << 24)
1436 | (((spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas & 7) ?
1437 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr :
1438 0)
1439 & ~0xFF000000);
1440}
1441
1442static int InitSpdif()
1443{
1444 int i;
1445 USE_SPU2_MMIO_HWPORT();
1446
1447 spu2_mmio_hwport->m_u.m_e.m_spdif_out = 0;
1448 libsd_do_busyloop(2);
1449 spu2_mmio_hwport->m_u.m_e.m_spdif_out = 0x8000;
1450 libsd_do_busyloop(1);
1451 // Unofficial: rerolled
1452 for ( i = 0; i < 2; i += 1 )
1453 {
1454 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvoll = 0;
1455 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvolr = 0;
1456 }
1457 // Unofficial: rerolled
1458 for ( i = 0; i < 2; i += 1 )
1459 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_admas = 0;
1460 // Unofficial: rerolled
1461 for ( i = 0; i < 2; i += 1 )
1462 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_attr = 0;
1463 libsd_do_busyloop(1);
1464 // Unofficial: rerolled
1465 for ( i = 0; i < 2; i += 1 )
1466 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_attr = SD_SPU2_ON;
1467 // Unofficial: rerolled
1468 for ( i = 0; i < 2; i += 1 )
1469 {
1470 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvoll = 0;
1471 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvolr = 0;
1472 }
1473 for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_statx & 0x7FF)
1474 && (spu2_mmio_hwport->m_u.m_m.m_core_regs[1].m_cregs.m_statx & 0x7FF) && i < 0xF00;
1475 i += 1 )
1476 libsd_do_busyloop(1);
1477 // Unofficial: rerolled
1478 for ( i = 0; i < 2; i += 1 )
1479 {
1480 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_koff.m_pair[0] = 0xFFFF;
1481 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_koff.m_pair[1] = 0xFF;
1482 }
1483 // Unofficial: rerolled
1484 for ( i = 0; i < 2; i += 1 )
1485 {
1486 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_pmon.m_pair[0] = 0;
1487 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_pmon.m_pair[1] = 0;
1488 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_non.m_pair[0] = 0;
1489 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_non.m_pair[1] = 0;
1490 }
1491 return 0;
1492}
1493
1494static void SetDmaWrite(int chan)
1495{
1496 vu32 *dmachanptr;
1497 USE_IOP_MMIO_HWPORT();
1498
1499 dmachanptr = chan ? &iop_mmio_hwport->ssbus2.ind_9_delay : &iop_mmio_hwport->ssbus1.ind_4_delay;
1500 *dmachanptr &= ~0xF000000;
1501}
1502
1503static void SetDmaRead(int chan)
1504{
1505 vu32 *dmachanptr;
1506 USE_IOP_MMIO_HWPORT();
1507
1508 dmachanptr = chan ? &iop_mmio_hwport->ssbus2.ind_9_delay : &iop_mmio_hwport->ssbus1.ind_4_delay;
1509 *dmachanptr = (*dmachanptr & ~0xF000000) | 0x2000000;
1510}
1511
1512static void __attribute__((optimize("no-unroll-loops"))) libsd_do_busyloop_inner(void)
1513{
1514 int i;
1515 int loopmul;
1516
1517 loopmul = 13;
1518 for ( i = 0; i < 120; i += 1 )
1519 {
1520 loopmul *= 13;
1521 __asm__ __volatile__("" : "+g"(loopmul) : :);
1522 }
1523}
1524
1525static void libsd_do_busyloop(int count)
1526{
1527 int i;
1528
1529 for ( i = 0; i < count; i += 1 )
1530 libsd_do_busyloop_inner();
1531}
1532
1533static u32 DmaStartStop(int mainarg, void *vararg2, u32 vararg3)
1534{
1535 int core;
1536 u32 tsa_tmp;
1537 u32 vararg3_cal;
1538 u32 blocktransbufitem;
1539 int dma_addr;
1540 int i;
1541 int hichk;
1542 int state;
1543 USE_IOP_MMIO_HWPORT();
1544 USE_SPU2_MMIO_HWPORT();
1545
1546 // Unofficial: restrict core
1547 core = (mainarg >> 4) & 1;
1548 switch ( mainarg & 0xF )
1549 {
1550 case 2:
1551 tsa_tmp = ((u16)(uiptr)vararg2 >> 1) & ~7;
1552 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[1] = tsa_tmp;
1553 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[0] = (tsa_tmp >> 16) & 0xFFFF;
1554 return 0;
1555 case 4:
1556 if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_DMA_IN_PROCESS) )
1557 return -1;
1558 if ( ((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr & SD_DMA_START) )
1559 return -1;
1560 if ( spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas )
1561 return -1;
1562 return 0;
1563 case 5:
1564 CpuSuspendIntr(&state);
1565 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr |= SD_DMA_READ;
1566 CpuResumeIntr(state);
1567 SetDmaRead(core);
1568 vararg3_cal = (vararg3 >> 6) + (!!(vararg3 & 0x3F));
1569 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)vararg2;
1570#pragma GCC diagnostic push
1571#pragma GCC diagnostic ignored "-Wstrict-aliasing"
1572 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16;
1573#pragma GCC diagnostic pop
1574 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = vararg3_cal;
1575 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1576 SD_DMA_START | SD_DMA_CS | SD_DMA_DIR_SPU2IOP;
1577 return vararg3_cal << 6;
1578 case 6:
1579 CpuSuspendIntr(&state);
1580 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr =
1581 (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & ~SD_CORE_DMA) | SD_DMA_WRITE;
1582 CpuResumeIntr(state);
1583 SetDmaWrite(core);
1584 vararg3_cal = (vararg3 >> 6) + (!!(vararg3 & 0x3F));
1585 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)vararg2;
1586#pragma GCC diagnostic push
1587#pragma GCC diagnostic ignored "-Wstrict-aliasing"
1588 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16;
1589#pragma GCC diagnostic pop
1590 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = vararg3_cal;
1591 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1592 SD_DMA_START | SD_DMA_CS | SD_DMA_DIR_IOP2SPU;
1593 return vararg3_cal << 6;
1594 case 0xA:
1595 blocktransbufitem = 0;
1596 dma_addr = 0;
1597 if ( ((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr & SD_DMA_START) )
1598 {
1599 blocktransbufitem = g_BlockTransBuff[core];
1600 dma_addr = (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr;
1601 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr &= ~SD_DMA_START;
1602 if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) )
1603 {
1604 for ( i = 0; !(spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_statx & 0x80) && i < 0x1000000; i += 1 )
1605 {
1606 }
1607 }
1608 }
1609 if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) )
1610 {
1611 CpuSuspendIntr(&state);
1612 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1613 CpuResumeIntr(state);
1614 for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) && i < 0xF00; i += 1 )
1615 {
1616 }
1617 }
1618 hichk = 0;
1619 if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas & 7) )
1620 {
1621 hichk = 1;
1622 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 0;
1623 }
1624 if ( QueryIntrContext() )
1625 iSetEventFlag(g_VoiceTransCompleteEf[core], 1);
1626 else
1627 SetEventFlag(g_VoiceTransCompleteEf[core], 1);
1628 g_VoiceTransCompleteBool[core] = 0;
1629 g_VoiceTransIoMode[core] = 1;
1630 g_CleanHandlers[core] = 0;
1631 return (dma_addr && hichk) ? ((dma_addr & ~0xFF000000) | (blocktransbufitem << 24)) : 0;
1632 default:
1633 return 0;
1634 }
1635}
1636
1637static u32 VoiceTrans_Write_IOMode(const u16 *iopaddr, u32 size, int core)
1638{
1639 u32 size_tmp;
1640 int count;
1641 int i;
1642 int state;
1643 USE_SPU2_MMIO_HWPORT();
1644
1645 // Unofficial: restrict core
1646 core &= 1;
1647 for ( size_tmp = size; size_tmp; size_tmp -= count )
1648 {
1649 count = (size_tmp <= 0x40) ? size_tmp : 0x40;
1650 for ( i = 0; i < (count / 2); i += 1 )
1651 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_xferdata = iopaddr[i];
1652 CpuSuspendIntr(&state);
1653 // Set Transfer mode to IO
1654 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr =
1655 (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & ~SD_CORE_DMA) | SD_DMA_IO;
1656 CpuResumeIntr(state);
1657 // Wait for transfer to complete;
1658 for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_statx & SD_IO_IN_PROCESS) && i < 0xF00; i += 1 )
1659 libsd_do_busyloop(1);
1660 }
1661 CpuSuspendIntr(&state);
1662 // Reset DMA settings
1663 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1664 CpuResumeIntr(state);
1665 g_VoiceTransIoMode[core] = 1;
1666 // Unofficial: return size
1667 return size;
1668}
1669
1670static void do_finish_block_clean_xfer(int core)
1671{
1672 USE_SPU2_MMIO_HWPORT();
1673
1674 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1675 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 0;
1676}
1677
1678static int TransInterrupt(IntrData *intr)
1679{
1680 int dma_dir;
1681 u32 mode;
1682 int core;
1683 int i;
1684 void *dma_addr;
1685 int dma_size;
1686 USE_IOP_MMIO_HWPORT();
1687 USE_SPU2_MMIO_HWPORT();
1688
1689 mode = intr->m_mode;
1690 switch ( mode & 0xC00 )
1691 {
1692 case 0x400:
1693 dma_dir = SD_DMA_DIR_IOP2SPU;
1694 break;
1695 case 0x800:
1696 dma_dir = SD_DMA_DIR_SPU2IOP;
1697 break;
1698 default:
1699 return 1;
1700 }
1701 core = mode & 1;
1702 switch ( mode & 0x300 )
1703 {
1704 // Voice Transfer
1705 case 0x100:
1706 // SD_C_STATX(core)
1707 // If done elsewise, it doesn't work, havn't figured out why yet.
1708 for ( i = 0; !(spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_statx & 0x80) && i < 0x1000000; i += 1 )
1709 {
1710 }
1711 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1712 for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) && i < 0xF00; i += 1 )
1713 {
1714 }
1715 if ( dma_dir == SD_DMA_DIR_SPU2IOP )
1716 FlushDcache();
1717 if ( g_CleanHandlers[core] )
1718 g_CleanHandlers[core](core);
1719 else
1720 {
1721 iSetEventFlag(g_VoiceTransCompleteEf[core], 1);
1722 if ( g_TransIntrHandlers[core] )
1723 {
1724 g_VoiceTransIoMode[core] = 1;
1725 g_TransIntrHandlers[core](core, intr->m_data);
1726 }
1727 else if ( !g_TransIntrCallbacks[core] )
1728 g_VoiceTransCompleteBool[core] = 1;
1729 else
1730 {
1731 g_VoiceTransIoMode[core] = 1;
1732 g_TransIntrCallbacks[core](0);
1733 }
1734 }
1735 break;
1736 // Block Transfer
1737 case 0x200:
1738 if ( (mode & 0x8000) )
1739 {
1740 if ( g_BlockHandlerIntrData[core].m_cb )
1741 {
1742 g_BlockHandlerIntrData[core].m_cb(core, g_BlockHandlerIntrData[core].m_userdata, &dma_addr, &dma_size);
1743 if ( dma_size > 0 )
1744 {
1745 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] =
1746 (dma_size >> 6) + (dma_size - (dma_size & 0x3FFFFFF) > 0);
1747 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)dma_addr;
1748 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1749 dma_dir | SD_DMA_START | SD_DMA_CS;
1750 }
1751 else
1752 {
1753 do_finish_block_clean_xfer(core);
1754 g_BlockHandlerIntrData[core].m_cb = 0;
1755 g_BlockHandlerIntrData[core].m_userdata = 0;
1756 }
1757 }
1758 else
1759 do_finish_block_clean_xfer(core);
1760 if ( dma_dir == SD_DMA_DIR_SPU2IOP )
1761 FlushDcache();
1762 }
1763 else
1764 {
1765 if ( (mode & (SD_TRANS_LOOP << 8)) )
1766 {
1767 // Switch buffers
1768 g_BlockTransBuff[core] = 1 - g_BlockTransBuff[core];
1769 // Setup DMA & send
1770 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] =
1771 (int)g_BlockTransSize[core] / 0x40 + ((int)g_BlockTransSize[core] % 0x40 > 0);
1772 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr =
1773 (uiptr)(g_BlockTransAddr[core] + g_BlockTransBuff[core] * g_BlockTransSize[core]);
1774 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1775 dma_dir | SD_DMA_START | SD_DMA_CS;
1776 }
1777 else
1778 do_finish_block_clean_xfer(core);
1779 if ( dma_dir == SD_DMA_DIR_SPU2IOP )
1780 FlushDcache();
1781 if ( g_TransIntrHandlers[core] )
1782 g_TransIntrHandlers[core](core, intr->m_data);
1783 else if ( g_TransIntrCallbacks[core] )
1784 g_TransIntrCallbacks[core](0);
1785 }
1786 break;
1787 default:
1788 break;
1789 }
1790 return 1;
1791}
1792
1793static u32 BlockTransWriteFrom(u8 *iopaddr, u32 size, int core, int mode, u8 *startaddr)
1794{
1795 u8 *startaddr_tmp;
1796 int size_align;
1797 int size_align_r6;
1798 int state;
1799 USE_IOP_MMIO_HWPORT();
1800 USE_SPU2_MMIO_HWPORT();
1801
1802 core &= 1;
1803 startaddr_tmp = startaddr;
1804 g_BlockTransAddr[core] = iopaddr;
1805 g_BlockTransBuff[core] = 0;
1806 g_BlockTransSize[core] = size;
1807 if ( startaddr )
1808 {
1809 size_align = size - (startaddr - iopaddr);
1810 if ( (u32)(startaddr - iopaddr) >= size )
1811 {
1812 u32 other_align;
1813
1814 other_align = startaddr - iopaddr - size;
1815 if ( !(mode & SD_TRANS_LOOP) || other_align >= size )
1816 return -100;
1817 g_BlockTransBuff[core] += 1;
1818 size_align = size - other_align;
1819 }
1820 if ( size_align % 0x400 > 0 )
1821 {
1822 size_align = (size_align / 0x400 + 1) << 10;
1823 startaddr_tmp = iopaddr + g_BlockTransBuff[core] * size + size - size_align;
1824 }
1825 }
1826 else
1827 {
1828 startaddr_tmp = iopaddr;
1829 size_align = size;
1830 }
1831 CpuSuspendIntr(&state);
1832 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1833 CpuResumeIntr(state);
1834 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[0] = 0;
1835 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[1] = 0;
1836 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 1 << core;
1837 SetDmaWrite(core);
1838 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)startaddr_tmp;
1839#pragma GCC diagnostic push
1840#pragma GCC diagnostic ignored "-Wstrict-aliasing"
1841 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16;
1842#pragma GCC diagnostic pop
1843 size_align_r6 = ((size_align < 0) ? (size_align + 63) : size_align) >> 6;
1844 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] =
1845 size_align_r6 + (size_align - (size_align_r6 << 6) > 0);
1846 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1847 SD_DMA_START | SD_DMA_CS | SD_DMA_DIR_IOP2SPU;
1848 return size;
1849}
1850
1851static u32 BlockTransRead(u8 *iopaddr, u32 size, int core, u16 mode)
1852{
1853 int state;
1854 USE_IOP_MMIO_HWPORT();
1855 USE_SPU2_MMIO_HWPORT();
1856
1857 core &= 1;
1858 g_BlockTransAddr[core] = iopaddr;
1859 g_BlockTransBuff[core] = 0;
1860 g_BlockTransSize[core] = size;
1861 CpuSuspendIntr(&state);
1862 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1863 CpuResumeIntr(state);
1864 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[0] = 0;
1865 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[1] = ((mode & ~0xF0FF) << 1) + 0x400;
1866 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_unk1ae = (mode & ~0xFFF) >> 11;
1867 libsd_do_busyloop(3);
1868 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 4;
1869 SetDmaRead(core);
1870 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)iopaddr;
1871#pragma GCC diagnostic push
1872#pragma GCC diagnostic ignored "-Wstrict-aliasing"
1873 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16;
1874#pragma GCC diagnostic pop
1875 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] =
1876 (int)g_BlockTransSize[core] / 0x40 + ((int)g_BlockTransSize[core] % 0x40 > 0);
1877 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr = SD_DMA_START | SD_DMA_CS;
1878 return size;
1879}
1880
1881static int SifDmaBatch(void *ee_addr, void *iop_addr, int size)
1882{
1883 int dmat;
1884 int i;
1885 int dma_status;
1886 SifDmaTransfer_t xferparam;
1887 int state;
1888
1889 xferparam.dest = ee_addr;
1890 xferparam.src = iop_addr;
1891 xferparam.size = size;
1892 xferparam.attr = 0;
1893 CpuSuspendIntr(&state);
1894 dmat = sceSifSetDma(&xferparam, SIF_DMA_TO_EE);
1895 CpuResumeIntr(state);
1896 if ( !dmat )
1897 return -1;
1898 for ( i = 0, dma_status = 0; i >= 0 && dma_status >= 0; i += 1 )
1899 {
1900 CpuSuspendIntr(&state);
1901 dma_status = sceSifDmaStat(dmat);
1902 CpuResumeIntr(state);
1903 }
1904 return (i < 0) ? -1 : 0;
1905}
1906
1907int sceSdProcBatch(const sceSdBatch *batch, u32 *rets, u32 num)
1908{
1909 u32 cnt;
1910
1911 for ( cnt = 0; cnt < num; cnt += 1 )
1912 {
1913 u32 Param;
1914
1915 Param = 0;
1916 switch ( batch[cnt].func )
1917 {
1918 case SD_BATCH_SETPARAM:
1919 sceSdSetParam(batch[cnt].entry, batch[cnt].value);
1920 break;
1921 case SD_BATCH_SETSWITCH:
1922 sceSdSetSwitch(batch[cnt].entry, batch[cnt].value);
1923 break;
1924 case SD_BATCH_SETADDR:
1925 sceSdSetAddr(batch[cnt].entry, batch[cnt].value);
1926 break;
1927 case SD_BATCH_SETCORE:
1928 sceSdSetCoreAttr(batch[cnt].entry, batch[cnt].value);
1929 break;
1930 case SD_BATCH_WRITEIOP:
1931 *(u32 *)batch[cnt].value = batch[cnt].entry;
1932 break;
1933 case SD_BATCH_WRITEEE:
1934 g_BatchData = batch[cnt].entry;
1935 Param = SifDmaBatch((void *)batch[cnt].value, &g_BatchData, sizeof(g_BatchData));
1936 break;
1937 case SD_BATCH_EERETURN:
1938 Param = SifDmaBatch((void *)batch[cnt].value, rets, batch[cnt].entry);
1939 break;
1940 case SD_BATCH_GETPARAM:
1941 Param = sceSdGetParam(batch[cnt].entry);
1942 break;
1943 case SD_BATCH_GETSWITCH:
1944 Param = sceSdGetSwitch(batch[cnt].entry);
1945 break;
1946 case SD_BATCH_GETADDR:
1947 Param = sceSdGetAddr(batch[cnt].entry);
1948 break;
1949 case SD_BATCH_GETCORE:
1950 Param = sceSdGetCoreAttr(batch[cnt].entry);
1951 break;
1952 default:
1953 return ~cnt;
1954 }
1955 if ( rets )
1956 rets[cnt] = Param;
1957 }
1958 return cnt;
1959}
1960
1961int sceSdProcBatchEx(const sceSdBatch *batch, u32 *rets, u32 num, u32 voice)
1962{
1963 u32 cnt;
1964 int loop;
1965 int i;
1966
1967 loop = 0;
1968 for ( cnt = 0; cnt < num; cnt += 1 )
1969 {
1970 u32 Param;
1971
1972 Param = 0;
1973 switch ( batch[cnt].func )
1974 {
1975 case SD_BATCH_SETPARAM:
1976 if ( (batch[cnt].entry & 0x3E) == 0x3E )
1977 {
1978 for ( i = 0; i < 24; i += 1 )
1979 {
1980 if ( ((1 << i) & voice) )
1981 {
1982 loop += 1;
1983 sceSdSetParam((batch[cnt].entry & ~0x3E) | (i << 1), batch[cnt].value);
1984 }
1985 }
1986 loop -= 1;
1987 }
1988 else
1989 sceSdSetParam(batch[cnt].entry, batch[cnt].value);
1990 break;
1991 case SD_BATCH_SETSWITCH:
1992 sceSdSetSwitch(batch[cnt].entry, batch[cnt].value);
1993 break;
1994 case SD_BATCH_SETADDR:
1995 if ( (batch[cnt].entry & 0x7E) == 0x7E )
1996 {
1997 for ( i = 0; i < 24; i += 1 )
1998 {
1999 if ( ((1 << i) & voice) )
2000 {
2001 loop += 1;
2002 sceSdSetAddr((batch[cnt].entry & ~0x3E) | (i << 1), batch[cnt].value);
2003 }
2004 }
2005 loop -= 1;
2006 }
2007 else
2008 sceSdSetAddr(batch[cnt].entry, batch[cnt].value);
2009 break;
2010 case SD_BATCH_SETCORE:
2011 sceSdSetCoreAttr(batch[cnt].entry, batch[cnt].value);
2012 break;
2013 case SD_BATCH_WRITEIOP:
2014 *(u32 *)batch[cnt].value = batch[cnt].entry;
2015 break;
2016 case SD_BATCH_WRITEEE:
2017 g_BatchData = batch[cnt].entry;
2018 Param = SifDmaBatch((void *)batch[cnt].value, &g_BatchData, sizeof(g_BatchData));
2019 break;
2020 case SD_BATCH_EERETURN:
2021 Param = SifDmaBatch((void *)batch[cnt].value, rets, batch[cnt].entry);
2022 break;
2023 case SD_BATCH_GETPARAM:
2024 if ( (batch[cnt].entry & 0x3E) == 0x3E )
2025 {
2026 for ( i = 0; i < 24; i += 1 )
2027 {
2028 if ( ((1 << i) & voice) )
2029 Param = sceSdGetParam((batch[cnt].entry & ~0x3E) | (i << 1));
2030 if ( rets )
2031 rets[loop] = Param;
2032 loop += 1;
2033 }
2034 loop -= 1;
2035 }
2036 else
2037 Param = sceSdGetParam(batch[cnt].entry);
2038 break;
2039 case SD_BATCH_GETSWITCH:
2040 Param = sceSdGetSwitch(batch[cnt].entry);
2041 break;
2042 case SD_BATCH_GETADDR:
2043 if ( (batch[cnt].entry & 0x7E) == 0x7E )
2044 {
2045 for ( i = 0; i < 24; i += 1 )
2046 {
2047 if ( ((1 << i) & voice) )
2048 {
2049 Param = sceSdGetAddr((batch[cnt].entry & ~0x3E) | (i << 1));
2050 if ( rets )
2051 rets[loop] = Param;
2052 loop += 1;
2053 }
2054 }
2055 loop -= 1;
2056 }
2057 else
2058 Param = sceSdGetAddr(batch[cnt].entry);
2059 break;
2060 case SD_BATCH_GETCORE:
2061 Param = sceSdGetCoreAttr(batch[cnt].entry);
2062 break;
2063 default:
2064 return ~cnt;
2065 }
2066 if ( rets )
2067 rets[loop] = Param;
2068 loop += 1;
2069 }
2070 return loop;
2071}
2072
2073void sceSdSetParam(u16 entry, u16 value)
2074{
2075 // Determine the channel offset (entry & 0x80)
2076 g_ParamRegList[((entry >> 8) & 0xFF)]
2077 [((entry & 0x3E) << 2) + (((entry & 1) * (0x400 - 984 * (!!(entry & 0x80)))) >> 1)] = value;
2078}
2079
2080u16 sceSdGetParam(u16 entry)
2081{
2082 // Determine the channel offset (entry & 0x80)
2083 return g_ParamRegList[((entry >> 8) & 0xFF)]
2084 [((entry & 0x3E) << 2) + (((entry & 1) * (0x400 - 984 * (!!(entry & 0x80)))) >> 1)];
2085}
2086
2087void sceSdSetSwitch(u16 entry, u32 value)
2088{
2089 vu16 *regptr;
2090
2091 regptr = &g_ParamRegList[((entry >> 8) & 0xFF)][(entry & 1) << 9];
2092 regptr[0] = value;
2093 regptr[1] = (value >> 16) & 0xFF;
2094}
2095
2096u32 sceSdGetSwitch(u16 entry)
2097{
2098 const vu16 *regptr;
2099
2100 regptr = &g_ParamRegList[((entry >> 8) & 0xFF)][(entry & 1) << 9];
2101 return regptr[0] | (regptr[1] << 16);
2102}
2103
2104void sceSdSetAddr(u16 entry, u32 value)
2105{
2106 vu16 *reg1;
2107
2108 reg1 = &g_ParamRegList[((entry >> 8) & 0xFF)][((entry & 1) << 9) + 3 * (entry & 0x3E)];
2109 reg1[0] = value >> 17;
2110 if ( (entry & 0xFF00) != 0x1D00 )
2111 reg1[1] = (value >> 1) & ~7;
2112}
2113
2114u32 sceSdGetAddr(u16 entry)
2115{
2116 int retlo;
2117 const vu16 *reg1;
2118 int regmask;
2119 int rethi;
2120
2121 retlo = 0x1FFFF;
2122 reg1 = &g_ParamRegList[((entry >> 8) & 0xFF)][((entry & 1) << 9) + 3 * (entry & 0x3E)];
2123 regmask = entry & 0xFF00;
2124 rethi = reg1[0] << 17;
2125 if ( regmask != 0x1D00 )
2126 {
2127 retlo = reg1[1] << 1;
2128 if ( regmask == 0x2100 || regmask == 0x2200 )
2129 {
2130 rethi = reg1[0] << 17;
2131 retlo = reg1[1] << 1;
2132 }
2133 }
2134 return rethi | retlo;
2135}
2136
2137u16 sceSdNote2Pitch(u16 center_note, u16 center_fine, u16 note, s16 fine)
2138{
2139 int _fine;
2140 s16 _note;
2141 int _fine2;
2142 int offset2;
2143 int val2;
2144 s16 val;
2145 s16 offset1;
2146 int retval;
2147
2148 _fine = fine + center_fine;
2149 _fine2 = _fine / 0x80;
2150 _note = note + _fine2 - center_note;
2151 offset2 = _fine % 0x80;
2152 val2 = ((_note / 6) >> 1) - (_note < 0);
2153 offset1 = _note - 12 * val2;
2154 val = val2 - 2;
2155 if ( (offset1 < 0) || (!offset1 && offset2 < 0) )
2156 {
2157 offset1 += 12;
2158 val -= 1;
2159 }
2160 if ( offset2 < 0 )
2161 {
2162 offset2 += (_fine2 + 1) << 7;
2163 offset1 -= 1;
2164 offset1 += _fine2;
2165 }
2166 retval = (g_NotePitchTable[offset1] * g_NotePitchTable[offset2 + 12]) >> 16;
2167 return (val < 0) ? (u32)(retval + (1 << (-val - 1))) >> -val : (u32)retval;
2168}
2169
2170u16 sceSdPitch2Note(u16 center_note, u16 center_fine, u16 pitch)
2171{
2172 int bit;
2173 int i1;
2174 s16 val;
2175 int i2;
2176 int i5;
2177
2178 bit = 0;
2179 pitch = (pitch > 0x3FFF) ? 0x3FFF : pitch;
2180 for ( i1 = 0; i1 < 14; i1 += 1 )
2181 {
2182 if ( ((pitch >> i1) & 1) )
2183 bit = i1;
2184 }
2185 val = pitch << (15 - bit);
2186 for ( i2 = 11; val < g_NotePitchTable[i2] && i2 > 0; i2 -= 1 )
2187 {
2188 }
2189 if ( !g_NotePitchTable[i2] )
2190 __builtin_trap();
2191 val <<= 15;
2192 val /= g_NotePitchTable[i2];
2193 for ( i5 = 127; val < g_NotePitchTable[i5 + 12] && i5 > 0; i5 -= 1 )
2194 {
2195 }
2196 return (((center_fine + i5 + 1) & 0x7E)
2197 + ((i2 + center_note + 12 * (bit - 12) + ((u16)(center_fine + i5 + 1) >> 7)) << 8))
2198 & ~1;
2199}
2200
2201static int SetSpdifMode(int val)
2202{
2203 u16 spdif_out_new;
2204 u16 spdif_mode_new;
2205 USE_SPU2_MMIO_HWPORT();
2206
2207 spdif_out_new = spu2_mmio_hwport->m_u.m_e.m_spdif_out & ~0x1A8;
2208 spdif_mode_new = spu2_mmio_hwport->m_u.m_e.m_spdif_mode & ~0xBF06;
2209 switch ( val & 0xF )
2210 {
2211 case 0:
2212 spdif_out_new |= 0x20;
2213 break;
2214 case 1:
2215 spdif_out_new |= 0x100;
2216 spdif_mode_new |= 2;
2217 break;
2218 case 2:
2219 break;
2220 case 3:
2221 spdif_out_new |= 0x100;
2222 break;
2223 default:
2224 return -100;
2225 }
2226 spdif_mode_new |= (val & 0x80) ? 0x8000 : 0;
2227 switch ( val & 0xF00 )
2228 {
2229 case 0x400:
2230 spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0;
2231 spdif_mode_new |= 0x100;
2232 break;
2233 case 0x800:
2234 spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0x200;
2235 spdif_mode_new |= 0x1900;
2236 break;
2237 default:
2238 spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0x200;
2239 spdif_mode_new |= 0x900;
2240 break;
2241 }
2242 spu2_mmio_hwport->m_u.m_e.m_spdif_out = spdif_out_new;
2243 spu2_mmio_hwport->m_u.m_e.m_spdif_mode = spdif_mode_new;
2244 g_SpdifSettings = val;
2245 return 0;
2246}
2247
2248void sceSdSetCoreAttr(u16 entry, u16 value)
2249{
2250 u16 setting_tmp;
2251 u16 param_tmp;
2252 int state;
2253
2254 switch ( entry & ~0xFFFF0001 )
2255 {
2256 case SD_CORE_SPDIF_MODE:
2257 SetSpdifMode(value);
2258 break;
2259 case SD_CORE_NOISE_CLK:
2260 CpuSuspendIntr(&state);
2261 param_tmp = (entry & 1) | 0x2300;
2262 sceSdSetParam(param_tmp, (sceSdGetParam(param_tmp) & ~0x3F00) | ((value & 0x3F) << 8));
2263 CpuResumeIntr(state);
2264 break;
2265 default:
2266 // Unofficial: inline the following
2267 setting_tmp = g_CoreAttrShifts[((entry & 0xE) >> 1) - 1];
2268 CpuSuspendIntr(&state);
2269 param_tmp = (entry & 1) | 0x2300;
2270 sceSdSetParam(param_tmp, (sceSdGetParam(param_tmp) & ~(1 << setting_tmp)) | ((value & 1) << setting_tmp));
2271 CpuResumeIntr(state);
2272 break;
2273 }
2274}
2275
2276u16 sceSdGetCoreAttr(u16 entry)
2277{
2278 int core;
2279 USE_SPU2_MMIO_HWPORT();
2280
2281 core = entry & 1;
2282 switch ( entry & 0xE )
2283 {
2284 case SD_CORE_EFFECT_ENABLE:
2285 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 7) & 1;
2286 case SD_CORE_IRQ_ENABLE:
2287 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 6) & 1;
2288 case SD_CORE_MUTE_ENABLE:
2289 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 14) & 1;
2290 case SD_CORE_NOISE_CLK:
2291 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 8) & 0x3F;
2292 case SD_CORE_SPDIF_MODE:
2293 return g_SpdifSettings & 0xFFFF;
2294 default:
2295 return 0;
2296 }
2297}
2298
2299SdIntrCallback sceSdSetTransCallback(s32 core, SdIntrCallback cb)
2300{
2301 SdIntrCallback oldtmp;
2302
2303 // Unofficial: restrict core
2304 core &= 1;
2305 oldtmp = g_TransIntrCallbacks[core];
2306 g_TransIntrCallbacks[core] = cb;
2307 return oldtmp;
2308}
2309
2310sceSdTransIntrHandler sceSdSetTransIntrHandler(int channel, sceSdTransIntrHandler func, void *arg)
2311{
2312 sceSdTransIntrHandler oldtmp;
2313 int core;
2314
2315 // Unofficial: restrict core
2316 core = channel & 1;
2317 oldtmp = g_TransIntrHandlers[core];
2318 g_TransIntrHandlers[core] = func;
2319 g_TransIntrData[core].m_data = arg;
2320 return oldtmp;
2321}
2322
2323void *sceSdGetTransIntrHandlerArgument(int arg)
2324{
2325 return g_TransIntrData[arg].m_data;
2326}
2327
2328SdIntrCallback sceSdSetIRQCallback(SdIntrCallback cb)
2329{
2330 SdIntrCallback oldtmp;
2331
2332 oldtmp = g_Spu2IrqCallback;
2333 g_Spu2IrqCallback = cb;
2334 return oldtmp;
2335}
2336
2337sceSdSpu2IntrHandler sceSdSetSpu2IntrHandler(sceSdSpu2IntrHandler func, void *arg)
2338{
2339 sceSdSpu2IntrHandler oldtmp;
2340
2341 oldtmp = g_Spu2IntrHandler;
2342 g_Spu2IntrHandler = func;
2343 g_Spu2IntrHandlerData = arg;
2344 return oldtmp;
2345}
2346
2347void *sceSdGetSpu2IntrHandlerArgument()
2348{
2349 return g_Spu2IntrHandlerData;
2350}
2351
2352static int Spu2Interrupt(void *data)
2353{
2354 int val;
2355 USE_SPU2_MMIO_HWPORT();
2356
2357 (void)data;
2358 if ( !g_Spu2IntrHandler && !g_Spu2IrqCallback )
2359 return 1;
2360 while ( (val = (spu2_mmio_hwport->m_u.m_e.m_spdif_irqinfo & 0xC) >> 2) )
2361 {
2362 int i;
2363
2364 for ( i = 0; i < 2; i += 1 )
2365 if ( val & (1 << i) )
2366 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_attr &= ~0x40;
2367 if ( g_Spu2IntrHandler )
2368 g_Spu2IntrHandler(val, g_Spu2IntrHandlerData);
2369 else if ( g_Spu2IrqCallback )
2370 g_Spu2IrqCallback(0);
2371 }
2372 return 1;
2373}
2374
2375static int InitVoices(void)
2376{
2377 int i;
2378 int j;
2379 USE_SPU2_MMIO_HWPORT();
2380
2381 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr &= ~SD_CORE_DMA;
2382 // Set Start Address of data to transfer.
2383 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_tsa.m_pair[0] = 0x0000;
2384 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_tsa.m_pair[1] = 0x5000 >> 1;
2385 // Fill with data.
2386 // First 16 bytes are reserved.
2387 for ( i = 0; i < (int)(sizeof(g_VoiceDataInit) / sizeof(g_VoiceDataInit[0])); i += 1 )
2388 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_xferdata = g_VoiceDataInit[i];
2389
2390 // Set Transfer mode to IO
2391 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr =
2392 (spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr & ~SD_CORE_DMA) | SD_DMA_IO;
2393 // Wait for transfer to complete;
2394 for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_statx & SD_IO_IN_PROCESS) && i <= 0x1000000; i += 1 )
2395 libsd_do_busyloop(1);
2396 // Reset DMA settings
2397 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr &= ~SD_CORE_DMA;
2398 // Unofficial: rerolled
2399 // Init voices
2400 for ( i = 0; i < 24; i += 1 )
2401 {
2402 for ( j = 0; j < 2; j += 1 )
2403 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_voll = 0;
2404 for ( j = 0; j < 2; j += 1 )
2405 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_volr = 0;
2406 for ( j = 0; j < 2; j += 1 )
2407 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_pitch = 0x3FFF;
2408 for ( j = 0; j < 2; j += 1 )
2409 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_adsr1 = 0;
2410 for ( j = 0; j < 2; j += 1 )
2411 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_adsr2 = 0;
2412 for ( j = 0; j < 2; j += 1 )
2413 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_address[i].m_ssa.m_pair[0] = 0;
2414 // Top address of waveform data
2415 for ( j = 0; j < 2; j += 1 )
2416 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_address[i].m_ssa.m_pair[1] = 0x5000 >> 1;
2417 }
2418 // Unofficial: rerolled
2419 // Set all voices to ON
2420 for ( i = 0; i < 2; i += 1 )
2421 {
2422 spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_kon.m_pair[0] = 0xFFFF;
2423 spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_kon.m_pair[1] = 0xFF;
2424 }
2425 // There is no guarantee that voices will be turn on at once.
2426 // So we wait to make sure.
2427 libsd_do_busyloop(3);
2428 // Unofficial: rerolled
2429 // Set all voices to OFF
2430 for ( i = 0; i < 2; i += 1 )
2431 {
2432 spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_koff.m_pair[0] = 0xFFFF;
2433 spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_koff.m_pair[1] = 0xFF;
2434 }
2435 // There is no guarantee that voices will be turn off at once.
2436 // So we wait to make sure.
2437 libsd_do_busyloop(3);
2438 // Unofficial: rerolled
2439 for ( i = 0; i < 2; i += 1 )
2440 {
2441 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_endx.m_pair[1] = 0;
2442 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_endx.m_pair[0] = 0;
2443 }
2444 return 0;
2445}
2446
2447static int Reset(int flag)
2448{
2449 iop_event_t efparam;
2450 int intrstate;
2451 int i;
2452 USE_SPU2_MMIO_HWPORT();
2453
2454 DisableIntr(IOP_IRQ_DMA_SPU, &intrstate);
2455 DisableIntr(IOP_IRQ_DMA_SPU2, &intrstate);
2456 DisableIntr(IOP_IRQ_SPU, &intrstate);
2457 ReleaseIntrHandler(IOP_IRQ_DMA_SPU);
2458 ReleaseIntrHandler(IOP_IRQ_DMA_SPU2);
2459 ReleaseIntrHandler(IOP_IRQ_SPU);
2460 // Unofficial: rerolled
2461 for ( i = 0; i < 2; i += 1 )
2462 {
2463 g_VoiceTransStatus[i] = 0;
2464 g_VoiceTransIoMode[i] = 1;
2465 g_VoiceTransCompleteBool[i] = 0;
2466 g_TransIntrHandlers[i] = 0;
2467 g_CleanHandlers[i] = 0;
2468 g_TransIntrData[i].m_mode = i;
2469 g_TransIntrData[i].m_data = 0;
2470 g_BlockHandlerIntrData[i].m_cb = 0;
2471 g_BlockHandlerIntrData[i].m_userdata = 0;
2472 g_TransIntrCallbacks[i] = 0;
2473 }
2474 g_Spu2IntrHandler = 0;
2475 g_Spu2IntrHandlerData = 0;
2476 g_Spu2IrqCallback = 0;
2477 if ( !(flag & 0xF) )
2478 {
2479 bzero(g_EffectAttr, sizeof(g_EffectAttr));
2480 // Unofficial: rerolled
2481 for ( i = 0; i < 2; i += 1 )
2482 g_EffectAddr[i] = 0x1DFFF0 + (0x20000 * i);
2483 // Unofficial: rerolled
2484 for ( i = 0; i < 2; i += 1 )
2485 {
2486 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_esa.m_pair[0] = 0x000E + i;
2487 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_esa.m_pair[1] = 0xFFF8;
2488 }
2489 }
2490 efparam.attr = EA_MULTI;
2491 efparam.bits = 1;
2492 efparam.option = 0;
2493 // Unofficial: rerolled
2494 for ( i = 0; i < 2; i += 1 )
2495 {
2496 if ( g_VoiceTransCompleteEf[i] <= 0 )
2497 g_VoiceTransCompleteEf[i] = CreateEventFlag(&efparam);
2498 else
2499 {
2500 if ( QueryIntrContext() )
2501 iSetEventFlag(g_VoiceTransCompleteEf[i], 1);
2502 else
2503 SetEventFlag(g_VoiceTransCompleteEf[i], 1);
2504 }
2505 }
2506 return (g_VoiceTransCompleteEf[0] <= 0 || g_VoiceTransCompleteEf[1] <= 0) ? -301 : 0;
2507}
2508
2509static void reset_vars(void)
2510{
2511 int i;
2512
2513 g_vars_inited = 0;
2514 // Unofficial: rerolled
2515 for ( i = 0; i < 2; i += 1 )
2516 g_VoiceTransCompleteEf[i] = 0;
2517}
2518
2519int sceSdInit(int flag)
2520{
2521 int resetres;
2522
2523 InitSpu2();
2524 if ( !(flag & 0xF) )
2525 InitSpdif();
2526 resetres = Reset(flag);
2527 InitVoices();
2528 InitCoreVolume(flag & 0xF);
2529 EnableIntr(IOP_IRQ_DMA_SPU);
2530 EnableIntr(IOP_IRQ_DMA_SPU2);
2531 EnableIntr(IOP_IRQ_SPU);
2532 RegisterIntrHandler(IOP_IRQ_DMA_SPU, 1, (int (*)(void *))TransInterrupt, &g_TransIntrData[0]);
2533 RegisterIntrHandler(IOP_IRQ_DMA_SPU2, 1, (int (*)(void *))TransInterrupt, &g_TransIntrData[1]);
2534 RegisterIntrHandler(IOP_IRQ_SPU, 1, (int (*)(void *))Spu2Interrupt, g_Spu2IntrHandlerData);
2535 g_vars_inited = 1;
2536 return resetres;
2537}
2538
2539int sceSdQuit()
2540{
2541 int intrstate;
2542 int i;
2543
2544 // Unofficial: rerolled
2545 for ( i = 0; i < 2; i += 1 )
2546 DmaStartStop((i << 4) | 0xA, 0, 0);
2547 // Unofficial: rerolled
2548 for ( i = 0; i < 2; i += 1 )
2549 if ( g_VoiceTransCompleteEf[i] > 0 )
2550 DeleteEventFlag(g_VoiceTransCompleteEf[i]);
2551 DisableIntr(IOP_IRQ_DMA_SPU2, &intrstate);
2552 DisableIntr(IOP_IRQ_DMA_SPU, &intrstate);
2553 DisableIntr(IOP_IRQ_SPU, &intrstate);
2554 ReleaseIntrHandler(IOP_IRQ_DMA_SPU2);
2555 ReleaseIntrHandler(IOP_IRQ_DMA_SPU);
2556 ReleaseIntrHandler(IOP_IRQ_SPU);
2557 return 0;
2558}
int CpuResumeIntr(int state)
Definition intrman.c:227
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
int QueryIntrContext(void)
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int CpuSuspendIntr(int *state)
Definition intrman.c:205
int EnableIntr(int irq)
Definition intrman.c:346
#define EA_MULTI
Definition thevent.h:35
u32 count
start sector of fragmented bd/file