diff --git a/sim/fakes/media.py b/sim/fakes/media.py
index 165690168bab09f1ad7003745149900a3217323b..60bf2d0827b7794e33d04bfb5e1235f283ad0bb8 100644
--- a/sim/fakes/media.py
+++ b/sim/fakes/media.py
@@ -1,15 +1,49 @@
+import pygame
+from _sim import path_replace
+
+_loaded = False
+
+
 def stop():
     """
     Stops media playback, frees resources.
     """
-    pass
+    global _loaded
+    _loaded = False
+    pygame.mixer.music.stop()
+    pygame.mixer.music.unload()
 
 
-def load(path):
+def load(path, paused=False):
     """
     Load path
     """
-    pass
+    global _loaded
+    if path.startswith(("http://", "https://")):
+        return
+    pygame.mixer.music.load(path_replace(path))
+    pygame.mixer.music.play()
+    if paused:
+        pygame.mixer.music.pause()
+    _loaded = True
+
+
+def play():
+    if not _loaded:
+        return
+    pygame.mixer.music.unpause()
+
+
+def pause():
+    if not _loaded:
+        return
+    pygame.mixer.music.pause()
+
+
+def is_playing():
+    if not _loaded:
+        return False
+    return pygame.mixer.music.get_busy()
 
 
 def draw(ctx):
@@ -24,3 +58,43 @@ def think(delta_ms):
     Process ms amounts of media, queuing PCM data and preparing for draw()
     """
     pass
+
+
+def set_volume(vol):
+    if not _loaded:
+        return
+    pygame.mixer.music.set_volume(vol)
+
+
+def get_volume():
+    if not _loaded:
+        return 1.0
+    return pygame.mixer.music.get_volume()
+
+
+def get_position():
+    if not _loaded:
+        return 0
+    pos = pygame.mixer.music.get_pos() / 1000
+    if pos < 0:
+        pos = get_duration()
+    return pos
+
+
+def get_time():
+    return get_position()
+
+
+def seek(pos):
+    if not _loaded:
+        return
+    pygame.mixer.music.play()
+    pygame.mixer.music.rewind()
+
+
+def get_duration():
+    return 99999
+
+
+def is_visual():
+    return False