Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • KartKrew/RingRacers
  • bitten2up/RingRacers
  • X.organic/RingRacers
  • StarManiaKG/the-story-of-subsequent-tutorials-and-dance-dance-revolutions-remastered-rocking-the-4th
  • LoganAir/RingRacers
  • Hanicef/RingRacers
  • aa/RingRacers
  • JugadorXEI/RingRacers
  • Jisk/RingRacers
  • Callmore/RingRacers
  • Lugent/RingRacers
  • Chopp/ring-racers-cope
  • tertu/RingRacers
  • pastel/RingRacers
  • Snu/RingRacers
  • Zwip-Zwap_Zapony/RingRacers
  • haya_/RingRacers
  • Lactozilla/RingRacers
  • SMS_Alfredo/RingRacers
  • spectrumuk2/RingRacers
  • vanhouc/RingRacers
  • diskpoppy/RingRacers
  • kingofmemes2401g/ring-racers-kings-fork
  • LatiusAuro/RingRacers
  • Guil/RingRacers
  • Chearii/RingRacers
  • EeveeEuphoria/RingRacers
  • kimmy/RingRacers
  • spazzylemons/RingRacers
  • brosasaki/RingRacers
  • wehrlia/RingRacers
  • MightyMcTopher/RingRacers
  • FreakyMutantMan/RingRacers
  • troy236/RingRacers
  • Craftyawesome/RingRacers
  • NepDisk/RingRacers
  • alufolie91/RingRacers
  • bird/RingRacers
  • PencilVoid/RingRacers
  • Superstarxalien/RingRacers
  • WTF/RingRacers
  • Lach/RingRacers
  • frostu8/RingRacers
  • Benji_Menji/RingRacers
  • Dr_Nope/RingRacers
  • Nep2Disk/RingRacers
  • Lighto97/RingRacers
47 results
Show changes
Showing with 619 additions and 67 deletions
......@@ -101,88 +101,113 @@
"name": "ninja-debug",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__debug", "__ninja"]
"inherits": [ "__debug", "__ninja" ]
},
{
"name": "ninja-develop",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__develop", "__ninja"]
"inherits": [ "__develop", "__ninja" ]
},
{
"name": "ninja-release",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__release", "__ninja"]
"inherits": [ "__release", "__ninja" ]
},
{
"name": "ninja-testers",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__testers", "__ninja"]
"inherits": [ "__testers", "__ninja" ]
},
{
"name": "ninja-vcpkg-debug",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": [ "__debug", "__ninja", "__vcpkg-toolchain" ]
},
{
"name": "ninja-vcpkg-develop",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": [ "__develop", "__ninja", "__vcpkg-toolchain" ]
},
{
"name": "ninja-vcpkg-release",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": [ "__release", "__ninja", "__vcpkg-toolchain" ]
},
{
"name": "ninja-vcpkg-testers",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": [ "__testers", "__ninja", "__vcpkg-toolchain" ]
},
{
"name": "ninja-x86_mingw_static_vcpkg-debug",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__debug", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"]
"inherits": [ "__debug", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static" ]
},
{
"name": "ninja-x86_mingw_static_vcpkg-develop",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__develop", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"]
"inherits": [ "__develop", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static" ]
},
{
"name": "ninja-x86_mingw_static_vcpkg-release",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__release", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"]
"inherits": [ "__release", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static" ]
},
{
"name": "ninja-x86_mingw_static_vcpkg-testers",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__testers", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"]
"inherits": [ "__testers", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static" ]
},
{
"name": "ninja-x64_osx_vcpkg-debug",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__debug", "__ninja", "__vcpkg-toolchain", "__osx_x64"]
"inherits": [ "__debug", "__ninja", "__vcpkg-toolchain", "__osx_x64" ]
},
{
"name": "ninja-x64_osx_vcpkg-develop",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__develop", "__ninja", "__vcpkg-toolchain", "__osx_x64"]
"inherits": [ "__develop", "__ninja", "__vcpkg-toolchain", "__osx_x64" ]
},
{
"name": "ninja-x64_osx_vcpkg-release",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__release", "__ninja", "__vcpkg-toolchain", "__osx_x64"]
"inherits": [ "__release", "__ninja", "__vcpkg-toolchain", "__osx_x64" ]
},
{
"name": "ninja-arm64_osx_vcpkg-debug",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__debug", "__ninja", "__vcpkg-toolchain", "__osx_arm64"]
"inherits": [ "__debug", "__ninja", "__vcpkg-toolchain", "__osx_arm64" ]
},
{
"name": "ninja-arm64_osx_vcpkg-develop",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__develop", "__ninja", "__vcpkg-toolchain", "__osx_arm64"]
"inherits": [ "__develop", "__ninja", "__vcpkg-toolchain", "__osx_arm64" ]
},
{
"name": "ninja-arm64_osx_vcpkg-release",
"hidden": false,
"binaryDir": "build/${presetName}",
"inherits": ["__release", "__ninja", "__vcpkg-toolchain", "__osx_arm64"]
"inherits": [ "__release", "__ninja", "__vcpkg-toolchain", "__osx_arm64" ]
}
],
......
===============================================================================
Universal Doom Map Format - Ring Racers extensions v1.0 - 20.09.2024
Copyright (C) 2025 Sally Cochenour.
Copyright (C) 2025 Kart Krew Dev.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
===============================================================================
This document serves to only specify changes that "Dr. Robotnik's Ring Racers"
makes to the base UDMF specification.
=======================================
I. Grammar / Syntax
=======================================
No changes were made.
=======================================
II. Implementation Semantics
=======================================
------------------------------------
II.A : Storage and Retrieval of Data
------------------------------------
No changes were made.
-----------------------------------
II.B : Storage Within Archive Files
-----------------------------------
Between the TEXTMAP and ENDMAP lumps, Ring Racers supports the following
additional lumps:
BEHAVIOR = Compiled ACS code.
ZNODES = Compiled extended / GL friendly nodes. These are required.
PICTURE = A Doom graphic lump, expected to be 320x200. Intended to be a
screenshot of the map itself. This is used by the game for level
select menus.
MINIMAP = A Doom graphic lump, expected to be 100x100. Intended to be a
an overview of the map. This is used by the game for the minimap
on-screen HUD.
ENCORE = A Doom flat lump, expected to be 16x16. Describes a color remap
palette to use in Encore Mode.
TWEAKMAP = A Doom flat lump, expected to be 16x16. Describes a color remap
palette to use outside of Encore Mode.
Any lumps not listed or specified in the original document will be ignored by
the game. In particular, the "SCRIPTS" lump is considered to be ACS source
code, and is garantueed to be ignored by the engine.
--------------------------------
II.C : Implementation Dependence
--------------------------------
Ring Racers does not aspire for Doom backwards compatibility, thus it does not
support any of the namespaces in the original document, and only implements
its own: "ringracers". Any maps not using the "ringracers" namespace is
considered unsupported.
=======================================
III. Standardized Fields
=======================================
Ring Racers' namespace implements the following additional fields:
version = <integer>; // Specifies the map format version.
// This is used for resolving backwards compatibility issues.
// Note that this doesn't map directly to specification version;
// it means behavior of an already existing field or action special
// was changed.
// 0 / default - RR indev
// 1 - RR v2.0, spec v1.0
// 2 - RR v2.4, spec v1.0
linedef
{
moreids = <string>; // Additional IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
arg5 = <integer>; // Argument 5. Default = 0.
arg6 = <integer>; // Argument 6. Default = 0.
arg7 = <integer>; // Argument 7. Default = 0.
arg8 = <integer>; // Argument 8. Default = 0.
arg9 = <integer>; // Argument 9. Default = 0.
stringarg0 = <string>; // String argument 0. This replaces usage of 'arg0' when specified.
stringarg1 = <string>; // String argument 1. This replaces usage of 'arg1' when specified.
alpha = <float>; // Transparency value of the mid-textures. Default = 1.0.
renderstyle = <string>; // The rendering mode to use for the mid-textures.
// Can be "translucent", "add", "subtract", "reversesubtract", "modulate", or "fog".
// Default = "translucent".
// The following flags default to false.
blockplayers = <bool>; // true = line blocks players.
skewtd = <bool>; // true = upper and lower textures are skewed to match slopes.
noskew = <bool>; // true = mid-textures are not skewed to match slopes.
midpeg = <bool>; // true = invert mid-texture unpegged behavior.
midsolid = <bool>; // true = mid-texture has collision.
wrapmidtex = <bool>; // true = mid-textures are wrapped.
nonet = <bool>; // true = special is disabled in networked multiplayer games.
netonly = <bool>; // true = special is only enabled in networked multiplayer games.
notbouncy = <bool>; // true = disable bouncing collision.
transfer = <bool>; // true = use FOF transfer properties effect.
}
sidedef
{
repeatcnt = <integer>; // Number of times to mid-texture wrap. Default = 0.
}
vertex
{
zfloor = <float>; // The floor height at this vertex, for vertex slopes.
zceiling = <float>; // The ceiling height at this vertex, for vertex slopes
}
sector
{
lightfloor = <integer>; // The floor's light level. Default is 0.
lightceiling = <integer>; // The ceiling's light level. Default is 0.
lightfloorabsolute = <bool>; // true = 'lightfloor' is an absolute value. Default is
// relative to the owning sector's light level.
lightceilingabsolute = <bool>; // true = 'lightceiling' is an absolute value. Default is
// relative to the owning sector's light level.
moreids = <string>; // Additional IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
xpanningfloor = <float>; // X texture offset of floor texture, Default = 0.0.
ypanningfloor = <float>; // Y texture offset of floor texture, Default = 0.0.
xpanningceiling = <float>; // X texture offset of ceiling texture, Default = 0.0.
ypanningceiling = <float>; // Y texture offset of ceiling texture, Default = 0.0.
rotationfloor = <float>; // Rotation of floor texture in degrees, Default = 0.0.
rotationceiling = <float>; // Rotation of ceiling texture in degrees, Default = 0.0.
floorplane_a = <float>; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'.
floorplane_b = <float>; // 'heightfloor' will still be used to calculate texture alignment.
floorplane_c = <float>; // The plane equation will only be used if all 4 values are given.
floorplane_d = <float>;
ceilingplane_a = <float>; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'.
ceilingplane_b = <float>; // 'heightceiling' will still be used to calculate texture alignment.
ceilingplane_c = <float>; // The plane equation will only be used if all 4 values are given.
ceilingplane_d = <float>;
friction = <float>; // Sector's friction. Default = 0.90625.
gravity = <float>; // Sector's gravity multiplier. Default = 1.0.
damagetype = <string>; // Damage inflicted by the sector.
// Can be "None", "Generic", "Lava", "DeathPit", "Instakill", or "Stumble".
// Default = "None".
action = <integer>; // Sector action, same as line special. Default = 0.
arg0 = <integer>; // Argument 0. Default = 0.
arg1 = <integer>; // Argument 1. Default = 0.
arg2 = <integer>; // Argument 2. Default = 0.
arg3 = <integer>; // Argument 3. Default = 0.
arg4 = <integer>; // Argument 4. Default = 0.
arg5 = <integer>; // Argument 5. Default = 0.
arg6 = <integer>; // Argument 6. Default = 0.
arg7 = <integer>; // Argument 7. Default = 0.
arg8 = <integer>; // Argument 8. Default = 0.
arg9 = <integer>; // Argument 9. Default = 0.
stringarg0 = <integer>; // String argument 0. This replaces usage of 'arg0' when specified.
stringarg1 = <integer>; // String argument 1. This replaces usage of 'arg1' when specified.
lightcolor = <integer>; // Sector's light color as RRGGBB value. Default = 0x000000.
lightalpha = <integer>; // Sector's light color alpha value. Default = 25.
fadecolor = <integer>; // Sector's fog color as RRGGBB value. Default = 0x000000.
fadealpha = <integer>; // Sector's fog color alpha value. Default = 25.
fadestart = <integer>; // Sector's fog start distance. Default = 0.
fadeend = <integer>; // Sector's fog end distance. Default = 31.
// The following flags default to false.
colormapfog = <bool>; // true = render transparent planes at light level instead of fullbright
colormapfadesprites = <bool>; // true = fog color affects fullbright sprites
colormapprotected = <bool>; // true = colormap cannot be changed at run-time
flipspecial_nofloor = <bool>; // true = plane touch specials aren't ran when on the floor
flipspecial_ceiling = <bool>; // true = plane touch specials are ran when on the ceiling
triggerspecial_touch = <bool>; // true = specials are ran when touching edges of sector
triggerspecial_headbump = <bool>; // true = plane touch specials are ran when touching the opposite plane than gravity
invertprecip = <bool>; // true = precipitation spawning rules are inverted
gravityflip = <bool>; // true = flip gravity of objects in this sector
heatwave = <bool>; // true = add heat wave screen effect
noclipcamera = <bool>; // true = camera is not blocked by this sector
ripple_floor = <bool>; // true = add ripple effect to floor
ripple_ceiling = <bool>; // true = add ripple effect to ceiling
invertencore = <bool>; // true = encore remap rules are inverted
flatlighting = <bool>; // true = directional lighting is forced off
forcedirectionallighting = <bool>; // true = directional lighting is forced on
nostepup = <bool>; // true = objects can't step up
doublestepup = <bool>; // true = objects have increased step up
nostepdown = <bool>; // true = objects can't step down
cheatcheckactivator = <bool>; // true = players activate cheat checks when in this sector
exit = <bool>; // true = players finish match when entering sector
deleteitems = <bool>; // true = items instantly explode when entering sector
fan = <bool>; // true = players are propelled upwards in this sector
zoomtubestart = <bool>; // true = sector is start of a zoom tube
zoomtubeend = <bool>; // true = sector is end of a zoom tube
repeatspecial = <bool>; // true = repeatable action
continuousspecial = <bool>; // true = action is executed every game tick
playerenter = <bool>; // true = player activates when entering
playerfloor = <bool>; // true = player activates when touching floor
playerceiling = <bool>; // true = player activates when touching ceiling
monsterenter = <bool>; // true = enemy activates when entering
monsterfloor = <bool>; // true = enemy activates when touching floor
monsterceiling = <bool>; // true = enemy activates when touching ceiling
missileenter = <bool>; // true = items / projectiles activate when entering
missilefloor = <bool>; // true = items / projectiles activate when touching floor
missileceiling = <bool>; // true = items / projectiles activate when touching ceiling
}
thing
{
pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
roll = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
scalex = <float>; // Vertical visual scale on thing. Default = 1.0.
scaley = <float>; // Horizontal visual scale on thing. Default = 1.0.
scale = <float>; // Vertical and horizontal visual scale on thing. Default = 1.0.
mobjscale = <float>; // Physical scale on thing. Default = 1.0.
foflayer = <integer>; // Which FOF is treated as the base floor/ceiling.
// This changes what 'height' is relative to.
// Default = 0, for no FOF.
// Action special arguments
arg5 = <integer>; // Argument 5. Default = 0.
arg6 = <integer>; // Argument 6. Default = 0.
arg7 = <integer>; // Argument 7. Default = 0.
arg8 = <integer>; // Argument 8. Default = 0.
arg9 = <integer>; // Argument 9. Default = 0.
stringarg0 = <string>; // String argument 0. This replaces usage of 'arg0' when specified.
stringarg1 = <string>; // String argument 1. This replaces usage of 'arg1' when specified.
// These arguments modify object behavior on a per-type basis.
// Not to be confused with action special arguments.
thingarg0 = <integer>; // Argument 0. Default = 0.
thingarg1 = <integer>; // Argument 1. Default = 0.
thingarg2 = <integer>; // Argument 2. Default = 0.
thingarg3 = <integer>; // Argument 3. Default = 0.
thingarg4 = <integer>; // Argument 4. Default = 0.
thingarg5 = <integer>; // Argument 5. Default = 0.
thingarg6 = <integer>; // Argument 6. Default = 0.
thingarg7 = <integer>; // Argument 7. Default = 0.
thingarg8 = <integer>; // Argument 8. Default = 0.
thingarg9 = <integer>; // Argument 9. Default = 0.
thingstringarg0 = <integer>; // String argument 0. This replaces usage of 'thingarg0' when specified.
thingstringarg1 = <integer>; // String argument 1. This replaces usage of 'thingarg1' when specified.
// Following flags default to false.
flip = <bool>; // true = object has reversed gravity
}
=======================================
Changelog
=======================================
1.0: 20.09.2024
- Initial document created.
......@@ -122,6 +122,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
lua_blockmaplib.c
lua_hudlib.c
lua_hudlib_drawlist.c
lua_followerlib.c
lua_profile.cpp
k_kart.c
k_respawn.c
......@@ -200,11 +201,14 @@ add_custom_target(_SRB2_reconf ALL
)
add_dependencies(SRB2SDL2 _SRB2_reconf)
if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
if(("${CMAKE_COMPILER_IS_GNUCC}" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
target_link_options(SRB2SDL2 PRIVATE "-Wl,--disable-dynamicbase")
if("${SRB2_CONFIG_STATIC_STDLIB}")
# On MinGW with internal libraries, link the standard library statically
target_link_options(SRB2SDL2 PRIVATE "-static")
target_link_options(SRB2SDL2 PRIVATE -Wl,--add-stdcall-alias -static-libgcc -static-libstdc++ -static -lpthread)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
target_link_libraries(SRB2SDL2 PRIVATE Threads::Threads)
endif()
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
target_link_options(SRB2SDL2 PRIVATE "-Wl,--large-address-aware")
......@@ -238,6 +242,10 @@ if (UNIX)
target_compile_definitions(SRB2SDL2 PRIVATE -DUNIXCOMMON)
endif()
if (BSD MATCHES "FreeBSD")
target_compile_definitions(SRB2SDL2 PRIVATE -DFREEBSD)
endif()
if(CMAKE_COMPILER_IS_GNUCC)
find_program(OBJCOPY objcopy)
endif()
......@@ -249,6 +257,11 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
endif()
endif()
if("${CMAKE_SYSTEM_NAME}" MATCHES "Haiku")
target_compile_definitions(SRB2SDL2 PRIVATE -DNOEXECINFO)
target_link_libraries(SRB2SDL2 PRIVATE network)
endif()
if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
target_compile_definitions(SRB2SDL2 PRIVATE -DMACOSX)
endif()
......@@ -407,10 +420,12 @@ endif()
# Compatibility flag with later versions of GCC
# We should really fix our code to not need this
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
check_cxx_compiler_flag("-mno-ms-bitfields" HAS_NO_MS_BITFIELDS)
if(HAS_NO_MS_BITFIELDS)
target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields)
if (NOT SRB2_CONFIG_FORCE_NO_MS_BITFIELDS)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
check_cxx_compiler_flag("-mno-ms-bitfields" HAS_NO_MS_BITFIELDS)
if(HAS_NO_MS_BITFIELDS)
target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields)
endif()
endif()
endif()
......@@ -580,6 +595,11 @@ endif()
if(SRB2_CONFIG_PACKETDROP)
target_compile_definitions(SRB2SDL2 PRIVATE -DPACKETDROP)
endif()
if(SRB2_CONFIG_EXECINFO)
else()
target_compile_definitions(SRB2SDL2 PRIVATE -DNOEXECINFO)
message(STATUS "You have disabled stack trace dump support")
endif()
if(SRB2_CONFIG_ZDEBUG)
target_compile_definitions(SRB2SDL2 PRIVATE -DZDEBUG)
endif()
......@@ -608,32 +628,182 @@ endif()
add_subdirectory(hud)
add_subdirectory(modp_b64)
# strip debug symbols into separate file when using gcc.
# strip debug symbols into separate file when using gcc or clang.
# to be consistent with Makefile, don't generate for OS X.
if((CMAKE_COMPILER_IS_GNUCC) AND NOT ("${CMAKE_SYSTEM_NAME}" MATCHES Darwin))
if(${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo)
if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND NOT ("${CMAKE_SYSTEM_NAME}" MATCHES Darwin))
if(${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo OR SRB2_CONFIG_ALWAYS_MAKE_DEBUGLINK)
message(STATUS "Will make separate debug symbols in *.debug")
add_custom_command(TARGET SRB2SDL2 POST_BUILD
COMMAND ${OBJCOPY} ${OBJCOPY_ONLY_KEEP_DEBUG} $<TARGET_FILE:SRB2SDL2> $<TARGET_FILE:SRB2SDL2>.debug
COMMAND ${CMAKE_OBJCOPY} ${OBJCOPY_ONLY_KEEP_DEBUG} $<TARGET_FILE:SRB2SDL2> $<TARGET_FILE:SRB2SDL2>.debug
# mold linker: .gnu_debuglink is present by default, so --add-gnu-debuglink would fail
COMMAND ${OBJCOPY} --strip-debug --remove-section=.gnu_debuglink $<TARGET_FILE:SRB2SDL2>
COMMAND ${OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE:SRB2SDL2>.debug $<TARGET_FILE:SRB2SDL2>
COMMAND ${CMAKE_OBJCOPY} --strip-debug --remove-section=.gnu_debuglink $<TARGET_FILE:SRB2SDL2>
COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE:SRB2SDL2>.debug $<TARGET_FILE:SRB2SDL2>
)
endif()
endif()
# copy DLLs to bin/ directory if building internal shared on windows
if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows AND NOT "${SRB2_CONFIG_INTERNAL_LIBRARIES}" AND "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}")
if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows AND NOT "${SRB2_CONFIG_INTERNAL_LIBRARIES}")
# also copy implicitly linked system libraries
set(ADDITIONAL_DLLS "")
if("${CMAKE_C_COMPILER_ID}" STREQUAL GNU)
# also copy implicitly linked system libraries
get_filename_component(MINGW_BIN_PATH ${CMAKE_CXX_COMPILER} PATH)
list(APPEND ADDITIONAL_DLLS
"libgcc_s_dw2-1.dll"
"libstdc++-6.dll"
"libwinpthread-1.dll"
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL GNU)
string(CONCAT gcc_search_dirs_path "${CMAKE_BINARY_DIR}" /gcc_search_dirs.txt)
#message(STATUS gcc_search_dirs_path=${gcc_search_dirs_path})
execute_process(
COMMAND ${CMAKE_CXX_COMPILER} -print-search-dirs
OUTPUT_FILE "${gcc_search_dirs_path}"
#OUTPUT_VARIABLE gcc_search_dirs
)
file(READ "${gcc_search_dirs_path}" gcc_search_dirs)
#message(STATUS gcc_search_dirs=${gcc_search_dirs})
#set(gcc_install_dir "${gcc_search_dirs}")
#string(REGEX MATCH "install: =[ \t]*([^\r\n]*)" gcc_install_dir "${gcc_install_dir}" )
#set(gcc_install_dir "${CMAKE_MATCH_1}")
#message(STATUS gcc_install_dir="${gcc_install_dir}")
string(CONCAT gcc_search_dirs_install_path_1 "${CMAKE_BINARY_DIR}" /gcc_search_dirs_install_1.txt)
#message(STATUS gcc_search_dirs_install_path_1=${gcc_search_dirs_install_path_1})
execute_process(
COMMAND grep "^install:"
INPUT_FILE "${gcc_search_dirs_path}"
OUTPUT_FILE "${gcc_search_dirs_install_path_1}"
)
string(CONCAT gcc_search_dirs_install_path_2 "${CMAKE_BINARY_DIR}" /gcc_search_dirs_install_2.txt)
#message(STATUS gcc_search_dirs_install_path_2=${gcc_search_dirs_install_path_2})
execute_process(
COMMAND sed -e "s/^install: //" -e "s,=/,/,g"
INPUT_FILE "${gcc_search_dirs_install_path_1}"
OUTPUT_FILE "${gcc_search_dirs_install_path_2}"
)
if(NOT ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows"))
string(REPLACE ":" ";" gcc_install_dir "${gcc_install_dir}")
endif()
file(READ ${gcc_search_dirs_install_path_2} gcc_install_dir)
#set(gcc_programs_dir "${gcc_search_dirs}")
#string(REGEX MATCH "programs: =[ \t]*([^\r\n]*)" gcc_programs_dir "${gcc_programs_dir}" )
#set(gcc_programs_dir "${CMAKE_MATCH_1}")
#message(STATUS gcc_programs_dir="${gcc_programs_dir}")
string(CONCAT gcc_search_dirs_programs_path_1 "${CMAKE_BINARY_DIR}" /gcc_search_dirs_programs_1.txt)
#message(STATUS gcc_search_dirs_programs_path_1=${gcc_search_dirs_programs_path_1})
execute_process(
COMMAND grep "^programs:"
INPUT_FILE "${gcc_search_dirs_path}"
OUTPUT_FILE "${gcc_search_dirs_programs_path_1}"
)
string(CONCAT gcc_search_dirs_programs_path_2 "${CMAKE_BINARY_DIR}" /gcc_search_dirs_programs_2.txt)
#message(STATUS gcc_search_dirs_programs_path_2=${gcc_search_dirs_programs_path_2})
execute_process(
COMMAND sed -e "s/^programs: =//" -e "s,=/,/,g"
INPUT_FILE "${gcc_search_dirs_programs_path_1}"
OUTPUT_FILE "${gcc_search_dirs_programs_path_2}"
)
file(READ ${gcc_search_dirs_programs_path_2} gcc_programs_dir)
if(NOT ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows"))
string(REPLACE ":" ";" gcc_programs_dir "${gcc_programs_dir}")
endif()
#set(gcc_libraries_dir "${gcc_search_dirs}")
#string(REGEX MATCH "libraries: =[ \t]*([^\r\n]*)" gcc_libraries_dir "${gcc_libraries_dir}" )
#set(gcc_libraries_dir "${CMAKE_MATCH_1}")
#message(STATUS gcc_libraries_dir="${gcc_libraries_dir}")
string(CONCAT gcc_search_dirs_libraries_path_1 "${CMAKE_BINARY_DIR}" /gcc_search_dirs_libraries_1.txt)
#message(STATUS gcc_search_dirs_libraries_path_1=${gcc_search_dirs_libraries_path_1})
execute_process(
COMMAND grep "^libraries:"
INPUT_FILE "${gcc_search_dirs_path}"
OUTPUT_FILE "${gcc_search_dirs_libraries_path_1}"
)
string(CONCAT gcc_search_dirs_libraries_path_2 "${CMAKE_BINARY_DIR}" /gcc_search_dirs_libraries_2.txt)
#message(STATUS gcc_search_dirs_libraries_path_2=${gcc_search_dirs_libraries_path_2})
execute_process(
COMMAND sed -e "s/^libraries: =//" -e "s,=/,/,g"
INPUT_FILE "${gcc_search_dirs_libraries_path_1}"
OUTPUT_FILE "${gcc_search_dirs_libraries_path_2}"
)
list(TRANSFORM ADDITIONAL_DLLS PREPEND "${MINGW_BIN_PATH}/")
file(READ ${gcc_search_dirs_libraries_path_2} gcc_libraries_dir)
if(NOT ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows"))
string(REPLACE ":" ";" gcc_libraries_dir "${gcc_libraries_dir}")
endif()
#list(LENGTH gcc_install_dir gcc_install_dir_len)
#list(LENGTH gcc_programs_dir gcc_programs_dir_len)
#list(LENGTH gcc_libraries_dir gcc_libraries_dir_len)
#message(STATUS gcc_install_dir_len="${gcc_install_dir_len}")
#message(STATUS gcc_install_dir="${gcc_install_dir}")
#message(STATUS gcc_programs_dir_len="${gcc_programs_dir_len}")
#message(STATUS gcc_programs_dir="${gcc_programs_dir}")
#message(STATUS gcc_libraries_dir_len="${gcc_libraries_dir_len}")
#message(STATUS gcc_libraries_dir="${gcc_libraries_dir}")
get_filename_component(CMAKE_CXX_COMPILER_DIR ${CMAKE_CXX_COMPILER} DIRECTORY)
#message(STATUS CMAKE_CXX_COMPILER_DIR="${CMAKE_CXX_COMPILER_DIR}")
set(OLD_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES "" ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(OLD_CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES})
set(CMAKE_FIND_LIBRARY_PREFIXES "" ${CMAKE_FIND_LIBRARY_PREFIXES})
find_library(LIBUNWIND
NAMES "libunwind.dll"
PATHS ${gcc_programs_dir} ${CMAKE_CXX_COMPILER_DIR}
)
if (LIBUNWIND)
#message(STATUS LIBUNWIND="${LIBUNWIND}")
list(APPEND ADDITIONAL_DLLS ${LIBUNWIND})
endif()
unset(LIBUNWIND)
find_library(LIBGCC
NAMES "libgcc_s_dw2-1.dll" "libgcc_s_sjlj-1.dll" "libgcc_s_seh-1.dll"
PATHS ${gcc_programs_dir} ${CMAKE_CXX_COMPILER_DIR}
)
if (LIBGCC)
#message(STATUS LIBGCC="${LIBGCC}")
list(APPEND ADDITIONAL_DLLS ${LIBGCC})
endif()
unset(LIBGCC)
find_library(LIBSTDCPP
NAMES "libstdc++-6.dll" "libc++.dll"
PATHS ${gcc_programs_dir} ${CMAKE_CXX_COMPILER_DIR}
)
if (LIBSTDCPP)
#message(STATUS LIBSTDCPP="${LIBSTDCPP}")
list(APPEND ADDITIONAL_DLLS ${LIBSTDCPP})
endif()
unset(LIBSTDCPP)
find_library(LIBPTHREAD
NAMES "winpthread-1.dll" "libwinpthread-1.dll" "pthreadGC2.dll"
PATHS ${gcc_libraries_dir} ${CMAKE_CXX_COMPILER_DIR}
)
if(LIBPTHREAD)
#message(STATUS LIBPTHREAD="${LIBPTHREAD}")
list(APPEND ADDITIONAL_DLLS ${LIBPTHREAD})
endif()
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_PREFIXES ${OLD_CMAKE_FIND_LIBRARY_PREFIXES})
unset(LIBPTHREAD)
unset(gcc_install_dir)
unset(gcc_programs_dir)
unset(gcc_libraries_dir)
unset(OLD_CMAKE_FIND_LIBRARY_SUFFIXES)
unset(OLD_CMAKE_FIND_LIBRARY_PREFIXES)
#message(STATUS ADDITIONAL_DLLS="${ADDITIONAL_DLLS}")
endif()
add_custom_command(TARGET SRB2SDL2 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
......@@ -645,3 +815,11 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows AND NOT "${SRB2_CONFIG_INTERNAL_LIBRA
COMMENT "Copying runtime DLLs"
)
endif()
# Setup clang-tidy
if(SRB2_CONFIG_ENABLE_CLANG_TIDY_C)
target_set_default_clang_tidy(SRB2SDL2 C "-*,clang-analyzer-*,-clang-analyzer-cplusplus-*")
endif()
if(SRB2_CONFIG_ENABLE_CLANG_TIDY_CXX)
target_set_default_clang_tidy(SRB2SDL2 CXX "-*,clang-analyzer-*,modernize-*")
endif()
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -1147,6 +1147,37 @@ bool CallFunc_SetLineTexture(ACSVM::Thread *thread, const ACSVM::Word *argV, ACS
return false;
}
/*--------------------------------------------------
bool CallFunc_SetLineBlocking(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
Changes a linedef's blocking flag.
--------------------------------------------------*/
bool CallFunc_SetLineBlocking(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
{
mtag_t tag = 0;
UINT32 blocking = 0;
INT32 lineId = -1;
tag = argV[0];
if (argV[1] != 0)
{
blocking = ML_IMPASSABLE;
}
TAG_ITER_LINES(tag, lineId)
{
line_t *line = &lines[lineId];
if (line->flags & ML_TWOSIDED) // disallow changing this for 1-sided lines
{
line->flags = (line->flags & ~ML_IMPASSABLE) | blocking;
}
}
return false;
}
/*--------------------------------------------------
bool CallFunc_SetLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
......@@ -2026,7 +2057,7 @@ bool CallFunc_SetLineRenderStyle(ACSVM::Thread *thread, const ACSVM::Word *argV,
}
alpha = argV[2];
alpha = std::clamp(alpha, 0, FRACUNIT);
alpha = std::clamp<fixed_t>(alpha, 0, FRACUNIT);
TAG_ITER_LINES(tag, lineId)
{
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -57,6 +57,7 @@ bool CallFunc_IsNetworkGame(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSV
bool CallFunc_SectorSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_AmbientSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_SetLineTexture(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_SetLineBlocking(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_SetLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_ThingSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
bool CallFunc_EndPrintBold(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -46,6 +46,9 @@ Environment::Environment()
// Not that we're adding any modules to it, though. :p
global->active = true;
// Set a branch limit (same as ZDoom's instruction limit)
branchLimit = 2000000;
// Add the data & function pointers.
// Starting with raw ACS0 codes. I'm using this classic-style
......@@ -85,7 +88,7 @@ Environment::Environment()
addCodeDataACS0( 95, {"", 2, addCallFunc(CallFunc_AmbientSound)});
addCodeDataACS0( 97, {"", 4, addCallFunc(CallFunc_SetLineTexture)});
addCodeDataACS0( 98, {"", 2, addCallFunc(CallFunc_SetLineBlocking)});
addCodeDataACS0( 99, {"", 7, addCallFunc(CallFunc_SetLineSpecial)});
addCodeDataACS0(100, {"", 3, addCallFunc(CallFunc_ThingSound)});
addCodeDataACS0(101, {"", 0, addCallFunc(CallFunc_EndPrintBold)});
......@@ -405,3 +408,42 @@ ACSVM::Word Environment::callSpecImpl
P_ProcessSpecial(activator, spec, args, stringargs);
return 1;
}
void Environment::printKill(ACSVM::Thread *thread, ACSVM::Word type, ACSVM::Word data)
{
std::string scriptName;
ACSVM::String *scriptNamePtr = (thread->script != nullptr) ? (thread->script->name.s) : nullptr;
if (scriptNamePtr && scriptNamePtr->len)
scriptName = std::string(scriptNamePtr->str);
else
scriptName = std::to_string((int)thread->script->name.i);
ACSVM::KillType killType = static_cast<ACSVM::KillType>(type);
if (killType == ACSVM::KillType::BranchLimit)
{
CONS_Alert(CONS_ERROR, "Terminated runaway script %s\n", scriptName.c_str());
return;
}
else if (killType == ACSVM::KillType::UnknownCode)
{
CONS_Alert(CONS_ERROR, "ACSVM ERROR: Unknown opcode %d in script %s\n", data, scriptName.c_str());
}
else if (killType == ACSVM::KillType::UnknownFunc)
{
CONS_Alert(CONS_ERROR, "ACSVM ERROR: Unknown function %d in script %s\n", data, scriptName.c_str());
}
else if (killType == ACSVM::KillType::OutOfBounds)
{
CONS_Alert(CONS_ERROR, "ACSVM ERROR: Jumped to out of bounds location %s in script %s\n",
sizeu1(thread->codePtr - thread->module->codeV.data() - 1), scriptName.c_str());
}
else
{
CONS_Alert(CONS_ERROR, "ACSVM ERROR: Kill %u:%d at %s in script %s\n",
type, data, sizeu1(thread->codePtr - thread->module->codeV.data() - 1), scriptName.c_str());
}
CONS_Printf("Script terminated.\n");
}
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -32,6 +32,8 @@ public:
virtual ACSVM::Thread *allocThread();
virtual void printKill(ACSVM::Thread *thread, ACSVM::Word type, ACSVM::Word data);
protected:
virtual void loadModule(ACSVM::Module *module);
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
......@@ -10,7 +10,7 @@
##
##-----------------------------------------------------------------------------
cmake_minimum_required(VERSION 2.6)
cmake_minimum_required(VERSION 3.14)
cmake_policy(SET CMP0017 NEW)
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Vivian "toastergrl" Grannell.
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2025 by Vivian "toastergrl" Grannell.
// Copyright (C) 2025 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2000 by DooM Legacy Team.
// Copyright (C) 1996 by id Software, Inc.
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Vivian "toastergrl" Grannell.
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2025 by Vivian "toastergrl" Grannell.
// Copyright (C) 2025 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2000 by DooM Legacy Team.
// Copyright (C) 1996 by id Software, Inc.
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2025 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2025 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
......
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2025 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
......