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);

Reply via email to