diff --git a/assets b/assets
index b2404b6b1..7efad31cf 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit b2404b6b1cba47da8eef4910f49985d54318186b
+Subproject commit 7efad31cf80a42600375bf08b397786df5c1037c
diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx
index 91e158299..20d2f75a4 100644
--- a/source/funkin/play/song/Song.hx
+++ b/source/funkin/play/song/Song.hx
@@ -98,7 +98,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
   }
 
   // this returns false so that any new song can override this and return true when needed
-  public function isSongNew(currentDifficulty:String):Bool
+  public function isSongNew(currentDifficulty:String, currentVariation:String):Bool
   {
     return false;
   }
@@ -434,17 +434,25 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
     return null;
   }
 
+  /**
+   * Returns the first valid variation that matches both the difficulty id, and the current character / possible input variations
+   * @param diffId
+   * @param currentCharacter
+   * @param possibleVariations
+   * @return Null<String>
+   */
   public function getFirstValidVariation(?diffId:String, ?currentCharacter:PlayableCharacter, ?possibleVariations:Array<String>):Null<String>
   {
     if (possibleVariations == null)
     {
       possibleVariations = getVariationsByCharacter(currentCharacter);
     }
+
     if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0];
 
     for (variationId in possibleVariations)
     {
-      if (difficulties.exists('$variationId')) return variationId;
+      if (difficulties.get('$variationId')?.exists(diffId) ?? false) return variationId;
     }
 
     return null;
diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx
index 73e7aa77e..47467cd45 100644
--- a/source/funkin/save/Save.hx
+++ b/source/funkin/save/Save.hx
@@ -543,22 +543,34 @@ class Save
    *
    * @param songId The ID of the song.
    * @param difficultyId The difficulty to check.
+   * @param variation The variation to check. Defaults to empty string. Appended to difficulty with `-`, e.g. `easy-pico`.
    * @return A data structure containing score, judgement counts, and accuracy. Returns `null` if no score is saved.
    */
-  public function getSongScore(songId:String, difficultyId:String = 'normal'):Null<SaveScoreData>
+  public function getSongScore(songId:String, difficultyId:String = 'normal', ?variation:String):Null<SaveScoreData>
   {
     var song = data.scores.songs.get(songId);
+    trace('Getting song score for $songId $difficultyId $variation');
     if (song == null)
     {
+      trace('Could not find song data for $songId $difficultyId $variation');
       song = [];
       data.scores.songs.set(songId, song);
     }
+
+    // 'default' variations are left with no suffix ('easy', 'normal', 'hard'),
+    // along with 'erect' variations ('erect', 'nightmare')
+    // otherwise, we want to add a suffix of our current variation to get the save data.
+    if (variation != null && variation != '' && variation != 'default' && variation != 'erect')
+    {
+      difficultyId = '${difficultyId}-${variation}';
+    }
+
     return song.get(difficultyId);
   }
 
-  public function getSongRank(songId:String, difficultyId:String = 'normal'):Null<ScoringRank>
+  public function getSongRank(songId:String, difficultyId:String = 'normal', ?variation:String):Null<ScoringRank>
   {
-    return Scoring.calculateRank(getSongScore(songId, difficultyId));
+    return Scoring.calculateRank(getSongScore(songId, difficultyId, variation));
   }
 
   /**
diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx
index 312c17713..b4e72ef4a 100644
--- a/source/funkin/ui/freeplay/FreeplayState.hx
+++ b/source/funkin/ui/freeplay/FreeplayState.hx
@@ -1717,8 +1717,6 @@ class FreeplayState extends MusicBeatSubState
       }
     }
 
-    trace('CURRENT VARIATION OF SONG: ${currentVariation}');
-
     var daSong:Null<FreeplaySongData> = grpCapsules.members[curSelected].freeplayData;
     if (daSong != null)
     {
@@ -1729,7 +1727,7 @@ class FreeplayState extends MusicBeatSubState
         return;
       }
 
-      var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSong.data.id, currentDifficulty);
+      var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSong.data.id, currentDifficulty, currentVariation);
       intendedScore = songScore?.score ?? 0;
       intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
       rememberedDifficulty = currentDifficulty;
@@ -2025,7 +2023,7 @@ class FreeplayState extends MusicBeatSubState
     var daSongCapsule:SongMenuItem = grpCapsules.members[curSelected];
     if (daSongCapsule.freeplayData != null)
     {
-      var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSongCapsule.freeplayData.data.id, currentDifficulty);
+      var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSongCapsule.freeplayData.data.id, currentDifficulty, currentVariation);
       intendedScore = songScore?.score ?? 0;
       intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
       rememberedSongId = daSongCapsule.freeplayData.data.id;
@@ -2260,7 +2258,7 @@ class FreeplaySongData
   /**
    * Whether the player has seen/played this song before within freeplay
    */
-  public var isNew:Bool = false;
+  public var isNew(get, never):Bool;
 
   /**
    * The default opponent for the song.
@@ -2312,6 +2310,18 @@ class FreeplaySongData
     // this.isNew = song.isSongNew(suffixedDifficulty);
   }
 
+  function get_isNew():Bool
+  {
+    // We use a slightly different manner to get the new status of a song than the other getters here
+    // `isSongNew()` only takes a single variation, and it's data that isn't accessible via the Song data/metadata
+    // it's stored in the song .hxc script in a function that overrides `isSongNew()`
+    // and is only accessible with the correct valid variation inputs
+
+    var variations:Array<String> = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId);
+    var variation:String = data.getFirstValidVariation(FreeplayState.rememberedDifficulty, null, variations);
+    return data.isSongNew(FreeplayState.rememberedDifficulty, variation);
+  }
+
   function get_songCharacter():String
   {
     var variations:Array<String> = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId);
@@ -2340,8 +2350,10 @@ class FreeplaySongData
 
   function get_scoringRank():Null<ScoringRank>
   {
-    // TODO: Properly get/migrate the save data from the suffixed difficulty version to our new unsuffixed version
-    return Save.instance.getSongRank(data.songName, FreeplayState.rememberedDifficulty);
+    var variations:Array<String> = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId);
+    var variation:String = data.getFirstValidVariation(FreeplayState.rememberedDifficulty, null, variations);
+
+    return Save.instance.getSongRank(data.id, FreeplayState.rememberedDifficulty, variation);
   }
 }