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