1 /***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
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. *
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. *
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 02111-1307 USA. *
18 ***************************************************************************/
21 * Functions for PSX hardware control.
30 //#define PSXHW_LOG printf
33 if (Config.Sio) psxHu32ref(0x1070) |= SWAP32(0x80);
34 if (Config.SpuIrq) psxHu32ref(0x1070) |= SWAP32(0x200);
36 memset(psxH, 0, 0x10000);
38 mdecInit(); // initialize mdec decoder
41 HW_GPU_STATUS = 0x14802000;
44 u8 psxHwRead8(u32 add) {
48 case 0x1f801040: hard = sioRead8();break;
\r
50 case 0x1f801050: hard = SIO1_readData8(); break;
\r
52 case 0x1f801800: hard = cdrRead0(); break;
53 case 0x1f801801: hard = cdrRead1(); break;
54 case 0x1f801802: hard = cdrRead2(); break;
55 case 0x1f801803: hard = cdrRead3(); break;
59 PSXHW_LOG("*Unkwnown 8bit read at address %x\n", add);
65 PSXHW_LOG("*Known 8bit read at address %x value %x\n", add, hard);
70 u16 psxHwRead16(u32 add) {
75 case 0x1f801070: PSXHW_LOG("IREG 16bit read %x\n", psxHu16(0x1070));
76 return psxHu16(0x1070);
79 case 0x1f801074: PSXHW_LOG("IMASK 16bit read %x\n", psxHu16(0x1074));
80 return psxHu16(0x1074);
85 hard|= sioRead8() << 8;
87 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
91 hard = sioReadStat16();
93 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
97 hard = sioReadMode16();
99 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
103 hard = sioReadCtrl16();
105 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
109 hard = sioReadBaud16();
111 PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
114 #ifdef ENABLE_SIO1API
116 hard = SIO1_readData16();
119 hard = SIO1_readStat16();
122 hard = SIO1_readCtrl16();
125 hard = SIO1_readBaud16();
128 /* Fixes Armored Core misdetecting the Link cable being detected.
129 * We want to turn that thing off and force it to do local multiplayer instead.
130 * Thanks Sony for the fix, they fixed it in their PS Classic fork.
136 hard = psxRcntRcount(0);
138 PSXHW_LOG("T0 count read16: %x\n", hard);
142 hard = psxRcntRmode(0);
144 PSXHW_LOG("T0 mode read16: %x\n", hard);
148 hard = psxRcntRtarget(0);
150 PSXHW_LOG("T0 target read16: %x\n", hard);
154 hard = psxRcntRcount(1);
156 PSXHW_LOG("T1 count read16: %x\n", hard);
160 hard = psxRcntRmode(1);
162 PSXHW_LOG("T1 mode read16: %x\n", hard);
166 hard = psxRcntRtarget(1);
168 PSXHW_LOG("T1 target read16: %x\n", hard);
172 hard = psxRcntRcount(2);
174 PSXHW_LOG("T2 count read16: %x\n", hard);
178 hard = psxRcntRmode(2);
180 PSXHW_LOG("T2 mode read16: %x\n", hard);
184 hard = psxRcntRtarget(2);
186 PSXHW_LOG("T2 target read16: %x\n", hard);
190 //case 0x1f802030: hard = //int_2000????
191 //case 0x1f802040: hard =//dip switches...??
194 if (add >= 0x1f801c00 && add < 0x1f801e00) {
195 hard = SPU_readRegister(add);
199 PSXHW_LOG("*Unkwnown 16bit read at address %x\n", add);
206 PSXHW_LOG("*Known 16bit read at address %x value %x\n", add, hard);
211 u32 psxHwRead32(u32 add) {
217 hard |= sioRead8() << 8;
218 hard |= sioRead8() << 16;
219 hard |= sioRead8() << 24;
221 PAD_LOG("sio read32 ;ret = %x\n", hard);
224 #ifdef ENABLE_SIO1API
226 hard = SIO1_readData32();
231 PSXHW_LOG("RAM size read %x\n", psxHu32(0x1060));
232 return psxHu32(0x1060);
235 case 0x1f801070: PSXHW_LOG("IREG 32bit read %x\n", psxHu32(0x1070));
236 return psxHu32(0x1070);
239 case 0x1f801074: PSXHW_LOG("IMASK 32bit read %x\n", psxHu32(0x1074));
240 return psxHu32(0x1074);
244 hard = GPU_readData();
246 PSXHW_LOG("GPU DATA 32bit read %x\n", hard);
251 hard = HW_GPU_STATUS;
252 if (hSyncCount < 240 && (HW_GPU_STATUS & PSXGPU_ILACE_BITS) != PSXGPU_ILACE_BITS)
253 hard |= PSXGPU_LCF & (psxRegs.cycle << 20);
255 PSXHW_LOG("GPU STATUS 32bit read %x\n", hard);
259 case 0x1f801820: hard = mdecRead0(); break;
260 case 0x1f801824: hard = mdecRead1(); break;
264 PSXHW_LOG("DMA2 MADR 32bit read %x\n", psxHu32(0x10a0));
265 return SWAPu32(HW_DMA2_MADR);
267 PSXHW_LOG("DMA2 BCR 32bit read %x\n", psxHu32(0x10a4));
268 return SWAPu32(HW_DMA2_BCR);
270 PSXHW_LOG("DMA2 CHCR 32bit read %x\n", psxHu32(0x10a8));
271 return SWAPu32(HW_DMA2_CHCR);
276 PSXHW_LOG("DMA3 MADR 32bit read %x\n", psxHu32(0x10b0));
277 return SWAPu32(HW_DMA3_MADR);
279 PSXHW_LOG("DMA3 BCR 32bit read %x\n", psxHu32(0x10b4));
280 return SWAPu32(HW_DMA3_BCR);
282 PSXHW_LOG("DMA3 CHCR 32bit read %x\n", psxHu32(0x10b8));
283 return SWAPu32(HW_DMA3_CHCR);
288 PSXHW_LOG("DMA PCR 32bit read %x\n", psxHu32(0x10f0));
289 return SWAPu32(HW_DMA_PCR); // dma rest channel
291 PSXHW_LOG("DMA ICR 32bit read %x\n", psxHu32(0x10f4));
292 return SWAPu32(HW_DMA_ICR); // interrupt enabler?*/
295 // time for rootcounters :)
297 hard = psxRcntRcount(0);
299 PSXHW_LOG("T0 count read32: %x\n", hard);
303 hard = psxRcntRmode(0);
305 PSXHW_LOG("T0 mode read32: %x\n", hard);
309 hard = psxRcntRtarget(0);
311 PSXHW_LOG("T0 target read32: %x\n", hard);
315 hard = psxRcntRcount(1);
317 PSXHW_LOG("T1 count read32: %x\n", hard);
321 hard = psxRcntRmode(1);
323 PSXHW_LOG("T1 mode read32: %x\n", hard);
327 hard = psxRcntRtarget(1);
329 PSXHW_LOG("T1 target read32: %x\n", hard);
333 hard = psxRcntRcount(2);
335 PSXHW_LOG("T2 count read32: %x\n", hard);
339 hard = psxRcntRmode(2);
341 PSXHW_LOG("T2 mode read32: %x\n", hard);
345 hard = psxRcntRtarget(2);
347 PSXHW_LOG("T2 target read32: %x\n", hard);
354 PSXHW_LOG("*Unkwnown 32bit read at address %x\n", add);
359 PSXHW_LOG("*Known 32bit read at address %x\n", add);
364 void psxHwWrite8(u32 add, u8 value) {
366 case 0x1f801040: sioWrite8(value); break;
\r
367 #ifdef ENABLE_SIO1API
368 case 0x1f801050: SIO1_writeData8(value); break;
\r
370 case 0x1f801800: cdrWrite0(value); break;
371 case 0x1f801801: cdrWrite1(value); break;
372 case 0x1f801802: cdrWrite2(value); break;
373 case 0x1f801803: cdrWrite3(value); break;
378 PSXHW_LOG("*Unknown 8bit write at address %x value %x\n", add, value);
384 PSXHW_LOG("*Known 8bit write at address %x value %x\n", add, value);
388 void psxHwWrite16(u32 add, u16 value) {
391 sioWrite8((unsigned char)value);
392 sioWrite8((unsigned char)(value>>8));
394 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
398 sioWriteStat16(value);
400 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
404 sioWriteMode16(value);
406 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
409 case 0x1f80104a: // control register
410 sioWriteCtrl16(value);
412 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
415 case 0x1f80104e: // baudrate register
416 sioWriteBaud16(value);
418 PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
421 #ifdef ENABLE_SIO1API
423 SIO1_writeData16(value);
426 SIO1_writeStat16(value);
429 SIO1_writeCtrl16(value);
432 SIO1_writeBaud16(value);
437 PSXHW_LOG("IREG 16bit write %x\n", value);
439 if (Config.Sio) psxHu16ref(0x1070) |= SWAPu16(0x80);
440 if (Config.SpuIrq) psxHu16ref(0x1070) |= SWAPu16(0x200);
441 psxHu16ref(0x1070) &= SWAPu16(value);
446 PSXHW_LOG("IMASK 16bit write %x\n", value);
448 psxHu16ref(0x1074) = SWAPu16(value);
449 if (psxHu16ref(0x1070) & value)
450 new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1);
455 PSXHW_LOG("COUNTER 0 COUNT 16bit write %x\n", value);
457 psxRcntWcount(0, value); return;
460 PSXHW_LOG("COUNTER 0 MODE 16bit write %x\n", value);
462 psxRcntWmode(0, value); return;
465 PSXHW_LOG("COUNTER 0 TARGET 16bit write %x\n", value);
467 psxRcntWtarget(0, value); return;
471 PSXHW_LOG("COUNTER 1 COUNT 16bit write %x\n", value);
473 psxRcntWcount(1, value); return;
476 PSXHW_LOG("COUNTER 1 MODE 16bit write %x\n", value);
478 psxRcntWmode(1, value); return;
481 PSXHW_LOG("COUNTER 1 TARGET 16bit write %x\n", value);
483 psxRcntWtarget(1, value); return;
487 PSXHW_LOG("COUNTER 2 COUNT 16bit write %x\n", value);
489 psxRcntWcount(2, value); return;
492 PSXHW_LOG("COUNTER 2 MODE 16bit write %x\n", value);
494 psxRcntWmode(2, value); return;
497 PSXHW_LOG("COUNTER 2 TARGET 16bit write %x\n", value);
499 psxRcntWtarget(2, value); return;
502 if (add>=0x1f801c00 && add<0x1f801e00) {
503 SPU_writeRegister(add, value, psxRegs.cycle);
507 psxHu16ref(add) = SWAPu16(value);
509 PSXHW_LOG("*Unknown 16bit write at address %x value %x\n", add, value);
513 psxHu16ref(add) = SWAPu16(value);
515 PSXHW_LOG("*Known 16bit write at address %x value %x\n", add, value);
519 #define DmaExec(n) { \
520 HW_DMA##n##_CHCR = SWAPu32(value); \
522 if (SWAPu32(HW_DMA##n##_CHCR) & 0x01000000 && SWAPu32(HW_DMA_PCR) & (8 << (n * 4))) { \
523 psxDma##n(SWAPu32(HW_DMA##n##_MADR), SWAPu32(HW_DMA##n##_BCR), SWAPu32(HW_DMA##n##_CHCR)); \
527 void psxHwWrite32(u32 add, u32 value) {
530 sioWrite8((unsigned char)value);
531 sioWrite8((unsigned char)((value&0xff) >> 8));
532 sioWrite8((unsigned char)((value&0xff) >> 16));
533 sioWrite8((unsigned char)((value&0xff) >> 24));
535 PAD_LOG("sio write32 %x\n", value);
538 #ifdef ENABLE_SIO1API
540 SIO1_writeData32(value);
545 PSXHW_LOG("RAM size write %x\n", value);
546 psxHu32ref(add) = SWAPu32(value);
552 PSXHW_LOG("IREG 32bit write %x\n", value);
554 if (Config.Sio) psxHu32ref(0x1070) |= SWAPu32(0x80);
555 if (Config.SpuIrq) psxHu32ref(0x1070) |= SWAPu32(0x200);
556 psxHu32ref(0x1070) &= SWAPu32(value);
560 PSXHW_LOG("IMASK 32bit write %x\n", value);
562 psxHu32ref(0x1074) = SWAPu32(value);
563 if (psxHu32ref(0x1070) & value)
564 new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1);
569 PSXHW_LOG("DMA0 MADR 32bit write %x\n", value);
570 HW_DMA0_MADR = SWAPu32(value); return; // DMA0 madr
572 PSXHW_LOG("DMA0 BCR 32bit write %x\n", value);
573 HW_DMA0_BCR = SWAPu32(value); return; // DMA0 bcr
577 PSXHW_LOG("DMA0 CHCR 32bit write %x\n", value);
579 DmaExec(0); // DMA0 chcr (MDEC in DMA)
584 PSXHW_LOG("DMA1 MADR 32bit write %x\n", value);
585 HW_DMA1_MADR = SWAPu32(value); return; // DMA1 madr
587 PSXHW_LOG("DMA1 BCR 32bit write %x\n", value);
588 HW_DMA1_BCR = SWAPu32(value); return; // DMA1 bcr
592 PSXHW_LOG("DMA1 CHCR 32bit write %x\n", value);
594 DmaExec(1); // DMA1 chcr (MDEC out DMA)
599 PSXHW_LOG("DMA2 MADR 32bit write %x\n", value);
600 HW_DMA2_MADR = SWAPu32(value); return; // DMA2 madr
602 PSXHW_LOG("DMA2 BCR 32bit write %x\n", value);
603 HW_DMA2_BCR = SWAPu32(value); return; // DMA2 bcr
607 PSXHW_LOG("DMA2 CHCR 32bit write %x\n", value);
609 DmaExec(2); // DMA2 chcr (GPU DMA)
614 PSXHW_LOG("DMA3 MADR 32bit write %x\n", value);
615 HW_DMA3_MADR = SWAPu32(value); return; // DMA3 madr
617 PSXHW_LOG("DMA3 BCR 32bit write %x\n", value);
618 HW_DMA3_BCR = SWAPu32(value); return; // DMA3 bcr
622 PSXHW_LOG("DMA3 CHCR 32bit write %x\n", value);
624 DmaExec(3); // DMA3 chcr (CDROM DMA)
630 PSXHW_LOG("DMA4 MADR 32bit write %x\n", value);
631 HW_DMA4_MADR = SWAPu32(value); return; // DMA4 madr
633 PSXHW_LOG("DMA4 BCR 32bit write %x\n", value);
634 HW_DMA4_BCR = SWAPu32(value); return; // DMA4 bcr
638 PSXHW_LOG("DMA4 CHCR 32bit write %x\n", value);
640 DmaExec(4); // DMA4 chcr (SPU DMA)
644 case 0x1f8010d0: break; //DMA5write_madr();
645 case 0x1f8010d4: break; //DMA5write_bcr();
646 case 0x1f8010d8: break; //DMA5write_chcr(); // Not needed
651 PSXHW_LOG("DMA6 MADR 32bit write %x\n", value);
652 HW_DMA6_MADR = SWAPu32(value); return; // DMA6 bcr
654 PSXHW_LOG("DMA6 BCR 32bit write %x\n", value);
655 HW_DMA6_BCR = SWAPu32(value); return; // DMA6 bcr
659 PSXHW_LOG("DMA6 CHCR 32bit write %x\n", value);
661 DmaExec(6); // DMA6 chcr (OT clear)
666 PSXHW_LOG("DMA PCR 32bit write %x\n", value);
667 HW_DMA_PCR = SWAPu32(value);
673 PSXHW_LOG("DMA ICR 32bit write %x\n", value);
676 u32 tmp = value & 0x00ff803f;
677 tmp |= (SWAPu32(HW_DMA_ICR) & ~value) & 0x7f000000;
678 if ((tmp & HW_DMA_ICR_GLOBAL_ENABLE && tmp & 0x7f000000)
679 || tmp & HW_DMA_ICR_BUS_ERROR) {
680 if (!(SWAPu32(HW_DMA_ICR) & HW_DMA_ICR_IRQ_SENT))
681 psxHu32ref(0x1070) |= SWAP32(8);
682 tmp |= HW_DMA_ICR_IRQ_SENT;
684 HW_DMA_ICR = SWAPu32(tmp);
690 PSXHW_LOG("GPU DATA 32bit write %x\n", value);
692 GPU_writeData(value); return;
695 PSXHW_LOG("GPU STATUS 32bit write %x\n", value);
697 GPU_writeStatus(value);
702 mdecWrite0(value); break;
704 mdecWrite1(value); break;
708 PSXHW_LOG("COUNTER 0 COUNT 32bit write %x\n", value);
710 psxRcntWcount(0, value & 0xffff); return;
713 PSXHW_LOG("COUNTER 0 MODE 32bit write %x\n", value);
715 psxRcntWmode(0, value); return;
718 PSXHW_LOG("COUNTER 0 TARGET 32bit write %x\n", value);
720 psxRcntWtarget(0, value & 0xffff); return; // HW_DMA_ICR&= SWAP32((~value)&0xff000000);
724 PSXHW_LOG("COUNTER 1 COUNT 32bit write %x\n", value);
726 psxRcntWcount(1, value & 0xffff); return;
729 PSXHW_LOG("COUNTER 1 MODE 32bit write %x\n", value);
731 psxRcntWmode(1, value); return;
734 PSXHW_LOG("COUNTER 1 TARGET 32bit write %x\n", value);
736 psxRcntWtarget(1, value & 0xffff); return;
740 PSXHW_LOG("COUNTER 2 COUNT 32bit write %x\n", value);
742 psxRcntWcount(2, value & 0xffff); return;
745 PSXHW_LOG("COUNTER 2 MODE 32bit write %x\n", value);
747 psxRcntWmode(2, value); return;
750 PSXHW_LOG("COUNTER 2 TARGET 32bit write %x\n", value);
752 psxRcntWtarget(2, value & 0xffff); return;
755 // Dukes of Hazard 2 - car engine noise
756 if (add>=0x1f801c00 && add<0x1f801e00) {
757 SPU_writeRegister(add, value&0xffff, psxRegs.cycle);
758 SPU_writeRegister(add + 2, value>>16, psxRegs.cycle);
762 psxHu32ref(add) = SWAPu32(value);
764 PSXHW_LOG("*Unknown 32bit write at address %x value %x\n", add, value);
768 psxHu32ref(add) = SWAPu32(value);
770 PSXHW_LOG("*Known 32bit write at address %x value %x\n", add, value);
774 int psxHwFreeze(void *f, int Mode) {