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