WIP: port renderer + supporting layers to SDL 3 (builds clean)

Completes phases 3-6 of the migration plan. After this commit, the
codebase compiles and links against pure SDL 3 (no compat shim). The
binary is unverified at runtime but the build is clean.

Renderer (graphics/gfxengine.{cpp,h}):
- Replace SDL_SetVideoMode + SDL_Flip + page-flip machinery with
  SDL_CreateWindow + SDL_CreateRenderer + a streaming SDL_Texture.
  The CPU-side back buffer (softbuf) is now always ARGB8888; legacy
  HW/double-buffer/page flags are dead.
- flip() does a single full-frame SDL_UpdateTexture + SDL_RenderClear
  + SDL_RenderTexture + SDL_RenderPresent each frame. The dirtyrect
  iteration is retained only to drive widget phys_refresh() callbacks.
- SDL_SetRenderLogicalPresentation gives us letterbox scaling for free.
- SDL_SetRenderVSync replaces glSDL_VSync.
- title()/cursor() ported to SDL 3 window/cursor APIs.

Surface API (graphics/sprite.c, filters.c, window.cpp, sofont.cpp,
region.c):
- SDL_FreeSurface → SDL_DestroySurface
- SDL_FillRect → SDL_FillSurfaceRect
- SDL_SetClipRect → SDL_SetSurfaceClipRect
- SDL_SetColorKey(s, flags, key) → SDL_SetSurfaceColorKey(s, bool, key)
- SDL_SetAlpha(s, flags, a) → SDL_SetSurfaceAlphaMod + BlendMode
- SDL_SetColors → SDL_SetSurfacePalette
- SDL_CreateRGBSurface(...) → SDL_CreateSurface(w, h, format_enum)
- SDL_DisplayFormat[Alpha] → SDL_ConvertSurface(s, ARGB8888)
- SDL_MapRGB(surf->format, ...) → SDL_MapSurfaceRGB(surf, ...)
- surface->format->Field → SDL_GetPixelFormatDetails(surf->format)->field
- surface->format->Amask test → SDL_ISPIXELFORMAT_ALPHA
- surface->clip_rect → SDL_GetSurfaceClipRect

Events (kobo.cpp):
- SDL_{KEYDOWN,KEYUP,QUIT,VIDEOEXPOSE,MOUSE*,JOY*} → SDL_EVENT_*
- SDL_ACTIVEEVENT (with gain check) → SDL_EVENT_WINDOW_FOCUS_LOST
- ev.key.keysym.sym → ev.key.key (.unicode → text input, deferred)
- SDLK_PRINT/SYSREQ → SDLK_PRINTSCREEN; lowercase SDLK_p/y/n → uppercase
- ev.motion.x/y for button events → ev.button.x/y (struct layout differs)
- KMOD_META → SDL_KMOD_GUI
- SDL_INIT_NOPARACHUTE → SDL_Init(0) (no parachute by default in SDL 3)

Keymap (gamectl.{cpp,h}):
- SDLKey → SDL_Keycode
- SDLK_KP{1..9} → SDLK_KP_{1..9}

Stubs deferred for later phases (binary will run but with degraded
behavior):
- sound/audio.c: _start_SDL_output returns -1 immediately; SDL 1.2
  audio callback model needs full rewrite onto SDL_AudioStream.
- kobo.cpp init_js/close_js: SDL 3 joystick API uses instance IDs;
  re-port deferred.
- states.cpp SDL_WM_GrabInput/SDL_EnableUNICODE: need window pointer
  exposed from gfxengine; stubbed.
- gamectl.cpp SDL_EnableKeyRepeat: removed; relies on ev.key.repeat.

Other adjustments:
- options.cpp: GFX_DRIVER_GLSDL menu paths removed; show vsync option
  always (renderer handles it).
- sound/a_wave.c: AUDIO_S8/AUDIO_S16SYS → SDL_AUDIO_S8/S16, SDL_FreeWAV
  → SDL_free.
- gfxengine.cpp: SDL_putenv("SDL_VIDEO_CENTERED=1") obsolete (handled
  by SDL_CreateWindow defaults).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ville Lindholm 2026-05-28 21:54:55 +03:00
parent 762b095462
commit f11b6516da
No known key found for this signature in database
GPG Key ID: 89AE9EAA3B6FDE7C
15 changed files with 378 additions and 386 deletions

View File

@ -54,7 +54,10 @@ void gamecontrol_t::init(int always_fire)
down = 0;
shot = 0;
movekey_pressed = 0;
SDL_EnableKeyRepeat(r_delay, r_interval);
// SDL 3 removed SDL_EnableKeyRepeat; OS-level key repeat fires
// SDL_EVENT_KEY_DOWN with ev.key.repeat set. r_delay/r_interval
// retained in case we re-implement software repeat later.
(void)r_delay; (void)r_interval;
}
@ -68,9 +71,8 @@ void gamecontrol_t::repeat(int delay, int interval)
{
r_delay = delay;
r_interval = interval;
//Temporary kludge - should apply repeat to
//all switch inputs, not just the keyboard!
SDL_EnableKeyRepeat(delay, interval);
// SDL_EnableKeyRepeat is gone in SDL 3. Stored for future
// software-side repeat handling.
}
@ -80,7 +82,7 @@ void gamecontrol_t::clear()
}
int gamecontrol_t::map(SDLKey sym)
int gamecontrol_t::map(SDL_Keycode sym)
{
/*
FIXME: This should be replaced by a configurable mapping system.
@ -137,7 +139,7 @@ FIXME: This should be replaced by a configurable mapping system.
case SDLK_ESCAPE:
return BTN_EXIT;
case SDLK_PAUSE:
case SDLK_p:
case SDLK_P:
return BTN_PAUSE;
case SDLK_SPACE:
return BTN_START;
@ -148,9 +150,9 @@ FIXME: This should be replaced by a configurable mapping system.
return BTN_INC;
case SDLK_KP_MINUS:
return BTN_DEC;
case SDLK_y:
case SDLK_Y:
return BTN_YES;
case SDLK_n:
case SDLK_N:
return BTN_NO;
case SDLK_BACKSPACE:
return BTN_BACK;

View File

@ -26,14 +26,14 @@
#include "sdl_compat.h"
#include "config.h"
#define KEY_KP_DOWN SDLK_KP2
#define KEY_KP_LEFT SDLK_KP4
#define KEY_KP_UP SDLK_KP8
#define KEY_KP_RIGHT SDLK_KP6
#define KEY_KP_DL SDLK_KP1
#define KEY_KP_DR SDLK_KP3
#define KEY_KP_UL SDLK_KP7
#define KEY_KP_UR SDLK_KP9
#define KEY_KP_DOWN SDLK_KP_2
#define KEY_KP_LEFT SDLK_KP_4
#define KEY_KP_UP SDLK_KP_8
#define KEY_KP_RIGHT SDLK_KP_6
#define KEY_KP_DL SDLK_KP_1
#define KEY_KP_DR SDLK_KP_3
#define KEY_KP_UL SDLK_KP_7
#define KEY_KP_UR SDLK_KP_9
enum buttons_t
@ -105,7 +105,7 @@ class gamecontrol_t
static void init(int always_fire);
static void repeat(int delay, int interval);
static void clear();
static int map(SDLKey sym);
static int map(SDL_Keycode sym);
static void process(); // Call every frame!
static void press(int k);
static void release(int k);

View File

@ -235,33 +235,17 @@ int s_filter_rgba8(s_bank_t *b, unsigned first, unsigned frames,
s_filter_args_t *args)
{
unsigned i;
SDL_PixelFormat fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.BitsPerPixel = 32;
fmt.BytesPerPixel = 4;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
fmt.Rmask = 0xff000000;
fmt.Gmask = 0x00ff0000;
fmt.Bmask = 0x0000ff00;
fmt.Amask = 0x000000ff;
#else
fmt.Rmask = 0x000000ff;
fmt.Gmask = 0x0000ff00;
fmt.Bmask = 0x00ff0000;
fmt.Amask = 0xff000000;
#endif
for(i = 0; i < frames; ++i)
{
SDL_Surface *tmp;
s_sprite_t *s = s_get_sprite_b(b, first+i);
if(!s)
continue;
tmp = SDL_ConvertSurface(s->surface, &fmt,
SDL_SWSURFACE);
tmp = SDL_ConvertSurface(s->surface, SDL_PIXELFORMAT_RGBA32);
if(!tmp)
return -1;
SDL_FreeSurface(s->surface);
SDL_DestroySurface(s->surface);
s->surface = tmp;
}
return 0;
@ -289,7 +273,7 @@ int s_filter_dither(s_bank_t *b, unsigned first, unsigned frames,
switch (s_blitmode)
{
case S_BLITMODE_AUTO:
if(s->surface->format->Amask)
if(SDL_ISPIXELFORMAT_ALPHA(s->surface->format))
ar = ag = ab = 8;
break;
case S_BLITMODE_OPAQUE:
@ -458,7 +442,8 @@ int s_filter_dither(s_bank_t *b, unsigned first, unsigned frames,
static void tweak_ck(SDL_Surface *s)
{
int x, y;
if(s->format->BitsPerPixel != 32)
const SDL_PixelFormatDetails *fmt = SDL_GetPixelFormatDetails(s->format);
if(!fmt || fmt->bits_per_pixel != 32)
return;
for(y = 0; y < s->h; ++y)
{
@ -488,53 +473,54 @@ int s_filter_displayformat(s_bank_t * b, unsigned first, unsigned frames,
switch(s_blitmode)
{
case S_BLITMODE_AUTO:
if(s->surface->format->Amask)
SDL_SetAlpha(s->surface,
SDL_SRCALPHA |
SDL_RLEACCEL,
if(SDL_ISPIXELFORMAT_ALPHA(s->surface->format))
{
SDL_SetSurfaceAlphaMod(s->surface,
SDL_ALPHA_OPAQUE);
SDL_SetSurfaceBlendMode(s->surface,
SDL_BLENDMODE_BLEND);
}
else
SDL_SetColorKey(s->surface, SDL_RLEACCEL, 0);
SDL_SetSurfaceColorKey(s->surface, false, 0);
break;
case S_BLITMODE_OPAQUE:
SDL_SetColorKey(s->surface, SDL_RLEACCEL, 0);
SDL_SetSurfaceColorKey(s->surface, false, 0);
break;
case S_BLITMODE_COLORKEY:
SDL_SetColorKey(s->surface,
SDL_SRCCOLORKEY | SDL_RLEACCEL,
SDL_MapRGB(s->surface->format,
SDL_SetSurfaceColorKey(s->surface, true,
SDL_MapSurfaceRGB(s->surface,
s_colorkey.r,
s_colorkey.g,
s_colorkey.b));
break;
case S_BLITMODE_ALPHA:
SDL_SetAlpha(s->surface,
SDL_SRCALPHA | SDL_RLEACCEL,
s_alpha);
SDL_SetSurfaceAlphaMod(s->surface, s_alpha);
SDL_SetSurfaceBlendMode(s->surface,
SDL_BLENDMODE_BLEND);
break;
}
// SDL 3 dropped SDL_DisplayFormat. We always convert sprites
// to the back-buffer format (ARGB8888); see gfxengine.cpp.
if(args->x)
{
if(s->surface->format->Amask)
if(SDL_ISPIXELFORMAT_ALPHA(s->surface->format))
tweak_ck(s->surface);
tmp = SDL_DisplayFormat(s->surface);
if(s->surface->format->Amask)
SDL_SetColorKey(tmp,
SDL_SRCCOLORKEY | SDL_RLEACCEL,
SDL_MapRGB(tmp->format, 0,0,0));
tmp = SDL_ConvertSurface(s->surface,
SDL_PIXELFORMAT_ARGB8888);
if(tmp && SDL_ISPIXELFORMAT_ALPHA(s->surface->format))
SDL_SetSurfaceColorKey(tmp, true,
SDL_MapSurfaceRGB(tmp, 0,0,0));
}
else
{
if(s->surface->format->Amask)
tmp = SDL_DisplayFormatAlpha(s->surface);
else
tmp = SDL_DisplayFormat(s->surface);
tmp = SDL_ConvertSurface(s->surface,
SDL_PIXELFORMAT_ARGB8888);
}
if(!tmp)
return -1;
SDL_FreeSurface(s->surface);
SDL_DestroySurface(s->surface);
s->surface = tmp;
}
return 0;
@ -900,18 +886,13 @@ int s_filter_scale(s_bank_t *b, unsigned first, unsigned frames,
if(!s)
continue;
params.src = s->surface;
params.dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
params.max_x, params.max_y, 32,
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
#else
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
#endif
params.dst = SDL_CreateSurface(params.max_x, params.max_y,
SDL_PIXELFORMAT_RGBA32);
if(!params.dst)
return -1;
#ifdef DEBUG
SDL_FillRect(params.dst, NULL,
SDL_MapRGB(params.dst->format, 255, 128, 0));
SDL_FillSurfaceRect(params.dst, NULL,
SDL_MapSurfaceRGB(params.dst, 255, 128, 0));
#endif
/* Deal with SFont marker row */
@ -957,7 +938,7 @@ int s_filter_scale(s_bank_t *b, unsigned first, unsigned frames,
break;
}
SDL_FreeSurface(s->surface);
SDL_DestroySurface(s->surface);
s->surface = params.dst;
}
b->w = params.max_x;

View File

@ -40,6 +40,9 @@ gfxengine_t::gfxengine_t()
{
gfxengine = this; /* Uurgh! Kludge. */
sdl_window = NULL;
sdl_renderer = NULL;
fb_texture = NULL;
screen_surface = NULL;
softbuf = NULL;
fullwin = NULL;
@ -443,10 +446,13 @@ void gfxengine_t::dither(int type, int _broken_rgba8)
if(_dither)
{
// SDL 3: back buffer is always ARGB8888 (8 bits per channel,
// no loss). The legacy formula was 1 << (Rloss - 1); for 8 bpc
// the dithering amplitude collapses to 0.
df->args.x = 0;
df->args.r = 1<<(screen_surface->format->Rloss-1);
df->args.g = 1<<(screen_surface->format->Gloss-1);
df->args.b = 1<<(screen_surface->format->Bloss-1);
df->args.r = 0;
df->args.g = 0;
df->args.b = 0;
}
else
df->args.x = df->args.r = df->args.g = df->args.b = 0;
@ -732,8 +738,8 @@ void gfxengine_t::title(const char *win, const char *icon)
{
_title = win;
_icontitle = icon;
if(screen_surface)
SDL_WM_SetCaption(_title, _icontitle);
if(sdl_window)
SDL_SetWindowTitle(sdl_window, _title);
}
@ -743,97 +749,94 @@ void gfxengine_t::title(const char *win, const char *icon)
int gfxengine_t::show()
{
int flags = 0;
if(!is_open)
return -1;
if(is_showing)
return 0;
if(_centered && !_fullscreen)
SDL_putenv((char *)"SDL_VIDEO_CENTERED=1");
log_printf(DLOG, "Opening screen...\n");
if(!SDL_WasInit(SDL_INIT_VIDEO))
if(SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
if(!SDL_InitSubSystem(SDL_INIT_VIDEO))
{
log_printf(ELOG, "Failed to initialize SDL!\n");
log_printf(ELOG, "Failed to initialize SDL: %s\n",
SDL_GetError());
return -2;
}
if(_doublebuf)
flags |= SDL_DOUBLEBUF | SDL_HWSURFACE;
else
{
if(!_shadow)
flags |= SDL_HWSURFACE;
}
// SDL 3 window + renderer model.
//
// The kobo engine renders into a CPU-side back buffer (softbuf) via
// SDL_BlitSurface/SDL_FillSurfaceRect, and uploads the result to a
// streaming SDL_Texture once per frame. This preserves the entire
// software-compositing code path inherited from SDL 1.2 (window.cpp,
// sprite.c, filters.c, sofont.cpp), while letting the GPU handle
// scaling and presentation. SDL_DOUBLEBUF / SDL_HWSURFACE / page-
// flipping flags are obsolete and ignored.
Uint64 win_flags = 0;
if(_fullscreen)
flags |= SDL_FULLSCREEN;
win_flags |= SDL_WINDOW_FULLSCREEN;
flags |= xflags;
screen_surface = SDL_SetVideoMode(_width, _height, _depth, flags);
if(!screen_surface)
sdl_window = SDL_CreateWindow(_title ? _title : "Kobo Deluxe",
_width, _height, win_flags);
if(!sdl_window)
{
log_printf(ELOG, "Failed to open display!\n");
log_printf(ELOG, "Failed to open window: %s\n", SDL_GetError());
return -3;
}
if((screen_surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
sdl_renderer = SDL_CreateRenderer(sdl_window, NULL);
if(!sdl_renderer)
{
if(!_doublebuf)
{
log_printf(WLOG, "Could not get"
" single buffered display.\n");
doublebuffer(1);
}
}
else
{
if(_doublebuf)
{
log_printf(WLOG, "Could not get"
" double buffered display.\n");
doublebuffer(0);
}
log_printf(ELOG, "Failed to create renderer: %s\n",
SDL_GetError());
SDL_DestroyWindow(sdl_window);
sdl_window = NULL;
return -4;
}
if((screen_surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE)
{
if(_shadow)
{
softbuf = SDL_CreateRGBSurface(SDL_SWSURFACE,
_width, _height,
screen_surface->format->BitsPerPixel,
screen_surface->format->Rmask,
screen_surface->format->Gmask,
screen_surface->format->Bmask,
screen_surface->format->Amask);
if(!softbuf)
{
log_printf(WLOG, "Failed to create shadow buffer! "
"Trying direct rendering.\n");
shadow(0);
}
}
}
else
{
if(_shadow)
log_printf(WLOG, "Shadow buffer requested; "
"relying on SDL's shadow buffer.\n");
else
{
log_printf(WLOG, "Could not get h/w display surface.\n");
shadow(0); //...which means we're using SDL's shadow.
}
}
// Letterbox the back buffer when the window is resized / fullscreen.
SDL_SetRenderLogicalPresentation(sdl_renderer, _width, _height,
SDL_LOGICAL_PRESENTATION_LETTERBOX);
SDL_SetRenderVSync(sdl_renderer, _vsync ? 1 : 0);
// The back buffer is always a CPU-side ARGB8888 surface.
softbuf = SDL_CreateSurface(_width, _height, SDL_PIXELFORMAT_ARGB8888);
if(!softbuf)
{
log_printf(ELOG, "Failed to create back buffer: %s\n",
SDL_GetError());
SDL_DestroyRenderer(sdl_renderer);
SDL_DestroyWindow(sdl_window);
sdl_renderer = NULL;
sdl_window = NULL;
return -5;
}
screen_surface = softbuf; // alias for legacy code paths
fb_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, _width, _height);
if(!fb_texture)
{
log_printf(ELOG, "Failed to create framebuffer texture: %s\n",
SDL_GetError());
SDL_DestroySurface(softbuf);
SDL_DestroyRenderer(sdl_renderer);
SDL_DestroyWindow(sdl_window);
softbuf = screen_surface = NULL;
sdl_renderer = NULL;
sdl_window = NULL;
return -6;
}
SDL_SetTextureScaleMode(fb_texture,
(_scalemode == GFX_SCALE_NEAREST) ?
SDL_SCALEMODE_NEAREST : SDL_SCALEMODE_LINEAR);
if(_cursor)
SDL_ShowCursor();
else
SDL_HideCursor();
SDL_WM_SetCaption(_title, _icontitle);
SDL_ShowCursor(_cursor);
cs_engine_set_size(csengine, _width, _height);
csengine->filter = use_interpolation;
@ -886,12 +889,27 @@ void gfxengine_t::hide(void)
w = w->next;
}
if(fb_texture)
{
SDL_DestroyTexture(fb_texture);
fb_texture = NULL;
}
if(softbuf)
{
SDL_FreeSurface(softbuf);
SDL_DestroySurface(softbuf);
softbuf = NULL;
}
screen_surface = NULL;
if(sdl_renderer)
{
SDL_DestroyRenderer(sdl_renderer);
sdl_renderer = NULL;
}
if(sdl_window)
{
SDL_DestroyWindow(sdl_window);
sdl_window = NULL;
}
is_showing = 0;
}
@ -940,13 +958,15 @@ void gfxengine_t::__invalidate(int page, SDL_Rect *rect, window_t *window)
/* Clip to screen (stolen from SDL_surface.c) */
SDL_Rect dr = *rect;
SDL_Rect screen_clip;
SDL_GetSurfaceClipRect(screen_surface, &screen_clip);
int Amin, Amax, Bmin, Bmax;
/* Horizontal intersection */
Amin = dr.x;
Amax = Amin + dr.w;
Bmin = screen_surface->clip_rect.x;
Bmax = Bmin + screen_surface->clip_rect.w;
Bmin = screen_clip.x;
Bmax = Bmin + screen_clip.w;
if(Bmin > Amin)
Amin = Bmin;
dr.x = Amin;
@ -957,8 +977,8 @@ void gfxengine_t::__invalidate(int page, SDL_Rect *rect, window_t *window)
/* Vertical intersection */
Amin = dr.y;
Amax = Amin + dr.h;
Bmin = screen_surface->clip_rect.y;
Bmax = Bmin + screen_surface->clip_rect.h;
Bmin = screen_clip.y;
Bmax = Bmin + screen_clip.h;
if(Bmin > Amin)
Amin = Bmin;
dr.y = Amin;
@ -1062,7 +1082,12 @@ void gfxengine_t::cursor(int csr)
{
_cursor = csr;
if(screen_surface)
SDL_ShowCursor(csr);
{
if(csr)
SDL_ShowCursor();
else
SDL_HideCursor();
}
}
@ -1168,8 +1193,8 @@ void gfxengine_t::frame()
SDL_Event ev;
while(SDL_PollEvent(&ev))
{
if(ev.type == SDL_KEYDOWN)
if(ev.key.keysym.sym == SDLK_ESCAPE)
if(ev.type == SDL_EVENT_KEY_DOWN)
if(ev.key.key == SDLK_ESCAPE)
stop();
}
}
@ -1236,41 +1261,15 @@ void gfxengine_t::refresh_rect(SDL_Rect *r)
void gfxengine_t::flip()
{
if(!screen_surface)
if(!screen_surface || !sdl_renderer || !fb_texture)
return;
// Init dirtyrect table flipping, if necessary.
switch(_pages)
{
case -1:
if(!_doublebuf)
frontpage = backpage = 0;
else if(frontpage == backpage)
{
frontpage = 0;
backpage = 1;
}
break;
case 0:
frontpage = backpage = 0;
invalidate();
break;
case 1:
frontpage = backpage = 0;
break;
case 2:
case 3:
if(frontpage == backpage)
{
frontpage = 0;
backpage = 1;
}
break;
}
// Process the dirtyrects.
int i;
for(i = 0; i < dirtyrects[backpage]; ++i)
// SDL 3 has no hardware page flipping; we always present one back
// buffer per frame. Keep the dirtyrect iteration only to drive the
// phys_refresh() callbacks that window widgets rely on; the upload
// is a single full-surface copy regardless.
frontpage = backpage = 0;
for(int i = 0; i < dirtyrects[backpage]; ++i)
{
if(dirtywtable[backpage][i])
{
@ -1282,36 +1281,12 @@ void gfxengine_t::flip()
else
refresh_rect(&dirtytable[backpage][i]);
}
dirtyrects[backpage] = 0;
// Perform the actual flip or update
if(_shadow)
{
for(i = 0; i < dirtyrects[backpage]; ++i)
SDL_BlitSurface(softbuf,
&dirtytable[backpage][i],
screen_surface,
&dirtytable[backpage][i]);
}
if(_doublebuf)
{
dirtyrects[backpage] = 0;
if(_pages == -1)
{
backpage = !backpage;
frontpage = !frontpage;
}
else if(_pages > 1)
{
backpage = (backpage + 1) % _pages;
frontpage = (frontpage + 1) % _pages;
}
SDL_Flip(screen_surface);
}
else
{
SDL_UpdateRects(screen_surface, dirtyrects[0], dirtytable[0]);
dirtyrects[0] = 0;
}
SDL_UpdateTexture(fb_texture, NULL, softbuf->pixels, softbuf->pitch);
SDL_RenderClear(sdl_renderer);
SDL_RenderTexture(sdl_renderer, fb_texture, NULL, NULL);
SDL_RenderPresent(sdl_renderer);
}

View File

@ -208,7 +208,10 @@ class gfxengine_t
gfx_drivers_t _driver;
gfx_scalemodes_t _scalemode;
int _clamping;
SDL_Surface *screen_surface;
SDL_Window *sdl_window;
SDL_Renderer *sdl_renderer;
SDL_Texture *fb_texture;
SDL_Surface *screen_surface; // alias for softbuf in SDL 3
SDL_Surface *softbuf;
int backpage;
int frontpage;

View File

@ -44,7 +44,9 @@ static Uint32 gp2(SDL_Surface *surface, int x, int y)
static Uint32 gp3(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
const SDL_PixelFormatDetails *fmt =
SDL_GetPixelFormatDetails(surface->format);
int bpp = fmt ? fmt->bytes_per_pixel : 3;
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
@ -74,7 +76,14 @@ RGN_region *RGN_ScanMask(SDL_Surface *src, Uint32 key)
RGN_FreeRegion(rgn);
return NULL;
}
switch(src->format->BytesPerPixel)
const SDL_PixelFormatDetails *src_fmt =
SDL_GetPixelFormatDetails(src->format);
if(!src_fmt)
{
RGN_FreeRegion(rgn);
return NULL;
}
switch(src_fmt->bytes_per_pixel)
{
case 1:
gp = gp1;

View File

@ -20,7 +20,7 @@ SoFont::SoFont()
SoFont::~SoFont()
{
if(picture)
SDL_FreeSurface(picture);
SDL_DestroySurface(picture);
delete[]CharPos;
delete[]CharOffset;
delete[]Spacing;
@ -45,7 +45,11 @@ namespace SoFontUtilities
return 0;
}
Bpp = Surface->format->BytesPerPixel;
const SDL_PixelFormatDetails *fmt =
SDL_GetPixelFormatDetails(Surface->format);
if(!fmt)
return 0;
Bpp = fmt->bytes_per_pixel;
bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch +
X * Bpp;
@ -63,10 +67,10 @@ namespace SoFontUtilities
case 3:
// Format/endian independent
Uint8 r, g, b;
r = *((bits) + Surface->format->Rshift / 8);
g = *((bits) + Surface->format->Gshift / 8);
b = *((bits) + Surface->format->Bshift / 8);
return SDL_MapRGB(Surface->format, r, g, b);
r = *((bits) + fmt->Rshift / 8);
g = *((bits) + fmt->Gshift / 8);
b = *((bits) + fmt->Bshift / 8);
return SDL_MapSurfaceRGB(Surface, r, g, b);
break;
case 4:
return *((Uint32 *) Surface->pixels +
@ -94,7 +98,11 @@ namespace SoFontUtilities
return;
}
Bpp = Surface->format->BytesPerPixel;
const SDL_PixelFormatDetails *fmt =
SDL_GetPixelFormatDetails(Surface->format);
if(!fmt)
return;
Bpp = fmt->bytes_per_pixel;
bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch +
X * Bpp;
@ -113,10 +121,11 @@ namespace SoFontUtilities
case 3:
// Format/endian independent
Uint8 r, g, b;
SDL_GetRGB(c, Surface->format, &r, &g, &b);
*((bits) + Surface->format->Rshift / 8) = r;
*((bits) + Surface->format->Gshift / 8) = g;
*((bits) + Surface->format->Bshift / 8) = b;
SDL_GetRGB(c, fmt, SDL_GetSurfacePalette(Surface),
&r, &g, &b);
*((bits) + fmt->Rshift / 8) = r;
*((bits) + fmt->Gshift / 8) = g;
*((bits) + fmt->Bshift / 8) = b;
break;
case 4:
*((Uint32 *) Surface->pixels +
@ -224,7 +233,7 @@ bool SoFont::DoStartNewChar(Sint32 x)
if(!picture)
return false;
return SoFontGetPixel(picture, x, 0) ==
SDL_MapRGB(picture->format, 255, 0, 255);
SDL_MapSurfaceRGB(picture, 255, 0, 255);
}
void SoFont::CleanSurface()
@ -233,7 +242,7 @@ void SoFont::CleanSurface()
return;
int x = 0, y = 0;
Uint32 pix = SDL_MapRGB(picture->format, 255, 0, 255);
Uint32 pix = SDL_MapSurfaceRGB(picture, 255, 0, 255);
while(x < picture->w)
{
@ -259,7 +268,7 @@ bool SoFont::load(SDL_Surface * FontSurface)
return false;
}
if(picture)
SDL_FreeSurface(picture);
SDL_DestroySurface(picture);
picture = FontSurface;
height = picture->h - 1;
while(x < picture->w)
@ -499,8 +508,10 @@ void SoFont::CenteredString(SDL_Surface * Surface, const char *text,
{
if(!picture)
return;
CenteredString(Surface, Surface->clip_rect.w / 2,
Surface->clip_rect.h / 2, text, clip);
SDL_Rect surf_clip;
SDL_GetSurfaceClipRect(Surface, &surf_clip);
CenteredString(Surface, surf_clip.w / 2,
surf_clip.h / 2, text, clip);
}
void SoFont::PutStringCleverCursor(SDL_Surface * Surface, const char *text,

View File

@ -177,7 +177,7 @@ s_sprite_t *s_new_sprite_b(s_bank_t *b, unsigned frame)
else
{
if(s->surface)
SDL_FreeSurface(s->surface);
SDL_DestroySurface(s->surface);
s->surface = NULL;
}
return s;
@ -212,7 +212,7 @@ void s_delete_sprite_b(s_bank_t *b, unsigned frame)
if(!b->sprites[frame])
return;
if(b->sprites[frame]->surface)
SDL_FreeSurface(b->sprites[frame]->surface);
SDL_DestroySurface(b->sprites[frame]->surface);
b->sprites[frame]->surface = NULL;
free(b->sprites[frame]);
b->sprites[frame] = NULL;
@ -355,44 +355,51 @@ static int extract_sprite(s_bank_t *bank, unsigned frame,
if(!s_new_sprite_b(bank, frame))
return -2;
tmp = SDL_CreateRGBSurface(src->flags,
from->w, from->h,
src->format->BitsPerPixel,
src->format->Rmask,
src->format->Gmask,
src->format->Bmask,
src->format->Amask );
const SDL_PixelFormatDetails *src_fmt =
SDL_GetPixelFormatDetails(src->format);
if(!src_fmt)
return -3;
tmp = SDL_CreateSurface(from->w, from->h, src->format);
if(!tmp)
return -3;
/* Copy the pixel data */
if(SDL_LockSurface(src) < 0)
if(!SDL_LockSurface(src))
{
log_printf(ELOG, "sprite: extract_sprite() failed to lock surface!\n");
SDL_FreeSurface(tmp);
SDL_DestroySurface(tmp);
return -4;
}
for(y = 0; y < tmp->h; ++y)
{
char *s = (char *)src->pixels + src->pitch * (y + from->y) +
from->x * src->format->BytesPerPixel;
from->x * src_fmt->bytes_per_pixel;
char *d = (char *)tmp->pixels + tmp->pitch * y;
memcpy(d, s, src->format->BytesPerPixel * tmp->w);
memcpy(d, s, src_fmt->bytes_per_pixel * tmp->w);
}
SDL_UnlockSurface(src);
/* Copy palette, if any */
if(src->format->palette)
SDL_SetColors(tmp, src->format->palette->colors, 0,
src->format->palette->ncolors);
SDL_Palette *src_palette = SDL_GetSurfacePalette(src);
if(src_palette)
SDL_SetSurfacePalette(tmp, src_palette);
/* Copy alpha and colorkey */
if(src->flags & SDL_SRCALPHA)
SDL_SetAlpha(tmp, src->flags & (SDL_SRCALPHA | SDL_RLEACCEL),
src->format->alpha);
if(src->flags & SDL_SRCCOLORKEY)
SDL_SetColorKey(tmp, src->flags & (SDL_SRCCOLORKEY | SDL_RLEACCEL),
src->format->colorkey);
/* Copy alpha modulation and blend mode */
Uint8 src_alpha = SDL_ALPHA_OPAQUE;
SDL_GetSurfaceAlphaMod(src, &src_alpha);
SDL_SetSurfaceAlphaMod(tmp, src_alpha);
SDL_BlendMode src_blend = SDL_BLENDMODE_NONE;
SDL_GetSurfaceBlendMode(src, &src_blend);
SDL_SetSurfaceBlendMode(tmp, src_blend);
/* Copy colorkey */
if(SDL_SurfaceHasColorKey(src))
{
Uint32 src_key = 0;
SDL_GetSurfaceColorKey(src, &src_key);
SDL_SetSurfaceColorKey(tmp, true, src_key);
}
bank->sprites[frame]->surface = tmp;
@ -466,21 +473,23 @@ int s_load_image(s_container_t *c, unsigned bank, const char *name)
return -1;
}
b = s_new_bank(c, bank, 1, src->clip_rect.w, src->clip_rect.h);
SDL_Rect src_clip;
SDL_GetSurfaceClipRect(src, &src_clip);
b = s_new_bank(c, bank, 1, src_clip.w, src_clip.h);
if(!b)
{
log_printf(ELOG, "sprite: Failed to allocate bank for \"%s\"!\n", name);
return -2;
}
if(extract_sprite(b, 0, src, &src->clip_rect) < 0)
if(extract_sprite(b, 0, src, &src_clip) < 0)
{
log_printf(ELOG, "sprite: Something went wrong while"
" extracting sprite \"%s\".\n", name);
return -3;
}
SDL_FreeSurface(src);
SDL_DestroySurface(src);
__run_plugins(b, 0, 1);
return 0;
}
@ -506,7 +515,7 @@ int s_load_sprite(s_container_t *c, unsigned bank, unsigned frame,
return -1;
}
from = src->clip_rect;
SDL_GetSurfaceClipRect(src, &from);
if( (from.w != b->w) || (from.h != b->h) )
{
log_printf(ELOG, "sprite: Warning: Sprite \"%s\" cropped"
@ -522,7 +531,7 @@ int s_load_sprite(s_container_t *c, unsigned bank, unsigned frame,
return -3;
}
SDL_FreeSurface(src);
SDL_DestroySurface(src);
__run_plugins(b, frame, 1);
return 0;
}
@ -582,7 +591,7 @@ int s_load_bank(s_container_t *c, unsigned bank, unsigned w, unsigned h,
}
++frame;
}
SDL_FreeSurface(src);
SDL_DestroySurface(src);
__run_plugins(b, 0, frames);
return 0;
}

View File

@ -50,7 +50,7 @@ window_t::window_t()
window_t::~window_t()
{
if(_offscreen && surface)
SDL_FreeSurface(surface);
SDL_DestroySurface(surface);
if(selected == this)
selected = NULL;
unlink();
@ -64,7 +64,7 @@ void window_t::init(gfxengine_t *e)
ys = engine->ys;
if(_offscreen && surface)
{
SDL_FreeSurface(surface);
SDL_DestroySurface(surface);
surface = NULL;
}
_offscreen = 0;
@ -137,14 +137,10 @@ int window_t::offscreen()
return 0; // Already offscreen!
visible(0);
_offscreen = 1;
SDL_Surface *s = SDL_CreateRGBSurface(SDL_SWSURFACE,
phys_rect.w, phys_rect.h,
32, 0xff000000, 0x00ff0000,
0x0000ff00, 0x000000ff);
if(!s)
return -1;
surface = SDL_DisplayFormat(s);
SDL_FreeSurface(s);
// SDL 3: back buffer is always ARGB8888; offscreen windows use
// the same format to allow direct blits without conversion.
surface = SDL_CreateSurface(phys_rect.w, phys_rect.h,
SDL_PIXELFORMAT_ARGB8888);
if(!surface)
return -1;
return 0;
@ -163,7 +159,7 @@ void window_t::_select()
SDL_Rect r = phys_rect;
selected = this;
if(surface)
SDL_SetClipRect(surface, &r);
SDL_SetSurfaceClipRect(surface, &r);
}
@ -248,7 +244,7 @@ Uint32 window_t::map_rgb(Uint8 r, Uint8 g, Uint8 b)
return 0;
if(surface)
return SDL_MapRGB(surface->format, r, g, b);
return SDL_MapSurfaceRGB(surface, r, g, b);
else
return 0xffffff;
}
@ -263,7 +259,7 @@ Uint32 window_t::map_rgb(Uint32 rgb)
Uint8 b = rgb & 0xff;
if(surface)
return SDL_MapRGB(surface->format, r, g, b);
return SDL_MapSurfaceRGB(surface, r, g, b);
else
return 0xffffff;
}
@ -283,7 +279,7 @@ void window_t::colorkey(Uint32 color)
return;
if(!_offscreen)
return;
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, color);
SDL_SetSurfaceColorKey(surface, true, color);
}
void window_t::colorkey()
@ -294,7 +290,7 @@ void window_t::colorkey()
return;
if(!_offscreen)
return;
SDL_SetColorKey(surface, 0, 0);
SDL_SetSurfaceColorKey(surface, false, 0);
}
void window_t::alpha(float a)
@ -305,7 +301,8 @@ void window_t::alpha(float a)
return;
if(!_offscreen)
return;
SDL_SetAlpha(surface, SDL_SRCALPHA, (int)(a * 255.0));
SDL_SetSurfaceAlphaMod(surface, (Uint8)(a * 255.0f));
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
}
@ -476,13 +473,13 @@ void window_t::clear(SDL_Rect *r)
dr.y += phys_rect.y;
}
if((-1 == bg_bank) && (-1 == bg_frame))
SDL_FillRect(surface, &dr, bgcolor);
SDL_FillSurfaceRect(surface, &dr, bgcolor);
else
{
s_sprite_t *s = engine->get_sprite(bg_bank, bg_frame);
if(!s || !s->surface)
{
SDL_FillRect(surface, &dr, bgcolor);
SDL_FillSurfaceRect(surface, &dr, bgcolor);
return;
}
SDL_BlitSurface(s->surface, &sr, surface, &dr);
@ -507,7 +504,7 @@ void window_t::point(int _x, int _y)
r.w = x2 - _x;
r.h = y2 - _y;
if(surface)
SDL_FillRect(surface, &r, fgcolor);
SDL_FillSurfaceRect(surface, &r, fgcolor);
}
@ -527,7 +524,7 @@ void window_t::fillrect(int _x, int _y, int w, int h)
r.w = x2 - _x;
r.h = y2 - _y;
if(surface)
SDL_FillRect(surface, &r, fgcolor);
SDL_FillSurfaceRect(surface, &r, fgcolor);
}
@ -556,7 +553,7 @@ void window_t::fillrect_fxp(int _x, int _y, int w, int h)
r.w = w;
r.h = h;
if(surface)
SDL_FillRect(surface, &r, fgcolor);
SDL_FillSurfaceRect(surface, &r, fgcolor);
}

120
kobo.cpp
View File

@ -440,14 +440,14 @@ int KOBO_main::quit_requested()
{
switch(e.type)
{
case SDL_QUIT:
case SDL_EVENT_QUIT:
exit_game_fast = 1;
break;
case SDL_VIDEOEXPOSE:
case SDL_EVENT_WINDOW_EXPOSED:
gengine->invalidate();
break;
case SDL_KEYUP:
switch(e.key.keysym.sym)
case SDL_EVENT_KEY_UP:
switch(e.key.key)
{
case SDLK_ESCAPE:
if(escape_hammering())
@ -459,9 +459,7 @@ int KOBO_main::quit_requested()
break;
}
}
if(exit_game_fast)
return 1;
return SDL_QuitRequested();
return exit_game_fast ? 1 : 0;
}
@ -1205,7 +1203,7 @@ int KOBO_main::load_graphics(prefs_t *p)
return -10;
RGN_FreeRegion(logo_region);
logo_region = RGN_ScanMask(s->surface,
SDL_MapRGB(s->surface->format, 255, 255, 255));
SDL_MapSurfaceRGB(s->surface, 255, 255, 255));
if(!logo_region)
{
log_printf(ELOG, "Could not create logo region!\n");
@ -1239,52 +1237,20 @@ int KOBO_main::load_sounds(prefs_t *p, int render_all)
int KOBO_main::init_js(prefs_t *p)
{
/* Activate Joystick sub-sys if we are using it */
// SDL 3 joystick API uses instance IDs and SDL_GetJoysticks /
// SDL_OpenJoystick. Port deferred — disabled for now.
if(p->use_joystick)
{
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
{
log_printf(ELOG, "Error setting up joystick!\n");
return -1;
}
p->number_of_joysticks = SDL_NumJoysticks();
if(p->number_of_joysticks > 0)
{
SDL_JoystickEventState(SDL_ENABLE);
if(p->joystick_no >= p->number_of_joysticks)
p->joystick_no = 0;
joystick = SDL_JoystickOpen(p->joystick_no);
if(!joystick)
{
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
return -2;
}
}
else
{
log_printf(ELOG, "No joysticks found!\n");
joystick = NULL;
return -3;
}
}
log_printf(WLOG, "Joystick support not yet ported to SDL 3.\n");
p->number_of_joysticks = 0;
joystick = NULL;
return 0;
}
void KOBO_main::close_js()
{
if(!SDL_WasInit(SDL_INIT_JOYSTICK))
return;
if(!joystick)
return;
if(SDL_JoystickOpened(0))
SDL_JoystickClose(joystick);
// Stub: see init_js. Joystick port pending.
joystick = NULL;
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
}
@ -1597,8 +1563,8 @@ void kobo_gfxengine_t::frame()
int k, ms;
switch (ev.type)
{
case SDL_KEYDOWN:
switch(ev.key.keysym.sym)
case SDL_EVENT_KEY_DOWN:
switch(ev.key.key)
{
#ifdef PROFILE_AUDIO
case SDLK_F10:
@ -1607,7 +1573,7 @@ void kobo_gfxengine_t::frame()
case SDLK_F12:
audio_print_info();
break;
case SDLK_r:
case SDLK_R:
{
audio_channel_stop(-1, -1);
int startt = SDL_GetTicks();
@ -1626,9 +1592,9 @@ void kobo_gfxengine_t::frame()
break;
case SDLK_RETURN:
ms = SDL_GetModState();
if(ms & (KMOD_CTRL | KMOD_SHIFT | KMOD_META))
if(ms & (SDL_KMOD_CTRL | SDL_KMOD_SHIFT | SDL_KMOD_GUI))
break;
if(!(ms & KMOD_ALT))
if(!(ms & SDL_KMOD_ALT))
break;
km.pause_game();
prefs->fullscreen = !prefs->fullscreen;
@ -1637,21 +1603,23 @@ void kobo_gfxengine_t::frame()
OS_RESTART_VIDEO;
stop();
return;
case SDLK_PRINT:
case SDLK_SYSREQ:
case SDLK_PRINTSCREEN:
// FIXME: Doesn't this trigger when entering names and stuff...?
case SDLK_s:
case SDLK_S:
gengine->screenshot();
break;
default:
break;
}
k = gamecontrol.map(ev.key.keysym.sym);
k = gamecontrol.map(ev.key.key);
gamecontrol.press(k);
gsm.press(k, ev.key.keysym.unicode);
// SDL 3 dropped per-keydown unicode; text input is via
// SDL_EVENT_TEXT_INPUT. Pass 0 for the unicode arg until
// the high-score name-entry path is re-wired.
gsm.press(k, 0);
break;
case SDL_KEYUP:
if((ev.key.keysym.sym == SDLK_ESCAPE) && km.escape_hammering())
case SDL_EVENT_KEY_UP:
if((ev.key.key == SDLK_ESCAPE) && km.escape_hammering())
{
km.pause_game();
prefs->fullscreen = 0;
@ -1674,7 +1642,7 @@ void kobo_gfxengine_t::frame()
gsm.push(&st_error);
return;
}
k = gamecontrol.map(ev.key.keysym.sym);
k = gamecontrol.map(ev.key.key);
if(k == SDLK_PAUSE)
{
gamecontrol.press(BTN_PAUSE);
@ -1686,19 +1654,17 @@ void kobo_gfxengine_t::frame()
gsm.release(k);
}
break;
case SDL_VIDEOEXPOSE:
case SDL_EVENT_WINDOW_EXPOSED:
gengine->invalidate();
break;
case SDL_ACTIVEEVENT:
// Any type of focus loss should activate pause mode!
if(!ev.active.gain)
km.pause_game();
case SDL_EVENT_WINDOW_FOCUS_LOST:
km.pause_game();
break;
case SDL_QUIT:
case SDL_EVENT_QUIT:
/*gsm.press(BTN_CLOSE);*/
km.brutal_quit();
break;
case SDL_JOYBUTTONDOWN:
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
if(ev.jbutton.button == km.js_fire)
{
gamecontrol.press(BTN_FIRE);
@ -1710,14 +1676,14 @@ void kobo_gfxengine_t::frame()
gsm.press(BTN_START);
}
break;
case SDL_JOYBUTTONUP:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
if(ev.jbutton.button == km.js_fire)
{
gamecontrol.release(BTN_FIRE);
gsm.release(BTN_FIRE);
}
break;
case SDL_JOYAXISMOTION:
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
// FIXME: We will want to allow these to be
// redefined, but for now, this works ;-)
if(ev.jaxis.axis == km.js_lr)
@ -1762,7 +1728,8 @@ void kobo_gfxengine_t::frame()
}
}
case SDL_MOUSEMOTION:
break;
case SDL_EVENT_MOUSE_MOTION:
mouse_x = (int)(ev.motion.x / gengine->xscale()) - km.xoffs;
mouse_y = (int)(ev.motion.y / gengine->yscale()) - km.yoffs;
if(prefs->use_mouse)
@ -1770,9 +1737,9 @@ void kobo_gfxengine_t::frame()
mouse_x - 8 - MARGIN - WSIZE/2,
mouse_y - MARGIN - WSIZE/2);
break;
case SDL_MOUSEBUTTONDOWN:
mouse_x = (int)(ev.motion.x / gengine->xscale()) - km.xoffs;
mouse_y = (int)(ev.motion.y / gengine->yscale()) - km.yoffs;
case SDL_EVENT_MOUSE_BUTTON_DOWN:
mouse_x = (int)(ev.button.x / gengine->xscale()) - km.xoffs;
mouse_y = (int)(ev.button.y / gengine->yscale()) - km.yoffs;
gsm.press(BTN_FIRE);
if(prefs->use_mouse)
{
@ -1794,9 +1761,9 @@ void kobo_gfxengine_t::frame()
gamecontrol.press(BTN_FIRE);
}
break;
case SDL_MOUSEBUTTONUP:
mouse_x = (int)(ev.motion.x / gengine->xscale()) - km.xoffs;
mouse_y = (int)(ev.motion.y / gengine->yscale()) - km.yoffs;
case SDL_EVENT_MOUSE_BUTTON_UP:
mouse_x = (int)(ev.button.x / gengine->xscale()) - km.xoffs;
mouse_y = (int)(ev.button.y / gengine->yscale()) - km.yoffs;
if(prefs->use_mouse)
{
gamecontrol.mouse_position(
@ -2086,8 +2053,9 @@ int main(int argc, char *argv[])
if(prefs->cmd_noparachute)
{
// SDL 3 has no parachute / signal handler by default.
SDL_Quit();
SDL_Init(SDL_INIT_NOPARACHUTE);
SDL_Init(0);
}
km.open_logging(prefs);

View File

@ -87,8 +87,8 @@ class _manage
static void lost_myship();
static void destroyed_a_core();
static void add_score(int sc);
static void key_down(SDLKey sym);
static void key_up(SDLKey sym);
static void key_down(SDL_Keycode sym);
static void key_up(SDL_Keycode sym);
static int title_blank() { return blank; }
static void select_next(int redraw_map = 1);
static void select_prev(int redraw_map = 1);

View File

@ -187,18 +187,13 @@ void video_options_t::build()
prf->videodriver = GFX_DRIVER_SDL2D;
space();
xoffs = 0.55;
switch(prf->videodriver)
{
case GFX_DRIVER_SDL2D:
list("Display Buffering Mode", &prf->doublebuf, OS_RESTART_VIDEO);
item("Single", 0);
item("Double", 1);
yesno("Software Shadow Buffer", &prf->shadow, OS_RESTART_VIDEO);
break;
case GFX_DRIVER_GLSDL:
yesno("Vertical Retrace Sync", &prf->vsync, OS_RESTART_VIDEO);
break;
}
// Only the SDL 2D driver remains since the SDL 3 migration; the
// OpenGL driver is now handled by the SDL renderer itself.
list("Display Buffering Mode", &prf->doublebuf, OS_RESTART_VIDEO);
item("Single", 0);
item("Double", 1);
yesno("Software Shadow Buffer", &prf->shadow, OS_RESTART_VIDEO);
yesno("Vertical Retrace Sync", &prf->vsync, OS_RESTART_VIDEO);
list("Display Buffer Pages", &prf->pages, OS_UPDATE_ENGINE);
item("Assume Standard", -1);
item("Always Repaint", 0);
@ -243,13 +238,9 @@ void graphics_options_t::build()
item("2x2 Filter", 0);
item("4x4 Filter", 1);
item("Random", 2);
switch(prf->videodriver)
{
case GFX_DRIVER_GLSDL:
yesno("Broken RGBA8 (OpenGL)", &prf->broken_rgba8,
OS_RELOAD_GRAPHICS);
break;
}
// "Broken RGBA8" was a glSDL workaround for cards that supported
// RGB8 but not RGBA8 textures; SDL 3's renderer handles this
// transparently.
space();
yesno("Alpha Blending", &prf->alpha, OS_RELOAD_GRAPHICS);
space();
@ -396,11 +387,15 @@ void control_options_t::build()
item("5 frames", 5);
space();
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
if(!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
label("Could not initialize joysticks!");
else
{
prf->number_of_joysticks = SDL_NumJoysticks();
// SDL 3: SDL_NumJoysticks → SDL_GetJoysticks(&count).
int njs = 0;
SDL_JoystickID *jids = SDL_GetJoysticks(&njs);
SDL_free(jids);
prf->number_of_joysticks = njs;
yesno("Use Joystick", &prf->use_joystick,
OS_RESTART_INPUT | OS_REBUILD);
if(prf->use_joystick)

View File

@ -832,15 +832,15 @@ int audio_wave_load(int wid, const char *name, int looped)
{
switch (spec.format)
{
case AUDIO_S8:
case SDL_AUDIO_S8:
wavetab[wid].format = AF_MONO8;
break;
case AUDIO_S16SYS:
case SDL_AUDIO_S16:
wavetab[wid].format = AF_MONO16;
break;
default:
log_printf(ELOG, "sound_load(): Unsupported wave format!\n");
SDL_FreeWAV((Uint8 *)(wavetab[wid].data.si8));
SDL_free(wavetab[wid].data.si8);
res = -1;
break;
}
@ -862,7 +862,7 @@ int audio_wave_load(int wid, const char *name, int looped)
audio_wave_load_mem(wid, data, size, looped);
if(using_loadwav)
SDL_FreeWAV(data);
SDL_free(data);
else
free(data);

View File

@ -49,6 +49,29 @@
#include <SDL3/SDL_audio.h>
#include "logger.h"
/*
* SDL 3 migration: the SDL 1.2 audio API (SDL_OpenAudio + callback model,
* AUDIO_S16SYS, SDL_LockAudio/PauseAudio/CloseAudio, SDL_AudioSpec.samples
* and .callback) is gone. SDL 3 uses SDL_OpenAudioDeviceStream with a
* pull-stream callback. Porting that bridge is a separate phase; for now
* we provide local stubs so the engine links, and _start_SDL_output()
* below returns -1 so audio is silently disabled.
*/
#define AUDIO_S16SYS 0
#define SDL_OpenAudio(a, b) (-1)
#define SDL_CloseAudio() ((void)0)
#define SDL_PauseAudio(x) ((void)0)
#define SDL_LockAudio() ((void)0)
#define SDL_UnlockAudio() ((void)0)
typedef struct {
int freq;
Uint16 format;
Uint8 channels;
Uint16 samples;
void (*callback)(void *userdata, Uint8 *stream, int len);
} kobo_legacy_audio_spec_t;
#define SDL_AudioSpec kobo_legacy_audio_spec_t
#include "a_struct.h"
#include "a_commands.h"
#include "a_control.h"
@ -569,6 +592,10 @@ static int _start_oss_output()
static int _start_SDL_output(void)
{
log_printf(WLOG, "audio.c: SDL 3 audio backend not yet ported;"
" sound disabled.\n");
return -1;
#if 0
SDL_AudioSpec as;
SDL_AudioSpec audiospec;
@ -629,6 +656,7 @@ static int _start_SDL_output(void)
_audio_running = 1;
SDL_PauseAudio(0);
return 0;
#endif
}

View File

@ -23,6 +23,20 @@
#include "sdl_compat.h"
#include <math.h>
/*
* SDL 3 migration: SDL_WM_GrabInput and SDL_EnableUNICODE are gone.
* Replacements (SDL_SetWindowMouseGrab and SDL_StartTextInput) both
* require the window pointer, which we don't yet expose from gfxengine.
* Stub them out so the code links; mouse-capture and unicode text-input
* (high-score name entry) will be re-wired once gfxengine exposes the
* SDL_Window handle.
*/
#define SDL_GRAB_QUERY 0
#define SDL_GRAB_ON 1
#define SDL_GRAB_OFF 0
#define SDL_WM_GrabInput(x) (SDL_GRAB_OFF)
#define SDL_EnableUNICODE(x) ((void)0)
#ifndef M_PI
# define M_PI 3.14159265358979323846 /* pi */
#endif