[Scummvm-tracker] [ScummVM :: Bugs] #14737: SCUMM/HE: Blue's Birthday - Carrying over Red/Yellow CD savegames (fix included)

ScummVM :: Bugs trac at scummvm.org
Mon Apr 1 11:00:53 UTC 2024


#14737: SCUMM/HE: Blue's Birthday - Carrying over Red/Yellow CD savegames (fix
included)
----------------------------+----------------------------------------
Reporter:  fusefib          |       Owner:  (none)
    Type:  feature request  |      Status:  new
Priority:  normal           |   Component:  Engine: SCUMM
 Version:                   |  Resolution:
Keywords:                   |        Game:  Blue's Birthday Adventure
----------------------------+----------------------------------------

Old description:

> ''Blue's Clues: Blue's Birthday Adventure'' is a two-CD game with four
> pathways, two on each disc. The original behavior is that savefiles are
> partially common for both CDs. In the original game, the following
> savefiles are generated:
> {{{
> (for Yellow CD)
> Blues1.nam
> [PlayerName1].bca
> [PlayerName1].sga
> [PlayerName1].sgb
> ...
> (for Red CD)
> Blues1.nam
> [PlayerName1].bca
> [PlayerName1].sgc
> [PlayerName1].sgd
> ...
> }}}
> ''Blues1.nam'' and ''[PlayerName1].bca'' are shared between the CDs and
> contain the game profile, i.e. sign-in information and overall game
> progress across e.g. minigames from all four pathways. The first has
> name/color/birthday in INI-format (when uncompressed); the other is a
> light, player-specific game progress file. When you create a sign-in
> profile and proceed, both get generated. ''[PlayerName1]'' is whatever
> gets chosen.
>
> The ''.sga'' to ''.sgd'' files are pathway-specific savefiles that get
> generated once you enter a pathway and the game saves progress.
>
> ScummVM generates the same type of savefiles, albeit compressed, though
> its behavior is to prefix the files with the game entry's **target**.
> Targets get incremented if one adds, ID-wise, the same detected game
> again. With the Yellow CD and Red CD being considered separate games with
> one default `gameID`, in a typical scenario we get "**BluesBirthday-**"
> and "**BluesBirthday-1-**" as default savegame prefixes, thus:
> {{{
> BluesBirthday-Blues1.nam
> BluesBirthday-[PlayerName1].bca
> BluesBirthday-1-Blues1.nam
> BluesBirthday-1-[PlayerName1].bca
> }}}
>
> The result is needlessly getting separately loaded game profiles and
> progress by dint of ''not loading the same files'', when ScummVM would
> otherwise manage common savefiles for both game entries just fine.
>
> Here is a proposed fix to easily restore original functionality:
>
> [https://github.com/scummvm/scummvm/blob/98df6023f5699545770d30ee74f7b7ff9037b2d9/engines/scumm/he/script_v60he.cpp#L155
> /engines/scumm/he/script_v60he.cpp#L155]
>
> {{{
>     // Prepend the target name
>     filePath = _targetName + '-' + filePath;
> }}}
>
> ->
>
> {{{
>     if (_game.id == GID_BIRTHDAYYELLOW || _game.id == GID_BIRTHDAYRED) {
>         // Prepend generic name for shared game profile between targets
>         // for Yellow CD and Red CD of Blue's Birthday Adventure
>         filePath = "BluesBirthday-" + filePath;
>     } else {
>         // Prepend the target name
>         filePath = _targetName + '-' + filePath;
>     }
> }}}
>
> Per MD5s and detection entries, there is only one known Red version and
> Yellow version of the full game and demos don't create these files, so
> probably zero compatibility issues on that account.
>
> The gameID-based prefix remains useful so users can distinguish these
> savegames among other ScummVM saves as well as partial overlap with the
> existing default naming.
>
> A minor drawback is the other target's (e.g. "BluesBirthday-1") progress
> gets reset to zero, unless the user manually swaps the savesets which
> would still exist. But the inconvenience is minor.

New description:

 ''Blue's Clues: Blue's Birthday Adventure'' is a two-CD game with four
 pathways, two on each disc. The original behavior is that savefiles are
 partially common for both CDs. In the original game, the following
 savefiles are generated:
 {{{
 (for Yellow CD)
 Blues1.nam
 [PlayerName1].bca
 [PlayerName1].sga
 [PlayerName1].sgb
 ...
 (for Red CD)
 Blues1.nam
 [PlayerName1].bca
 [PlayerName1].sgc
 [PlayerName1].sgd
 ...
 }}}
 ''Blues1.nam'' and ''[PlayerName1].bca'' are shared between the CDs and
 contain the game profile, i.e. sign-in information and overall game
 progress across e.g. minigames from all four pathways. The .sga to .sgd
 files are pathway-specific savefiles that get generated once you enter a
 pathway and the game saves progress. [PlayerName1] is whatever gets
 chosen.

 ScummVM generates the same type of savefiles, but its behavior is to add
 "[gameID]-" as a prefix to these savefiles, and to increment gameIDs (or
 targets) when adding what is considered ID-wise the same game. With the
 Yellow CD and Red CD being considered separate games with one default
 gameID, we get "**BluesBirthday-**" and "**BluesBirthday-1-**" as default
 savegame prefixes, thus:
 {{{
 BluesBirthday-Blues1.nam
 BluesBirthday-[PlayerName1].bca
 BluesBirthday-1-Blues1.nam
 BluesBirthday-1-[PlayerName1].bca
 }}}

 The result is needlessly getting separately loaded game profiles and
 progress by dint of ''not loading the same files'', when ScummVM would
 otherwise manage common savefiles for both game entries just fine.

 Here is a proposed fix to easily restore original functionality:

 [https://github.com/scummvm/scummvm/blob/98df6023f5699545770d30ee74f7b7ff9037b2d9/engines/scumm/he/script_v60he.cpp#L155
 /engines/scumm/he/script_v60he.cpp#L155]

 {{{
     // Prepend the target name
     filePath = _targetName + '-' + filePath;
 }}}

 ->

 {{{
     if (_game.id == GID_BIRTHDAYYELLOW || _game.id == GID_BIRTHDAYRED) {
         // Prepend generic name for shared game profile between targets
         // for Yellow CD and Red CD of Blue's Birthday Adventure
         filePath = "BluesBirthday-" + filePath;
     } else {
         // Prepend the target name
         filePath = _targetName + '-' + filePath;
     }
 }}}

 Per MD5s and detection entries, there is only one known Red version and
 Yellow version of the full game and demos don't create these files, so
 probably zero compatibility issues on that account.

 The prefix remains useful so users can distinguish these savegames among
 other ScummVM saves as well as partial overlap with the existing default
 naming.

 A minor drawback is the "BluesBirthday-1-" progress gets reset to zero,
 unless the user manually swaps the savesets which would still exist. I
 would say the drawback is minimal and the possibility of restoring game
 profiles by renaming can simply be documented in the game's Wiki entry.

 A seamless user experience fix might be to newly add a game configuration
 key by default (e.g. boolean "sharedsaves") when adding these games going
 forward, and to add a check for that configuration key in the code above.
 This way, (the other half of the) existing entries will continue to work
 with the current savegame naming convention and newer entries will have
 shared game sign-in and progress by default. However, this needlessly
 clutters the code.

--
Comment (by fusefib):

 Here are some additional thoughts on this matter:

 {{{
     if ((_game.id == GID_BIRTHDAYYELLOW || _game.id == GID_BIRTHDAYRED) &&
 _targetName.find("BluesBirthday") != 0) {
         // Prepend generic name for shared game profile between targets
         // for Yellow CD and Red CD of Blue's Birthday Adventure,
         // but only if target name begins with "BluesBirthday" (default).
         filePath = "BluesBirthday-" + filePath;
     } else {
         // Prepend the target name
         filePath = _targetName + '-' + filePath;
     }
 }}}

 This adds a placeholder condition that the target name must start with
 "BluesBirthday" - this allow the user to manually change target's name
 (`ID:` in the GUI) to revert back to the old ways of per-target savegames,
 if that's ever desired.

 However, for a better UX solution and one that allows using old savegames,
 this condition should probably be changed to a GUI-accessible game
 configuration key that's disabled by default (e.g. boolean
 "avoidSharedBirthdaySaves").

 Sev suggested a mass-rename, so below is a partial solution. It's pretty
 seamless and doesn't bother the user with a GUI prompt.

 {{{
 void processBirthdaySaveFiles() {
     // Condition 1: Check game ID and that target name begins with
 "BluesBirthday"
     if ((_game.id != GID_BIRTHDAYYELLOW && _game.id != GID_BIRTHDAYRED) ||
 _targetName.find("BluesBirthday") != 0) {
         return;
     }

     // Condition 2: Check for existing shared savegame files
     if (!_saveFileMan->listSavefiles("BluesBirthday-Blues1.nam").empty())
 {
         if (!_saveFileMan->listSavefiles(_targetName +
 "-Blues1.nam").empty() && _targetName != "BluesBirthday") {
             debug("Old savegame files for target/ID '%s' detected, but
 ScummVM is using shared savegame files instead.", _targetName.c_str());
             return;
         } else {
             return;
         }
     }

     // Condition 3: Check if target name matches BluesBirthday or no
 existing target save files
     if (_targetName == "BluesBirthday" ||
 _saveFileMan->listSavefiles(_targetName + "-Blues1.nam").empty()) {
         return;
     }

     // Rename save files
     Common::StringArray targetFilenames =
 _saveFileMan->listSavefiles(_targetName + "-Blues1.nam");
     targetFilenames.append(_saveFileMan->listSavefiles(_targetName +
 "-*.bca"));
     targetFilenames.append(_saveFileMan->listSavefiles(_targetName +
 "-*.sg?"));

     Common::String oldName, newName;

     for (uint i = 0; i < targetFilenames.size(); ++i) {
         oldName = targetFilenames[i];

         newName = oldName;
         newName.replace(_targetName, "BluesBirthday");

         if (_saveFileMan->renameSavefile(oldName, newName)) {
             debug("Renamed %s to %s.", oldName.c_str(), newName.c_str());
         } else {
             warning("Error %i (%s) occurred while renaming %s to %s",
 _saveFileMan->getError().getCode(),
                 _saveFileMan->getErrorDesc().c_str(), oldName.c_str(),
 newName.c_str());
             return;
         }
     }
 }
 }}}
 Basically:
 - if non-gameID-target savegames exist and shared savegames exist: warn in
 console, but don't do anything (i.e. run shared savegames);
 - if non-gameID-target savegames exist and shared savegames don't exist:
 rename target savegames to shared savegames;
 - otherwise, don't do anything.

 It's in untested doodled form, and I'm not sure where it's best wired in.
 It should be done once every time the target starts.

 As suggested with the filePath part, the
 `_targetName.find("BluesBirthday") != 0` condition should probably be
 changed to checking some `avoidSharedBirthdaySaves` bool thing, and this
 should become a disabled-by-default option in the GUI. This way, users can
 choose to utilize their target's existing savegames by checking 'Avoid
 shared savegames (not recommended)' in the Game Options or something like
 that.
-- 
Ticket URL: <https://bugs.scummvm.org/ticket/14737#comment:4>
ScummVM :: Bugs <https://bugs.scummvm.org>
ScummVM


More information about the Scummvm-tracker mailing list