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>
495 lines
12 KiB
C++
495 lines
12 KiB
C++
/*(GPL)
|
|
------------------------------------------------------------
|
|
Kobo Deluxe - An enhanced SDL port of XKobo
|
|
------------------------------------------------------------
|
|
* Copyright (C) 2001-2003, 2006-2007 David Olofson
|
|
* Copyright (C) 2005 Erik Auerswald
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
|
|
#include "config.h"
|
|
#include "options.h"
|
|
#include "gfxengine.h"
|
|
#include "gamectl.h"
|
|
#include "a_types.h"
|
|
#include "kobo.h"
|
|
|
|
|
|
void system_options_t::build()
|
|
{
|
|
medium();
|
|
label("System Options");
|
|
|
|
space();
|
|
small();
|
|
xoffs = 0.6;
|
|
list("Maximum Frame Rate", &prf->max_fps, OS_REBUILD);
|
|
{
|
|
char buf[10];
|
|
item("OFF", 0);
|
|
for(int i = 1; i < 25; i += 1)
|
|
{
|
|
snprintf((char *)&buf, sizeof(buf),
|
|
"%d Hz", i);
|
|
item(buf, i);
|
|
}
|
|
for(int i = 25; i < 100; i += 5)
|
|
{
|
|
snprintf((char *)&buf, sizeof(buf),
|
|
"%d Hz", i);
|
|
item(buf, i);
|
|
}
|
|
for(int i = 100; i <= 200; i += 10)
|
|
{
|
|
snprintf((char *)&buf, sizeof(buf),
|
|
"%d Hz", i);
|
|
item(buf, i);
|
|
}
|
|
}
|
|
if(prf->max_fps)
|
|
yesno("Strictly Regulated", &prf->max_fps_strict, 0);
|
|
|
|
space();
|
|
xoffs = 0.6;
|
|
list("Time Filter", &prf->timefilter, OS_UPDATE_ENGINE);
|
|
item("Off", 100);
|
|
item("Fast", 75);
|
|
item("Normal", 50);
|
|
item("Slow", 10);
|
|
item("Logic/Video Lock", 0);
|
|
onoff("Motion Interpolation", &prf->filter, OS_UPDATE_ENGINE);
|
|
|
|
space();
|
|
xoffs = 0.6;
|
|
yesno("Log Messages to File", &prf->logfile, OS_RESTART_LOGGER);
|
|
list("Log Output Format", &prf->logformat, 0);
|
|
item("Plain Text", 0);
|
|
item("ANSI Coloring", 1);
|
|
item("HTML", 2);
|
|
xoffs = 0.45;
|
|
list("Log Verbosity", &prf->logverbosity, 0);
|
|
item("Critical Errors Only", 0);
|
|
item("Errors Only", 1);
|
|
item("Errors & Warnings", 2);
|
|
item("Some Debug", 3);
|
|
item("More Debug", 4);
|
|
item("Everything", 5);
|
|
|
|
big();
|
|
space();
|
|
xoffs = 0.5;
|
|
button("ACCEPT", OS_CLOSE);
|
|
button("CANCEL", OS_CANCEL);
|
|
}
|
|
|
|
|
|
void video_options_t::build()
|
|
{
|
|
medium();
|
|
label("Video Options");
|
|
space();
|
|
small();
|
|
|
|
if(firstbuild)
|
|
{
|
|
vmm_Init(VMM_ALL, 0);
|
|
VMM_Mode *vm = vmm_FindMode(prf->videomode);
|
|
if(vm)
|
|
{
|
|
if(vm->flags & VMM_PC)
|
|
showmodes = VMM_PC;
|
|
else if(vm->flags & VMM_TV)
|
|
showmodes = VMM_TV;
|
|
else if(vm->flags & VMM_4_3)
|
|
showmodes = VMM_4_3;
|
|
else if(vm->flags & VMM_3_2)
|
|
showmodes = VMM_3_2;
|
|
else if(vm->flags & VMM_5_4)
|
|
showmodes = VMM_5_4;
|
|
else if(vm->flags & VMM_16_10)
|
|
showmodes = VMM_16_10;
|
|
else if(vm->flags & VMM_16_9)
|
|
showmodes = VMM_16_9;
|
|
else
|
|
showmodes = VMM_ALL;
|
|
if(vm->flags & VMM_LORES)
|
|
showlow = 1;
|
|
}
|
|
else
|
|
{
|
|
showmodes = VMM_PC;
|
|
showlow = 0;
|
|
prf->videomode = -1;
|
|
}
|
|
firstbuild = 0;
|
|
}
|
|
|
|
xoffs = 0.35;
|
|
list("Show Modes" , &showmodes, OS_REBUILD);
|
|
item("Show All", VMM_ALL);
|
|
item("Common PC/Mac Modes", VMM_PC);
|
|
item("Common TV Modes", VMM_TV);
|
|
item("4:3 (Standard CRT)", VMM_4_3);
|
|
item("3:2 (NTSC TV)", VMM_3_2);
|
|
item("5:4 (Some TFTs)", VMM_5_4);
|
|
item("16:10 (PC/Mac Widescreen)", VMM_16_10);
|
|
item("16:9 (TV Widescreen)", VMM_16_9);
|
|
xoffs = 0.7;
|
|
yesno("Show Odd Low Resolutions" , &showlow, OS_REBUILD);
|
|
xoffs = 0.5;
|
|
list("Display Mode", &prf->videomode, OS_RESTART_VIDEO | OS_REBUILD);
|
|
vmm_Init(showmodes, showlow ? 0 : VMM_LORES);
|
|
VMM_Mode *vm = vmm_First();
|
|
char buf[256];
|
|
buf[sizeof(buf) - 1] = 0;
|
|
while(vm)
|
|
{
|
|
if(vm->name)
|
|
snprintf(buf, sizeof(buf) - 1, "%dx%d (%s)",
|
|
vm->width, vm->height, vm->name);
|
|
else
|
|
snprintf(buf, sizeof(buf) - 1, "%dx%d",
|
|
vm->width, vm->height);
|
|
item(buf, vm->id);
|
|
vm = vmm_Next(vm);
|
|
}
|
|
item("Custom", -1);
|
|
if(prf->videomode < 0)
|
|
{
|
|
spin("Width", &prf->width, 32, 4096, "pixels",
|
|
OS_RESTART_VIDEO | OS_REBUILD);
|
|
spin("Height", &prf->height, 32, 4096, "pixels",
|
|
OS_RESTART_VIDEO | OS_REBUILD);
|
|
}
|
|
space();
|
|
yesno("Fullscreen Display", &prf->fullscreen, OS_RESTART_VIDEO);
|
|
list("Display Depth", &prf->depth, OS_RESTART_VIDEO);
|
|
item("Default", 0);
|
|
item("8 bits", 8);
|
|
item("15 bits", 15);
|
|
item("16 bits", 16);
|
|
item("24 bits", 24);
|
|
item("32 bits", 32);
|
|
prf->videodriver = GFX_DRIVER_SDL2D;
|
|
space();
|
|
xoffs = 0.55;
|
|
// 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);
|
|
item("Single", 1);
|
|
item("Double", 2);
|
|
item("Triple", 3);
|
|
big();
|
|
space();
|
|
xoffs = 0.5;
|
|
button("ACCEPT", OS_CLOSE);
|
|
button("CANCEL", OS_CANCEL);
|
|
}
|
|
|
|
|
|
void graphics_options_t::build()
|
|
{
|
|
medium();
|
|
label("Graphics Options");
|
|
space();
|
|
small();
|
|
xoffs = 0.6;
|
|
list("Scale Mode", &prf->scalemode, OS_RELOAD_GRAPHICS);
|
|
item("Nearest", GFX_SCALE_NEAREST);
|
|
item("Bilinear", GFX_SCALE_BILINEAR);
|
|
// FIXME: Bilinear+Oversampling is unreliable and doesn't help much anyway
|
|
// item("Bilinear+Oversampling", GFX_SCALE_BILIN_OVER);
|
|
|
|
// FIXME: We need to specify a fallback chain for when filters do not support
|
|
// FIXME: ratios. So, we have quality and image specific requirements, and we
|
|
// FIXME: want a list of filters/modes in order of preference.
|
|
|
|
// if((gengine->xscale() == 2.0f) && (gengine->yscale() == 2.0f))
|
|
// {
|
|
item("Scale2x", GFX_SCALE_SCALE2X);
|
|
item("Diamond2x", GFX_SCALE_DIAMOND);
|
|
// }
|
|
// else if(prf->scalemode >= GFX_SCALE_SCALE2X)
|
|
// prf->scalemode = GFX_SCALE_BILINEAR;
|
|
space(1);
|
|
yesno("Dithering", &prf->use_dither, OS_RELOAD_GRAPHICS);
|
|
list("Dither Type", &prf->dither_type, OS_RELOAD_GRAPHICS);
|
|
item("2x2 Filter", 0);
|
|
item("4x4 Filter", 1);
|
|
item("Random", 2);
|
|
// "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();
|
|
list("Brightness", &prf->brightness, OS_RELOAD_GRAPHICS);
|
|
perc_list(50, 150, 10);
|
|
list("Contrast", &prf->contrast, OS_RELOAD_GRAPHICS);
|
|
perc_list(50, 150, 10);
|
|
big();
|
|
space();
|
|
xoffs = 0.5;
|
|
button("ACCEPT", OS_CLOSE);
|
|
button("CANCEL", OS_CANCEL);
|
|
}
|
|
|
|
|
|
void audio_options_t::build()
|
|
{
|
|
medium();
|
|
label("Sound Options");
|
|
small();
|
|
space();
|
|
xoffs = 0.57;
|
|
yesno("Enable Sound", &prf->use_sound, OS_RESTART_AUDIO | OS_REBUILD);
|
|
if(prf->use_sound)
|
|
{
|
|
yesno("Enable Music", &prf->use_music, OS_RESTART_AUDIO | OS_REBUILD);
|
|
yesno("Cached Sounds", &prf->cached_sounds, OS_RELOAD_AUDIO_CACHE);
|
|
|
|
//System
|
|
space();
|
|
list("Sample Rate", &prf->samplerate, OS_RESTART_AUDIO);
|
|
item("8 kHz", 8000);
|
|
item("11025 Hz", 11025);
|
|
item("16 kHz", 16000);
|
|
item("22050", 22050);
|
|
item("32 kHz", 32000);
|
|
item("44.1 kHz", 44100);
|
|
item("48 kHz", 48000);
|
|
item("88.2 kHz", 88200);
|
|
item("96 kHz", 96000);
|
|
item("176.4 kHz", 176400);
|
|
item("192 kHz", 192000);
|
|
list("Mixing Quality", &prf->mixquality, OS_UPDATE_AUDIO);
|
|
item("Very Low", AQ_VERY_LOW);
|
|
item("Low", AQ_LOW);
|
|
item("Normal", AQ_NORMAL);
|
|
item("High", AQ_HIGH);
|
|
item("Very High", AQ_VERY_HIGH);
|
|
list("Sound Latency", &prf->latency, OS_RESTART_AUDIO);
|
|
{
|
|
char buf[10];
|
|
for(int i = 1; i < 20; i += 1)
|
|
{
|
|
snprintf((char *)&buf, sizeof(buf),
|
|
"%d ms", i);
|
|
item(buf, i);
|
|
}
|
|
for(int i = 20; i < 50; i += 5)
|
|
{
|
|
snprintf((char *)&buf, sizeof(buf),
|
|
"%d ms", i);
|
|
item(buf, i);
|
|
}
|
|
for(int i = 50; i < 100; i += 10)
|
|
{
|
|
snprintf((char *)&buf, sizeof(buf),
|
|
"%d ms", i);
|
|
item(buf, i);
|
|
}
|
|
for(int i = 100; i <= 500; i += 25)
|
|
{
|
|
snprintf((char *)&buf, sizeof(buf),
|
|
"%d ms", i);
|
|
item(buf, i);
|
|
}
|
|
}
|
|
#ifdef HAVE_OSS
|
|
yesno("Use OSS Sound Driver", &prf->use_oss, OS_RESTART_AUDIO);
|
|
#else
|
|
// We're running out of space here... :-/
|
|
space();
|
|
#endif
|
|
//Mixer
|
|
list("Sound Effects Level", &prf->sfx_vol, OS_UPDATE_AUDIO);
|
|
item("OFF", 0);
|
|
perc_list(10, 90, 10);
|
|
perc_list(100, 200, 25);
|
|
if(prf->use_music)
|
|
{
|
|
list("Intro Music Level", &prf->intro_vol, OS_UPDATE_AUDIO);
|
|
item("OFF", 0);
|
|
perc_list(10, 90, 10);
|
|
perc_list(100, 200, 25);
|
|
list("In-Game Music Level", &prf->music_vol, OS_UPDATE_AUDIO);
|
|
item("OFF", 0);
|
|
perc_list(10, 90, 10);
|
|
perc_list(100, 200, 25);
|
|
}
|
|
|
|
//Master effects
|
|
list("Ambience", &prf->reverb, OS_UPDATE_AUDIO);
|
|
item("OFF", 0);
|
|
item("Low", 50);
|
|
item("Normal", 100);
|
|
item("High", 175);
|
|
item("Extreme", 250);
|
|
list("Volume Boost", &prf->vol_boost, OS_UPDATE_AUDIO);
|
|
item("OFF", 0);
|
|
item("Low", 1);
|
|
item("Moderate", 2);
|
|
item("High", 3);
|
|
item("Extreme", 4);
|
|
}
|
|
space();
|
|
big();
|
|
xoffs = 0.5;
|
|
button("ACCEPT", OS_CLOSE);
|
|
button("CANCEL", OS_CANCEL | OS_UPDATE_AUDIO);
|
|
}
|
|
|
|
void audio_options_t::undo_hook()
|
|
{
|
|
clearstatus(OS_RELOAD | OS_RESTART | OS_UPDATE);
|
|
setstatus(OS_UPDATE_AUDIO);
|
|
}
|
|
|
|
|
|
void control_options_t::build()
|
|
{
|
|
medium();
|
|
label("Control Options");
|
|
space();
|
|
small();
|
|
xoffs = 0.67;
|
|
yesno("Always Fire", &prf->always_fire, OS_RESTART_INPUT);
|
|
space();
|
|
yesno("Broken NumPad Diagonals", &prf->broken_numdia, 0);
|
|
list("Diagonals Emphasis Filter", &prf->dia_emphasis, 0);
|
|
item("OFF", 0);
|
|
item("1 frame", 1);
|
|
item("2 frames", 2);
|
|
item("3 frames", 3);
|
|
item("4 frames", 4);
|
|
item("5 frames", 5);
|
|
space();
|
|
|
|
if(!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
|
|
label("Could not initialize joysticks!");
|
|
else
|
|
{
|
|
// 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)
|
|
{
|
|
if(prf->number_of_joysticks)
|
|
{
|
|
list("Joystick Number", &prf->joystick_no,
|
|
OS_RESTART_INPUT);
|
|
enum_list(0, prf->number_of_joysticks - 1);
|
|
}
|
|
else
|
|
label("No Joysticks Found!");
|
|
}
|
|
}
|
|
space();
|
|
|
|
yesno("Use Mouse", &prf->use_mouse, OS_RESTART_INPUT | OS_REBUILD);
|
|
if(prf->use_mouse)
|
|
{
|
|
list("Mouse Control Mode", &prf->mousemode, OS_RESTART_INPUT);
|
|
item("Disabled", MMD_OFF);
|
|
item("Crosshair", MMD_CROSSHAIR);
|
|
}
|
|
space();
|
|
yesno("In-game Mouse Capture", &prf->mousecapture, 0);
|
|
big();
|
|
space();
|
|
xoffs = 0.5;
|
|
button("ACCEPT", OS_CLOSE);
|
|
button("CANCEL", OS_CANCEL);
|
|
}
|
|
|
|
|
|
void game_options_t::build()
|
|
{
|
|
medium();
|
|
label("Game Options");
|
|
space();
|
|
small();
|
|
xoffs = 0.6;
|
|
list("Radar Scroll Mode", &prf->scrollradar, 0);
|
|
item("Off", 0);
|
|
// FIXME: Radar sweep mode is broken!
|
|
// item("Sweep", 1);
|
|
item("Scroll", 2);
|
|
space();
|
|
list("Get Ready Countdown", &prf->countdown, 0);
|
|
item("Quick Start", 0);
|
|
item("1 second", 1);
|
|
item("2 seconds", 2);
|
|
item("3 seconds", 3);
|
|
item("4 seconds", 4);
|
|
item("5 seconds", 5);
|
|
item("6 seconds", 6);
|
|
item("7 seconds", 7);
|
|
item("8 seconds", 8);
|
|
item("9 seconds", 9);
|
|
item("Wait Forever", 10);
|
|
space();
|
|
list("Starfield Mode", &prf->starfield, OS_REBUILD);
|
|
item("None", STARFIELD_NONE);
|
|
item("Old (Flat)", STARFIELD_OLD);
|
|
item("Parallax", STARFIELD_PARALLAX);
|
|
if(prf->starfield == STARFIELD_PARALLAX)
|
|
{
|
|
list("Starfield Density", &prf->stars, 0);
|
|
item("Minimal", 50);
|
|
item("Low", 250);
|
|
item("Normal", 500);
|
|
item("High", 1000);
|
|
item("Massive", 2500);
|
|
item("Insane", 8000);
|
|
}
|
|
space();
|
|
xoffs = 0.7;
|
|
list("Cannon Overheat Warning", &prf->overheatloud, 0);
|
|
item("Off", 0);
|
|
item("Soft", 50);
|
|
item("Normal", 100);
|
|
item("Loud", 200);
|
|
list("Cannon Sound Suppression", &prf->cannonloud, 0);
|
|
item("Off", 200);
|
|
item("Low", 100);
|
|
item("High", 50);
|
|
big();
|
|
space();
|
|
xoffs = 0.5;
|
|
button("ACCEPT", OS_CLOSE);
|
|
button("CANCEL", OS_CANCEL | OS_UPDATE_ENGINE);
|
|
}
|
|
|
|
void game_options_t::undo_hook()
|
|
{
|
|
clearstatus(OS_RELOAD | OS_RESTART | OS_UPDATE);
|
|
setstatus(OS_UPDATE_ENGINE);
|
|
}
|