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