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