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