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