diff --git a/difficulty.py b/difficulty.py
index 89f4f4bacd0b7d5abd8083cab86363cac417394e..2de9e2a579d172d58d84ec25e033f27bbb5ec6f8 100644
--- a/difficulty.py
+++ b/difficulty.py
@@ -24,6 +24,7 @@ class DifficultyView(BaseView):
         if len(self.song.difficulties) > 2:
             self._sc.set_position(1)
         self._scroll_pos = 0
+        self.song.readScores()
 
     def draw(self, ctx: Context) -> None:
         
@@ -96,15 +97,23 @@ class DifficultyView(BaseView):
         ctx.move_to (0, -78)
         ctx.text("DIFFICULTY")
         
-        """
-        ctx.font_size = 15
-        ctx.move_to(0, 78)
-        ctx.text("Put songs into")
-        ctx.move_to(0, 94)
-        ctx.font_size = 15
-        ctx.gray(0.75)
-        ctx.text("/sd/PetalHero")
-        """
+        if self.song.difficulties:
+            score = self.song.scores[self.song.difficulties[self._sc.target_position()]]
+            if not score.empty():
+                ctx.font_size = 15
+                ctx.gray(0.5)
+                ctx.text_align = ctx.RIGHT
+                ctx.font = "Material Icons"
+                ctx.move_to(-7, 86)
+                ctx.text("\ue885")
+                ctx.move_to(-7, 102)
+                ctx.text("\uea0b")
+                ctx.font = "Camp Font 3"
+                ctx.text_align = ctx.LEFT
+                ctx.move_to(-5, 83)
+                ctx.text(f"{int(score.max_acc.accuracy * 100)}%")
+                ctx.move_to(-5, 99)
+                ctx.text(str(score.max_streak.streak))
 
     def think(self, ins: InputState, delta_ms: int) -> None:
         super().think(ins, delta_ms)
diff --git a/score.py b/score.py
index 4a308164ae4a0d4246d462bffbcfcd8b50be766e..6c9b76e8a6888f81428a8c9399156164dc46847f 100644
--- a/score.py
+++ b/score.py
@@ -37,6 +37,9 @@ class ScoreView(BaseView):
             events = data.track.getAllEvents()
             self.accuracy = len(set(filter(lambda x: x.played and not x.missed, events))) / (len(events) + badnotes)
         self.stars = int(5.0 * (self.accuracy + 0.05))
+        
+        self.highscore = self.song.recordScore(difficulty, self.accuracy, streak, badnotes)
+        self.timeout = 5 if self.highscore else 0
 
     def draw(self, ctx: Context) -> None:
         #utils.background(ctx)
@@ -95,20 +98,34 @@ class ScoreView(BaseView):
         ctx.text(f"Accuracy: {int(self.accuracy * 100)}%")
         ctx.move_to(0,58)
         ctx.text(f"Longest streak: {self.streak}")
-                
+        
         ctx.font = "Camp Font 3"
-        ctx.font_size = 16
         ctx.text_align = ctx.CENTER
         ctx.text_baseline = ctx.MIDDLE
-        ctx.gray(0.5)
-        ctx.move_to(0, 84 - math.sin(self.time * 4) * 2)
-        ctx.text("Press the button...")
+
+        alpha = min(self.timeout, 0.5) / 0.5
+        if alpha > 0:
+          ctx.global_alpha = alpha
+          utils.fire_gradient(ctx)
+          ctx.font_size = 18
+          ctx.move_to(0, 85  - math.sin(self.time * 4) * 2)
+          ctx.text("New highscore!")
+        
+        if alpha < 1:
+          ctx.global_alpha = 1.0 - alpha
+          ctx.gray(0.5)
+          ctx.font_size = 16
+          ctx.move_to(0, 84 - math.sin(self.time * 4) * 2)
+          ctx.text("Press the button...")
 
     def think(self, ins: InputState, delta_ms: int) -> None:
         super().think(ins, delta_ms)
         media.think(delta_ms)
         utils.blm_timeout(self, delta_ms)
         self.time += delta_ms / 1000
+        self.timeout -= delta_ms / 1000
+        if self.timeout < 0:
+            self.timeout = 0
         
         if self.time > 1.5 and not self.played:
             self.played = True
diff --git a/songinfo.py b/songinfo.py
index 1f62758fd2f4fb19a57e8446c267a0b482fc3d8b..e076b6902d7ed099396b05c7b25ee9b017de5593 100644
--- a/songinfo.py
+++ b/songinfo.py
@@ -1,5 +1,6 @@
 import os
 import sys
+import struct
 
 from .configparser import ConfigParser
 
@@ -40,6 +41,41 @@ class MidiInfoReader(MidiOutStream):
       if len(self.difficulties) == len(difficulties):
         raise MidiInfoReader.Done()
 
+class Score():
+  accuracy = None
+  streak = None
+  badnotes = None
+  
+  def __init__(self, score = None):
+    if score is not None:
+      self.accuracy = score.accuracy
+      self.streak = score.streak
+      self.badnotes = score.badnotes
+      
+  def __eq__(self, score):
+    return self.accuracy == score.accuracy and self.streak == score.streak and self.badnotes == score.badnotes
+  
+  def empty(self):
+    return self.accuracy is None or self.streak is None or self.badnotes is None
+  
+  def __repr__(self):
+    if self.empty():
+      return "Score()"
+    return f"Score(acc: {self.accuracy}, str: {self.streak}, bn: {self.badnotes})"
+
+class ScoreSet():
+  def __init__(self):
+    self.max_acc = Score()
+    self.max_streak = Score()
+    
+  def empty(self):
+    return self.max_acc.empty() and self.max_streak.empty()
+    
+  def __repr__(self):
+    if self.empty():
+      return "ScoreSet()"
+    return f"ScoreSet(max_acc: {str(self.max_acc)}, max_str: {str(self.max_streak)})" 
+
 class SongInfo(object):
   def __init__(self, dirName):
     infoFileName = dirName + "/song.ini"
@@ -48,6 +84,7 @@ class SongInfo(object):
     self.fileName      = infoFileName
     self.info          = ConfigParser()
     self._difficulties = None
+    self._scores       = None
 
     try:
       self.info.read(infoFileName)
@@ -142,6 +179,91 @@ class SongInfo(object):
           f.write(bytes([diff.id]))
     except Exception as e:
       sys.print_exception(e)
+  
+  def readScores(self):
+    self._scores = {}
+    for diff in difficulties.values():
+      self._scores[diff] = ScoreSet()
+
+    scoreFileName = os.path.join(os.path.dirname(self.fileName), ".score.pet")
+    if not os.path.exists(scoreFileName):
+      return self._scores
+    
+    try:
+      with open(scoreFileName, "rb") as f:
+        magic = f.read(7)
+        assert(magic == b"PHSCORE")
+        ver = f.read(1)
+        assert(ver == b"\0")
+        length = f.read(1)[0]
+        for i in range(length):
+          diff = f.read(1)[0]
+          assert(diff in difficulties)
+          assert(difficulties[diff] in self._scores)
+          score = self._scores[difficulties[diff]]
+          score.max_acc.accuracy, score.max_acc.streak, score.max_acc.badnotes = struct.unpack('!fII', f.read(12))
+          score.max_streak.accuracy, score.max_streak.streak, score.max_streak.badnotes = struct.unpack('!fII', f.read(12))
+    except Exception as e:
+      sys.print_exception(e)
+
+    return self._scores
+
+  def saveScores(self):
+    try:
+      scoreFileName = os.path.join(os.path.dirname(self.fileName), ".score.pet")
+      with open(scoreFileName, "wb") as f:
+        f.write(b"PHSCORE\0")
+        diffs = tuple(filter(lambda x: not self._scores[x].empty(), self._scores.keys()))
+        f.write(bytes((len(diffs),)))
+        for diff in diffs:
+          score = self._scores[diff]
+          f.write(bytes((diff.id,)))
+          f.write(struct.pack("!fII", score.max_acc.accuracy, score.max_acc.streak, score.max_acc.badnotes))
+          f.write(struct.pack("!fII", score.max_streak.accuracy, score.max_streak.streak, score.max_streak.badnotes))
+    except Exception as e:
+      sys.print_exception(e)
+  
+  def recordScore(self, difficulty, accuracy, streak, badnotes):
+    if self._scores is None:
+      self.readScores()
+      
+    max_acc = self._scores[difficulty].max_acc
+    max_streak = self._scores[difficulty].max_streak
+      
+    save = False
+      
+    if max_acc.empty() or accuracy > max_acc.accuracy:
+      max_acc.accuracy = accuracy
+      max_acc.streak = streak
+      max_acc.badnotes = badnotes
+      save = True
+    elif accuracy == max_acc.accuracy:
+      if streak > max_acc.streak:
+        max_acc.streak = streak
+        max_acc.badnotes = badnotes
+        save = True
+      elif badnotes < max_acc.badnotes:
+        max_acc.badnotes = badnotes
+        save = True
+        
+    if max_streak.empty() or streak > max_streak.streak:
+      max_streak.streak = streak
+      max_streak.accuracy = accuracy
+      max_streak.badnotes = badnotes
+      save = True
+    elif streak == max_streak.streak:
+      if accuracy > max_streak.accuracy:
+        max_streak.accuracy = accuracy
+        max_streak.badnotes = badnotes
+        save = True
+      elif badnotes < max_streak.badnotes:
+        max_streak.badnotes = badnotes
+        save = True
+    
+    if save:
+      self.saveScores()
+
+    return save
 
   def getName(self):
     return self._get("name")
@@ -167,9 +289,15 @@ class SongInfo(object):
     if preview is None or preview < 0 or length is None or length <= 0:
         return 0.1
     return preview / length
+  
+  def getScores(self):
+    if self._scores is None:
+      self.readScores()
+    return self._scores
     
   name          = property(getName, setName)
   artist        = property(getArtist, setArtist)
   delay         = property(getDelay, setDelay)
   difficulties  = property(getDifficulties)
   preview       = property(getPreview)
+  scores        = property(getScores)