1 /***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
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 *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18 ***************************************************************************/
19
20 /*
21 * Functions for PSX hardware control.
22 */
23
24 #include "psxhw.h"
25 #include "mdec.h"
26 #include "cdrom.h"
27 #include "gpu.h"
28
29 // Vampire Hunter D hack
30 boolean dmaGpuListHackEn=FALSE;
31
32 static inline
setIrq(u32 irq)33 void setIrq( u32 irq )
34 {
35 psxHu32ref(0x1070) |= SWAPu32(irq);
36 }
37
psxHwReset()38 void psxHwReset() {
39 if (Config.SioIrq) psxHu32ref(0x1070) |= SWAP32(0x80);
40 if (Config.SpuIrq) psxHu32ref(0x1070) |= SWAP32(0x200);
41
42 memset(psxH, 0, 0x10000);
43
44 mdecInit(); // initialize mdec decoder
45 cdrReset();
46 psxRcntInit();
47 }
48
psxHwRead8(u32 add)49 u8 psxHwRead8(u32 add) {
50 unsigned char hard;
51
52 switch (add) {
53 case 0x1f801040: hard = sioRead8(); break;
54 #ifdef ENABLE_SIO1API
55 case 0x1f801050: hard = SIO1_readData8(); break;
56 #endif
57 case 0x1f801800: hard = cdrRead0(); break;
58 case 0x1f801801: hard = cdrRead1(); break;
59 case 0x1f801802: hard = cdrRead2(); break;
60 case 0x1f801803: hard = cdrRead3(); break;
61 default:
62 hard = psxHu8(add);
63 #ifdef PSXHW_LOG
64 PSXHW_LOG("*Unkwnown 8bit read at address %x\n", add);
65 #endif
66 return hard;
67 }
68
69 #ifdef PSXHW_LOG
70 PSXHW_LOG("*Known 8bit read at address %x value %x\n", add, hard);
71 #endif
72 return hard;
73 }
74
psxHwRead16(u32 add)75 u16 psxHwRead16(u32 add) {
76 unsigned short hard;
77
78 switch (add) {
79 #ifdef PSXHW_LOG
80 case 0x1f801070:
81 PSXHW_LOG("IREG 16bit read %x\n", psxHu16(0x1070));
82 return psxHu16(0x1070);
83 #endif
84 #ifdef PSXHW_LOG
85 case 0x1f801074:
86 PSXHW_LOG("IMASK 16bit read %x\n", psxHu16(0x1074));
87 return psxHu16(0x1074);
88 #endif
89
90 case 0x1f801040:
91 hard = sioRead8();
92 hard|= sioRead8() << 8;
93 #ifdef PAD_LOG
94 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
95 #endif
96 return hard;
97 case 0x1f801044:
98 hard = sioReadStat16();
99 #ifdef PAD_LOG
100 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
101 #endif
102 return hard;
103 case 0x1f801048:
104 hard = sioReadMode16();
105 #ifdef PAD_LOG
106 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
107 #endif
108 return hard;
109 case 0x1f80104a:
110 hard = sioReadCtrl16();
111 #ifdef PAD_LOG
112 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
113 #endif
114 return hard;
115 case 0x1f80104e:
116 hard = sioReadBaud16();
117 #ifdef PAD_LOG
118 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
119 #endif
120 return hard;
121 #ifdef ENABLE_SIO1API
122 case 0x1f801050:
123 hard = SIO1_readData16();
124 #ifdef SIO1_LOG
125 SIO1_LOG("sio1 read16 %x; ret = %x\n", add&0xf, hard);
126 #endif
127 return hard;
128 case 0x1f801054:
129 hard = SIO1_readStat16();
130 #ifdef SIO1_LOG
131 SIO1_LOG("sio1 read16 %x; ret = %x\n", add&0xf, hard);
132 #endif
133 return hard;
134 case 0x1f801058:
135 hard = SIO1_readMode16();
136 #ifdef SIO1_LOG
137 SIO1_LOG("sio1 read16 %x; ret = %x\n", add&0xf, hard);
138 #endif
139 return hard;
140 case 0x1f80105a:
141 hard = SIO1_readCtrl16();
142 #ifdef SIO1_LOG
143 SIO1_LOG("sio1 read16 %x; ret = %x\n", add&0xf, hard);
144 #endif
145 return hard;
146 case 0x1f80105e:
147 hard = SIO1_readBaud16();
148 #ifdef SIO1_LOG
149 SIO1_LOG("sio1 read16 %x; ret = %x\n", add&0xf, hard);
150 #endif
151 return hard;
152 #endif
153 case 0x1f801100:
154 hard = psxRcntRcount(0);
155 #ifdef PSXHW_LOG
156 PSXHW_LOG("T0 count read16: %x\n", hard);
157 #endif
158 return hard;
159 case 0x1f801104:
160 hard = psxRcntRmode(0);
161 #ifdef PSXHW_LOG
162 PSXHW_LOG("T0 mode read16: %x\n", hard);
163 #endif
164 return hard;
165 case 0x1f801108:
166 hard = psxRcntRtarget(0);
167 #ifdef PSXHW_LOG
168 PSXHW_LOG("T0 target read16: %x\n", hard);
169 #endif
170 return hard;
171 case 0x1f801110:
172 hard = psxRcntRcount(1);
173 #ifdef PSXHW_LOG
174 PSXHW_LOG("T1 count read16: %x\n", hard);
175 #endif
176 return hard;
177 case 0x1f801114:
178 hard = psxRcntRmode(1);
179 #ifdef PSXHW_LOG
180 PSXHW_LOG("T1 mode read16: %x\n", hard);
181 #endif
182 return hard;
183 case 0x1f801118:
184 hard = psxRcntRtarget(1);
185 #ifdef PSXHW_LOG
186 PSXHW_LOG("T1 target read16: %x\n", hard);
187 #endif
188 return hard;
189 case 0x1f801120:
190 hard = psxRcntRcount(2);
191 #ifdef PSXHW_LOG
192 PSXHW_LOG("T2 count read16: %x\n", hard);
193 #endif
194 return hard;
195 case 0x1f801124:
196 hard = psxRcntRmode(2);
197 #ifdef PSXHW_LOG
198 PSXHW_LOG("T2 mode read16: %x\n", hard);
199 #endif
200 return hard;
201 case 0x1f801128:
202 hard = psxRcntRtarget(2);
203 #ifdef PSXHW_LOG
204 PSXHW_LOG("T2 target read16: %x\n", hard);
205 #endif
206 return hard;
207
208 //case 0x1f802030: hard = //int_2000????
209 //case 0x1f802040: hard =//dip switches...??
210
211 default:
212 if (add >= 0x1f801c00 && add < 0x1f801e00) {
213 hard = SPU_readRegister(add);
214 } else {
215 hard = psxHu16(add);
216 #ifdef PSXHW_LOG
217 PSXHW_LOG("*Unkwnown 16bit read at address %x\n", add);
218 #endif
219 }
220 return hard;
221 }
222
223 #ifdef PSXHW_LOG
224 PSXHW_LOG("*Known 16bit read at address %x value %x\n", add, hard);
225 #endif
226 return hard;
227 }
228
psxHwRead32(u32 add)229 u32 psxHwRead32(u32 add) {
230 u32 hard;
231
232 switch (add) {
233 case 0x1f801040:
234 hard = sioRead8();
235 hard |= sioRead8() << 8;
236 hard |= sioRead8() << 16;
237 hard |= sioRead8() << 24;
238 #ifdef PAD_LOG
239 PAD_LOG("sio read32 ;ret = %x\n", hard);
240 #endif
241 return hard;
242 #ifdef ENABLE_SIO1API
243 case 0x1f801050:
244 hard = SIO1_readData32();
245 #ifdef SIO1_LOG
246 SIO1_LOG("sio1 read32 ;ret = %x\n", hard);
247 #endif
248 return hard;
249 #endif
250 #ifdef PSXHW_LOG
251 case 0x1f801060:
252 PSXHW_LOG("RAM size read %x\n", psxHu32(0x1060));
253 return psxHu32(0x1060);
254 #endif
255 #ifdef PSXHW_LOG
256 case 0x1f801070:
257 PSXHW_LOG("IREG 32bit read %x\n", psxHu32(0x1070));
258 return psxHu32(0x1070);
259 #endif
260 #ifdef PSXHW_LOG
261 case 0x1f801074:
262 PSXHW_LOG("IMASK 32bit read %x\n", psxHu32(0x1074));
263 return psxHu32(0x1074);
264 #endif
265
266 case 0x1f801810:
267 hard = GPU_readData();
268 #ifdef PSXHW_LOG
269 PSXHW_LOG("GPU DATA 32bit read %x\n", hard);
270 #endif
271 return hard;
272 case 0x1f801814:
273 hard = gpuReadStatus();
274 #ifdef PSXHW_LOG
275 PSXHW_LOG("GPU STATUS 32bit read %x\n", hard);
276 #endif
277 return hard;
278
279 case 0x1f801820: hard = mdecRead0(); break;
280 case 0x1f801824: hard = mdecRead1(); break;
281
282 #ifdef PSXHW_LOG
283 case 0x1f8010a0:
284 PSXHW_LOG("DMA2 MADR 32bit read %x\n", psxHu32(0x10a0));
285 return SWAPu32(HW_DMA2_MADR);
286 case 0x1f8010a4:
287 PSXHW_LOG("DMA2 BCR 32bit read %x\n", psxHu32(0x10a4));
288 return SWAPu32(HW_DMA2_BCR);
289 case 0x1f8010a8:
290 PSXHW_LOG("DMA2 CHCR 32bit read %x\n", psxHu32(0x10a8));
291 return SWAPu32(HW_DMA2_CHCR);
292 #endif
293
294 #ifdef PSXHW_LOG
295 case 0x1f8010b0:
296 PSXHW_LOG("DMA3 MADR 32bit read %x\n", psxHu32(0x10b0));
297 return SWAPu32(HW_DMA3_MADR);
298 case 0x1f8010b4:
299 PSXHW_LOG("DMA3 BCR 32bit read %x\n", psxHu32(0x10b4));
300 return SWAPu32(HW_DMA3_BCR);
301 case 0x1f8010b8:
302 PSXHW_LOG("DMA3 CHCR 32bit read %x\n", psxHu32(0x10b8));
303 return SWAPu32(HW_DMA3_CHCR);
304 #endif
305
306 #ifdef PSXHW_LOG
307 case 0x1f8010f0:
308 PSXHW_LOG("DMA PCR 32bit read %x\n", HW_DMA_PCR);
309 return SWAPu32(HW_DMA_PCR); // DMA control register
310 case 0x1f8010f4:
311 PSXHW_LOG("DMA ICR 32bit read %x\n", HW_DMA_ICR);
312 return SWAPu32(HW_DMA_ICR); // DMA interrupt register (enable/ack)
313 #endif
314
315 // time for rootcounters :)
316 case 0x1f801100:
317 hard = psxRcntRcount(0);
318 #ifdef PSXHW_LOG
319 PSXHW_LOG("T0 count read32: %x\n", hard);
320 #endif
321 return hard;
322 case 0x1f801104:
323 hard = psxRcntRmode(0);
324 #ifdef PSXHW_LOG
325 PSXHW_LOG("T0 mode read32: %x\n", hard);
326 #endif
327 return hard;
328 case 0x1f801108:
329 hard = psxRcntRtarget(0);
330 #ifdef PSXHW_LOG
331 PSXHW_LOG("T0 target read32: %x\n", hard);
332 #endif
333 return hard;
334 case 0x1f801110:
335 hard = psxRcntRcount(1);
336 #ifdef PSXHW_LOG
337 PSXHW_LOG("T1 count read32: %x\n", hard);
338 #endif
339 return hard;
340 case 0x1f801114:
341 hard = psxRcntRmode(1);
342 #ifdef PSXHW_LOG
343 PSXHW_LOG("T1 mode read32: %x\n", hard);
344 #endif
345 return hard;
346 case 0x1f801118:
347 hard = psxRcntRtarget(1);
348 #ifdef PSXHW_LOG
349 PSXHW_LOG("T1 target read32: %x\n", hard);
350 #endif
351 return hard;
352 case 0x1f801120:
353 hard = psxRcntRcount(2);
354 #ifdef PSXHW_LOG
355 PSXHW_LOG("T2 count read32: %x\n", hard);
356 #endif
357 return hard;
358 case 0x1f801124:
359 hard = psxRcntRmode(2);
360 #ifdef PSXHW_LOG
361 PSXHW_LOG("T2 mode read32: %x\n", hard);
362 #endif
363 return hard;
364 case 0x1f801128:
365 hard = psxRcntRtarget(2);
366 #ifdef PSXHW_LOG
367 PSXHW_LOG("T2 target read32: %x\n", hard);
368 #endif
369 return hard;
370 case 0x1f801014:
371 hard = psxHu32(add);
372 #ifdef PSXHW_LOG
373 PSXHW_LOG("SPU delay [0x1014] read32: %8.8lx\n", hard);
374 #endif
375 return hard;
376
377 default:
378 hard = psxHu32(add);
379 #ifdef PSXHW_LOG
380 PSXHW_LOG("*Unknown 32bit read at address %x (0x%8.8lx)\n", add, hard);
381 #endif
382 return hard;
383 }
384 #ifdef PSXHW_LOG
385 PSXHW_LOG("*Known 32bit read at address %x\n", add);
386 #endif
387 return hard;
388 }
389
psxHwWrite8(u32 add,u8 value)390 void psxHwWrite8(u32 add, u8 value) {
391 switch (add) {
392 case 0x1f801040: sioWrite8(value); break;
393 #ifdef ENABLE_SIO1API
394 case 0x1f801050: SIO1_writeData8(value); break;
395 #endif
396 case 0x1f801800: cdrWrite0(value); break;
397 case 0x1f801801: cdrWrite1(value); break;
398 case 0x1f801802: cdrWrite2(value); break;
399 case 0x1f801803: cdrWrite3(value); break;
400
401 default:
402 psxHu8ref(add) = value;
403 #ifdef PSXHW_LOG
404 PSXHW_LOG("*Unknown 8bit write at address %x value %x\n", add, value);
405 #endif
406 return;
407 }
408 psxHu8ref(add) = value;
409 #ifdef PSXHW_LOG
410 PSXHW_LOG("*Known 8bit write at address %x value %x\n", add, value);
411 #endif
412 }
413
psxHwWrite16(u32 add,u16 value)414 void psxHwWrite16(u32 add, u16 value) {
415 switch (add) {
416 case 0x1f801040:
417 sioWrite8((unsigned char)value);
418 sioWrite8((unsigned char)(value>>8));
419 #ifdef PAD_LOG
420 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
421 #endif
422 return;
423 case 0x1f801044:
424 sioWriteStat16(value);
425 #ifdef PAD_LOG
426 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
427 #endif
428 return;
429 case 0x1f801048:
430 sioWriteMode16(value);
431 #ifdef PAD_LOG
432 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
433 #endif
434 return;
435 case 0x1f80104a: // control register
436 sioWriteCtrl16(value);
437 #ifdef PAD_LOG
438 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
439 #endif
440 return;
441 case 0x1f80104e: // baudrate register
442 sioWriteBaud16(value);
443 #ifdef PAD_LOG
444 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
445 #endif
446 return;
447 #ifdef ENABLE_SIO1API
448 case 0x1f801050:
449 SIO1_writeData16(value);
450 #ifdef SIO1_LOG
451 SIO1_LOG("sio1 write16 %x, %x\n", add&0xf, value);
452 #endif
453 return;
454 case 0x1f801054:
455 SIO1_writeStat16(value);
456 #ifdef SIO1_LOG
457 SIO1_LOG("sio1 write16 %x, %x\n", add&0xf, value);
458 #endif
459 return;
460 case 0x1f801058:
461 SIO1_writeMode16(value);
462 #ifdef SIO1_LOG
463 SIO1_LOG("sio1 write16 %x, %x\n", add&0xf, value);
464 #endif
465 return;
466 case 0x1f80105a:
467 SIO1_writeCtrl16(value);
468 #ifdef SIO1_LOG
469 SIO1_LOG("sio1 write16 %x, %x\n", add&0xf, value);
470 #endif
471 return;
472 case 0x1f80105e:
473 SIO1_writeBaud16(value);
474 #ifdef SIO1_LOG
475 SIO1_LOG("sio1 write16 %x, %x\n", add&0xf, value);
476 #endif
477 return;
478 #endif
479 case 0x1f801070:
480 #ifdef PSXHW_LOG
481 PSXHW_LOG("IREG 16bit write %x\n", value);
482 #endif
483 if (Config.SioIrq) psxHu16ref(0x1070) |= SWAPu16(0x80);
484 if (Config.SpuIrq) psxHu16ref(0x1070) |= SWAPu16(0x200);
485 psxHu16ref(0x1070) &= SWAPu16(value);
486 return;
487
488 case 0x1f801074:
489 #ifdef PSXHW_LOG
490 PSXHW_LOG("IMASK 16bit write %x\n", value);
491 #endif
492 psxHu16ref(0x1074) = SWAPu16(value);
493 return;
494
495 case 0x1f801100:
496 #ifdef PSXHW_LOG
497 PSXHW_LOG("COUNTER 0 COUNT 16bit write %x\n", value);
498 #endif
499 psxRcntWcount(0, value); return;
500 case 0x1f801104:
501 #ifdef PSXHW_LOG
502 PSXHW_LOG("COUNTER 0 MODE 16bit write %x\n", value);
503 #endif
504 psxRcntWmode(0, value); return;
505 case 0x1f801108:
506 #ifdef PSXHW_LOG
507 PSXHW_LOG("COUNTER 0 TARGET 16bit write %x\n", value);
508 #endif
509 psxRcntWtarget(0, value); return;
510
511 case 0x1f801110:
512 #ifdef PSXHW_LOG
513 PSXHW_LOG("COUNTER 1 COUNT 16bit write %x\n", value);
514 #endif
515 psxRcntWcount(1, value); return;
516 case 0x1f801114:
517 #ifdef PSXHW_LOG
518 PSXHW_LOG("COUNTER 1 MODE 16bit write %x\n", value);
519 #endif
520 psxRcntWmode(1, value); return;
521 case 0x1f801118:
522 #ifdef PSXHW_LOG
523 PSXHW_LOG("COUNTER 1 TARGET 16bit write %x\n", value);
524 #endif
525 psxRcntWtarget(1, value); return;
526
527 case 0x1f801120:
528 #ifdef PSXHW_LOG
529 PSXHW_LOG("COUNTER 2 COUNT 16bit write %x\n", value);
530 #endif
531 psxRcntWcount(2, value); return;
532 case 0x1f801124:
533 #ifdef PSXHW_LOG
534 PSXHW_LOG("COUNTER 2 MODE 16bit write %x\n", value);
535 #endif
536 psxRcntWmode(2, value); return;
537 case 0x1f801128:
538 #ifdef PSXHW_LOG
539 PSXHW_LOG("COUNTER 2 TARGET 16bit write %x\n", value);
540 #endif
541 psxRcntWtarget(2, value); return;
542
543 default:
544 if (add>=0x1f801c00 && add<0x1f801e00) {
545 SPU_writeRegister(add, value);
546 return;
547 }
548
549 psxHu16ref(add) = SWAPu16(value);
550 #ifdef PSXHW_LOG
551 PSXHW_LOG("*Unknown 16bit write at address %x value %x\n", add, value);
552 #endif
553 return;
554 }
555 psxHu16ref(add) = SWAPu16(value);
556 #ifdef PSXHW_LOG
557 PSXHW_LOG("*Known 16bit write at address %x value %x\n", add, value);
558 #endif
559 }
560
561 #define DmaExec(n) { \
562 HW_DMA##n##_CHCR = SWAPu32(value); \
563 \
564 if (SWAPu32(HW_DMA##n##_CHCR) & 0x01000000 && SWAPu32(HW_DMA_PCR) & (8 << (n * 4))) { \
565 psxDma##n(SWAPu32(HW_DMA##n##_MADR), SWAPu32(HW_DMA##n##_BCR), SWAPu32(HW_DMA##n##_CHCR)); \
566 } \
567 }
568
psxHwWrite32(u32 add,u32 value)569 void psxHwWrite32(u32 add, u32 value) {
570 switch (add) {
571 case 0x1f801040:
572 sioWrite8((unsigned char)value);
573 sioWrite8((unsigned char)((value&0xff) >> 8));
574 sioWrite8((unsigned char)((value&0xff) >> 16));
575 sioWrite8((unsigned char)((value&0xff) >> 24));
576 #ifdef PAD_LOG
577 PAD_LOG("sio write32 %x\n", value);
578 #endif
579 return;
580 #ifdef ENABLE_SIO1API
581 case 0x1f801050:
582 SIO1_writeData32(value);
583 #ifdef SIO1_LOG
584 SIO1_LOG("sio1 write32 %x\n", value);
585 #endif
586 return;
587 #endif
588 #ifdef PSXHW_LOG
589 case 0x1f801060:
590 PSXHW_LOG("RAM size write %x\n", value);
591 psxHu32ref(add) = SWAPu32(value);
592 return; // Ram size
593 #endif
594
595 case 0x1f801070:
596 #ifdef PSXHW_LOG
597 PSXHW_LOG("IREG 32bit write %x\n", value);
598 #endif
599 if (Config.SioIrq) psxHu32ref(0x1070) |= SWAPu32(0x80);
600 if (Config.SpuIrq) psxHu32ref(0x1070) |= SWAPu32(0x200);
601 psxHu32ref(0x1070) &= SWAPu32(value);
602 return;
603 case 0x1f801074:
604 #ifdef PSXHW_LOG
605 PSXHW_LOG("IMASK 32bit write %x\n", value);
606 #endif
607 psxHu32ref(0x1074) = SWAPu32(value);
608 return;
609
610 #ifdef PSXHW_LOG
611 case 0x1f801080:
612 PSXHW_LOG("DMA0 MADR 32bit write %x\n", value);
613 HW_DMA0_MADR = SWAPu32(value); return; // DMA0 madr
614 case 0x1f801084:
615 PSXHW_LOG("DMA0 BCR 32bit write %x\n", value);
616 HW_DMA0_BCR = SWAPu32(value); return; // DMA0 bcr
617 #endif
618 case 0x1f801088:
619 #ifdef PSXHW_LOG
620 PSXHW_LOG("DMA0 CHCR 32bit write %x\n", value);
621 #endif
622 DmaExec(0); // DMA0 chcr (MDEC in DMA)
623 return;
624
625 #ifdef PSXHW_LOG
626 case 0x1f801090:
627 PSXHW_LOG("DMA1 MADR 32bit write %x\n", value);
628 HW_DMA1_MADR = SWAPu32(value); return; // DMA1 madr
629 case 0x1f801094:
630 PSXHW_LOG("DMA1 BCR 32bit write %x\n", value);
631 HW_DMA1_BCR = SWAPu32(value); return; // DMA1 bcr
632 #endif
633 case 0x1f801098:
634 #ifdef PSXHW_LOG
635 PSXHW_LOG("DMA1 CHCR 32bit write %x\n", value);
636 #endif
637 DmaExec(1); // DMA1 chcr (MDEC out DMA)
638 return;
639
640 #ifdef PSXHW_LOG
641 case 0x1f8010a0:
642 PSXHW_LOG("DMA2 MADR 32bit write %x\n", value);
643 HW_DMA2_MADR = SWAPu32(value); return; // DMA2 madr
644 case 0x1f8010a4:
645 PSXHW_LOG("DMA2 BCR 32bit write %x\n", value);
646 HW_DMA2_BCR = SWAPu32(value); return; // DMA2 bcr
647 #endif
648 case 0x1f8010a8:
649 #ifdef PSXHW_LOG
650 PSXHW_LOG("DMA2 CHCR 32bit write %x\n", value);
651 #endif
652 /* A hack that makes Vampire Hunter D title screen visible,
653 * but makes Tomb Raider II water effect to stay opaque
654 * Root cause for this problem is that when DMA2 is issued
655 * it is incompletele and still beign built by the game.
656 * Maybe it is ready when some signal comes in or within given delay?
657 */
658 if (dmaGpuListHackEn && value == 0x00000401 && HW_DMA2_BCR == 0x0) {
659 psxDma2(SWAPu32(HW_DMA2_MADR), SWAPu32(HW_DMA2_BCR), SWAPu32(value));
660 return;
661 }
662 DmaExec(2); // DMA2 chcr (GPU DMA)
663 if (Config.HackFix && HW_DMA2_CHCR == 0x1000401)
664 dmaGpuListHackEn=TRUE;
665 return;
666
667 #ifdef PSXHW_LOG
668 case 0x1f8010b0:
669 PSXHW_LOG("DMA3 MADR 32bit write %x\n", value);
670 HW_DMA3_MADR = SWAPu32(value); return; // DMA3 madr
671 case 0x1f8010b4:
672 PSXHW_LOG("DMA3 BCR 32bit write %x\n", value);
673 HW_DMA3_BCR = SWAPu32(value); return; // DMA3 bcr
674 #endif
675 case 0x1f8010b8:
676 #ifdef PSXHW_LOG
677 PSXHW_LOG("DMA3 CHCR 32bit write %x\n", value);
678 #endif
679 DmaExec(3); // DMA3 chcr (CDROM DMA)
680
681 return;
682
683 #ifdef PSXHW_LOG
684 case 0x1f8010c0:
685 PSXHW_LOG("DMA4 MADR 32bit write %x\n", value);
686 HW_DMA4_MADR = SWAPu32(value); return; // DMA4 madr
687 case 0x1f8010c4:
688 PSXHW_LOG("DMA4 BCR 32bit write %x\n", value);
689 HW_DMA4_BCR = SWAPu32(value); return; // DMA4 bcr
690 #endif
691 case 0x1f8010c8:
692 #ifdef PSXHW_LOG
693 PSXHW_LOG("DMA4 CHCR 32bit write %x\n", value);
694 #endif
695 DmaExec(4); // DMA4 chcr (SPU DMA)
696 return;
697
698 #if 0
699 case 0x1f8010d0: break; //DMA5write_madr();
700 case 0x1f8010d4: break; //DMA5write_bcr();
701 case 0x1f8010d8: break; //DMA5write_chcr(); // Not needed
702 #endif
703
704 #ifdef PSXHW_LOG
705 case 0x1f8010e0:
706 PSXHW_LOG("DMA6 MADR 32bit write %x\n", value);
707 HW_DMA6_MADR = SWAPu32(value); return; // DMA6 bcr
708 case 0x1f8010e4:
709 PSXHW_LOG("DMA6 BCR 32bit write %x\n", value);
710 HW_DMA6_BCR = SWAPu32(value); return; // DMA6 bcr
711 #endif
712 case 0x1f8010e8:
713 #ifdef PSXHW_LOG
714 PSXHW_LOG("DMA6 CHCR 32bit write %x\n", value);
715 #endif
716 DmaExec(6); // DMA6 chcr (OT clear)
717 return;
718
719 #ifdef PSXHW_LOG
720 case 0x1f8010f0:
721 PSXHW_LOG("DMA PCR 32bit write %x\n", value);
722 HW_DMA_PCR = SWAPu32(value);
723 return;
724 #endif
725
726 case 0x1f8010f4:
727 #ifdef PSXHW_LOG
728 PSXHW_LOG("DMA ICR 32bit write %x\n", value);
729 #endif
730 {
731 u32 tmp = (~value) & SWAPu32(HW_DMA_ICR);
732 HW_DMA_ICR = SWAPu32(((tmp ^ value) & 0xffffff) ^ tmp);
733 return;
734 }
735
736
737 case 0x1f801014:
738 #ifdef PSXHW_LOG
739 PSXHW_LOG("SPU delay [0x1014] write32: %8.8lx\n", value);
740 #endif
741 psxHu32ref(add) = SWAPu32(value);
742 return;
743 case 0x1f801810:
744 #ifdef PSXHW_LOG
745 PSXHW_LOG("GPU DATA 32bit write %x (CMD/MSB %x)\n", value, value>>24);
746 #endif
747 // 0x1F means irq request, so fulfill it here because plugin can't and won't
748 // Probably no need to send this to plugin in first place...
749 // MML/Tronbonne is known to use this.
750 // TODO FIFO is not implemented properly so commands are not exact
751 // and thus we rely on hack that counter/cdrom irqs are enabled at same time
752 if (Config.HackFix && SWAPu32(value) == 0x1f00000 && (psxHu32ref(0x1070) & 0x44)) {
753 setIrq( 0x01 );
754 }
755 GPU_writeData(value); return;
756 case 0x1f801814:
757 #ifdef PSXHW_LOG
758 PSXHW_LOG("GPU STATUS 32bit write %x\n", value);
759 #endif
760 if (value & 0x8000000)
761 dmaGpuListHackEn=FALSE;
762 GPU_writeStatus(value); return;
763
764 case 0x1f801820:
765 mdecWrite0(value); break;
766 case 0x1f801824:
767 mdecWrite1(value); break;
768
769 case 0x1f801100:
770 #ifdef PSXHW_LOG
771 PSXHW_LOG("COUNTER 0 COUNT 32bit write %x\n", value);
772 #endif
773 psxRcntWcount(0, value & 0xffff); return;
774 case 0x1f801104:
775 #ifdef PSXHW_LOG
776 PSXHW_LOG("COUNTER 0 MODE 32bit write %x\n", value);
777 #endif
778 psxRcntWmode(0, value); return;
779 case 0x1f801108:
780 #ifdef PSXHW_LOG
781 PSXHW_LOG("COUNTER 0 TARGET 32bit write %x\n", value);
782 #endif
783 psxRcntWtarget(0, value & 0xffff); return; // HW_DMA_ICR&= SWAP32((~value)&0xff000000);
784
785 case 0x1f801110:
786 #ifdef PSXHW_LOG
787 PSXHW_LOG("COUNTER 1 COUNT 32bit write %x\n", value);
788 #endif
789 psxRcntWcount(1, value & 0xffff); return;
790 case 0x1f801114:
791 #ifdef PSXHW_LOG
792 PSXHW_LOG("COUNTER 1 MODE 32bit write %x\n", value);
793 #endif
794 psxRcntWmode(1, value); return;
795 case 0x1f801118:
796 #ifdef PSXHW_LOG
797 PSXHW_LOG("COUNTER 1 TARGET 32bit write %x\n", value);
798 #endif
799 psxRcntWtarget(1, value & 0xffff); return;
800
801 case 0x1f801120:
802 #ifdef PSXHW_LOG
803 PSXHW_LOG("COUNTER 2 COUNT 32bit write %x\n", value);
804 #endif
805 psxRcntWcount(2, value & 0xffff); return;
806 case 0x1f801124:
807 #ifdef PSXHW_LOG
808 PSXHW_LOG("COUNTER 2 MODE 32bit write %x\n", value);
809 #endif
810 psxRcntWmode(2, value); return;
811 case 0x1f801128:
812 #ifdef PSXHW_LOG
813 PSXHW_LOG("COUNTER 2 TARGET 32bit write %x\n", value);
814 #endif
815 psxRcntWtarget(2, value & 0xffff); return;
816
817 default:
818 // Dukes of Hazard 2 - car engine noise
819 if (add>=0x1f801c00 && add<0x1f801e00) {
820 SPU_writeRegister(add, value&0xffff);
821 add += 2;
822 value >>= 16;
823
824 if (add>=0x1f801c00 && add<0x1f801e00)
825 SPU_writeRegister(add, value&0xffff);
826 return;
827 }
828
829
830 psxHu32ref(add) = SWAPu32(value);
831 #ifdef PSXHW_LOG
832 PSXHW_LOG("*Unknown 32bit write at address %x value %x\n", add, value);
833 #endif
834 return;
835 }
836 psxHu32ref(add) = SWAPu32(value);
837 #ifdef PSXHW_LOG
838 PSXHW_LOG("*Known 32bit write at address %x value %x\n", add, value);
839 #endif
840 }
841
psxHwFreeze(gzFile f,int Mode)842 int psxHwFreeze(gzFile f, int Mode) {
843 return 0;
844 }
845