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