From 0aaa8d5d9196a57cf161a239a1c657b643216e4d Mon Sep 17 00:00:00 2001
From: TheSola10 <me@thesola.io>
Date: Fri, 4 Apr 2025 17:21:25 +0200
Subject: [PATCH] now catching disc change

---
 Makefile    |  2 +-
 exports.exp |  7 ++++-
 io_funcs.c  | 31 ++++++++++++++++----
 io_funcs.h  | 72 ++++++++++++++++++++++++++++++----------------
 main.c      | 83 ++++++++++++++++++++++++++++++++++-------------------
 rpatch.c    |  8 ++++++
 rpatch.h    |  3 ++
 7 files changed, 145 insertions(+), 61 deletions(-)

diff --git a/Makefile b/Makefile
index c7d8b47..89a151c 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ CFLAGS += -DDEBUG=$(DEBUG)
 endif
 
 LDFLAGS =  -nostartfiles -L .
-LIBS = -lpspsystemctrl_kernel
+LIBS = -lpspsystemctrl_kernel -lpspumd
 
 PSP_FW_VERSION = 660
 
diff --git a/exports.exp b/exports.exp
index 646ee62..08c2230 100644
--- a/exports.exp
+++ b/exports.exp
@@ -7,7 +7,7 @@ PSP_EXPORT_FUNC_HASH(module_stop)
 PSP_EXPORT_VAR_HASH(module_info)
 PSP_EXPORT_END
 
-# Voluntary collision with Inferno to prevent conflicts
+# Voluntary collision with Inferno to prevent loading
 PSP_EXPORT_START(inferno_driver, 0x0011, 0x0001)
 # inferno_driver_CF8299BE
 PSP_EXPORT_FUNC(infernoSetDiscType)
@@ -19,4 +19,9 @@ PSP_EXPORT_FUNC(infernoCacheInit)
 PSP_EXPORT_FUNC(infernoSetUmdDelay)
 PSP_EXPORT_END
 
+PSP_EXPORT_START(umd_livepatch, 0x0011, 0x0001)
+PSP_EXPORT_FUNC(lp_discChangeCallback)
+PSP_EXPORT_FUNC(lp_discChangeWatcher)
+PSP_EXPORT_END
+
 PSP_END_EXPORTS
diff --git a/io_funcs.c b/io_funcs.c
index 1374cd3..f1d0437 100644
--- a/io_funcs.c
+++ b/io_funcs.c
@@ -67,7 +67,7 @@ _impl_lp_readDiscHeader(PspIoDrvFileArg *arg, const char *devname)
         .byte_size_last = 0
     };
 
-    ret = reserveUmdFuncs.IoDevctl(arg, devname, lp_UmdIoctl_READ_SECTORS,
+    ret = reserveUmdFuncs.IoDevctl(arg, devname, lp_UmdDevctl_READ_SECTORS,
                                    &param, sizeof param, &hdr, ISO_SECTOR_SIZE);
     return ret;
 }
@@ -116,10 +116,10 @@ patched_IoDevctl(PspIoDrvFileArg *arg, const char *devname,
                  unsigned int cmd, void *indata, int inlen,
                  void *outdata, int outlen)
 {
-    switch ((lp_UmdIoctl) cmd) {
-    case lp_UmdIoctl_READ_GENERAL:
-    case lp_UmdIoctl_READ_CACHE:
-    case lp_UmdIoctl_READ_SECTORS:
+    switch ((lp_UmdDevctl) cmd) {
+    case lp_UmdDevctl_READ_GENERAL:
+    case lp_UmdDevctl_READ_CACHE:
+    case lp_UmdDevctl_READ_SECTORS:
         return _impl_lp_devctlRead(arg, devname, cmd, (lp_UmdLba *) indata,
                                    inlen, outdata, outlen);
     default:
@@ -130,4 +130,25 @@ passthru:
     return reserveUmdFuncs.IoDevctl(arg, devname, cmd, indata, inlen, outdata, outlen);
 }
 
+
+int
+patched_IoRead(PspIoDrvFileArg *arg, char *data, int len)
+{
+    Kprintf("Reading UMD data, hum dee dum...\n");
+    return reserveUmdFuncs.IoRead(arg, data, len);
+}
+
+int
+patched_IoOpen(PspIoDrvFileArg *arg, char *file, int flags, SceMode mode)
+{
+    Kprintf("Opening UMD.\n");
+    return reserveUmdFuncs.IoOpen(arg, file, flags, mode);
+}
+
+void
+lp_pingDiscRemoved(void)
+{
+    first_read = 1;
+}
+
 // vim: ft=c.doxygen
diff --git a/io_funcs.h b/io_funcs.h
index e1c20d2..d0845e1 100644
--- a/io_funcs.h
+++ b/io_funcs.h
@@ -28,32 +28,39 @@
  */
 
 typedef enum: int {
-    lp_UmdIoctl_01F00003  = 0x01F00003,
-    lp_UmdIoctl_01F010DB  = 0x01F010DB,
-
-    lp_UmdIoctl_DISC_TYPE = 0x01F20001,
-    lp_UmdIoctl_SEEK_RAW  = 0x01F100A3,
-    lp_UmdIoctl_CACHE_ADD  = 0x01F100A4,
-    lp_UmdIoctl_CACHE_ADD2 = 0x01F300A5,
-
-    /* Cache control, worth intercepting */
-    lp_UmdIoctl_01F300A7  = 0x01F300A7,
-    lp_UmdIoctl_01F300A8  = 0x01F300A8,
-    lp_UmdIoctl_01F300A9  = 0x01F300A9,
-    lp_UmdIoctl_NUM_SECTORS  = 0x01F20002,
-    lp_UmdIoctl_NUM_SECTORS2 = 0x01F20003,
-    lp_UmdIoctl_01E18030  = 0x01E18030,
-    lp_UmdIoctl_01E180D3  = 0x01E180D3,
-    lp_UmdIoctl_01E080A8  = 0x01E080A8,
-    lp_UmdIoctl_GET_SECTOR_BUF = 0x01E28035,
-    lp_UmdIoctl_GET_SECTOR_SIZE = 0x01E280A9,
-    lp_UmdIoctl_01E38034  = 0x01E38034,
-    lp_UmdIoctl_READ_GENERAL = 0x01E380C0,
-    lp_UmdIoctl_READ_SECTORS = 0x01F200A1,
-    lp_UmdIoctl_READ_CACHE   = 0x01F200A2,
-    lp_UmdIoctl_GET_INFO     = 0x01E38012
+    lp_UmdIoctl_01F010DB   = 0x01F010DB,
+    lp_UmdIoctl_GET_OFFSET = 0x01D20001,
+    lp_UmdIoctl_LSEEK      = 0x01F100A6,
+    lp_UmdIoctl_READ       = 0x01F30003
 } lp_UmdIoctl;
 
+typedef enum: int {
+    lp_UmdDevctl_01F00003  = 0x01F00003,
+    lp_UmdDevctl_01F010DB  = 0x01F010DB,
+
+    lp_UmdDevctl_DISC_TYPE = 0x01F20001,
+    lp_UmdDevctl_SEEK_RAW  = 0x01F100A3,
+    lp_UmdDevctl_CACHE_ADD  = 0x01F100A4,
+    lp_UmdDevctl_CACHE_ADD2 = 0x01F300A5,
+
+    /* CacDev control, worth intercepting */
+    lp_UmdDevctl_01F300A7  = 0x01F300A7,
+    lp_UmdDevctl_01F300A8  = 0x01F300A8,
+    lp_UmdDevctl_01F300A9  = 0x01F300A9,
+    lp_UmdDevctl_NUM_SECTORS  = 0x01F20002,
+    lp_UmdDevctl_NUM_SECTORS2 = 0x01F20003,
+    lp_UmdDevctl_01E18030  = 0x01E18030,
+    lp_UmdDevctl_01E180D3  = 0x01E180D3,
+    lp_UmdDevctl_01E080A8  = 0x01E080A8,
+    lp_UmdDevctl_GET_SECTOR_BUF = 0x01E28035,
+    lp_UmdDevctl_GET_SECTOR_SIZE = 0x01E280A9,
+    lp_UmdDevctl_01E38034  = 0x01E38034,
+    lp_UmdDevctl_READ_GENERAL = 0x01E380C0,
+    lp_UmdDevctl_READ_SECTORS = 0x01F200A1,
+    lp_UmdDevctl_READ_CACHE   = 0x01F200A2,
+    lp_UmdDevctl_GET_INFO     = 0x01E38012
+} lp_UmdDevctl;
+
 typedef struct {
     int unknown1; // 0
     int cmd; // 4
@@ -81,6 +88,23 @@ patched_IoDevctl(PspIoDrvFileArg *arg, const char *devname,
                  unsigned int cmd, void *indata, int inlen,
                  void *outdata, int outlen);
 
+int
+patched_IoRead(PspIoDrvFileArg *arg, char *data, int len);
+
+int
+patched_IoOpen(PspIoDrvFileArg *arg, char *file, int flags, SceMode mode);
+
+/**
+ * @brief      Tell this module to expect a new disc.
+ *
+ * This function resets the "first read" flag which prompts this module to read
+ * the UMD's disc ID.
+ * On its own, this function does not invalidate the cache. It will only be
+ * invalidated if the effective disc ID has changed on the next read devctl.
+ */
+void
+lp_pingDiscRemoved(void);
+
 #endif //__IO_FUNCS_H
 
 // vim: ft=c.doxygen
diff --git a/main.c b/main.c
index 573b5bf..1220144 100644
--- a/main.c
+++ b/main.c
@@ -12,46 +12,61 @@
 
 #include "io_funcs.h"
 #include <string.h>
+#include <pspumd.h>
 
 PSP_MODULE_INFO("umd_livepatch", PSP_MODULE_KERNEL, 2, 1);
 
 
 void lp_patchFunction(u32 addr, void *newaddr, void *fptr);
 
+PspIoDrv *umdDriver;
 PspIoDrvFuncs reserveUmdFuncs;
 
-PspIoDrvFuncs patchedUmdFuncs;
-
-PspIoDrv originalUmdDriver;
-
-PspIoDrv reserveUmdDriver = {
-    .name = "umdraw",
-    .dev_type = 4,
-    .unk2 = 0x800,
-    .name2 = "UMD_RAW",
-    .funcs = &reserveUmdFuncs
-};
-
-PspIoDrv patchedUmdDriver = {
-    .name = "umd",
-    .dev_type = 4, // block device
-    .unk2 = 0x800,
-    .name2 = "UMD9660",
-    .funcs = &patchedUmdFuncs
-};
+SceUID vshCallbackId = 0;
+SceUID umdCallbackId;
+SceUID umdCallbackThread;
 
 #define MAX_MODULE_NUMBER 256
 
-// Bogus read to test intercepting
-static int patched_IoRead(PspIoDrvFileArg *arg, char *data, int len)
+
+
+int lp_discChangeCallback(int unk, int event, void *data)
 {
-    Kprintf("Reading UMD data, hum dee dum...\n");
-    return reserveUmdFuncs.IoRead(arg, data, len);
+    if (event == PSP_UMD_NOT_PRESENT)
+        lp_pingDiscRemoved();
+    if (vshCallbackId)
+        sceKernelNotifyCallback(vshCallbackId, event);
+    return 0;
+}
+
+
+int lp_discChangeWatcher(SceSize argc, void *argp)
+{
+    SceUID callbacks[50];
+    int count;
+    SceKernelCallbackInfo cbinfo;
+
+    sceKernelGetThreadmanIdList(SCE_KERNEL_TMID_Callback, callbacks, 50, &count);
+
+    for (int i = 0; i < count; i++) {
+        sceKernelReferCallbackStatus(callbacks[i], &cbinfo);
+        if (!strcmp(cbinfo.name, "SceVshMediaDetectUMD")) {
+            Kprintf("Found VSH UMD callback: 0x%08x\n", vshCallbackId);
+            vshCallbackId = callbacks[i];
+            break;
+        }
+    }
+
+    umdCallbackId = sceKernelCreateCallback("lp_discChangeCallback",
+                                            lp_discChangeCallback,
+                                            NULL);
+    sceUmdRegisterUMDCallBack(umdCallbackId);
+
+    sceKernelSleepThreadCB();
 }
 
 int module_start(SceSize argc, void *argp)
 {
-    PspIoDrv *umdDriver = 0;
     int ret;
 
     Kprintf("------------------\nUMD Livepatch starting...\n");
@@ -61,7 +76,6 @@ int module_start(SceSize argc, void *argp)
 
     umdDriver = sctrlHENFindDriver("umd");
     if (umdDriver) {
-        originalUmdDriver = *umdDriver;
         reserveUmdFuncs = *umdDriver->funcs;
         Kprintf("Found UMD driver at 0x%08x\n", umdDriver);
     } else {
@@ -69,9 +83,13 @@ int module_start(SceSize argc, void *argp)
         return 1;
     }
 
-    patchedUmdFuncs = reserveUmdFuncs;
+    umdCallbackThread = sceKernelCreateThread("lp_discChangeWatcher",
+                                              lp_discChangeWatcher,
+                                              0x10, 0x1000, 0, NULL);
+    sceKernelStartThread(umdCallbackThread, 0, NULL);
 
     umdDriver->funcs->IoRead = patched_IoRead;
+    umdDriver->funcs->IoOpen = patched_IoOpen;
     umdDriver->funcs->IoDevctl = patched_IoDevctl;
 
     return 0;
@@ -80,11 +98,16 @@ int module_start(SceSize argc, void *argp)
 int module_stop(void)
 {
     Kprintf("Unloading UMD Livepatch.");
-    sceIoDelDrv("umd");
 
-    sceIoAddDrv(&originalUmdDriver);
-    sceIoDelDrv("umdraw");
-    Kprintf("Restored original UMD driver\n");
+    *umdDriver->funcs = reserveUmdFuncs;
+    Kprintf("Restored original UMD driver functions.\n");
+
+    sceUmdUnRegisterUMDCallBack(umdCallbackId);
+    sceKernelDeleteCallback(umdCallbackId);
+
+    if (vshCallbackId)
+        sceUmdRegisterUMDCallBack(vshCallbackId);
+    Kprintf("Disconnected drive state callback.\n");
     return 0;
 }
 
diff --git a/rpatch.c b/rpatch.c
index bbe4485..1191d4f 100644
--- a/rpatch.c
+++ b/rpatch.c
@@ -1,6 +1,8 @@
 #include "io_funcs.h"
 #include "rpatch.h"
 
+lp_UMDiffCommand cmd_buffer[1024];
+
 lp_UMDiffFile
 lp_PatchSet_open(const char *path)
 {
@@ -12,3 +14,9 @@ lp_PatchSet_covered(lp_UMDiffCommand *ps, u32 offset)
 {
 
 }
+
+int
+lp_loadCmdsForIndex(long sector)
+{
+
+}
diff --git a/rpatch.h b/rpatch.h
index 864b971..164c0b6 100644
--- a/rpatch.h
+++ b/rpatch.h
@@ -3,4 +3,7 @@
 
 #include "umdiff/umdiff.h"
 
+int
+lp_loadCmdsForIndex(long sector);
+
 #endif //__RPATCH_H