/[pcsx2_0.9.7]/branch/debug/0.X/0.9.X/0.9.7/r3113/plugins/zerospu2/zerodma.cpp
ViewVC logotype

Contents of /branch/debug/0.X/0.9.X/0.9.7/r3113/plugins/zerospu2/zerodma.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 171 - (show annotations) (download)
Mon Sep 13 16:38:21 2010 UTC (10 years, 2 months ago) by william
File size: 6008 byte(s)
fix warnings

1 /* ZeroSPU2
2 * Copyright (C) 2006-2010 zerofrog
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #include "zerospu2.h"
20 #include "zerodma.h"
21
22 #include <assert.h>
23 #include <stdlib.h>
24
25 #include "SoundTouch/SoundTouch.h"
26 #include "SoundTouch/WavFile.h"
27
28 void CALLBACK SPU2readDMAMem(u16 *pMem, s32 size, int channel)
29 {
30 u32 spuaddr = C_SPUADDR(channel);
31
32 SPU2_LOG("SPU2 readDMAMem(%d) size %x, addr: %x\n", channel, size, pMem);
33
34 for (s32 i = 0; i < size; i++)
35 {
36 *pMem++ = *(u16*)(spu2mem + spuaddr);
37 if (spu2attr(channel).irq && (C_IRQA(channel) == spuaddr))
38 {
39 C_SPUADDR_SET(spuaddr, channel);
40 IRQINFO |= (4 * (channel + 1));
41 SPU2_LOG("SPU2readDMAMem(%d):interrupt\n", channel);
42 irqCallbackSPU2();
43 }
44
45 spuaddr++; // inc spu addr
46 if (spuaddr > 0x0fffff) spuaddr=0; // wrap at 2Mb
47 }
48
49 spuaddr += 19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd)
50 C_SPUADDR_SET(spuaddr, channel);
51
52 // DMA complete
53 spu2stat_clear_80(channel);
54 SPUStartCycle[channel] = SPUCycles;
55 SPUTargetCycle[channel] = size;
56 interrupt |= (1 << (1 + channel));
57 }
58
59 void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size)
60 {
61 LOG_CALLBACK("SPU2readDMA4Mem()\n");
62 return SPU2readDMAMem(pMem, size, 0);
63 }
64
65 void CALLBACK SPU2readDMA7Mem(u16* pMem, int size)
66 {
67 LOG_CALLBACK("SPU2readDMA7Mem()\n");
68 return SPU2readDMAMem(pMem, size, 1);
69 }
70
71 // WRITE
72
73 // AutoDMA's are used to transfer to the DIRECT INPUT area of the spu2 memory
74 // Left and Right channels are always interleaved together in the transfer so
75 // the AutoDMA's deinterleaves them and transfers them. An interrupt is
76 // generated when half of the buffer (256 short-words for left and 256
77 // short-words for right ) has been transferred. Another interrupt occurs at
78 // the end of the transfer.
79
80 int ADMASWrite(int channel)
81 {
82 u32 spuaddr;
83 ADMA *Adma = &adma[channel];
84
85 if (interrupt & 0x2)
86 {
87 WARN_LOG("ADMASWrite(%d) returning for interrupt\n", channel);
88 return 0;
89 }
90
91 if (Adma->AmountLeft <= 0)
92 {
93 WARN_LOG("ADMASWrite(%d) amount left is 0\n", channel);
94 return 1;
95 }
96
97 assert( Adma->AmountLeft >= 512 );
98 spuaddr = C_SPUADDR(channel);
99 u32 left_addr = spuaddr + 0x2000 + c_offset(channel);
100 u32 right_addr = left_addr + 0x200;
101
102 // SPU2 Deinterleaves the Left and Right Channels
103 memcpy((s16*)(spu2mem + left_addr),(s16*)Adma->MemAddr,512);
104 Adma->MemAddr += 256;
105 memcpy((s16*)(spu2mem + right_addr),(s16*)Adma->MemAddr,512);
106 Adma->MemAddr += 256;
107
108 if (spu2attr(channel).irq && (irq_test1(channel, spuaddr) || irq_test2(channel, spuaddr)))
109 {
110 IRQINFO |= (4 * (channel + 1));
111 WARN_LOG("ADMAMem access(%d): interrupt\n", channel);
112 irqCallbackSPU2();
113 }
114
115 spuaddr = (spuaddr + 256) & 511;
116 C_SPUADDR_SET(spuaddr, channel);
117
118 Adma->AmountLeft -= 512;
119
120 return (Adma->AmountLeft <= 0);
121 }
122
123 void SPU2writeDMAMem(u16* pMem, int size, int channel)
124 {
125 u32 spuaddr;
126 ADMA *Adma = &adma[channel];
127 s32 offset = (channel == 0) ? 0 : 0x400;
128
129 SPU2_LOG("SPU2 writeDMAMem size %x, addr: %x(spu2:%x)"/*, ctrl: %x, adma: %x\n"*/, \
130 size, pMem, C_SPUADDR(channel)/*, spu2Ru16(REG_C0_CTRL + offset), spu2Ru16(REG_C0_ADMAS + offset)*/);
131
132 if (spu2admas(channel) && (spu2attr(channel).dma == 0) && size)
133 {
134 if (!Adma->Enabled ) Adma->Index = 0;
135
136 Adma->MemAddr = pMem;
137 Adma->AmountLeft = size;
138 SPUTargetCycle[channel] = size;
139 spu2stat_clear_80(channel);
140 if (!Adma->Enabled || (Adma->Index > 384))
141 {
142 C_SPUADDR_SET(0, channel);
143 if (ADMASWrite(channel))
144 {
145 SPUStartCycle[channel] = SPUCycles;
146 interrupt |= (1 << (1 + channel));
147 }
148 }
149 Adma->Enabled = 1;
150
151 return;
152 }
153
154 #ifdef ZEROSPU2_DEVBUILD
155 if ((conf.Log && conf.options & OPTION_RECORDING) && (channel == 1))
156 LogPacketSound(pMem, 0x8000);
157 #endif
158
159 spuaddr = C_SPUADDR(channel);
160 memcpy((u8*)(spu2mem + spuaddr),(u8*)pMem,size << 1);
161 spuaddr += size;
162 C_SPUADDR_SET(spuaddr, channel);
163
164 if (spu2attr(channel).irq && (spuaddr < C_IRQA(channel) && (C_IRQA(channel) <= (spuaddr + 0x20))))
165 {
166 IRQINFO |= 4 * (channel + 1);
167 SPU2_LOG("SPU2writeDMAMem:interrupt\n");
168 irqCallbackSPU2();
169 }
170
171 if (spuaddr > 0xFFFFE) spuaddr = 0x2800;
172 C_SPUADDR_SET(spuaddr, channel);
173
174 MemAddr[channel] += size << 1;
175 spu2stat_clear_80(channel);
176 SPUStartCycle[channel] = SPUCycles;
177 SPUTargetCycle[channel] = size;
178 interrupt |= (1 << (channel + 1));
179 }
180
181 void CALLBACK SPU2interruptDMA(int channel)
182 {
183 SPU2_LOG("SPU2 interruptDMA(%d)\n", channel);
184 spu2attr(channel).dma = 0;
185 spu2stat_set_80(channel);
186 }
187
188 #ifndef ENABLE_NEW_IOPDMA_SPU2
189 void CALLBACK SPU2writeDMA4Mem(u16* pMem, int size)
190 {
191 LOG_CALLBACK("SPU2writeDMA4Mem()\n");
192 SPU2writeDMAMem(pMem, size, 0);
193 }
194
195 void CALLBACK SPU2writeDMA7Mem(u16* pMem, int size)
196 {
197 LOG_CALLBACK("SPU2writeDMA7Mem()\n");
198 SPU2writeDMAMem(pMem, size, 1);
199 }
200
201 void CALLBACK SPU2interruptDMA4()
202 {
203 LOG_CALLBACK("SPU2interruptDMA4()\n");
204 SPU2interruptDMA(4);
205 }
206
207 void CALLBACK SPU2interruptDMA7()
208 {
209 LOG_CALLBACK("SPU2interruptDMA7()\n");
210 SPU2interruptDMA(7);
211 }
212 #else
213 s32 CALLBACK SPU2dmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
214 {
215 // Needs implementation.
216 return 0;
217 }
218
219 s32 CALLBACK SPU2dmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
220 {
221 // Needs implementation.
222 return 0;
223 }
224
225 void CALLBACK SPU2dmaInterrupt(s32 channel)
226 {
227 LOG_CALLBACK("SPU2dmaInterruptDMA()\n");
228 SPU2interruptDMA(channel);
229 }
230 #endif

  ViewVC Help
Powered by ViewVC 1.1.22