What changed, and why it matters
This commit updates the Trezor firmware build system and emulator code to use SDL3 instead of the older SDL2 library. It is a routine dependency migration affecting only emulator builds (software simulations of the hardware wallet), not the real device firmware. The changes rename functions and constants to match SDL3's API, adjust build scripts, and add a couple of small safety checks. There is no indication this fixes a known security vulnerability.
Treat as a normal maintenance/dependency migration. Verify emulator builds and tests pass with SDL3. No security-specific response is warranted based on the supplied materials.
Security signals we found
Dependency version bump (SDL2 -> SDL3) for emulator-only code paths
Minor added NULL checks in display suspend overlay and screenshot cropping paths
No changes to cryptographic, storage, bootloader verification, or hardware-wallet runtime logic
No vendor security advisory, CVE, or researcher attribution present in commit or references
Evidence from the diff
The diff migrates Trezor’s emulator targets from SDL2/SDL2_image to SDL3/SDL3_image. Changes include pkg-config invocations (sdl3 / sdl3-image), header paths (
Changed components
core emulator build scripts (SConscript.bootloader_emu, SConscript.prodtest_emu, SConscript.unix)core emulator Unix I/O drivers (button, display, power_manager, touch)core emulator project entry points (bootloader, prodtest, unix main)core embed Rust build scriptlegacy emulator (buttons.c, oled.c, Makefile.include)Nix development shell (shell.nix)Inspect captured patch +171 / −144
diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu
index d7d8ebae..244dd0ce 100644
--- a/core/SConscript.bootloader_emu
+++ b/core/SConscript.bootloader_emu
@@ -228,9 +228,9 @@ except OSError:
print("libjpeg not installed, Emulator build is not possible")
try:
- env.ParseConfig('pkg-config --cflags --libs sdl2 SDL2_image')
+ env.ParseConfig('pkg-config --cflags --libs sdl3 sdl3-image')
except OSError:
- print("SDL2 not installed, Emulator build is not possible")
+ print("SDL3 not installed, Emulator build is not possible")
env.Replace(
diff --git a/core/SConscript.prodtest_emu b/core/SConscript.prodtest_emu
index 262afba3..ada4f4f5 100644
--- a/core/SConscript.prodtest_emu
+++ b/core/SConscript.prodtest_emu
@@ -245,9 +245,9 @@ except OSError:
print("libjpeg not installed, Emulator build is not possible")
try:
- env.ParseConfig('pkg-config --cflags --libs sdl2 SDL2_image')
+ env.ParseConfig('pkg-config --cflags --libs sdl3 sdl3-image')
except OSError:
- print("SDL2 not installed, Emulator build is not possible")
+ print("SDL3 not installed, Emulator build is not possible")
env.Replace(
diff --git a/core/SConscript.unix b/core/SConscript.unix
index 7e5438e7..df00e9f5 100644
--- a/core/SConscript.unix
+++ b/core/SConscript.unix
@@ -563,9 +563,9 @@ except OSError:
print("libjpeg not installed, Emulator build is not possible")
try:
- env.ParseConfig('pkg-config --cflags --libs sdl2 SDL2_image')
+ env.ParseConfig('pkg-config --cflags --libs sdl3 sdl3-image')
except OSError:
- print("SDL2 not installed, Emulator build is not possible")
+ print("SDL3 not installed, Emulator build is not possible")
BYTECODE_OPTIMIZATION = {'0': '0', '1': '3'}[PYOPT]
@@ -981,7 +981,8 @@ env.Depends(obj_program, qstr_generated)
program = env.Command(
target='trezor-emu-core',
source=obj_program,
- action='$CC -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $LINKFLAGS', )
+ action='$CC -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $LINKFLAGS',
+)
if CMAKELISTS != 0:
env.Depends(program, cmake_gen)
diff --git a/core/embed/io/button/unix/button.c b/core/embed/io/button/unix/button.c
index c1922314..10698842 100644
--- a/core/embed/io/button/unix/button.c
+++ b/core/embed/io/button/unix/button.c
@@ -79,7 +79,8 @@ void button_deinit(void) {
static void button_sdl_event_filter(void* context, SDL_Event* sdl_event) {
button_driver_t* drv = &g_button_driver;
- if (sdl_event->type != SDL_KEYDOWN && sdl_event->type != SDL_KEYUP) {
+ if (sdl_event->type != SDL_EVENT_KEY_DOWN &&
+ sdl_event->type != SDL_EVENT_KEY_UP) {
return;
}
@@ -89,7 +90,7 @@ static void button_sdl_event_filter(void* context, SDL_Event* sdl_event) {
button_t button;
- switch (sdl_event->key.keysym.sym) {
+ switch (sdl_event->key.key) {
#ifdef BTN_LEFT_KEY
case BTN_LEFT_KEY:
button = BTN_LEFT;
@@ -109,7 +110,7 @@ static void button_sdl_event_filter(void* context, SDL_Event* sdl_event) {
return;
}
- if (sdl_event->type == SDL_KEYDOWN) {
+ if (sdl_event->type == SDL_EVENT_KEY_DOWN) {
drv->state |= (1 << button);
} else {
drv->state &= ~(1 << button);
diff --git a/core/embed/io/display/unix/display_driver.c b/core/embed/io/display/unix/display_driver.c
index ba47f160..e1c72a58 100644
--- a/core/embed/io/display/unix/display_driver.c
+++ b/core/embed/io/display/unix/display_driver.c
@@ -30,10 +30,11 @@
#include <sys/logging.h>
#include <sys/systask.h>
-#include <SDL2/SDL.h>
-#include <SDL2/SDL_blendmode.h>
-#include <SDL2/SDL_image.h>
-#include <SDL2/SDL_render.h>
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_blendmode.h>
+#include <SDL3/SDL_render.h>
+#include <SDL3_image/SDL_image.h>
+#include <stdlib.h>
#include "profile.h"
@@ -109,7 +110,7 @@ bool display_init(display_content_mode_t mode) {
return true;
}
- if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+ if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_HAPTIC | SDL_INIT_EVENTS)) {
LOG_ERR("%s", SDL_GetError());
error_shutdown("SDL_Init error");
}
@@ -123,21 +124,19 @@ bool display_init(display_content_mode_t mode) {
window_title_alloc = NULL;
}
- drv->window =
- SDL_CreateWindow(window_title, SDL_WINDOWPOS_UNDEFINED,
- SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT,
+ drv->window = SDL_CreateWindow(window_title, WINDOW_WIDTH, WINDOW_HEIGHT,
#ifdef TREZOR_EMULATOR_RASPI
- SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN
+ SDL_WINDOW_FULLSCREEN
#else
- SDL_WINDOW_SHOWN
+ 0 // windows are visible by default in SDL3
#endif
- );
+ );
free(window_title_alloc);
if (!drv->window) {
LOG_ERR("%s", SDL_GetError());
error_shutdown("SDL_CreateWindow error");
}
- drv->renderer = SDL_CreateRenderer(drv->window, -1, SDL_RENDERER_SOFTWARE);
+ drv->renderer = SDL_CreateRenderer(drv->window, NULL);
if (!drv->renderer) {
LOG_ERR("%s", SDL_GetError());
SDL_DestroyWindow(drv->window);
@@ -146,9 +145,10 @@ bool display_init(display_content_mode_t mode) {
SDL_SetRenderDrawColor(drv->renderer, 0, 0, 0, 255);
SDL_RenderClear(drv->renderer);
- drv->buffer = SDL_CreateRGBSurface(0, DISPLAY_RESX, DISPLAY_RESY, COLOR_DEPTH,
- COLOR_MASK_R, COLOR_MASK_G, COLOR_MASK_B,
- COLOR_MASK_A);
+ drv->buffer = SDL_CreateSurface(
+ DISPLAY_RESX, DISPLAY_RESY,
+ SDL_GetPixelFormatForMasks(COLOR_DEPTH, COLOR_MASK_R, COLOR_MASK_G,
+ COLOR_MASK_B, COLOR_MASK_A));
drv->texture = SDL_CreateTexture(drv->renderer, PIXEL_FORMAT,
SDL_TEXTUREACCESS_STREAMING, DISPLAY_RESX,
DISPLAY_RESY);
@@ -162,31 +162,31 @@ bool display_init(display_content_mode_t mode) {
#define CONCAT_LEN(name) CONCAT_LEN_HELPER(name)
#ifdef BACKGROUND_FILE
#include BACKGROUND_FILE
- drv->background = IMG_LoadTexture_RW(
+ drv->background = IMG_LoadTexture_IO(
drv->renderer,
- SDL_RWFromMem(BACKGROUND_NAME, CONCAT_LEN(BACKGROUND_NAME)), 0);
+ SDL_IOFromMem(BACKGROUND_NAME, CONCAT_LEN(BACKGROUND_NAME)), true);
#endif
#ifdef FOREGROUND_FILE
#include FOREGROUND_FILE
- drv->foreground = IMG_LoadTexture_RW(
+ drv->foreground = IMG_LoadTexture_IO(
drv->renderer,
- SDL_RWFromMem(FOREGROUND_NAME, CONCAT_LEN(FOREGROUND_NAME)), 0);
+ SDL_IOFromMem(FOREGROUND_NAME, CONCAT_LEN(FOREGROUND_NAME)), true);
if (drv->foreground) {
SDL_SetTextureBlendMode(drv->foreground, SDL_BLENDMODE_BLEND);
// check that foreground dimensions match the window size which is important
// for cutouts
- int fw, fh;
- if (SDL_QueryTexture(drv->foreground, NULL, NULL, &fw, &fh) == 0) {
- if (fw != WINDOW_WIDTH || fh != WINDOW_HEIGHT) {
+ float fw, fh;
+ if (SDL_GetTextureSize(drv->foreground, &fw, &fh)) {
+ if ((int)fw != WINDOW_WIDTH || (int)fh != WINDOW_HEIGHT) {
LOG_ERR(
"Foreground texture size (%dx%d) does not match window size "
"(%dx%d)",
- fw, fh, WINDOW_WIDTH, WINDOW_HEIGHT);
+ (int)fw, (int)fh, WINDOW_WIDTH, WINDOW_HEIGHT);
error_shutdown("Foreground texture size mismatch");
}
} else {
- LOG_ERR("SDL_QueryTexture failed: %s", SDL_GetError());
- error_shutdown("SDL_QueryTexture error");
+ LOG_ERR("SDL_GetTextureSize failed: %s", SDL_GetError());
+ error_shutdown("SDL_GetTextureSize error");
}
}
#endif
@@ -212,7 +212,7 @@ bool display_init(display_content_mode_t mode) {
#endif
#ifdef TREZOR_EMULATOR_RASPI
drv->orientation_angle = 270;
- SDL_ShowCursor(SDL_DISABLE);
+ SDL_HideCursor();
#else
drv->orientation_angle = 0;
#endif
@@ -235,8 +235,9 @@ void display_deinit(display_content_mode_t mode) {
gfx_bitblt_deinit();
- SDL_FreeSurface(drv->prev_saved);
- SDL_FreeSurface(drv->buffer);
+ SDL_DestroySurface(drv->prev_saved);
+ drv->prev_saved = NULL;
+ SDL_DestroySurface(drv->buffer);
if (drv->background != NULL) {
SDL_DestroyTexture(drv->background);
}
@@ -416,7 +417,7 @@ void draw_rgb_led() {
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
- SDL_RenderDrawPoint(drv->renderer, center_x + x, center_y + y);
+ SDL_RenderPoint(drv->renderer, center_x + x, center_y + y);
}
}
}
@@ -424,14 +425,14 @@ void draw_rgb_led() {
}
#endif // USE_RGB_LED
-static SDL_Rect screen_rect(void) {
+static SDL_FRect screen_rect(void) {
display_driver_t *drv = &g_display_driver;
if (drv->background || drv->foreground) {
- return (SDL_Rect){TOUCH_OFFSET_X, TOUCH_OFFSET_Y, DISPLAY_RESX,
- DISPLAY_RESY};
+ return (SDL_FRect){TOUCH_OFFSET_X, TOUCH_OFFSET_Y, DISPLAY_RESX,
+ DISPLAY_RESY};
} else {
- return (SDL_Rect){EMULATOR_BORDER, EMULATOR_BORDER, DISPLAY_RESX,
- DISPLAY_RESY};
+ return (SDL_FRect){EMULATOR_BORDER, EMULATOR_BORDER, DISPLAY_RESX,
+ DISPLAY_RESY};
}
}
@@ -447,8 +448,8 @@ static void display_refresh_internal(void) {
#endif
if (drv->background) {
- const SDL_Rect r = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
- SDL_RenderCopy(drv->renderer, drv->background, NULL, &r);
+ const SDL_FRect r = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
+ SDL_RenderTexture(drv->renderer, drv->background, NULL, &r);
} else {
SDL_RenderClear(drv->renderer);
}
@@ -458,13 +459,13 @@ static void display_refresh_internal(void) {
#define BACKLIGHT_NORMAL 150
SDL_SetTextureAlphaMod(
drv->texture, MIN(255, 255 * drv->backlight_level / BACKLIGHT_NORMAL));
- const SDL_Rect r = screen_rect();
- SDL_RenderCopyEx(drv->renderer, drv->texture, NULL, &r,
- drv->orientation_angle, NULL, 0);
+ const SDL_FRect r = screen_rect();
+ SDL_RenderTextureRotated(drv->renderer, drv->texture, NULL, &r,
+ drv->orientation_angle, NULL, 0);
if (drv->foreground) {
- const SDL_Rect fr = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
- SDL_RenderCopy(drv->renderer, drv->foreground, NULL, &fr);
+ const SDL_FRect fr = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
+ SDL_RenderTexture(drv->renderer, drv->foreground, NULL, &fr);
}
#ifdef USE_RGB_LED
@@ -597,19 +598,20 @@ void display_save(const char *prefix) {
static char filename[256];
// take a cropped view of the screen contents
const SDL_Rect rect = {0, 0, DISPLAY_RESX, DISPLAY_RESY};
- SDL_Surface *crop = SDL_CreateRGBSurface(
- drv->buffer->flags, rect.w, rect.h, drv->buffer->format->BitsPerPixel,
- drv->buffer->format->Rmask, drv->buffer->format->Gmask,
- drv->buffer->format->Bmask, drv->buffer->format->Amask);
+ SDL_Surface *crop = SDL_CreateSurface(rect.w, rect.h, drv->buffer->format);
+ if (crop == NULL) {
+ LOG_ERR("SDL_CreateSurface failed: %s", SDL_GetError());
+ return;
+ }
SDL_BlitSurface(drv->buffer, &rect, crop, NULL);
// compare with previous screen, skip if equal
if (drv->prev_saved != NULL) {
if (memcmp(drv->prev_saved->pixels, crop->pixels, crop->pitch * crop->h) ==
0) {
- SDL_FreeSurface(crop);
+ SDL_DestroySurface(crop);
return;
}
- SDL_FreeSurface(drv->prev_saved);
+ SDL_DestroySurface(drv->prev_saved);
}
// save to png
snprintf(filename, sizeof(filename), "%s%08d.png", prefix, count++);
@@ -624,7 +626,7 @@ void display_clear_save(void) {
return;
}
- SDL_FreeSurface(drv->prev_saved);
+ SDL_DestroySurface(drv->prev_saved);
drv->prev_saved = NULL;
}
@@ -636,7 +638,7 @@ static void display_draw_suspend_overlay_internal(void) {
return;
}
- SDL_Rect screen = screen_rect();
+ SDL_FRect screen = screen_rect();
// create a blue texture
SDL_Texture *overlay =
SDL_CreateTexture(drv->renderer, SDL_PIXELFORMAT_RGBA8888,
@@ -649,24 +651,33 @@ static void display_draw_suspend_overlay_internal(void) {
SDL_RenderClear(drv->renderer);
// draw the suspend overlay png in the middle of the texture
- SDL_Texture *suspend_text = IMG_LoadTexture_RW(
+ SDL_Texture *suspend_text = IMG_LoadTexture_IO(
drv->renderer,
- SDL_RWFromMem(_suspend_overlay_text_data, _suspend_overlay_text_len), 0);
- int text_width, text_height;
- SDL_QueryTexture(suspend_text, NULL, NULL, &text_width, &text_height);
- SDL_Rect middle = {(screen.w - text_width) / 2, (screen.h - text_height) / 2,
- text_width, text_height};
- SDL_RenderCopy(drv->renderer, suspend_text, NULL, &middle);
+ SDL_IOFromMem(_suspend_overlay_text_data, _suspend_overlay_text_len),
+ true);
+ if (suspend_text == NULL) {
+ LOG_ERR("Failed to load suspend overlay texture: %s", SDL_GetError());
+ goto cleanup;
+ }
+ float text_width = 0.0f, text_height = 0.0f;
+ if (!SDL_GetTextureSize(suspend_text, &text_width, &text_height)) {
+ LOG_ERR("SDL_GetTextureSize failed: %s", SDL_GetError());
+ goto cleanup;
+ }
+ SDL_FRect middle = {(screen.w - text_width) / 2, (screen.h - text_height) / 2,
+ text_width, text_height};
+ SDL_RenderTexture(drv->renderer, suspend_text, NULL, &middle);
SDL_RenderPresent(drv->renderer);
// render to the screen
SDL_SetRenderTarget(drv->renderer, NULL);
- SDL_RenderCopy(drv->renderer, overlay, NULL, &screen);
+ SDL_RenderTexture(drv->renderer, overlay, NULL, &screen);
SDL_RenderPresent(drv->renderer);
- // cleanup
+cleanup:
SDL_DestroyTexture(suspend_text);
SDL_DestroyTexture(overlay);
+ SDL_SetRenderTarget(drv->renderer, NULL);
SDL_SetRenderDrawColor(drv->renderer, 0, 0, 0, 255);
}
diff --git a/core/embed/io/power_manager/unix/power_manager.c b/core/embed/io/power_manager/unix/power_manager.c
index 0554f7a4..d1bbfba6 100644
--- a/core/embed/io/power_manager/unix/power_manager.c
+++ b/core/embed/io/power_manager/unix/power_manager.c
@@ -23,8 +23,9 @@
#include <io/power_manager.h>
#include <io/unix/sdl_display.h>
-#include <SDL.h>
-#include <SDL2/SDL_events.h>
+#include <SDL3/SDL.h>
+#include <stdlib.h>
+#include "SDL3/SDL_events.h"
#include "../power_manager_poll.h"
@@ -76,11 +77,12 @@ pm_status_t pm_suspend(wakeup_flags_t* wakeup_reason) {
SDL_Event event;
while (SDL_WaitEvent(&event)) {
- if (event.type == SDL_QUIT) {
+ if (event.type == SDL_EVENT_QUIT) {
exit(1);
}
- if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP ||
- event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
+ if (event.type == SDL_EVENT_KEY_DOWN || event.type == SDL_EVENT_KEY_UP ||
+ event.type == SDL_EVENT_MOUSE_BUTTON_DOWN ||
+ event.type == SDL_EVENT_MOUSE_BUTTON_UP) {
*wakeup_reason = WAKEUP_FLAG_BUTTON;
break;
}
diff --git a/core/embed/io/touch/unix/touch.c b/core/embed/io/touch/unix/touch.c
index 24aad4e6..2d69c18a 100644
--- a/core/embed/io/touch/unix/touch.c
+++ b/core/embed/io/touch/unix/touch.c
@@ -79,7 +79,7 @@ static void handle_mouse_events(touch_driver_t* drv, SDL_Event* event) {
bool inside_display = is_inside_display(event->button.x, event->button.y);
switch (event->type) {
- case SDL_MOUSEBUTTONDOWN:
+ case SDL_EVENT_MOUSE_BUTTON_DOWN:
if (inside_display) {
int x = event->button.x - sdl_touch_offset_x;
int y = event->button.y - sdl_touch_offset_y;
@@ -88,7 +88,7 @@ static void handle_mouse_events(touch_driver_t* drv, SDL_Event* event) {
}
break;
- case SDL_MOUSEBUTTONUP:
+ case SDL_EVENT_MOUSE_BUTTON_UP:
if (drv->state != IDLE) {
int x = inside_display ? event->button.x - sdl_touch_offset_x
: touch_unpack_x(drv->last_event);
@@ -100,7 +100,7 @@ static void handle_mouse_events(touch_driver_t* drv, SDL_Event* event) {
}
break;
- case SDL_MOUSEMOTION:
+ case SDL_EVENT_MOUSE_MOTION:
if (drv->state != IDLE) {
if (inside_display) {
int x = event->motion.x - sdl_touch_offset_x;
@@ -129,9 +129,9 @@ static void handle_mouse_events(touch_driver_t* drv, SDL_Event* event) {
static void handle_button_events(touch_driver_t* drv, SDL_Event* event) {
// Handle arrow buttons to trigger a scroll movement by set length in the
// direction of the button
- if (event->type == SDL_KEYDOWN && !event->key.repeat) {
+ if (event->type == SDL_EVENT_KEY_DOWN && !event->key.repeat) {
if (drv->state != BUTTON_SWIPE_INITIATED) {
- switch (event->key.keysym.sym) {
+ switch (event->key.key) {
case SDLK_LEFT:
drv->swipe_start_x = _btn_swipe_begin;
drv->swipe_start_y = sdl_display_res_y / 2;
@@ -163,14 +163,14 @@ static void handle_button_events(touch_driver_t* drv, SDL_Event* event) {
}
if (drv->state == BUTTON_SWIPE_INITIATED) {
- drv->swipe_key = event->key.keysym.sym;
+ drv->swipe_key = event->key.key;
drv->swipe_time = systick_ms();
drv->last_event =
TOUCH_START | touch_pack_xy(drv->swipe_start_x, drv->swipe_start_y);
}
}
- } else if (event->type == SDL_KEYUP &&
- event->key.keysym.sym == drv->swipe_key) {
+ } else if (event->type == SDL_EVENT_KEY_UP &&
+ event->key.key == drv->swipe_key) {
if (drv->state == BUTTON_SWIPE_INITIATED) {
drv->last_event =
TOUCH_END | touch_pack_xy(drv->swipe_end_x, drv->swipe_end_y);
diff --git a/core/embed/models/T3W1/boards/t3w1-unix.h b/core/embed/models/T3W1/boards/t3w1-unix.h
index 25c78c35..4e2be872 100644
--- a/core/embed/models/T3W1/boards/t3w1-unix.h
+++ b/core/embed/models/T3W1/boards/t3w1-unix.h
@@ -6,7 +6,7 @@
#define TOUCH_OFFSET_X 107
#define TOUCH_OFFSET_Y 53
-#define BTN_POWER_KEY SDLK_p
+#define BTN_POWER_KEY SDLK_P
#define ORIENTATION_NS 1
diff --git a/core/embed/projects/bootloader/emulator.c b/core/embed/projects/bootloader/emulator.c
index 47890be1..46a17c49 100644
--- a/core/embed/projects/bootloader/emulator.c
+++ b/core/embed/projects/bootloader/emulator.c
@@ -1,9 +1,11 @@
+#include <stdlib.h>
+
#include <trezor_model.h>
#include <trezor_rtl.h>
#include <unistd.h>
-#include <SDL.h>
+#include <SDL3/SDL.h>
#include <io/display.h>
#include <sys/bootargs.h>
@@ -106,32 +108,32 @@ bool preload_firmware_image(const char *filename) {
size_t read = fread(fw_buffer, 1, sizeof(fw_buffer), file);
fclose(file);
- flash_area_erase(&FIRMWARE_AREA, NULL);
+ ensure(flash_area_erase(&FIRMWARE_AREA, NULL), NULL);
return sectrue == flash_area_write_data_padded(&FIRMWARE_AREA, 0, fw_buffer,
read, 0x0, FIRMWARE_MAXSIZE);
}
-static int sdl_event_filter(void *userdata, SDL_Event *event) {
+static bool sdl_event_filter(void *userdata, SDL_Event *event) {
switch (event->type) {
- case SDL_QUIT:
+ case SDL_EVENT_QUIT:
exit(3);
- return 0;
- case SDL_KEYUP:
+ return false;
+ case SDL_EVENT_KEY_UP:
if (event->key.repeat) {
- return 0;
+ return false;
}
- switch (event->key.keysym.sym) {
+ switch (event->key.key) {
case SDLK_ESCAPE:
exit(3);
- return 0;
- case SDLK_s:
+ return false;
+ case SDLK_S:
display_save("emu");
- return 0;
+ return false;
}
break;
}
- return 1;
+ return true;
}
int main(int argc, char **argv) {
diff --git a/core/embed/projects/bootloader/main.c b/core/embed/projects/bootloader/main.c
index 70d94a61..67371068 100644
--- a/core/embed/projects/bootloader/main.c
+++ b/core/embed/projects/bootloader/main.c
@@ -110,7 +110,7 @@
#endif
#ifdef TREZOR_EMULATOR
-#include "SDL.h"
+#include "SDL3/SDL.h"
#include "emulator.h"
#endif
diff --git a/core/embed/projects/prodtest/emulator.c b/core/embed/projects/prodtest/emulator.c
index 3db3e016..3be68283 100644
--- a/core/embed/projects/prodtest/emulator.c
+++ b/core/embed/projects/prodtest/emulator.c
@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <unistd.h>
-#include <SDL.h>
+#include <SDL3/SDL.h>
#include <io/display.h>
#include <sys/flash.h>
@@ -28,26 +28,26 @@ void usage(void) {
printf(" -h show this help\n");
}
-static int sdl_event_filter(void *userdata, SDL_Event *event) {
+static bool sdl_event_filter(void *userdata, SDL_Event *event) {
switch (event->type) {
- case SDL_QUIT:
+ case SDL_EVENT_QUIT:
exit(3);
- return 0;
- case SDL_KEYUP:
+ return false;
+ case SDL_EVENT_KEY_UP:
if (event->key.repeat) {
- return 0;
+ return false;
}
- switch (event->key.keysym.sym) {
+ switch (event->key.key) {
case SDLK_ESCAPE:
exit(3);
- return 0;
- case SDLK_s:
+ return false;
+ case SDLK_S:
display_save("emu");
- return 0;
+ return false;
}
break;
}
- return 1;
+ return true;
}
int main(int argc, char **argv) {
diff --git a/core/embed/projects/unix/main_main.c b/core/embed/projects/unix/main_main.c
index 54acdc3c..06bfe73d 100644
--- a/core/embed/projects/unix/main_main.c
+++ b/core/embed/projects/unix/main_main.c
@@ -17,6 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
+
#include <trezor_rtl.h>
#include <io/display.h>
@@ -71,7 +73,7 @@
#include <sec/mcu_attestation.h>
#endif
-#include <SDL.h>
+#include <SDL3/SDL.h>
static void drivers_deinit(void) { flash_deinit(); }
@@ -133,28 +135,28 @@ static void throw_exit_exception(systask_t *task, int code) {
// We are back and the task should be terminated by now
}
-static int sdl_event_filter(void *userdata, SDL_Event *event) {
+static bool sdl_event_filter(void *userdata, SDL_Event *event) {
applet_t *coreapp = (applet_t *)userdata;
switch (event->type) {
- case SDL_QUIT:
+ case SDL_EVENT_QUIT:
throw_exit_exception(&coreapp->task, 0);
- return 0;
- case SDL_KEYUP:
+ return false;
+ case SDL_EVENT_KEY_UP:
if (event->key.repeat) {
- return 0;
+ return false;
}
- switch (event->key.keysym.sym) {
+ switch (event->key.key) {
case SDLK_ESCAPE:
throw_exit_exception(&coreapp->task, 0);
- return 0;
- case SDLK_s:
+ return false;
+ case SDLK_S:
display_save("emu");
- return 0;
+ return false;
}
break;
}
- return 1;
+ return true;
}
// Kernel task main loop
diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs
index 9832efea..9c8aacb5 100644
--- a/core/embed/rust/build.rs
+++ b/core/embed/rust/build.rs
@@ -615,8 +615,8 @@ fn link_core_objects() {
// Compile all the objects into a static library and link it in automatically.
cc.compile("core_lib");
- println!("cargo:rustc-link-lib=SDL2");
- println!("cargo:rustc-link-lib=SDL2_image");
+ println!("cargo:rustc-link-lib=SDL3");
+ println!("cargo:rustc-link-lib=SDL3_image");
#[cfg(any(feature = "ui_jpeg", feature = "hw_jpeg_decoder"))]
println!("cargo:rustc-link-lib=jpeg");
diff --git a/core/embed/sys/task/inc/sys/unix/sdl_event.h b/core/embed/sys/task/inc/sys/unix/sdl_event.h
index ff680903..ae554c5c 100644
--- a/core/embed/sys/task/inc/sys/unix/sdl_event.h
+++ b/core/embed/sys/task/inc/sys/unix/sdl_event.h
@@ -21,7 +21,7 @@
#include <trezor_types.h>
-#include <SDL2/SDL.h>
+#include "SDL3/SDL.h"
// This module provides a modular approach to processing SDL events.
//
diff --git a/core/embed/sys/task/unix/sdl_event.c b/core/embed/sys/task/unix/sdl_event.c
index b6068349..761b10ea 100644
--- a/core/embed/sys/task/unix/sdl_event.c
+++ b/core/embed/sys/task/unix/sdl_event.c
@@ -73,7 +73,7 @@ void sdl_events_poll(void) {
SDL_Event sdl_event;
// Process all pending events
- while (SDL_PollEvent(&sdl_event) > 0) {
+ while (SDL_PollEvent(&sdl_event)) {
for (int index = 0; index < ARRAY_LENGTH(dispatcher->filter); index++) {
sdl_event_filter_t* filter = &dispatcher->filter[index];
if (filter->callback != NULL) {
diff --git a/legacy/Makefile.include b/legacy/Makefile.include
index 600b30cf..6f76bae8 100644
--- a/legacy/Makefile.include
+++ b/legacy/Makefile.include
@@ -116,8 +116,8 @@ LDFLAGS += -L$(TOP_DIR)emulator
LDLIBS += -ltrezor -lemulator
LIBDEPS += $(TOP_DIR)/libtrezor.a $(TOP_DIR)emulator/libemulator.a
-CFLAGS += $(shell pkg-config --cflags sdl2 SDL2_image)
-LDLIBS += $(shell pkg-config --libs sdl2 SDL2_image)
+CFLAGS += $(shell pkg-config --cflags sdl3)
+LDLIBS += $(shell pkg-config --libs sdl3)
else
ifdef APPVER
diff --git a/legacy/emulator/buttons.c b/legacy/emulator/buttons.c
index c30bd2cf..82815fb5 100644
--- a/legacy/emulator/buttons.c
+++ b/legacy/emulator/buttons.c
@@ -19,12 +19,12 @@
#include "buttons.h"
-#include <SDL.h>
+#include <SDL3/SDL.h>
uint16_t buttonRead(void) {
uint16_t state = 0;
- const uint8_t *scancodes = SDL_GetKeyboardState(NULL);
+ const bool *scancodes = SDL_GetKeyboardState(NULL);
if (scancodes[SDL_SCANCODE_LEFT]) {
state |= BTN_PIN_NO;
}
diff --git a/legacy/emulator/oled.c b/legacy/emulator/oled.c
index 5f6b2647..7466b675 100644
--- a/legacy/emulator/oled.c
+++ b/legacy/emulator/oled.c
@@ -19,11 +19,12 @@
#include "oled.h"
-#include <SDL.h>
+#include <SDL3/SDL.h>
+#include <stdlib.h>
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
-static SDL_Rect dstrect;
+static SDL_FRect dstrect;
#define ENV_OLED_FULLSCREEN "TREZOR_OLED_FULLSCREEN"
#define ENV_OLED_SCALE "TREZOR_OLED_SCALE"
@@ -49,7 +50,7 @@ static int emulatorScale(void) {
}
void oledInit(void) {
- if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+ if (!SDL_Init(SDL_INIT_VIDEO)) {
fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError());
exit(1);
}
@@ -58,42 +59,42 @@ void oledInit(void) {
int scale = emulatorScale();
int fullscreen = emulatorFullscreen();
- SDL_Window *window = SDL_CreateWindow(
- "Trezor^emu", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
- OLED_WIDTH * scale, OLED_HEIGHT * scale,
- fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
+ SDL_Window *window =
+ SDL_CreateWindow("Trezor^emu", OLED_WIDTH * scale, OLED_HEIGHT * scale,
+ fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
if (window == NULL) {
fprintf(stderr, "Failed to create window: %s\n", SDL_GetError());
exit(1);
}
- renderer = SDL_CreateRenderer(window, -1, 0);
+ renderer = SDL_CreateRenderer(window, NULL);
if (!renderer) {
fprintf(stderr, "Failed to create renderer: %s\n", SDL_GetError());
exit(1);
}
if (fullscreen) {
- SDL_DisplayMode current_mode;
- if (SDL_GetCurrentDisplayMode(0, ¤t_mode) != 0) {
+ SDL_DisplayID display = SDL_GetPrimaryDisplay();
+ const SDL_DisplayMode *current_mode = SDL_GetCurrentDisplayMode(display);
+ if (!current_mode) {
fprintf(stderr, "Failed to get current display mode: %s\n",
SDL_GetError());
exit(1);
}
- dstrect.x = (current_mode.w - OLED_WIDTH * scale) / 2;
- dstrect.y = (current_mode.h - OLED_HEIGHT * scale) / 2;
+ dstrect.x = (current_mode->w - OLED_WIDTH * scale) / 2.0f;
+ dstrect.y = (current_mode->h - OLED_HEIGHT * scale) / 2.0f;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
- SDL_ShowCursor(SDL_DISABLE);
+ SDL_HideCursor();
} else {
dstrect.x = 0;
dstrect.y = 0;
}
- dstrect.w = OLED_WIDTH * scale;
- dstrect.h = OLED_HEIGHT * scale;
+ dstrect.w = (float)(OLED_WIDTH * scale);
+ dstrect.h = (float)(OLED_HEIGHT * scale);
texture =
SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
@@ -122,7 +123,7 @@ void oledRefresh(void) {
}
SDL_UpdateTexture(texture, NULL, data, OLED_WIDTH * sizeof(uint32_t));
- SDL_RenderCopy(renderer, texture, NULL, &dstrect);
+ SDL_RenderTexture(renderer, texture, NULL, &dstrect);
SDL_RenderPresent(renderer);
/* Return it back */
@@ -133,7 +134,7 @@ void emulatorPoll(void) {
SDL_Event event;
if (SDL_PollEvent(&event)) {
- if (event.type == SDL_QUIT) {
+ if (event.type == SDL_EVENT_QUIT) {
exit(1);
}
}
diff --git a/shell.nix b/shell.nix
index 5250c715..d92fd338 100644
--- a/shell.nix
+++ b/shell.nix
@@ -76,6 +76,7 @@ in
with nixpkgs;
stdenvNoCC.mkDerivation ({
name = "trezor-firmware-env";
+ nativeBuildInputs = lib.optionals (!stdenv.isDarwin) [ autoPatchelfHook ];
buildInputs = lib.optionals fullDeps [
bitcoind
] ++ [
@@ -83,6 +84,8 @@ stdenvNoCC.mkDerivation ({
# crash with SDL_CreateRenderer error.
oldNixpkgs.SDL2
oldNixpkgs.SDL2_image
+ sdl3
+ sdl3-image
bash
bloaty # for binsize
cargo-audit
@@ -114,7 +117,6 @@ stdenvNoCC.mkDerivation ({
zlib
moreutils
] ++ lib.optionals (!stdenv.isDarwin) [
- autoPatchelfHook
procps
valgrind
] ++ lib.optionals (stdenv.isDarwin) [
@@ -137,7 +139,12 @@ stdenvNoCC.mkDerivation ({
nrfutil
nrfconnect
];
- LD_LIBRARY_PATH = "${libffi}/lib:${libjpeg.out}/lib:${libusb1}/lib:${libressl.out}/lib";
+ LD_LIBRARY_PATH = lib.makeLibraryPath [
+ libffi
+ libjpeg
+ libusb1
+ libressl
+ ];
DYLD_LIBRARY_PATH = "${libffi}/lib:${libjpeg.out}/lib:${libusb1}/lib:${libressl.out}/lib";
NIX_ENFORCE_PURITY = 0;
Why this scored 20/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.