Skip to content

Commit 5c1439e

Browse files
committed
vif: Fix STAT and CODE reads after IRQs
Improves Gran Turismo 3/4 speed issues
1 parent 45426e1 commit 5c1439e

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

src/ee/vif.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#include "vif.h"
88

9-
// #define printf(fmt, ...)(0)
9+
#define printf(fmt, ...)(0)
1010

1111
struct ps2_vif* ps2_vif_create(void) {
1212
return malloc(sizeof(struct ps2_vif));
@@ -185,6 +185,18 @@ static inline void vif_handle_fifo_write(struct ps2_vif* vif, uint32_t data) {
185185
// printf("vif%d: FLUSHE\n", vif->id);
186186
} break;
187187
case VIF_CMD_FLUSH: {
188+
// Note: MASSIVE GRAN TURISMO HACK!
189+
// GT3/4 expect IBT and stall bits to be set when a
190+
// VIF IRQ occurs, CODE also needs to be set to the
191+
// last command that caused a stall.
192+
// This is admittedly a huge hack, but we can't really
193+
// emulate any of this without properly implementing
194+
// DMA timings.
195+
if (data & 0x80000000) {
196+
vif->stat |= 0x00000c02;
197+
vif->stat ^= 0x0f000000;
198+
vif->code = data;
199+
}
188200
// printf("vif%d: FLUSH\n", vif->id);
189201
} break;
190202
case VIF_CMD_FLUSHA: {
@@ -269,7 +281,7 @@ static inline void vif_handle_fifo_write(struct ps2_vif* vif, uint32_t data) {
269281
vif->shift = 0;
270282
} break;
271283
case VIF_CMD_DIRECT: {
272-
//printf("vif%d: DIRECT(%04x)\n", vif->id, data & 0xffff);
284+
// fprintf(stdout, "vif%d: DIRECT(%04x)\n", vif->id, data & 0xffff);
273285

274286
int imm = data & 0xffff;
275287

@@ -282,7 +294,7 @@ static inline void vif_handle_fifo_write(struct ps2_vif* vif, uint32_t data) {
282294
vif->shift = 0;
283295
} break;
284296
case VIF_CMD_DIRECTHL: {
285-
// printf("vif%d: DIRECTHL(%04x)\n", vif->id, data & 0xffff);
297+
// fprintf(stdout, "vif%d: DIRECTHL(%04x)\n", vif->id, data & 0xffff);
286298

287299
int imm = data & 0xffff;
288300

@@ -346,7 +358,7 @@ static inline void vif_handle_fifo_write(struct ps2_vif* vif, uint32_t data) {
346358
vif->shift = 0;
347359
vif->addr = addr;
348360

349-
// printf("vif%d: UNPACK %02x fmt=%02x flg=%d num=%02x addr=%08x tops=%08x usn=%d wr=%d mode=%d\n", vif->id, data >> 24, vif->unpack_fmt, flg, vif->unpack_num, addr, vif->tops, vif->unpack_usn, vif->pending_words, vif->mode);
361+
// fprintf(stdout, "vif%d: UNPACK %02x fmt=%02x flg=%d num=%02x addr=%08x tops=%08x usn=%d wr=%d mode=%d\n", vif->id, data >> 24, vif->unpack_fmt, flg, vif->unpack_num, addr, vif->tops, vif->unpack_usn, vif->pending_words, vif->mode);
350362
} break;
351363
default: {
352364
// printf("vif%d: Unhandled command %02x\n", vif->id, vif->cmd);
@@ -375,12 +387,13 @@ static inline void vif_handle_fifo_write(struct ps2_vif* vif, uint32_t data) {
375387
}
376388
} break;
377389
case VIF_CMD_MPG: {
378-
// printf("vif%d: Writing %08x to MicroMem\n", vif->id, data);
379-
380390
if (!vif->shift) {
381391
vif->data.u32[vif->shift++] = data;
382392
} else {
383393
vif->data.u32[1] = data;
394+
395+
// fprintf(stdout, "vif%d: Writing %08x %08x to MicroMem addr=%04x\n", vif->id, vif->data.u32[0], vif->data.u32[1], vif->addr);
396+
384397
vif->vu->micro_mem[(vif->addr++) & 0x7ff] = vif->data.u64[0];
385398
vif->shift = 0;
386399
}
@@ -393,13 +406,18 @@ static inline void vif_handle_fifo_write(struct ps2_vif* vif, uint32_t data) {
393406
case VIF_CMD_DIRECT: {
394407
vif->data.u32[vif->shift++] = data;
395408

409+
vif->pending_words--;
410+
396411
if (vif->shift == 4) {
412+
// fprintf(stdout, "vif%d: Writing %08x %08x %08x %08x to GIF FIFO pending=%d\n", vif->id, vif->data.u32[3], vif->data.u32[2], vif->data.u32[1], vif->data.u32[0], vif->pending_words);
397413
ee_bus_write128(vif->bus, 0x10006000, vif->data);
398414

399415
vif->shift = 0;
400416
}
401417

402-
if (!(--vif->pending_words)) {
418+
if (!vif->pending_words) {
419+
// fprintf(stdout, "vif%d: DIRECT complete\n", vif->id);
420+
403421
vif->state = VIF_IDLE;
404422
}
405423
} break;
@@ -805,7 +823,11 @@ uint64_t ps2_vif_read32(struct ps2_vif* vif, uint32_t addr) {
805823
case 0x10003970: return vif->c[3];
806824

807825
// VIF1 registers
808-
case 0x10003c00: return vif->stat;
826+
case 0x10003c00: {
827+
uint32_t stat = vif->stat; vif->stat = 0;
828+
829+
return stat;
830+
} break;
809831
case 0x10003c10: return vif->fbrst;
810832
case 0x10003c20: return vif->err;
811833
case 0x10003c30: return vif->mark;
@@ -877,15 +899,15 @@ void ps2_vif_write32(struct ps2_vif* vif, uint32_t addr, uint64_t data) {
877899
default: {
878900
printf("vif%d: Unhandled 32-bit write to %08x\n", vif->id, addr);
879901

880-
exit(1);
902+
// exit(1);
881903
} break;
882904
}
883905
}
884906

885907
uint128_t ps2_vif_read128(struct ps2_vif* vif, uint32_t addr) {
886908
switch (addr) {
887-
case 0x10004000: // printf("vif%d: 128-bit FIFO read\n", vif->id); exit(1); break;
888-
case 0x10005000: // printf("vif%d: 128-bit FIFO read\n", vif->id); exit(1); break;
909+
case 0x10004000: break; // printf("vif%d: 128-bit FIFO read\n", vif->id); exit(1); break;
910+
case 0x10005000: break; // printf("vif%d: 128-bit FIFO read\n", vif->id); exit(1); break;
889911

890912
default: {
891913
printf("vif%d: Unhandled 128-bit read to %08x\n", vif->id, addr);

0 commit comments

Comments
 (0)