ref: b81987ecacac88d3cfeea1f094be08b3fec2b068
parent: 2e6491c20b71356eb4450b1180a6a11fb1df13bb
author: allkern <lisandroaalarcon@gmail.com>
date: Mon Jul 24 12:37:04 EDT 2023
Several improvements
--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -306,8 +306,58 @@
}
void cdrom_cmd_getlocl(psx_cdrom_t* cdrom) { log_fatal("getlocl: Unimplemented"); exit(1); } void cdrom_cmd_getlocp(psx_cdrom_t* cdrom) { log_fatal("getlocp: Unimplemented"); exit(1); }-void cdrom_cmd_gettn(psx_cdrom_t* cdrom) { log_fatal("gettn: Unimplemented"); exit(1); }-void cdrom_cmd_gettd(psx_cdrom_t* cdrom) { log_fatal("gettd: Unimplemented"); exit(1); }+void cdrom_cmd_gettn(psx_cdrom_t* cdrom) {+ switch (cdrom->state) {+ case CD_STATE_CMD: {+ if (cdrom->pfifo_index) {+ log_fatal("CdlGetTN: Expected exactly 0 parameters");+
+ return;
+ }
+
+ cdrom->irq_delay = DELAY_1MS;
+ cdrom->delayed_command = CDL_GETTN;
+ cdrom->state = CD_STATE_RESP1;
+ } break;
+
+ case CD_STATE_RESP1: {+ SET_BITS(ifr, IFR_INT, IFR_INT3);
+ RESP_PUSH(0x14);
+ RESP_PUSH(0x01);
+ RESP_PUSH(cdrom->stat);
+
+ cdrom->delayed_command = CDL_NONE;
+ cdrom->state = CD_STATE_CMD;
+ } break;
+ }
+}
+void cdrom_cmd_gettd(psx_cdrom_t* cdrom) {+ switch (cdrom->state) {+ case CD_STATE_CMD: {+ if (cdrom->pfifo_index != 1) {+ log_fatal("CdlGetTD: Expected exactly 0 parameters");+
+ return;
+ }
+
+ int track = PFIFO_POP;
+
+ cdrom->irq_delay = DELAY_1MS;
+ cdrom->delayed_command = CDL_GETTD;
+ cdrom->state = CD_STATE_RESP1;
+ } break;
+
+ case CD_STATE_RESP1: {+ SET_BITS(ifr, IFR_INT, IFR_INT3);
+ RESP_PUSH(0x14);
+ RESP_PUSH(0x01);
+ RESP_PUSH(cdrom->stat);
+
+ cdrom->delayed_command = CDL_NONE;
+ cdrom->state = CD_STATE_CMD;
+ } break;
+ }
+}
void cdrom_cmd_seekl(psx_cdrom_t* cdrom) { switch (cdrom->state) { case CD_STATE_CMD: {@@ -427,7 +477,58 @@
} break;
}
}
-void cdrom_cmd_reads(psx_cdrom_t* cdrom) { log_fatal("reads: Unimplemented"); exit(1); }+void cdrom_cmd_reads(psx_cdrom_t* cdrom) {+ switch (cdrom->state) {+ case CD_STATE_CMD: {+ log_fatal("CdlReadS: CD_STATE_CMD");+ cdrom->irq_delay = DELAY_1MS;
+ cdrom->state = CD_STATE_RESP1;
+ cdrom->delayed_command = CDL_READS;
+ } break;
+
+ case CD_STATE_RESP1: {+ log_fatal("CdlReadS: CD_STATE_RESP1");+
+ SET_BITS(ifr, IFR_INT, 3);
+ RESP_PUSH(GETSTAT_MOTOR);
+
+ fseek(cdrom->disc, cdrom->seek_offset, 0);
+
+ int double_speed = cdrom->mode & MODE_SPEED;
+
+ cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY;
+ cdrom->state = CD_STATE_RESP2;
+ cdrom->delayed_command = CDL_READS;
+
+ if (cdrom->spin_delay) {+ cdrom->irq_delay += cdrom->spin_delay;
+ cdrom->spin_delay = 0;
+ }
+ } break;
+
+ case CD_STATE_RESP2: {+ log_fatal("CdlReadS: CD_STATE_RESP2");+
+ SET_BITS(ifr, IFR_INT, 1);
+ RESP_PUSH(GETSTAT_MOTOR | GETSTAT_READ);
+
+ log_fatal("Reading data from disc. offset=%02x:%02x:%02x (%08x, tellg=%08x)",+ cdrom->seek_mm, cdrom->seek_ss, cdrom->seek_sect,
+ cdrom->seek_offset, ftell(cdrom->disc)
+ );
+
+ cdrom->dfifo_index = 0;
+
+ fread(cdrom->dfifo, 1, CD_SECTOR_SIZE, cdrom->disc);
+
+ int double_speed = cdrom->mode & MODE_SPEED;
+
+ cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY;
+ cdrom->state = CD_STATE_CMD;
+ cdrom->delayed_command = CDL_NONE;
+ } break;
+ }
+}
void cdrom_cmd_readtoc(psx_cdrom_t* cdrom) { log_fatal("readtoc: Unimplemented"); exit(1); }typedef void (*cdrom_cmd_t)(psx_cdrom_t*);
--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -106,8 +106,11 @@
dma->dicr &= ~(value & DICR_FLAGS);
// Write other fields
- dma->dicr &= DICR_FLAGS;
+ uint32_t flags = dma->dicr & DICR_FLAGS;
+
+ dma->dicr &= ~DICR_FLAGS;
dma->dicr |= value & (~DICR_FLAGS);
+ dma->dicr |= flags;
} break;
default: {@@ -122,7 +125,7 @@
default: { log_fatal("Unhandled 16-bit DMA write at offset %08x (%04x)", offset, value);- exit(1);
+ //exit(1);
} break;
}
}
@@ -132,7 +135,7 @@
default: { log_fatal("Unhandled 8-bit DMA write at offset %08x (%02x)", offset, value);- exit(1);
+ //exit(1);
} break;
}
}
@@ -152,6 +155,8 @@
uint32_t size = hdr >> 24;
uint32_t addr = dma->gpu.madr;
+ int count = 0;
+
while (true) { while (size--) {addr = (addr + (CHCR_STEP(gpu) ? -4 : 4)) & 0x1ffffc;
@@ -161,6 +166,8 @@
// Write to GP0
psx_bus_write32(dma->bus, 0x1f801810, cmd);
+
+ dma->gpu_irq_delay++;
}
addr = hdr & 0xffffff;
@@ -195,6 +202,8 @@
dma->gpu.madr += CHCR_STEP(gpu) ? -4 : 4;
}
}
+
+ dma->gpu_irq_delay = size;
}
void psx_dma_do_gpu_burst(psx_dma_t* dma) {@@ -249,7 +258,7 @@
(dma->dicr >> 24) & 0x7f
);
- uint32_t size = BCR_SIZE(cdrom) * BCR_BCNT(cdrom);
+ uint32_t size = BCR_SIZE(cdrom);
if (!size) { log_fatal("0 sized CDROM DMA");@@ -310,23 +319,6 @@
}
dma->spu_irq_delay = size * 4;
-
- if (!CHCR_TDIR(spu)) {- for (int i = 0; i < size; i++) {- uint32_t data = 0;
-
- data |= psx_bus_read8(dma->bus, 0x1f801802) << 0;
- data |= psx_bus_read8(dma->bus, 0x1f801802) << 8;
- data |= psx_bus_read8(dma->bus, 0x1f801802) << 16;
- data |= psx_bus_read8(dma->bus, 0x1f801802) << 24;
-
- psx_bus_write32(dma->bus, dma->spu.madr, data);
-
- dma->spu.madr += CHCR_STEP(spu) ? -4 : 4;
- }
- } else {- log_fatal("Invalid SPU DMA transfer direction");- }
// Clear BCR and CHCR trigger and busy bits
dma->spu.chcr = 0;
@@ -358,6 +350,8 @@
dma->otc.madr -= 4;
}
+ dma->otc_irq_delay = BCR_SIZE(otc);
+
// Clear BCR and CHCR trigger and busy bits
dma->otc.chcr = 0;
//dma->otc.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK);
@@ -366,25 +360,31 @@
void psx_dma_update(psx_dma_t* dma, int cyc) { if (dma->cdrom_irq_delay) {- dma->cdrom_irq_delay -= cyc;
+ if (dma->dicr & DICR_DMA3EN)
+ dma->dicr |= DICR_DMA3FL;
- if (dma->cdrom_irq_delay <= 0) {- if (dma->dicr & DICR_DMA3EN)
- dma->dicr |= DICR_DMA3FL;
-
- dma->cdrom_irq_delay = 0;
- }
+ dma->cdrom_irq_delay = 0;
}
if (dma->spu_irq_delay) {- dma->spu_irq_delay -= cyc;
+ if (dma->dicr & DICR_DMA4EN)
+ dma->dicr |= DICR_DMA4FL;
+
+ dma->spu_irq_delay = 0;
+ }
- if (dma->spu_irq_delay <= 0) {- if (dma->dicr & DICR_DMA4EN)
- dma->dicr |= DICR_DMA4FL;
+ if (dma->gpu_irq_delay) {+ if (dma->dicr & DICR_DMA2EN)
+ dma->dicr |= DICR_DMA2FL;
- dma->spu_irq_delay = 0;
- }
+ dma->gpu_irq_delay = 0;
+ }
+
+ if (dma->otc_irq_delay) {+ if (dma->dicr & DICR_DMA6EN)
+ dma->dicr |= DICR_DMA6FL;
+
+ dma->otc_irq_delay = 0;
}
int prev_irq_signal = (dma->dicr & DICR_IRQSI) != 0;
--- a/psx/dev/dma.h
+++ b/psx/dev/dma.h
@@ -32,6 +32,8 @@
int cdrom_irq_delay;
int spu_irq_delay;
+ int gpu_irq_delay;
+ int otc_irq_delay;
uint32_t dpcr;
uint32_t dicr;
--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -62,6 +62,25 @@
gpu->c0_tsiz -= 2;
}
+ if (gpu->gp1_10h_req) {+ switch (gpu->gp1_10h_req & 7) {+ case 2: {+ data = ((gpu->texw_oy / 8) << 15) | ((gpu->texw_ox / 8) << 10) | ((gpu->texw_my / 8) << 5) | (gpu->texw_mx / 8);
+ } break;
+ case 3: {+ data = (gpu->draw_y1 << 10) | gpu->draw_x1;
+ } break;
+ case 4: {+ data = (gpu->draw_y2 << 10) | gpu->draw_x2;
+ } break;
+ case 5: {+ data = (gpu->off_y << 10) | gpu->off_x;
+ } break;
+ }
+
+ gpu->gp1_10h_req = 0;
+ }
+
return data;
} break;
case 0x04: return gpu->gpustat | 0x1c000000;
@@ -73,23 +92,15 @@
}
uint16_t psx_gpu_read16(psx_gpu_t* gpu, uint32_t offset) {- switch (offset) {- case 0x00: return 0xaaaa;
- case 0x04: return gpu->gpustat;
- }
+ log_fatal("Unhandled 16-bit GPU read at offset %08x", offset);- log_warn("Unhandled 16-bit GPU read at offset %08x", offset);-
- return 0x0;
+ exit(1);
}
uint8_t psx_gpu_read8(psx_gpu_t* gpu, uint32_t offset) {- switch (offset) {- case 0x00: return gpu->gpuread;
- case 0x04: return gpu->gpustat;
- }
+ log_fatal("Unhandled 8-bit GPU read at offset %08x", offset);- log_warn("Unhandled 8-bit GPU read at offset %08x", offset);+ exit(1);
return 0x0;
}
@@ -445,6 +456,21 @@
gpu->ysiz = ((gpu->ysiz - 1) & 0x1ff) + 1;
gpu->tsiz = ((gpu->xsiz * gpu->ysiz) + 1) & 0xfffffffe;
gpu->addr = gpu->xpos + (gpu->ypos * 1024);
+
+ //log_set_quiet(0);
+
+ log_fatal("pos=(%u, %u), siz=(%u, %u), tsiz=%08x, addr=%08x",+ gpu->xpos, gpu->ypos,
+ gpu->xsiz, gpu->ysiz,
+ gpu->tsiz, gpu->addr
+ );
+
+ // system("pause > nul");+
+ // if (gpu->event_cb_table[GPU_EVENT_VBLANK])
+ // gpu->event_cb_table[GPU_EVENT_VBLANK](gpu);
+
+ //log_set_quiet(1);
}
} break;
@@ -815,6 +841,36 @@
}
}
+void gpu_cmd_80(psx_gpu_t* gpu) {+ switch (gpu->state) {+ case GPU_STATE_RECV_CMD: {+ gpu->state = GPU_STATE_RECV_ARGS;
+ gpu->cmd_args_remaining = 3;
+ } break;
+
+ case GPU_STATE_RECV_ARGS: {+ if (!gpu->cmd_args_remaining) {+ gpu->state = GPU_STATE_RECV_DATA;
+
+ uint32_t srcx = gpu->buf[1] & 0xffff;
+ uint32_t srcy = gpu->buf[1] >> 16;
+ uint32_t dstx = gpu->buf[2] & 0xffff;
+ uint32_t dsty = gpu->buf[2] >> 16;
+ uint32_t xsiz = gpu->buf[3] & 0xffff;
+ uint32_t ysiz = gpu->buf[3] >> 16;
+
+ for (int y = 0; y < ysiz; y++) {+ for (int x = 0; x < xsiz; x++) {+ gpu->vram[(dstx + x) + (dsty + y) * 1024] = gpu->vram[(srcx + x) + (srcy + y) * 1024];
+ }
+ }
+
+ gpu->state = GPU_STATE_RECV_CMD;
+ }
+ } break;
+ }
+}
+
void psx_gpu_update_cmd(psx_gpu_t* gpu) { switch (gpu->buf[0] >> 24) {case 0x00: /* nop */ break;
@@ -833,6 +889,7 @@
case 0x65: gpu_cmd_64(gpu); break;
case 0x66: gpu_cmd_64(gpu); break;
case 0x68: gpu_cmd_68(gpu); break;
+ case 0x80: gpu_cmd_80(gpu); break;
case 0xa0: gpu_cmd_a0(gpu); break;
case 0xc0: gpu_cmd_c0(gpu); break;
case 0xe1: {@@ -901,6 +958,11 @@
uint8_t cmd = value >> 24;
switch (cmd) {+ case 0x04: {+ // log_set_quiet(0);
+ // log_fatal("GP1(04h) !!!!!!!!!!!!!!!!!");+ // log_set_quiet(1);
+ } break;
case 0x08:
gpu->display_mode = value & 0xffffff;
@@ -908,23 +970,13 @@
gpu->event_cb_table[GPU_EVENT_DMODE](gpu);
break;
- case 0x10:
- switch (value & 7) {- case 2:
- gpu->gpuread = ((gpu->texw_oy / 8) << 15) | ((gpu->texw_ox / 8) << 10) | ((gpu->texw_my / 8) << 5) | (gpu->texw_mx / 8);
- break;
- case 3:
- gpu->gpuread = (gpu->draw_y1 << 10) | gpu->draw_x1;
- break;
- case 4:
- gpu->gpuread = (gpu->draw_y2 << 10) | gpu->draw_x2;
- break;
- case 5: // Drawing Offset
- gpu->gpuread = (gpu->off_y << 10) | gpu->off_x;
- break;
- default:
- break;
- }
+ case 0x10: {+ gpu->gp1_10h_req = value & 7;
+
+ // log_set_quiet(0);
+ // log_fatal("GP1(10h) %u !!!!!!!!!!!!!!!!!", value & 7);+ // log_set_quiet(1);
+ } break;
}
log_error("GP1(%02Xh) args=%06x", value >> 24, value & 0xffffff);--- a/psx/dev/gpu.h
+++ b/psx/dev/gpu.h
@@ -78,6 +78,7 @@
uint32_t c0_addr;
int c0_xsiz, c0_ysiz;
int c0_tsiz;
+ int gp1_10h_req;
// GPU state
uint32_t state;
--- a/psx/input/sda.c
+++ b/psx/input/sda.c
@@ -39,6 +39,13 @@
sda->tx_data = 0xff;
sda->state = SDA_STATE_WFR;
}
+
+ // Memory card access
+ if (data == 0x81) {+ sda->tx_data_ready = 1;
+ sda->tx_data = 0xff;
+ sda->state = SDA_STATE_WFR;
+ }
} break;
case SDA_STATE_WFR: {@@ -45,6 +52,9 @@
if (data == 'B') {sda->tx_data = sda->model;
sda->state = SDA_STATE_TX_IDH;
+ } else if (data == 'R') {+ sda->tx_data = 0xff;
+ sda->state = SDA_STATE_WFR;
}
} break;
--
⑨