log unhandled io more clearly
[pcsx_rearmed.git] / libpcsxcore / psxhw.c
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 02111-1307 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 //#undef PSXHW_LOG
30 //#define PSXHW_LOG printf
31 #ifndef PAD_LOG
32 #define PAD_LOG(...)
33 #endif
34
35 void psxHwReset() {
36         memset(psxH, 0, 0x10000);
37
38         mdecInit(); // initialize mdec decoder
39         cdrReset();
40         psxRcntInit();
41         HW_GPU_STATUS = SWAP32(0x14802000);
42 }
43
44 u8 psxHwRead8(u32 add) {
45         unsigned char hard;
46
47         switch (add & 0x1fffffff) {
48                 case 0x1f801040: hard = sioRead8(); break;
49                 case 0x1f801800: hard = cdrRead0(); break;
50                 case 0x1f801801: hard = cdrRead1(); break;
51                 case 0x1f801802: hard = cdrRead2(); break;
52                 case 0x1f801803: hard = cdrRead3(); break;
53
54                 case 0x1f801041: case 0x1f801042: case 0x1f801043:
55                 case 0x1f801044: case 0x1f801045:
56                 case 0x1f801046: case 0x1f801047:
57                 case 0x1f801048: case 0x1f801049:
58                 case 0x1f80104a: case 0x1f80104b:
59                 case 0x1f80104c: case 0x1f80104d:
60                 case 0x1f80104e: case 0x1f80104f:
61                 case 0x1f801050: case 0x1f801051:
62                 case 0x1f801054: case 0x1f801055:
63                 case 0x1f801058: case 0x1f801059:
64                 case 0x1f80105a: case 0x1f80105b:
65                 case 0x1f80105c: case 0x1f80105d:
66                 case 0x1f801100: case 0x1f801101:
67                 case 0x1f801104: case 0x1f801105:
68                 case 0x1f801108: case 0x1f801109:
69                 case 0x1f801110: case 0x1f801111:
70                 case 0x1f801114: case 0x1f801115:
71                 case 0x1f801118: case 0x1f801119:
72                 case 0x1f801120: case 0x1f801121:
73                 case 0x1f801124: case 0x1f801125:
74                 case 0x1f801128: case 0x1f801129:
75                 case 0x1f801810: case 0x1f801811:
76                 case 0x1f801812: case 0x1f801813:
77                 case 0x1f801814: case 0x1f801815:
78                 case 0x1f801816: case 0x1f801817:
79                 case 0x1f801820: case 0x1f801821:
80                 case 0x1f801822: case 0x1f801823:
81                 case 0x1f801824: case 0x1f801825:
82                 case 0x1f801826: case 0x1f801827:
83                         log_unhandled("unhandled r8  %08x @%08x\n", add, psxRegs.pc);
84                         // falthrough
85                 default:
86                         if (0x1f801c00 <= add && add < 0x1f802000)
87                                 log_unhandled("spu r8 %02x @%08x\n", add, psxRegs.pc);
88                         hard = psxHu8(add); 
89 #ifdef PSXHW_LOG
90                         PSXHW_LOG("*Unkwnown 8bit read at address %x\n", add);
91 #endif
92                         return hard;
93         }
94
95 #ifdef PSXHW_LOG
96         PSXHW_LOG("*Known 8bit read at address %x value %x\n", add, hard);
97 #endif
98         return hard;
99 }
100
101 u16 psxHwRead16(u32 add) {
102         unsigned short hard;
103
104         switch (add & 0x1fffffff) {
105 #ifdef PSXHW_LOG
106                 case 0x1f801070: PSXHW_LOG("IREG 16bit read %x\n", psxHu16(0x1070));
107                         return psxHu16(0x1070);
108                 case 0x1f801074: PSXHW_LOG("IMASK 16bit read %x\n", psxHu16(0x1074));
109                         return psxHu16(0x1074);
110 #endif
111                 case 0x1f801040:
112                         hard = sioRead8();
113                         hard|= sioRead8() << 8;
114                         PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
115                         return hard;
116                 case 0x1f801044:
117                         hard = sioReadStat16();
118                         PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
119                         return hard;
120                 case 0x1f801048:
121                         hard = sioReadMode16();
122                         PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
123                         return hard;
124                 case 0x1f80104a:
125                         hard = sioReadCtrl16();
126                         PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
127                         return hard;
128                 case 0x1f80104e:
129                         hard = sioReadBaud16();
130                         PAD_LOG("sio read16 %x; ret = %x\n", add&0xf, hard);
131                         return hard;
132
133                 /* Fixes Armored Core misdetecting the Link cable being detected.
134                  * We want to turn that thing off and force it to do local multiplayer instead.
135                  * Thanks Sony for the fix, they fixed it in their PS Classic fork.
136                  */
137                 case 0x1f801054:
138                         return 0x80;\r
139
140                 case 0x1f801100:
141                         hard = psxRcntRcount(0);
142 #ifdef PSXHW_LOG
143                         PSXHW_LOG("T0 count read16: %x\n", hard);
144 #endif
145                         return hard;
146                 case 0x1f801104:
147                         hard = psxRcntRmode(0);
148 #ifdef PSXHW_LOG
149                         PSXHW_LOG("T0 mode read16: %x\n", hard);
150 #endif
151                         return hard;
152                 case 0x1f801108:
153                         hard = psxRcntRtarget(0);
154 #ifdef PSXHW_LOG
155                         PSXHW_LOG("T0 target read16: %x\n", hard);
156 #endif
157                         return hard;
158                 case 0x1f801110:
159                         hard = psxRcntRcount(1);
160 #ifdef PSXHW_LOG
161                         PSXHW_LOG("T1 count read16: %x\n", hard);
162 #endif
163                         return hard;
164                 case 0x1f801114:
165                         hard = psxRcntRmode(1);
166 #ifdef PSXHW_LOG
167                         PSXHW_LOG("T1 mode read16: %x\n", hard);
168 #endif
169                         return hard;
170                 case 0x1f801118:
171                         hard = psxRcntRtarget(1);
172 #ifdef PSXHW_LOG
173                         PSXHW_LOG("T1 target read16: %x\n", hard);
174 #endif
175                         return hard;
176                 case 0x1f801120:
177                         hard = psxRcntRcount(2);
178 #ifdef PSXHW_LOG
179                         PSXHW_LOG("T2 count read16: %x\n", hard);
180 #endif
181                         return hard;
182                 case 0x1f801124:
183                         hard = psxRcntRmode(2);
184 #ifdef PSXHW_LOG
185                         PSXHW_LOG("T2 mode read16: %x\n", hard);
186 #endif
187                         return hard;
188                 case 0x1f801128:
189                         hard = psxRcntRtarget(2);
190 #ifdef PSXHW_LOG
191                         PSXHW_LOG("T2 target read16: %x\n", hard);
192 #endif
193                         return hard;
194
195                 //case 0x1f802030: hard =   //int_2000????
196                 //case 0x1f802040: hard =//dip switches...??
197
198                 case 0x1f801042:
199                 case 0x1f801046:
200                 case 0x1f80104c:
201                 case 0x1f801050:
202                 case 0x1f801058:
203                 case 0x1f80105a:
204                 case 0x1f80105c:
205                 case 0x1f801800:
206                 case 0x1f801802:
207                 case 0x1f801810:
208                 case 0x1f801812:
209                 case 0x1f801814:
210                 case 0x1f801816:
211                 case 0x1f801820:
212                 case 0x1f801822:
213                 case 0x1f801824:
214                 case 0x1f801826:
215                         log_unhandled("unhandled r16 %08x @%08x\n", add, psxRegs.pc);
216                         // falthrough
217                 default:
218                         if (0x1f801c00 <= add && add < 0x1f802000)
219                                 return SPU_readRegister(add);
220                         hard = psxHu16(add);
221 #ifdef PSXHW_LOG
222                         PSXHW_LOG("*Unkwnown 16bit read at address %x\n", add);
223 #endif
224                         return hard;
225         }
226         
227 #ifdef PSXHW_LOG
228         PSXHW_LOG("*Known 16bit read at address %x value %x\n", add, hard);
229 #endif
230         return hard;
231 }
232
233 u32 psxHwRead32(u32 add) {
234         u32 hard;
235
236         switch (add & 0x1fffffff) {
237                 case 0x1f801040:
238                         hard = sioRead8();
239                         hard |= sioRead8() << 8;
240                         hard |= sioRead8() << 16;
241                         hard |= sioRead8() << 24;
242                         PAD_LOG("sio read32 ;ret = %x\n", hard);
243                         return hard;
244                 case 0x1f801044:
245                         hard = sioReadStat16();
246                         PAD_LOG("sio read32 %x; ret = %x\n", add&0xf, hard);
247                         return hard;
248 #ifdef PSXHW_LOG
249                 case 0x1f801060:
250                         PSXHW_LOG("RAM size read %x\n", psxHu32(0x1060));
251                         return psxHu32(0x1060);
252                 case 0x1f801070: PSXHW_LOG("IREG 32bit read %x\n", psxHu32(0x1070));
253                         return psxHu32(0x1070);
254                 case 0x1f801074: PSXHW_LOG("IMASK 32bit read %x\n", psxHu32(0x1074));
255                         return psxHu32(0x1074);
256 #endif
257
258                 case 0x1f801810:
259                         hard = GPU_readData();
260 #ifdef PSXHW_LOG
261                         PSXHW_LOG("GPU DATA 32bit read %x\n", hard);
262 #endif
263                         return hard;
264                 case 0x1f801814:
265                         gpuSyncPluginSR();
266                         hard = SWAP32(HW_GPU_STATUS);
267                         if (hSyncCount < 240 && (hard & PSXGPU_ILACE_BITS) != PSXGPU_ILACE_BITS)
268                                 hard |= PSXGPU_LCF & (psxRegs.cycle << 20);
269 #ifdef PSXHW_LOG
270                         PSXHW_LOG("GPU STATUS 32bit read %x\n", hard);
271 #endif
272                         return hard;
273
274                 case 0x1f801820: hard = mdecRead0(); break;
275                 case 0x1f801824: hard = mdecRead1(); break;
276
277 #ifdef PSXHW_LOG
278                 case 0x1f8010a0:
279                         PSXHW_LOG("DMA2 MADR 32bit read %x\n", psxHu32(0x10a0));
280                         return SWAPu32(HW_DMA2_MADR);
281                 case 0x1f8010a4:
282                         PSXHW_LOG("DMA2 BCR 32bit read %x\n", psxHu32(0x10a4));
283                         return SWAPu32(HW_DMA2_BCR);
284                 case 0x1f8010a8:
285                         PSXHW_LOG("DMA2 CHCR 32bit read %x\n", psxHu32(0x10a8));
286                         return SWAPu32(HW_DMA2_CHCR);
287 #endif
288
289 #ifdef PSXHW_LOG
290                 case 0x1f8010b0:
291                         PSXHW_LOG("DMA3 MADR 32bit read %x\n", psxHu32(0x10b0));
292                         return SWAPu32(HW_DMA3_MADR);
293                 case 0x1f8010b4:
294                         PSXHW_LOG("DMA3 BCR 32bit read %x\n", psxHu32(0x10b4));
295                         return SWAPu32(HW_DMA3_BCR);
296                 case 0x1f8010b8:
297                         PSXHW_LOG("DMA3 CHCR 32bit read %x\n", psxHu32(0x10b8));
298                         return SWAPu32(HW_DMA3_CHCR);
299 #endif
300
301 #ifdef PSXHW_LOG
302 /*              case 0x1f8010f0:
303                         PSXHW_LOG("DMA PCR 32bit read %x\n", psxHu32(0x10f0));
304                         return SWAPu32(HW_DMA_PCR); // dma rest channel
305                 case 0x1f8010f4:
306                         PSXHW_LOG("DMA ICR 32bit read %x\n", psxHu32(0x10f4));
307                         return SWAPu32(HW_DMA_ICR); // interrupt enabler?*/
308 #endif
309
310                 // time for rootcounters :)
311                 case 0x1f801100:
312                         hard = psxRcntRcount(0);
313 #ifdef PSXHW_LOG
314                         PSXHW_LOG("T0 count read32: %x\n", hard);
315 #endif
316                         return hard;
317                 case 0x1f801104:
318                         hard = psxRcntRmode(0);
319 #ifdef PSXHW_LOG
320                         PSXHW_LOG("T0 mode read32: %x\n", hard);
321 #endif
322                         return hard;
323                 case 0x1f801108:
324                         hard = psxRcntRtarget(0);
325 #ifdef PSXHW_LOG
326                         PSXHW_LOG("T0 target read32: %x\n", hard);
327 #endif
328                         return hard;
329                 case 0x1f801110:
330                         hard = psxRcntRcount(1);
331 #ifdef PSXHW_LOG
332                         PSXHW_LOG("T1 count read32: %x\n", hard);
333 #endif
334                         return hard;
335                 case 0x1f801114:
336                         hard = psxRcntRmode(1);
337 #ifdef PSXHW_LOG
338                         PSXHW_LOG("T1 mode read32: %x\n", hard);
339 #endif
340                         return hard;
341                 case 0x1f801118:
342                         hard = psxRcntRtarget(1);
343 #ifdef PSXHW_LOG
344                         PSXHW_LOG("T1 target read32: %x\n", hard);
345 #endif
346                         return hard;
347                 case 0x1f801120:
348                         hard = psxRcntRcount(2);
349 #ifdef PSXHW_LOG
350                         PSXHW_LOG("T2 count read32: %x\n", hard);
351 #endif
352                         return hard;
353                 case 0x1f801124:
354                         hard = psxRcntRmode(2);
355 #ifdef PSXHW_LOG
356                         PSXHW_LOG("T2 mode read32: %x\n", hard);
357 #endif
358                         return hard;
359                 case 0x1f801128:
360                         hard = psxRcntRtarget(2);
361 #ifdef PSXHW_LOG
362                         PSXHW_LOG("T2 target read32: %x\n", hard);
363 #endif
364                         return hard;
365
366                 case 0x1f801048:
367                 case 0x1f80104c:
368                 case 0x1f801050:
369                 case 0x1f801054:
370                 case 0x1f801058:
371                 case 0x1f80105c:
372                 case 0x1f801800:
373                         log_unhandled("unhandled r32 %08x @%08x\n", add, psxRegs.pc);
374                         // falthrough
375                 default:
376                         if (0x1f801c00 <= add && add < 0x1f802000) {
377                                 hard = SPU_readRegister(add);
378                                 hard |= SPU_readRegister(add + 2) << 16;
379                                 return hard;
380                         }
381                         hard = psxHu32(add);
382 #ifdef PSXHW_LOG
383                         PSXHW_LOG("*Unkwnown 32bit read at address %x\n", add);
384 #endif
385                         return hard;
386         }
387 #ifdef PSXHW_LOG
388         PSXHW_LOG("*Known 32bit read at address %x\n", add);
389 #endif
390         return hard;
391 }
392
393 void psxHwWrite8(u32 add, u8 value) {
394         switch (add & 0x1fffffff) {
395                 case 0x1f801040: sioWrite8(value); break;\r
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                 case 0x1f801041: case 0x1f801042: case 0x1f801043:
402                 case 0x1f801044: case 0x1f801045:
403                 case 0x1f801046: case 0x1f801047:
404                 case 0x1f801048: case 0x1f801049:
405                 case 0x1f80104a: case 0x1f80104b:
406                 case 0x1f80104c: case 0x1f80104d:
407                 case 0x1f80104e: case 0x1f80104f:
408                 case 0x1f801050: case 0x1f801051:
409                 case 0x1f801054: case 0x1f801055:
410                 case 0x1f801058: case 0x1f801059:
411                 case 0x1f80105a: case 0x1f80105b:
412                 case 0x1f80105c: case 0x1f80105d:
413                 case 0x1f801100: case 0x1f801101:
414                 case 0x1f801104: case 0x1f801105:
415                 case 0x1f801108: case 0x1f801109:
416                 case 0x1f801110: case 0x1f801111:
417                 case 0x1f801114: case 0x1f801115:
418                 case 0x1f801118: case 0x1f801119:
419                 case 0x1f801120: case 0x1f801121:
420                 case 0x1f801124: case 0x1f801125:
421                 case 0x1f801128: case 0x1f801129:
422                 case 0x1f801810: case 0x1f801811:
423                 case 0x1f801812: case 0x1f801813:
424                 case 0x1f801814: case 0x1f801815:
425                 case 0x1f801816: case 0x1f801817:
426                 case 0x1f801820: case 0x1f801821:
427                 case 0x1f801822: case 0x1f801823:
428                 case 0x1f801824: case 0x1f801825:
429                 case 0x1f801826: case 0x1f801827:
430                         log_unhandled("unhandled w8  %08x @%08x\n", add, psxRegs.pc);
431                         // falthrough
432                 default:
433                         if (0x1f801c00 <= add && add < 0x1f802000) {
434                                 log_unhandled("spu w8 %02x @%08x\n", value, psxRegs.pc);
435                                 if (!(add & 1))
436                                         SPU_writeRegister(add, value, psxRegs.cycle);
437                                 return;
438                         }
439
440                         psxHu8(add) = value;
441 #ifdef PSXHW_LOG
442                         PSXHW_LOG("*Unknown 8bit write at address %x value %x\n", add, value);
443 #endif
444                         return;
445         }
446         psxHu8(add) = value;
447 #ifdef PSXHW_LOG
448         PSXHW_LOG("*Known 8bit write at address %x value %x\n", add, value);
449 #endif
450 }
451
452 void psxHwWrite16(u32 add, u16 value) {
453         switch (add & 0x1fffffff) {
454                 case 0x1f801040:
455                         sioWrite8((unsigned char)value);
456                         sioWrite8((unsigned char)(value>>8));
457                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
458                         return;
459                 case 0x1f801044:
460                         sioWriteStat16(value);
461                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
462                         return;
463                 case 0x1f801048:
464                         sioWriteMode16(value);
465                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
466                         return;
467                 case 0x1f80104a: // control register
468                         sioWriteCtrl16(value);
469                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
470                         return;
471                 case 0x1f80104e: // baudrate register
472                         sioWriteBaud16(value);
473                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
474                         return;
475                 case 0x1f801070: 
476 #ifdef PSXHW_LOG
477                         PSXHW_LOG("IREG 16bit write %x\n", value);
478 #endif
479                         psxHu16ref(0x1070) &= SWAPu16(value);
480                         return;
481
482                 case 0x1f801074:
483 #ifdef PSXHW_LOG
484                         PSXHW_LOG("IMASK 16bit write %x\n", value);
485 #endif
486                         psxHu16ref(0x1074) = SWAPu16(value);
487                         if (psxHu16ref(0x1070) & SWAPu16(value)) {
488                                 //if ((psxRegs.CP0.n.SR & 0x401) == 0x401)
489                                 //      log_unhandled("irq on unmask @%08x\n", psxRegs.pc);
490                                 new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1);
491                         }
492                         return;
493
494                 case 0x1f801100:
495 #ifdef PSXHW_LOG
496                         PSXHW_LOG("COUNTER 0 COUNT 16bit write %x\n", value);
497 #endif
498                         psxRcntWcount(0, value); return;
499                 case 0x1f801104:
500 #ifdef PSXHW_LOG
501                         PSXHW_LOG("COUNTER 0 MODE 16bit write %x\n", value);
502 #endif
503                         psxRcntWmode(0, value); return;
504                 case 0x1f801108:
505 #ifdef PSXHW_LOG
506                         PSXHW_LOG("COUNTER 0 TARGET 16bit write %x\n", value);
507 #endif
508                         psxRcntWtarget(0, value); return;
509
510                 case 0x1f801110:
511 #ifdef PSXHW_LOG
512                         PSXHW_LOG("COUNTER 1 COUNT 16bit write %x\n", value);
513 #endif
514                         psxRcntWcount(1, value); return;
515                 case 0x1f801114:
516 #ifdef PSXHW_LOG
517                         PSXHW_LOG("COUNTER 1 MODE 16bit write %x\n", value);
518 #endif
519                         psxRcntWmode(1, value); return;
520                 case 0x1f801118:
521 #ifdef PSXHW_LOG
522                         PSXHW_LOG("COUNTER 1 TARGET 16bit write %x\n", value);
523 #endif
524                         psxRcntWtarget(1, value); return;
525
526                 case 0x1f801120:
527 #ifdef PSXHW_LOG
528                         PSXHW_LOG("COUNTER 2 COUNT 16bit write %x\n", value);
529 #endif
530                         psxRcntWcount(2, value); return;
531                 case 0x1f801124:
532 #ifdef PSXHW_LOG
533                         PSXHW_LOG("COUNTER 2 MODE 16bit write %x\n", value);
534 #endif
535                         psxRcntWmode(2, value); return;
536                 case 0x1f801128:
537 #ifdef PSXHW_LOG
538                         PSXHW_LOG("COUNTER 2 TARGET 16bit write %x\n", value);
539 #endif
540                         psxRcntWtarget(2, value); return;
541
542                 case 0x1f801042:
543                 case 0x1f801046:
544                 case 0x1f80104c:
545                 case 0x1f801050:
546                 case 0x1f801054:
547                 case 0x1f801058:
548                 case 0x1f80105a:
549                 case 0x1f80105c:
550                 case 0x1f801800:
551                 case 0x1f801802:
552                 case 0x1f801810:
553                 case 0x1f801812:
554                 case 0x1f801814:
555                 case 0x1f801816:
556                 case 0x1f801820:
557                 case 0x1f801822:
558                 case 0x1f801824:
559                 case 0x1f801826:
560                         log_unhandled("unhandled w16 %08x @%08x\n", add, psxRegs.pc);
561                         // falthrough
562                 default:
563                         if (0x1f801c00 <= add && add < 0x1f802000) {
564                                 SPU_writeRegister(add, value, psxRegs.cycle);
565                                 return;
566                         }
567
568                         psxHu16ref(add) = SWAPu16(value);
569 #ifdef PSXHW_LOG
570                         PSXHW_LOG("*Unknown 16bit write at address %x value %x\n", add, value);
571 #endif
572                         return;
573         }
574         psxHu16ref(add) = SWAPu16(value);
575 #ifdef PSXHW_LOG
576         PSXHW_LOG("*Known 16bit write at address %x value %x\n", add, value);
577 #endif
578 }
579
580 #define DmaExec(n) { \
581         if (value & SWAPu32(HW_DMA##n##_CHCR) & 0x01000000) \
582                 log_unhandled("dma" #n " %08x -> %08x\n", HW_DMA##n##_CHCR, value); \
583         HW_DMA##n##_CHCR = SWAPu32(value); \
584 \
585         if (SWAPu32(HW_DMA##n##_CHCR) & 0x01000000 && SWAPu32(HW_DMA_PCR) & (8 << (n * 4))) { \
586                 psxDma##n(SWAPu32(HW_DMA##n##_MADR), SWAPu32(HW_DMA##n##_BCR), SWAPu32(HW_DMA##n##_CHCR)); \
587         } \
588 }
589
590 void psxHwWrite32(u32 add, u32 value) {
591         switch (add & 0x1fffffff) {
592             case 0x1f801040:
593                         sioWrite8((unsigned char)value);
594                         sioWrite8((unsigned char)((value&0xff) >>  8));
595                         sioWrite8((unsigned char)((value&0xff) >> 16));
596                         sioWrite8((unsigned char)((value&0xff) >> 24));
597                         PAD_LOG("sio write32 %x\n", value);
598                         return;
599 #ifdef PSXHW_LOG
600                 case 0x1f801060:
601                         PSXHW_LOG("RAM size write %x\n", value);
602                         psxHu32ref(add) = SWAPu32(value);
603                         return; // Ram size
604 #endif
605
606                 case 0x1f801070: 
607 #ifdef PSXHW_LOG
608                         PSXHW_LOG("IREG 32bit write %x\n", value);
609 #endif
610                         psxHu32ref(0x1070) &= SWAPu32(value);
611                         return;
612                 case 0x1f801074:
613 #ifdef PSXHW_LOG
614                         PSXHW_LOG("IMASK 32bit write %x\n", value);
615 #endif
616                         psxHu32ref(0x1074) = SWAPu32(value);
617                         if (psxHu32ref(0x1070) & SWAPu32(value)) {
618                                 if ((psxRegs.CP0.n.SR & 0x401) == 0x401)
619                                         log_unhandled("irq on unmask @%08x\n", psxRegs.pc);
620                                 new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1);
621                         }
622                         return;
623
624 #ifdef PSXHW_LOG
625                 case 0x1f801080:
626                         PSXHW_LOG("DMA0 MADR 32bit write %x\n", value);
627                         HW_DMA0_MADR = SWAPu32(value); return; // DMA0 madr
628                 case 0x1f801084:
629                         PSXHW_LOG("DMA0 BCR 32bit write %x\n", value);
630                         HW_DMA0_BCR  = SWAPu32(value); return; // DMA0 bcr
631 #endif
632                 case 0x1f801088:
633 #ifdef PSXHW_LOG
634                         PSXHW_LOG("DMA0 CHCR 32bit write %x\n", value);
635 #endif
636                         DmaExec(0);                      // DMA0 chcr (MDEC in DMA)
637                         return;
638
639 #ifdef PSXHW_LOG
640                 case 0x1f801090:
641                         PSXHW_LOG("DMA1 MADR 32bit write %x\n", value);
642                         HW_DMA1_MADR = SWAPu32(value); return; // DMA1 madr
643                 case 0x1f801094:
644                         PSXHW_LOG("DMA1 BCR 32bit write %x\n", value);
645                         HW_DMA1_BCR  = SWAPu32(value); return; // DMA1 bcr
646 #endif
647                 case 0x1f801098:
648 #ifdef PSXHW_LOG
649                         PSXHW_LOG("DMA1 CHCR 32bit write %x\n", value);
650 #endif
651                         DmaExec(1);                  // DMA1 chcr (MDEC out DMA)
652                         return;
653
654 #ifdef PSXHW_LOG
655                 case 0x1f8010a0:
656                         PSXHW_LOG("DMA2 MADR 32bit write %x\n", value);
657                         HW_DMA2_MADR = SWAPu32(value); return; // DMA2 madr
658                 case 0x1f8010a4:
659                         PSXHW_LOG("DMA2 BCR 32bit write %x\n", value);
660                         HW_DMA2_BCR  = SWAPu32(value); return; // DMA2 bcr
661 #endif
662                 case 0x1f8010a8:
663 #ifdef PSXHW_LOG
664                         PSXHW_LOG("DMA2 CHCR 32bit write %x\n", value);
665 #endif
666                         DmaExec(2);                  // DMA2 chcr (GPU DMA)
667                         return;
668
669 #ifdef PSXHW_LOG
670                 case 0x1f8010b0:
671                         PSXHW_LOG("DMA3 MADR 32bit write %x\n", value);
672                         HW_DMA3_MADR = SWAPu32(value); return; // DMA3 madr
673                 case 0x1f8010b4:
674                         PSXHW_LOG("DMA3 BCR 32bit write %x\n", value);
675                         HW_DMA3_BCR  = SWAPu32(value); return; // DMA3 bcr
676 #endif
677                 case 0x1f8010b8:
678 #ifdef PSXHW_LOG
679                         PSXHW_LOG("DMA3 CHCR 32bit write %x\n", value);
680 #endif
681                         DmaExec(3);                  // DMA3 chcr (CDROM DMA)
682                         
683                         return;
684
685 #ifdef PSXHW_LOG
686                 case 0x1f8010c0:
687                         PSXHW_LOG("DMA4 MADR 32bit write %x\n", value);
688                         HW_DMA4_MADR = SWAPu32(value); return; // DMA4 madr
689                 case 0x1f8010c4:
690                         PSXHW_LOG("DMA4 BCR 32bit write %x\n", value);
691                         HW_DMA4_BCR  = SWAPu32(value); return; // DMA4 bcr
692 #endif
693                 case 0x1f8010c8:
694 #ifdef PSXHW_LOG
695                         PSXHW_LOG("DMA4 CHCR 32bit write %x\n", value);
696 #endif
697                         DmaExec(4);                  // DMA4 chcr (SPU DMA)
698                         return;
699
700 #if 0
701                 case 0x1f8010d0: break; //DMA5write_madr();
702                 case 0x1f8010d4: break; //DMA5write_bcr();
703                 case 0x1f8010d8: break; //DMA5write_chcr(); // Not needed
704 #endif
705
706 #ifdef PSXHW_LOG
707                 case 0x1f8010e0:
708                         PSXHW_LOG("DMA6 MADR 32bit write %x\n", value);
709                         HW_DMA6_MADR = SWAPu32(value); return; // DMA6 bcr
710                 case 0x1f8010e4:
711                         PSXHW_LOG("DMA6 BCR 32bit write %x\n", value);
712                         HW_DMA6_BCR  = SWAPu32(value); return; // DMA6 bcr
713 #endif
714                 case 0x1f8010e8:
715 #ifdef PSXHW_LOG
716                         PSXHW_LOG("DMA6 CHCR 32bit write %x\n", value);
717 #endif
718                         DmaExec(6);                   // DMA6 chcr (OT clear)
719                         return;
720
721 #ifdef PSXHW_LOG
722                 case 0x1f8010f0:
723                         PSXHW_LOG("DMA PCR 32bit write %x\n", value);
724                         HW_DMA_PCR = SWAPu32(value);
725                         return;
726 #endif
727
728                 case 0x1f8010f4:
729 #ifdef PSXHW_LOG
730                         PSXHW_LOG("DMA ICR 32bit write %x\n", value);
731 #endif
732                 {
733                         u32 tmp = value & 0x00ff803f;
734                         tmp |= (SWAPu32(HW_DMA_ICR) & ~value) & 0x7f000000;
735                         if ((tmp & HW_DMA_ICR_GLOBAL_ENABLE && tmp & 0x7f000000)
736                             || tmp & HW_DMA_ICR_BUS_ERROR) {
737                                 if (!(SWAPu32(HW_DMA_ICR) & HW_DMA_ICR_IRQ_SENT))
738                                         psxHu32ref(0x1070) |= SWAP32(8);
739                                 tmp |= HW_DMA_ICR_IRQ_SENT;
740                         }
741                         HW_DMA_ICR = SWAPu32(tmp);
742                         return;
743                 }
744
745                 case 0x1f801810:
746 #ifdef PSXHW_LOG
747                         PSXHW_LOG("GPU DATA 32bit write %x\n", value);
748 #endif
749                         GPU_writeData(value); return;
750                 case 0x1f801814:
751 #ifdef PSXHW_LOG
752                         PSXHW_LOG("GPU STATUS 32bit write %x\n", value);
753 #endif
754                         GPU_writeStatus(value);
755                         gpuSyncPluginSR();
756                         return;
757
758                 case 0x1f801820:
759                         mdecWrite0(value); break;
760                 case 0x1f801824:
761                         mdecWrite1(value); break;
762
763                 case 0x1f801100:
764 #ifdef PSXHW_LOG
765                         PSXHW_LOG("COUNTER 0 COUNT 32bit write %x\n", value);
766 #endif
767                         psxRcntWcount(0, value & 0xffff); return;
768                 case 0x1f801104:
769 #ifdef PSXHW_LOG
770                         PSXHW_LOG("COUNTER 0 MODE 32bit write %x\n", value);
771 #endif
772                         psxRcntWmode(0, value); return;
773                 case 0x1f801108:
774 #ifdef PSXHW_LOG
775                         PSXHW_LOG("COUNTER 0 TARGET 32bit write %x\n", value);
776 #endif
777                         psxRcntWtarget(0, value & 0xffff); return; //  HW_DMA_ICR&= SWAP32((~value)&0xff000000);
778
779                 case 0x1f801110:
780 #ifdef PSXHW_LOG
781                         PSXHW_LOG("COUNTER 1 COUNT 32bit write %x\n", value);
782 #endif
783                         psxRcntWcount(1, value & 0xffff); return;
784                 case 0x1f801114:
785 #ifdef PSXHW_LOG
786                         PSXHW_LOG("COUNTER 1 MODE 32bit write %x\n", value);
787 #endif
788                         psxRcntWmode(1, value); return;
789                 case 0x1f801118:
790 #ifdef PSXHW_LOG
791                         PSXHW_LOG("COUNTER 1 TARGET 32bit write %x\n", value);
792 #endif
793                         psxRcntWtarget(1, value & 0xffff); return;
794
795                 case 0x1f801120:
796 #ifdef PSXHW_LOG
797                         PSXHW_LOG("COUNTER 2 COUNT 32bit write %x\n", value);
798 #endif
799                         psxRcntWcount(2, value & 0xffff); return;
800                 case 0x1f801124:
801 #ifdef PSXHW_LOG
802                         PSXHW_LOG("COUNTER 2 MODE 32bit write %x\n", value);
803 #endif
804                         psxRcntWmode(2, value); return;
805                 case 0x1f801128:
806 #ifdef PSXHW_LOG
807                         PSXHW_LOG("COUNTER 2 TARGET 32bit write %x\n", value);
808 #endif
809                         psxRcntWtarget(2, value & 0xffff); return;
810
811                 case 0x1f801044:
812                 case 0x1f801048:
813                 case 0x1f80104c:
814                 case 0x1f801050:
815                 case 0x1f801054:
816                 case 0x1f801058:
817                 case 0x1f80105c:
818                 case 0x1f801800:
819                         log_unhandled("unhandled w32 %08x @%08x\n", add, psxRegs.pc);
820                         // falthrough
821                 default:
822                         // Dukes of Hazard 2 - car engine noise
823                         if (0x1f801c00 <= add && add < 0x1f802000) {
824                                 SPU_writeRegister(add, value&0xffff, psxRegs.cycle);
825                                 SPU_writeRegister(add + 2, value>>16, psxRegs.cycle);
826                                 return;
827                         }
828
829                         psxHu32ref(add) = SWAPu32(value);
830 #ifdef PSXHW_LOG
831                         PSXHW_LOG("*Unknown 32bit write at address %x value %x\n", add, value);
832 #endif
833                         return;
834         }
835         psxHu32ref(add) = SWAPu32(value);
836 #ifdef PSXHW_LOG
837         PSXHW_LOG("*Known 32bit write at address %x value %x\n", add, value);
838 #endif
839 }
840
841 int psxHwFreeze(void *f, int Mode) {
842         return 0;
843 }