diff --git a/.run/Build_BIG_UI.run.xml b/.run/Build_BIG_UI.run.xml
new file mode 100644
index 0000000000..b58b1bf1b7
--- /dev/null
+++ b/.run/Build_BIG_UI.run.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Build_SMALL_UI.run.xml b/.run/Build_SMALL_UI.run.xml
new file mode 100644
index 0000000000..6c231c83f8
--- /dev/null
+++ b/.run/Build_SMALL_UI.run.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SConstruct b/SConstruct
index 48dd044709..f5d5ec6fb8 100644
--- a/SConstruct
+++ b/SConstruct
@@ -178,7 +178,8 @@ Export('envCython', 'np_version')
Export('env', 'arch')
# Setup cache dir
-cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache'
+default_cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache'
+cache_dir = ARGUMENTS.get('cache_dir', default_cache_dir)
CacheDir(cache_dir)
Clean(["."], cache_dir)
diff --git a/system/ui/README.md b/system/ui/README.md
index f81cb5573a..796d298626 100644
--- a/system/ui/README.md
+++ b/system/ui/README.md
@@ -10,6 +10,7 @@ Quick start:
* set `BURN_IN=1` to get a burn-in heatmap version of the UI
* set `GRID=50` to show a 50-pixel alignment grid overlay
* set `MAGIC_DEBUG=1` to show every dropped frames (only on device)
+* set `SUNNYPILOT_UI=0` to run the stock UI instead of the sunnypilot UI
* https://www.raylib.com/cheatsheet/cheatsheet.html
* https://electronstudio.github.io/raylib-python-cffi/README.html#quickstart
diff --git a/system/ui/lib/application.py b/system/ui/lib/application.py
index e3370a5f74..7271127838 100644
--- a/system/ui/lib/application.py
+++ b/system/ui/lib/application.py
@@ -19,6 +19,8 @@ from openpilot.system.hardware import HARDWARE, PC
from openpilot.system.ui.lib.multilang import multilang
from openpilot.common.realtime import Ratekeeper
+from openpilot.system.ui.sunnypilot.lib.application import GuiApplicationExt
+
_DEFAULT_FPS = int(os.getenv("FPS", {'tizi': 20}.get(HARDWARE.get_device_type(), 60)))
FPS_LOG_INTERVAL = 5 # Seconds between logging FPS drops
FPS_DROP_THRESHOLD = 0.9 # FPS drop threshold for triggering a warning
@@ -186,7 +188,7 @@ class MouseState:
self._prev_mouse_event[slot] = ev
-class GuiApplication:
+class GuiApplication(GuiApplicationExt):
def __init__(self, width: int | None = None, height: int | None = None):
self._fonts: dict[FontWeight, rl.Font] = {}
self._width = width if width is not None else GuiApplication._default_width()
diff --git a/system/ui/sunnypilot/lib/application.py b/system/ui/sunnypilot/lib/application.py
new file mode 100644
index 0000000000..b39bf31e9d
--- /dev/null
+++ b/system/ui/sunnypilot/lib/application.py
@@ -0,0 +1,15 @@
+"""
+Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
+
+This file is part of sunnypilot and is licensed under the MIT License.
+See the LICENSE.md file in the root directory for more details.
+"""
+import os
+
+SUNNYPILOT_UI = os.getenv("SUNNYPILOT_UI", "1") == "1"
+
+
+class GuiApplicationExt:
+ @staticmethod
+ def sunnypilot_ui() -> bool:
+ return SUNNYPILOT_UI