Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package sopwith for openSUSE:Factory checked in at 2025-12-08 11:56:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/sopwith (Old) and /work/SRC/openSUSE:Factory/.sopwith.new.1939 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "sopwith" Mon Dec 8 11:56:09 2025 rev:12 rq:1321462 version:2.9.0 Changes: -------- --- /work/SRC/openSUSE:Factory/sopwith/sopwith.changes 2025-04-22 17:27:31.005151628 +0200 +++ /work/SRC/openSUSE:Factory/.sopwith.new.1939/sopwith.changes 2025-12-08 11:56:57.445036465 +0100 @@ -1,0 +2,12 @@ +Sun Dec 7 08:53:03 UTC 2025 - Martin Hauke <[email protected]> + +- Update to ver 2.9.0 + * A crash was fixed when any object was destroyed in multiplayer. + * Scoring has been fixed when killing animals (it is supposed to + be negative, but because of a bug, accidentally became positive). + * The game now saves high scores to a system-wide high scores + table (if possible; or a per-user one otherwise). + * The "tailspin" animation when a plane is crashing and in a + nosedive was tweaked to add two additional frames of animation. + +------------------------------------------------------------------- Old: ---- sdl-sopwith-2.8.0.tar.gz New: ---- sdl-sopwith-2.9.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ sopwith.spec ++++++ --- /var/tmp/diff_new_pack.W4u2KP/_old 2025-12-08 11:56:58.009060095 +0100 +++ /var/tmp/diff_new_pack.W4u2KP/_new 2025-12-08 11:56:58.013060262 +0100 @@ -1,7 +1,7 @@ # # spec file for package sopwith # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2025 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: sopwith -Version: 2.8.0 +Version: 2.9.0 Release: 0 Summary: SDL port of the %{name} game License: GPL-2.0-or-later @@ -27,6 +27,7 @@ Source3: %{name}.png BuildRequires: desktop-file-utils BuildRequires: hicolor-icon-theme +BuildRequires: pkgconfig BuildRequires: pkgconfig(SDL2_gfx) BuildRequires: pkgconfig(sdl2) @@ -66,6 +67,9 @@ mkdir -p %{buildroot}%{_datadir}/%{name}/maps cp -r maps %{buildroot}%{_datadir}/%{name} +# no system-wide hiscores +rm %{buildroot}/%{_localstatedir}/games/sopwith/hiscores.txt + %files %license COPYING.md %doc FAQ.md NEWS.md README.md TODO doc/origdoc.txt ++++++ sdl-sopwith-2.8.0.tar.gz -> sdl-sopwith-2.9.0.tar.gz ++++++ ++++ 7440 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/Makefile.am new/sdl-sopwith-2.9.0/Makefile.am --- old/sdl-sopwith-2.8.0/Makefile.am 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/Makefile.am 2025-04-27 19:46:59.000000000 +0200 @@ -2,6 +2,13 @@ $(ac_aux_dir)/install-sh \ $(ac_aux_dir)/missing +# The `make distcheck` command does a simulated install to check that +# `make install` works correctly; we need to pick a different path for +# the high scores directory, otherwise we will likely get permissions +# errors with the default path: +AM_DISTCHECK_CONFIGURE_FLAGS = \ + "--with-hiscores-path=$$dc_install_base/hiscores" + DOC_FILES= \ COPYING.md \ FAQ.md \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/NEWS.md new/sdl-sopwith-2.9.0/NEWS.md --- old/sdl-sopwith-2.8.0/NEWS.md 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/NEWS.md 2025-12-06 23:54:35.000000000 +0100 @@ -1,3 +1,16 @@ +# v2.9.0 (2025-12-06) + + * A crash was fixed when any object was destroyed in multiplayer (thanks to + @alphanumericcharter and @scandox for reporting this bug). + * Scoring has been fixed when killing animals (it is supposed to be negative, + but because of a bug, accidentally became positive). + * The game now saves high scores to a system-wide high scores table (if + possible; or a per-user one otherwise). + * The "tailspin" animation when a plane is crashing and in a nosedive was + tweaked to add two additional frames of animation. + * Various Emscripten fixes were made; the previous release had to be rolled + back from the website because of them. + # v2.8.0 (2025-03-21) * Gamepad support was added. This uses the SDL Game Controller API, so it diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/autotools/compile new/sdl-sopwith-2.9.0/autotools/compile --- old/sdl-sopwith-2.8.0/autotools/compile 2025-03-21 20:53:00.000000000 +0100 +++ new/sdl-sopwith-2.9.0/autotools/compile 2025-04-27 19:49:04.000000000 +0200 @@ -1,9 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2018-03-07.03; # UTC +scriptversion=2024-06-19.01; # UTC -# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# Copyright (C) 1999-2024 Free Software Foundation, Inc. # Written by Tom Tromey <[email protected]>. # # This program is free software; you can redistribute it and/or modify @@ -143,7 +143,7 @@ # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in - *.o | *.[oO][bB][jJ]) + *.o | *.lo | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift @@ -248,14 +248,17 @@ right script to run: please start by reading the file 'INSTALL'. Report bugs to <[email protected]>. +GNU Automake home page: <https://www.gnu.org/software/automake/>. +General help using GNU software: <https://www.gnu.org/gethelp/>. EOF exit $? ;; -v | --v*) - echo "compile $scriptversion" + echo "compile (GNU Automake) $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + clang-cl | *[/\\]clang-cl | clang-cl.exe | *[/\\]clang-cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/autotools/missing new/sdl-sopwith-2.9.0/autotools/missing --- old/sdl-sopwith-2.8.0/autotools/missing 2025-03-21 20:53:00.000000000 +0100 +++ new/sdl-sopwith-2.9.0/autotools/missing 2025-04-27 19:49:05.000000000 +0200 @@ -1,9 +1,11 @@ #! /bin/sh -# Common wrapper for a few potentially missing GNU programs. +# Common wrapper for a few potentially missing GNU and other programs. -scriptversion=2018-03-07.03; # UTC +scriptversion=2024-06-07.14; # UTC -# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# shellcheck disable=SC2006,SC2268 # we must support pre-POSIX shells + +# Copyright (C) 1996-2024 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard <[email protected]>, 1996. # This program is free software; you can redistribute it and/or modify @@ -54,18 +56,20 @@ -v, --version output version information and exit Supported PROGRAM values: - aclocal autoconf autoheader autom4te automake makeinfo - bison yacc flex lex help2man +aclocal autoconf autogen autoheader autom4te automake autoreconf +bison flex help2man lex makeinfo perl yacc Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. -Send bug reports to <[email protected]>." +Report bugs to <[email protected]>. +GNU Automake home page: <https://www.gnu.org/software/automake/>. +General help using GNU software: <https://www.gnu.org/gethelp/>." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" + echo "missing (GNU Automake) $scriptversion" exit $? ;; @@ -108,7 +112,7 @@ program_details () { case $1 in - aclocal|automake) + aclocal|automake|autoreconf) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" @@ -123,6 +127,9 @@ echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; + *) + : + ;; esac } @@ -137,48 +144,55 @@ printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + autoheader_deps="'acconfig.h'" + automake_deps="'Makefile.am'" + aclocal_deps="'acinclude.m4'" case $normalized_program in + aclocal*) + echo "You should only need it if you modified $aclocal_deps or" + echo "$configure_deps." + ;; autoconf*) - echo "You should only need it if you modified 'configure.ac'," - echo "or m4 files included by it." - program_details 'autoconf' + echo "You should only need it if you modified $configure_deps." + ;; + autogen*) + echo "You should only need it if you modified a '.def' or '.tpl' file." + echo "You may want to install the GNU AutoGen package:" + echo "<$gnu_software_URL/autogen/>" ;; autoheader*) - echo "You should only need it if you modified 'acconfig.h' or" + echo "You should only need it if you modified $autoheader_deps or" echo "$configure_deps." - program_details 'autoheader' ;; automake*) - echo "You should only need it if you modified 'Makefile.am' or" - echo "$configure_deps." - program_details 'automake' - ;; - aclocal*) - echo "You should only need it if you modified 'acinclude.m4' or" + echo "You should only need it if you modified $automake_deps or" echo "$configure_deps." - program_details 'aclocal' ;; - autom4te*) + autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." - program_details 'autom4te' + ;; + autoreconf*) + echo "You should only need it if you modified $aclocal_deps or" + echo "$automake_deps or $autoheader_deps or $automake_deps or" + echo "$configure_deps." ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; - lex*|flex*) - echo "You should only need it if you modified a '.l' file." - echo "You may want to install the Fast Lexical Analyzer package:" - echo "<$flex_URL>" - ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." @@ -189,6 +203,12 @@ echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; + perl*) + echo "You should only need it to run GNU Autoconf, GNU Automake, " + echo " assorted other tools, or if you modified a Perl source file." + echo "You may want to install the Perl 5 language interpreter:" + echo "<$perl_URL>" + ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" @@ -197,6 +217,7 @@ echo "case some other package contains this missing '$1' program." ;; esac + program_details "$normalized_program" } give_advice "$1" | sed -e '1s/^/WARNING: /' \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/config.hin new/sdl-sopwith-2.9.0/config.hin --- old/sdl-sopwith-2.8.0/config.hin 2025-03-21 20:53:00.000000000 +0100 +++ new/sdl-sopwith-2.9.0/config.hin 2025-12-07 00:08:57.000000000 +0100 @@ -3,7 +3,7 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H -/* Define to 1 if you have the `isatty' function. */ +/* Define to 1 if you have the 'isatty' function. */ #undef HAVE_ISATTY /* Define to 1 if you have the <netinet/in.h> header file. */ @@ -39,6 +39,9 @@ /* Define to 1 if you have the <winsock.h> header file. */ #undef HAVE_WINSOCK_H +/* Path to directory containing high scores file. */ +#undef HISCORES_PATH + /* Name of package */ #undef PACKAGE @@ -60,7 +63,7 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* Define to 1 if all of the C90 standard headers exist (not just the ones +/* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/configure.ac new/sdl-sopwith-2.9.0/configure.ac --- old/sdl-sopwith-2.8.0/configure.ac 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/configure.ac 2025-12-06 23:54:35.000000000 +0100 @@ -1,4 +1,4 @@ -AC_INIT([SDL Sopwith], [2.8.0], [[email protected]], [sdl-sopwith]) +AC_INIT([SDL Sopwith], [2.9.0], [[email protected]], [sdl-sopwith]) AC_CONFIG_AUX_DIR(autotools) VERSION=$CONFIG_VERSION @@ -58,6 +58,24 @@ ;; esac +case "$host" in + *cygwin* | *mingw* | *emscripten* | *haiku*) + HISCORES_PATH= + ;; + *) + HISCORES_PATH=/var/games/sopwith + ;; +esac +AC_ARG_WITH([hiscores-path], + [AS_HELP_STRING([--with-hiscores-path=dir], + [directory for system-wide high scores file])], + [HISCORES_PATH=${with_hiscores_path}], []) +AC_SUBST(HISCORES_PATH) + +AM_CONDITIONAL(GLOBAL_HISCORES, test "$HISCORES_PATH" != "") +AC_DEFINE_UNQUOTED(HISCORES_PATH, "$HISCORES_PATH", + [Path to directory containing high scores file.]) + AM_CONDITIONAL(HAVE_WINDRES, test "$WINDRES" != "") AM_CONDITIONAL(HAVE_CONVERT, test "$CONVERT" != "") AC_CONFIG_HEADERS([config.h:config.hin]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/doc/sopwith.6 new/sdl-sopwith-2.9.0/doc/sopwith.6 --- old/sdl-sopwith-2.8.0/doc/sopwith.6 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/doc/sopwith.6 2025-12-06 23:54:35.000000000 +0100 @@ -120,14 +120,36 @@ Ctrl+C Ctrl+C Ctrl+C quit immediately . +.SH SCORING +.PP +Playing the game, you can rack up a score based on targets destroyed. You +\fIlose\fR the same number of points if your own targets get destroyed. The +scoring is as follows: +.TP +Enemy Plane +50 points +.TP +Ground target +100 points +.TP +Oil tank +200 points +.TP +Planes left over when completing a level +25 points each +.PP +If you do very well, you may obtain a high score! The high score is shown on +the title screen of the game after 10 seconds. High scores are stored in the +high score file: \fI~/.local/share/SDL Sopwith/hiscores.txt\fR +. .SH DASHBOARD At the bottom of the screen, the plane's dashboard is shown. This consists of several components: .TP Score Your current score, which is accumulated from the enemy targets and planes you -have successfully destroyed. In multiplayer two scores are shown, so that both -players can see each others' scores. +have successfully destroyed (see \fBSCORING\fR above). In multiplayer two +scores are shown, so that both players can see each others' scores. .TP Lives (Cyan) Number of lives remaining. You have five lives. @@ -286,6 +308,19 @@ https://github.com/fragglet/sdl-sopwith .UE . +.SH FILES +.TP +~/.local/share/SDL Sopwith/sopwith.cfg +Configuration file. See \fBsopwith.cfg\fR(5). +.TP +/var/games/sopwith/hiscores.txt +High scores file. This is shared between all users on the system. However, the +file is usually installed world-writable, so be aware that it's possible for +others to cheat and edit their names into the list. +.TP +~/.local/share/SDL Sopwith/hiscores.txt +Alternate high scores file. If the system-wide high scores file doesn't exist, +the game will save one here instead. .SH SEE ALSO \fBsopwith.cfg\fR(5), \fBsopwith-mission\fR(5), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/embuild.sh new/sdl-sopwith-2.9.0/embuild.sh --- old/sdl-sopwith-2.8.0/embuild.sh 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/embuild.sh 2025-04-27 19:46:59.000000000 +0200 @@ -22,7 +22,7 @@ export PKG_CONFIG_PATH=$EM_CACHE/pkg export PATH="$EM_CACHE/bin:$PATH" export CFLAGS="-fexceptions -sSUPPORT_LONGJMP=emscripten" -export LDFLAGS="-flto -sASYNCIFY -sENVIRONMENT=web -lidbfs.js -Wl,-u,ntohs $CFLAGS" +export LDFLAGS="-flto -sASYNCIFY -sFORCE_FILESYSTEM -sEXPORTED_FUNCTIONS=_main -sENVIRONMENT=web -lidbfs.js -Wl,-u,ntohs $CFLAGS" # The first time creating the cache directory, we make a copy of the # one already installed on the system, to avoid having to rebuild all diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/maps/original.sop new/sdl-sopwith-2.9.0/maps/original.sop --- old/sdl-sopwith-2.8.0/maps/original.sop 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/maps/original.sop 2025-12-06 23:54:35.000000000 +0100 @@ -113,6 +113,42 @@ " - * * - \n"& " * * * - \n"& " * * * \n" + + 2: + " - - - - * * - - - - \n"& + " - - - * * - - - \n"& + " - - * * - - \n"& + " * * \n"& + " * * \n"& + " * * \n"& + " * * * * \n"& + " * * * * \n"& + " * * * * \n"& + " * * * * \n"& + "- - - - - - - - - - - - - - \n"& + " - - - - - - - - - - - - - - - \n"& + "- - - - - - - - - - - - - - - - \n"& + "- - - - - - - - - - - - - - - \n"& + " * * * * \n"& + " * * * * \n" + + 3: + " * * * - \n"& + " * * * - * \n"& + " * * * - * * * \n"& + " * * - * * \n"& + " * - * * \n"& + " * * * \n"& + " * * * \n"& + " * * * \n"& + " - * * - \n"& + " - * * - \n"& + " - - - - - * \n"& + " - * * - * * * \n"& + " - - - - - * \n"& + " - * * - \n"& + " - * * * \n"& + " * * * \n" } swwinsym { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/Makefile.am new/sdl-sopwith-2.9.0/src/Makefile.am --- old/sdl-sopwith-2.8.0/src/Makefile.am 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/Makefile.am 2025-12-06 23:54:35.000000000 +0100 @@ -2,7 +2,7 @@ IWYU_FLAGS = --error --mapping_file=.iwyu-overrides.imp IWYU_TRANSFORMED_FLAGS = $(patsubst %,-Xiwyu %,$(IWYU_FLAGS)) $(CFLAGS) -EXTRA_DIST = sopwith.ico +EXTRA_DIST = sopwith.ico hiscores.txt appdir = $(prefix)/share/applications dist_app_DATA = sopwith.desktop @@ -41,6 +41,7 @@ swsymbol.c swsymbol.h \ swtext.c swtext.h \ swtitle.c swtitle.h \ + hiscore.c hiscore.h \ tcpcomm.c tcpcomm.h \ timer.h \ touch_area.c \ @@ -73,3 +74,16 @@ convert $< $@ endif +if GLOBAL_HISCORES +hiscoresdir = $(HISCORES_PATH) +hiscores_DATA = hiscores.txt + +# Note: we install the high scores file as world-writable; we used to install +# it as owned by the `games` user, with the Sopwith binary installed as setgid +# `games`. However, we can't do this because the Gtk+ team have an ideological +# opposition to the setgid mechanism (bug #57). +install-data-hook: + @chmod 666 "$(DESTDIR)$(HISCORES_PATH)/hiscores.txt" || \ + echo "*** WARNING: Failed to set permissions for system-wide high" \ + "scores file. High scores will have to be per-user." +endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/hiscore.c new/sdl-sopwith-2.9.0/src/hiscore.c --- old/sdl-sopwith-2.8.0/src/hiscore.c 1970-01-01 01:00:00.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/hiscore.c 2025-12-06 23:54:35.000000000 +0100 @@ -0,0 +1,399 @@ +// +// Copyright(C) 2025 Simon Howard +// +// You can redistribute and/or modify this program under the terms of the +// GNU General Public License version 2 as published by the Free Software +// Foundation, or any later version. This program is distributed WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// +// High score table +// + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <errno.h> + +#include "sw.h" + +#include "hiscore.h" +#include "swgames.h" +#include "swmain.h" +#include "swsound.h" +#include "swtext.h" +#include "swtitle.h" +#include "video.h" + +#define HISCORE_FILENAME "hiscores.txt" +#define MAX_HIGH_SCORES 10 + +#define TABLE_X 9 +#define TABLE_Y 1 + +struct high_score { + char name[4]; + score_t score; +}; + +struct high_score high_scores[MAX_HIGH_SCORES] = { + {"DLC", {6500}}, // David L. Clark + {"DG", {6000}}, // Dave Growden (Ox) + {"JHC", {5500}}, // Jack Cole + {"JS", {5000}}, // Jesse Smith + {"JH", {4500}}, // Josh Horowitz + {"CR", {4000}}, // Christoph Reichenbach + {"AMJ", {3500}}, // Andrew Jenner + {"HJM", {3000}}, // Harry Mason + {"BMB", {2500}}, + {"SDH", {2000}}, // Simon Howard +}; + +static int UnpackMedals(int input, int *medals, int max_medals) +{ + int i, result = 0; + + for (i = 0; i < max_medals; ++i) { + if ((input & (1 << i)) != 0) { + medals[result] = i; + ++result; + } + } + + return result; +} + +static bool ReadLine(FILE *fs, char *buf, size_t buf_len) +{ + char tmpbuf[8]; + + if (feof(fs) || fgets(buf, buf_len, fs) == NULL) { + return false; + } + // Long line? Keep reading chunks until we reach the end + if (strchr(buf, '\n') == NULL) { + do { + fgets(tmpbuf, sizeof(tmpbuf), fs); + } while (!feof(fs) && strchr(tmpbuf, '\n') == NULL); + } + return true; +} + +static bool LoadHighScores(const char *filename) +{ + struct high_score *hs; + char line[64]; + FILE *fs; + int idx, medals, ribbons; + + fs = fopen(filename, "r"); + if (fs == NULL) { + return false; + } + + idx = 0; + while (idx < MAX_HIGH_SCORES && ReadLine(fs, line, sizeof(line))) { + hs = &high_scores[idx]; + // Comment? + if (line[0] == '#') { + continue; + } + if (sscanf(line, "%3s %d %d %d", hs->name, + &hs->score.score, &medals, &ribbons) < 4) { + continue; + } + hs->score.medals_nr = + UnpackMedals(medals, hs->score.medals, 3); + hs->score.ribbons_nr = + UnpackMedals(ribbons, hs->score.ribbons, 6); + ++idx; + } + + fclose(fs); + + return true; +} + +static int PackMedals(const int *medals, int cnt) +{ + int i, result = 0; + + for (i = 0; i < cnt; ++i) { + result |= 1 << medals[i]; + } + + return result; +} + +static bool SaveHighScores(const char *filename) +{ + const struct high_score *hs; + FILE *fs; + int i; + + fs = fopen(filename, "w"); + if (fs == NULL) { + perror("Failed to write high scores: fopen"); + return false; + } + fprintf(fs, "# Sopwith high scores file, generated by " + PACKAGE_STRING"\n"); + + for (i = 0; i < MAX_HIGH_SCORES; ++i) { + hs = &high_scores[i]; + fprintf(fs, "%-3.3s %7d %d %2d\n", hs->name, hs->score.score, + PackMedals(hs->score.medals, hs->score.medals_nr), + PackMedals(hs->score.ribbons, hs->score.ribbons_nr)); + } + + return true; +} + +static const char *HighScoreFilePath(void) +{ + static char *hiscore_file = NULL; + size_t len; + char *pref_path; + + if (hiscore_file != NULL) { + return hiscore_file; + } + + // If there is a global high scores file on the system, we will + // use that instead of the home directory one. + if (strlen(HISCORES_PATH) > 0) { + FILE *fs; + char *p = HISCORES_PATH "/" HISCORE_FILENAME; + fs = fopen(p, "r+"); + if (fs != NULL) { + fclose(fs); + hiscore_file = p; + return hiscore_file; + } + // We print a warning message if the file does appear to + // exist but we can't write to it for some reason. + if (errno != ENOENT) { + fprintf(stderr, "Error opening the system-wide high " + "scores file (%s): %s. The file might not " + "have the necessary permissions set for this " + "program to write to it.\n", + p, strerror(errno)); + } + } + + pref_path = Vid_GetPrefPath(); + if (pref_path == NULL) { + return HISCORE_FILENAME; + } + + len = strlen(pref_path) + strlen(HISCORE_FILENAME) + 1; + hiscore_file = calloc(1, len); + assert(hiscore_file != NULL); + snprintf(hiscore_file, len, "%s%s", pref_path, HISCORE_FILENAME); + return hiscore_file; +} + +void LoadHighScoreTable(void) +{ + LoadHighScores(HighScoreFilePath()); +} + +void SaveHighScoreTable(void) +{ + SaveHighScores(HighScoreFilePath()); +} + +void InitHighScores(void) +{ + score_t *s; + int i, m, cnt; + + // At startup, every entry in the high score table gets assigned + // a smattering of random medals and ribbons: + for (i = 0; i < MAX_HIGH_SCORES; ++i) { + s = &high_scores[i].score; + for (m = 0, cnt = 0; m < 2; ++m) { + if (s->score > rand() % 4500) { + s->medals[cnt] = m + 1; + ++cnt; + } + } + s->medals_nr = cnt; + for (m = 0, cnt = 0; m < 6; ++m) { + if (s->score > rand() % 6500) { + s->ribbons[cnt] = m; + ++cnt; + } + } + s->ribbons_nr = cnt; + } + + // Try to load the high score table file, if one exists. + LoadHighScoreTable(); +} + +static void DrawHighScore(const struct high_score *hs, int x, int y) +{ + int px, py, m; + char buf[20]; + + swposcur(x, y); + snprintf(buf, sizeof(buf), "%-3.3s ....... %-4d", + hs->name, hs->score.score); + swputs(buf); + + if (!conf_medals) { + return; + } + + px = (x + 16) * 8 + 4; + py = (SCR_HGHT - 1) - y * 8 + 5; + + for (m = 0; m < hs->score.medals_nr; ++m) { + symset_t *ss = &symbol_medal[hs->score.medals[m]]; + Vid_DispSymbol(px + m * 8, py, &ss->sym[0], + FACTION_PLAYER1); + } + + // Medal symbols are 12 characters tall, but each line is + // only 8 characters tall. The top part of the medal symbol + // gets cut off so that we can pack all the medals in; we do + // this by drawing a black box over the top of it. + Vid_Box(px, py, 32, 4, 0); + + for (m = 0; m < hs->score.ribbons_nr; ++m) { + symset_t *ss = &symbol_ribbon[hs->score.ribbons[m]]; + int rx = (m / 2) * 8, ry = (m % 2) * 4 + 6; + Vid_DispSymbol(px + 18 + rx, py - ry, &ss->sym[0], + FACTION_PLAYER1); + } +} + +void DrawHighScoreTable(void) +{ + int i; + +#ifdef HISCORE_DEBUG + for (i = 0; i < MAX_HIGH_SCORES; ++i) { + int m; + high_scores[i].score.medals_nr = 2; + high_scores[i].score.medals[0] = MEDAL_COMPETENCE; + high_scores[i].score.medals[1] = MEDAL_VALOUR; + for (m = 0; m < 6; ++m) { + high_scores[i].score.ribbons[m] = m; + } + high_scores[i].score.ribbons_nr = 6; + } +#endif + + swcolor(2); + swposcur(TABLE_X + 3, TABLE_Y); + swputs("TOP PILOTS"); + + swcolor(3); + + // We draw the table bottom up. See comment in DrawHighScore for why. + for (i = MAX_HIGH_SCORES - 1; i >= 0; i--) { + DrawHighScore(&high_scores[i], TABLE_X, TABLE_Y + 2 + i); + } +} + +static int CompareHighScores(const struct high_score *a, + const struct high_score *b) +{ + if (a->score.score != b->score.score) { + return a->score.score - b->score.score; + } + if (a->score.medals_nr != b->score.medals_nr) { + return a->score.medals_nr - b->score.medals_nr; + } + if (a->score.ribbons_nr != b->score.ribbons_nr) { + return a->score.ribbons_nr - b->score.ribbons_nr; + } + return 0; +} + +// NewHighScoreIndex returns the index in the high_scores[] array where the +// new high score should be inserted, or -1 if it is not a new high score. +static int NewHighScoreIndex(const struct high_score *hs) +{ + int i; + + for (i = 0; i < MAX_HIGH_SCORES; ++i) { + if (CompareHighScores(hs, &high_scores[i]) > 0) { + return i; + } + } + + return -1; +} + +static bool IsNewHighScore(const struct high_score *hs) +{ + return NewHighScoreIndex(hs) >= 0; +} + +static bool EnterHighScore(struct high_score *hs) +{ + char *p; + + // TODO: Add a new music track for the high score screen? + soundoff(); + + Vid_ClearBuf(); + DrawHighScoreTable(); + + swcolor(2); + swposcur(2, 15); + swputs("NEW HIGH SCORE!"); + swcolor(3); + swposcur(2, 17); + DrawHighScore(hs, TABLE_X, 17); + + swposcur(TABLE_X - 1, 17); + swputs("[ ]"); + clrprmpt(); + swposcur(TABLE_X, 17); + swgets(hs->name, sizeof(hs->name) - 1); + + for (p = hs->name; *p != '\0'; ++p) { + *p = toupper(*p); + } + + return strlen(hs->name) > 0; +} + +// NewHighScore checks if the given score is actually a new high score, and if +// so: prompts the user for their name and adds it. +bool NewHighScore(score_t *s) +{ + struct high_score new_hs = {"", *s}; + int idx; + + // High scores only apply to the default version of the game. + if (playmode != PLAYMODE_COMPUTER + || currgame != &original_level + || conf_missiles || conf_wounded || !conf_animals + || !conf_big_explosions) { + return false; + } + if (!IsNewHighScore(&new_hs)) { + return false; + } + if (!EnterHighScore(&new_hs)) { + return false; + } + + idx = NewHighScoreIndex(&new_hs); + if (idx < 0) { + return false; + } + memmove(&high_scores[idx + 1], &high_scores[idx], + sizeof(struct high_score) * (MAX_HIGH_SCORES - 1 - idx)); + high_scores[idx] = new_hs; + SaveHighScoreTable(); + + return true; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/hiscore.h new/sdl-sopwith-2.9.0/src/hiscore.h --- old/sdl-sopwith-2.8.0/src/hiscore.h 1970-01-01 01:00:00.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/hiscore.h 2025-04-27 19:47:00.000000000 +0200 @@ -0,0 +1,25 @@ +// +// Copyright(C) 2025 Simon Howard +// +// You can redistribute and/or modify this program under the terms of the +// GNU General Public License version 2 as published by the Free Software +// Foundation, or any later version. This program is distributed WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// +// High score table +// + +#ifndef __HISCORE_H__ +#define __HISCORE_H__ + +#include "sw.h" + +extern void DrawHighScoreTable(void); +extern void LoadHighScoreTable(void); +extern void SaveHighScoreTable(void); +extern bool NewHighScore(score_t *s); +extern void InitHighScores(void); + +#endif /* #ifndef __HISCORE_H__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/hiscores.txt new/sdl-sopwith-2.9.0/src/hiscores.txt --- old/sdl-sopwith-2.8.0/src/hiscores.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/hiscores.txt 2025-04-27 19:47:00.000000000 +0200 @@ -0,0 +1,11 @@ +# Sopwith high scores file (default scores) +DLC 6500 6 63 +DG 6000 6 63 +JHC 5500 6 43 +JS 5000 6 59 +JH 4500 6 46 +CR 4000 4 5 +AMJ 3500 6 49 +HJM 3000 4 52 +BMB 2500 2 7 +SDH 2000 2 56 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/io.github.fragglet.sdl_sopwith.metainfo.xml new/sdl-sopwith-2.9.0/src/io.github.fragglet.sdl_sopwith.metainfo.xml --- old/sdl-sopwith-2.8.0/src/io.github.fragglet.sdl_sopwith.metainfo.xml 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/io.github.fragglet.sdl_sopwith.metainfo.xml 2025-12-06 23:54:35.000000000 +0100 @@ -40,6 +40,21 @@ </screenshot> </screenshots> <releases> + <release version="2.9.0" date="2025-12-06"> + <url>https://github.com/fragglet/sdl-sopwith/releases/tag/sdl-sopwith-2.9.0</url> + <description> + <p>A crash was fixed when any object was destroyed in multiplayer (thanks to + @alphanumericcharter and @scandox for reporting this bug).</p> + <p>Scoring has been fixed when killing animals (it is supposed to be negative, + but because of a bug, accidentally became positive).</p> + <p>The game now saves high scores to a system-wide high scores table (if + possible; or a per-user one otherwise).</p> + <p>The "tailspin" animation when a plane is crashing and in a nosedive was + tweaked to add two additional frames of animation.</p> + <p>Various Emscripten fixes were made; the previous release had to be rolled + back from the website because of them.</p> + </description> + </release> <release version="2.8.0" date="2025-03-21"> <url>https://github.com/fragglet/sdl-sopwith/releases/tag/sdl-sopwith-2.8.0</url> <description> @@ -118,23 +133,5 @@ <p>The help screen is no longer shown when aborting the game.</p> </description> </release> - <release version="2.2.0" date="2023-05-17"> - <url>https://github.com/fragglet/sdl-sopwith/releases/tag/sdl-sopwith-2.2.0</url> - <description> - <p>Help text is now shown for new players. This is shown on game start in -novice mode, but won't be shown again after a successful flight. The help -text will also appear in other single player modes, but only if it looks -like you're really struggling to get the plane off the ground.</p> - <p>It's no longer possible to flip the plane upside down while sitting -motionless on the runway (a bug since the original DOS versions).</p> - <p>It's no longer possible to get wounded on the ground. If a plane shoots -another on the ground, that's a successful raid. This fixes a bug where -a wounded plane on the runway would still be damaged after takeoff.</p> - <p>The game no longer freezes up in multiplayer mode if the other player -quits. When establishing a connection, a helpful message is shown about how -to abort.</p> - <p>If the game quits with an error, a friendly dialog box now shows the error.</p> - </description> - </release> </releases> </component> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/resource.rc new/sdl-sopwith-2.9.0/src/resource.rc --- old/sdl-sopwith-2.8.0/src/resource.rc 2025-03-21 20:53:02.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/resource.rc 2025-12-07 00:08:55.000000000 +0100 @@ -9,12 +9,12 @@ { BLOCK "040904E4" { - VALUE "FileVersion", "2.8.0.0" - VALUE "FileDescription", "SDL Sopwith 2.8.0" + VALUE "FileVersion", "2.9.0.0" + VALUE "FileDescription", "SDL Sopwith 2.9.0" VALUE "InternalName", "sdl-sopwith" VALUE "LegalCopyright", "Copyright (C) 1984-2024. Licensed under GNU General Public License, version 2" VALUE "ProductName", "SDL Sopwith" - VALUE "ProductVersion", "2.8.0" + VALUE "ProductVersion", "2.9.0" } } BLOCK "VarFileInfo" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/swcollsn.c new/sdl-sopwith-2.9.0/src/swcollsn.c --- old/sdl-sopwith-2.8.0/src/swcollsn.c 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/swcollsn.c 2025-12-06 23:54:35.000000000 +0100 @@ -122,17 +122,17 @@ static OBJECTS *GetScoreObject(OBJECTS *ob, int *reverse) { OBJECTS *retval; - *reverse = 0; if (playmode != PLAYMODE_ASYNCH) { retval = planes[0]; - if (ob->ob_faction == FACTION_PLAYER1) { - *reverse = 1; - } + *reverse = ob->ob_faction == FACTION_PLAYER1 + || ob->ob_faction == FACTION_NONE; } else { // TODO: Support more than two factions. - retval = planes[ob->ob_faction == FACTION_PLAYER1 ? - FACTION_PLAYER2 : FACTION_PLAYER1]; + retval = planes[ob->ob_faction == FACTION_PLAYER1 ? 1 : 0]; + // TODO: This always penalizes player 1 when animals are + // killed, even if it was player 2 that killed the animal. + *reverse = ob->ob_faction == FACTION_NONE; } return retval; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/swinit.c new/sdl-sopwith-2.9.0/src/swinit.c --- old/sdl-sopwith-2.8.0/src/swinit.c 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/swinit.c 2025-04-27 19:47:00.000000000 +0200 @@ -17,6 +17,7 @@ #include <time.h> #include <assert.h> +#include "hiscore.h" #include "pcsound.h" #include "timer.h" #include "video.h" @@ -1120,12 +1121,11 @@ void swrestart(void) { - OBJECTS *ob; + OBJECTS *ob = planes[player]; int inc; int time; - + if (consoleplayer->ob_endsts == WINNER) { - ob = planes[player]; inc = 0; GetEndLevel(ob); @@ -1147,6 +1147,8 @@ savescore = ob->ob_score; have_savescore = true; } else { + NewHighScore(&ob->ob_score); + // gamenum = 0; // allow variable start level -- Jesse gamenum = starting_level; @@ -1244,6 +1246,7 @@ Timer_Init(); Vid_Init(); Vid_SetVideoPalette(conf_video_palette); + InitHighScores(); // Don't init speaker if started with -q (quiet) if (soundflg) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/swmove.c new/sdl-sopwith-2.9.0/src/swmove.c --- old/sdl-sopwith-2.8.0/src/swmove.c 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/swmove.c 2025-12-06 23:54:35.000000000 +0100 @@ -460,7 +460,7 @@ } else if (ob->ob_dx > 0) { --ob->ob_dx; } else { - ob->ob_orient = !ob->ob_orient; + ++ob->ob_orient; } } @@ -622,7 +622,7 @@ } else if (ob->ob_state == FINISHED) { ob->ob_symbol = NULL; } else if (ob->ob_state == FALLING && !ob->ob_dx && ob->ob_dy < 0) { - ob->ob_symbol = &symbol_plane_hit[ob->ob_orient].sym[0]; + ob->ob_symbol = &symbol_plane_hit[ob->ob_orient % 4].sym[0]; } else if (ob->ob_orient) { // Flipped: int a = (16 - ob->ob_angle) % 16; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/swsound.c new/sdl-sopwith-2.9.0/src/swsound.c --- old/sdl-sopwith-2.8.0/src/swsound.c 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/swsound.c 2025-04-27 19:47:00.000000000 +0200 @@ -211,7 +211,7 @@ ob->ob_sound = NULL; } -static void soundoff(void) +void soundoff(void) { if (lastfreq) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/swsound.h new/sdl-sopwith-2.9.0/src/swsound.h --- old/sdl-sopwith-2.8.0/src/swsound.h 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/swsound.h 2025-04-27 19:47:00.000000000 +0200 @@ -27,6 +27,7 @@ extern void swsound(void); extern void initsound(OBJECTS *obp, int type); extern void stopsound(OBJECTS *ob); +extern void soundoff(void); extern void swsndupdate(void); extern OBJECTS *ob; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/swsymbol.c new/sdl-sopwith-2.9.0/src/swsymbol.c --- old/sdl-sopwith-2.8.0/src/swsymbol.c 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/swsymbol.c 2025-12-06 23:54:35.000000000 +0100 @@ -127,6 +127,40 @@ " - * * - \n" " * * * - \n" " * * * \n", + // ------------------------------- + " - - - - * * - - - - \n" + " - - - * * - - - \n" + " - - * * - - \n" + " * * \n" + " * * \n" + " * * \n" + " * * * * \n" + " * * * * \n" + " * * * * \n" + " * * * * \n" + "- - - - - - - - - - - - - - \n" + " - - - - - - - - - - - - - - - \n" + "- - - - - - - - - - - - - - - - \n" + "- - - - - - - - - - - - - - - \n" + " * * * * \n" + " * * * * \n", + // ------------------------------- + " * * * - \n" + " * * * - * \n" + " * * * - * * * \n" + " * * - * * \n" + " * - * * \n" + " * * * \n" + " * * * \n" + " * * * \n" + " - * * - \n" + " - * * - \n" + " - - - - - * \n" + " - * * - * * * \n" + " - - - - - * \n" + " - * * - \n" + " - * * * \n" + " * * * \n", }; static const char *swwinsym[] = { /* Win plane pixel array */ @@ -1172,7 +1206,7 @@ symset_t symbol_missile[4]; // swmscsym symset_t symbol_burst[2]; // swbstsym symset_t symbol_plane[4]; // swplnsym -symset_t symbol_plane_hit[2]; // swhitsym +symset_t symbol_plane_hit[4]; // swhitsym symset_t symbol_plane_win[4]; // swwinsym symset_t symbol_medal[3]; // swmedalsym symset_t symbol_ribbon[6]; // swribbonsym diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/swsymbol.h new/sdl-sopwith-2.9.0/src/swsymbol.h --- old/sdl-sopwith-2.8.0/src/swsymbol.h 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/swsymbol.h 2025-12-06 23:54:35.000000000 +0100 @@ -49,7 +49,7 @@ extern symset_t symbol_missile[4]; // swmscsym extern symset_t symbol_burst[2]; // swbstsym extern symset_t symbol_plane[4]; // swplnsym -extern symset_t symbol_plane_hit[2]; // swhitsym +extern symset_t symbol_plane_hit[4]; // swhitsym extern symset_t symbol_plane_win[4]; // swwinsym extern symset_t symbol_medal[3]; // swmedalsym extern symset_t symbol_ribbon[6]; // swribbonsym diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/sdl-sopwith-2.8.0/src/swtitle.c new/sdl-sopwith-2.9.0/src/swtitle.c --- old/sdl-sopwith-2.8.0/src/swtitle.c 2025-03-21 20:52:58.000000000 +0100 +++ new/sdl-sopwith-2.9.0/src/swtitle.c 2025-04-27 19:47:00.000000000 +0200 @@ -21,6 +21,7 @@ #include "video.h" +#include "hiscore.h" #include "sw.h" #include "swasynio.h" #include "swconf.h" @@ -34,20 +35,19 @@ #include "swsound.h" #include "swsymbol.h" #include "swtitle.h" +#include "timer.h" + +// How many milliseconds from when the title screen appears to when the high +// score table gets shown? +#define HIGH_SCORE_PERIOD 10000 #define X_OFFSET ((SCR_WDTH/2)-160) -void swtitln(void) +static int title_screen_start; + +static void DrawTitleScreenContent(void) { const char *version_string; - GRNDTYPE *orground = original_level.gm_ground; - - int i, h; - - sound(S_TITLE, 0, NULL); - - // clear the screen - Vid_ClearBuf(); swcolor(2); swposcur(18+X_OFFSET/8, 2); @@ -85,6 +85,26 @@ swputs("GNU"); swcolor(3); swputs(" GPL"); +} + +void swtitln(void) +{ + GRNDTYPE *orground = original_level.gm_ground; + int i, h; + + sound(S_TITLE, 0, NULL); + + // clear the screen + Vid_ClearBuf(); + + // We show the title screen, but after five seconds it switches to the + // high score table instead. + i = Timer_GetMS() - title_screen_start; + if ((i / HIGH_SCORE_PERIOD) % 2 == 0) { + DrawTitleScreenContent(); + } else { + DrawHighScoreTable(); + } swground(orground, 507 - X_OFFSET); @@ -257,6 +277,7 @@ void getgamemode(void) { + title_screen_start = Timer_GetMS(); playmode = PLAYMODE_UNSET; while (playmode == PLAYMODE_UNSET) { RunMenu(&main_menu);
