How webMAN MOD Handles Multi-Disc PSXISO Support with USB Eject/Insert Triggers

webMAN MOD automatically advances to the next disc in multi-disc PSXISO games by monitoring USB eject/insert events through the check_multipsx state tracker and the mount_on_insert_usb() polling mechanism.

webMAN MOD enables seamless playback of multi-disc PlayStation 1 games on PlayStation 3 by detecting specific filename patterns and monitoring USB drive hot-swap events. When a game is marked as multi-disc, the system enters a wait state that tracks USB presence and automatically mounts the next disc image upon physical re-insertion of the drive.

Detecting Multi-Disc PSXISO Titles

The detection logic resides in include/scan/games_html.h, where the is_multi_cd() function scans filenames for multi-disc indicators during directory scanning.

/* include/scan/games_html.h – lines 274-280 */
static char *is_multi_cd(const char *name)
{
    char *p = strstr(name, "CD");
    if (!p) { p = strcasestr(name, "Vol"); }
    if (!p)  p = strcasestr(name, "Disc");
    return p;                 // non-NULL → multi-disc name
}

When set_sort_key() processes entries in /PSXISO or /PSXGAMES, it invokes is_multi_cd() to identify titles spanning multiple volumes. The function returns a non-NULL pointer if the filename contains "CD", "Vol", or "Disc", flagging the entry for multi-disc handling.

Initializing the Multi-Disc State

During the mount operation, mount_game() sets the multiCD boolean flag based on the filename check:

/* include/mount/mount_lastgames.h – lines 34-40 */
bool multiCD = (is_multi_cd(_path) != NULL);
if (!multiCD) goto mounting_done;

If multiCD is true, the system records the current USB state in the check_multipsx variable defined in include/mount/mount.h (line 25):

/* include/mount/mount.h – line 25 */
static int8_t check_multipsx = NONE;   // NONE = -1

The value is populated in include/mount/mount_rawiso.h (line 17):

/* include/mount/mount_rawiso.h – line 17 */
if (multiCD) check_multipsx = !isDir("/dev_usb000");   // remember USB state

This signed byte stores 0 when /dev_usb000 is present at mount time, or 1 when the device is already ejected, creating a toggle mechanism for the polling loop.

Polling for USB Eject/Insert Triggers

The XMB polling routine continuously monitors for USB state changes. In include/poll/poll.h (line 242), the main loop invokes the trigger check:

/* include/poll/poll.h – line 242 */
mount_on_insert_usb(_IS_ON_XMB_, msg);

The core logic in include/mount/mount.h (lines 1401-1412) compares the current USB presence against the stored check_multipsx value:

/* include/mount/mount.h – lines 1401-1412 */
else if ((check_multipsx >= 0) && IS_INGAME)
{
    if (isDir("/dev_usb000") == check_multipsx)   // USB appears again
    {
        check_multipsx = NONE;
        show_msg(STR_GAMEUM);                    // "Game Unmounted"
        wait_for("/dev_usb000", 5);               // give user time to re-plug
        mount_game("_next", MOUNT_NEXT_CD);       // mount next CD
    }
}

When the physical USB device is removed and re-inserted, the equality condition matches, resetting check_multipsx to NONE (-1) and invoking mount_game() with the MOUNT_NEXT_CD directive to load the subsequent disc image.

Manual Disc Ejection via Web Commands

Users can manually trigger the eject sequence without physically removing hardware by accessing the /eject.ps3 endpoint. This command invokes eject_insert(1, 0) defined in include/cmd/insert_eject.h, which sends a fake disc eject event via cobra_send_fake_disc_eject_event() and sets the check_multipsx state if a multi-disc game is active.

The automatic mounting sequence requires no additional scripting; the polling loop handles the transition seamlessly when the USB device reappears or when the eject command is issued.

Summary

  • Filename Detection: The is_multi_cd() function in include/scan/games_html.h identifies multi-disc sets by scanning for "CD", "Vol", or "Disc" substrings.
  • State Tracking: The check_multipsx variable stores the initial USB presence state as an int8_t, enabling the system to detect changes.
  • Event Polling: mount_on_insert_usb() in include/mount/mount.h monitors /dev_usb000 status during gameplay, triggering mount_game("_next", MOUNT_NEXT_CD) upon re-insertion.
  • Manual Control: The /eject.ps3 command provides software-based disc ejection without physical USB removal.

Frequently Asked Questions

How does webMAN MOD detect multi-disc PSXISO files?

The system scans filenames during directory enumeration using is_multi_cd() in include/scan/games_html.h. If the filename contains "CD", "Vol", or "Disc" (case-insensitive for the latter two), the function returns a non-NULL pointer, causing mount_game() to set the multiCD flag and initialize the USB monitoring state.

What happens when I eject the USB drive during gameplay?

When you eject the USB drive containing the PSXISO files, the system notes the absence of /dev_usb000. Upon re-insertion, the polling loop detects that isDir("/dev_usb000") now matches the stored check_multipsx value, automatically invoking mount_game("_next", MOUNT_NEXT_CD) to load the next disc in the sequence.

Can I trigger disc changes without physically removing the USB?

Yes. Accessing http://<ps3-ip>/eject.ps3 triggers the eject_insert(1, 0) function in include/cmd/insert_eject.h, which sends a fake disc eject event and prepares the system for the next mount operation. This software-based method achieves the same result as physical USB hot-swapping.

Where is the multi-disc logic implemented in the source code?

The multi-disc implementation spans several files: include/scan/games_html.h handles detection, include/mount/mount_lastgames.h and include/mount/mount_rawiso.h manage state initialization, include/mount/mount.h contains the mount_on_insert_usb() polling logic (lines 1401-1412), and include/poll/poll.h (line 242) integrates the checks into the main XMB polling loop.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →