diff --git a/hw/xbox/nv2a/nv2a_pgraph.c b/hw/xbox/nv2a/nv2a_pgraph.c
index 5b40a03b15..2fd1d1f12f 100644
--- a/hw/xbox/nv2a/nv2a_pgraph.c
+++ b/hw/xbox/nv2a/nv2a_pgraph.c
@@ -299,6 +299,33 @@ static uint64_t fnv_hash(const uint8_t *data, size_t len);
 static uint64_t fast_hash(const uint8_t *data, size_t len, unsigned int samples);
 
 /* PGRAPH - accelerated 2d/3d drawing engine */
+
+static uint32_t pgraph_rdi_read(PGRAPHState *pg,
+                                unsigned int select, unsigned int address)
+{
+    uint32_t r = 0;
+    switch(select) {
+    default:
+        fprintf(stderr, "nv2a: unknown rdi read select 0x%x address 0x%x\n",
+                select, address);
+        assert(false);
+        break;
+    }
+    return r;
+}
+
+static void pgraph_rdi_write(PGRAPHState *pg,
+                             unsigned int select, unsigned int address,
+                             uint32_t val)
+{
+    switch(select) {
+    default:
+        NV2A_DPRINTF("unknown rdi write select 0x%x, address 0x%x, val 0x%08x\n",
+                     select, address, val);
+        break;
+    }
+}
+
 uint64_t pgraph_read(void *opaque, hwaddr addr, unsigned int size)
 {
     NV2AState *d = (NV2AState *)opaque;
@@ -314,6 +341,21 @@ uint64_t pgraph_read(void *opaque, hwaddr addr, unsigned int size)
     case NV_PGRAPH_INTR_EN:
         r = pg->enabled_interrupts;
         break;
+    case NV_PGRAPH_RDI_DATA: {
+        unsigned int select = GET_MASK(pg->regs[NV_PGRAPH_RDI_INDEX],
+                                       NV_PGRAPH_RDI_INDEX_SELECT);
+        unsigned int address = GET_MASK(pg->regs[NV_PGRAPH_RDI_INDEX],
+                                        NV_PGRAPH_RDI_INDEX_ADDRESS);
+
+        r = pgraph_rdi_read(pg, select, address);
+
+        /* FIXME: Overflow into select? */
+        assert(address < GET_MASK(NV_PGRAPH_RDI_INDEX_ADDRESS,
+                                  NV_PGRAPH_RDI_INDEX_ADDRESS));
+        SET_MASK(pg->regs[NV_PGRAPH_RDI_INDEX],
+                 NV_PGRAPH_RDI_INDEX_ADDRESS, address + 1);
+        break;
+    }
     default:
         r = pg->regs[addr];
         break;
@@ -353,6 +395,21 @@ void pgraph_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
             qemu_cond_broadcast(&pg->flip_3d);
         }
         break;
+    case NV_PGRAPH_RDI_DATA: {
+        unsigned int select = GET_MASK(pg->regs[NV_PGRAPH_RDI_INDEX],
+                                       NV_PGRAPH_RDI_INDEX_SELECT);
+        unsigned int address = GET_MASK(pg->regs[NV_PGRAPH_RDI_INDEX],
+                                        NV_PGRAPH_RDI_INDEX_ADDRESS);
+
+        pgraph_rdi_write(pg, select, address, val);
+
+        /* FIXME: Overflow into select? */
+        assert(address < GET_MASK(NV_PGRAPH_RDI_INDEX_ADDRESS,
+                                  NV_PGRAPH_RDI_INDEX_ADDRESS));
+        SET_MASK(pg->regs[NV_PGRAPH_RDI_INDEX],
+                 NV_PGRAPH_RDI_INDEX_ADDRESS, address + 1);
+        break;
+    }
     case NV_PGRAPH_CHANNEL_CTX_TRIGGER: {
         hwaddr context_address =
             GET_MASK(pg->regs[NV_PGRAPH_CHANNEL_CTX_POINTER],
diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h
index e13052fc1e..ac1561dbb8 100644
--- a/hw/xbox/nv2a/nv2a_regs.h
+++ b/hw/xbox/nv2a/nv2a_regs.h
@@ -256,6 +256,10 @@
 #   define NV_PGRAPH_INCREMENT_READ_3D                          (1 << 1)
 #define NV_PGRAPH_FIFO                                   0x00000720
 #   define NV_PGRAPH_FIFO_ACCESS                                (1 << 0)
+#define NV_PGRAPH_RDI_INDEX                              0x00000750
+#   define NV_PGRAPH_RDI_INDEX_ADDRESS                        0x00001FFC
+#   define NV_PGRAPH_RDI_INDEX_SELECT                         0x01FF0000
+#define NV_PGRAPH_RDI_DATA                               0x00000754
 #define NV_PGRAPH_CHANNEL_CTX_TABLE                      0x00000780
 #   define NV_PGRAPH_CHANNEL_CTX_TABLE_INST                   0x0000FFFF
 #define NV_PGRAPH_CHANNEL_CTX_POINTER                    0x00000784