diff --git a/.editorconfig b/.editorconfig
index f04f2926..f17c07ba 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -9,11 +9,10 @@ charset = utf-8
indent_style = tab
# indent_size = 4
-[*.{py,html,js}]
+[*.{py,html,js,nsi.in}]
indent_style = space
indent_size = 4
[meson.build]
indent_style = space
indent_size = 4
-
diff --git a/misc/taisei-angle.bat b/misc/taisei-angle.bat
index 77292f72..b41c5e68 100644
--- a/misc/taisei-angle.bat
+++ b/misc/taisei-angle.bat
@@ -1,10 +1,2 @@
@echo off
-
-cd "%~dp0"
-set ANGLE_PATH=.\ANGLE
-set TAISEI_RENDERER=gles30
-set SDL_OPENGL_ES_DRIVER=1
-set SDL_VIDEO_GL_DRIVER=%ANGLE_PATH%\libGLESv2.dll
-set SDL_VIDEO_EGL_DRIVER=%ANGLE_PATH%\libEGL.dll
-
-start .\taisei.exe %*
+"%~dp0\taisei.exe" --renderer gles30 %*
diff --git a/scripts/taisei.nsi.in b/scripts/taisei.nsi.in
index 9aa44129..98f911de 100644
--- a/scripts/taisei.nsi.in
+++ b/scripts/taisei.nsi.in
@@ -155,20 +155,17 @@ Section "-Core installation"
CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
+ CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei.lnk" "$INSTDIR\taisei.exe"
!if @USE_ANGLE@ == 1
- CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei (OpenGL).lnk" "$INSTDIR\taisei.exe"
- CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei (ANGLE).lnk" "$INSTDIR\taisei-angle.bat" "" "$INSTDIR\taisei.exe" 0 SW_SHOWMINIMIZED
- !else
- CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei.lnk" "$INSTDIR\taisei.exe"
+ CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei (ANGLE).lnk" "$INSTDIR\taisei.exe" "--renderer gles30"
!endif
${If} "$INSTALL_DESKTOP" == "1"
+ CreateShortcut "$DESKTOP\Taisei.lnk" "$INSTDIR\taisei.exe"
+
!if @USE_ANGLE@ == 1
- CreateShortcut "$DESKTOP\Taisei (OpenGL).lnk" "$INSTDIR\taisei.exe"
- CreateShortcut "$DESKTOP\Taisei (ANGLE).lnk" "$INSTDIR\taisei-angle.bat" "" "$INSTDIR\taisei.exe" 0 SW_SHOWMINIMIZED
- !else
- CreateShortcut "$DESKTOP\Taisei.lnk" "$INSTDIR\taisei.exe"
+ CreateShortcut "$DESKTOP\Taisei (ANGLE).lnk" "$INSTDIR\taisei.exe" "--renderer gles30"
!endif
${EndIf}
@@ -257,7 +254,7 @@ Function .onInit
StrCmp $0 "" inst
MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \
- "${APPNAME} is already installed. $\n$\nDo you want to uninstall the old version before installing the new one?" \
+ "${APPNAME} is already installed.$\n$\nDo you want to uninstall the old version before installing the new one?$\n$\nIf unsure, choose YES." \
/SD IDYES IDYES uninst IDNO inst
Abort
diff --git a/src/cli.c b/src/cli.c
index 8a7d9a9d..a1c77733 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -19,27 +19,53 @@
struct TsOption { struct option opt; const char *help; const char *argname;};
+enum {
+ OPT_RENDERER = INT_MIN,
+};
+
static void print_help(struct TsOption* opts) {
tsfprintf(stdout, "Usage: taisei [OPTIONS]\nTaisei is an open source Tōhō Project fangame.\n\nOptions:\n");
int margin = 20;
for(struct TsOption *opt = opts; opt->opt.name; opt++) {
- tsfprintf(stdout, " -%c, --%s ", opt->opt.val,opt->opt.name);
+ if(opt->opt.val > 0) {
+ tsfprintf(stdout, " -%c, --%s ", opt->opt.val, opt->opt.name);
+ } else {
+ tsfprintf(stdout, " --%s ", opt->opt.name);
+ }
+
int length = margin-(int)strlen(opt->opt.name);
+
if(opt->argname) {
tsfprintf(stdout, "%s", opt->argname);
length -= (int)strlen(opt->argname);
}
- for(int i = 0; i < length; i++)
- tsfprintf(stdout, " ");
- if(opt->argname)
+
+ for(int i = 0; i < length; i++) {
+ fputc(' ', stdout);
+ }
+
+ fputs(" ", stdout);
+
+ if(opt->argname && strchr(opt->help, '%')) {
tsfprintf(stdout, opt->help, opt->argname);
- else
+ } else {
tsfprintf(stdout, "%s", opt->help);
+ }
+
tsfprintf(stdout, "\n");
}
}
int cli_args(int argc, char **argv, CLIAction *a) {
+ const char *const _renderer_list =
+ #define R(r) ","#r
+ TAISEI_BUILDCONF_RENDERER_BACKENDS
+ #undef R
+ ;
+
+ char renderer_list[strlen(_renderer_list) + 2];
+ snprintf(renderer_list, sizeof(renderer_list), "{%s}", _renderer_list+1);
+
struct TsOption taisei_opts[] = {
{{"replay", required_argument, 0, 'r'}, "Play a replay from %s", "FILE"},
{{"verify-replay", required_argument, 0, 'R'}, "Play a replay from %s in headless mode, crash as soon as it desyncs", "FILE"},
@@ -53,6 +79,7 @@ int cli_args(int argc, char **argv, CLIAction *a) {
#endif
{{"frameskip", optional_argument, 0, 'f'}, "Disable FPS limiter, render only every %s frame", "FRAME"},
{{"credits", no_argument, 0, 'c'}, "Show the credits scene and exit"},
+ {{"renderer", required_argument, 0, OPT_RENDERER}, "Choose the rendering backend", renderer_list},
{{"help", no_argument, 0, 'h'}, "Display this help"},
{{0,0,0,0},0,0}
};
@@ -66,6 +93,11 @@ int cli_args(int argc, char **argv, CLIAction *a) {
for(int i = 0; i < nopts; i++) {
opts[i] = taisei_opts[i].opt;
+
+ if(opts[i].val <= 0) {
+ continue;
+ }
+
*ptr = opts[i].val;
ptr++;
@@ -160,8 +192,11 @@ int cli_args(int argc, char **argv, CLIAction *a) {
case 'c':
a->type = CLI_Credits;
break;
+ case OPT_RENDERER:
+ env_set("TAISEI_RENDERER", optarg, true);
+ break;
default:
- log_fatal("Unknown option (this shouldn’t happen)");
+ UNREACHABLE;
}
}
diff --git a/src/meson.build b/src/meson.build
index 15e5df55..24ca9e3f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -10,8 +10,15 @@ if host_machine.system() == 'windows'
winmod = import('windows')
rcpath = join_paths(meson.current_build_dir(), 'taisei.rc')
+ icons_dir = join_paths(meson.source_root(), 'misc', 'icons')
+ icon_main = join_paths(icons_dir, 'taisei.ico')
+ icon_replay = join_paths(icons_dir, 'taisei-replay.ico')
+ manifest = join_paths(meson.current_source_dir(), 'taisei.manifest')
+
rcdefs = [
- '-DICONS_DIR=@0@'.format(join_paths(meson.source_root(), 'misc', 'icons'))
+ '-DICON_MAIN=@0@'.format(icon_main),
+ '-DICON_REPLAY=@0@'.format(icon_replay),
+ '-DMANIFEST=@0@'.format(manifest),
]
if is_debug_build
@@ -28,12 +35,25 @@ if host_machine.system() == 'windows'
output : 'taisei.rc',
)
- version_deps += winmod.compile_resources(rc_target)
+ if meson.version().version_compare('>=0.47.0')
+ version_deps += winmod.compile_resources(
+ rc_target,
+ depend_files : files(
+ 'taisei.manifest',
+ icon_main,
+ icon_replay,
+ )
+ )
+ else
+ version_deps += winmod.compile_resources(rc_target)
+ endif
# msvcrt is dumb and only supports up to c89.
# with this defined, alternative implementations from mingw for e.g. the
# printf family of functions will be used, which conform to c11.
config.set('__USE_MINGW_ANSI_STDIO', 1)
+
+ taisei_deps += cc.find_library('comctl32')
endif
use_intel_intrin = get_option('intel_intrin') and cc.links('''
diff --git a/src/renderer/glcommon/opengl.c b/src/renderer/glcommon/opengl.c
index b2380e40..56badd74 100644
--- a/src/renderer/glcommon/opengl.c
+++ b/src/renderer/glcommon/opengl.c
@@ -593,6 +593,78 @@ static APIENTRY GLvoid shim_glClearDepthf(GLfloat depthval) {
}
#endif
+static void detect_broken_intel_driver(void) {
+#ifdef TAISEI_BUILDCONF_HAVE_WINDOWS_ANGLE_FALLBACK
+ extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+ bool is_broken_intel_driver = (
+ !glext.version.is_es &&
+ strstartswith((const char*)glGetString(GL_VENDOR), "Intel") &&
+ strstr((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION), " - Build ")
+ );
+
+ if(!is_broken_intel_driver) {
+ return;
+ }
+
+ int button;
+ SDL_MessageBoxData mbdata = { 0 };
+
+ mbdata.flags = SDL_MESSAGEBOX_WARNING;
+ mbdata.title = "Taisei Project";
+
+ char *msg = strfmt(
+ "Looks like you have a broken OpenGL driver.\n"
+ "Taisei will probably not work correctly, if at all.\n\n"
+ "Starting the game in ANGLE mode should fix the problem, but may introduce slowdown.\n\n"
+ "Restart in ANGLE mode now? (If unsure, press YES)"
+ );
+
+ mbdata.message = msg;
+ mbdata.numbuttons = 3;
+ mbdata.buttons = (SDL_MessageBoxButtonData[]) {
+ { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 2, "Abort" },
+ { 0, 1, "No" },
+ { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 0, "Yes (safe)" },
+ };
+
+ int mbresult = SDL_ShowMessageBox(&mbdata, &button);
+ free(msg);
+
+ if(mbresult < 0) {
+ log_sdl_error(LOG_ERROR, "SDL_ShowMessageBox");
+ } else if(button == 1) {
+ return;
+ } else if(button == 2) {
+ exit(1);
+ }
+
+ const WCHAR *cmdline = GetCommandLine();
+ const WCHAR renderer_args[] = L" --renderer gles30";
+ WCHAR new_cmdline[wcslen(cmdline) + wcslen(renderer_args) + 1];
+ memcpy(new_cmdline, cmdline, sizeof(WCHAR) * wcslen(cmdline));
+ memcpy(new_cmdline + wcslen(cmdline), renderer_args, sizeof(renderer_args));
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si = { sizeof(si) };
+
+ CreateProcessW(
+ NULL,
+ new_cmdline,
+ NULL,
+ NULL,
+ false,
+ 0,
+ NULL,
+ NULL,
+ &si,
+ &pi
+ );
+
+ exit(0);
+#endif
+}
+
void glcommon_check_capabilities(void) {
memset(&glext, 0, sizeof(glext));
@@ -632,6 +704,8 @@ void glcommon_check_capabilities(void) {
log_info("OpenGL renderer: %s", (const char*)glGetString(GL_RENDERER));
log_info("GLSL version: %s", glslv);
+ detect_broken_intel_driver();
+
// XXX: this is the legacy way, maybe we shouldn't try this first
const char *exts = (const char*)glGetString(GL_EXTENSIONS);
diff --git a/src/renderer/glescommon/gles.c b/src/renderer/glescommon/gles.c
index 9ede64fb..52682953 100644
--- a/src/renderer/glescommon/gles.c
+++ b/src/renderer/glescommon/gles.c
@@ -14,6 +14,20 @@
#include "../gl33/gl33.h"
void gles_init(RendererBackend *gles_backend, int major, int minor) {
+#ifdef TAISEI_BUILDCONF_HAVE_WINDOWS_ANGLE_FALLBACK
+ char *basepath = SDL_GetBasePath();
+ size_t basepath_len = strlen(basepath);
+ char buf[basepath_len + 32];
+ snprintf(buf, sizeof(buf), "%sANGLE\\", basepath);
+ SDL_free(basepath);
+ basepath_len += sizeof("ANGLE");
+ strlcpy(buf + basepath_len, "libGLESv2.dll", sizeof(buf) - basepath_len);
+ env_set("SDL_VIDEO_GL_DRIVER", buf, false);
+ strlcpy(buf + basepath_len, "libEGL.dll", sizeof(buf) - basepath_len);
+ env_set("SDL_VIDEO_EGL_DRIVER", buf, false);
+ env_set("SDL_OPENGL_ES_DRIVER", 1, false);
+#endif
+
_r_backend_inherit(gles_backend, &_r_backend_gl33);
glcommon_setup_attributes(SDL_GL_CONTEXT_PROFILE_ES, major, minor, 0);
glcommon_load_library();
diff --git a/src/renderer/meson.build b/src/renderer/meson.build
index 9b6555aa..83dc178f 100644
--- a/src/renderer/meson.build
+++ b/src/renderer/meson.build
@@ -61,3 +61,8 @@ endforeach
r_macro = ' '.join(r_macro)
config.set('TAISEI_BUILDCONF_RENDERER_BACKENDS', r_macro)
config.set_quoted('TAISEI_BUILDCONF_RENDERER_DEFAULT', default_renderer)
+config.set('TAISEI_BUILDCONF_HAVE_WINDOWS_ANGLE_FALLBACK',
+ host_machine.system() == 'windows' and
+ enabled_renderers.contains('gles30') and
+ get_option('install_angle')
+)
diff --git a/src/taisei.manifest b/src/taisei.manifest
new file mode 100644
index 00000000..f881defe
--- /dev/null
+++ b/src/taisei.manifest
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/taisei.rc.in b/src/taisei.rc.in
index 019ad8f2..11d6c3bb 100644
--- a/src/taisei.rc.in
+++ b/src/taisei.rc.in
@@ -2,16 +2,19 @@
#define IDS_TAISEI 1
#define IDS_REPLAY 2
-#include "winver.h"
+#include
+#include
-IDI_ICON1 ICON "${ICONS_DIR}/taisei.ico"
-IDI_ICON2 ICON "${ICONS_DIR}/taisei-replay.ico"
+IDI_ICON1 ICON "${ICON_MAIN}"
+IDI_ICON2 ICON "${ICON_REPLAY}"
STRINGTABLE BEGIN
IDS_TAISEI, "Taisei Project"
IDS_REPLAY, "Taisei Project replay"
END
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "${MANIFEST}"
+
${BUILDTYPE_DEFINE}
#ifdef DEBUG_BUILD
diff --git a/src/util/env.c b/src/util/env.c
index a53600b6..fb834ff1 100644
--- a/src/util/env.c
+++ b/src/util/env.c
@@ -32,6 +32,7 @@ const char *env_get_string_nonempty(const char *var, const char *fallback) {
}
void env_set_string(const char *var, const char *val, bool override) {
+ log_debug("%s=%s (%i)", var, val, override);
SDL_setenv(var, val, override);
}
diff --git a/src/video.c b/src/video.c
index 565b5dc4..263d2449 100644
--- a/src/video.c
+++ b/src/video.c
@@ -208,10 +208,11 @@ static void video_new_window_internal(uint display, uint w, uint h, uint32_t fla
title,
SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display),
- w, h, flags
+ w, h, flags | SDL_WINDOW_HIDDEN
);
if(video.window) {
+ SDL_ShowWindow(video.window);
SDL_SetWindowMinimumSize(video.window, SCREEN_W / 4, SCREEN_H / 4);
video_update_mode_settings();
return;