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