shithub: psxe

Download patch

ref: 2c93171f461b593b81e161eb6208689337a1e8be
parent: 478a6bd0cd359b42614c125b9d1c8f275e551715
author: allkern <lisandroaalarcon@gmail.com>
date: Sun Aug 6 10:00:03 EDT 2023

Implement `mdec_in`

Stub quant and scale table recv

--- a/psx/bus.c
+++ b/psx/bus.c
@@ -267,7 +267,7 @@
     bus->pad = pad;
 }
 
-void psx_bus_init_pad(psx_bus_t* bus, psx_mdec_t* mdec) {
+void psx_bus_init_mdec(psx_bus_t* bus, psx_mdec_t* mdec) {
     bus->mdec = mdec;
 }
 
--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -147,9 +147,29 @@
     "reserved"
 };
 
-void psx_dma_do_mdec_in(psx_dma_t* dma) { log_error("MDEC_IN DMA channel unimplemented"); }
-void psx_dma_do_mdec_out(psx_dma_t* dma) { log_error("MDEC_OUT DMA channel unimplemented"); }
+void psx_dma_do_mdec_in(psx_dma_t* dma) {
+    if (!CHCR_BUSY(mdec_in))
+        return;
 
+    for (int i = 0; i < BCR_SIZE(mdec_in); i++) {
+        uint32_t data = psx_bus_read32(dma->bus, dma->gpu.madr);
+
+        psx_bus_write32(dma->bus, 0x1f801820, data);
+
+        dma->gpu.madr += CHCR_STEP(mdec_in) ? -4 : 4;
+    }
+
+    dma->mdec_in.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK);
+    dma->mdec_in.bcr = 0;
+}
+
+void psx_dma_do_mdec_out(psx_dma_t* dma) {
+    if (!CHCR_BUSY(mdec_out))
+        return;
+
+    log_fatal("MDEC_OUT DMA channel unimplemented");
+}
+
 void psx_dma_do_gpu_linked(psx_dma_t* dma) {
     uint32_t hdr = psx_bus_read32(dma->bus, dma->gpu.madr);
     uint32_t size = hdr >> 24;
@@ -224,13 +244,13 @@
     if (!CHCR_BUSY(gpu))
         return;
 
-    log_error("GPU DMA transfer: madr=%08x, dir=%s, sync=%s (%u), step=%s, size=%x",
-        dma->gpu.madr,
-        CHCR_TDIR(gpu) ? "to device" : "to RAM",
-        g_psx_dma_sync_type_name_table[CHCR_SYNC(gpu)], CHCR_SYNC(gpu),
-        CHCR_STEP(gpu) ? "decrementing" : "incrementing",
-        BCR_SIZE(gpu)
-    );
+    // log_error("GPU DMA transfer: madr=%08x, dir=%s, sync=%s (%u), step=%s, size=%x",
+    //     dma->gpu.madr,
+    //     CHCR_TDIR(gpu) ? "to device" : "to RAM",
+    //     g_psx_dma_sync_type_name_table[CHCR_SYNC(gpu)], CHCR_SYNC(gpu),
+    //     CHCR_STEP(gpu) ? "decrementing" : "incrementing",
+    //     BCR_SIZE(gpu)
+    // );
 
     g_psx_dma_gpu_table[CHCR_SYNC(gpu)](dma);
 
@@ -243,20 +263,20 @@
     if (!CHCR_BUSY(cdrom))
         return;
     
-    log_fatal("CDROM DMA transfer: madr=%08x, dir=%s, sync=%s (%u), step=%s, size=%x",
-        dma->cdrom.madr,
-        CHCR_TDIR(cdrom) ? "to device" : "to RAM",
-        g_psx_dma_sync_type_name_table[CHCR_SYNC(cdrom)], CHCR_SYNC(cdrom),
-        CHCR_STEP(cdrom) ? "decrementing" : "incrementing",
-        BCR_SIZE(cdrom)
-    );
+    // log_fatal("CDROM DMA transfer: madr=%08x, dir=%s, sync=%s (%u), step=%s, size=%x",
+    //     dma->cdrom.madr,
+    //     CHCR_TDIR(cdrom) ? "to device" : "to RAM",
+    //     g_psx_dma_sync_type_name_table[CHCR_SYNC(cdrom)], CHCR_SYNC(cdrom),
+    //     CHCR_STEP(cdrom) ? "decrementing" : "incrementing",
+    //     BCR_SIZE(cdrom)
+    // );
 
-    log_fatal("DICR: force=%u, en=%02x, irqen=%u, flags=%02x",
-        (dma->dicr >> 15) & 1,
-        (dma->dicr >> 16) & 0x7f,
-        (dma->dicr >> 23) & 1,
-        (dma->dicr >> 24) & 0x7f
-    );
+    // log_fatal("DICR: force=%u, en=%02x, irqen=%u, flags=%02x",
+    //     (dma->dicr >> 15) & 1,
+    //     (dma->dicr >> 16) & 0x7f,
+    //     (dma->dicr >> 23) & 1,
+    //     (dma->dicr >> 24) & 0x7f
+    // );
 
     uint32_t size = BCR_SIZE(cdrom);
 
@@ -295,20 +315,20 @@
     if (!CHCR_BUSY(spu))
         return;
     
-    log_fatal("SPU DMA transfer: madr=%08x, dir=%s, sync=%s (%u), step=%s, size=%x",
-        dma->spu.madr,
-        CHCR_TDIR(spu) ? "to device" : "to RAM",
-        g_psx_dma_sync_type_name_table[CHCR_SYNC(spu)], CHCR_SYNC(spu),
-        CHCR_STEP(spu) ? "decrementing" : "incrementing",
-        BCR_SIZE(spu)
-    );
+    // log_fatal("SPU DMA transfer: madr=%08x, dir=%s, sync=%s (%u), step=%s, size=%x",
+    //     dma->spu.madr,
+    //     CHCR_TDIR(spu) ? "to device" : "to RAM",
+    //     g_psx_dma_sync_type_name_table[CHCR_SYNC(spu)], CHCR_SYNC(spu),
+    //     CHCR_STEP(spu) ? "decrementing" : "incrementing",
+    //     BCR_SIZE(spu)
+    // );
 
-    log_fatal("DICR: force=%u, en=%02x, irqen=%u, flags=%02x",
-        (dma->dicr >> 15) & 1,
-        (dma->dicr >> 16) & 0x7f,
-        (dma->dicr >> 23) & 1,
-        (dma->dicr >> 24) & 0x7f
-    );
+    // log_fatal("DICR: force=%u, en=%02x, irqen=%u, flags=%02x",
+    //     (dma->dicr >> 15) & 1,
+    //     (dma->dicr >> 16) & 0x7f,
+    //     (dma->dicr >> 23) & 1,
+    //     (dma->dicr >> 24) & 0x7f
+    // );
 
     uint32_t size = BCR_SIZE(spu) * BCR_BCNT(spu);
 
@@ -334,13 +354,13 @@
     if (!CHCR_TRIG(otc))
         return;
 
-    log_error("OTC DMA transfer: madr=%08x, dir=%s, sync=%s, step=%s, size=%x",
-        dma->otc.madr,
-        CHCR_TDIR(otc) ? "to device" : "to RAM",
-        CHCR_SYNC(otc) ? "other" : "burst",
-        CHCR_STEP(otc) ? "decrementing" : "incrementing",
-        BCR_SIZE(otc)
-    );
+    // log_error("OTC DMA transfer: madr=%08x, dir=%s, sync=%s, step=%s, size=%x",
+    //     dma->otc.madr,
+    //     CHCR_TDIR(otc) ? "to device" : "to RAM",
+    //     CHCR_SYNC(otc) ? "other" : "burst",
+    //     CHCR_STEP(otc) ? "decrementing" : "incrementing",
+    //     BCR_SIZE(otc)
+    // );
 
     for (int i = BCR_SIZE(otc); i > 0; i--) {
         uint32_t addr = (i != 1) ? (dma->otc.madr - 4) : 0xffffff;
--- a/psx/dev/mdec.c
+++ b/psx/dev/mdec.c
@@ -5,6 +5,68 @@
 #include <string.h>
 #include <stdlib.h>
 
+void mdec_nop(psx_mdec_t* mdec) { /* Do nothing */ }
+
+void mdec_decode_macroblock(psx_mdec_t* mdec) {
+    // To-do
+}
+
+void mdec_set_iqtab(psx_mdec_t* mdec) {
+    mdec->state = mdec->cmd & 1 ? MDEC_RECV_QUANT_COLOR : MDEC_RECV_QUANT;
+    mdec->data_remaining = mdec->cmd & 1 ? 32 : 16;
+    mdec->index = 0;
+}
+
+void mdec_set_scale(psx_mdec_t* mdec) {
+    mdec->state = MDEC_RECV_SCALE;
+    mdec->data_remaining = 32;
+    mdec->index = 0;
+}
+
+mdec_fn_t g_mdec_cmd_table[] = {
+    mdec_nop,
+    mdec_decode_macroblock,
+    mdec_set_iqtab,
+    mdec_set_scale,
+    mdec_nop,
+    mdec_nop,
+    mdec_nop,
+    mdec_nop
+};
+
+void mdec_recv_cmd(psx_mdec_t* mdec) {
+    log_fatal("MDEC command %u (%08x)", mdec->cmd >> 29, mdec->cmd);
+
+    g_mdec_cmd_table[mdec->cmd >> 29](mdec);
+}
+void mdec_recv_block(psx_mdec_t* mdec) {}
+void mdec_recv_quant(psx_mdec_t* mdec) {
+    mdec->data_remaining--;
+
+    if (!mdec->data_remaining)
+        mdec->state = MDEC_RECV_CMD;
+}
+void mdec_recv_quant_color(psx_mdec_t* mdec) {
+    mdec->data_remaining--;
+
+    if (!mdec->data_remaining)
+        mdec->state = MDEC_RECV_CMD;
+}
+void mdec_recv_scale(psx_mdec_t* mdec) {
+    mdec->data_remaining--;
+
+    if (!mdec->data_remaining)
+        mdec->state = MDEC_RECV_CMD;
+}
+
+mdec_fn_t g_mdec_recv_table[] = {
+    mdec_recv_cmd,
+    mdec_recv_block,
+    mdec_recv_quant,
+    mdec_recv_quant_color,
+    mdec_recv_scale
+};
+
 psx_mdec_t* psx_mdec_create() {
     return (psx_mdec_t*)malloc(sizeof(psx_mdec_t));
 }
@@ -14,10 +76,17 @@
 
     mdec->io_base = PSX_MDEC_BEGIN;
     mdec->io_size = PSX_MDEC_SIZE;
+
+    mdec->state = MDEC_RECV_CMD;
 }
 
 uint32_t psx_mdec_read32(psx_mdec_t* mdec, uint32_t offset) {
-    log_fatal("32-bit MDEC read offset=%u", offset);
+    switch (offset) {
+        case 0: {
+
+        } break;
+        case 4: return mdec->status;
+    }
 }
 
 uint16_t psx_mdec_read16(psx_mdec_t* mdec, uint32_t offset) {
@@ -33,6 +102,22 @@
 }
 
 void psx_mdec_write32(psx_mdec_t* mdec, uint32_t offset, uint32_t value) {
+    switch (offset) {
+        case 0: {
+            mdec->cmd = value;
+
+            g_mdec_recv_table[mdec->state](mdec);
+        } break;
+
+        case 4: {
+            if (value & 0x80000000)
+                mdec->status = 0x80040000;
+
+            mdec->status &= 0xe7ffffff;
+            mdec->status |= (value & 0x60000000) >> 2;
+        } break;
+    }
+
     log_fatal("32-bit MDEC write offset=%u, value=%08x", offset, value);
 }
 
--- a/psx/dev/mdec.h
+++ b/psx/dev/mdec.h
@@ -9,8 +9,24 @@
 #define PSX_MDEC_BEGIN   0x1f801820
 #define PSX_MDEC_END     0x1f801827
 
+enum {
+    MDEC_RECV_CMD,
+    MDEC_RECV_BLOCK,
+    MDEC_RECV_QUANT,
+    MDEC_RECV_QUANT_COLOR,
+    MDEC_RECV_SCALE
+};
+
 typedef struct {
     uint32_t io_base, io_size;
+
+    uint32_t cmd;
+
+    int state;
+    int data_remaining;
+    int index;
+
+    uint32_t status;
 } psx_mdec_t;
 
 psx_mdec_t* psx_mdec_create();
@@ -22,5 +38,7 @@
 void psx_mdec_write16(psx_mdec_t*, uint32_t, uint16_t);
 void psx_mdec_write8(psx_mdec_t*, uint32_t, uint8_t);
 void psx_mdec_destroy(psx_mdec_t*);
+
+typedef void (*mdec_fn_t)(psx_mdec_t*);
 
 #endif
\ No newline at end of file
--