/[pcsx2_0.9.7]/trunk/pcsx2/IPU/IPU_Fifo.cpp
ViewVC logotype

Contents of /trunk/pcsx2/IPU/IPU_Fifo.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (9 years, 5 months ago) by william
File size: 4499 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "PrecompiledHeader.h"
17 #include "Common.h"
18 #include "IPU.h"
19 #include "IPU/IPUdma.h"
20 #include "mpeg2lib/Mpeg.h"
21
22
23 __aligned16 IPU_Fifo ipu_fifo;
24
25 void IPU_Fifo::init()
26 {
27 out.readpos = 0;
28 out.writepos = 0;
29 in.readpos = 0;
30 in.writepos = 0;
31 memzero(in.data);
32 memzero(out.data);
33 }
34
35 void IPU_Fifo_Input::clear()
36 {
37 memzero(data);
38 g_BP.IFC = 0;
39 ipuRegs.ctrl.IFC = 0;
40 readpos = 0;
41 writepos = 0;
42 }
43
44 void IPU_Fifo_Output::clear()
45 {
46 memzero(data);
47 ipuRegs.ctrl.OFC = 0;
48 readpos = 0;
49 writepos = 0;
50 }
51
52 void IPU_Fifo::clear()
53 {
54 in.clear();
55 out.clear();
56 }
57
58 wxString IPU_Fifo_Input::desc() const
59 {
60 return wxsFormat(L"IPU Fifo Input: readpos = 0x%x, writepos = 0x%x, data = 0x%x", readpos, writepos, data);
61 }
62
63 wxString IPU_Fifo_Output::desc() const
64 {
65 return wxsFormat(L"IPU Fifo Output: readpos = 0x%x, writepos = 0x%x, data = 0x%x", readpos, writepos, data);
66 }
67
68 int IPU_Fifo_Input::write(u32* pMem, int size)
69 {
70 int transsize;
71 int firsttrans = min(size, 8 - (int)g_BP.IFC);
72
73 g_BP.IFC += firsttrans;
74 transsize = firsttrans;
75
76 while (transsize-- > 0)
77 {
78 for (int i = 0; i <= 3; i++)
79 {
80 data[writepos + i] = pMem[i];
81 }
82 writepos = (writepos + 4) & 31;
83 pMem += 4;
84 }
85
86 return firsttrans;
87 }
88
89 int IPU_Fifo_Output::write(const u32 *value, int size)
90 {
91 int transsize, firsttrans;
92
93 if ((int)ipuRegs.ctrl.OFC >= 8) IPU0dma();
94
95 transsize = min(size, 8 - (int)ipuRegs.ctrl.OFC);
96 firsttrans = transsize;
97
98 while (transsize-- > 0)
99 {
100 for (int i = 0; i <= 3; i++)
101 {
102 data[writepos + i] = ((u32*)value)[i];
103 }
104 writepos = (writepos + 4) & 31;
105 value += 4;
106 }
107
108 ipuRegs.ctrl.OFC += firsttrans;
109 IPU0dma();
110
111 return firsttrans;
112 }
113
114 int IPU_Fifo_Input::read(void *value)
115 {
116 // wait until enough data to ensure proper streaming.
117 if (g_BP.IFC < 4)
118 {
119 // IPU FIFO is empty and DMA is waiting so lets tell the DMA we are ready to put data in the FIFO
120 if(cpuRegs.eCycle[4] == 0x9999)
121 {
122 CPU_INT( DMAC_TO_IPU, 4 );
123 }
124
125 if (g_BP.IFC == 0) return 0;
126 pxAssert(g_BP.IFC > 0);
127 }
128
129 // transfer 1 qword, split into two transfers
130 for (int i = 0; i <= 3; i++)
131 {
132 ((u32*)value)[i] = data[readpos + i];
133 data[readpos + i] = 0;
134 }
135
136 readpos = (readpos + 4) & 31;
137 g_BP.IFC--;
138 return 1;
139 }
140
141 void IPU_Fifo_Output::_readsingle(void *value)
142 {
143 // transfer 1 qword, split into two transfers
144 for (int i = 0; i <= 3; i++)
145 {
146 ((u32*)value)[i] = data[readpos + i];
147 data[readpos + i] = 0;
148 }
149 readpos = (readpos + 4) & 31;
150 }
151
152 void IPU_Fifo_Output::read(void *value, int size)
153 {
154 ipuRegs.ctrl.OFC -= size;
155 while (size > 0)
156 {
157 _readsingle(value);
158 value = (u32*)value + 4;
159 size--;
160 }
161 }
162
163 void IPU_Fifo_Output::readsingle(void *value)
164 {
165 if (ipuRegs.ctrl.OFC > 0)
166 {
167 ipuRegs.ctrl.OFC--;
168 _readsingle(value);
169 }
170 }
171
172 __fi bool decoder_t::ReadIpuData(u128* out)
173 {
174 if(ipu0_data == 0)
175 {
176 IPU_LOG( "ReadFIFO/IPUout -> (fifo empty/no data available)" );
177 return false;
178 }
179
180 CopyQWC(out, GetIpuDataPtr());
181
182 --ipu0_data;
183 ++ipu0_idx;
184
185 IPU_LOG( "ReadFIFO/IPUout -> %ls", out->ToString().c_str() );
186
187 return true;
188 }
189
190 void __fastcall ReadFIFO_IPUout(mem128_t* out)
191 {
192 // FIXME! When ReadIpuData() doesn't succeed (returns false), the EE should probably stall
193 // until a value becomes available. This isn't exactly easy to do since the virtualized EE
194 // in PCSX2 *has* to be running in order for the IPU DMA to upload new input data to allow
195 // IPUout's FIFO to fill. Thus if we implement an EE stall, PCSX2 deadlocks. Grr. --air
196
197 if (decoder.ReadIpuData(out))
198 {
199 ipu_fifo.out.readpos = (ipu_fifo.out.readpos + 4) & 31;
200 }
201 }
202
203 void __fastcall WriteFIFO_IPUin(const mem128_t* value)
204 {
205 IPU_LOG( "WriteFIFO/IPUin <- %ls", value->ToString().c_str() );
206
207 //committing every 16 bytes
208 if( ipu_fifo.in.write((u32*)value, 1) == 0 )
209 {
210 IPUProcessInterrupt();
211 }
212 }

  ViewVC Help
Powered by ViewVC 1.1.22