psxhw: debug-log more weird writes
[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
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;
477                 case 0x1f8010f6:
478                         // nocash documents it as forced w32, but still games use this?
479                         break;
480                 case 0x1f801800: cdrWrite0(value); break;
481                 case 0x1f801801: cdrWrite1(value); break;
482                 case 0x1f801802: cdrWrite2(value); break;
483                 case 0x1f801803: cdrWrite3(value); break;
484
485                 case 0x1f801810: case 0x1f801811:
486                 case 0x1f801812: case 0x1f801813:
487                 case 0x1f801814: case 0x1f801815:
488                 case 0x1f801816: case 0x1f801817:
489                 case 0x1f801820: case 0x1f801821:
490                 case 0x1f801822: case 0x1f801823:
491                 case 0x1f801824: case 0x1f801825:
492                 case 0x1f801826: case 0x1f801827:
493                         log_unhandled("unhandled w8  %08x @%08x\n", add, psxRegs.pc);
494                         // falthrough
495                 default:
496                         if (0x1f801c00 <= add && add < 0x1f802000) {
497                                 log_unhandled("spu w8 %02x @%08x\n", value, psxRegs.pc);
498                                 if (!(add & 1))
499                                         SPU_writeRegister(add, value, psxRegs.cycle);
500                                 return;
501                         }
502                         else if (0x1f801000 <= add && add < 0x1f801800)
503                                 log_unhandled("unhandled w8  %08x @%08x\n", add, psxRegs.pc);
504
505                         psxHu8(add) = value;
506 #ifdef PSXHW_LOG
507                         PSXHW_LOG("*Unknown 8bit write at address %x value %x\n", add, value);
508 #endif
509                         return;
510         }
511         psxHu8(add) = value;
512 #ifdef PSXHW_LOG
513         PSXHW_LOG("*Known 8bit write at address %x value %x\n", add, value);
514 #endif
515 }
516
517 void psxHwWrite16(u32 add, u16 value) {
518         switch (add & 0x1fffffff) {
519                 case 0x1f801040:
520                         sioWrite8((unsigned char)value);
521                         sioWrite8((unsigned char)(value>>8));
522                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
523                         return;
524                 case 0x1f801044:
525                         sioWriteStat16(value);
526                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
527                         return;
528                 case 0x1f801048:
529                         sioWriteMode16(value);
530                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
531                         return;
532                 case 0x1f80104a: // control register
533                         sioWriteCtrl16(value);
534                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
535                         return;
536                 case 0x1f80104e: // baudrate register
537                         sioWriteBaud16(value);
538                         PAD_LOG ("sio write16 %x, %x\n", add&0xf, value);
539                         return;
540                 case 0x1f801070: 
541 #ifdef PSXHW_LOG
542                         PSXHW_LOG("IREG 16bit write %x\n", value);
543 #endif
544                         psxHwWriteIstat(value);
545                         return;
546
547                 case 0x1f801074:
548 #ifdef PSXHW_LOG
549                         PSXHW_LOG("IMASK 16bit write %x\n", value);
550 #endif
551                         psxHwWriteImask(value);
552                         return;
553
554                 case 0x1f801100:
555 #ifdef PSXHW_LOG
556                         PSXHW_LOG("COUNTER 0 COUNT 16bit write %x\n", value);
557 #endif
558                         psxRcntWcount(0, value); return;
559                 case 0x1f801104:
560 #ifdef PSXHW_LOG
561                         PSXHW_LOG("COUNTER 0 MODE 16bit write %x\n", value);
562 #endif
563                         psxRcntWmode(0, value); return;
564                 case 0x1f801108:
565 #ifdef PSXHW_LOG
566                         PSXHW_LOG("COUNTER 0 TARGET 16bit write %x\n", value);
567 #endif
568                         psxRcntWtarget(0, value); return;
569
570                 case 0x1f801110:
571 #ifdef PSXHW_LOG
572                         PSXHW_LOG("COUNTER 1 COUNT 16bit write %x\n", value);
573 #endif
574                         psxRcntWcount(1, value); return;
575                 case 0x1f801114:
576 #ifdef PSXHW_LOG
577                         PSXHW_LOG("COUNTER 1 MODE 16bit write %x\n", value);
578 #endif
579                         psxRcntWmode(1, value); return;
580                 case 0x1f801118:
581 #ifdef PSXHW_LOG
582                         PSXHW_LOG("COUNTER 1 TARGET 16bit write %x\n", value);
583 #endif
584                         psxRcntWtarget(1, value); return;
585
586                 case 0x1f801120:
587 #ifdef PSXHW_LOG
588                         PSXHW_LOG("COUNTER 2 COUNT 16bit write %x\n", value);
589 #endif
590                         psxRcntWcount(2, value); return;
591                 case 0x1f801124:
592 #ifdef PSXHW_LOG
593                         PSXHW_LOG("COUNTER 2 MODE 16bit write %x\n", value);
594 #endif
595                         psxRcntWmode(2, value); return;
596                 case 0x1f801128:
597 #ifdef PSXHW_LOG
598                         PSXHW_LOG("COUNTER 2 TARGET 16bit write %x\n", value);
599 #endif
600                         psxRcntWtarget(2, value); return;
601
602                 case 0x1f801042:
603                 case 0x1f801046:
604                 case 0x1f80104c:
605                 case 0x1f801050:
606                 case 0x1f801054:
607                 case 0x1f801058:
608                 case 0x1f80105a:
609                 case 0x1f80105c:
610                 case 0x1f801800:
611                 case 0x1f801802:
612                 case 0x1f801810:
613                 case 0x1f801812:
614                 case 0x1f801814:
615                 case 0x1f801816:
616                 case 0x1f801820:
617                 case 0x1f801822:
618                 case 0x1f801824:
619                 case 0x1f801826:
620                         log_unhandled("unhandled w16 %08x @%08x\n", add, psxRegs.pc);
621                         // falthrough
622                 default:
623                         if (0x1f801c00 <= add && add < 0x1f802000) {
624                                 SPU_writeRegister(add, value, psxRegs.cycle);
625                                 return;
626                         }
627
628                         psxHu16ref(add) = SWAPu16(value);
629 #ifdef PSXHW_LOG
630                         PSXHW_LOG("*Unknown 16bit write at address %x value %x\n", add, value);
631 #endif
632                         return;
633         }
634         psxHu16ref(add) = SWAPu16(value);
635 #ifdef PSXHW_LOG
636         PSXHW_LOG("*Known 16bit write at address %x value %x\n", add, value);
637 #endif
638 }
639
640 #define DmaExec(n) { \
641         if (value & SWAPu32(HW_DMA##n##_CHCR) & 0x01000000) \
642                 log_unhandled("dma" #n " %08x -> %08x\n", HW_DMA##n##_CHCR, value); \
643         HW_DMA##n##_CHCR = SWAPu32(value); \
644 \
645         if (SWAPu32(HW_DMA##n##_CHCR) & 0x01000000 && SWAPu32(HW_DMA_PCR) & (8 << (n * 4))) { \
646                 psxDma##n(SWAPu32(HW_DMA##n##_MADR), SWAPu32(HW_DMA##n##_BCR), SWAPu32(HW_DMA##n##_CHCR)); \
647         } \
648 }
649
650 void psxHwWrite32(u32 add, u32 value) {
651         switch (add & 0x1fffffff) {
652             case 0x1f801040:
653                         sioWrite8((unsigned char)value);
654                         sioWrite8((unsigned char)((value&0xff) >>  8));
655                         sioWrite8((unsigned char)((value&0xff) >> 16));
656                         sioWrite8((unsigned char)((value&0xff) >> 24));
657                         PAD_LOG("sio write32 %x\n", value);
658                         return;
659 #ifdef PSXHW_LOG
660                 case 0x1f801060:
661                         PSXHW_LOG("RAM size write %x\n", value);
662                         psxHu32ref(add) = SWAPu32(value);
663                         return; // Ram size
664 #endif
665
666                 case 0x1f801070: 
667 #ifdef PSXHW_LOG
668                         PSXHW_LOG("IREG 32bit write %x\n", value);
669 #endif
670                         psxHwWriteIstat(value);
671                         return;
672                 case 0x1f801074:
673 #ifdef PSXHW_LOG
674                         PSXHW_LOG("IMASK 32bit write %x\n", value);
675 #endif
676                         psxHwWriteImask(value);
677                         return;
678
679 #ifdef PSXHW_LOG
680                 case 0x1f801080:
681                         PSXHW_LOG("DMA0 MADR 32bit write %x\n", value);
682                         HW_DMA0_MADR = SWAPu32(value); return; // DMA0 madr
683                 case 0x1f801084:
684                         PSXHW_LOG("DMA0 BCR 32bit write %x\n", value);
685                         HW_DMA0_BCR  = SWAPu32(value); return; // DMA0 bcr
686 #endif
687                 case 0x1f801088:
688 #ifdef PSXHW_LOG
689                         PSXHW_LOG("DMA0 CHCR 32bit write %x\n", value);
690 #endif
691                         DmaExec(0);                      // DMA0 chcr (MDEC in DMA)
692                         return;
693
694 #ifdef PSXHW_LOG
695                 case 0x1f801090:
696                         PSXHW_LOG("DMA1 MADR 32bit write %x\n", value);
697                         HW_DMA1_MADR = SWAPu32(value); return; // DMA1 madr
698                 case 0x1f801094:
699                         PSXHW_LOG("DMA1 BCR 32bit write %x\n", value);
700                         HW_DMA1_BCR  = SWAPu32(value); return; // DMA1 bcr
701 #endif
702                 case 0x1f801098:
703 #ifdef PSXHW_LOG
704                         PSXHW_LOG("DMA1 CHCR 32bit write %x\n", value);
705 #endif
706                         DmaExec(1);                  // DMA1 chcr (MDEC out DMA)
707                         return;
708
709 #ifdef PSXHW_LOG
710                 case 0x1f8010a0:
711                         PSXHW_LOG("DMA2 MADR 32bit write %x\n", value);
712                         HW_DMA2_MADR = SWAPu32(value); return; // DMA2 madr
713                 case 0x1f8010a4:
714                         PSXHW_LOG("DMA2 BCR 32bit write %x\n", value);
715                         HW_DMA2_BCR  = SWAPu32(value); return; // DMA2 bcr
716 #endif
717                 case 0x1f8010a8:
718 #ifdef PSXHW_LOG
719                         PSXHW_LOG("DMA2 CHCR 32bit write %x\n", value);
720 #endif
721                         DmaExec(2);                  // DMA2 chcr (GPU DMA)
722                         return;
723
724 #ifdef PSXHW_LOG
725                 case 0x1f8010b0:
726                         PSXHW_LOG("DMA3 MADR 32bit write %x\n", value);
727                         HW_DMA3_MADR = SWAPu32(value); return; // DMA3 madr
728                 case 0x1f8010b4:
729                         PSXHW_LOG("DMA3 BCR 32bit write %x\n", value);
730                         HW_DMA3_BCR  = SWAPu32(value); return; // DMA3 bcr
731 #endif
732                 case 0x1f8010b8:
733 #ifdef PSXHW_LOG
734                         PSXHW_LOG("DMA3 CHCR 32bit write %x\n", value);
735 #endif
736                         DmaExec(3);                  // DMA3 chcr (CDROM DMA)
737                         
738                         return;
739
740 #ifdef PSXHW_LOG
741                 case 0x1f8010c0:
742                         PSXHW_LOG("DMA4 MADR 32bit write %x\n", value);
743                         HW_DMA4_MADR = SWAPu32(value); return; // DMA4 madr
744                 case 0x1f8010c4:
745                         PSXHW_LOG("DMA4 BCR 32bit write %x\n", value);
746                         HW_DMA4_BCR  = SWAPu32(value); return; // DMA4 bcr
747 #endif
748                 case 0x1f8010c8:
749 #ifdef PSXHW_LOG
750                         PSXHW_LOG("DMA4 CHCR 32bit write %x\n", value);
751 #endif
752                         DmaExec(4);                  // DMA4 chcr (SPU DMA)
753                         return;
754
755 #if 0
756                 case 0x1f8010d0: break; //DMA5write_madr();
757                 case 0x1f8010d4: break; //DMA5write_bcr();
758                 case 0x1f8010d8: break; //DMA5write_chcr(); // Not needed
759 #endif
760
761 #ifdef PSXHW_LOG
762                 case 0x1f8010e0:
763                         PSXHW_LOG("DMA6 MADR 32bit write %x\n", value);
764                         HW_DMA6_MADR = SWAPu32(value); return; // DMA6 bcr
765                 case 0x1f8010e4:
766                         PSXHW_LOG("DMA6 BCR 32bit write %x\n", value);
767                         HW_DMA6_BCR  = SWAPu32(value); return; // DMA6 bcr
768 #endif
769                 case 0x1f8010e8:
770 #ifdef PSXHW_LOG
771                         PSXHW_LOG("DMA6 CHCR 32bit write %x\n", value);
772 #endif
773                         DmaExec(6);                   // DMA6 chcr (OT clear)
774                         return;
775
776 #ifdef PSXHW_LOG
777                 case 0x1f8010f0:
778                         PSXHW_LOG("DMA PCR 32bit write %x\n", value);
779                         HW_DMA_PCR = SWAPu32(value);
780                         return;
781 #endif
782
783                 case 0x1f8010f4:
784 #ifdef PSXHW_LOG
785                         PSXHW_LOG("DMA ICR 32bit write %x\n", value);
786 #endif
787                         psxHwWriteDmaIcr32(value);
788                         return;
789
790                 case 0x1f801810:
791 #ifdef PSXHW_LOG
792                         PSXHW_LOG("GPU DATA 32bit write %x\n", value);
793 #endif
794                         GPU_writeData(value); return;
795                 case 0x1f801814:
796 #ifdef PSXHW_LOG
797                         PSXHW_LOG("GPU STATUS 32bit write %x\n", value);
798 #endif
799                         psxHwWriteGpuSR(value);
800                         return;
801
802                 case 0x1f801820:
803                         mdecWrite0(value); break;
804                 case 0x1f801824:
805                         mdecWrite1(value); break;
806
807                 case 0x1f801100:
808 #ifdef PSXHW_LOG
809                         PSXHW_LOG("COUNTER 0 COUNT 32bit write %x\n", value);
810 #endif
811                         psxRcntWcount(0, value & 0xffff); return;
812                 case 0x1f801104:
813 #ifdef PSXHW_LOG
814                         PSXHW_LOG("COUNTER 0 MODE 32bit write %x\n", value);
815 #endif
816                         psxRcntWmode(0, value); return;
817                 case 0x1f801108:
818 #ifdef PSXHW_LOG
819                         PSXHW_LOG("COUNTER 0 TARGET 32bit write %x\n", value);
820 #endif
821                         psxRcntWtarget(0, value & 0xffff); return; //  HW_DMA_ICR&= SWAP32((~value)&0xff000000);
822
823                 case 0x1f801110:
824 #ifdef PSXHW_LOG
825                         PSXHW_LOG("COUNTER 1 COUNT 32bit write %x\n", value);
826 #endif
827                         psxRcntWcount(1, value & 0xffff); return;
828                 case 0x1f801114:
829 #ifdef PSXHW_LOG
830                         PSXHW_LOG("COUNTER 1 MODE 32bit write %x\n", value);
831 #endif
832                         psxRcntWmode(1, value); return;
833                 case 0x1f801118:
834 #ifdef PSXHW_LOG
835                         PSXHW_LOG("COUNTER 1 TARGET 32bit write %x\n", value);
836 #endif
837                         psxRcntWtarget(1, value & 0xffff); return;
838
839                 case 0x1f801120:
840 #ifdef PSXHW_LOG
841                         PSXHW_LOG("COUNTER 2 COUNT 32bit write %x\n", value);
842 #endif
843                         psxRcntWcount(2, value & 0xffff); return;
844                 case 0x1f801124:
845 #ifdef PSXHW_LOG
846                         PSXHW_LOG("COUNTER 2 MODE 32bit write %x\n", value);
847 #endif
848                         psxRcntWmode(2, value); return;
849                 case 0x1f801128:
850 #ifdef PSXHW_LOG
851                         PSXHW_LOG("COUNTER 2 TARGET 32bit write %x\n", value);
852 #endif
853                         psxRcntWtarget(2, value & 0xffff); return;
854
855                 case 0x1f801044:
856                 case 0x1f801048:
857                 case 0x1f80104c:
858                 case 0x1f801050:
859                 case 0x1f801054:
860                 case 0x1f801058:
861                 case 0x1f80105c:
862                 case 0x1f801800:
863                         log_unhandled("unhandled w32 %08x @%08x\n", add, psxRegs.pc);
864                         // falthrough
865                 default:
866                         // Dukes of Hazard 2 - car engine noise
867                         if (0x1f801c00 <= add && add < 0x1f802000) {
868                                 SPU_writeRegister(add, value&0xffff, psxRegs.cycle);
869                                 SPU_writeRegister(add + 2, value>>16, psxRegs.cycle);
870                                 return;
871                         }
872
873                         psxHu32ref(add) = SWAPu32(value);
874 #ifdef PSXHW_LOG
875                         PSXHW_LOG("*Unknown 32bit write at address %x value %x\n", add, value);
876 #endif
877                         return;
878         }
879         psxHu32ref(add) = SWAPu32(value);
880 #ifdef PSXHW_LOG
881         PSXHW_LOG("*Known 32bit write at address %x value %x\n", add, value);
882 #endif
883 }
884
885 int psxHwFreeze(void *f, int Mode) {
886         return 0;
887 }