/[pcsx2_0.9.7]/trunk/pcsx2/Hw.cpp
ViewVC logotype

Contents of /trunk/pcsx2/Hw.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File size: 9099 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
19 #include "Hardware.h"
20 #include "newVif.h"
21 #include "IPU/IPUdma.h"
22
23 using namespace R5900;
24
25 const int rdram_devices = 2; // put 8 for TOOL and 2 for PS2 and PSX
26 int rdram_sdevid = 0;
27
28 static bool hwInitialized = false;
29
30 void hwInit()
31 {
32 // [TODO] / FIXME: PCSX2 no longer works on an Init system. It assumes that the
33 // static global vars for the process will be initialized when the process is created, and
34 // then issues *resets only* from then on. (reset code for various S2 components should do
35 // NULL checks and allocate memory and such if the pointers are NULL only).
36
37 if( hwInitialized ) return;
38
39 VifUnpackSSE_Init();
40
41 gsInit();
42 sifInit();
43 sprInit();
44 ipuInit();
45
46 hwInitialized = true;
47 }
48
49 void hwReset()
50 {
51 hwInit();
52
53 memzero( eeHw );
54
55 psHu32(SBUS_F260) = 0x1D000060;
56
57 // i guess this is kinda a version, it's used by some bioses
58 psHu32(DMAC_ENABLEW) = 0x1201;
59 psHu32(DMAC_ENABLER) = 0x1201;
60
61 SPU2reset();
62
63 sifInit();
64 sprInit();
65
66 gsReset();
67 ipuReset();
68 vif0Reset();
69 vif1Reset();
70
71 // needed for legacy DMAC
72 ipuDmaReset();
73 }
74
75 __fi uint intcInterrupt()
76 {
77 if ((psHu32(INTC_STAT)) == 0) {
78 //DevCon.Warning("*PCSX2*: intcInterrupt already cleared");
79 return 0;
80 }
81 if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0)
82 {
83 //DevCon.Warning("*PCSX2*: No valid interrupt INTC_MASK: %x INTC_STAT: %x", psHu32(INTC_MASK), psHu32(INTC_STAT));
84 return 0;
85 }
86
87 HW_LOG("intcInterrupt %x", psHu32(INTC_STAT) & psHu32(INTC_MASK));
88 if(psHu32(INTC_STAT) & 0x2){
89 counters[0].hold = rcntRcount(0);
90 counters[1].hold = rcntRcount(1);
91 }
92
93 //cpuException(0x400, cpuRegs.branch);
94 return 0x400;
95 }
96
97 __fi uint dmacInterrupt()
98 {
99 if( ((psHu16(DMAC_STAT + 2) & psHu16(DMAC_STAT)) == 0 ) &&
100 ( psHu16(DMAC_STAT) & 0x8000) == 0 )
101 {
102 //DevCon.Warning("No valid DMAC interrupt MASK %x STAT %x", psHu16(DMAC_STAT+2), psHu16(DMAC_STAT));
103 return 0;
104 }
105
106 if (!dmacRegs.ctrl.DMAE || psHu8(DMAC_ENABLER+2) == 1)
107 {
108 //DevCon.Warning("DMAC Suspended or Disabled on interrupt");
109 return 0;
110 }
111 HW_LOG("dmacInterrupt %x", (psHu16(DMAC_STAT + 2) & psHu16(DMAC_STAT) |
112 psHu16(DMAC_STAT) & 0x8000));
113
114 //cpuException(0x800, cpuRegs.branch);
115 return 0x800;
116 }
117
118 void hwIntcIrq(int n)
119 {
120 psHu32(INTC_STAT) |= 1<<n;
121 if(psHu32(INTC_MASK) & (1<<n))cpuTestINTCInts();
122 }
123
124 void hwDmacIrq(int n)
125 {
126 psHu32(DMAC_STAT) |= 1<<n;
127 if(psHu16(DMAC_STAT+2) & (1<<n))cpuTestDMACInts();
128 }
129
130 // Write 'size' bytes to memory address 'addr' from 'data'.
131 __ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
132 {
133 // all FIFO addresses should always be QWC-aligned.
134 pxAssume((dmacRegs.rbor.ADDR & 15) == 0);
135 pxAssume((addr & 15) == 0);
136
137 // DMAC Address resolution: FIFO can be placed anywhere in the *physical* memory map
138 // for the PS2. Its probably a serious error for a PS2 app to have the buffer cross
139 // valid/invalid page areas of ram, so realistically we only need to test the base address
140 // of the FIFO for address validity.
141
142 if (u128* dst = (u128*)PSM(dmacRegs.rbor.ADDR))
143 {
144 const u32 ringsize = (dmacRegs.rbsr.RMSK / 16) + 1;
145 pxAssertMsg( PSM(dmacRegs.rbor.ADDR+ringsize-1) != NULL, "Scratchpad/MFIFO ringbuffer spans into invalid (unmapped) physical memory!" );
146 uint startpos = (addr & dmacRegs.rbsr.RMSK)/16;
147 MemCopy_WrappedDest( data, dst, startpos, ringsize, qwc );
148 }
149 else
150 {
151 SPR_LOG( "Scratchpad/MFIFO: invalid base physical address: 0x%08x", dmacRegs.rbor.ADDR );
152 pxFailDev( wxsFormat( L"Scratchpad/MFIFO: Invalid base physical address: 0x%08x", dmacRegs.rbor.ADDR) );
153 return false;
154 }
155
156 return true;
157 }
158
159 __ri bool hwDmacSrcChainWithStack(DMACh& dma, int id) {
160 switch (id) {
161 case TAG_REFE: // Refe - Transfer Packet According to ADDR field
162 //End Transfer
163 return true;
164
165 case TAG_CNT: // CNT - Transfer QWC following the tag.
166 // Set MADR to QW afer tag, and set TADR to QW following the data.
167 dma.madr = dma.tadr + 16;
168 dma.tadr = dma.madr + (dma.qwc << 4);
169 return false;
170
171 case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
172 {
173 // Set MADR to QW following the tag, and set TADR to the address formerly in MADR.
174 u32 temp = dma.madr;
175 dma.madr = dma.tadr + 16;
176 dma.tadr = temp;
177 return false;
178 }
179 case TAG_REF: // Ref - Transfer QWC from ADDR field
180 case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
181 //Set TADR to next tag
182 dma.tadr += 16;
183 return false;
184
185 case TAG_CALL: // Call - Transfer QWC following the tag, save succeeding tag
186 {
187 // Store the address in MADR in temp, and set MADR to the data following the tag.
188 u32 temp = dma.madr;
189 dma.madr = dma.tadr + 16;
190
191 if(temp == 0)
192 {
193 DevCon.Warning("DMA Chain CALL next tag error. Tag Addr = 0");
194 dma.tadr = dma.madr + (dma.qwc << 4);
195 return false;
196 }
197 // Stash an address on the address stack pointer.
198 switch(dma.chcr.ASP)
199 {
200 case 0: //Check if ASR0 is empty
201 // Store the succeeding tag in asr0, and mark chcr as having 1 address.
202 dma.asr0 = dma.madr + (dma.qwc << 4);
203 dma.chcr.ASP++;
204 break;
205
206 case 1:
207 // Store the succeeding tag in asr1, and mark chcr as having 2 addresses.
208 dma.asr1 = dma.madr + (dma.qwc << 4);
209 dma.chcr.ASP++;
210 break;
211
212 default:
213 Console.Warning("Call Stack Overflow (report if it fixes/breaks anything)");
214 return true;
215 }
216
217 // Set TADR to the address from MADR we stored in temp.
218 dma.tadr = temp;
219
220 return false;
221 }
222
223 case TAG_RET: // Ret - Transfer QWC following the tag, load next tag
224 //Set MADR to data following the tag.
225 dma.madr = dma.tadr + 16;
226
227 // Snag an address from the address stack pointer.
228 switch(dma.chcr.ASP)
229 {
230 case 2:
231 // Pull asr1 from the stack, give it to TADR, and decrease the # of addresses.
232 dma.tadr = dma.asr1;
233 dma.asr1 = 0;
234 dma.chcr.ASP--;
235 break;
236
237 case 1:
238 // Pull asr0 from the stack, give it to TADR, and decrease the # of addresses.
239 dma.tadr = dma.asr0;
240 dma.asr0 = 0;
241 dma.chcr.ASP--;
242 break;
243
244 case 0:
245 // There aren't any addresses to pull, so end the transfer.
246 //dma.tadr += 16; //Clear tag address - Kills Klonoa 2
247 return true;
248
249 default:
250 // If ASR1 and ASR0 are messed up, end the transfer.
251 //Console.Error("TAG_RET: ASR 1 & 0 == 1. This shouldn't happen!");
252 //dma.tadr += 16; //Clear tag address - Kills Klonoa 2
253 return true;
254 }
255 return false;
256
257 case TAG_END: // End - Transfer QWC following the tag
258 //Set MADR to data following the tag, and end the transfer.
259 dma.madr = dma.tadr + 16;
260 //Don't Increment tadr; breaks Soul Calibur II and III
261 return true;
262 }
263
264 return false;
265 }
266
267 bool hwDmacSrcChain(DMACh& dma, int id)
268 {
269 u32 temp;
270
271 switch (id)
272 {
273 case TAG_REFE: // Refe - Transfer Packet According to ADDR field
274 // End the transfer.
275 return true;
276
277 case TAG_CNT: // CNT - Transfer QWC following the tag.
278 // Set MADR to QW after the tag, and TADR to QW following the data.
279 dma.madr = dma.tadr + 16;
280 dma.tadr = dma.madr + (dma.qwc << 4);
281 return false;
282
283 case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
284 // Set MADR to QW following the tag, and set TADR to the address formerly in MADR.
285 temp = dma.madr;
286 dma.madr = dma.tadr + 16;
287 dma.tadr = temp;
288 return false;
289
290 case TAG_REF: // Ref - Transfer QWC from ADDR field
291 case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
292 //Set TADR to next tag
293 dma.tadr += 16;
294 return false;
295
296 case TAG_END: // End - Transfer QWC following the tag
297 //Set MADR to data following the tag, and end the transfer.
298 dma.madr = dma.tadr + 16;
299 //Don't Increment tadr; breaks Soul Calibur II and III
300 return true;
301 }
302
303 return false;
304 }

  ViewVC Help
Powered by ViewVC 1.1.22