Compare commits

..
5 Commits
Author SHA1 Message Date
GenericHeroGuy 744dc87c16 In rehashtab, do counthash before adding asize
Thanks alug!
2025-01-29 22:25:24 +01:00
GenericHeroGuy b400655f3c Add cleanjit target
Recompiling the whole game after changing a single flag is pretty tiring
2025-01-06 00:02:11 +01:00
GenericHeroGuy 314ab9e9f0 Fix some functions leaking doubles in INTONLY 2025-01-05 23:48:40 +01:00
GenericHeroGuy 0fbc448013 Use references instead of upvalues for original I/O functions
No more unrestricted I/O through debug.getupvalue
2025-01-03 22:16:11 +01:00
GenericHeroGuy eb9d1982fa Update to BLUAJIT 449b76f 2025-01-03 20:12:26 +01:00
338 changed files with 59375 additions and 42593 deletions

No files matched your search

-1
View File
@@ -4,7 +4,6 @@
*.plg
*.suo
*.vcproj.*.*.user
*.kate-swp
Win32_LIB_ASM_Debug
Win32_LIB_ASM_Release
*.bsc
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.0)
# DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
# Version change is fine.
project(SRB2
-9
View File
@@ -28,10 +28,6 @@ exist.
Returns the values of the given HUD item's `xoffset`/`yoffset` cvars.
Available for any HUD item with offset cvars.
## patch = v.cachePatchRotated(name, rollangle)
Like v.cachePatch, it caches a new patch with the corresponding name. Unlike v.cachePatch, however,
a rollangle can be supplied to the function so that it returns a rotated patch instead.
## x, y, flags = v.getDrawInfo(item)
Returns the X, Y and flags where the given HUD item will be drawn for the current displayplayer.
@@ -156,11 +152,6 @@ Add Gamepad Rumble support for things.
To be used with Displayplayers.
Duration is in milliseconds and is optional to set, default value is 84ms.
## P_CheckSightFast(mo1, mo2)
Exactly same as P_CheckSight but uses cheaper algorithm, useful for things like nametags. Doesn't work exactly
like P_CheckSight so don't use it for anything gameplay-related.
# Other changes
## P_PlayRinglossSound(source, damager)
-8
View File
@@ -1,8 +0,0 @@
ifdef SILENT
MAKEFLAGS+=--no-print-directory
endif
all :
% ::
@$(MAKE) -C src $(MAKECMDGOALS)
+1 -1
View File
@@ -76,7 +76,7 @@ Crashlogs now contain alot more informations. and even more if your build has de
Also allows 64bit Windows builds to produce Crashlogs!
## MISC
- Bird's Camera Tilting feature is no longer turned on by default
- Bird's Camara Tilting feature is no longer turned on by default
- Bird's warning on the title screen has been removed
## Bugs
+5
View File
@@ -1726,6 +1726,11 @@ HW3SOUND for 3D hardware sound support
<Option compilerVar="CC" />
</Unit>
<Unit filename="src/r_draw.h" />
<Unit filename="src/r_draw16.c">
<Option compilerVar="CC" />
<Option compile="0" />
<Option link="0" />
</Unit>
<Unit filename="src/r_draw8.c">
<Option compilerVar="CC" />
<Option compile="0" />
+10
View File
@@ -773,6 +773,16 @@ Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit79]
FileName=src\r_draw16.c
Folder=R_Rend
Compile=0
CompileCpp=0
Link=0
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit80]
FileName=src\r_draw8.c
Folder=R_Rend
+32 -32
View File
@@ -1,32 +1,32 @@
@echo off
set BRA=Unknown
set REV=illegal
copy nul: /b +%1\comptime.c tmp.$$$ > nul
move tmp.$$$ %1\comptime.c > nul
if exist .git goto gitrev
if exist ..\.git goto gitrev
if exist .svn goto svnrev
goto filwri
:gitrev
set GIT=%2
if "%GIT%"=="" set GIT=git
for /f "usebackq" %%s in (`%GIT% rev-parse --abbrev-ref HEAD`) do @set BRA=%%s
for /f "usebackq" %%s in (`%GIT% rev-parse HEAD`) do @set REV=%%s
set REV=%REV:~0,8%
goto filwri
:svnrev
set BRA=Subversion
for /f "usebackq" %%s in (`svnversion .`) do @set REV=%%s
set REV=r%REV%
goto filwri
:filwri
echo // Do not edit! This file was autogenerated > %1\comptime.h
echo // by the %0 batch file >> %1\comptime.h
echo // >> %1\comptime.h
echo const char* compbranch = "%BRA%"; >> %1\comptime.h
echo const char* comprevision = "%REV%"; >> %1\comptime.h
@echo off
set BRA=Unknown
set REV=illegal
copy nul: /b +%1\comptime.c tmp.$$$ > nul
move tmp.$$$ %1\comptime.c > nul
if exist .git goto gitrev
if exist ..\.git goto gitrev
if exist .svn goto svnrev
goto filwri
:gitrev
set GIT=%2
if "%GIT%"=="" set GIT=git
for /f "usebackq" %%s in (`%GIT% rev-parse --abbrev-ref HEAD`) do @set BRA=%%s
for /f "usebackq" %%s in (`%GIT% rev-parse HEAD`) do @set REV=%%s
set REV=%REV:~0,8%
goto filwri
:svnrev
set BRA=Subversion
for /f "usebackq" %%s in (`svnversion .`) do @set REV=%%s
set REV=r%REV%
goto filwri
:filwri
echo // Do not edit! This file was autogenerated > %1\comptime.h
echo // by the %0 batch file >> %1\comptime.h
echo // >> %1\comptime.h
echo const char* compbranch = "%BRA%"; >> %1\comptime.h
echo const char* comprevision = "%REV%"; >> %1\comptime.h
+2 -1
View File
@@ -17,7 +17,7 @@ EOF
versiongit() {
gitbranch="$(git rev-parse --abbrev-ref HEAD)"
gitversion="$(git show --pretty=format:'%h %s' -s HEAD | sed 's/"/\\"/g')"
gitversion="$(git rev-parse HEAD | cut -c -8)"
version "$gitbranch" "$gitversion";
exit 0
}
@@ -42,3 +42,4 @@ compversion() {
[ -f "$path/comptime.c" ] && compversion "$@"
exit 2
+1 -5
View File
@@ -31,8 +31,4 @@ and don't forget to build r_opengl.dll for srb2dd.
Updated 2/17/2024 (v1.6 Saturn)
No i threw everthing into dll-binaries
theres no reason at all to have stuff spread across multiple directories
Updated 3/19/2025 (v1.6; Neptune)
We're using some C++ code now, so we need to have a few more DLLs.
Otherwise, it's about the same as prior.
theres no reason at all to have stuff spread across multiple directories
File diff suppressed because it is too large. Load diff
+191
View File
@@ -0,0 +1,191 @@
/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */
#ifndef __CURL_CURLBUILD_H
#define __CURL_CURLBUILD_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/* ================================================================ */
/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
/* ================================================================ */
/*
* NOTE 1:
* -------
*
* Nothing in this file is intended to be modified or adjusted by the
* curl library user nor by the curl library builder.
*
* If you think that something actually needs to be changed, adjusted
* or fixed in this file, then, report it on the libcurl development
* mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
*
* This header file shall only export symbols which are 'curl' or 'CURL'
* prefixed, otherwise public name space would be polluted.
*
* NOTE 2:
* -------
*
* Right now you might be staring at file include/curl/curlbuild.h.in or
* at file include/curl/curlbuild.h, this is due to the following reason:
*
* On systems capable of running the configure script, the configure process
* will overwrite the distributed include/curl/curlbuild.h file with one that
* is suitable and specific to the library being configured and built, which
* is generated from the include/curl/curlbuild.h.in template file.
*
*/
/* ================================================================ */
/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
/* ================================================================ */
#ifdef CURL_SIZEOF_LONG
# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
#endif
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
#endif
#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
#endif
#ifdef CURL_TYPEOF_CURL_OFF_T
# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
#endif
#ifdef CURL_FORMAT_CURL_OFF_T
# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
#endif
#ifdef CURL_FORMAT_CURL_OFF_TU
# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
#endif
#ifdef CURL_FORMAT_OFF_T
# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
#endif
#ifdef CURL_SIZEOF_CURL_OFF_T
# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
#endif
#ifdef CURL_SUFFIX_CURL_OFF_T
# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
#endif
#ifdef CURL_SUFFIX_CURL_OFF_TU
# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
#endif
/* ================================================================ */
/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
/* ================================================================ */
/* Configure process defines this to 1 when it finds out that system */
/* header file ws2tcpip.h must be included by the external interface. */
#define CURL_PULL_WS2TCPIP_H 1
#ifdef CURL_PULL_WS2TCPIP_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN 1
# endif
# include <windows.h>
# include <winsock2.h>
# include <ws2tcpip.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file sys/types.h must be included by the external interface. */
#define CURL_PULL_SYS_TYPES_H 1
#ifdef CURL_PULL_SYS_TYPES_H
# include <sys/types.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file stdint.h must be included by the external interface. */
#define CURL_PULL_STDINT_H 1
#ifdef CURL_PULL_STDINT_H
# include <stdint.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file inttypes.h must be included by the external interface. */
#define CURL_PULL_INTTYPES_H 1
#ifdef CURL_PULL_INTTYPES_H
# include <inttypes.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file sys/socket.h must be included by the external interface. */
/* #undef CURL_PULL_SYS_SOCKET_H */
#ifdef CURL_PULL_SYS_SOCKET_H
# include <sys/socket.h>
#endif
/* The size of `long', as computed by sizeof. */
#define CURL_SIZEOF_LONG 4
/* Integral data type used for curl_socklen_t. */
#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
/* The size of `curl_socklen_t', as computed by sizeof. */
#define CURL_SIZEOF_CURL_SOCKLEN_T 4
/* Data type definition of curl_socklen_t. */
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
/* Signed integral data type used for curl_off_t. */
#define CURL_TYPEOF_CURL_OFF_T int64_t
/* Data type definition of curl_off_t. */
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
/* curl_off_t formatting string directive without "%" conversion specifier. */
#define CURL_FORMAT_CURL_OFF_T "I64d"
/* unsigned curl_off_t formatting string without "%" conversion specifier. */
#define CURL_FORMAT_CURL_OFF_TU "I64u"
/* curl_off_t formatting string directive with "%" conversion specifier. */
#define CURL_FORMAT_OFF_T "%I64d"
/* The size of `curl_off_t', as computed by sizeof. */
#define CURL_SIZEOF_CURL_OFF_T 8
/* curl_off_t constant suffix. */
#define CURL_SUFFIX_CURL_OFF_T LL
/* unsigned curl_off_t constant suffix. */
#define CURL_SUFFIX_CURL_OFF_TU ULL
#endif /* __CURL_CURLBUILD_H */
+261
View File
@@ -0,0 +1,261 @@
#ifndef __CURL_CURLRULES_H
#define __CURL_CURLRULES_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/* ================================================================ */
/* COMPILE TIME SANITY CHECKS */
/* ================================================================ */
/*
* NOTE 1:
* -------
*
* All checks done in this file are intentionally placed in a public
* header file which is pulled by curl/curl.h when an application is
* being built using an already built libcurl library. Additionally
* this file is also included and used when building the library.
*
* If compilation fails on this file it is certainly sure that the
* problem is elsewhere. It could be a problem in the curlbuild.h
* header file, or simply that you are using different compilation
* settings than those used to build the library.
*
* Nothing in this file is intended to be modified or adjusted by the
* curl library user nor by the curl library builder.
*
* Do not deactivate any check, these are done to make sure that the
* library is properly built and used.
*
* You can find further help on the libcurl development mailing list:
* http://cool.haxx.se/mailman/listinfo/curl-library/
*
* NOTE 2
* ------
*
* Some of the following compile time checks are based on the fact
* that the dimension of a constant array can not be a negative one.
* In this way if the compile time verification fails, the compilation
* will fail issuing an error. The error description wording is compiler
* dependent but it will be quite similar to one of the following:
*
* "negative subscript or subscript is too large"
* "array must have at least one element"
* "-1 is an illegal array size"
* "size of array is negative"
*
* If you are building an application which tries to use an already
* built libcurl library and you are getting this kind of errors on
* this file, it is a clear indication that there is a mismatch between
* how the library was built and how you are trying to use it for your
* application. Your already compiled or binary library provider is the
* only one who can give you the details you need to properly use it.
*/
/*
* Verify that some macros are actually defined.
*/
#ifndef CURL_SIZEOF_LONG
# error "CURL_SIZEOF_LONG definition is missing!"
Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing
#endif
#ifndef CURL_TYPEOF_CURL_SOCKLEN_T
# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!"
Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing
#endif
#ifndef CURL_SIZEOF_CURL_SOCKLEN_T
# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!"
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing
#endif
#ifndef CURL_TYPEOF_CURL_OFF_T
# error "CURL_TYPEOF_CURL_OFF_T definition is missing!"
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing
#endif
#ifndef CURL_FORMAT_CURL_OFF_T
# error "CURL_FORMAT_CURL_OFF_T definition is missing!"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing
#endif
#ifndef CURL_FORMAT_CURL_OFF_TU
# error "CURL_FORMAT_CURL_OFF_TU definition is missing!"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
#endif
#ifndef CURL_FORMAT_OFF_T
# error "CURL_FORMAT_OFF_T definition is missing!"
Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
#endif
#ifndef CURL_SIZEOF_CURL_OFF_T
# error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
#endif
#ifndef CURL_SUFFIX_CURL_OFF_T
# error "CURL_SUFFIX_CURL_OFF_T definition is missing!"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing
#endif
#ifndef CURL_SUFFIX_CURL_OFF_TU
# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing
#endif
/*
* Macros private to this header file.
*/
#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1
#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
/*
* Verify that the size previously defined and expected for long
* is the same as the one reported by sizeof() at compile time.
*/
typedef char
__curl_rule_01__
[CurlchkszEQ(long, CURL_SIZEOF_LONG)];
/*
* Verify that the size previously defined and expected for
* curl_off_t is actually the the same as the one reported
* by sizeof() at compile time.
*/
typedef char
__curl_rule_02__
[CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)];
/*
* Verify at compile time that the size of curl_off_t as reported
* by sizeof() is greater or equal than the one reported for long
* for the current compilation.
*/
typedef char
__curl_rule_03__
[CurlchkszGE(curl_off_t, long)];
/*
* Verify that the size previously defined and expected for
* curl_socklen_t is actually the the same as the one reported
* by sizeof() at compile time.
*/
typedef char
__curl_rule_04__
[CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)];
/*
* Verify at compile time that the size of curl_socklen_t as reported
* by sizeof() is greater or equal than the one reported for int for
* the current compilation.
*/
typedef char
__curl_rule_05__
[CurlchkszGE(curl_socklen_t, int)];
/* ================================================================ */
/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */
/* ================================================================ */
/*
* CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
* these to be visible and exported by the external libcurl interface API,
* while also making them visible to the library internals, simply including
* setup.h, without actually needing to include curl.h internally.
* If some day this section would grow big enough, all this should be moved
* to its own header file.
*/
/*
* Figure out if we can use the ## preprocessor operator, which is supported
* by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
* or __cplusplus so we need to carefully check for them too.
*/
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
defined(__ILEC400__)
/* This compiler is believed to have an ISO compatible preprocessor */
#define CURL_ISOCPP
#else
/* This compiler is believed NOT to have an ISO compatible preprocessor */
#undef CURL_ISOCPP
#endif
/*
* Macros for minimum-width signed and unsigned curl_off_t integer constants.
*/
#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
# define __CURL_OFF_T_C_HLPR2(x) x
# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
#else
# ifdef CURL_ISOCPP
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
# else
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
# endif
# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
#endif
/*
* Get rid of macros private to this header file.
*/
#undef CurlchkszEQ
#undef CurlchkszGE
/*
* Get rid of macros not intended to exist beyond this point.
*/
#undef CURL_PULL_WS2TCPIP_H
#undef CURL_PULL_SYS_TYPES_H
#undef CURL_PULL_SYS_SOCKET_H
#undef CURL_PULL_STDINT_H
#undef CURL_PULL_INTTYPES_H
#undef CURL_TYPEOF_CURL_SOCKLEN_T
#undef CURL_TYPEOF_CURL_OFF_T
#ifdef CURL_NO_OLDIES
#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */
#endif
#endif /* __CURL_CURLRULES_H */
+1
View File
@@ -0,0 +1 @@
/* not used */
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+94 -94
View File
@@ -1,94 +1,94 @@
# CMake project definition file.
project(libgme)
include (CheckCXXCompilerFlag)
# When version is changed, also change the one in gme/gme.h to match
set(GME_VERSION 0.6.2 CACHE INTERNAL "libgme Version")
# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't.
# Of course, 2.4 might work, in which case you're welcome to drop
# down the requirement, but I can't test that.
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
# Default emulators to build (all of them! ;)
if (NOT DEFINED USE_GME_AY)
SET(USE_GME_AY 1 CACHE BOOL "Enable support for Spectrum ZX music emulation")
endif()
if (NOT DEFINED USE_GME_GBS)
SET(USE_GME_GBS 1 CACHE BOOL "Enable support for Game Boy music emulation")
endif()
if (NOT DEFINED USE_GME_GYM)
SET(USE_GME_GYM 1 CACHE BOOL "Enable Sega MegaDrive/Genesis music emulation")
endif()
if (NOT DEFINED USE_GME_HES)
SET(USE_GME_HES 1 CACHE BOOL "Enable PC Engine/TurboGrafx-16 music emulation")
endif()
if (NOT DEFINED USE_GME_KSS)
SET(USE_GME_KSS 1 CACHE BOOL "Enable MSX or other Z80 systems music emulation")
endif()
if (NOT DEFINED USE_GME_NSF)
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation")
endif()
if (NOT DEFINED USE_GME_NSFE)
SET(USE_GME_NSFE 1 CACHE BOOL "Enable NES NSFE and NSF music emulation")
endif()
if (NOT DEFINED USE_GME_SAP)
SET(USE_GME_SAP 1 CACHE BOOL "Enable Atari SAP music emulation")
endif()
if (NOT DEFINED USE_GME_SPC)
SET(USE_GME_SPC 1 CACHE BOOL "Enable SNES SPC music emulation")
endif()
if (NOT DEFINED USE_GME_VGM)
SET(USE_GME_VGM 1 CACHE BOOL "Enable Sega VGM/VGZ music emulation")
endif()
if (USE_GME_NSFE AND NOT USE_GME_NSF)
MESSAGE(" -- NSFE support requires NSF, enabling NSF support. --")
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE)
endif()
option(BUILD_SHARED_LIBS "Build shared library (set to OFF for static library)" ON)
# Check for GCC "visibility" support.
if (CMAKE_COMPILER_IS_GNUCXX)
check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY)
set (ENABLE_VISIBILITY OFF)
if (__LIBGME_TEST_VISIBILITY)
# get the gcc version
exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE _gcc_version_info)
string (REGEX MATCH "[3-9]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}")
# gcc <4.1 had poor support for symbol visibility
if ((${_gcc_version} VERSION_GREATER "4.1") OR (${_gcc_version} VERSION_EQUAL "4.1"))
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
set (ENABLE_VISIBILITY ON)
add_definitions (-DLIBGME_VISIBILITY)
# GCC >= 4.2 also correctly supports making inline members have hidden
# visibility by default.
if ((${_gcc_version} VERSION_GREATER "4.2") OR (${_gcc_version} VERSION_EQUAL "4.2"))
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
endif()
endif()
endif() # test visibility
# Cache this result
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
endif (CMAKE_COMPILER_IS_GNUCXX)
# Shared library defined here
add_subdirectory(gme)
# EXCLUDE_FROM_ALL adds build rules but keeps it out of default build
add_subdirectory(player EXCLUDE_FROM_ALL)
add_subdirectory(demo EXCLUDE_FROM_ALL)
# CMake project definition file.
project(libgme)
include (CheckCXXCompilerFlag)
# When version is changed, also change the one in gme/gme.h to match
set(GME_VERSION 0.6.2 CACHE INTERNAL "libgme Version")
# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't.
# Of course, 2.4 might work, in which case you're welcome to drop
# down the requirement, but I can't test that.
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
# Default emulators to build (all of them! ;)
if (NOT DEFINED USE_GME_AY)
SET(USE_GME_AY 1 CACHE BOOL "Enable support for Spectrum ZX music emulation")
endif()
if (NOT DEFINED USE_GME_GBS)
SET(USE_GME_GBS 1 CACHE BOOL "Enable support for Game Boy music emulation")
endif()
if (NOT DEFINED USE_GME_GYM)
SET(USE_GME_GYM 1 CACHE BOOL "Enable Sega MegaDrive/Genesis music emulation")
endif()
if (NOT DEFINED USE_GME_HES)
SET(USE_GME_HES 1 CACHE BOOL "Enable PC Engine/TurboGrafx-16 music emulation")
endif()
if (NOT DEFINED USE_GME_KSS)
SET(USE_GME_KSS 1 CACHE BOOL "Enable MSX or other Z80 systems music emulation")
endif()
if (NOT DEFINED USE_GME_NSF)
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation")
endif()
if (NOT DEFINED USE_GME_NSFE)
SET(USE_GME_NSFE 1 CACHE BOOL "Enable NES NSFE and NSF music emulation")
endif()
if (NOT DEFINED USE_GME_SAP)
SET(USE_GME_SAP 1 CACHE BOOL "Enable Atari SAP music emulation")
endif()
if (NOT DEFINED USE_GME_SPC)
SET(USE_GME_SPC 1 CACHE BOOL "Enable SNES SPC music emulation")
endif()
if (NOT DEFINED USE_GME_VGM)
SET(USE_GME_VGM 1 CACHE BOOL "Enable Sega VGM/VGZ music emulation")
endif()
if (USE_GME_NSFE AND NOT USE_GME_NSF)
MESSAGE(" -- NSFE support requires NSF, enabling NSF support. --")
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE)
endif()
option(BUILD_SHARED_LIBS "Build shared library (set to OFF for static library)" ON)
# Check for GCC "visibility" support.
if (CMAKE_COMPILER_IS_GNUCXX)
check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY)
set (ENABLE_VISIBILITY OFF)
if (__LIBGME_TEST_VISIBILITY)
# get the gcc version
exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE _gcc_version_info)
string (REGEX MATCH "[3-9]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}")
# gcc <4.1 had poor support for symbol visibility
if ((${_gcc_version} VERSION_GREATER "4.1") OR (${_gcc_version} VERSION_EQUAL "4.1"))
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
set (ENABLE_VISIBILITY ON)
add_definitions (-DLIBGME_VISIBILITY)
# GCC >= 4.2 also correctly supports making inline members have hidden
# visibility by default.
if ((${_gcc_version} VERSION_GREATER "4.2") OR (${_gcc_version} VERSION_EQUAL "4.2"))
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
endif()
endif()
endif() # test visibility
# Cache this result
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
endif (CMAKE_COMPILER_IS_GNUCXX)
# Shared library defined here
add_subdirectory(gme)
# EXCLUDE_FROM_ALL adds build rules but keeps it out of default build
add_subdirectory(player EXCLUDE_FROM_ALL)
add_subdirectory(demo EXCLUDE_FROM_ALL)
+5 -5
View File
@@ -1,5 +1,5 @@
Game_Music_Emu Change Log
-------------------------
Please see the git version history (e.g. git shortlog tags/0.6.0..tags/0.6.1)
for the accurate change log.
Game_Music_Emu Change Log
-------------------------
Please see the git version history (e.g. git shortlog tags/0.6.0..tags/0.6.1)
for the accurate change log.
+194 -194
View File
@@ -1,194 +1,194 @@
Game_Music_Emu 0.6.0 Design
---------------------------
This might be slightly out-of-date at times, but will be a big help in
understanding the library implementation.
Architecture
------------
The library is essentially a bunch of independent game music file
emulators unified with a common interface.
Gme_File and Music_Emu provide a common interface to the emulators. The
virtual functions are protected rather than public to allow pre- and
post-processing of arguments and data in one place. This allows the
emulator classes to assume that everything is set up properly when
starting a track and playing samples.
All file input is done with the Data_Reader interface. Many derived
classes are present, for the usual disk-based file and block of memory,
to specialized adaptors for things like reading a subset of data or
combining a block of memory with a Data_Reader to the remaining data.
This makes the library much more flexible with regard to the source of
game music file data. I still added a specialized load_mem() function to
have the emulator keep a pointer to data already read in memory, for
those formats whose files can be absolutely huge (GYM, some VGMs). This
is important if for some reason the caller must load the data ahead of
time, but doesn't want the emulator needlessly making a copy.
Since silence checking and fading are relatively complex, they are kept
separate from basic file loading and track information, which are
handled in the base class Gme_File. My original intent was to use
Gme_File as the common base class for full emulators and track
information-only readers, but implementing the C interface was much
simpler if both derived from Music_Emu. User C++ code can still benefit
from static checking by using Gme_File where only track information will
be accessed.
Each emulator generally has three components: main emulator, CPU
emulator, and sound chip emulator(s). Each component has minimal
coupling, so use in a full emulator or stand alone is fairly easy. This
modularity really helps reduce complexity. Blip_Buffer helps a lot with
simplifying the APU interfaces and implementation.
The "classic" emulators derive from Classic_Emu, which handles
Blip_Buffer filling and multiple channels. It uses Multi_Buffer for
output, allowing you to derive a custom buffer that could output each
voice to a separate sound channel and do different processing on each.
At some point I'm going to implement a better Effects_Buffer that allows
individual control of every channel.
In implementing the C interface, I wanted a way to specify an emulator
type that didn't require linking in all the emulators. For each emulator
type there is a global object with pointers to functions to create the
emulator or a track information reader. The emulator type is thus a
pointer to this, which conveniently allows for a NULL value. The user
referencing this emulator type object is what ultimately links the
emulator in (unless new Foo_Emu is used in C++, of course). This type
also serves as a useful substitute for RTTI on older C++ compilers.
Addendum: I have since added gme_type_list(), which causes all listed
emulators to be linked in. To avoid this, I make the list itself
editable in blargg_config.h. Having a built-in list allows
gme_load_file() to take a path and give back an emulator with the file
loaded, which is extremely useful for new users.
Interface conventions
----------------------
If a function retains a pointer to or replaces the value of an object
passed, it takes a pointer so that it will be clear in the caller's
source code that care is required.
Multi-word names have an underscore '_' separator between individual
words.
Functions are named with lowercase words. Functions which perform an
action with side-effects are named with a verb phrase (i.e. load, move,
run). Functions which return the value of a piece of state are named
using a noun phrase (i.e. loaded, moved, running).
Classes are named with capitalized words. Only the first letter of an
acronym is capitalized. Class names are nouns, sometimes suggestive of
what they do (i.e. File_Scanner).
Structure, enumeration, and typedefs to these and built-in types are
named using lowercase words with a _t suffix.
Macros are named with all-uppercase words.
Internal names which can't be hidden due to technical reasons have an
underscore '_' suffix.
Managing Complexity
-------------------
Complexity has been a factor in most library decisions. Many features
have been passed by due to the complexity they would add. Once
complexity goes past a certain level, it mentally grasping the library
in its entirety, at which point more defects will occur and be hard to
find.
I chose 16-bit signed samples because it seems to be the most common
format. Supporting multiple formats would add too much complexity to be
worth it. Other formats can be obtained via conversion.
I've kept interfaces fairly lean, leaving many possible features
untapped but easy to add if necessary. For example the classic emulators
could have volume and frequency equalization adjusted separately for
each channel, since they each have an associated Blip_Synth.
Source files of 400 lines or less seem to be the best size to limit
complexity. In a few cases there is no reasonable way to split longer
files, or there is benefit from having the source together in one file.
Preventing Bugs
---------------
I've done many things to reduce the opportunity for defects. A general
principle is to write code so that defects will be as visible as
possible. I've used several techniques to achieve this.
I put assertions at key points where defects seem likely or where
corruption due to a defect is likely to be visible. I've also put
assertions where violations of the interface are likely. In emulators
where I am unsure of exact hardware operation in a particular case, I
output a debug-only message noting that this has occurred; many times I
haven't implemented a hardware feature because nothing uses it. I've
made code brittle where there is no clear reason flexibility; code
written to handle every possibility sacrifices quality and reliability
to handle vaguely defined situations.
Flexibility through indirection
-------------------------------
I've tried to allow the most flexibility of modules by using indirection
to allow extension by the user. This keeps each module simpler and more
focused on its unique task.
The classic emulators use Multi_Buffer, which potentially allows a
separate Blip_Buffer for each channel. This keeps emulators free of
typical code to allow output in mono, stereo, panning, etc.
All emulators use a reader object to access file data, allowing it to be
stored in a regular file, compressed archive, memory, or generated
on-the-fly. Again, the library can be kept free of the particulars of
file access and changes required to support new formats.
Emulators in general
--------------------
When I wrote the first NES sound emulator, I stored most of the state in
an emulator-specific format, with significant redundancy. In the
register write function I decoded everything into named variables. I
became tired of the verbosity and wanted to more closely model the
hardware, so I moved to a style of storing the last written value to
each register, along with as little other state as possible, mostly the
internal hardware registers. While this involves slightly more
recalculation, in most cases the emulation code is of comparable size.
It also makes state save/restore (for use in a full emulator) much
simpler. Finally, it makes debugging easier since the hardware registers
used in emulation are obvious.
CPU Cores
---------
I've spent lots of time coming up with techniques to optimize the CPU
cores. Some of the most important: execute multiple instructions during
an emulation call, keep state in local variables to allow register
assignment, optimize state representation for most common instructions,
defer status flag calculation until actually needed, read program code
directly without a call to the memory read function, always pre-fetch
the operand byte before decoding instruction, and emulate instructions
using common blocks of code.
I've successfully used Nes_Cpu in a fairly complete NES emulator, and
I'd like to make all the CPU emulators suitable for use in emulators. It
seems a waste for them to be used only for the small amount of emulation
necessary for game music files.
I debugged the CPU cores by writing a test shell that ran them in
parallel with other CPU cores and compared all memory accesses and
processor states at each step. This provided good value at little cost.
The CPU mapping page size is adjustable to allow the best tradeoff
between memory/cache usage and handler granularity. The interface allows
code to be somewhat independent of the page size.
I optimize program memory accesses to direct reads rather than calls to
the memory read function. My assumption is that it would be difficult to
get useful code out of hardware I/O addresses, so no software will
intentionally execute out of I/O space. Since the page size can be
changed easily, most program memory mapping schemes can be accommodated.
This greatly reduces memory access function calls.
Game_Music_Emu 0.6.0 Design
---------------------------
This might be slightly out-of-date at times, but will be a big help in
understanding the library implementation.
Architecture
------------
The library is essentially a bunch of independent game music file
emulators unified with a common interface.
Gme_File and Music_Emu provide a common interface to the emulators. The
virtual functions are protected rather than public to allow pre- and
post-processing of arguments and data in one place. This allows the
emulator classes to assume that everything is set up properly when
starting a track and playing samples.
All file input is done with the Data_Reader interface. Many derived
classes are present, for the usual disk-based file and block of memory,
to specialized adaptors for things like reading a subset of data or
combining a block of memory with a Data_Reader to the remaining data.
This makes the library much more flexible with regard to the source of
game music file data. I still added a specialized load_mem() function to
have the emulator keep a pointer to data already read in memory, for
those formats whose files can be absolutely huge (GYM, some VGMs). This
is important if for some reason the caller must load the data ahead of
time, but doesn't want the emulator needlessly making a copy.
Since silence checking and fading are relatively complex, they are kept
separate from basic file loading and track information, which are
handled in the base class Gme_File. My original intent was to use
Gme_File as the common base class for full emulators and track
information-only readers, but implementing the C interface was much
simpler if both derived from Music_Emu. User C++ code can still benefit
from static checking by using Gme_File where only track information will
be accessed.
Each emulator generally has three components: main emulator, CPU
emulator, and sound chip emulator(s). Each component has minimal
coupling, so use in a full emulator or stand alone is fairly easy. This
modularity really helps reduce complexity. Blip_Buffer helps a lot with
simplifying the APU interfaces and implementation.
The "classic" emulators derive from Classic_Emu, which handles
Blip_Buffer filling and multiple channels. It uses Multi_Buffer for
output, allowing you to derive a custom buffer that could output each
voice to a separate sound channel and do different processing on each.
At some point I'm going to implement a better Effects_Buffer that allows
individual control of every channel.
In implementing the C interface, I wanted a way to specify an emulator
type that didn't require linking in all the emulators. For each emulator
type there is a global object with pointers to functions to create the
emulator or a track information reader. The emulator type is thus a
pointer to this, which conveniently allows for a NULL value. The user
referencing this emulator type object is what ultimately links the
emulator in (unless new Foo_Emu is used in C++, of course). This type
also serves as a useful substitute for RTTI on older C++ compilers.
Addendum: I have since added gme_type_list(), which causes all listed
emulators to be linked in. To avoid this, I make the list itself
editable in blargg_config.h. Having a built-in list allows
gme_load_file() to take a path and give back an emulator with the file
loaded, which is extremely useful for new users.
Interface conventions
----------------------
If a function retains a pointer to or replaces the value of an object
passed, it takes a pointer so that it will be clear in the caller's
source code that care is required.
Multi-word names have an underscore '_' separator between individual
words.
Functions are named with lowercase words. Functions which perform an
action with side-effects are named with a verb phrase (i.e. load, move,
run). Functions which return the value of a piece of state are named
using a noun phrase (i.e. loaded, moved, running).
Classes are named with capitalized words. Only the first letter of an
acronym is capitalized. Class names are nouns, sometimes suggestive of
what they do (i.e. File_Scanner).
Structure, enumeration, and typedefs to these and built-in types are
named using lowercase words with a _t suffix.
Macros are named with all-uppercase words.
Internal names which can't be hidden due to technical reasons have an
underscore '_' suffix.
Managing Complexity
-------------------
Complexity has been a factor in most library decisions. Many features
have been passed by due to the complexity they would add. Once
complexity goes past a certain level, it mentally grasping the library
in its entirety, at which point more defects will occur and be hard to
find.
I chose 16-bit signed samples because it seems to be the most common
format. Supporting multiple formats would add too much complexity to be
worth it. Other formats can be obtained via conversion.
I've kept interfaces fairly lean, leaving many possible features
untapped but easy to add if necessary. For example the classic emulators
could have volume and frequency equalization adjusted separately for
each channel, since they each have an associated Blip_Synth.
Source files of 400 lines or less seem to be the best size to limit
complexity. In a few cases there is no reasonable way to split longer
files, or there is benefit from having the source together in one file.
Preventing Bugs
---------------
I've done many things to reduce the opportunity for defects. A general
principle is to write code so that defects will be as visible as
possible. I've used several techniques to achieve this.
I put assertions at key points where defects seem likely or where
corruption due to a defect is likely to be visible. I've also put
assertions where violations of the interface are likely. In emulators
where I am unsure of exact hardware operation in a particular case, I
output a debug-only message noting that this has occurred; many times I
haven't implemented a hardware feature because nothing uses it. I've
made code brittle where there is no clear reason flexibility; code
written to handle every possibility sacrifices quality and reliability
to handle vaguely defined situations.
Flexibility through indirection
-------------------------------
I've tried to allow the most flexibility of modules by using indirection
to allow extension by the user. This keeps each module simpler and more
focused on its unique task.
The classic emulators use Multi_Buffer, which potentially allows a
separate Blip_Buffer for each channel. This keeps emulators free of
typical code to allow output in mono, stereo, panning, etc.
All emulators use a reader object to access file data, allowing it to be
stored in a regular file, compressed archive, memory, or generated
on-the-fly. Again, the library can be kept free of the particulars of
file access and changes required to support new formats.
Emulators in general
--------------------
When I wrote the first NES sound emulator, I stored most of the state in
an emulator-specific format, with significant redundancy. In the
register write function I decoded everything into named variables. I
became tired of the verbosity and wanted to more closely model the
hardware, so I moved to a style of storing the last written value to
each register, along with as little other state as possible, mostly the
internal hardware registers. While this involves slightly more
recalculation, in most cases the emulation code is of comparable size.
It also makes state save/restore (for use in a full emulator) much
simpler. Finally, it makes debugging easier since the hardware registers
used in emulation are obvious.
CPU Cores
---------
I've spent lots of time coming up with techniques to optimize the CPU
cores. Some of the most important: execute multiple instructions during
an emulation call, keep state in local variables to allow register
assignment, optimize state representation for most common instructions,
defer status flag calculation until actually needed, read program code
directly without a call to the memory read function, always pre-fetch
the operand byte before decoding instruction, and emulate instructions
using common blocks of code.
I've successfully used Nes_Cpu in a fairly complete NES emulator, and
I'd like to make all the CPU emulators suitable for use in emulators. It
seems a waste for them to be used only for the small amount of emulation
necessary for game music files.
I debugged the CPU cores by writing a test shell that ran them in
parallel with other CPU cores and compared all memory accesses and
processor states at each step. This provided good value at little cost.
The CPU mapping page size is adjustable to allow the best tradeoff
between memory/cache usage and handler granularity. The interface allows
code to be somewhat independent of the page size.
I optimize program memory accesses to direct reads rather than calls to
the memory read function. My assumption is that it would be difficult to
get useful code out of hardware I/O addresses, so no software will
intentionally execute out of I/O space. Since the page size can be
changed easily, most program memory mapping schemes can be accommodated.
This greatly reduces memory access function calls.
+376 -376
View File
@@ -1,376 +1,376 @@
Game_Music_Emu 0.6.2
--------------------
Author : Shay Green <gblargg@gmail.com>
Maintainer : Michael Pyne <mpyne@purinchu.net>
Website : https://bitbucket.org/mpyne/game-music-emu/
Source : https://bitbucket.org/mpyne/game-music-emu/
License : GNU Lesser General Public License (LGPL), see LICENSE.txt
Contents
--------
* Overview
* Error handling
* Emulator types
* M3U playlist support
* Information fields
* Track length
* Loading file data
* Sound parameters
* VGM/GYM YM2413 & YM2612 FM sound
* Modular construction
* Obscure features
* Solving problems
* Thanks
Overview
--------
This library can open game music files, play tracks, and read game and
track information tags. To play a game music file, do the following:
* Open the file with gme_open_file()
* Start a track with gme_start_track();
* Generate samples as needed with gme_play()
* Play samples through speaker using your operating system
* Delete emulator when done with gme_delete()
Your code must arrange for the generated samples to be played through
the computer's speaker using whatever method your operating system
requires.
There are many additional features available; you can:
* Determine of the type of a music file without opening it with
gme_identify_*()
* Load just the file's information tags with gme_info_only
* Load from a block of memory rather than a file with gme_load_data()
* Arrange for a fade-out at a particular time with gme_set_fade
* Find when a track has ended with gme_track_ended()
* Seek to a new time in the track with gme_seek()
* Load an extended m3u playlist with gme_load_m3u()
* Get a list of the voices (channels) and mute them individually with
gme_voice_names() and gme_mute_voice()
* Change the playback tempo without affecting pitch with gme_set_tempo()
* Adjust treble/bass equalization with gme_set_equalizer()
* Associate your own data with an emulator and later get it back with
gme_set_user_data()
* Register a function of yours to be called back when the emulator is
deleted with gme_set_user_cleanup()
Refer to gme.h for a comprehensive summary of features.
Error handling
--------------
Functions which can fail have a return type of gme_err_t, which is a
pointer to an error string (const char*). If a function is successful it
returns NULL. Errors that you can easily avoid are checked with debug
assertions; gme_err_t return values are only used for genuine run-time
errors that can't be easily predicted in advance (out of memory, I/O
errors, incompatible file data). Your code should check all error
values.
When loading a music file in the wrong emulator or trying to load a
non-music file, gme_wrong_file_type is returned. You can check for this
error in C++ like this:
gme_err_t err = gme_open_file( path, &emu );
if ( err == gme_wrong_file_type )
...
To check for minor problems, call gme_warning() to get a string
describing the last warning. Your player should allow the user some way
of knowing when this is the case, since these minor errors could affect
playback. Without this information the user can't solve problems as
well. When playing a track, gme_warning() returns minor playback-related
problems (major playback problems end the track immediately and set the
warning string).
Emulator types
--------------
The library includes several game music emulators that each support a
different file type. Each is identified by a gme_type_t constant defined
in gme.h, for example gme_nsf_emu is for the NSF emulator. If you use
gme_open_file() or gme_open_data(), the library does the work of
determining the file type and creating an appropriate emulator. If you
want more control over this process, read on.
There are two basic ways to identify a game music file's type: look at
its file extension, or read the header data. The library includes
functions to help with both methods. The first is preferable because it
is fast and the most common way to identify files. Sometimes the
extension is lost or wrong, so the header must be read.
Use gme_identify_extension() to find the correct game music type based
on a filename. To identify a file based on its extension and header
contents, use gme_identify_file(). If you read the header data yourself,
use gme_identify_header().
If you want to remove support for some music types to reduce your
executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
support just NSF and GBS, use this:
#define GME_TYPE_LIST \
gme_nsf_type,\
gme_gbs_type
M3U playlist support
--------------------
The library supports playlists in an extended m3u format with
gme_load_m3u() to give track names and times to multi-song formats: AY,
GBS, HES, KSS, NSF, NSFE, and SAP. Some aspects of the file format
itself is not well-defined so some m3u files won't work properly
(particularly those provided with KSS files). Only m3u files referencing
a single file are supported; your code must handle m3u files covering
more than one game music file, though it can use the built-in m3u
parsing provided by the library.
Information fields
------------------
Support is provided for the various text fields and length information
in a file with gme_track_info(). If you just need track information for
a file (for example, building a playlist), use gme_new_info() in place
of gme_new_emu(), load the file normally, then you can access the track
count and info, but nothing else.
M3U VGM GYM SPC SAP NSFE NSF AY GBS HES KSS
-------------------------------------------------------
Track Count | * * * * * * * * *
|
System | * * * * * * * * * *
|
Game | * * * * * * *
|
Song | * * * * * * *
|
Author | * * * * * * * *
|
Copyright | * * * * * * * *
|
Comment | * * * *
|
Dumper | * * * *
|
Length | * * * * * *
|
Intro Length| * * *
|
Loop Length | * * *
As listed above, the HES and KSS file formats don't include a track
count, and tracks are often scattered over the 0-255 range, so an m3u
playlist for these is a must.
Unavailable text fields are set to an empty string and times to -1. Your
code should be prepared for any combination of available and unavailable
fields, as a particular music file might not use all of the supported
fields listed above.
Currently text fields are truncated to 255 characters. Obscure fields of
some formats are not currently decoded; contact me if you want one
added.
Track length
------------
The library leaves it up to you as to when to stop playing a track. You
can ask for available length information and then tell the library what
time it should start fading the track with gme_set_fade(). By default it
also continually checks for 6 or more seconds of silence to mark the end
of a track. Here is a reasonable algorithm you can use to decide how
long to play a track:
* If the track length is > 0, use it
* If the loop length > 0, play for intro + loop * 2
* Otherwise, default to 2.5 minutes (150000 msec)
If you want to play a track longer than normal, be sure the loop length
isn't zero. See Music_Player.cpp around line 145 for example code.
By default, the library skips silence at the beginning of a track. It
also continually checks for the end of a non-looping track by watching
for 6 seconds of unbroken silence. When doing this is scans *ahead* by
several seconds so it can report the end of the track after only one
second of silence has actually played. This feature can be disabled with
gme_ignore_silence().
Loading file data
-----------------
The library allows file data to be loaded in many different ways. All
load functions return an error which you should check. The following
examples assume these variables:
Music_Emu* emu;
gme_err_t error;
If you're letting the library determine a file's type, you can use
either gme_open_file() or gme_open_data():
error = gme_open_file( pathname, &emu );
error = gme_open_data( pointer, size, &emu );
If you're manually determining file type and using used gme_new_emu() to
create an emulator, you can use the following methods of loading:
* From a block of memory:
error = gme_load_data( emu, pointer, size );
* Have library call your function to read data:
gme_err_t my_read( void* my_data, void* out, long count )
{
// code that reads 'count' bytes into 'out' buffer
// and return 0 if no error
}
error = gme_load_custom( emu, my_read, file_size, my_data );
Sound parameters
----------------
All emulators support an arbitrary output sampling rate. A rate of 44100
Hz should work well on most systems. Since band-limited synthesis is
used, a sampling rate above 48000 Hz is not necessary and will actually
reduce sound quality and performance.
All emulators also support adjustable gain, mainly for the purpose of
getting consistent volume between different music formats and avoiding
excessive modulation. The gain can only be set *before* setting the
emulator's sampling rate, so it's not useful as a general volume
control. The default gains of emulators are set so that they give
generally similar volumes, though some soundtracks are significantly
louder or quieter than normal.
Some emulators support adjustable treble and bass frequency equalization
(AY, GBS, HES, KSS, NSF, NSFE, SAP, VGM) using set_equalizer().
Parameters are specified using gme_equalizer_t eq = { treble_dB,
bass_freq }. Treble_dB sets the treble level (in dB), where 0.0 dB gives
normal treble; -200.0 dB is quite muffled, and 5.0 dB emphasizes treble
for an extra crisp sound. Bass_freq sets the frequency where bass
response starts to diminish; 15 Hz is normal, 0 Hz gives maximum bass,
and 15000 Hz removes all bass. For example, the following makes the
sound extra-crisp but lacking bass:
gme_equalizer_t eq = { 5.0, 1000 };
gme_set_equalizer( music_emu, &eq );
Each emulator's equalization defaults to approximate the particular
console's sound quality; this default can be determined by calling
equalizer() just after creating the emulator. The Music_Emu::tv_eq
profile gives sound as if coming from a TV speaker, and some emulators
include other profiles for different versions of the system. For
example, to use Famicom sound equalization with the NSF emulator, do the
following:
music_emu->set_equalizer( Nsf_Emu::famicom_eq );
VGM/GYM YM2413 & YM2612 FM sound
--------------------------------
The library plays Sega Genesis/Mega Drive music using a YM2612 FM sound
chip emulator based on the Gens project. Because this has some
inaccuracies, other YM2612 emulators can be used in its place by
re-implementing the interface in YM2612_Emu.h. Available on my website
is a modified version of MAME's YM2612 emulator, which sounds better in
some ways and whose author is still making improvements.
VGM music files using the YM2413 FM sound chip are also supported, but a
YM2413 emulator isn't included with the library due to technical
reasons. I have put one of the available YM2413 emulators on my website
that can be used directly.
Modular construction
--------------------
The library is made of many fairly independent modules. If you're using
only one music file emulator, you can eliminate many of the library
sources from your program. Refer to the files list in readme.txt to get
a general idea of what can be removed, and be sure to edit GME_TYPE_LIST
(see "Emulator types" above). Post to the forum if you'd like me to put
together a smaller version for a particular use, as this only takes me a
few minutes to do.
If you want to use one of the individual sound chip emulators (or CPU
cores) in your own console emulator, first check the libraries page on
my website since I have released several of them as stand alone
libraries with included documentation and examples on their use. If you
don't find it as a standalone library, contact me and I'll consider
separating it.
The "classic" sound chips use my Blip_Buffer library, which greatly
simplifies their implementation and efficiently handles band-limited
synthesis. It is also available as a stand alone library with
documentation and many examples.
Obscure features
----------------
The library's flexibility allows many possibilities. Contact me if you
want help implementing ideas or removing limitations.
* Uses no global/static variables, allowing multiple instances of any
emulator. This is useful in a music player if you want to allow
simultaneous recording or scanning of other tracks while one is already
playing. This will also be useful if your platform disallows global
data.
* Emulators that support a custom sound buffer can have *every* voice
routed to a different Blip_Buffer, allowing custom processing on each
voice. For example you could record a Game Boy track as a 4-channel
sound file.
* Defining BLIP_BUFFER_FAST uses lower quality, less-multiply-intensive
synthesis on "classic" emulators, which might help on some really old
processors. This significantly lowers sound quality and prevents treble
equalization. Try this if your platform's processor isn't fast enough
for normal quality. Even on my ten-year-old 400 MHz Mac, this reduces
processor usage at most by about 0.6% (from 4% to 3.4%), hardly worth
the quality loss.
Solving problems
----------------
If you're having problems, try the following:
* If you're getting garbled sound, try this simple siren generator in
place of your call to play(). This will quickly tell whether the problem
is in the library or in your code.
static void play_siren( long count, short* out )
{
static double a, a2;
while ( count-- )
*out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) );
}
* Enable debugging support in your environment. This enables assertions
and other run-time checks.
* Turn the compiler's optimizer is off. Sometimes an optimizer generates
bad code.
* If multiple threads are being used, ensure that only one at a time is
accessing a given set of objects from the library. This library is not
in general thread-safe, though independent objects can be used in
separate threads.
* If all else fails, see if the demos work.
Thanks
------
Big thanks to Chris Moeller (kode54) for help with library testing and
feedback, for maintaining the Foobar2000 plugin foo_gep based on it, and
for original work on openspc++ that was used when developing Spc_Emu.
Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
and giving feedback for the library in their respective game music
players. More recently, Lucas Paul and Michael Pyne have helped nudge the
library into a public repository and get its interface more stable for use
in shared libraries.
Game_Music_Emu 0.6.2
--------------------
Author : Shay Green <gblargg@gmail.com>
Maintainer : Michael Pyne <mpyne@purinchu.net>
Website : https://bitbucket.org/mpyne/game-music-emu/
Source : https://bitbucket.org/mpyne/game-music-emu/
License : GNU Lesser General Public License (LGPL), see LICENSE.txt
Contents
--------
* Overview
* Error handling
* Emulator types
* M3U playlist support
* Information fields
* Track length
* Loading file data
* Sound parameters
* VGM/GYM YM2413 & YM2612 FM sound
* Modular construction
* Obscure features
* Solving problems
* Thanks
Overview
--------
This library can open game music files, play tracks, and read game and
track information tags. To play a game music file, do the following:
* Open the file with gme_open_file()
* Start a track with gme_start_track();
* Generate samples as needed with gme_play()
* Play samples through speaker using your operating system
* Delete emulator when done with gme_delete()
Your code must arrange for the generated samples to be played through
the computer's speaker using whatever method your operating system
requires.
There are many additional features available; you can:
* Determine of the type of a music file without opening it with
gme_identify_*()
* Load just the file's information tags with gme_info_only
* Load from a block of memory rather than a file with gme_load_data()
* Arrange for a fade-out at a particular time with gme_set_fade
* Find when a track has ended with gme_track_ended()
* Seek to a new time in the track with gme_seek()
* Load an extended m3u playlist with gme_load_m3u()
* Get a list of the voices (channels) and mute them individually with
gme_voice_names() and gme_mute_voice()
* Change the playback tempo without affecting pitch with gme_set_tempo()
* Adjust treble/bass equalization with gme_set_equalizer()
* Associate your own data with an emulator and later get it back with
gme_set_user_data()
* Register a function of yours to be called back when the emulator is
deleted with gme_set_user_cleanup()
Refer to gme.h for a comprehensive summary of features.
Error handling
--------------
Functions which can fail have a return type of gme_err_t, which is a
pointer to an error string (const char*). If a function is successful it
returns NULL. Errors that you can easily avoid are checked with debug
assertions; gme_err_t return values are only used for genuine run-time
errors that can't be easily predicted in advance (out of memory, I/O
errors, incompatible file data). Your code should check all error
values.
When loading a music file in the wrong emulator or trying to load a
non-music file, gme_wrong_file_type is returned. You can check for this
error in C++ like this:
gme_err_t err = gme_open_file( path, &emu );
if ( err == gme_wrong_file_type )
...
To check for minor problems, call gme_warning() to get a string
describing the last warning. Your player should allow the user some way
of knowing when this is the case, since these minor errors could affect
playback. Without this information the user can't solve problems as
well. When playing a track, gme_warning() returns minor playback-related
problems (major playback problems end the track immediately and set the
warning string).
Emulator types
--------------
The library includes several game music emulators that each support a
different file type. Each is identified by a gme_type_t constant defined
in gme.h, for example gme_nsf_emu is for the NSF emulator. If you use
gme_open_file() or gme_open_data(), the library does the work of
determining the file type and creating an appropriate emulator. If you
want more control over this process, read on.
There are two basic ways to identify a game music file's type: look at
its file extension, or read the header data. The library includes
functions to help with both methods. The first is preferable because it
is fast and the most common way to identify files. Sometimes the
extension is lost or wrong, so the header must be read.
Use gme_identify_extension() to find the correct game music type based
on a filename. To identify a file based on its extension and header
contents, use gme_identify_file(). If you read the header data yourself,
use gme_identify_header().
If you want to remove support for some music types to reduce your
executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
support just NSF and GBS, use this:
#define GME_TYPE_LIST \
gme_nsf_type,\
gme_gbs_type
M3U playlist support
--------------------
The library supports playlists in an extended m3u format with
gme_load_m3u() to give track names and times to multi-song formats: AY,
GBS, HES, KSS, NSF, NSFE, and SAP. Some aspects of the file format
itself is not well-defined so some m3u files won't work properly
(particularly those provided with KSS files). Only m3u files referencing
a single file are supported; your code must handle m3u files covering
more than one game music file, though it can use the built-in m3u
parsing provided by the library.
Information fields
------------------
Support is provided for the various text fields and length information
in a file with gme_track_info(). If you just need track information for
a file (for example, building a playlist), use gme_new_info() in place
of gme_new_emu(), load the file normally, then you can access the track
count and info, but nothing else.
M3U VGM GYM SPC SAP NSFE NSF AY GBS HES KSS
-------------------------------------------------------
Track Count | * * * * * * * * *
|
System | * * * * * * * * * *
|
Game | * * * * * * *
|
Song | * * * * * * *
|
Author | * * * * * * * *
|
Copyright | * * * * * * * *
|
Comment | * * * *
|
Dumper | * * * *
|
Length | * * * * * *
|
Intro Length| * * *
|
Loop Length | * * *
As listed above, the HES and KSS file formats don't include a track
count, and tracks are often scattered over the 0-255 range, so an m3u
playlist for these is a must.
Unavailable text fields are set to an empty string and times to -1. Your
code should be prepared for any combination of available and unavailable
fields, as a particular music file might not use all of the supported
fields listed above.
Currently text fields are truncated to 255 characters. Obscure fields of
some formats are not currently decoded; contact me if you want one
added.
Track length
------------
The library leaves it up to you as to when to stop playing a track. You
can ask for available length information and then tell the library what
time it should start fading the track with gme_set_fade(). By default it
also continually checks for 6 or more seconds of silence to mark the end
of a track. Here is a reasonable algorithm you can use to decide how
long to play a track:
* If the track length is > 0, use it
* If the loop length > 0, play for intro + loop * 2
* Otherwise, default to 2.5 minutes (150000 msec)
If you want to play a track longer than normal, be sure the loop length
isn't zero. See Music_Player.cpp around line 145 for example code.
By default, the library skips silence at the beginning of a track. It
also continually checks for the end of a non-looping track by watching
for 6 seconds of unbroken silence. When doing this is scans *ahead* by
several seconds so it can report the end of the track after only one
second of silence has actually played. This feature can be disabled with
gme_ignore_silence().
Loading file data
-----------------
The library allows file data to be loaded in many different ways. All
load functions return an error which you should check. The following
examples assume these variables:
Music_Emu* emu;
gme_err_t error;
If you're letting the library determine a file's type, you can use
either gme_open_file() or gme_open_data():
error = gme_open_file( pathname, &emu );
error = gme_open_data( pointer, size, &emu );
If you're manually determining file type and using used gme_new_emu() to
create an emulator, you can use the following methods of loading:
* From a block of memory:
error = gme_load_data( emu, pointer, size );
* Have library call your function to read data:
gme_err_t my_read( void* my_data, void* out, long count )
{
// code that reads 'count' bytes into 'out' buffer
// and return 0 if no error
}
error = gme_load_custom( emu, my_read, file_size, my_data );
Sound parameters
----------------
All emulators support an arbitrary output sampling rate. A rate of 44100
Hz should work well on most systems. Since band-limited synthesis is
used, a sampling rate above 48000 Hz is not necessary and will actually
reduce sound quality and performance.
All emulators also support adjustable gain, mainly for the purpose of
getting consistent volume between different music formats and avoiding
excessive modulation. The gain can only be set *before* setting the
emulator's sampling rate, so it's not useful as a general volume
control. The default gains of emulators are set so that they give
generally similar volumes, though some soundtracks are significantly
louder or quieter than normal.
Some emulators support adjustable treble and bass frequency equalization
(AY, GBS, HES, KSS, NSF, NSFE, SAP, VGM) using set_equalizer().
Parameters are specified using gme_equalizer_t eq = { treble_dB,
bass_freq }. Treble_dB sets the treble level (in dB), where 0.0 dB gives
normal treble; -200.0 dB is quite muffled, and 5.0 dB emphasizes treble
for an extra crisp sound. Bass_freq sets the frequency where bass
response starts to diminish; 15 Hz is normal, 0 Hz gives maximum bass,
and 15000 Hz removes all bass. For example, the following makes the
sound extra-crisp but lacking bass:
gme_equalizer_t eq = { 5.0, 1000 };
gme_set_equalizer( music_emu, &eq );
Each emulator's equalization defaults to approximate the particular
console's sound quality; this default can be determined by calling
equalizer() just after creating the emulator. The Music_Emu::tv_eq
profile gives sound as if coming from a TV speaker, and some emulators
include other profiles for different versions of the system. For
example, to use Famicom sound equalization with the NSF emulator, do the
following:
music_emu->set_equalizer( Nsf_Emu::famicom_eq );
VGM/GYM YM2413 & YM2612 FM sound
--------------------------------
The library plays Sega Genesis/Mega Drive music using a YM2612 FM sound
chip emulator based on the Gens project. Because this has some
inaccuracies, other YM2612 emulators can be used in its place by
re-implementing the interface in YM2612_Emu.h. Available on my website
is a modified version of MAME's YM2612 emulator, which sounds better in
some ways and whose author is still making improvements.
VGM music files using the YM2413 FM sound chip are also supported, but a
YM2413 emulator isn't included with the library due to technical
reasons. I have put one of the available YM2413 emulators on my website
that can be used directly.
Modular construction
--------------------
The library is made of many fairly independent modules. If you're using
only one music file emulator, you can eliminate many of the library
sources from your program. Refer to the files list in readme.txt to get
a general idea of what can be removed, and be sure to edit GME_TYPE_LIST
(see "Emulator types" above). Post to the forum if you'd like me to put
together a smaller version for a particular use, as this only takes me a
few minutes to do.
If you want to use one of the individual sound chip emulators (or CPU
cores) in your own console emulator, first check the libraries page on
my website since I have released several of them as stand alone
libraries with included documentation and examples on their use. If you
don't find it as a standalone library, contact me and I'll consider
separating it.
The "classic" sound chips use my Blip_Buffer library, which greatly
simplifies their implementation and efficiently handles band-limited
synthesis. It is also available as a stand alone library with
documentation and many examples.
Obscure features
----------------
The library's flexibility allows many possibilities. Contact me if you
want help implementing ideas or removing limitations.
* Uses no global/static variables, allowing multiple instances of any
emulator. This is useful in a music player if you want to allow
simultaneous recording or scanning of other tracks while one is already
playing. This will also be useful if your platform disallows global
data.
* Emulators that support a custom sound buffer can have *every* voice
routed to a different Blip_Buffer, allowing custom processing on each
voice. For example you could record a Game Boy track as a 4-channel
sound file.
* Defining BLIP_BUFFER_FAST uses lower quality, less-multiply-intensive
synthesis on "classic" emulators, which might help on some really old
processors. This significantly lowers sound quality and prevents treble
equalization. Try this if your platform's processor isn't fast enough
for normal quality. Even on my ten-year-old 400 MHz Mac, this reduces
processor usage at most by about 0.6% (from 4% to 3.4%), hardly worth
the quality loss.
Solving problems
----------------
If you're having problems, try the following:
* If you're getting garbled sound, try this simple siren generator in
place of your call to play(). This will quickly tell whether the problem
is in the library or in your code.
static void play_siren( long count, short* out )
{
static double a, a2;
while ( count-- )
*out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) );
}
* Enable debugging support in your environment. This enables assertions
and other run-time checks.
* Turn the compiler's optimizer is off. Sometimes an optimizer generates
bad code.
* If multiple threads are being used, ensure that only one at a time is
accessing a given set of objects from the library. This library is not
in general thread-safe, though independent objects can be used in
separate threads.
* If all else fails, see if the demos work.
Thanks
------
Big thanks to Chris Moeller (kode54) for help with library testing and
feedback, for maintaining the Foobar2000 plugin foo_gep based on it, and
for original work on openspc++ that was used when developing Spc_Emu.
Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
and giving feedback for the library in their respective game music
players. More recently, Lucas Paul and Michael Pyne have helped nudge the
library into a public repository and get its interface more stable for use
in shared libraries.
-89
View File
@@ -1,89 +0,0 @@
/* Included at the beginning of library source files, after all other #include lines.
* Sets up helpful macros and services used in my source code. They don't need
* module an annoying module prefix on their names since they are defined after
* all other #include lines. */
#ifndef BLARGG_SOURCE_H
#define BLARGG_SOURCE_H
/* If debugging is enabled, abort program if expr is false. Meant for checking
* internal state and consistency. A failed assertion indicates a bug in the module.
* void assert( bool expr ); */
#include <assert.h>
/* If debugging is enabled and expr is false, abort program. Meant for checking
* caller-supplied parameters and operations that are outside the control of the
* module. A failed requirement indicates a bug outside the module.
* void require( bool expr ); */
#undef require
#define require( expr ) assert( expr )
/* Use to provide hints to compiler for optimized code layout in situations where we
* can almost always expect a conditional to go one way or the other. Should only be
* used in situations where an unexpected branch is truly exceptional though! */
#undef likely
#undef unlikely
#ifdef __GNUC__
#define likely( x ) __builtin_expect(x, 1)
#define unlikely( x ) __builtin_expect(x, 0)
#else
#define likely( x ) (x)
#define unlikely( x ) (x)
#endif
/* Like printf() except output goes to debug log file. Might be defined to do
* nothing (not even evaluate its arguments).
* void debug_printf( const char* format, ... ); */
#if defined(__cplusplus)
static inline void blargg_dprintf_( const char* fmt_str, ... ) { (void) fmt_str; }
#undef debug_printf
#define debug_printf (1) ? (void) 0 : blargg_dprintf_
#endif
/* If enabled, evaluate expr and if false, make debug log entry with source file
* and line. Meant for finding situations that should be examined further, but that
* don't indicate a problem. In all cases, execution continues normally. */
#undef check
#define check( expr ) ((void) 0)
/* If expr yields error string, return it from current function, otherwise continue. */
#undef RETURN_ERR
#define RETURN_ERR( expr ) do { \
blargg_err_t blargg_return_err_ = (expr); \
if ( blargg_return_err_ ) return blargg_return_err_; \
} while ( 0 )
/* If ptr is 0, return out of memory error string. */
#undef CHECK_ALLOC
#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 )
/* TODO: good idea? bad idea? */
#undef byte
#define byte byte_
typedef unsigned char byte;
/* Setup compiler defines useful for exporting required public API symbols in gme.cpp */
#ifndef BLARGG_EXPORT
#if defined (_WIN32)
#if defined(BLARGG_BUILD_DLL)
#define BLARGG_EXPORT __declspec(dllexport)
#else
#define BLARGG_EXPORT /* Leave blank: friendly with both static and shared linking */
#endif
#elif defined (LIBGME_VISIBILITY) && defined(__cplusplus)
#define BLARGG_EXPORT __attribute__((visibility ("default")))
#else
#define BLARGG_EXPORT
#endif
#endif
/* deprecated */
#define BLARGG_CHECK_ALLOC CHECK_ALLOC
#define BLARGG_RETURN_ERR RETURN_ERR
/* BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of debug_printf and check */
#ifdef BLARGG_SOURCE_BEGIN
#include BLARGG_SOURCE_BEGIN
#endif
#endif
-339
View File
@@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+504 -504
View File
File diff suppressed because it is too large. Load diff
+231 -231
View File
@@ -1,231 +1,231 @@
Game_Music_Emu 0.6.2: Game Music Emulators
------------------------------------------
Game_Music_Emu is a collection of video game music file emulators that
support the following formats and systems:
AY ZX Spectrum/Amstrad CPC
GBS Nintendo Game Boy
GYM Sega Genesis/Mega Drive
HES NEC TurboGrafx-16/PC Engine
KSS MSX Home Computer/other Z80 systems (doesn't support FM sound)
NSF/NSFE Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)
SAP Atari systems using POKEY sound chip
SPC Super Nintendo/Super Famicom
VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
Features:
* C interface for use in C, C++, and other compatible languages
* High emphasis has been placed on making the library very easy to use
* One set of common functions work with all emulators the same way
* Several code examples, including music player using SDL
* Portable code for use on any system with modern or older C++ compilers
* Adjustable output sample rate using quality band-limited resampling
* Uniform access to text information fields and track timing information
* End-of-track fading and automatic look ahead silence detection
* Treble/bass and stereo echo for AY/GBS/HES/KSS/NSF/NSFE/SAP/VGM
* Tempo can be adjusted and individual voices can be muted while playing
* Can read music data from file, memory, or custom reader function/class
* Can access track information without having to load into full emulator
* M3U track listing support for multi-track formats
* Modular design allows elimination of unneeded emulators/features
This library has been used in game music players for Windows, Linux on
several architectures, Mac OS, MorphOS, Xbox, PlayStation Portable,
GP2X, and Nintendo DS.
Author : Shay Green <gblargg@gmail.com>
Website: https://bitbucket.org/mpyne/game-music-emu/wiki/Home
License: GNU Lesser General Public License (LGPL)
Current Maintainer: Michael Pyne <mpyne@purinchu.net>
Getting Started
---------------
Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
all source files in gme/.
Or, if you have CMake 2.6 or later, execute at a command prompt (from the
extracted source directory):
mkdir build
cd build
cmake ../ # <-- Pass any needed CMake flags here
make # To build the library
cd demo
make # To build the demo itself
Be sure "test.nsf" is in the same directory as the demo program. Running it
should generate the recording "out.wav".
You can use "make install" to install the library. To choose where to install
the library to, use the CMake argument "-DCMAKE_INSTALL_PREFIX=/usr/local"
(and replace /usr/local with the base path you wish to use). Alternately, you
can specify the base path to install to when you run "make install" by passing
'DESTDIR=/usr/local' on the make install command line (again, replace
/usr/local as appropriate).
To build a static library instead of shared (the default), pass
-DBUILD_SHARED_LIBS=OFF to the cmake command when running cmake.
A slightly more extensive demo application is available in the player/
directory. It requires SDL to build.
Read gme.txt for more information. Post to the discussion forum for
assistance.
Files
-----
gme.txt General notes about the library
changes.txt Changes made since previous releases
design.txt Library design notes
license.txt GNU Lesser General Public License
CMakeLists.txt CMake build rules
test.nsf Test file for NSF emulator
test.m3u Test m3u playlist for features.c demo
demo/
basics.c Records NSF file to wave sound file
features.c Demonstrates many additional features
Wave_Writer.h WAVE sound file writer used for demo output
Wave_Writer.cpp
CMakeLists.txt CMake build rules
player/ Player using the SDL multimedia library
player.cpp Simple music player with waveform display
Music_Player.cpp Stand alone player for background music
Music_Player.h
Audio_Scope.cpp Audio waveform scope
Audio_Scope.h
CMakeLists.txt CMake build rules
gme/
blargg_config.h Library configuration (modify this file as needed)
gme.h Library interface header file
gme.cpp
Ay_Emu.h ZX Spectrum AY emulator
Ay_Emu.cpp
Ay_Apu.cpp
Ay_Apu.h
Ay_Cpu.cpp
Ay_Cpu.h
Gbs_Emu.h Nintendo Game Boy GBS emulator
Gbs_Emu.cpp
Gb_Apu.cpp
Gb_Apu.h
Gb_Cpu.cpp
Gb_Cpu.h
gb_cpu_io.h
Gb_Oscs.cpp
Gb_Oscs.h
Hes_Emu.h TurboGrafx-16/PC Engine HES emulator
Hes_Apu.cpp
Hes_Apu.h
Hes_Cpu.cpp
Hes_Cpu.h
hes_cpu_io.h
Hes_Emu.cpp
Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator
Kss_Emu.cpp
Kss_Cpu.cpp
Kss_Cpu.h
Kss_Scc_Apu.cpp
Kss_Scc_Apu.h
Ay_Apu.h
Ay_Apu.cpp
Sms_Apu.h
Sms_Apu.cpp
Sms_Oscs.h
Nsf_Emu.h Nintendo NES NSF/NSFE emulator
Nsf_Emu.cpp
Nes_Apu.cpp
Nes_Apu.h
Nes_Cpu.cpp
Nes_Cpu.h
nes_cpu_io.h
Nes_Oscs.cpp
Nes_Oscs.h
Nes_Fme7_Apu.cpp
Nes_Fme7_Apu.h
Nes_Namco_Apu.cpp
Nes_Namco_Apu.h
Nes_Vrc6_Apu.cpp
Nes_Vrc6_Apu.h
Nsfe_Emu.h NSFE support
Nsfe_Emu.cpp
Spc_Emu.h Super Nintendo SPC emulator
Spc_Emu.cpp
Snes_Spc.cpp
Snes_Spc.h
Spc_Cpu.cpp
Spc_Cpu.h
Spc_Dsp.cpp
Spc_Dsp.h
Fir_Resampler.cpp
Fir_Resampler.h
Sap_Emu.h Atari SAP emulator
Sap_Emu.cpp
Sap_Apu.cpp
Sap_Apu.h
Sap_Cpu.cpp
Sap_Cpu.h
sap_cpu_io.h
Vgm_Emu.h Sega VGM emulator
Vgm_Emu_Impl.cpp
Vgm_Emu_Impl.h
Vgm_Emu.cpp
Ym2413_Emu.cpp
Ym2413_Emu.h
Gym_Emu.h Sega Genesis GYM emulator
Gym_Emu.cpp
Sms_Apu.cpp Common Sega emulator files
Sms_Apu.h
Sms_Oscs.h
Ym2612_Emu.cpp
Ym2612_Emu.h
Dual_Resampler.cpp
Dual_Resampler.h
Fir_Resampler.cpp
Fir_Resampler.h
M3u_Playlist.h M3U playlist support
M3u_Playlist.cpp
Effects_Buffer.h Sound buffer with stereo echo and panning
Effects_Buffer.cpp
blargg_common.h Common files needed by all emulators
blargg_endian.h
blargg_source.h
Blip_Buffer.cpp
Blip_Buffer.h
Gme_File.h
Gme_File.cpp
Music_Emu.h
Music_Emu.cpp
Classic_Emu.h
Classic_Emu.cpp
Multi_Buffer.h
Multi_Buffer.cpp
Data_Reader.h
Data_Reader.cpp
CMakeLists.txt CMake build rules
Legal
-----
Game_Music_Emu library copyright (C) 2003-2009 Shay Green.
Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville.
--
Shay Green <gblargg@gmail.com>
Game_Music_Emu 0.6.2: Game Music Emulators
------------------------------------------
Game_Music_Emu is a collection of video game music file emulators that
support the following formats and systems:
AY ZX Spectrum/Amstrad CPC
GBS Nintendo Game Boy
GYM Sega Genesis/Mega Drive
HES NEC TurboGrafx-16/PC Engine
KSS MSX Home Computer/other Z80 systems (doesn't support FM sound)
NSF/NSFE Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)
SAP Atari systems using POKEY sound chip
SPC Super Nintendo/Super Famicom
VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
Features:
* C interface for use in C, C++, and other compatible languages
* High emphasis has been placed on making the library very easy to use
* One set of common functions work with all emulators the same way
* Several code examples, including music player using SDL
* Portable code for use on any system with modern or older C++ compilers
* Adjustable output sample rate using quality band-limited resampling
* Uniform access to text information fields and track timing information
* End-of-track fading and automatic look ahead silence detection
* Treble/bass and stereo echo for AY/GBS/HES/KSS/NSF/NSFE/SAP/VGM
* Tempo can be adjusted and individual voices can be muted while playing
* Can read music data from file, memory, or custom reader function/class
* Can access track information without having to load into full emulator
* M3U track listing support for multi-track formats
* Modular design allows elimination of unneeded emulators/features
This library has been used in game music players for Windows, Linux on
several architectures, Mac OS, MorphOS, Xbox, PlayStation Portable,
GP2X, and Nintendo DS.
Author : Shay Green <gblargg@gmail.com>
Website: https://bitbucket.org/mpyne/game-music-emu/wiki/Home
License: GNU Lesser General Public License (LGPL)
Current Maintainer: Michael Pyne <mpyne@purinchu.net>
Getting Started
---------------
Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
all source files in gme/.
Or, if you have CMake 2.6 or later, execute at a command prompt (from the
extracted source directory):
mkdir build
cd build
cmake ../ # <-- Pass any needed CMake flags here
make # To build the library
cd demo
make # To build the demo itself
Be sure "test.nsf" is in the same directory as the demo program. Running it
should generate the recording "out.wav".
You can use "make install" to install the library. To choose where to install
the library to, use the CMake argument "-DCMAKE_INSTALL_PREFIX=/usr/local"
(and replace /usr/local with the base path you wish to use). Alternately, you
can specify the base path to install to when you run "make install" by passing
'DESTDIR=/usr/local' on the make install command line (again, replace
/usr/local as appropriate).
To build a static library instead of shared (the default), pass
-DBUILD_SHARED_LIBS=OFF to the cmake command when running cmake.
A slightly more extensive demo application is available in the player/
directory. It requires SDL to build.
Read gme.txt for more information. Post to the discussion forum for
assistance.
Files
-----
gme.txt General notes about the library
changes.txt Changes made since previous releases
design.txt Library design notes
license.txt GNU Lesser General Public License
CMakeLists.txt CMake build rules
test.nsf Test file for NSF emulator
test.m3u Test m3u playlist for features.c demo
demo/
basics.c Records NSF file to wave sound file
features.c Demonstrates many additional features
Wave_Writer.h WAVE sound file writer used for demo output
Wave_Writer.cpp
CMakeLists.txt CMake build rules
player/ Player using the SDL multimedia library
player.cpp Simple music player with waveform display
Music_Player.cpp Stand alone player for background music
Music_Player.h
Audio_Scope.cpp Audio waveform scope
Audio_Scope.h
CMakeLists.txt CMake build rules
gme/
blargg_config.h Library configuration (modify this file as needed)
gme.h Library interface header file
gme.cpp
Ay_Emu.h ZX Spectrum AY emulator
Ay_Emu.cpp
Ay_Apu.cpp
Ay_Apu.h
Ay_Cpu.cpp
Ay_Cpu.h
Gbs_Emu.h Nintendo Game Boy GBS emulator
Gbs_Emu.cpp
Gb_Apu.cpp
Gb_Apu.h
Gb_Cpu.cpp
Gb_Cpu.h
gb_cpu_io.h
Gb_Oscs.cpp
Gb_Oscs.h
Hes_Emu.h TurboGrafx-16/PC Engine HES emulator
Hes_Apu.cpp
Hes_Apu.h
Hes_Cpu.cpp
Hes_Cpu.h
hes_cpu_io.h
Hes_Emu.cpp
Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator
Kss_Emu.cpp
Kss_Cpu.cpp
Kss_Cpu.h
Kss_Scc_Apu.cpp
Kss_Scc_Apu.h
Ay_Apu.h
Ay_Apu.cpp
Sms_Apu.h
Sms_Apu.cpp
Sms_Oscs.h
Nsf_Emu.h Nintendo NES NSF/NSFE emulator
Nsf_Emu.cpp
Nes_Apu.cpp
Nes_Apu.h
Nes_Cpu.cpp
Nes_Cpu.h
nes_cpu_io.h
Nes_Oscs.cpp
Nes_Oscs.h
Nes_Fme7_Apu.cpp
Nes_Fme7_Apu.h
Nes_Namco_Apu.cpp
Nes_Namco_Apu.h
Nes_Vrc6_Apu.cpp
Nes_Vrc6_Apu.h
Nsfe_Emu.h NSFE support
Nsfe_Emu.cpp
Spc_Emu.h Super Nintendo SPC emulator
Spc_Emu.cpp
Snes_Spc.cpp
Snes_Spc.h
Spc_Cpu.cpp
Spc_Cpu.h
Spc_Dsp.cpp
Spc_Dsp.h
Fir_Resampler.cpp
Fir_Resampler.h
Sap_Emu.h Atari SAP emulator
Sap_Emu.cpp
Sap_Apu.cpp
Sap_Apu.h
Sap_Cpu.cpp
Sap_Cpu.h
sap_cpu_io.h
Vgm_Emu.h Sega VGM emulator
Vgm_Emu_Impl.cpp
Vgm_Emu_Impl.h
Vgm_Emu.cpp
Ym2413_Emu.cpp
Ym2413_Emu.h
Gym_Emu.h Sega Genesis GYM emulator
Gym_Emu.cpp
Sms_Apu.cpp Common Sega emulator files
Sms_Apu.h
Sms_Oscs.h
Ym2612_Emu.cpp
Ym2612_Emu.h
Dual_Resampler.cpp
Dual_Resampler.h
Fir_Resampler.cpp
Fir_Resampler.h
M3u_Playlist.h M3U playlist support
M3u_Playlist.cpp
Effects_Buffer.h Sound buffer with stereo echo and panning
Effects_Buffer.cpp
blargg_common.h Common files needed by all emulators
blargg_endian.h
blargg_source.h
Blip_Buffer.cpp
Blip_Buffer.h
Gme_File.h
Gme_File.cpp
Music_Emu.h
Music_Emu.cpp
Classic_Emu.h
Classic_Emu.cpp
Multi_Buffer.h
Multi_Buffer.cpp
Data_Reader.h
Data_Reader.cpp
CMakeLists.txt CMake build rules
Legal
-----
Game_Music_Emu library copyright (C) 2003-2009 Shay Green.
Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville.
--
Shay Green <gblargg@gmail.com>
+8 -9
View File
@@ -1,5 +1,5 @@
/* backtrace.h -- Public header file for stack backtrace library.
Copyright (C) 2012-2021 Free Software Foundation, Inc.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -54,14 +54,13 @@ struct backtrace_state;
invalid after this function returns.
As a special case, the ERRNUM argument will be passed as -1 if no
debug info can be found for the executable, or if the debug info
exists but has an unsupported version, but the function requires
debug info (e.g., backtrace_full, backtrace_pcinfo). The MSG in
this case will be something along the lines of "no debug info".
Similarly, ERRNUM will be passed as -1 if there is no symbol table,
but the function requires a symbol table (e.g., backtrace_syminfo).
This may be used as a signal that some other approach should be
tried. */
debug info can be found for the executable, but the function
requires debug info (e.g., backtrace_full, backtrace_pcinfo). The
MSG in this case will be something along the lines of "no debug
info". Similarly, ERRNUM will be passed as -1 if there is no
symbol table, but the function requires a symbol table (e.g.,
backtrace_syminfo). This may be used as a signal that some other
approach should be tried. */
typedef void (*backtrace_error_callback) (void *data, const char *msg,
int errnum);
Binary file not shown.
+1 -2
View File
@@ -1,3 +1,2 @@
/cscope.out
*.json
*.idx
/srb2wii
+2 -6
View File
@@ -129,7 +129,6 @@ set(SRB2_CORE_RENDER_SOURCES
r_fps.c
r_main.c
r_patch.c
r_patchrotation.c
r_plane.c
r_segs.c
r_sky.c
@@ -144,8 +143,7 @@ set(SRB2_CORE_RENDER_SOURCES
r_fps.h
r_local.h
r_main.h
r_patch.h
r_patchrotation.h
r_patch
r_plane.h
r_segs.h
r_sky.h
@@ -175,7 +173,6 @@ set(SRB2_CORE_GAME_SOURCES
p_user.c
k_director.c
k_kart.c
k_stats.c
i_time.c
p_local.h
@@ -190,7 +187,6 @@ set(SRB2_CORE_GAME_SOURCES
p_tick.h
k_director.h
k_kart.h
k_stats.h
)
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
@@ -491,7 +487,7 @@ if(${SRB2_CONFIG_HWRENDER})
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_gl.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_drv.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_glob.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_portal.h
+129 -40
View File
@@ -31,6 +31,18 @@
# compile all HW render and 3D sound DLLs for the set
# opengl_dll
# Pure Mingw only, compile OpenGL HW render DLL
# minigl_dll
# Pure Mingw only, compile MiniGL HW render DLL
# ds3d_dll
# Pure Mingw only, compile DirectX DirectSound HW sound DLL
# fmod_dll
# Pure Mingw only, compile FMOD HW sound DLL
# openal_dll
# Pure Mingw only, compile OpenAL HW sound DLL
# fmod_so
# Non-Mingw, compile FMOD HW sound SO
# openal_so
# Non-Mingw, compile OpenAL HW sound SO
#
#
# Addon:
@@ -57,7 +69,10 @@
# Compile without SDL_Mixer, add 'NOMIXER=1'
# Compile without BSD API, add 'NONET=1'
# Compile without IPX/SPX, add 'NOIPX=1'
# Compile Mingw/SDL with S_DS3S, add 'DS3D=1'
# Compile without libopenmpt, add 'NOOPENMPT=1'
# Compile with S_FMOD3D, add 'FMOD=1' (WIP)
# Compile with S_OPENAL, add 'OPENAL=1' (WIP)
# To link with the whole SDL_Image lib to load Icons, add 'SDL_IMAGE=1' but it isn't not realy needed
# To link with SDLMain to hide console or make on a console-less binary, add 'SDLMAIN=1'
#
@@ -68,6 +83,7 @@ ALL_SYSTEMS=\
LINUX64\
MINGW64\
HAIKU\
DUMMY\
MINGW\
UNIX\
LINUX\
@@ -80,19 +96,18 @@ ALL_SYSTEMS=\
ifeq (,$(filter $(ALL_SYSTEMS),$(.VARIABLES)))
ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
ifeq ($(shell uname -s | grep -o MINGW64),MINGW64) # 64-bit MinGW
$(info Detected a Windows system, compiling for 64-bit MinGW SDL2...)
MINGW64=1
else # 32-bit MinGW
$(info Detected a Windows system, compiling for 32-bit MinGW SDL2...)
MINGW=1
endif
$(info Detected a Windows system, compiling for 32-bit MinGW SDL2...)
# go for a 32-bit sdl mingw exe by default
MINGW=1
SDL=1
WINDOWSHELL=1
NOOBJDUMP=1
NOUPX=1
else # if you on the *nix
NOUPX=1
system:=$(shell uname -s)
ifeq ($(system),Linux)
@@ -116,7 +131,6 @@ else # if you on the *nix
endif
endif
NOUPX=1
# SRB2 data files
D_DIR?=../bin/Resources
@@ -157,6 +171,17 @@ endif
include Makefile.cfg
ifdef DUMMY
NOPNG=1
NOZLIB=1
NONET=1
NOHW=1
NOIPX=1
EXENAME?=srb2dummy
OBJS=$(OBJDIR)/i_video.o
LIBS=-lm
endif
ifdef HAIKU
NOIPX=1
ifndef NONET
@@ -183,6 +208,8 @@ endif
endif
ifndef NONET
ifndef NOSATURNSYNCH
DOSATURNSYNCH=1
ifndef NOSATURNJOIN
DOSATURNJOIN=1
endif
@@ -190,6 +217,7 @@ ifndef NOSATURNPAK
DOSATURNPAK=1
endif
endif
endif
ifdef MINGW
include win32/Makefile.cfg
@@ -201,7 +229,6 @@ endif
ifdef LINUX
UNIXCOMMON=1
NOOBJDUMP=1
ifndef NOGME
HAVE_LIBGME=1
endif
@@ -274,7 +301,7 @@ else
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o $(OBJDIR)/hw_shaders.o
endif
OPTS += -DCOMPVERSION
OPTS += -DCOMPVERSION -fwrapv
ifndef NONX86
ifndef GCC29
@@ -284,10 +311,11 @@ else
endif
else
ifdef X86_64
ARCHOPTS?=-march=native
ARCHOPTS?=-march=nocona
endif
endif
ifndef NOPNG
OPTS+=-DHAVE_PNG
@@ -375,6 +403,8 @@ endif
endif
ifndef NONET
ifndef NOSATURNSYNCH
OPTS+=-DDOSATURNSYNCH
ifndef NOSATURNJOIN
OPTS+=-DDOSATURNJOIN
endif
@@ -382,6 +412,7 @@ ifndef NOSATURNPAK
OPTS+=-DDOSATURNPAK
endif
endif
endif
ifdef HAVE_MINIUPNPC
ifdef NONET
@@ -441,24 +472,7 @@ else
# build a normal optimised version
WINDRESFLAGS = -DNDEBUG
CFLAGS+=-O3
CPPFLAGS+=-O3
endif
ifndef DEBUGMODE
ifdef USELTO
# compile with LTO
CFLAGS+=-flto=auto
CPPFLAGS+=-flto=auto
endif
endif
ifdef USEASAN
# compile with asan
CFLAGS+=-fsanitize=address
CPPFLAGS+=-fsanitize=address
LDFLAGS+=-fsanitize=address
endif
CFLAGS+=-g $(OPTS) $(ARCHOPTS) $(WINDRESFLAGS)
ifdef PROFILEMODE
@@ -513,7 +527,6 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/st_stuff.o \
$(OBJDIR)/k_director.o \
$(OBJDIR)/k_kart.o \
$(OBJDIR)/k_stats.o \
$(OBJDIR)/m_aatree.o \
$(OBJDIR)/m_anigif.o \
$(OBJDIR)/m_argv.o \
@@ -556,7 +569,6 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_sky.o \
$(OBJDIR)/r_splats.o \
$(OBJDIR)/r_patch.o \
$(OBJDIR)/r_patchrotation.o \
$(OBJDIR)/r_things.o \
$(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \
@@ -600,6 +612,10 @@ ifdef SDL
all: pre-build $(BIN)/$(EXENAME)
endif
ifdef DUMMY
all: $(BIN)/$(EXENAME)
endif
cleandep:
$(REMOVE) $(OBJDIR)/depend.dep
$(REMOVE) comptime.h
@@ -636,7 +652,7 @@ endif
$(BIN)/$(EXENAME): $(POS) $(OBJS)
-$(MKDIR) $(BIN)
@echo Linking $(EXENAME)...
$(LD) $(LDFLAGS) $(OBJS) -o $(BIN)/$(EXENAME) $(LIBS) -lstdc++
$(LD) $(LDFLAGS) $(OBJS) -o $(BIN)/$(EXENAME) $(LIBS)
ifndef VALGRIND
ifndef NOOBJDUMP
@echo Dumping debugging info
@@ -688,7 +704,7 @@ else
dll : opengl_dll
endif
ifdef MINGW
all_dll: opengl_dll
all_dll: opengl_dll ds3d_dll fmod_dll openal_dll
opengl_dll: $(BIN)/r_opengl.dll
$(BIN)/r_opengl.dll: $(OBJDIR)/ogl_win.o $(OBJDIR)/r_opengl.o
@@ -698,13 +714,44 @@ $(BIN)/r_opengl.dll: $(OBJDIR)/ogl_win.o $(OBJDIR)/r_opengl.o
ifndef NOUPX
-$(UPX) $(UPX_OPTS) $@
endif
ds3d_dll: $(BIN)/s_ds3d.dll
$(BIN)/s_ds3d.dll: $(OBJDIR)/s_ds3d.o
@echo Linking S_DS3d.dll...
$(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -ldsound -luuid
fmod_dll: $(BIN)/s_fmod.dll
$(BIN)/s_fmod.dll: $(OBJDIR)/s_fmod.o
-$(MKDIR) $(BIN)
@echo Linking S_FMOD.dll...
$(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lfmod
openal_dll: $(BIN)/s_openal.dll
$(BIN)/s_openal.dll: $(OBJDIR)/s_openal.o
-$(MKDIR) $(BIN)
@echo Linking S_OpenAL.dll...
$(CC) --shared $^ -o $@ -g -Wl,--add-stdcall-alias -lopenal32
else
all_dll: fmod_so openal_so
fmod_so: $(BIN)/s_fmod.so
$(BIN)/s_fmod.so: $(OBJDIR)/s_fmod.o
-$(MKDIR) $(BIN)
@echo Linking S_FMOD.so...
$(CC) --shared $^ -o $@ -g --nostartfiles -lm -lfmod
openal_so: $(BIN)/s_openal.so
$(BIN)/s_openal.so: $(OBJDIR)/s_openal.o
-$(MKDIR) $(BIN)
@echo Linking S_OpenAL.so...
$(CC) --shared $^ -o $@ -g --nostartfiles -lm -lopenal
endif
else
ifdef SDL
ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_gl.h screen.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_defs.h hardware/hw_md2.h \
hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h hardware/hw_portal.h\
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
@@ -713,7 +760,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_gl.h screen.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_defs.h hardware/hw_md2.h \
hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h hardware/hw_portal.h \
hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \
@@ -727,14 +774,15 @@ endif
#dependecy made by gcc itself !
$(OBJS):
ifndef DUMMY
-include $(OBJDIR)/depend.dep
endif
$(OBJDIR)/depend.dep:
@echo "Creating dependency file, depend.dep"
@echo > comptime.h
-$(MKDIR) $(OBJDIR)
$(CC) $(CFLAGS) -MM *.c > $(OBJDIR)/depend.ped
$(CXX) $(CXXFLAGS) -MM *.cpp >> $(OBJDIR)/depend.ped
$(CC) $(CFLAGS) -MM $(INTERFACE)/*.c >> $(OBJDIR)/depend.ped
ifndef NOHW
$(CC) $(CFLAGS) -MM hardware/*.c >> $(OBJDIR)/depend.ped
@@ -793,10 +841,6 @@ else
include bluajit/Makefile.cfg2
endif
# C++
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/%.o: %.s
$(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@
@@ -804,10 +848,55 @@ $(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h
$(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff
ifdef SDL
ifdef MINGW
$(OBJDIR)/win_dbg.o: win32/win_dbg.c
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
endif
ifdef STATICHS
$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
ifdef MINGW
$(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
endif
else
$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_fmod/s_fmod.c
$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_openal/s_openal.c
endif
ifdef FILTERS
$(OBJDIR)/%.o: $(INTERFACE)/filter/%.c
@echo $< needs deps
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/filters.o: $(INTERFACE)/filter/filters.c $(INTERFACE)/filter/filters.c \
$(INTERFACE)/filter/filters.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/hq2x.o: $(INTERFACE)/filter/hq2x.c $(INTERFACE)/filter/hq2x.c \
$(INTERFACE)/filter/filters.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
$(OBJDIR)/lq2x.o: $(INTERFACE)/filter/lq2x.c $(INTERFACE)/filter/lq2x.c \
$(INTERFACE)/filter/filters.h $(INTERFACE)/filter/interp.h \
$(INTERFACE)/filter/hq2x.h $(INTERFACE)/filter/lq2x.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
endif
endif
#############################################################
+11 -13
View File
@@ -12,7 +12,6 @@
# to avoid a false positive with the version detection...
SUPPORTED_GCC_VERSIONS:=\
151 150 15\
142 141 140 14\
132 131 130 13\
123 122 121 120 12\
@@ -79,18 +78,6 @@ ifeq (,$(filter GCC%,$(.VARIABLES)))
endif
endif
ifdef GCC151
GCC150=1
endif
ifdef GCC15
GCC150=1
endif
ifdef GCC150
GCC142=1
endif
ifdef GCC142
GCC141=1
endif
@@ -482,6 +469,7 @@ ifdef GCC81
WFLAGS+=-Wno-error=multistatement-macros
endif
#indicate platform and what interface use with
ifndef LINUX
ifndef FREEBSD
@@ -489,6 +477,7 @@ ifndef CYGWIN32
ifndef MINGW
ifndef MINGW64
ifndef SDL
ifndef DUMMY
$(error No interface or platform flag defined)
endif
endif
@@ -496,6 +485,7 @@ endif
endif
endif
endif
endif
#determine the interface directory (where you put all i_*.c)
i_net_o=$(OBJDIR)/i_net.o
@@ -520,6 +510,11 @@ UPX_OPTS+=-q
endif
#Interface Setup
ifdef DUMMY
INTERFACE=dummy
OBJDIR:=$(OBJDIR)/dummy
BIN:=$(BIN)/dummy
else
ifdef LINUX
SDL=1
ifdef LINUX64
@@ -566,6 +561,7 @@ endif
endif
endif
endif
endif
ifdef ARCHNAME
OBJDIR:=$(OBJDIR)/$(ARCHNAME)
@@ -580,6 +576,7 @@ ifdef SDL
OBJDIR:=$(OBJDIR)/SDL
endif
ifndef DUMMY
ifdef DEBUGMODE
OBJDIR:=$(OBJDIR)/Debug
BIN:=$(BIN)/Debug
@@ -587,3 +584,4 @@ else
OBJDIR:=$(OBJDIR)/Release
BIN:=$(BIN)/Release
endif
endif
+121 -462
View File
@@ -1,10 +1,8 @@
// SONIC ROBO BLAST 2 KART
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 2024 by Vivian "toastergrl" Grannell.
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2000 by DooM Legacy Team.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2018 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
@@ -35,31 +33,36 @@ static const UINT8 GRAYSRANGE = 16;
static const UINT8 BROWNS = (3*16);
static const UINT8 YELLOWS = (7*16);
static const UINT8 GREENS = (10*16);
//static const UINT8 CYANS = (13*16);
static const UINT8 BLUES = (14*16);
static const UINT8 DBLACK = 31;
static const UINT8 DWHITE = 0;
static const UINT8 NOCLIMBREDS = 248;
static const UINT8 NOCLIMBREDRANGE = 8;
static const UINT8 NOCLIMBGRAYS = 204;
static const UINT8 NOCLIMBBROWNS = (2*16);
static const UINT8 NOCLIMBYELLOWS = (11*16);
// Automap colors
#define BACKGROUND DBLACK
#define WALLCOLORS (REDS + REDRANGE/2)
#define WALLRANGE (REDRANGE/2)
#define NOCLIMBWALLCOLORS (NOCLIMBREDS + NOCLIMBREDRANGE/2)
#define NOCLIMBWALLRANGE (NOCLIMBREDRANGE/2)
#define THOKWALLCOLORS REDS
#define THOKWALLRANGE REDRANGE
#define TSWALLCOLORS DWHITE
#define TSFINISHLINE (GREENS + 2)
#define TSFOFINFO (BLUES + 4)
#define NOCLIMBTHOKWALLCOLORS NOCLIMBREDS
#define NOCLIMBTHOKWALLRANGE NOCLIMBREDRANGE
#define TSWALLCOLORS GRAYS
#define TSWALLRANGE GRAYSRANGE
#define NOCLIMBTSWALLCOLORS NOCLIMBGRAYS
#define FDWALLCOLORS BROWNS
#define NOCLIMBFDWALLCOLORS NOCLIMBBROWNS
#define CDWALLCOLORS YELLOWS
#define NOCLIMBCDWALLCOLORS NOCLIMBYELLOWS
#define THINGCOLORS GREENS
#define GRIDCOLORS (GRAYS + GRAYSRANGE/2)
#define XHAIRCOLORS GRAYS
// Automap passes
#define PASS_SOLID 1
#define PASS_INTANGIBLE 2
#define PASS_FOF 4
// controls
#define AM_PANUPKEY KEY_UPARROW
#define AM_PANDOWNKEY KEY_DOWNARROW
@@ -107,6 +110,11 @@ typedef struct
mpoint_t a, b;
} mline_t;
typedef struct
{
fixed_t slp, islp;
} islope_t;
//
// The vector graphics for the automap.
// A line drawing of the player pointing right,
@@ -128,14 +136,16 @@ static const mline_t player_arrow[] = {
#undef R
#define NUMPLYRLINES (sizeof (player_arrow)/sizeof (mline_t))
#if 0
#define R (FRACUNIT)
static const mline_t cross_mark[] =
{
{ { -R, 0 }, { R, 0} },
{ { 0, -R }, { 0, R } },
static mline_t triangle_guy[] = {
{ { (fixed_t)-.867f*R, (fixed_t)-.5f*R }, { (fixed_t) .867f*R, (fixed_t)-.5f*R } },
{ { (fixed_t) .867f*R, (fixed_t)-.5f*R }, { (fixed_t) 0, (fixed_t) R } },
{ { (fixed_t) 0, (fixed_t) R }, { (fixed_t)-.867f*R, (fixed_t)-.5f*R } }
};
#undef R
#define NUMCROSSMARKLINES (sizeof(cross_mark)/sizeof(mline_t))
#define NUMTRIANGLEGUYLINES (sizeof (triangle_guy)/sizeof (mline_t))
#endif
#define R (FRACUNIT)
static const mline_t thintriangle_guy[] = {
@@ -152,14 +162,10 @@ static boolean draw_grid = false;
boolean automapactive = false;
boolean am_recalc = false; //added : 05-02-98 : true when screen size changes
static boolean am_stopped = true;
static boolean am_minigen = false;
static UINT8 *am_buf = NULL;
static INT32 f_x, f_y; // location of window on screen (always zero for both)
static INT32 f_w, f_h; // size of window on screen (always the screen width and height respectively)
static boolean m_keydown[4]; // which window panning keys are being pressed down?
static mpoint_t m_paninc; // how far the window pans each tic (map coords)
static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords)
@@ -199,13 +205,12 @@ static fixed_t scale_ftom;
static player_t *plr; // the player represented by an arrow
static boolean followplayer = true; // specifies whether to follow the player around
static INT32 followplayer = true; // specifies whether to follow the player around
// function for drawing lines, depends on rendermode
typedef void (*AMDRAWFLINEFUNC) (const fline_t *fl, INT32 color);
static AMDRAWFLINEFUNC AM_drawFline;
static void AM_drawPixel(INT32 xx, INT32 yy, INT32 cc);
static void AM_drawFline_soft(const fline_t *fl, INT32 color);
static void AM_activateNewScale(void)
@@ -265,6 +270,9 @@ static void AM_findMinMaxBoundaries(void)
max_w = minimapinfo.map_w << MAPBITS;
max_h = minimapinfo.map_h << MAPBITS;
max_w = (max_x >>= FRACTOMAPBITS) - (min_x >>= FRACTOMAPBITS);
max_h = (max_y >>= FRACTOMAPBITS) - (min_y >>= FRACTOMAPBITS);
a = FixedDiv(f_w<<FRACBITS, max_w);
b = FixedDiv(f_h<<FRACBITS, max_h);
@@ -312,13 +320,12 @@ static void AM_initVariables(void)
m_h = FTOM(f_h);
// find player to center on initially
if (!players[pnum = consoleplayer].ingame)
if (!playeringame[pnum = consoleplayer])
for (pnum = 0; pnum < MAXPLAYERS; pnum++)
if (players[pnum].ingame)
if (playeringame[pnum])
break;
plr = &players[pnum];
if (plr != NULL && plr->mo != NULL)
{
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
@@ -333,23 +340,22 @@ static void AM_initVariables(void)
old_m_h = m_h;
}
//
// Called when the screen size changes.
//
static void AM_FrameBufferInit(void)
{
f_x = f_y = 0;
f_w = vid.width;
f_h = vid.height;
am_buf = screens[0];
}
//
// should be called at the start of every level
// right now, i figure it out myself
//
static void AM_LevelInit(void)
{
f_x = f_y = 0;
f_w = vid.width;
f_h = vid.height;
AM_drawFline = AM_drawFline_soft;
#ifdef HWRENDER
if (rendermode == render_opengl)
AM_drawFline = HWR_drawAMline;
#endif
AM_findMinMaxBoundaries();
scale_mtof = FixedDiv(min_scale_mtof*10, 7*FRACUNIT);
if (scale_mtof > max_scale_mtof)
@@ -371,7 +377,7 @@ void AM_Stop(void)
*
* \sa AM_Stop
*/
void AM_Start(void)
static inline void AM_Start(void)
{
static INT32 lastlevel = -1;
@@ -380,12 +386,8 @@ void AM_Start(void)
am_stopped = false;
if (lastlevel != gamemap || am_recalc) // screen size changed
{
AM_FrameBufferInit();
if (lastlevel != gamemap)
{
AM_LevelInit();
lastlevel = gamemap;
}
AM_LevelInit();
lastlevel = gamemap;
am_recalc = false;
}
AM_initVariables();
@@ -411,28 +413,6 @@ static void AM_maxOutWindowScale(void)
AM_activateNewScale();
}
//
// set window panning
//
static void AM_setWindowPanning(void)
{
// up and down
if (m_keydown[2]) // pan up
m_paninc.y = FTOM(F_PANINC);
else if (m_keydown[3]) // pan down
m_paninc.y = -FTOM(F_PANINC);
else
m_paninc.y = 0;
// left and right
if (m_keydown[0]) // pan right
m_paninc.x = FTOM(F_PANINC);
else if (m_keydown[1]) // pan left
m_paninc.x = -FTOM(F_PANINC);
else
m_paninc.x = 0;
}
/** Responds to user inputs in automap mode.
*
* \param ev Event to possibly respond to.
@@ -465,49 +445,35 @@ boolean AM_Responder(event_t *ev)
{
case AM_PANRIGHTKEY: // pan right
if (!followplayer)
{
m_keydown[0] = true;
AM_setWindowPanning();
}
m_paninc.x = FTOM(F_PANINC);
else
rc = false;
break;
case AM_PANLEFTKEY: // pan left
if (!followplayer)
{
m_keydown[1] = true;
AM_setWindowPanning();
}
m_paninc.x = -FTOM(F_PANINC);
else
rc = false;
break;
case AM_PANUPKEY: // pan up
if (!followplayer)
{
m_keydown[2] = true;
AM_setWindowPanning();
}
m_paninc.y = FTOM(F_PANINC);
else
rc = false;
break;
case AM_PANDOWNKEY: // pan down
if (!followplayer)
{
m_keydown[3] = true;
AM_setWindowPanning();
}
m_paninc.y = -FTOM(F_PANINC);
else
rc = false;
break;
case AM_ZOOMOUTKEY: // zoom out
mtof_zoommul = M_ZOOMOUT;
ftom_zoommul = M_ZOOMIN;
AM_setWindowPanning();
break;
case AM_ZOOMINKEY: // zoom in
mtof_zoommul = M_ZOOMIN;
ftom_zoommul = M_ZOOMOUT;
AM_setWindowPanning();
break;
case AM_TOGGLEKEY:
AM_Stop();
@@ -521,7 +487,6 @@ boolean AM_Responder(event_t *ev)
}
else
AM_restoreScaleAndLoc();
AM_setWindowPanning();
break;
case AM_FOLLOWKEY:
followplayer = !followplayer;
@@ -541,32 +506,14 @@ boolean AM_Responder(event_t *ev)
switch (ev->data1)
{
case AM_PANRIGHTKEY:
if (!followplayer)
{
m_keydown[0] = false;
AM_setWindowPanning();
}
break;
case AM_PANLEFTKEY:
if (!followplayer)
{
m_keydown[1] = false;
AM_setWindowPanning();
}
m_paninc.x = 0;
break;
case AM_PANUPKEY:
if (!followplayer)
{
m_keydown[2] = false;
AM_setWindowPanning();
}
break;
case AM_PANDOWNKEY:
if (!followplayer)
{
m_keydown[3] = false;
AM_setWindowPanning();
}
m_paninc.y = 0;
break;
case AM_ZOOMOUTKEY:
case AM_ZOOMINKEY:
@@ -767,16 +714,6 @@ static boolean AM_clipMline(const mline_t *ml, fline_t *fl)
}
#undef DOOUTCODE
//
// Draws a pixel.
//
static void AM_drawPixel(INT32 xx, INT32 yy, INT32 cc)
{
if (xx < 0 || yy < 0 || xx >= f_w || yy >= f_h)
return; // off the screen
am_buf[(yy*f_w) + xx] = cc;
}
//
// Classic Bresenham w/ whatever optimizations needed for speed
//
@@ -798,6 +735,8 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
}
#endif
#define PUTDOT(xx,yy,cc) V_DrawFill(xx,yy,1,1,cc|V_NOSCALESTART);
dx = fl->b.x - fl->a.x;
ax = 2 * (dx < 0 ? -dx : dx);
sx = dx < 0 ? -1 : 1;
@@ -814,7 +753,7 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
d = ay - ax/2;
for (;;)
{
AM_drawPixel(x, y, color);
PUTDOT(x, y, color)
if (x == fl->b.x)
return;
if (d >= 0)
@@ -831,7 +770,7 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
d = ax - ay/2;
for (;;)
{
AM_drawPixel(x, y, color);
PUTDOT(x, y, color)
if (y == fl->b.y)
return;
if (d >= 0)
@@ -843,6 +782,8 @@ static void AM_drawFline_soft(const fline_t *fl, INT32 color)
d += ax;
}
}
#undef PUTDOT
}
//
@@ -864,18 +805,17 @@ static void AM_drawGrid(INT32 color)
fixed_t x, y;
fixed_t start, end;
mline_t ml;
fixed_t gridsize = (MAPBLOCKUNITS<<MAPBITS);
// Figure out start of vertical gridlines
start = m_x;
if ((start - (bmaporgx>>FRACTOMAPBITS)) % gridsize)
start += gridsize - ((start - (bmaporgx>>FRACTOMAPBITS)) % gridsize);
if ((start - bmaporgx) % (MAPBLOCKUNITS<<FRACBITS))
start += (MAPBLOCKUNITS<<FRACBITS) - ((start - bmaporgx) % (MAPBLOCKUNITS<<FRACBITS));
end = m_x + m_w;
// draw vertical gridlines
ml.a.y = m_y;
ml.b.y = m_y + m_h;
for (x = start; x < end; x += gridsize)
for (x = start; x < end; x += (MAPBLOCKUNITS<<FRACBITS))
{
ml.a.x = x;
ml.b.x = x;
@@ -884,14 +824,14 @@ static void AM_drawGrid(INT32 color)
// Figure out start of horizontal gridlines
start = m_y;
if ((start - (bmaporgy>>FRACTOMAPBITS)) % gridsize)
start += gridsize - ((start - (bmaporgy>>FRACTOMAPBITS)) % gridsize);
if ((start - bmaporgy) % (MAPBLOCKUNITS<<FRACBITS))
start += (MAPBLOCKUNITS<<FRACBITS) - ((start - bmaporgy) % (MAPBLOCKUNITS<<FRACBITS));
end = m_y + m_h;
// draw horizontal gridlines
ml.a.x = m_x;
ml.b.x = m_x + m_w;
for (y = start; y < end; y += gridsize)
for (y = start; y < end; y += (MAPBLOCKUNITS<<FRACBITS))
{
ml.a.y = y;
ml.b.y = y;
@@ -899,118 +839,14 @@ static void AM_drawGrid(INT32 color)
}
}
static INT32 GetDamage(INT32 special)
{
switch (special)
{
case 1: // Damage (Generic)
return 1;
case 6: // Death Pit (Camera Tilt)
return 6;
case 7: // Death Pit (No Camera Tilt)
return 7;
case 8: // Instant Kill
return 8;
default:
return 0;
}
}
static INT32 GetOffroad(INT32 special)
{
switch (special)
{
case 2: // Offroad (Weak)
return 2;
case 3: // Offroad
return 3;
case 4: // Offroad (Strong)
return 4;
default:
return 0;
}
}
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
end1 = (P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y, ((normalheight + FRACUNIT/2) >> FRACBITS)) + FRACUNIT/2) >> FRACBITS; \
end2 = (P_GetZAt(slope, lines[i].v2->x, lines[i].v2->y, ((normalheight + FRACUNIT/2) >> FRACBITS)) + FRACUNIT/2) >> FRACBITS;
static ffloor_t *AM_CompareFOFs(size_t i, ffloor_t *rover, ffloor_t *secondarystore)
{
ffloor_t *secondaryrover = NULL;
for (; rover; rover = rover->next)
{
fixed_t rovt1, rovt2;
fixed_t rovb1, rovb2;
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_BLOCKPLAYER))
continue;
SLOPEPARAMS(*rover->t_slope, rovt1, rovt2, *rover->topheight)
SLOPEPARAMS(*rover->b_slope, rovb1, rovb2, *rover->bottomheight)
for (secondaryrover = secondarystore; secondaryrover; secondaryrover = secondaryrover->next)
{
fixed_t sect1, sect2;
fixed_t secb1, secb2;
if (!(secondaryrover->flags & FF_EXISTS))
continue;
if (!(secondaryrover->flags & FF_BLOCKPLAYER))
continue;
if (secondaryrover->secnum == rover->secnum)
break;
SLOPEPARAMS(*secondaryrover->t_slope, sect1, sect2, *secondaryrover->topheight)
SLOPEPARAMS(*secondaryrover->b_slope, secb1, secb2, *secondaryrover->bottomheight)
if (rovt1 != sect1)
continue;
if (rovt2 != sect2)
continue;
if (rovb1 != secb1)
continue;
if (rovb2 != secb2)
continue;
// this is fucking horrible
INT32 damage1, damage2;
INT32 offroad1, offroad2;
INT32 special1, special2;
special1 = GETSECSPECIAL(sectors[rover->secnum].special, 1);
special2 = GETSECSPECIAL(sectors[secondaryrover->secnum].special, 1);
damage1 = GetDamage(special1);
damage2 = GetDamage(special2);
offroad1 = GetOffroad(special1);
offroad2 = GetOffroad(special2);
if (damage1 != damage2
//|| sectors[rover->secnum].friction != sectors[secondaryrover->secnum].friction
|| offroad1 != offroad2)
continue;
break;
}
if (secondaryrover == NULL)
break;
}
return rover;
}
//
// Determines visible lines, draws them.
// This is LineDef based, not LineSeg based.
//
static void AM_drawWalls(UINT8 pass)
static inline void AM_drawWalls(void)
{
size_t i;
static mline_t l;
const fixed_t maxstep = FixedMul(MAXSTEPMOVE, mapobjectscale)>>FRACBITS;
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1 = 0, backf2 = 0, backc1 = 0, backc2 = 0; // back floor ceiling ends
@@ -1020,142 +856,74 @@ static void AM_drawWalls(UINT8 pass)
l.a.y = lines[i].v1->y >> FRACTOMAPBITS;
l.b.x = lines[i].v2->x >> FRACTOMAPBITS;
l.b.y = lines[i].v2->y >> FRACTOMAPBITS;
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y); \
end2 = P_GetZAt(slope, lines[i].v2->x, lines[i].v2->y); \
} else \
end1 = end2 = normalheight;
SLOPEPARAMS(lines[i].frontsector->f_slope, frontf1, frontf2, lines[i].frontsector->floorheight)
SLOPEPARAMS(lines[i].frontsector->c_slope, frontc1, frontc2, lines[i].frontsector->ceilingheight)
if (lines[i].backsector) {
SLOPEPARAMS(lines[i].backsector->f_slope, backf1, backf2, lines[i].backsector->floorheight)
SLOPEPARAMS(lines[i].backsector->c_slope, backc1, backc2, lines[i].backsector->ceilingheight)
}
#undef SLOPEPARAMS
if (!lines[i].backsector) // 1-sided
{
if (!(pass & PASS_SOLID))
;
else if (frontf1 != frontc1 || frontf2 != frontc2 || lines[i].frontsector->f_slope)
{
AM_drawMline(&l, TSWALLCOLORS);
}
else if (!am_minigen)
{
if (lines[i].flags & ML_NOCLIMB)
AM_drawMline(&l, NOCLIMBWALLCOLORS);
else
AM_drawMline(&l, WALLCOLORS);
}
continue;
}
SLOPEPARAMS(lines[i].backsector->f_slope, backf1, backf2, lines[i].backsector->floorheight)
SLOPEPARAMS(lines[i].backsector->c_slope, backc1, backc2, lines[i].backsector->ceilingheight)
if ((backf1 == backc1 && backf2 == backc2) // Back is thok barrier
else if ((backf1 == backc1 && backf2 == backc2) // Back is thok barrier
|| (frontf1 == frontc1 && frontf2 == frontc2)) // Front is thok barrier
{
if (backf1 == backc1 && backf2 == backc2
&& frontf1 == frontc1 && frontf2 == frontc2) // BOTH are thok barriers
{
if (!am_minigen && (pass & PASS_INTANGIBLE))
{
AM_drawMline(&l, GRIDCOLORS);
}
if (lines[i].flags & ML_NOCLIMB)
AM_drawMline(&l, NOCLIMBTSWALLCOLORS);
else
AM_drawMline(&l, TSWALLCOLORS);
}
else if (pass & PASS_SOLID)
else
{
AM_drawMline(&l, TSWALLCOLORS);
if (lines[i].flags & ML_NOCLIMB)
AM_drawMline(&l, NOCLIMBTHOKWALLCOLORS);
else
AM_drawMline(&l, THOKWALLCOLORS);
}
}
else
{
if (lines[i].flags & ML_IMPASSIBLE) // (ML_IMPASSABLE|ML_BLOCKPLAYERS)
{
if (pass & PASS_SOLID)
AM_drawMline(&l, TSWALLCOLORS); // Completely solid course boundary
}
else if ((lines[i].flags & ML_EFFECT4) // ML_MIDSOLID
&& sides[lines->sidenum[0]].midtexture)
{
if (pass & PASS_SOLID)
AM_drawMline(&l, TSWALLCOLORS); // solid midtexture, likely a course boundary
}
if ((backf1 != frontf1 && abs(backf1 - frontf1) > maxstep)
|| (backf2 != frontf2 && abs(backf2 - frontf2) > maxstep))
{
if (pass & PASS_SOLID)
AM_drawMline(&l, TSWALLCOLORS); // floor-wall, likely a course boundary
}
else if (GETSECSPECIAL(lines[i].frontsector->special, 4) == 10 || GETSECSPECIAL(lines[i].backsector->special, 4) == 10)
{
if (pass & PASS_SOLID)
AM_drawMline(&l, TSFINISHLINE); // finish line
}
else if (backf1 != frontf1 || backf2 != frontf2)
{
if (pass & PASS_INTANGIBLE)
AM_drawMline(&l, FDWALLCOLORS); // floorlevel change
}
else if (backc1 != frontc1 || backc2 != frontc2)
{
if (!(pass & PASS_INTANGIBLE))
;
else if (abs(backc1 - frontc1) < maxstep
|| abs(backc2 - frontc2) < maxstep)
{
AM_drawMline(&l, CDWALLCOLORS); // ceilinglevel change
if (lines[i].flags & ML_NOCLIMB) {
if (backf1 != frontf1 || backf2 != frontf2) {
AM_drawMline(&l, NOCLIMBFDWALLCOLORS); // floor level change
}
else if (backc1 != frontc1 || backc2 != frontc2) {
AM_drawMline(&l, NOCLIMBCDWALLCOLORS); // ceiling level change
}
else
{
AM_drawMline(&l, GRIDCOLORS); // ceiling-wall, not likely to be a course boundary but flagged up just in case
}
AM_drawMline(&l, NOCLIMBTSWALLCOLORS);
}
else
{
ffloor_t *rover = NULL;
if (lines[i].frontsector->ffloors || lines[i].backsector->ffloors)
{
if (lines[i].backsector->ffloors == NULL)
{
// Check frontside for one solid
for (rover = lines[i].frontsector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_BLOCKPLAYER))
continue;
break;
}
}
else if (lines[i].frontsector->ffloors == NULL)
{
// Check backside for one solid
for (rover = lines[i].backsector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_BLOCKPLAYER))
continue;
break;
}
}
else
{
// Check to see if any secnums exist in one but not the other.
rover = AM_CompareFOFs(i, lines[i].frontsector->ffloors, lines[i].backsector->ffloors);
if (rover == NULL)
rover = AM_CompareFOFs(i, lines[i].backsector->ffloors, lines[i].frontsector->ffloors);
}
if (backf1 != frontf1 || backf2 != frontf2) {
AM_drawMline(&l, FDWALLCOLORS); // floor level change
}
if (rover != NULL)
{
if (pass & PASS_FOF)
AM_drawMline(&l, TSFOFINFO); // a FOF is here but we don't know how to distinguish them yet
}
else if (!am_minigen)
{
if (pass & PASS_INTANGIBLE)
AM_drawMline(&l, GRIDCOLORS); // likely low-relevance line
else if (backc1 != frontc1 || backc2 != frontc2) {
AM_drawMline(&l, CDWALLCOLORS); // ceiling level change
}
else
AM_drawMline(&l, TSWALLCOLORS);
}
}
}
}
#undef SLOPEPARAMS
//
// Rotation in 2D.
// Used to rotate player arrow line character.
@@ -1226,11 +994,18 @@ static inline void AM_drawPlayers(void)
player_t *p;
INT32 color = GREENS;
if (!multiplayer)
{
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle, DWHITE, plr->mo->x, plr->mo->y);
return;
}
// multiplayer (how??)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!players[i].ingame || players[i].spectator)
if (!playeringame[i] || players[i].spectator)
continue;
if (!players[i].mo)
continue;
@@ -1238,7 +1013,7 @@ static inline void AM_drawPlayers(void)
if (p->skincolor > 0)
color = R_GetTranslationColormap(TC_DEFAULT, p->skincolor, GTC_CACHE)[GREENS + 8];
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 16<<FRACBITS, p->mo->angle, color, p->mo->x, p->mo->y);
AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle, color, p->mo->x, p->mo->y);
}
}
@@ -1252,65 +1027,19 @@ static inline void AM_drawThings(UINT8 colors)
t = sectors[i].thinglist;
while (t)
{
if (!t->player)
AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<<FRACBITS, t->angle, colors, t->x, t->y);
AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<<FRACBITS, t->angle, colors, t->x, t->y);
t = t->snext;
}
}
}
static inline void AM_drawSpecialThingsOnly(UINT8 colors)
{
size_t i;
for (i = 0; i < numsectors; i++)
{
mobj_t *t = NULL;
// this is fucking horrible
const INT32 special = GETSECSPECIAL(sectors[i].special, 1);
if (GetDamage(special) != 0
//|| sectors[i].friction < ORIG_FRICTION
|| GetOffroad(special) != 0)
continue;
t = sectors[i].thinglist;
while (t)
{
if (t->type == MT_RANDOMITEM
|| t->type == MT_STARPOST
|| (t->flags & MF_SPRING))
AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<<FRACBITS, t->angle, colors, t->x, t->y);
t = t->snext;
}
}
}
/** Draws the crosshair.
/** Draws the crosshair, actually just a dot in software mode.
*
* \param color Color for the crosshair.
*/
static inline void AM_drawCrosshair(UINT8 color)
{
const fixed_t scale = 4<<FRACBITS;
size_t i;
fline_t fl;
for (i = 0; i < NUMCROSSMARKLINES; i++)
{
fl.a.x = FixedMul(cross_mark[i].a.x, scale) >> FRACBITS;
fl.a.y = FixedMul(cross_mark[i].a.y, scale) >> FRACBITS;
fl.b.x = FixedMul(cross_mark[i].b.x, scale) >> FRACBITS;
fl.b.y = FixedMul(cross_mark[i].b.y, scale) >> FRACBITS;
fl.a.x += f_x + (f_w / 2);
fl.a.y += f_y + (f_h / 2);
fl.b.x += f_x + (f_w / 2);
fl.b.y += f_y + (f_h / 2);
AM_drawFline(&fl, color);
}
V_DrawFill(f_w/2 + f_x, f_h/2 + f_y, 1, 1, color|V_NOSCALESTART);
}
/** Draws the automap.
@@ -1320,81 +1049,11 @@ void AM_Drawer(void)
if (!automapactive)
return;
AM_drawFline = AM_drawFline_soft;
#ifdef HWRENDER
if (rendermode == render_opengl)
AM_drawFline = HWR_drawAMline;
#endif
AM_clearFB(BACKGROUND);
if (draw_grid) AM_drawGrid(GRIDCOLORS);
AM_drawWalls(PASS_FOF|PASS_INTANGIBLE|PASS_SOLID);
AM_drawThings(THINGCOLORS);
AM_drawWalls();
AM_drawPlayers();
AM_drawThings(THINGCOLORS);
if (!followplayer) AM_drawCrosshair(XHAIRCOLORS);
}
minigen_t *AM_MinimapGenerate(INT32 mul)
{
static minigen_t ret = {0};
if (automapactive)
return NULL;
am_minigen = true;
AM_drawFline = AM_drawFline_soft; // yes, even in GL
//AM_FrameBufferInit();
f_x = f_y = 0;
ret.w = f_w = minimapinfo.minimap_w * mul;
ret.h = f_h = minimapinfo.minimap_h * mul;
am_buf = ret.buf = NULL;
//AM_LevelInit();
AM_findMinMaxBoundaries();
scale_mtof = min_scale_mtof - (min_scale_mtof/20);
scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
//AM_initVariables();
f_oldloc.x = INT32_MAX;
m_paninc.x = m_paninc.y = 0;
ftom_zoommul = FRACUNIT;
mtof_zoommul = FRACUNIT;
m_w = FTOM(f_w);
m_h = FTOM(f_h);
//AM_changeWindowLoc();
m_x = min_x - FixedMul(m_w, FRACUNIT/40);
m_y = min_y - FixedMul(m_h, FRACUNIT/40);
m_x2 = m_x + m_w;
m_y2 = m_y + m_h;
// for saving & restoring
old_m_x = m_x;
old_m_y = m_y;
old_m_w = m_w;
old_m_h = m_h;
am_buf = ret.buf = malloc((f_w*f_h));
if (ret.buf == NULL)
return NULL;
//AM_clearFB(BACKGROUND);
memset(am_buf, 0xff, (f_w*f_h));
AM_drawSpecialThingsOnly(BACKGROUND);
AM_drawWalls(PASS_FOF);
AM_drawWalls(PASS_INTANGIBLE);
AM_drawWalls(PASS_SOLID);
am_buf = NULL;
am_recalc = true;
am_minigen = false;
return &ret;
AM_drawCrosshair(XHAIRCOLORS);
}
+8 -17
View File
@@ -1,10 +1,8 @@
// SONIC ROBO BLAST 2 KART
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 2024 by Vivian "toastergrl" Grannell.
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2000 by DooM Legacy Team.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2018 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
@@ -28,6 +26,11 @@ typedef struct
fpoint_t a, b;
} fline_t;
// Used by ST StatusBar stuff.
#define AM_MSGHEADER (('a'<<24)+('m'<<16))
#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
extern boolean am_recalc; // true if screen size changes
extern boolean automapactive; // In AutoMap mode?
@@ -40,19 +43,7 @@ void AM_Ticker(void);
// Called by main loop, instead of view drawer if automap is active.
void AM_Drawer(void);
// Enables the automap.
void AM_Start(void);
// Called to force the automap to quit if the level is completed while it is up.
void AM_Stop(void);
typedef struct
{
INT32 w, h;
UINT8 *buf;
} minigen_t;
// Minimap generation
minigen_t *AM_MinimapGenerate(INT32 mul);
#endif
+4
View File
@@ -184,6 +184,8 @@ void I_OutputMsg(const char *fmt, ...)
void I_StartupMouse(void){}
void I_StartupMouse2(void){}
void I_StartupKeyboard(void){}
INT32 I_GetKey(void)
@@ -240,6 +242,8 @@ void I_GetJoystickEvents(void){}
void I_GetJoystick2Events(void){}
void I_GetMouseEvents(void){}
char *I_GetEnv(const char *name)
{
LOGW("I_GetEnv() called?!");
+5 -2
View File
@@ -36,7 +36,7 @@ static inline void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cm
return;
// Lua can handle it!
if (LUA_HookBotAI(sonic, tails, cmd))
if (LUAh_BotAI(sonic, tails, cmd))
return;
if (tails->player->pflags & (PF_MACESPIN|PF_ITEMHANG))
@@ -118,8 +118,11 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
return;
}
// Bot AI isn't programmed in analog.
//CV_SetValue(&cv_analog2, false);
// Let Lua scripts build ticcmds
if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd)))
if (LUAh_BotTiccmd(player, cmd))
return;
// We don't have any main character AI, sorry. D:
-2
View File
@@ -49,9 +49,7 @@ OBJS:=$(OBJS) \
$(OBJDIR)/lua_skinlib.o \
$(OBJDIR)/lua_thinkerlib.o \
$(OBJDIR)/lua_maplib.o \
$(OBJDIR)/hashtable.o \
$(OBJDIR)/lua_hudlib.o \
$(OBJDIR)/lua_hudlib_drawlist.o \
$(OBJDIR)/lua_udatalib.o \
$(OBJDIR)/lua_glib.o
-2
View File
@@ -400,9 +400,7 @@ OBJS:=$(OBJS) \
$(OBJDIR)/lua_skinlib.o \
$(OBJDIR)/lua_thinkerlib.o \
$(OBJDIR)/lua_maplib.o \
$(OBJDIR)/hashtable.o \
$(OBJDIR)/lua_hudlib.o \
$(OBJDIR)/lua_hudlib_drawlist.o \
$(OBJDIR)/lua_udatalib.o \
$(OBJDIR)/lua_glib.o
-14
View File
@@ -160,20 +160,6 @@ LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
/* }====================================================== */
/* compatibility with ref system */
/* pre-defined references */
#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
(lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
#define luaL_reg luaL_Reg
/* }====================================================== */
-4
View File
@@ -378,10 +378,6 @@ static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd)
return;
}
tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
#if LJ_INTONLY
/* x86 assembler can't handle STRTO with int type, have to CONV it instead */
tr = emitir(IRTI(IR_CONV), tr, IRCONV_INT_NUM);
#endif
}
#if LJ_HASFFI
} else if (tref_iscdata(tr)) {
+1 -1
View File
@@ -14,7 +14,7 @@
/* Lua lexer tokens. */
#define TKDEF(_, __) \
_(and) _(break) _(continue) _(do) _(else) _(elseif) _(end) _(false) \
_(for) _(function) _(if) _(in) _(local) _(nil) _(not) _(or) \
_(for) _(function) _(goto) _(if) _(in) _(local) _(nil) _(not) _(or) \
_(repeat) _(return) _(then) _(true) _(until) _(while) \
__(concat, ..) __(dots, ...) __(eq, ==) __(ge, >=) __(le, <=) __(ne, ~=) \
__(bxor, ^^) __(shl, <<) __(shr, >>) \
+12 -9
View File
@@ -786,11 +786,7 @@ static void bcemit_branch_f(FuncState *fs, ExpDesc *e)
pc = NO_JMP; /* Never jump. */
else if (e->k == VJMP)
pc = e->u.s.info;
else if (e->k == VKSTR || e->k == VKTRUE
#if !LJ_INTONLY
|| e->k == VKNUM
#endif
)
else if (e->k == VKSTR || e->k == VKNUM || e->k == VKTRUE)
expr_toreg_nobranch(fs, e, NO_REG), pc = bcemit_jmp(fs);
else
pc = bcemit_branch(fs, e, 1);
@@ -1151,7 +1147,7 @@ static void lex_match(LexState *ls, LexToken what, LexToken who, BCLine line)
static GCstr *lex_str(LexState *ls)
{
GCstr *s;
if (ls->tok != TK_name && LJ_52)
if (ls->tok != TK_name && (LJ_52 || ls->tok != TK_goto))
err_token(ls, TK_name);
s = strV(&ls->tokval);
lj_lex_next(ls);
@@ -1880,7 +1876,7 @@ static void expr_table(LexState *ls, ExpDesc *e)
if (!expr_isk(&key)) expr_index(fs, e, &key);
if (expr_isnumk(&key) && expr_numiszero(&key)) needarr = 1; else nhash++;
lex_check(ls, '=');
} else if ((ls->tok == TK_name) &&
} else if ((ls->tok == TK_name || (!LJ_52 && ls->tok == TK_goto)) &&
lj_lex_lookahead(ls) == '=') {
expr_str(ls, &key);
lex_check(ls, '=');
@@ -1976,7 +1972,7 @@ static BCReg parse_params(LexState *ls, int needself)
var_new_lit(ls, nparams++, "self");
if (ls->tok != ')') {
do {
if (ls->tok == TK_name) {
if (ls->tok == TK_name || (!LJ_52 && ls->tok == TK_goto)) {
var_new(ls, nparams++, lex_str(ls));
} else if (ls->tok == TK_dots) {
lj_lex_next(ls);
@@ -2154,7 +2150,7 @@ static void expr_primary(LexState *ls, ExpDesc *v)
expr(ls, v);
lex_match(ls, ')', '(', line);
expr_discharge(ls->fs, v);
} else if (ls->tok == TK_name) {
} else if (ls->tok == TK_name || (!LJ_52 && ls->tok == TK_goto)) {
var_lookup(ls, v);
} else if (ls->tok == '$') {
uint64_t i = ls->tokval.u64;
@@ -2994,6 +2990,13 @@ static int parse_stmt(LexState *ls)
case TK_label:
parse_label(ls);
break;
case TK_goto:
if (LJ_52 || lj_lex_lookahead(ls) == TK_name) {
lj_lex_next(ls);
parse_goto(ls);
break;
}
/* fallthrough */
default:
parse_call_assign(ls);
break;
-3
View File
@@ -496,9 +496,6 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
#endif
#if LJ_INTONLY
/* Skip trailing spaces */
while (lj_char_isspace(*p)) p++;
if (*p || p < pe)
return STRSCAN_ERROR;
#else
+23 -28
View File
@@ -1,7 +1,7 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2024 by Sonic Team Junior.
// Copyright (C) 1999-2018 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
@@ -11,9 +11,6 @@
/// \brief Macros to read/write from/to a UINT8 *,
/// used for packet creation and such
#ifndef __BYTEPTR_H__
#define __BYTEPTR_H__
#if defined (__alpha__) || defined (__arm__) || defined (__mips__) || defined (__ia64__) || defined (__clang__)
#define DEALIGNED
#endif
@@ -153,7 +150,7 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr)
#undef DEALIGNED
#define WRITESTRINGN(p, s, n) do { \
#define WRITESTRINGN(p, s, n) ({ \
size_t tmp_i; \
\
for (tmp_i = 0; tmp_i < n && s[tmp_i] != '\0'; tmp_i++) \
@@ -161,72 +158,70 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr)
\
if (tmp_i < n) \
WRITECHAR(p, '\0'); \
} while (0)
})
#define WRITESTRINGL(p, s, n) do { \
#define WRITESTRINGL(p, s, n) ({ \
size_t tmp_i; \
\
for (tmp_i = 0; tmp_i < n - 1 && s[tmp_i] != '\0'; tmp_i++) \
WRITECHAR(p, s[tmp_i]); \
\
WRITECHAR(p, '\0'); \
} while (0)
})
#define WRITESTRING(p, s) do { \
#define WRITESTRING(p, s) ({ \
size_t tmp_i; \
\
for (tmp_i = 0; s[tmp_i] != '\0'; tmp_i++) \
WRITECHAR(p, s[tmp_i]); \
\
WRITECHAR(p, '\0'); \
} while (0)
})
#define WRITEMEM(p, s, n) do { \
memcpy(p, s, n); \
p += n; \
} while (0)
#define WRITEMEM(p, s, n) ({ \
memcpy(p, s, n); \
p += n; \
})
#define SKIPSTRING(p) while (READCHAR(p) != '\0')
#define SKIPSTRINGN(p, n) do { \
#define SKIPSTRINGN(p, n) ({ \
size_t tmp_i = 0; \
\
while (tmp_i < n && READCHAR(p) != '\0') \
tmp_i++; \
} while (0)
})
#define SKIPSTRINGL(p, n) SKIPSTRINGN(p, n)
#define READSTRINGN(p, s, n) do { \
#define READSTRINGN(p, s, n) ({ \
size_t tmp_i = 0; \
\
while (tmp_i < n && (s[tmp_i] = READCHAR(p)) != '\0') \
tmp_i++; \
\
s[tmp_i] = '\0'; \
} while (0)
})
#define READSTRINGL(p, s, n) do { \
#define READSTRINGL(p, s, n) ({ \
size_t tmp_i = 0; \
\
while (tmp_i < n - 1 && (s[tmp_i] = READCHAR(p)) != '\0') \
tmp_i++; \
\
s[tmp_i] = '\0'; \
} while (0)
})
#define READSTRING(p, s) do { \
#define READSTRING(p, s) ({ \
size_t tmp_i = 0; \
\
while ((s[tmp_i] = READCHAR(p)) != '\0') \
tmp_i++; \
\
s[tmp_i] = '\0'; \
} while (0)
})
#define READMEM(p, s, n) do { \
memcpy(s, p, n); \
p += n; \
} while (0)
#endif // __BYTEPTR_H__
#define READMEM(p, s, n) ({ \
memcpy(s, p, n); \
p += n; \
})
+15 -2
View File
@@ -1493,7 +1493,11 @@ static void Got_NetVar(UINT8 **p, INT32 playernum)
if (server)
{
SendKick(playernum, KICK_MSG_CON_FAIL);
UINT8 buf[2];
buf[0] = (UINT8)playernum;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
}
return;
}
@@ -1984,7 +1988,7 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
return true;
}
// Block the Xbox DInput default axes and reset to the current defaults
// Block the Xbox DInput default axes and reset to the current defaults
static boolean CV_FilterJoyAxisVars2(consvar_t *v, const char *valstr)
{
if (!stricmp(v->name, "joyaxis_turn") && !stricmp(valstr, "X-Axis"))
@@ -2041,6 +2045,15 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr)
if (GETMAJOREXECVERSION(cv_execversion.value) < 2) // 2 = 1.0.2
{
#if 0
// We don't have changed saved cvars yet
if (!stricmp(v->name, "alwaysmlook")
|| !stricmp(v->name, "alwaysmlook2")
|| !stricmp(v->name, "mousemove")
|| !stricmp(v->name, "mousemove2"))
return false;
#endif
// axis defaults were changed to be friendly to 360 controllers
// if ALL axis settings are defaults, then change them to new values
if (!CV_FilterJoyAxisVars(v, valstr))
+35 -50
View File
@@ -59,7 +59,6 @@ static boolean con_started = false; // console has been initialised
boolean con_startup = false; // true at game startup, screen need refreshing
static boolean con_forcepic = true; // at startup toggle console translucency when first off
boolean con_recalc; // set true when screen size has changed
boolean con_muted = false;
static tic_t con_tick; // console ticker for anim or blinking prompt cursor
// con_scrollup should use time (currenttime - lasttime)..
@@ -276,28 +275,29 @@ void CON_SetupBackColormap(void)
switch (cons_backcolor.value)
{
case 0: palindex = 15; break; // White
case 1: palindex = 31; break; // Gray
case 2: palindex = 47; break; // Sepia
case 3: palindex = 63; break; // Brown
case 4: palindex = 150; shift = 7; break; // Pink
case 5: palindex = 127; shift = 7; break; // Raspberry
case 6: palindex = 143; break; // Red
case 7: palindex = 86; shift = 7; break; // Creamsicle
case 8: palindex = 95; break; // Orange
case 9: palindex = 119; shift = 7; break; // Gold
case 10: palindex = 111; break; // Yellow
case 11: palindex = 191; shift = 7; break; // Emerald
case 12: palindex = 175; break; // Green
case 13: palindex = 219; break; // Cyan
case 14: palindex = 207; shift = 7; break; // Steel
case 15: palindex = 230; shift = 7; break; // Periwinkle
case 16: palindex = 239; break; // Blue
case 17: palindex = 199; shift = 7; break; // Purple
case 18: palindex = 255; shift = 7; break; // Lavender
case 0: palindex = 15; break; // White
case 1: palindex = 31; break; // Gray
case 2: palindex = 47; break; // Sepia
case 3: palindex = 63; break; // Brown
case 4: palindex = 150; shift = 7; break; // Pink
case 5: palindex = 127; shift = 7; break; // Raspberry
case 6: palindex = 143; break; // Red
case 7: palindex = 86; shift = 7; break; // Creamsicle
case 8: palindex = 95; break; // Orange
case 9: palindex = 119; shift = 7; break; // Gold
case 10: palindex = 111; break; // Yellow
case 11: palindex = 191; shift = 7; break; // Emerald
case 12: palindex = 175; break; // Green
case 13: palindex = 219; break; // Cyan
case 14: palindex = 207; shift = 7; break; // Steel
case 15: palindex = 230; shift = 7; break; // Periwinkle
case 16: palindex = 239; break; // Blue
case 17: palindex = 199; shift = 7; break; // Purple
case 18: palindex = 255; shift = 7; break; // Lavender
// Default green
default: palindex = 175; break;
}
}
// setup background colormap
for (i = 0, j = 0; i < 768; i += 3, j++)
@@ -608,7 +608,7 @@ static void CON_MoveConsole(void)
}
// Not instant - Increment fracmovement fractionally
fracmovement += FixedMul(cons_speed.value*vid.fdupy, (cv_uncappedhud.value ? renderdeltatics : FRACUNIT));
fracmovement += FixedMul(cons_speed.value*vid.fdupy, renderdeltatics);
if (con_curlines < con_destlines) // Move the console downwards
{
@@ -621,11 +621,11 @@ static void CON_MoveConsole(void)
con_curlines -= FixedInt(fracmovement);
if (con_curlines < con_destlines)
con_curlines = con_destlines;
if (con_destlines == 0) // If the console is being closed, not just moved up...
con_tick = 0; // ...don't show the blinking cursor
}
fracmovement %= FRACUNIT; // Reset fracmovement's integer value, but keep the fraction
Unlock_state();
@@ -635,7 +635,7 @@ INT32 CON_ShiftChar(INT32 ch)
{
if (I_UseNativeKeyboard())
return ch;
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
{
if (cv_keyboardlayout.value == 3)
@@ -827,7 +827,7 @@ boolean CON_Responder(event_t *ev)
// let go keyup events, don't eat them
if (ev->type != ev_keydown && ev->type != ev_console)
{
if (ev->data1 == gamecontrol[0][gc_console][0] || ev->data1 == gamecontrol[0][gc_console][1])
if (ev->data1 == gamecontrol[gc_console][0] || ev->data1 == gamecontrol[gc_console][1])
consdown = false;
return false;
}
@@ -845,7 +845,7 @@ boolean CON_Responder(event_t *ev)
INT32 i;
for (i = 0; i < num_gamecontrols; i++)
{
if (gamecontrol[0][i][0] == ev->data1 || gamecontrol[0][i][1] == ev->data1)
if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1)
break;
}
@@ -853,7 +853,7 @@ boolean CON_Responder(event_t *ev)
return false;
}
if (key == gamecontrol[0][gc_console][0] || key == gamecontrol[0][gc_console][1])
if (key == gamecontrol[gc_console][0] || key == gamecontrol[gc_console][1])
{
if (consdown) // ignore repeat
return true;
@@ -1103,7 +1103,7 @@ static void CON_Print(char *msg)
INT32 controlchars = 0; // for color changing
char color = '\x80'; // keep color across lines
if (msg == NULL || con_muted)
if (msg == NULL)
return;
if (*msg == '\3') // chat text, makes ding sound
@@ -1236,19 +1236,15 @@ void CONS_Printf(const char *fmt, ...)
txt = malloc(8192);
va_start(argptr, fmt);
vsnprintf(txt, 8192, fmt, argptr);
vsprintf(txt, fmt, argptr);
va_end(argptr);
// echo console prints to log file
DEBFILE(txt);
//also mute the console in terminal/command line AND file, except for DEBFILE above
if (con_muted)
return;
if (con_started)
CON_Print(txt);
CON_LogMessage(txt);
Lock_state();
@@ -1338,12 +1334,7 @@ void CONS_Error(const char *msg)
// dirty quick hack, but for the good cause
while (I_GetKey() != KEY_ENTER)
{
// Sleep so we don't take too much of cpu usage
I_Sleep(1.f/TICRATE*1000);
I_OsPolling();
}
}
//======================================================================
@@ -1475,15 +1466,12 @@ static void CON_DrawHudlines(void)
{
charflags = (*p & 0x7f) << V_CHARCOLORSHIFT;
p++;
c++;
}
if (c >= con_width)
break;
if (*p < HU_FONTSTART)
;//charwidth = 4 * con_scalefactor;
else
{
//charwidth = hu_font['A'-HU_FONTSTART]->width * con_scalefactor;
//charwidth = SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
}
}
@@ -1518,7 +1506,7 @@ static void CON_DrawConsole(void)
// draw console background
if (cons_backpic.value || con_forcepic)
{
patch_t *con_backpic = W_CachePatchName("KARTKREW", PU_PATCH_LOWPRIORITY);
patch_t *con_backpic = W_CachePatchName("KARTKREW", PU_CACHE);
// Jimita: CON_DrawBackpic just called V_DrawScaledPatch
V_DrawFixedPatch(0, 0, FRACUNIT/2, 0, con_backpic, NULL);
@@ -1558,10 +1546,7 @@ static void CON_DrawConsole(void)
{
charflags = (*p & 0x7f) << V_CHARCOLORSHIFT;
p++;
c++;
}
if (c >= con_width)
break;
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
}
}
@@ -1586,11 +1571,11 @@ void CON_Drawer(void)
if (con_recalc)
{
CON_RecalcSize();
if (con_curlines <= 0)
CON_ClearHUD();
}
// console movement
if (con_curlines != con_destlines)
CON_MoveConsole();
-3
View File
@@ -25,9 +25,6 @@ extern I_mutex con_mutex;
// set true when screen size has changed, to adapt console
extern boolean con_recalc;
// no messages will be printed while the console is muted
extern boolean con_muted;
extern boolean con_startup;
// top clip value for view render: do not draw part of view hidden by console
+851 -1608
View File
File diff suppressed because it is too large. Load diff
+13 -57
View File
@@ -38,31 +38,9 @@ applications may follow different packet versions.
#define VANILLA_GT_MATCH 3
// Networking and tick handling related.
#define BACKUPTICS 512 // more than enough for most timeouts....
#define CLIENTBACKUPTICS 32
#define BACKUPTICS 32
#define TICQUEUE 512 // more than enough for most timeouts....
#define MAXTEXTCMD 256
// How many time bits to encode into ticcmds (aiming and angle components, respectively)
#define ENCODE_TICCMD_TIMES
#define TICCMD_TIMEBITS_AIMING 3
#define TICCMD_TIMEBITS_ANGLE 2
#define TICCMD_TIMEMASK_AIMING (~(0xFFFFFFFF<<TICCMD_TIMEBITS_AIMING))
#define TICCMD_TIMEMASK_ANGLE (~(0xFFFFFFFF<<TICCMD_TIMEBITS_ANGLE))
#define TICCMD_TIME_SIZE (1<<(TICCMD_TIMEBITS_AIMING+TICCMD_TIMEBITS_ANGLE))
// Maximum number of client-side simulations allowed. A simulation is a version of the game state extrapolated some frames ahead to cancel out network latency
#define MAXSIMULATIONS TICRATE //one second of simulations
#define MAXLOCALSAVESTATES 8
extern tic_t liveTic;
// No. of tics your controls can be delayed by.
// TODO: Instead of storing a ton of extra cmds for gentlemens' delay,
// keep them in a linked-list, with timestamps to discard everything that's older than already sent.
// That will support any amount of lag, and be less wasteful for clients who don't use it.
// This just works as a quick implementation.
#define MAXGENTLEMENDELAY TICRATE
//
// Packet structure
//
@@ -121,11 +99,12 @@ typedef enum
PT_PING, // Packet sent to tell clients the other client's latency to server.
#ifdef SATURNPAK
#ifdef SATURNSYNCH
PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate!
PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead.
PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again!
// we will reserve this for now even if unused, so order wont get mangled
PT_ISSATURN, // Saturn specific identifier packet
#endif
@@ -406,7 +385,6 @@ typedef struct
#define MAXSERVERNAME 32
#define MAXFILENEEDED 915
#define MAX_MIRROR_LENGTH 256
// This packet is too large
typedef struct
{
@@ -542,6 +520,7 @@ extern UINT32 serverlistultimatecount;
extern INT32 mapchangepending;
// Points inside doomcom
extern doomdata_t *netbuffer;
extern consvar_t cv_stunserver;
extern consvar_t cv_httpsource;
extern consvar_t cv_kicktime;
@@ -576,17 +555,6 @@ typedef enum
} kickreason_t;
// Player movement histories for simulated gamestates
typedef struct
{
// stores historical simulated positions where 0 is the real game position and simtic-gametic is the latest simulated position
fixed_t histx[MAXSIMULATIONS + 1], histy[MAXSIMULATIONS + 1], histz[MAXSIMULATIONS + 1];
// stores the final simulated position for each simulated gametic
fixed_t simx[MAXSIMULATIONS], simy[MAXSIMULATIONS], simz[MAXSIMULATIONS];
} steadyplayer_t;
/* the max number of name changes in some time period */
#define MAXNAMECHANGES (5)
#define NAMECHANGERATE (60*TICRATE)
@@ -600,10 +568,6 @@ extern boolean acceptnewnode;
extern SINT8 servernode;
extern char connectedservername[MAXSERVERNAME+1];
extern boolean issimulation; // whether the currently executed tic is part of a simulated gamestate
extern steadyplayer_t steadyplayers[MAXPLAYERS]; // Player movement histories for simulated gamestates
extern int rttJitter; //Round Trip Time jitter
void Command_Ping_f(void);
extern tic_t connectiontimeout;
extern tic_t jointimeout;
@@ -612,11 +576,6 @@ extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS];
extern tic_t servermaxping;
extern boolean server_lagless;
extern tic_t simulated_lag;
extern tic_t lowest_lag;
extern consvar_t cv_mindelay, cv_gentlemens;
extern consvar_t
#ifdef VANILLAJOINNEXTROUND
cv_joinnextround,
@@ -626,7 +585,7 @@ extern consvar_t
cv_allownewsaturnplayer,
#endif
cv_joinrefusemessage, cv_maxplayers, cv_resynchattempts,
#ifdef SATURNPAK
#ifdef SATURNSYNCH
cv_resynchcooldown, cv_gamestateattempts,
#endif
cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed;
@@ -641,9 +600,10 @@ void D_ClientServerInit(void);
// Initialise the other field
void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum));
void SendNetXCmdForPlayer(UINT8 playerid, netxcmd_t id, const void *param, size_t nparam);
#define SendNetXCmd(id, param, nparam) SendNetXCmdForPlayer(0, id, param, nparam) // Shortcut for P1
void SendKick(UINT8 playernum, UINT8 msg);
void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam);
void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player
void SendNetXCmd3(netxcmd_t id, const void *param, size_t nparam); // splitsreen3 player
void SendNetXCmd4(netxcmd_t id, const void *param, size_t nparam); // splitsreen4 player
// Create any new ticcmds and broadcast to other players.
void NetKeepAlive(void);
@@ -670,10 +630,7 @@ boolean Playing(void);
void D_QuitNetGame(void);
//? How many ticks to run?
boolean TryRunTics(tic_t realtic, tic_t entertic);
// Invalidates save states used in simulations
void InvalidateSavestates(void);
boolean TryRunTics(tic_t realtic);
// extra data for lmps
// these functions scare me. they contain magic.
@@ -690,14 +647,13 @@ extern char motd[254], server_context[8];
extern UINT8 playernode[MAXPLAYERS];
INT32 D_NumPlayers(void);
void D_ResetTiccmds(void);
tic_t GetLag(INT32 node);
//UINT8 GetFreeXCmdSize(UINT8 playerid);
UINT8 GetFreeXCmdSize(void);
extern UINT8 hu_resynching;
#ifdef SATURNPAK
#ifdef SATURNSYNCH
extern UINT8 hu_redownloadinggamestate;
#endif
extern boolean hu_stopped; // kart, true when the game is stopped for players due to a disconnecting or connecting player
+1
View File
@@ -25,6 +25,7 @@ typedef enum
ev_console,
ev_mouse,
ev_joystick,
ev_mouse2,
ev_joystick2,
ev_joystick3,
ev_joystick4,
+213 -425
View File
@@ -15,7 +15,6 @@
/// plus functions to parse command line parameters, configure game
/// parameters, and call the startup functions.
#include "d_netcmd.h"
#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON)
#include <sys/stat.h>
#include <sys/types.h>
@@ -85,6 +84,10 @@
#include "hardware/hw_main.h" // 3D View Rendering
#endif
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
#endif
#ifdef HAVE_DISCORDRPC
#include "discord.h"
#endif
@@ -133,7 +136,6 @@ char srb2home[256] = ".";
char srb2path[256] = ".";
boolean usehome = true;
const char *pandf = "%s" PATHSEP "%s";
static char addonsdir[MAX_WADPATH];
//
// EVENT HANDLING
@@ -147,7 +149,7 @@ INT32 eventhead, eventtail;
boolean dedicated = false;
boolean loaded_config = false; // true once config.cfg loaded AND executed
boolean loaded_config = false;
//
// D_PostEvent
@@ -166,73 +168,20 @@ UINT8 ctrldown = 0; // 0x1 left, 0x2 right
UINT8 altdown = 0; // 0x1 left, 0x2 right
boolean capslock = 0; // gee i wonder what this does.
static void D_PadMenuScrollInput(UINT8 input)
{
event_t dpadev;
memset(&dpadev, 0, sizeof(event_t));
dpadev.type = ev_keydown;
switch (input)
{
case DPAD_UP:
dpadev.data1 = KEY_UPARROW;
break;
case DPAD_DOWN:
dpadev.data1 = KEY_DOWNARROW;
break;
case DPAD_LEFT:
dpadev.data1 = KEY_LEFTARROW;
break;
case DPAD_RIGHT:
dpadev.data1 = KEY_RIGHTARROW;
break;
}
D_PostEvent(&dpadev); // put into eventlist
}
#define SCROLLDELAY 19
// Check if any dpad button is held
// and pass it to the eventlist
static void D_GamePadMenuScrollTicker(void)
{
static UINT8 menuInputDelayTimer = 0;
if (dedicated)
return;
for (UINT8 i = 0; i < 4; i++)
{
if (dpadscrollstate[i])
{
if (menuInputDelayTimer < SCROLLDELAY)
menuInputDelayTimer++;
else if (menuInputDelayTimer == SCROLLDELAY)
D_PadMenuScrollInput(i);
return;
}
}
menuInputDelayTimer = 0;
}
#undef SCROLLDELAY
static void D_DeviceLEDTick(void)
static inline void D_DeviceLEDTick(void)
{
UINT8 i;
static UINT16 color[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
UINT16 color[MAXSPLITSCREENPLAYERS];
UINT16 curcolor[MAXSPLITSCREENPLAYERS];
if (dedicated || numcontrollers == 0)
if (I_NumJoys() == 0 || (cv_gamepadled[0].value == 0 && cv_gamepadled[1].value == 0 && cv_gamepadled[2].value == 0 && cv_gamepadled[3].value == 0))
{
return;
}
for (i = 0; i <= splitscreen; i++)
{
if (!cv_usejoystick[i].value || !cv_gamepadled[i].value)
if (G_GetDeviceForPlayer(i) == 0)
continue;
color[i] = G_GetSkinColor(i);
@@ -343,7 +292,7 @@ static boolean D_Display(void)
if (rendermode == render_soft && !splitscreen)
{
R_InterpolateViewRollAngle(rendertimefrac_unpaused);
R_InterpolateViewRollAngle(rendertimefrac);
R_CheckViewMorph();
}
@@ -361,7 +310,6 @@ static boolean D_Display(void)
// save the current screen if about to wipe
wipe = (gamestate != wipegamestate);
if (wipe)
{
// set for all later
@@ -472,7 +420,6 @@ static boolean D_Display(void)
F_TitleScreenDrawer();
if (wipe)
wipedefindex = wipe_titlescreen_toblack;
HU_Drawer();
break;
case GS_WAITINGPLAYERS:
@@ -496,14 +443,12 @@ static boolean D_Display(void)
{
PS_START_TIMING(ps_rendercalltime);
R_ApplyLevelInterpolators(rendertimefrac);
R_ApplyLevelInterpolators(R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT);
for (i = 0; i <= splitscreen; i++)
{
if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD)
if (players[displayplayers[i]].mo || players[displayplayers[i]].playerstate == PST_DEAD)
{
viewssnum = i;
if (i == 0) // Initialize for P1
{
viewwindowy = 0;
@@ -513,9 +458,11 @@ static boolean D_Display(void)
objectsdrawn = 0;
}
viewssnum = i;
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_RenderPlayerView();
HWR_RenderPlayerView(i, &players[displayplayers[i]]);
else
#endif
if (rendermode != render_none)
@@ -569,7 +516,7 @@ static boolean D_Display(void)
for (i = 0; i <= splitscreen; i++)
{
V_DoPostProcessor(i, postimgparam[i]);
V_DoPostProcessor(i, &players[displayplayers[i]], postimgparam[i]);
}
}
@@ -612,8 +559,8 @@ static boolean D_Display(void)
py = 4;
else
py = viewwindowy + 4;
patch = W_CachePatchName("M_PAUSE", PU_PATCH);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, V_SNAPTOTOP, patch);
patch = W_CachePatchName("M_PAUSE", PU_CACHE);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, V_SNAPTOTOP, patch);
}
if (rendermode == render_soft && demo.rewinding)
@@ -650,8 +597,6 @@ static boolean D_Display(void)
}
}
NetUpdate(); // send out any new accumulation
// It's safe to end the game now.
if (G_GetExitGameFlag())
{
@@ -699,72 +644,12 @@ static boolean D_Display(void)
return ranwipe;
}
//TODO: this is absolutely fucking horrific
//TODO: pass a mobj to it so we dont have to do this terrible thing
// maybe someday.................
/*static void DoFunnyDance (void)
{
thinker_t *th;
static tic_t time = 0;
fixed_t bounce = 0;
fixed_t work, bpm = FLOAT_TO_FIXED(150.f); // FLOAT_TO_FIXED(mapmusic.bpm) << maybe can get the tempo and beat detection lib to work for autodetection
angle_t ang;
if (gamestate != GS_LEVEL)
return;
// dumb hack, preferrably would use beat detection so it starts ON the first beat
// since some songs have weird intros or begin slightly offbeat
if (S_MapMusPlaying())
{
bpm = FixedDiv((60*TICRATE)<<FRACBITS, bpm);
work = time<<FRACBITS;
work %= bpm;
if (time >= (FRACUNIT>>1)) // prevent overflow jump - takes about 15 minutes of loop on the same song to reach
time = (work>>FRACBITS);
work = FixedDiv(work*180, bpm);
ang = (FixedAngle(work)>>ANGLETOFINESHIFT) & FINEMASK;
bounce = (FINESINE(ang) - FRACUNIT/2);
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
mobj_t *mo;
if (th->function != (actionf_p1)P_MobjThinker) // not a mobj
continue;
mo = (mobj_t *)th;
if (!mo->player)
continue;
// plan is same as above, continue on the next beat of the song to stay in sync
if (paused || P_AutoPause())
{
mo->spritexscale = mo->realxscale;
mo->spriteyscale = mo->realyscale;
continue;
}
mo->spritexscale -= bounce/2;
mo->spriteyscale += bounce/2;
}
time++; // bruh
}
else
time = 0;
}*/
// =========================================================================
// D_SRB2Loop
// =========================================================================
tic_t rendergametic;
static SINT8 menuInputDelayTimer = 0;
void D_SRB2Loop(void)
{
@@ -803,7 +688,7 @@ void D_SRB2Loop(void)
COM_ImmedExecute("cls;version");
if (rendermode == render_soft)
V_DrawFixedPatch(0, 0, FRACUNIT/2, 0, W_CachePatchNum(W_GetNumForName("KARTKREW"), PU_PATCH_LOWPRIORITY), NULL);
V_DrawFixedPatch(0, 0, FRACUNIT/2, 0, (patch_t *)W_CacheLumpNum(W_GetNumForName("KARTKREW"), PU_CACHE), NULL);
I_FinishUpdate(); // page flip or blit buffer
for (;;)
@@ -813,9 +698,11 @@ void D_SRB2Loop(void)
precise_t enterprecise = I_GetPreciseTime();
precise_t finishprecise = enterprecise;
// Casting the return value of a function is bad practice (apparently)
double budget = ((R_GetFramerateCap() == 0) ? 0.0 : round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision()));
capbudget = (precise_t) budget;
{
// Casting the return value of a function is bad practice (apparently)
double budget = round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision());
capbudget = (precise_t) budget;
}
boolean ranwipe = false;
@@ -844,9 +731,13 @@ void D_SRB2Loop(void)
debugload--;
#endif
interp = (R_UsingFrameInterpolation() && !dedicated);
interp = R_UsingFrameInterpolation() && !dedicated;
doDisplay = false;
#ifdef HW3SOUND
HW3S_BeginFrameUpdate();
#endif
renderisnewtic = (realtics > 0 || singletics);
refreshdirmenu = 0; // not sure where to put this, here as good as any?
@@ -859,9 +750,9 @@ void D_SRB2Loop(void)
realtics = 1;
// process tics (but maybe not if realtic == 0)
TryRunTics(realtics, entertic);
TryRunTics(realtics);
if (lastdraw || singletics || (gametic > rendergametic))
if (lastdraw || singletics || gametic > rendergametic)
{
rendergametic = gametic;
rendertimeout = entertic + TICRATE/17;
@@ -875,7 +766,7 @@ void D_SRB2Loop(void)
{
// Evaluate the chase cam once for every local realtic
// This might actually be better suited inside G_Ticker or TryRunTics
for (tic_t chasecamtics = 0; (chasecamtics < realtics); chasecamtics++)
for (tic_t chasecamtics = 0; chasecamtics < realtics; chasecamtics++)
{
P_RunChaseCameras();
}
@@ -885,22 +776,42 @@ void D_SRB2Loop(void)
doDisplay = true;
}
if (menuactive)
#define DPADSCROLLINPUT(INPUT)\
{\
myev.data1 = INPUT;\
M_Responder(&myev);\
}
// this is absolutely awful and i hate it lmao
if (menuactive && (DPADUPSCROLL || DPADDOWNSCROLL || DPADLEFTSCROLL || DPADRIGHTSCROLL))
{
D_GamePadMenuScrollTicker();
event_t myev;
myev.type = ev_keydown;
if (menuInputDelayTimer < 19)
menuInputDelayTimer++;
if (menuInputDelayTimer == 19) // TICRATE * ( (k+2) (1 - [wz + h + j - q]^2 - [(gk + 2g + k + 1)(h + j) + h - z]^2 - [16(k + 1)^3(k + 2)(n + 1)^2 + 1 - f^2]^2 calculated by my butt
{
if (DPADUPSCROLL)
DPADSCROLLINPUT(KEY_UPARROW)
else if (DPADDOWNSCROLL)
DPADSCROLLINPUT(KEY_DOWNARROW)
else if (DPADLEFTSCROLL)
DPADSCROLLINPUT(KEY_LEFTARROW)
else if (DPADRIGHTSCROLL)
DPADSCROLLINPUT(KEY_RIGHTARROW)
}
}
else
menuInputDelayTimer = 0;
#undef DPADSCROLLINPUT
D_DeviceLEDTick();
}
if (interp)
{
renderdeltatics = FloatToFixed(deltatics);
// I looked at the possibility of putting in a float drawer for
// perfstats and it's very complicated, so we'll just do this instead...
ps_interp_frac.value.p = (precise_t)((FIXED_TO_FLOAT(g_time.timefrac)) * 1000.0f);
ps_interp_lag.value.p = (precise_t)((deltasecs) * 1000.0f);
renderdeltatics = FLOAT_TO_FIXED(deltatics);
if (!(paused || P_AutoPause()) && deltatics < 1.0 && !hu_stopped)
{
@@ -911,14 +822,7 @@ void D_SRB2Loop(void)
rendertimefrac = FRACUNIT;
}
if ((deltatics < 1.0) && !hu_stopped)
{
rendertimefrac_unpaused = g_time.timefrac;
}
else
{
rendertimefrac_unpaused = FRACUNIT;
}
rendertimefrac_unpaused = g_time.timefrac;
}
else
{
@@ -939,11 +843,16 @@ void D_SRB2Loop(void)
M_DoScreenShot();
// consoleplayer -> displayplayers (hear sounds from viewpoint)
if (renderisnewtic)
S_UpdateSounds(); // move positional sounds
S_UpdateSounds(); // move positional sounds
#ifdef HW3SOUND
HW3S_EndFrameUpdate();
#endif
LUA_Step();
#ifdef HAVE_DISCORDRPC
if (!dedicated && renderisnewtic)
if (! dedicated)
{
Discord_RunCallbacks();
}
@@ -965,7 +874,7 @@ void D_SRB2Loop(void)
//
// Wipes run an inner loop and artificially increase
// the measured time.
if (!ranwipe && (frameskip < 3) && (deltatics > 1.0))
if (!ranwipe && frameskip < 3 && deltatics > 1.0)
{
frameskip++;
}
@@ -981,7 +890,7 @@ void D_SRB2Loop(void)
// in the case of "match refresh rate" + vsync, don't sleep at all
const boolean vsync_with_match_refresh = cv_vidwait.value && cv_fpscap.value == 0;
if ((elapsed > 0) && ((INT64)capbudget > elapsed) && !vsync_with_match_refresh)
if (elapsed > 0 && (INT64)capbudget > elapsed && !vsync_with_match_refresh)
{
I_SleepDuration(capbudget - (finishprecise - enterprecise));
}
@@ -1003,7 +912,6 @@ void D_SRB2Loop(void)
void D_StartTitle(void)
{
INT32 i;
if (netgame)
{
if (gametype == GT_RACE) // SRB2kart
@@ -1025,8 +933,6 @@ void D_StartTitle(void)
return;
}
M_ClearMenus(true);
// okay, stop now
// (otherwise the game still thinks we're playing!)
SV_StopServer();
@@ -1055,10 +961,11 @@ void D_StartTitle(void)
//demosequence = -1;
gametype = GT_RACE; // SRB2kart
paused = false;
S_ResetKeepAndSpecialMus(); // just in case
F_StartTitleScreen();
// Reset the palette -- SRB2Kart: actually never mind let's do this in the middle of every fade
/*if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL");*/
}
//
@@ -1139,21 +1046,18 @@ static void D_AutoloadFile(const char *file, char **filearray)
COM_BufAddText(va("exec %s\n", newfile));
}
static char *strremove(char *str, const char *sub)
{
char *p, *q, *r;
if (*sub && (q = r = strstr(str, sub)) != NULL)
{
size_t len = strlen(sub);
while ((r = strstr(p = r + len, sub)) != NULL)
{
while (p < r)
*q++ = *p++;
}
while ((*q++ = *p++) != '\0')
continue;
}
return str;
static char *strremove(char *str, const char *sub) {
char *p, *q, *r;
if (*sub && (q = r = strstr(str, sub)) != NULL) {
size_t len = strlen(sub);
while ((r = strstr(p = r + len, sub)) != NULL) {
while (p < r)
*q++ = *p++;
}
while ((*q++ = *p++) != '\0')
continue;
}
return str;
}
// FIND THEM
@@ -1261,49 +1165,44 @@ void D_CleanFile(char **filearray)
static boolean AddIWAD(void)
{
char * path = va(pandf, srb2path, "srb2.srb");
char * path = va(pandf,srb2path,"srb2.srb");
if (FIL_ReadFileOK(path))
{
D_AddFile(path, startupwadfiles);
return true;
}
return false;
else
{
return false;
}
}
// extra graphic patches for saturn specific thingies
boolean found_extra_kart = false;
boolean found_extra2_kart = false;
boolean found_extra3_kart = false;
boolean found_extra_kart;
boolean found_extra2_kart;
boolean found_extra3_kart;
boolean xtra_speedo = false; // extra speedometer check
boolean xtra_speedo_clr = false; // extra speedometer colour check
boolean xtra_speedo3 = false; // 80x 11 extra speedometer check
boolean xtra_speedo_clr3 = false; // 80x 11 extra speedometer colour check
boolean achi_speedo = false; // achiiro speedometer check
boolean achi_speedo_clr = false; // extra speedometer colour check
boolean dial_speedo = false; // dial speedometer check
boolean dial_speedo_clr = false; // dial speedometer colour check
boolean kartz_speedo = false; // kartZ speedo
boolean kartz_speedo_smol = false; // kartZ speedo but smol
boolean clr_hud = false; // colour hud check
boolean driftgaugegfx_clr = false; // driftgauge colour check
boolean big_lap = false; // bigger lap counter
boolean big_lap_color = false; // bigger lap counter but colour
boolean statdp = false; // stat display for extended player setup
boolean nametaggfx = false; // Nametag stuffs
boolean driftgaugegfx = false; // Driftgauge stuffs
boolean multiitem_icon = false; // Extra icons for Sneakers, Banana and Jawz
boolean joystickicon = false; // Extra icons for the joystick input display
boolean minidoticon = false; // Dot graphic for minimap player angle display
boolean minilighticon = false; // mkwii-style minimap headlight
//
boolean xtra_speedo; // extra speedometer check
boolean xtra_speedo_clr; // extra speedometer colour check
boolean xtra_speedo3; // 80x 11 extra speedometer check
boolean xtra_speedo_clr3; // 80x 11 extra speedometer colour check
boolean achi_speedo; // achiiro speedometer check
boolean achi_speedo_clr; // extra speedometer colour check
boolean clr_hud; // colour hud check
boolean big_lap; // bigger lap counter
boolean big_lap_color; // bigger lap counter but colour
boolean kartzspeedo; // kartZ speedo
boolean statdp; // stat display for extended player setup
boolean nametaggfx; // Nametag stuffs
boolean driftgaugegfx;
static void IdentifyVersion(void)
{
const char *srb2waddir = NULL;
found_extra_kart = false;
found_extra2_kart = false;
found_extra3_kart = false;
#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL)
// change to the directory where 'srb2.srb' is found
@@ -1313,18 +1212,20 @@ static void IdentifyVersion(void)
// get the current directory (possible problem on NT with "." as current dir)
if (srb2waddir)
{
strlcpy(srb2path, srb2waddir, sizeof(srb2path));
strlcpy(srb2path,srb2waddir,sizeof (srb2path));
}
else
{
if (getcwd(srb2path, sizeof(srb2path)))
if (getcwd(srb2path, 256) != NULL)
srb2waddir = srb2path;
else
srb2waddir = ".";
{
srb2waddir = srb2path;
}
}
// Load the IWAD
if (!AddIWAD())
if (! AddIWAD())
{
I_Error("SRB2.SRB not found! Expected in %s\n", srb2waddir);
}
@@ -1349,21 +1250,18 @@ static void IdentifyVersion(void)
D_AddFile(va(pandf,srb2waddir,"patch.kart"), startupwadfiles);
#endif
// completely optional
if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra.kart")))
{
if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra.kart"))) {
D_AddFile(va(pandf,srb2waddir,"extra.kart"), startupwadfiles);
found_extra_kart = true;
}
// completely optional 2: Back with a vengence
if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra2.kart")))
{
if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra2.kart"))) {
D_AddFile(va(pandf,srb2waddir,"extra2.kart"), startupwadfiles);
found_extra2_kart = true;
}
if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra3.kart")))
{
if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra3.kart"))) {
D_AddFile(va(pandf,srb2waddir,"extra3.kart"), startupwadfiles);
found_extra3_kart = true;
}
@@ -1411,197 +1309,6 @@ static inline void D_MakeTitleString(char *s)
strcpy(s, temp);
}
static void D_CheckSaturnExtraFiles(void)
{
// Possible value that changes depending on whether required files for speedometer are found or not
CV_PossibleValue_t speedo_cons_temp[NUMSPEEDOSTUFF] = {{1, "Default"}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}};
CV_PossibleValue_t driftgaugestyle_cons_temp[NUMDGAUGESTUFF] = {{1, "Default"}, {2, "Small"}, {3, "Big Numbers"}, {4, "Numbers Only"}, {0, NULL}, {0, NULL}};
CV_PossibleValue_t inputdisplay_cons_temp[NUMINPUTDISPLAYSTUFF] = {{0, "Off"}, {1, "Wheel"}, {2, "Stick"}, {0, NULL}, {0, NULL}};
CV_PossibleValue_t minimapdot_cons_temp[NUMMINIMAPDOTSTUFF] = {{0, "Off"}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}};
unsigned last_speedo_i = 0;
unsigned last_driftgauge_i = 3;
unsigned last_inputdisplay_i = 2;
unsigned last_minimapdot_i = 0;
#define PUSHCONS(cons, i, id, name) { ++i; cons[i].value = id; cons[i].strvalue = name; }
// found the funny, add it in!
if (found_extra_kart)
{
mainwads++;
// now check for extra speedometer stuff
if (W_CheckMultipleLumps("SP_SMSTC", "K_TRNULL", "SP_MKMH", "SP_MMPH", "SP_MFRAC", "SP_MPERC", NULL))
{
xtra_speedo = true;
PUSHCONS(speedo_cons_temp, last_speedo_i, 2, "Small");
}
// now check for achii speedometer stuff
if (W_CheckMultipleLumps("SP_AMSTC", "K_TRNULL", "SP_AKMH", "SP_AMPH", "SP_AFRAC", "SP_APERC", NULL))
{
achi_speedo = true;
PUSHCONS(speedo_cons_temp, last_speedo_i, 3, "Achii");
}
// now check for dial speedometer stuff
if (W_CheckMultipleLumps("K_DSPBS1", "K_DSPBS2", "K_DSDIAL",
"K_TRNULL", "SP_DKMH", "SP_DMPH", "SP_DFRAC", "SP_DPERC",
"K_DSPNM0", "K_DSPNM1", "K_DSPNM2", "K_DSPNM3", "K_DSPNM4",
"K_DSPNM5", "K_DSPNM6", "K_DSPNM7", "K_DSPNM8", "K_DSPNM9",
"RANKFIN", NULL))
{
dial_speedo = true;
PUSHCONS(speedo_cons_temp, last_speedo_i, 4, "Dial");
}
// check for bigger lap count
if (W_CheckMultipleLumps("K_STLAPB", "K_STLA2B", NULL))
{
big_lap = true;
}
// kartzspeedo
if (W_CheckMultipleLumps("K_KZSP1", "K_KZSP2", "K_KZSP3", "K_KZSP4", "K_KZSP5",
"K_KZSP6", "K_KZSP7", "K_KZSP8", "K_KZSP9", "K_KZSP10", "K_KZSP11", "K_KZSP12",
"K_KZSP13", "K_KZSP14", "K_KZSP15", "K_KZSP16", "K_KZSP17", "K_KZSP18", "K_KZSP19",
"K_KZSP20", "K_KZSP21", "K_KZSP22", "K_KZSP23", "K_KZSP24", "K_KZSP25", NULL))
{
kartz_speedo = true;
PUSHCONS(speedo_cons_temp, last_speedo_i, 5, "P-Meter");
}
if (W_CheckMultipleLumps("K_KZSS1", "K_KZSS2", "K_KZSS3", "K_KZSS4", "K_KZSS5",
"K_KZSS6", "K_KZSS7", "K_KZSS8", "K_KZSS9", "K_KZSS10", "K_KZSS11", "K_KZSS12",
"K_KZSS13", "K_KZSS14", "K_KZSS15", "K_KZSS16", "K_KZSS17", "K_KZSS18", "K_KZSS19",
"K_KZSS20", "K_KZSS21", "K_KZSS22", "K_KZSS23", "K_KZSS24", "K_KZSS25", NULL))
{
kartz_speedo_smol = true;
PUSHCONS(speedo_cons_temp, last_speedo_i, 6, "P-Meter Small");
}
// stat display for extended player setup
if (W_CheckMultipleLumps("K_STATNB", "K_STATN1", "K_STATN2",
"K_STATN3", "K_STATN4", "K_STATN5", "K_STATN6", NULL))
{
statdp = true;
}
// Nametag stuffs
if (W_CheckMultipleLumps("NTLINE", "NTLINEV", "NTSP", "NTWH", NULL))
{
nametaggfx = true;
}
// driftgauge
if (W_CheckMultipleLumps("K_DGAU","K_DGSU", NULL))
{
driftgaugegfx = true;
}
// extra item icons
if (W_CheckMultipleLumps("K_ITSHO2", "K_ITSHO3", "K_ITBAN2", "K_ITBAN3", "K_ITBAN4", "K_ITJAW2", NULL))
{
multiitem_icon = true;
}
// extra round joystick inputdisplay sprites
if (W_CheckMultipleLumps("JOYBCK","JOYKNB","JOYSHD", NULL))
{
joystickicon = true;
PUSHCONS(inputdisplay_cons_temp, last_inputdisplay_i, 3, "StickGFX");
}
if (W_LumpExists("MMAPDOT"))
{
minidoticon = true;
PUSHCONS(minimapdot_cons_temp, last_minimapdot_i, 1, "Dot");
}
if (W_LumpExists("MMAPHDLT"))
{
minilighticon = true;
PUSHCONS(minimapdot_cons_temp, last_minimapdot_i, 2, "Headlight");
}
}
// now check for colour hud stuff
if (found_extra2_kart)
{
mainwads++;
// kart vanilla hud patches but colourizable
if (W_CheckMultipleLumps("K_SCTIME", "K_SCTIMW", "K_SCLAPS", "K_SCLAPW","K_SCBALN", "K_SCBALW",
"K_SCKARM", "K_SCTOUT", "K_ISMULC", "K_ITMULC", "K_ITBC", "K_ITBCD", "K_ISBC", "K_ISBCD", NULL))
{
clr_hud = true;
}
// extra speedo but colour
if (W_LumpExists("SC_SMSTC"))
{
xtra_speedo_clr = true;
}
// achii speedo but colour
if (W_CheckMultipleLumps("SC_AMSTC", "K_TRNULL", "SC_AKMH", "SC_AMPH", "SC_AFRAC", "SC_APERC", NULL))
{
achi_speedo_clr = true;
}
// dial speedo but colour
if (W_CheckMultipleLumps("K_DSPBC1", "K_DSPBC2", "K_DSDIAL",
"K_TRNULL", "SC_DKMH", "SC_DMPH", "SC_DFRAC", "SC_DPERC",
"K_DSPNC0", "K_DSPNC1", "K_DSPNC2", "K_DSPNC3", "K_DSPNC4",
"K_DSPNC5", "K_DSPNC6", "K_DSPNC7", "K_DSPNC8", "K_DSPNC9",
"RANKFIN", NULL))
{
dial_speedo_clr = true;
}
// driftgauge but colour
if (W_CheckMultipleLumps("K_DCAU","K_DCSU", NULL))
{
driftgaugegfx_clr = true;
}
// check for bigger lap count but color** its color bitch
if (W_CheckMultipleLumps("K_SCLAPB", "K_SCLA2B", NULL))
{
big_lap_color = true;
}
}
// can be used for custom hud stuff
// currently used for the v1 beta hud
if (found_extra3_kart)
{
mainwads++;
// 80x11 speedometer crap
if (W_LumpExists("SP_SM3TC"))
{
xtra_speedo3 = true;
PUSHCONS(speedo_cons_temp, last_speedo_i, 7, "Extra");
PUSHCONS(driftgaugestyle_cons_temp, last_driftgauge_i, 5, "Extra");
}
// 80x11 speedometer crap but colour
if (W_LumpExists("SC_SM3TC"))
{
xtra_speedo_clr3 = true;
}
}
#undef PUSHCONS
memcpy(speedo_cons_t, speedo_cons_temp, sizeof(speedo_cons_t));
memcpy(driftgaugestyle_cons_t, driftgaugestyle_cons_temp, sizeof(driftgaugestyle_cons_t));
memcpy(inputdisplay_cons_t, inputdisplay_cons_temp, sizeof(inputdisplay_cons_t));
memcpy(minimapdot_cons_t, minimapdot_cons_temp, sizeof(minimapdot_cons_t));
}
#include <locale.h>
//
// D_SRB2Main
//
@@ -1714,6 +1421,8 @@ void D_SRB2Main(void)
// can't use sprintf since there is %u in savegamename
strcatbf(savegamename, srb2home, PATHSEP);
I_mkdir(srb2home, 0700);
#else
snprintf(srb2home, sizeof srb2home, "%s", userhome);
snprintf(downloaddir, sizeof downloaddir, "%s", userhome);
@@ -1750,10 +1459,6 @@ void D_SRB2Main(void)
}
}
// Create addons dir
snprintf(addonsdir, sizeof addonsdir, "%s%s%s", srb2home, PATHSEP, "addons");
I_mkdir(addonsdir, 0755);
D_SetupProtocol();
// rand() needs seeded regardless of password
@@ -1799,7 +1504,6 @@ void D_SRB2Main(void)
CONS_Printf("I_InitializeTime()...\n");
I_InitializeTime();
setlocale(LC_TIME, "");
// Make backups of some SOCcable tables.
P_BackupTables();
@@ -1851,7 +1555,92 @@ void D_SRB2Main(void)
#endif //ifndef DEVELOP
D_CheckSaturnExtraFiles(); // check all the saturn stuff :3
// Possible value that changes depending on whether required files for speedometer are found or not
CV_PossibleValue_t speedo_cons_temp[NUMSPEEDOSTUFF] = {{1, "Default"}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}};
unsigned last_speedo_i = 0;
#define PUSHSPEEDO(id, name) { ++last_speedo_i; speedo_cons_temp[last_speedo_i].value = id; speedo_cons_temp[last_speedo_i].strvalue = name; }
if (found_extra_kart || found_extra2_kart || found_extra3_kart) // found the funny, add it in!
{
// HAYA: These are seperated for a reason lmao
if (found_extra_kart)
mainwads++;
if (found_extra2_kart)
mainwads++;
if (found_extra3_kart)
mainwads++;
// now check for extra speedometer stuff
if (W_CheckMultipleLumps("SP_SMSTC", "K_TRNULL", "SP_MKMH", "SP_MMPH", "SP_MFRAC", "SP_MPERC", NULL))
{
xtra_speedo = true;
PUSHSPEEDO(2, "Small");
}
if (W_LumpExists("SC_SMSTC"))
xtra_speedo_clr = true;
// now check for achii speedometer stuff
if (W_CheckMultipleLumps("SP_AMSTC", "K_TRNULL", "SP_AKMH", "SP_AMPH", "SP_AFRAC", "SP_APERC", NULL))
{
achi_speedo = true;
PUSHSPEEDO(3, "Achii");
}
if (W_CheckMultipleLumps("SC_AMSTC", "K_TRNULL", "SC_AKMH", "SC_AMPH", "SC_AFRAC", "SC_APERC", NULL))
achi_speedo_clr = true;
// check for bigger lap count
if (W_CheckMultipleLumps("K_STLAPB", "K_STLA2B", NULL))
big_lap = true;
// now check for colour hud stuff
if (W_CheckMultipleLumps("K_SCTIME", "K_SCTIMW", "K_SCLAPS", "K_SCLAPW", \
"K_SCBALN", "K_SCBALW", "K_SCKARM", "K_SCTOUT", "K_ISMULC", "K_ITMULC", "K_ITBC", "K_ITBCD", "K_ISBC", "K_ISBCD", NULL))
clr_hud = true;
// check for bigger lap count but color** its color bitch
if (W_CheckMultipleLumps("K_SCLAPB", "K_SCLA2B", NULL))
big_lap_color = true;
// kartzspeedo
if (W_CheckMultipleLumps("K_KZSP1", "K_KZSP2", "K_KZSP3", "K_KZSP4", "K_KZSP5", \
"K_KZSP6", "K_KZSP7", "K_KZSP8", "K_KZSP9", "K_KZSP10", "K_KZSP11", "K_KZSP12", \
"K_KZSP13", "K_KZSP14", "K_KZSP15", "K_KZSP16", "K_KZSP17", "K_KZSP18", "K_KZSP19", \
"K_KZSP20", "K_KZSP21", "K_KZSP22", "K_KZSP23", "K_KZSP24", "K_KZSP25", NULL))
{
kartzspeedo = true;
PUSHSPEEDO(4, "P-Meter");
}
// stat display for extended player setup
if (W_CheckMultipleLumps("K_STATNB", "K_STATN1", "K_STATN2", "K_STATN3", "K_STATN4", \
"K_STATN5", "K_STATN6", NULL))
statdp = true;
// Nametag stuffs
if (W_CheckMultipleLumps("NTLINE", "NTLINEV", "NTSP", "NTWH", NULL))
nametaggfx = true;
if (W_CheckMultipleLumps("K_DGAU","K_DCAU","K_DGSU","K_DCSU", NULL))
driftgaugegfx = true;
if (found_extra3_kart)
{
// 80x11 speedometer crap
if (W_LumpExists("SP_SM3TC"))
{
xtra_speedo3 = true;
PUSHSPEEDO(5, "Extra");
}
if (W_LumpExists("SC_SM3TC"))
xtra_speedo_clr3 = true;
}
}
#undef PUSHSPEEDO
memcpy(speedo_cons_t, speedo_cons_temp, sizeof(speedo_cons_t));
// Do it before P_InitMapData because PNG patch
// conversion sometimes needs the palette
@@ -1966,9 +1755,7 @@ void D_SRB2Main(void)
savedata.lives = 0; // flag this as not-used
// make sure I_Quit() will write back the correct config
// (do not write back the config if it crash before)
loaded_config = true; // so palettechange doesent get called 500 times at startup lol
loaded_config = true; // so pallettechange doesent get called 500 times at startup lol
//------------------------------------------------ COMMAND LINE PARAMS
@@ -2049,6 +1836,7 @@ void D_SRB2Main(void)
}
S_InitMusicDefs();
S_InitMTDefs();
CONS_Printf("ST_Init(): Init status bar.\n");
ST_Init();
@@ -2263,7 +2051,7 @@ void D_SRB2Main(void)
}
#ifdef HAVE_DISCORDRPC
if (!dedicated)
if (! dedicated)
{
DRPC_Init();
}
+14 -25
View File
@@ -17,9 +17,9 @@
#include "d_event.h"
#include "w_wad.h" // for MAX_WADFILES
// make sure not to write back the config until it's been correctly loaded
extern tic_t rendergametic;
// make sure not to write back the config until it's been correctly loaded
extern boolean loaded_config;
extern char srb2home[256]; //Alam: My Home
@@ -27,34 +27,23 @@ extern boolean usehome; //Alam: which path?
extern const char *pandf; //Alam: how to path?
extern char srb2path[256]; //Alam: SRB2's Home
// extra graphic patches for saturn specific thingies
extern boolean found_extra_kart; // for use in k_kart.c
extern boolean found_extra2_kart; // for use in k_kart.c
extern boolean found_extra3_kart; // for use in k_kart.c
extern boolean xtra_speedo; // extra speedometer check
extern boolean xtra_speedo_clr; // extra speedometer colour check
extern boolean xtra_speedo3; // 80x11 extra speedometer check
extern boolean xtra_speedo_clr3; // 80x11 extra speedometer colour check
extern boolean achi_speedo; // achiiro speedometer check
extern boolean achi_speedo_clr; // extra speedometer colour check
extern boolean dial_speedo; // dial speedometer check
extern boolean dial_speedo_clr; // dial speedometer colour check
extern boolean kartz_speedo; // kartZ speedo
extern boolean kartz_speedo_smol; // kartZ speedo but smol
extern boolean clr_hud; // colour hud check
extern boolean driftgaugegfx_clr; // driftgauge colour check
extern boolean big_lap; // bigger lap counter
extern boolean big_lap_color; // bigger lap counter but colour
extern boolean statdp; // stat display for extended player setup
extern boolean nametaggfx; // Nametag stuffs
extern boolean driftgaugegfx; // Driftgauge stuffs
extern boolean multiitem_icon; // Extra icons for Sneakers, Banana and Jawz
extern boolean joystickicon; // Extra icons for the joystick input display
extern boolean minidoticon; // Dot icon for minimap player angle display
extern boolean minilighticon; // mkwii-style minimap headlight
//
extern boolean xtra_speedo; // extra speedometer check
extern boolean xtra_speedo_clr; // extra speedometer colour check
extern boolean xtra_speedo3; // 80x11 extra speedometer check
extern boolean xtra_speedo_clr3; // 80x11 extra speedometer colour check
extern boolean achi_speedo; // achiiro speedometer check
extern boolean achi_speedo_clr; // extra speedometer colour check
extern boolean clr_hud; // colour hud check
extern boolean big_lap; // bigger lap counter
extern boolean big_lap_color; // bigger lap counter but colour
extern boolean kartzspeedo; // kartZ speedo
extern boolean statdp; // stat display for extended player setup
extern boolean nametaggfx; // Nametag stuffs
extern boolean driftgaugegfx;
// autoload stuff
extern boolean autoloading;
+112 -177
View File
@@ -48,6 +48,12 @@ tic_t connectiontimeout = (10*TICRATE);
/// \brief network packet
doomcom_t *doomcom = NULL;
/// \brief network packet data, points inside doomcom
doomdata_t *netbuffer = NULL;
/// \brief hole punching packet, also points inside doomcom
#ifdef HOLEPUNCH
holepunch_t *holepunchpacket = NULL;
#endif
#ifdef DEBUGFILE
FILE *debugfile = NULL; // put some net info in a file during the game
@@ -63,6 +69,8 @@ INT16 hardware_MAXPACKETLENGTH;
boolean (*I_NetGet)(void) = NULL;
void (*I_NetSend)(void) = NULL;
boolean (*I_NetCanSend)(void) = NULL;
boolean (*I_NetCanGet)(void) = NULL;
void (*I_NetCloseSocket)(void) = NULL;
void (*I_NetFreeNodenum)(INT32 nodenum) = NULL;
SINT8 (*I_NetMakeNodewPort)(const char *address, const char* port) = NULL;
@@ -103,24 +111,20 @@ boolean Net_GetNetStat(void)
{
const tic_t t = I_GetTime();
static INT64 oldsendbyte = 0;
if (statstarttic+STATLENGTH <= t)
{
const tic_t df = t-statstarttic;
const INT64 newsendbyte = sendbytes - oldsendbyte;
sendbps = (INT32)(newsendbyte*TICRATE)/df;
getbps = (getbytes*TICRATE)/df;
if (sendackpacket)
lostpercent = 100.0f*(float)retransmit/(float)sendackpacket;
else
lostpercent = 0.0f;
if (getackpacket)
duppercent = 100.0f*(float)duppacket/(float)getackpacket;
else
duppercent = 0.0f;
if (ticruned)
gamelostpercent = 100.0f*(float)ticmiss/(float)ticruned;
else
@@ -203,9 +207,13 @@ static node_t nodes[MAXNETNODES];
// 0 if a = n (mod 256)
// >0 if a > b (mod 256)
// mnemonic: to use it compare to 0: cmpack(a,b)<0 is "a < b" ...
FUNCMATH static inline INT32 cmpack(UINT8 a, UINT8 b)
FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b)
{
return (SINT8)(a - b);
register INT32 d = a - b;
if (d >= 127 || d < -128)
return -d;
return d;
}
/** Sets freeack to a free acknum and copies the netbuffer in the ackpak table
@@ -214,13 +222,11 @@ FUNCMATH static inline INT32 cmpack(UINT8 a, UINT8 b)
* \param lowtimer ???
* \return True if a free acknum was found
*/
static boolean GetFreeAcknum(UINT8 *freeack)
static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
{
node_t *node = &nodes[doomcom->remotenode];
INT32 i, numfreeslot = 0;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0)
{
DEBFILE(va("too fast %d %d\n",node->remotefirstack,node->nextacknum));
@@ -228,7 +234,6 @@ static boolean GetFreeAcknum(UINT8 *freeack)
}
for (i = 0; i < MAXACKPACKETS; i++)
{
if (!ackpak[i].acknum)
{
// For low priority packets, make sure to let freeslots so urgent packets can be sent
@@ -246,8 +251,17 @@ static boolean GetFreeAcknum(UINT8 *freeack)
node->nextacknum++;
ackpak[i].destinationnode = (UINT8)(node - nodes);
ackpak[i].length = doomcom->datalength;
ackpak[i].senttime = I_GetTime();
ackpak[i].resentnum = 0;
if (lowtimer)
{
// Lowtime means can't be sent now so try it as soon as possible
ackpak[i].senttime = 0;
ackpak[i].resentnum = 1;
}
else
{
ackpak[i].senttime = I_GetTime();
ackpak[i].resentnum = 0;
}
M_Memcpy(ackpak[i].pak.raw, netbuffer, ackpak[i].length);
*freeack = ackpak[i].acknum;
@@ -256,17 +270,46 @@ static boolean GetFreeAcknum(UINT8 *freeack)
return true;
}
}
#ifdef PARANOIA
CONS_Debug(DBG_NETPLAY, "No more free ackpacket\n");
#endif
if (netbuffer->packettype < PT_CANFAIL)
I_Error("Connection lost\n");
return false;
}
/** Counts how many acks are free
*
* \param urgent True if the type of the packet meant to
* use an ack is lower than PT_CANFAIL
* If for some reason you don't want use it
* for any packet type in particular,
* just set to false
* \return The number of free acks
*
*/
INT32 Net_GetFreeAcks(boolean urgent)
{
INT32 i, numfreeslot = 0;
INT32 n = 0; // Number of free acks found
for (i = 0; i < MAXACKPACKETS; i++)
if (!ackpak[i].acknum)
{
// For low priority packets, make sure to let freeslots so urgent packets can be sent
if (!urgent)
{
numfreeslot++;
if (numfreeslot <= URGENTFREESLOTNUM)
continue;
}
n++;
}
return n;
}
// Get a ack to send in the queue of this node
static UINT8 GetAcktosend(INT32 node)
{
@@ -279,7 +322,6 @@ static void RemoveAck(INT32 i)
INT32 node = ackpak[i].destinationnode;
DEBFILE(va("Remove ack %d\n",ackpak[i].acknum));
ackpak[i].acknum = 0;
if (nodes[node].flags & NF_CLOSE)
Net_CloseConnection(node);
}
@@ -290,22 +332,18 @@ static boolean Processackpak(void)
INT32 i;
boolean goodpacket = true;
node_t *node = &nodes[doomcom->remotenode];
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
// Received an ack return, so remove the ack in the list
if (netbuffer->ackreturn && cmpack(node->remotefirstack, netbuffer->ackreturn) < 0)
{
node->remotefirstack = netbuffer->ackreturn;
// Search the ackbuffer and free it
for (i = 0; i < MAXACKPACKETS; i++)
{
if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode
if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes
&& cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0)
{
RemoveAck(i);
}
}
}
// Received a packet with ack, queue it to send the ack back
@@ -313,7 +351,6 @@ static boolean Processackpak(void)
{
UINT8 ack = netbuffer->ack;
getackpacket++;
if (cmpack(ack, node->firstacktosend) <= 0)
{
DEBFILE(va("Discard(1) ack %d (duplicated)\n", ack));
@@ -324,7 +361,6 @@ static boolean Processackpak(void)
{
// Check if it is not already in the queue
for (i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND)
{
if (node->acktosend[i] == ack)
{
DEBFILE(va("Discard(2) ack %d (duplicated)\n", ack));
@@ -332,14 +368,11 @@ static boolean Processackpak(void)
goodpacket = false; // Discard packet (duplicate)
break;
}
}
if (goodpacket)
{
// Is a good packet so increment the acknowledge number,
// Then search for a "hole" in the queue
UINT8 nextfirstack = (UINT8)(node->firstacktosend + 1);
if (!nextfirstack)
nextfirstack = 1;
@@ -352,11 +385,9 @@ static boolean Processackpak(void)
if (!nextfirstack)
nextfirstack = 1;
hm1 = (UINT8)((node->acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND);
while (change)
{
change = false;
for (i = node->acktosend_tail; i != node->acktosend_head;
i = (i+1) % MAXACKTOSEND)
{
@@ -369,7 +400,6 @@ static boolean Processackpak(void)
nextfirstack = 1;
change = true;
}
if (i == node->acktosend_tail)
{
node->acktosend[node->acktosend_tail] = 0;
@@ -391,7 +421,6 @@ static boolean Processackpak(void)
// Will be incremented when the nextfirstack comes (code above)
UINT8 newhead = (UINT8)((node->acktosend_head+1) % MAXACKTOSEND);
DEBFILE(va("out of order packet (%d expected)\n", nextfirstack));
if (newhead != node->acktosend_tail)
{
node->acktosend[node->acktosend_head] = ack;
@@ -416,7 +445,6 @@ void Net_SendAcks(INT32 node)
#ifdef NONET
(void)node;
#else
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
netbuffer->packettype = PT_NOTHING;
M_Memcpy(netbuffer->u.textcmd, nodes[node].acktosend, MAXACKTOSEND);
HSendPacket(node, false, 0, MAXACKTOSEND);
@@ -428,14 +456,9 @@ static void GotAcks(void)
{
INT32 i, j;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
for (j = 0; j < MAXACKTOSEND; j++)
{
if (netbuffer->u.textcmd[j])
{
for (i = 0; i < MAXACKPACKETS; i++)
{
if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode)
{
if (ackpak[i].acknum == netbuffer->u.textcmd[j])
@@ -450,9 +473,6 @@ static void GotAcks(void)
ackpak[i].senttime--; // hurry up
}
}
}
}
}
}
#endif
@@ -483,13 +503,10 @@ void Net_AckTicker(void)
#ifndef NONET
INT32 i;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
for (i = 0; i < MAXACKPACKETS; i++)
{
const INT32 nodei = ackpak[i].destinationnode;
node_t *node = &nodes[nodei];
if (ackpak[i].acknum && ackpak[i].senttime + NODETIMEOUT < I_GetTime())
{
if (ackpak[i].resentnum > 10 && (node->flags & NF_CLOSE))
@@ -540,13 +557,10 @@ void Net_UnAcknowledgePacket(INT32 node)
#ifdef NONET
(void)node;
#else
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
INT32 hm1 = (nodes[node].acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND;
DEBFILE(va("UnAcknowledge node %d\n", node));
if (!node)
return;
if (nodes[node].acktosend[hm1] == netbuffer->ack)
{
nodes[node].acktosend[hm1] = 0;
@@ -570,7 +584,6 @@ void Net_UnAcknowledgePacket(INT32 node)
if (!nodes[node].firstacktosend)
nodes[node].firstacktosend = UINT8_MAX;
}
nodes[node].firstacktosend++;
if (!nodes[node].firstacktosend)
nodes[node].firstacktosend = 1;
@@ -589,10 +602,8 @@ static boolean Net_AllAcksReceived(void)
INT32 i;
for (i = 0; i < MAXACKPACKETS; i++)
{
if (ackpak[i].acknum)
return false;
}
return true;
}
@@ -612,7 +623,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
timeout = tictac + timeout*NEWTICRATE;
HGetPacket();
while (timeout > I_GetTime() && !Net_AllAcksReceived())
{
while (tictac == I_GetTime())
@@ -620,7 +630,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
I_Sleep(cv_sleep.value);
I_UpdateTime(cv_timescale.value);
}
tictac = I_GetTime();
HGetPacket();
Net_AckTicker();
@@ -631,7 +640,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
static void InitNode(node_t *node)
{
node->acktosend_head = node->acktosend_tail = 0;
memset(node->acktosend, 0, sizeof(node->acktosend));
node->firstacktosend = 0;
node->nextacknum = 1;
node->remotefirstack = 0;
@@ -661,14 +669,13 @@ void Net_AbortPacketType(UINT8 packettype)
#ifdef NONET
(void)packettype;
#else
for (INT32 i = 0; i < MAXACKPACKETS; i++)
{
INT32 i;
for (i = 0; i < MAXACKPACKETS; i++)
if (ackpak[i].acknum && (ackpak[i].pak.data.packettype == packettype
|| packettype == UINT8_MAX))
{
ackpak[i].acknum = 0;
}
}
#endif
}
@@ -713,7 +720,6 @@ void Net_CloseConnection(INT32 node)
// check if we are waiting for an ack from this node
for (i = 0; i < MAXACKPACKETS; i++)
{
if (ackpak[i].acknum && ackpak[i].destinationnode == node)
{
if (!forceclose)
@@ -721,7 +727,6 @@ void Net_CloseConnection(INT32 node)
else
ackpak[i].acknum = 0;
}
}
InitNode(&nodes[node]);
SV_AbortSendFiles(node);
@@ -735,12 +740,12 @@ void Net_CloseConnection(INT32 node)
//
static UINT32 NetbufferChecksum(void)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
UINT32 c = 0x1234567;
const INT32 l = doomcom->datalength - 4;
const UINT8 *buf = (UINT8 *)netbuffer + 4;
INT32 i;
for (INT32 i = 0; i < l; i++, buf++)
for (i = 0; i < l; i++, buf++)
c += (*buf) * (i+1);
return LONG(c);
@@ -755,7 +760,6 @@ static void fprintfstring(char *s, size_t len)
size_t i;
for (i = 0; i < len; i++)
{
if (s[i] < 32)
{
if (!mode)
@@ -775,8 +779,6 @@ static void fprintfstring(char *s, size_t len)
}
fprintf(debugfile, "%c", s[i]);
}
}
if (mode)
fprintf(debugfile, "]");
}
@@ -831,14 +833,15 @@ const char *packettypename[NUMPACKETTYPE] =
"MOREFILESNEEDED",
"PING"
#ifdef SATURNPAK
#ifdef SATURNSYNCH
,
"WILLRESENDGAMESTATE",
"CANRECEIVEGAMESTATE",
"RECEIVEDGAMESTATE",
"ISSATURN" // special packet to identify saturn clients
// we will reserve this for now even if unused, so order wont get mangled
"ISSATURN"
#endif
};
@@ -852,8 +855,6 @@ const char *Net_GetPacketName(UINT8 packettype)
static void DebugPrintpacket(const char *header)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
fprintf(debugfile, "%-12s (node %d,ack %d,ackret %d,size %d) type(%d) : %s\n",
header, doomcom->remotenode, netbuffer->ack, netbuffer->ackreturn, doomcom->datalength,
netbuffer->packettype, Net_GetPacketName(netbuffer->packettype));
@@ -1023,7 +1024,6 @@ void Command_Droprate(void)
#ifndef NONET
static boolean ShouldDropPacket(void)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
return (packetdropquantity[netbuffer->packettype])
|| (packetdroprate != 0 && rand() < (((double)RAND_MAX) * (packetdroprate / 100.f))) || packetdroprate == 100;
}
@@ -1035,9 +1035,7 @@ static boolean ShouldDropPacket(void)
//
boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlength)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
doomcom->datalength = (INT16)(packetlength + BASEPACKETSIZE);
if (node == 0) // Packet is to go back to us
{
if ((rebound_head+1) % MAXREBOUND == rebound_tail)
@@ -1073,7 +1071,6 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
// do this before GetFreeAcknum because this function backups
// the current packet
doomcom->remotenode = (INT16)node;
if (doomcom->datalength <= 0)
{
DEBFILE("HSendPacket: nothing to send\n");
@@ -1088,10 +1085,17 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
netbuffer->ackreturn = GetAcktosend(node);
else
netbuffer->ackreturn = 0;
if (reliable)
{
if (!GetFreeAcknum(&netbuffer->ack))
if (I_NetCanSend && !I_NetCanSend())
{
if (netbuffer->packettype < PT_CANFAIL)
GetFreeAcknum(&netbuffer->ack, true);
DEBFILE("HSendPacket: Out of bandwidth\n");
return false;
}
else if (!GetFreeAcknum(&netbuffer->ack, false))
return false;
}
else
@@ -1136,7 +1140,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
//
boolean HGetPacket(void)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
//boolean nodejustjoined;
// Get a packet from self
if (rebound_tail != rebound_head)
@@ -1163,6 +1167,7 @@ boolean HGetPacket(void)
while(true)
{
//nodejustjoined = I_NetGet();
I_NetGet();
if (doomcom->remotenode == -1) // No packet received
@@ -1191,6 +1196,21 @@ boolean HGetPacket(void)
DebugPrintpacket("GET");
#endif
/*// If a new node sends an unexpected packet, just ignore it
if (nodejustjoined && server
&& !(netbuffer->packettype == PT_ASKINFO
|| netbuffer->packettype == PT_SERVERINFO
|| netbuffer->packettype == PT_PLAYERINFO
|| netbuffer->packettype == PT_REQUESTFILE
|| netbuffer->packettype == PT_ASKINFOVIAMS
|| netbuffer->packettype == PT_CLIENTJOIN))
{
DEBFILE(va("New node sent an unexpected %s packet\n", packettypename[netbuffer->packettype]));
//CONS_Alert(CONS_NOTICE, "New node sent an unexpected %s packet\n", packettypename[netbuffer->packettype]);
Net_CloseConnection(doomcom->remotenode | FORCECLOSE);
continue;
}*/
// Proceed the ack and ackreturn field
if (!Processackpak())
continue; // discarded (duplicated)
@@ -1208,83 +1228,6 @@ boolean HGetPacket(void)
return true;
}
#define gettime (I_GetPreciseTime() / tic_frequency)
void TimeFudge(void)
{
// you can use SDL_GetPerformanceFrequency() instead of tic_frequency to get more precise timings
double startTime = gettime;
double packetTimeFudge[64];
int numReceivedPackets = 0;
const double numSampleTics = 10;
int i;
double lastTimeReceivedPacket;
if (server && netgame)
{
CONS_Printf("Servers do not need time fudging!\n");
return;
}
lastTimeReceivedPacket = gettime;
while ((fabs(gettime - startTime) < numSampleTics) || numReceivedPackets < 10)
{
I_NetGet();
if ((doomcom->remotenode != -1)) // Packet received
{
packetTimeFudge[numReceivedPackets] = 100 * fabs((gettime - lastTimeReceivedPacket) - netUpdateFudge); // gets the time fudge offset (0-100)
CONS_Printf("%i: %f\n", numReceivedPackets, packetTimeFudge[numReceivedPackets]);
numReceivedPackets++;
lastTimeReceivedPacket = gettime;
}
}
if (numReceivedPackets > 0)
{
UINT8 minOffset = 100, maxOffset = 0, averageOffset = 0;
UINT8 newTimeFudge;
UINT8 estimatedRange;
for (i = 0; i < numReceivedPackets; i++)
{
if (packetTimeFudge[i] < 0)
continue;
minOffset = min(minOffset, packetTimeFudge[i]);
maxOffset = max(maxOffset, packetTimeFudge[i]);
}
if (maxOffset - minOffset > 50)
{
// say maxOffset = 90 and minOffset = 20, we want the average to be 30...
maxOffset = maxOffset - 100;
if (minOffset > maxOffset)
{
int swap = maxOffset;
maxOffset = minOffset;
minOffset = swap;
}
}
estimatedRange = maxOffset - minOffset;
averageOffset = (maxOffset + minOffset) / 2;
CONS_Printf("%i packets received\n Timer fluctuations:\nmin: %d max: %d avg: %d est. range: %d (network update time: %lf)\n", numReceivedPackets, minOffset, maxOffset, averageOffset,
estimatedRange, netUpdateFudge);
if (averageOffset <= 0)
{
CONS_Printf("Timers are OK, no time fudging required\n");
return;
}
newTimeFudge = (cv_timefudge.value + averageOffset + 50) % 100;
CONS_Printf("New time fudge: %i%%\n", newTimeFudge);
CV_SetValue(&cv_timefudge, newTimeFudge);
}
}
#undef gettime
static boolean Internal_Get(void)
{
doomcom->remotenode = -1;
@@ -1301,33 +1244,26 @@ static void Internal_FreeNodenum(INT32 nodenum)
(void)nodenum;
}
static char *I_NetSplitAddress(char *host, char **port)
{
boolean v4 = (host[0] != '[');
host = strtok(host, v4 ? ":" : "[]");
if (port)
*port = strtok(NULL, ":");
return host;
}
SINT8 I_NetMakeNode(const char *hostname)
{
SINT8 newnode = -1;
if (I_NetMakeNodewPort)
{
char *localhostname = strdup(hostname);
char *port;
char *t = localhostname;
const char *port;
if (!localhostname)
return newnode;
// retrieve portnum from address!
hostname = I_NetSplitAddress(localhostname, &port);
strtok(localhostname, ":");
port = strtok(NULL, ":");
newnode = I_NetMakeNodewPort(hostname, port);
// remove the port in the hostname as we've it already
while ((*t != ':') && (*t != '\0'))
t++;
*t = '\0';
newnode = I_NetMakeNodewPort(localhostname, port);
free(localhostname);
}
return newnode;
@@ -1337,10 +1273,7 @@ void D_SetDoomcom(void)
{
if (doomcom) return;
doomcom = Z_Calloc(sizeof (doomcom_t), PU_STATIC, NULL);
doomcom->id = DOOMCOM_ID;
doomcom->numslots = doomcom->numnodes = 1;
doomcom->gametype = 0;
doomcom->consoleplayer = 0;
doomcom->extratics = 0;
}
@@ -1359,12 +1292,12 @@ boolean D_CheckNetGame(void)
I_NetGet = Internal_Get;
I_NetSend = Internal_Send;
I_NetCanSend = NULL;
I_NetCloseSocket = NULL;
I_NetFreeNodenum = Internal_FreeNodenum;
I_NetMakeNodewPort = NULL;
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
// I_InitNetwork sets doomcom and netgame
// check and initialize the network driver
multiplayer = false;
@@ -1384,7 +1317,6 @@ boolean D_CheckNetGame(void)
server = true; // WTF? server always true???
// no! The deault mode is server. Client is set elsewhere
// when the client executes connect command.
doomcom->ticdup = 1;
if (M_CheckParm("-extratic"))
{
@@ -1414,16 +1346,19 @@ boolean D_CheckNetGame(void)
if (netgame)
multiplayer = true;
if (doomcom->id != DOOMCOM_ID)
I_Error("Doomcom buffer invalid!");
if (doomcom->numnodes > MAXNETNODES)
I_Error("Too many nodes (%d), max:%d", doomcom->numnodes, MAXNETNODES);
netbuffer = (doomdata_t *)(void *)&doomcom->data;
#ifdef HOLEPUNCH
holepunchpacket = (holepunch_t *)(void *)&doomcom->data;
#endif
#ifdef DEBUGFILE
if (M_CheckParm("-debugfile"))
{
char filename[21];
INT32 k = doomcom->consoleplayer - 1;
INT32 k = consoleplayer - 1;
if (M_IsNextParm())
k = atoi(M_GetNextParm()) - 1;
while (!debugfile && k < MAXPLAYERS)
@@ -1479,10 +1414,9 @@ void Command_Ping_f(void)
INT32 i;
pingc = 0;
for (i = 1; i < MAXPLAYERS; ++i)
{
if (players[i].ingame)
if (playeringame[i])
{
INT32 ms;
@@ -1531,7 +1465,7 @@ void Command_Ping_f(void)
ms_width, pingv[i].ms);
}
if (!server && players[consoleplayer].ingame)
if (!server && playeringame[consoleplayer])
{
CONS_Printf("\nYour ping is %d frames (%d ms)\n", playerpingtable[consoleplayer], (INT32)(playerpingtable[consoleplayer] * (1000.00f / TICRATE)));
}
@@ -1557,6 +1491,7 @@ void D_CloseConnection(void)
I_NetGet = Internal_Get;
I_NetSend = Internal_Send;
I_NetCanSend = NULL;
I_NetCloseSocket = NULL;
I_NetFreeNodenum = Internal_FreeNodenum;
I_NetMakeNodewPort = NULL;
+3 -4
View File
@@ -27,9 +27,6 @@
#define STATLENGTH (TICRATE*2)
void TimeFudge(void);
extern double netUpdateFudge;
// stat of net
extern INT32 ticruned, ticmiss;
extern INT32 getbps, sendbps;
@@ -48,10 +45,12 @@ extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
extern boolean serverrunning;
INT32 Net_GetFreeAcks(boolean urgent);
void Net_AckTicker(void);
// If reliable return true if packet sent, 0 else
boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlength);
boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum,
size_t packetlength);
boolean HGetPacket(void);
void D_SetDoomcom(void);
#ifndef NONET
+626 -492
View File
File diff suppressed because it is too large. Load diff
+20 -16
View File
@@ -43,12 +43,25 @@ extern consvar_t cv_seenames, cv_allowseenames;
extern consvar_t cv_usemouse;
//WTF
extern consvar_t cv_mouseturn;
extern consvar_t cv_usejoystick[4]; //MAXSPLITSCREENPLAYERS
extern consvar_t cv_usejoystick;
extern consvar_t cv_usejoystick2;
extern consvar_t cv_usejoystick3;
extern consvar_t cv_usejoystick4;
#ifdef LJOYSTICK
extern consvar_t cv_joyport;
extern consvar_t cv_joyport2;
#endif
extern consvar_t cv_joyscale[4]; //MAXSPLITSCREENPLAYERS
extern consvar_t cv_joyscale;
extern consvar_t cv_joyscale2;
extern consvar_t cv_joyscale3;
extern consvar_t cv_joyscale4;
// splitscreen with second mouse
extern consvar_t cv_mouse2port;
extern consvar_t cv_usemouse2;
#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON)
extern consvar_t cv_mouse2opt;
#endif
// normally in p_mobj but the .h is not read
extern consvar_t cv_itemrespawntime;
@@ -146,24 +159,11 @@ extern consvar_t cv_pingmeasurement;
extern consvar_t cv_pingicon;
extern consvar_t cv_pingstyle;
extern consvar_t cv_simulate;
extern consvar_t cv_simulatetics;
extern consvar_t cv_simmisstics;
extern consvar_t cv_jittersmoothing;
extern consvar_t cv_simulateculldistance;
extern consvar_t cv_siminaccuracy;
extern consvar_t cv_netsteadyplayers;
extern consvar_t cv_debugsimulaterewind;
extern consvar_t cv_timefudge;
extern consvar_t cv_nettrails;
extern consvar_t cv_netslingdelay;
//extern consvar_t cv_smallpos;
extern consvar_t cv_showminimapnames;
extern consvar_t cv_minihead;
extern consvar_t cv_showminimapangle;
extern consvar_t cv_showlapemblem;
extern consvar_t cv_showlapemblem;
extern consvar_t cv_showviewpointtext;
extern consvar_t cv_showdownloadprompt;
@@ -185,7 +185,9 @@ extern consvar_t cv_nametagdist;
extern consvar_t cv_showownnametag;
extern consvar_t cv_smallnametags;
extern consvar_t cv_nametagrestat;
extern consvar_t cv_nametaghop;
extern consvar_t cv_nametagscore;
extern consvar_t cv_shownametagfinish;
extern consvar_t cv_shownametagspectator;
#define SKINSELECTSPIN_PAIN 25
@@ -308,6 +310,8 @@ typedef union {
#pragma pack()
#endif
extern tic_t driftsparkGrowTimer[16];
// add game commands, needs cleanup
void D_RegisterServerCommands(void);
void D_RegisterClientCommands(void);
+59 -71
View File
@@ -64,11 +64,11 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid);
#ifdef HAVE_CURL
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
#if (LIBCURL_VERSION_MAJOR <= 7) && (LIBCURL_VERSION_MINOR < 35)
static int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
#else
#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 35, 0)
static int curlprogress_callbackx(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
#define XFERINFOFUNCTION
#else
static int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
#endif
#endif
@@ -111,17 +111,26 @@ static fileused_t transferFiles[UINT8_MAX + 1];
// Receiver structure
INT32 fileneedednum; // Number of files needed to join the server
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
static I_mutex downloadmutex;
char downloaddir[512] = "DOWNLOAD";
file_download_t filedownload;
#ifdef CLIENT_LOADINGSCREEN
// for cl loading screen
INT32 lastfilenum = -1;
INT32 downloadcompletednum = 0;
UINT32 downloadcompletedsize = 0;
INT32 totalfilesrequestednum = 0;
UINT32 totalfilesrequestedsize = 0;
#endif
#ifdef HAVE_CURL
static CURL *http_handle;
static CURLM *multi_handle;
static UINT32 curl_dlnow;
static UINT32 curl_dltotal;
boolean curl_running = false;
boolean curl_failedwebdownload = false;
static double curl_dlnow;
static double curl_dltotal;
static time_t curl_starttime;
INT32 curl_transfers = 0;
static int curl_runninghandles = 0;
static UINT32 curl_origfilesize;
static UINT32 curl_origtotalfilesize;
@@ -140,7 +149,6 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
{
size_t i;
UINT8 count = 0;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded;
UINT8 *p = p_start;
char wadfilename[MAX_WADPATH] = "";
@@ -213,7 +221,6 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
for (i = firstfile; i < fileneedednum; i++)
{
fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet
fileneeded[i].justdownloaded = false;
filestatus = READUINT8(p); // The first byte is the file status
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
@@ -225,12 +232,8 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
void CL_PrepareDownloadSaveGame(const char *tmpsave)
{
#ifdef CLIENT_LOADINGSCREEN
filedownload.current = -1;
#endif
fileneedednum = 1;
fileneeded[0].status = FS_REQUESTED;
fileneeded[0].justdownloaded = false;
fileneeded[0].totalsize = UINT32_MAX;
fileneeded[0].file = NULL;
memset(fileneeded[0].md5sum, 0, 16);
@@ -322,7 +325,6 @@ boolean CL_SendRequestFile(void)
#ifdef MORELEGACYDOWNLOADER
boolean firstloop = true;
#endif
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
#ifdef PARANOIA
if (M_CheckParm("-nodownload"))
@@ -451,11 +453,9 @@ tryagain:
// returns false if a requested file was not found or cannot be sent
boolean Got_RequestFilePak(INT32 node)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
char wad[MAX_WADPATH+1];
UINT8 *p = netbuffer->u.textcmd;
UINT8 id;
while (p < netbuffer->u.textcmd + MAXTEXTCMD) // Don't allow hacked client to overflow
{
id = READUINT8(p);
@@ -548,13 +548,13 @@ INT32 CL_CheckFiles(void)
{
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK)
downloadrequired = true;
if (fileneeded[i].status != FS_OPEN)
filestoload++;
if (fileneeded[i].status != FS_NOTCHECKED) //since we're running this over multiple tics now, its possible for us to come across files checked in previous tics
continue;
CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
// Check in already loaded files
@@ -658,10 +658,13 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
q = &((*q)->next);
// Allocate a file request and append it to the file list
p = *q = (filetx_t *)calloc(1, sizeof(filetx_t)); // Initialise with zeros
p = *q = (filetx_t *)malloc(sizeof (filetx_t));
if (!p)
I_Error("SV_SendFile: No more memory\n");
// Initialise with zeros
memset(p, 0, sizeof (filetx_t));
// Allocate the file name
p->id.filename = (char *)malloc(MAX_WADPATH);
if (!p->id.filename)
@@ -740,10 +743,13 @@ void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UI
q = &((*q)->next);
// Allocate a file request and append it to the file list
p = *q = (filetx_t *)calloc(1, sizeof(filetx_t)); // Initialise with zeros
p = *q = (filetx_t *)malloc(sizeof (filetx_t));
if (!p)
I_Error("SV_SendRam: No more memory\n");
// Initialise with zeros
memset(p, 0, sizeof (filetx_t));
p->ram = freemethod; // Remember how to free the memory block for when we're done sending it
p->id.ram = data;
p->size = (UINT32)size;
@@ -819,7 +825,6 @@ void SV_FileSendTicker(void)
size_t size;
filetx_t *f;
INT32 packetsent, ram, i, j;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
if (!filestosend) // No file to send
return;
@@ -828,7 +833,6 @@ void SV_FileSendTicker(void)
netbuffer->packettype = PT_FILEFRAGMENT;
// (((sendbytes-nowsentbyte)*TICRATE)/(I_GetTime()-starttime)<(UINT32)net_bandwidth)
while (packetsent-- && filestosend != 0)
{
for (i = currentnode, j = 0; j < MAXNETNODES;
@@ -859,12 +863,8 @@ void SV_FileSendTicker(void)
if (!transferFiles[f->fileid].file)
{
CONS_Alert(CONS_ERROR, "Can't open file %s: %s\n",
I_Error("Can't open file %s: %s",
f->id.filename, strerror(errno));
SV_EndFileSend(i);
HSendPacket(i, true, 0, PT_SERVERREFUSE);
break;
}
}
@@ -948,7 +948,6 @@ void SV_FileSendTicker(void)
void Got_Filetxpak(void)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
INT32 filenum = netbuffer->u.filetxpak.fileid;
fileneeded_t *file = &fileneeded[filenum];
char *filename = file->filename;
@@ -970,7 +969,7 @@ void Got_Filetxpak(void)
if (filenum >= fileneedednum)
{
DEBFILE(va("filefragment not needed %d>%d\n", filenum, fileneedednum));
DEBFILE(va("fileframent not needed %d>%d\n", filenum, fileneedednum));
//I_Error("Received an unneeded file fragment (file id received: %d, file id needed: %d)\n", filenum, fileneedednum);
return;
}
@@ -991,7 +990,6 @@ void Got_Filetxpak(void)
{
UINT32 pos = LONG(netbuffer->u.filetxpak.position);
UINT16 size = SHORT(netbuffer->u.filetxpak.size);
// Use a special trick to know when the file is complete (not always used)
// WARNING: file fragments can arrive out of order so don't stop yet!
if (pos & 0x80000000)
@@ -1011,16 +1009,15 @@ void Got_Filetxpak(void)
fclose(file->file);
file->file = NULL;
file->status = FS_FOUND;
file->justdownloaded = true;
CONS_Printf(M_GetText("Downloading %s...(done)\n"),
filename);
#ifndef NONET
filedownload.completednum++;
filedownload.completedsize += file->totalsize;
downloadcompletednum++;
downloadcompletedsize += file->totalsize;
#endif
}
}
else if (!file->justdownloaded)
else
{
const char *s;
switch(file->status)
@@ -1043,7 +1040,6 @@ void Got_Filetxpak(void)
}
I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s);
}
// Send ack back quickly
if (++filetime == 3)
{
@@ -1052,7 +1048,7 @@ void Got_Filetxpak(void)
}
#ifdef CLIENT_LOADINGSCREEN
filedownload.current = filenum;
lastfilenum = filenum;
#endif
}
@@ -1201,7 +1197,9 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
#ifdef HAVE_CURL
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fwrite(ptr, size, nmemb, stream);
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}
#ifdef XFERINFOFUNCTION
@@ -1215,12 +1213,12 @@ static int curlprogress_callbackx(void *clientp, curl_off_t dltotal, curl_off_t
curtime = time(NULL);
curl_dlnow = (UINT32)dlnow;
curl_dltotal = (UINT32)dltotal;
curl_dlnow = dlnow;
curl_dltotal = dltotal;
if (curtime > curl_starttime)
{
getbytes = ((double)dlnow) / (curtime - curl_starttime); // To-do: Make this more accurate???
getbytes = curl_dlnow / (curtime - curl_starttime); // To-do: Make this more accurate???
}
else
{
@@ -1240,12 +1238,12 @@ static int curlprogress_callback(void *clientp, double dltotal, double dlnow, do
curtime = time(NULL);
curl_dlnow = (UINT32)dlnow;
curl_dltotal = (UINT32)dltotal;
curl_dlnow = dlnow;
curl_dltotal = dltotal;
if (curtime > curl_starttime)
{
getbytes = ((double)dlnow) / (curtime - curl_starttime); // To-do: Make this more accurate???
getbytes = curl_dlnow / (curtime - curl_starttime); // To-do: Make this more accurate???
}
else
{
@@ -1287,10 +1285,10 @@ void CURLPrepareFile(const char* url, int dfilenum)
curl_easy_setopt(http_handle, CURLOPT_URL, va("%s/%s", url, curl_realname));
// Only allow HTTP and HTTPS
#if (LIBCURL_VERSION_MAJOR <= 7) && (LIBCURL_VERSION_MINOR < 85)
curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
#else
#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 85, 0)
curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS_STR, "http,https");
#else
curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
#endif
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("SRB2Kart/v%d.%d", VERSION, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents.
@@ -1322,34 +1320,26 @@ void CURLPrepareFile(const char* url, int dfilenum)
#endif
curl_curfile->status = FS_DOWNLOADING;
lastfilenum = dfilenum;
curl_multi_add_handle(multi_handle, http_handle);
curl_multi_perform(multi_handle, &curl_runninghandles);
curl_starttime = time(NULL);
filedownload.current = dfilenum;
filedownload.http_running = true;
curl_running = true;
#ifdef HAVE_THREADS
I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL);
#endif
}
else
filedownload.http_running = false;
}
void CURLAbortFile(void)
{
filedownload.http_running = false;
// lock and unlock to wait for the download thread to exit
I_lock_mutex(&downloadmutex);
I_unlock_mutex(downloadmutex);
curl_running = false;
}
void CURLGetFile(void)
{
I_lock_mutex(&downloadmutex);
CURLMcode mc; /* return code used by curl_multi_wait() */
CURLcode easyres; /* Return from easy interface */
CURLMsg *m; /* for picking up messages with the transfer status */
@@ -1357,8 +1347,10 @@ void CURLGetFile(void)
int msgs_left; /* how many messages are left */
const char *easy_handle_error;
boolean running = true;
long response_code = 0;
static char *filename;
while (running && filedownload.http_running)
while (running && curl_running)
{
if (curl_runninghandles)
{
@@ -1385,13 +1377,11 @@ void CURLGetFile(void)
e = m->easy_handle;
easyres = m->data.result;
char *filename = Z_StrDup(curl_realname);
filename = Z_StrDup(curl_realname);
nameonly(filename);
if (easyres != CURLE_OK)
{
long response_code = 0;
if (easyres == CURLE_HTTP_RETURNED_ERROR)
curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code);
@@ -1399,7 +1389,7 @@ void CURLGetFile(void)
curl_curfile->status = FS_FALLBACK;
curl_curfile->currentsize = curl_origfilesize;
curl_curfile->totalsize = curl_origtotalfilesize;
filedownload.http_failed = true;
curl_failedwebdownload = true;
fclose(curl_curfile->file);
remove(curl_curfile->filename);
CONS_Printf(M_GetText("Failed to download %s (%s)\n"), filename, easy_handle_error);
@@ -1412,38 +1402,36 @@ void CURLGetFile(void)
{
CONS_Alert(CONS_ERROR, M_GetText("HTTP Download of %s finished but is corrupt or has been modified\n"), filename);
curl_curfile->status = FS_FALLBACK;
filedownload.http_failed = true;
curl_failedwebdownload = true;
}
else
{
CONS_Printf(M_GetText("Finished HTTP download of %s\n"), filename);
filedownload.completednum++;
filedownload.completedsize += curl_curfile->totalsize;
downloadcompletednum++;
downloadcompletedsize += curl_curfile->totalsize;
curl_curfile->status = FS_FOUND;
}
}
Z_Free(filename);
curl_curfile->file = NULL;
filedownload.remaining--;
curl_transfers--;
curl_multi_remove_handle(multi_handle, e);
curl_easy_cleanup(e);
if (!filedownload.remaining)
if (!curl_transfers)
break;
}
}
}
if (!filedownload.remaining || !filedownload.http_running)
if (!curl_transfers || !curl_running)
{
curl_multi_cleanup(multi_handle);
curl_global_cleanup();
multi_handle = NULL;
}
filedownload.http_running = false;
I_unlock_mutex(downloadmutex);
curl_running = false;
}
HTTP_login *
+8 -20
View File
@@ -13,7 +13,6 @@
#ifndef __D_NETFIL__
#define __D_NETFIL__
#include "d_clisrv.h"
#include "w_wad.h"
typedef enum
@@ -46,35 +45,24 @@ typedef struct
UINT32 currentsize;
UINT32 totalsize;
filestatus_t status; // The value returned by recsearch
boolean justdownloaded; // To prevent late fragments from causing an I_Error
} fileneeded_t;
extern INT32 fileneedednum;
extern fileneeded_t fileneeded[MAX_WADFILES];
extern char downloaddir[512];
typedef struct
{
#ifdef CLIENT_LOADINGSCREEN
INT32 current;
INT32 completednum;
UINT32 completedsize;
INT32 totalnum;
UINT32 totalsize;
extern INT32 lastfilenum;
extern INT32 downloadcompletednum;
extern UINT32 downloadcompletedsize;
extern INT32 totalfilesrequestednum;
extern UINT32 totalfilesrequestedsize;
#endif
#ifdef HAVE_CURL
INT32 remaining;
boolean http_failed;
boolean http_running;
char http_source[MAX_MIRROR_LENGTH+1];
#endif
} file_download_t;
extern file_download_t filedownload;
#ifdef HAVE_CURL
extern boolean curl_failedwebdownload;
extern boolean curl_running;
extern INT32 curl_transfers;
typedef struct HTTP_login HTTP_login;
+6 -20
View File
@@ -351,21 +351,10 @@ typedef enum
typedef enum
{
LAP_CUR,
LAP_BEST,
LAP_LAST,
LAP__MAX
} laptime_e;
// yes i made a whole struct for this :chonkbuncle:
typedef struct squishdance_s
{
tic_t countdown; // hold "custom 3" for 2 seconds to engange le dance
tic_t time;
fixed_t work;
fixed_t ang;
fixed_t bounce; // hehe squishy
} squishdance_t;
// ========================================================================
// PLAYER STRUCTURE
// ========================================================================
@@ -412,8 +401,9 @@ typedef struct player_s
INT32 kartstuff[NUMKARTSTUFF];
angle_t frameangle; // for the player add the ability to have the sprite only face other angles
angle_t old_frameangle, old_frameangle2;
// SRB2Kart CEP: Sliptide rolling
INT32 sliptidemem;
angle_t sliproll;
INT16 lturn_max[MAXPREDICTTICS]; // What's the expected turn value for full-left for a number of frames back (to account for netgame latency)?
@@ -423,6 +413,8 @@ typedef struct player_s
// See pflags_t, above.
pflags_t pflags;
UINT16 postimgflags;
// playing animation.
panim_t panim;
@@ -547,7 +539,6 @@ typedef struct player_s
INT32 awayviewtics;
angle_t awayviewaiming; // Used for cut-away view
boolean ingame;
boolean spectator;
UINT8 bot;
@@ -561,14 +552,9 @@ typedef struct player_s
UINT8 hitemvictim;
UINT8 splitscreenindex;
tic_t driftsparkGrowTimer;
fixed_t spinoutrot; // When a player spins out, this value increments modulus 360.
squishdance_t squishdance;
#ifdef HWRENDER
fixed_t fovadd; // adjust FOV for hw rendering
#endif
} player_t;
#endif
+8 -8
View File
@@ -17,8 +17,6 @@
#ifndef __D_THINK__
#define __D_THINK__
#include "doomdef.h"
#ifdef __GNUG__
#pragma interface
#endif
@@ -28,11 +26,18 @@
// To compile this as "ANSI C with classes" we will need to handle the various
// action functions cleanly.
//
typedef void (*actionf_v)();
typedef void (*actionf_p1)(void *);
typedef union
{
actionf_v acv;
actionf_p1 acp1;
} actionf_t;
// Historically, "think_t" is yet another function pointer to a routine
// to handle an actor.
typedef actionf_p1 think_t;
typedef actionf_t think_t;
// Doubly linked list of actors.
typedef struct thinker_s
@@ -44,11 +49,6 @@ typedef struct thinker_s
// killough 11/98: count of how many other objects reference
// this one using pointers. Used for garbage collection.
INT32 references;
boolean cachable;
#ifdef PARANOIA
INT32 debug_mobjtype;
tic_t debug_time;
#endif
} thinker_t;
#endif
+254 -349
View File
@@ -14,6 +14,7 @@
#include "d_main.h" // for srb2home
#include "g_game.h"
#include "sounds.h"
#include "info.h"
#include "d_think.h"
#include "m_argv.h"
#include "z_zone.h"
@@ -28,16 +29,16 @@
#include "p_local.h" // for var1 and var2, and some constants
#include "p_setup.h"
#include "r_data.h"
#include "r_fps.h"
#include "r_patch.h"
#include "r_sky.h"
#include "r_draw.h" // translation colormap consts (for lua)
#include "fastcmp.h"
#include "lua_script.h"
#include "lua_glib.h"
#include "lua_hook.h"
#include "d_clisrv.h"
#include "v_video.h" // video flags (for lua)
#include "lua_glib.h"
#include "lua_hook.h"
#include "lua_script.h"
#include "lua_libs.h"
@@ -47,14 +48,13 @@
// Free slot names
// The crazy word-reading stuff uses these.
char *FREE_STATES[NUMSTATEFREESLOTS];
char *FREE_MOBJS[NUMMOBJFREESLOTS];
UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
static char *FREE_STATES[NUMSTATEFREESLOTS];
static char *FREE_MOBJS[NUMMOBJFREESLOTS];
static UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
#define initfreeslots() {\
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
}
// Crazy word-reading stuff
@@ -690,20 +690,6 @@ static const struct {
{NULL, 0}
};
static mapheader_lighting_t *usemaplighting(INT32 mapnum, const char *word)
{
if (fastncmp(word, "ENCORE", 6))
{
mapheaderinfo[mapnum]->use_encore_lighting = true;
return &mapheaderinfo[mapnum]->lighting_encore;
}
else
{
return &mapheaderinfo[mapnum]->lighting;
}
}
static void readlevelheader(MYFILE *f, INT32 num, INT32 wadnum)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
@@ -997,35 +983,6 @@ static void readlevelheader(MYFILE *f, INT32 num, INT32 wadnum)
}*/
else if (fastcmp(word, "MOBJSCALE"))
mapheaderinfo[num-1]->mobj_scale = get_number(word2);
else if (fastcmp(word, "LIGHTCONTRAST") || fastcmp(word, "ENCORELIGHTCONTRAST"))
{
mapheader_lighting_t *lighting = usemaplighting(num-1, word);
lighting->light_contrast = (UINT8)i;
lighting->use_custom_light = true;
}
else if (fastcmp(word, "SPRITEBACKLIGHT") || fastcmp(word, "ENCORESPRITEBACKLIGHT"))
{
mapheader_lighting_t *lighting = usemaplighting(num-1, word);
lighting->sprite_backlight = (SINT8)i;
lighting->use_custom_light = true;
}
else if (fastcmp(word, "LIGHTANGLE") || fastcmp(word, "ENCORELIGHTANGLE"))
{
mapheader_lighting_t *lighting = usemaplighting(num-1, word);
if (fastcmp(word2, "EVEN"))
{
lighting->use_light_angle = false;
lighting->light_angle = 0;
}
else
{
lighting->use_light_angle = true;
lighting->light_angle = FixedAngle(FloatToFixed(atof(word2)));
}
lighting->use_custom_light = true;
}
// Individual triggers for level flags, for ease of use (and 2.0 compatibility)
else if (fastcmp(word, "SCRIPTISFILE"))
@@ -1070,13 +1027,6 @@ static void readlevelheader(MYFILE *f, INT32 num, INT32 wadnum)
else
mapheaderinfo[num-1]->levelflags &= ~LF_SECTIONRACE;
}
else if (fastcmp(word, "SUBTRACTNUM"))
{
if (i || word2[0] == 'T' || word2[0] == 'Y')
mapheaderinfo[num-1]->levelflags |= LF_SUBTRACTNUM;
else
mapheaderinfo[num-1]->levelflags &= ~LF_SUBTRACTNUM;
}
// Individual triggers for menu flags
else if (fastcmp(word, "HIDDEN"))
@@ -1423,212 +1373,214 @@ static void readhuditem(MYFILE *f, INT32 num)
// DO NOT FORGET TO SYNC THIS LIST WITH THE ACTIONNUM ENUM IN INFO.H
actionpointer_t actionpointers[] =
{
{A_Explode, "A_EXPLODE"},
{A_Pain, "A_PAIN"},
{A_Fall, "A_FALL"},
{A_MonitorPop, "A_MONITORPOP"},
{A_Look, "A_LOOK"},
{A_Chase, "A_CHASE"},
{A_FaceStabChase, "A_FACESTABCHASE"},
{A_FaceTarget, "A_FACETARGET"},
{A_FaceTracer, "A_FACETRACER"},
{A_Scream, "A_SCREAM"},
{A_BossDeath, "A_BOSSDEATH"},
{A_CustomPower, "A_CUSTOMPOWER"},
{A_GiveWeapon, "A_GIVEWEAPON"},
{A_RingShield, "A_RINGSHIELD"},
{A_RingBox, "A_RINGBOX"},
{A_Invincibility, "A_INVINCIBILITY"},
{A_SuperSneakers, "A_SUPERSNEAKERS"},
{A_BunnyHop, "A_BUNNYHOP"},
{A_BubbleSpawn, "A_BUBBLESPAWN"},
{A_FanBubbleSpawn, "A_FANBUBBLESPAWN"},
{A_BubbleRise, "A_BUBBLERISE"},
{A_BubbleCheck, "A_BUBBLECHECK"},
{A_AwardScore, "A_AWARDSCORE"},
{A_ExtraLife, "A_EXTRALIFE"},
{A_BombShield, "A_BOMBSHIELD"},
{A_JumpShield, "A_JUMPSHIELD"},
{A_WaterShield, "A_WATERSHIELD"},
{A_ForceShield, "A_FORCESHIELD"},
{A_PityShield, "A_PITYSHIELD"},
{A_GravityBox, "A_GRAVITYBOX"},
{A_ScoreRise, "A_SCORERISE"},
{A_ParticleSpawn, "A_PARTICLESPAWN"},
{A_AttractChase, "A_ATTRACTCHASE"},
{A_DropMine, "A_DROPMINE"},
{A_FishJump, "A_FISHJUMP"},
{A_ThrownRing, "A_THROWNRING"},
{A_GrenadeRing, "A_GRENADERING"}, // SRB2kart
{A_SetSolidSteam, "A_SETSOLIDSTEAM"},
{A_UnsetSolidSteam, "A_UNSETSOLIDSTEAM"},
{A_SignPlayer, "A_SIGNPLAYER"},
{A_OverlayThink, "A_OVERLAYTHINK"},
{A_JetChase, "A_JETCHASE"},
{A_JetbThink, "A_JETBTHINK"},
{A_JetgThink, "A_JETGTHINK"},
{A_JetgShoot, "A_JETGSHOOT"},
{A_ShootBullet, "A_SHOOTBULLET"},
{A_MinusDigging, "A_MINUSDIGGING"},
{A_MinusPopup, "A_MINUSPOPUP"},
{A_MinusCheck, "A_MINUSCHECK"},
{A_ChickenCheck, "A_CHICKENCHECK"},
{A_MouseThink, "A_MOUSETHINK"},
{A_DetonChase, "A_DETONCHASE"},
{A_CapeChase, "A_CAPECHASE"},
{A_RotateSpikeBall, "A_ROTATESPIKEBALL"},
{A_SlingAppear, "A_SLINGAPPEAR"},
{A_MaceRotate, "A_MACEROTATE"},
{A_UnidusBall, "A_UNIDUSBALL"},
{A_RockSpawn, "A_ROCKSPAWN"},
{A_SetFuse, "A_SETFUSE"},
{A_CrawlaCommanderThink, "A_CRAWLACOMMANDERTHINK"},
{A_SmokeTrailer, "A_SMOKETRAILER"},
{A_RingExplode, "A_RINGEXPLODE"},
{A_OldRingExplode, "A_OLDRINGEXPLODE"},
{A_MixUp, "A_MIXUP"},
{A_RecyclePowers, "A_RECYCLEPOWERS"},
{A_Boss1Chase, "A_BOSS1CHASE"},
{A_FocusTarget, "A_FOCUSTARGET"},
{A_Boss2Chase, "A_BOSS2CHASE"},
{A_Boss2Pogo, "A_BOSS2POGO"},
{A_BossZoom, "A_BOSSZOOM"},
{A_BossScream, "A_BOSSSCREAM"},
{A_Boss2TakeDamage, "A_BOSS2TAKEDAMAGE"},
{A_Boss7Chase, "A_BOSS7CHASE"},
{A_GoopSplat, "A_GOOPSPLAT"},
{A_Boss2PogoSFX, "A_BOSS2POGOSFX"},
{A_Boss2PogoTarget, "A_BOSS2POGOTARGET"},
{A_BossJetFume, "A_BOSSJETFUME"},
{A_EggmanBox, "A_EGGMANBOX"},
{A_TurretFire, "A_TURRETFIRE"},
{A_SuperTurretFire, "A_SUPERTURRETFIRE"},
{A_TurretStop, "A_TURRETSTOP"},
{A_JetJawRoam, "A_JETJAWROAM"},
{A_JetJawChomp, "A_JETJAWCHOMP"},
{A_PointyThink, "A_POINTYTHINK"},
{A_CheckBuddy, "A_CHECKBUDDY"},
{A_HoodThink, "A_HOODTHINK"},
{A_ArrowCheck, "A_ARROWCHECK"},
{A_SnailerThink, "A_SNAILERTHINK"},
{A_SharpChase, "A_SHARPCHASE"},
{A_SharpSpin, "A_SHARPSPIN"},
{A_VultureVtol, "A_VULTUREVTOL"},
{A_VultureCheck, "A_VULTURECHECK"},
{A_SkimChase, "A_SKIMCHASE"},
{A_1upThinker, "A_1UPTHINKER"},
{A_SkullAttack, "A_SKULLATTACK"},
{A_LobShot, "A_LOBSHOT"},
{A_FireShot, "A_FIRESHOT"},
{A_SuperFireShot, "A_SUPERFIRESHOT"},
{A_BossFireShot, "A_BOSSFIRESHOT"},
{A_Boss7FireMissiles, "A_BOSS7FIREMISSILES"},
{A_Boss1Laser, "A_BOSS1LASER"},
{A_Boss4Reverse, "A_BOSS4REVERSE"},
{A_Boss4SpeedUp, "A_BOSS4SPEEDUP"},
{A_Boss4Raise, "A_BOSS4RAISE"},
{A_SparkFollow, "A_SPARKFOLLOW"},
{A_BuzzFly, "A_BUZZFLY"},
{A_GuardChase, "A_GUARDCHASE"},
{A_EggShield, "A_EGGSHIELD"},
{A_SetReactionTime, "A_SETREACTIONTIME"},
{A_Boss1Spikeballs, "A_BOSS1SPIKEBALLS"},
{A_Boss3TakeDamage, "A_BOSS3TAKEDAMAGE"},
{A_Boss3Path, "A_BOSS3PATH"},
{A_LinedefExecute, "A_LINEDEFEXECUTE"},
{A_PlaySeeSound, "A_PLAYSEESOUND"},
{A_PlayAttackSound, "A_PLAYATTACKSOUND"},
{A_PlayActiveSound, "A_PLAYACTIVESOUND"},
{A_SpawnObjectAbsolute, "A_SPAWNOBJECTABSOLUTE"},
{A_SpawnObjectRelative, "A_SPAWNOBJECTRELATIVE"},
{A_ChangeAngleRelative, "A_CHANGEANGLERELATIVE"},
{A_ChangeAngleAbsolute, "A_CHANGEANGLEABSOLUTE"},
{A_PlaySound, "A_PLAYSOUND"},
{A_FindTarget, "A_FINDTARGET"},
{A_FindTracer, "A_FINDTRACER"},
{A_SetTics, "A_SETTICS"},
{A_SetRandomTics, "A_SETRANDOMTICS"},
{A_ChangeColorRelative, "A_CHANGECOLORRELATIVE"},
{A_ChangeColorAbsolute, "A_CHANGECOLORABSOLUTE"},
{A_MoveRelative, "A_MOVERELATIVE"},
{A_MoveAbsolute, "A_MOVEABSOLUTE"},
{A_Thrust, "A_THRUST"},
{A_ZThrust, "A_ZTHRUST"},
{A_SetTargetsTarget, "A_SETTARGETSTARGET"},
{A_SetObjectFlags, "A_SETOBJECTFLAGS"},
{A_SetObjectFlags2, "A_SETOBJECTFLAGS2"},
{A_RandomState, "A_RANDOMSTATE"},
{A_RandomStateRange, "A_RANDOMSTATERANGE"},
{A_DualAction, "A_DUALACTION"},
{A_RemoteAction, "A_REMOTEACTION"},
{A_ToggleFlameJet, "A_TOGGLEFLAMEJET"},
{A_ItemPop, "A_ITEMPOP"}, // SRB2kart
{A_JawzChase, "A_JAWZCHASE"}, // SRB2kart
{A_JawzExplode, "A_JAWZEXPLODE"}, // SRB2kart
{A_SPBChase, "A_SPBCHASE"}, // SRB2kart
{A_MineExplode, "A_MINEEXPLODE"}, // SRB2kart
{A_BallhogExplode, "A_BALLHOGEXPLODE"}, // SRB2kart
{A_LightningFollowPlayer,"A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart
{A_FZBoomFlash, "A_FZBOOMFLASH"}, //SRB2kart
{A_FZBoomSmoke, "A_FZBOOMSMOKE"}, //SRB2kart
{A_RandomShadowFrame, "A_RANDOMSHADOWFRAME"}, //SRB2kart
{A_RoamingShadowThinker, "A_ROAMINGSHADOWTHINKER"}, //SRB2kart
{A_MayonakaArrow, "A_MAYONAKAARROW"}, //SRB2kart
{A_ReaperThinker, "A_REAPERTHINKER"}, //SRB2kart
{A_MementosTPParticles, "A_MEMENTOSTPPARTICLES"}, //SRB2kart
{A_FlameParticle, "A_FLAMEPARTICLE"}, // SRB2kart
{A_OrbitNights, "A_ORBITNIGHTS"},
{A_GhostMe, "A_GHOSTME"},
{A_SetObjectState, "A_SETOBJECTSTATE"},
{A_SetObjectTypeState, "A_SETOBJECTTYPESTATE"},
{A_KnockBack, "A_KNOCKBACK"},
{A_PushAway, "A_PUSHAWAY"},
{A_RingDrain, "A_RINGDRAIN"},
{A_SplitShot, "A_SPLITSHOT"},
{A_MissileSplit, "A_MISSILESPLIT"},
{A_MultiShot, "A_MULTISHOT"},
{A_InstaLoop, "A_INSTALOOP"},
{A_Custom3DRotate, "A_CUSTOM3DROTATE"},
{A_SearchForPlayers, "A_SEARCHFORPLAYERS"},
{A_CheckRandom, "A_CHECKRANDOM"},
{A_CheckTargetRings, "A_CHECKTARGETRINGS"},
{A_CheckRings, "A_CHECKRINGS"},
{A_CheckTotalRings, "A_CHECKTOTALRINGS"},
{A_CheckHealth, "A_CHECKHEALTH"},
{A_CheckRange, "A_CHECKRANGE"},
{A_CheckHeight, "A_CHECKHEIGHT"},
{A_CheckTrueRange, "A_CHECKTRUERANGE"},
{A_CheckThingCount, "A_CHECKTHINGCOUNT"},
{A_CheckAmbush, "A_CHECKAMBUSH"},
{A_CheckCustomValue, "A_CHECKCUSTOMVALUE"},
{A_CheckCusValMemo, "A_CHECKCUSVALMEMO"},
{A_SetCustomValue, "A_SETCUSTOMVALUE"},
{A_UseCusValMemo, "A_USECUSVALMEMO"},
{A_RelayCustomValue, "A_RELAYCUSTOMVALUE"},
{A_CusValAction, "A_CUSVALACTION"},
{A_ForceStop, "A_FORCESTOP"},
{A_ForceWin, "A_FORCEWIN"},
{A_SpikeRetract, "A_SPIKERETRACT"},
{A_InfoState, "A_INFOSTATE"},
{A_Repeat, "A_REPEAT"},
{A_SetScale, "A_SETSCALE"},
{A_RemoteDamage, "A_REMOTEDAMAGE"},
{A_HomingChase, "A_HOMINGCHASE"},
{A_TrapShot, "A_TRAPSHOT"},
{A_VileTarget, "A_VILETARGET"},
{A_VileAttack, "A_VILEATTACK"},
{A_VileFire, "A_VILEFIRE"},
{A_BrakChase, "A_BRAKCHASE"},
{A_BrakFireShot, "A_BRAKFIRESHOT"},
{A_BrakLobShot, "A_BRAKLOBSHOT"},
{A_NapalmScatter, "A_NAPALMSCATTER"},
{A_SpawnFreshCopy, "A_SPAWNFRESHCOPY"},
//{A_InvincSparkleRotate, "A_INVINCSPARKLEROTATE"},
{{A_Explode}, "A_EXPLODE"},
{{A_Pain}, "A_PAIN"},
{{A_Fall}, "A_FALL"},
{{A_MonitorPop}, "A_MONITORPOP"},
{{A_Look}, "A_LOOK"},
{{A_Chase}, "A_CHASE"},
{{A_FaceStabChase}, "A_FACESTABCHASE"},
{{A_FaceTarget}, "A_FACETARGET"},
{{A_FaceTracer}, "A_FACETRACER"},
{{A_Scream}, "A_SCREAM"},
{{A_BossDeath}, "A_BOSSDEATH"},
{{A_CustomPower}, "A_CUSTOMPOWER"},
{{A_GiveWeapon}, "A_GIVEWEAPON"},
{{A_RingShield}, "A_RINGSHIELD"},
{{A_RingBox}, "A_RINGBOX"},
{{A_Invincibility}, "A_INVINCIBILITY"},
{{A_SuperSneakers}, "A_SUPERSNEAKERS"},
{{A_BunnyHop}, "A_BUNNYHOP"},
{{A_BubbleSpawn}, "A_BUBBLESPAWN"},
{{A_FanBubbleSpawn}, "A_FANBUBBLESPAWN"},
{{A_BubbleRise}, "A_BUBBLERISE"},
{{A_BubbleCheck}, "A_BUBBLECHECK"},
{{A_AwardScore}, "A_AWARDSCORE"},
{{A_ExtraLife}, "A_EXTRALIFE"},
{{A_BombShield}, "A_BOMBSHIELD"},
{{A_JumpShield}, "A_JUMPSHIELD"},
{{A_WaterShield}, "A_WATERSHIELD"},
{{A_ForceShield}, "A_FORCESHIELD"},
{{A_PityShield}, "A_PITYSHIELD"},
{{A_GravityBox}, "A_GRAVITYBOX"},
{{A_ScoreRise}, "A_SCORERISE"},
{{A_ParticleSpawn}, "A_PARTICLESPAWN"},
{{A_AttractChase}, "A_ATTRACTCHASE"},
{{A_DropMine}, "A_DROPMINE"},
{{A_FishJump}, "A_FISHJUMP"},
{{A_ThrownRing}, "A_THROWNRING"},
{{A_GrenadeRing}, "A_GRENADERING"}, // SRB2kart
{{A_SetSolidSteam}, "A_SETSOLIDSTEAM"},
{{A_UnsetSolidSteam}, "A_UNSETSOLIDSTEAM"},
{{A_SignPlayer}, "A_SIGNPLAYER"},
{{A_OverlayThink}, "A_OVERLAYTHINK"},
{{A_JetChase}, "A_JETCHASE"},
{{A_JetbThink}, "A_JETBTHINK"},
{{A_JetgThink}, "A_JETGTHINK"},
{{A_JetgShoot}, "A_JETGSHOOT"},
{{A_ShootBullet}, "A_SHOOTBULLET"},
{{A_MinusDigging}, "A_MINUSDIGGING"},
{{A_MinusPopup}, "A_MINUSPOPUP"},
{{A_MinusCheck}, "A_MINUSCHECK"},
{{A_ChickenCheck}, "A_CHICKENCHECK"},
{{A_MouseThink}, "A_MOUSETHINK"},
{{A_DetonChase}, "A_DETONCHASE"},
{{A_CapeChase}, "A_CAPECHASE"},
{{A_RotateSpikeBall}, "A_ROTATESPIKEBALL"},
{{A_SlingAppear}, "A_SLINGAPPEAR"},
{{A_MaceRotate}, "A_MACEROTATE"},
{{A_UnidusBall}, "A_UNIDUSBALL"},
{{A_RockSpawn}, "A_ROCKSPAWN"},
{{A_SetFuse}, "A_SETFUSE"},
{{A_CrawlaCommanderThink}, "A_CRAWLACOMMANDERTHINK"},
{{A_SmokeTrailer}, "A_SMOKETRAILER"},
{{A_RingExplode}, "A_RINGEXPLODE"},
{{A_OldRingExplode}, "A_OLDRINGEXPLODE"},
{{A_MixUp}, "A_MIXUP"},
{{A_RecyclePowers}, "A_RECYCLEPOWERS"},
{{A_Boss1Chase}, "A_BOSS1CHASE"},
{{A_FocusTarget}, "A_FOCUSTARGET"},
{{A_Boss2Chase}, "A_BOSS2CHASE"},
{{A_Boss2Pogo}, "A_BOSS2POGO"},
{{A_BossZoom}, "A_BOSSZOOM"},
{{A_BossScream}, "A_BOSSSCREAM"},
{{A_Boss2TakeDamage}, "A_BOSS2TAKEDAMAGE"},
{{A_Boss7Chase}, "A_BOSS7CHASE"},
{{A_GoopSplat}, "A_GOOPSPLAT"},
{{A_Boss2PogoSFX}, "A_BOSS2POGOSFX"},
{{A_Boss2PogoTarget}, "A_BOSS2POGOTARGET"},
{{A_BossJetFume}, "A_BOSSJETFUME"},
{{A_EggmanBox}, "A_EGGMANBOX"},
{{A_TurretFire}, "A_TURRETFIRE"},
{{A_SuperTurretFire}, "A_SUPERTURRETFIRE"},
{{A_TurretStop}, "A_TURRETSTOP"},
{{A_JetJawRoam}, "A_JETJAWROAM"},
{{A_JetJawChomp}, "A_JETJAWCHOMP"},
{{A_PointyThink}, "A_POINTYTHINK"},
{{A_CheckBuddy}, "A_CHECKBUDDY"},
{{A_HoodThink}, "A_HOODTHINK"},
{{A_ArrowCheck}, "A_ARROWCHECK"},
{{A_SnailerThink}, "A_SNAILERTHINK"},
{{A_SharpChase}, "A_SHARPCHASE"},
{{A_SharpSpin}, "A_SHARPSPIN"},
{{A_VultureVtol}, "A_VULTUREVTOL"},
{{A_VultureCheck}, "A_VULTURECHECK"},
{{A_SkimChase}, "A_SKIMCHASE"},
{{A_1upThinker}, "A_1UPTHINKER"},
{{A_SkullAttack}, "A_SKULLATTACK"},
{{A_LobShot}, "A_LOBSHOT"},
{{A_FireShot}, "A_FIRESHOT"},
{{A_SuperFireShot}, "A_SUPERFIRESHOT"},
{{A_BossFireShot}, "A_BOSSFIRESHOT"},
{{A_Boss7FireMissiles}, "A_BOSS7FIREMISSILES"},
{{A_Boss1Laser}, "A_BOSS1LASER"},
{{A_Boss4Reverse}, "A_BOSS4REVERSE"},
{{A_Boss4SpeedUp}, "A_BOSS4SPEEDUP"},
{{A_Boss4Raise}, "A_BOSS4RAISE"},
{{A_SparkFollow}, "A_SPARKFOLLOW"},
{{A_BuzzFly}, "A_BUZZFLY"},
{{A_GuardChase}, "A_GUARDCHASE"},
{{A_EggShield}, "A_EGGSHIELD"},
{{A_SetReactionTime}, "A_SETREACTIONTIME"},
{{A_Boss1Spikeballs}, "A_BOSS1SPIKEBALLS"},
{{A_Boss3TakeDamage}, "A_BOSS3TAKEDAMAGE"},
{{A_Boss3Path}, "A_BOSS3PATH"},
{{A_LinedefExecute}, "A_LINEDEFEXECUTE"},
{{A_PlaySeeSound}, "A_PLAYSEESOUND"},
{{A_PlayAttackSound}, "A_PLAYATTACKSOUND"},
{{A_PlayActiveSound}, "A_PLAYACTIVESOUND"},
{{A_SpawnObjectAbsolute}, "A_SPAWNOBJECTABSOLUTE"},
{{A_SpawnObjectRelative}, "A_SPAWNOBJECTRELATIVE"},
{{A_ChangeAngleRelative}, "A_CHANGEANGLERELATIVE"},
{{A_ChangeAngleAbsolute}, "A_CHANGEANGLEABSOLUTE"},
{{A_RollAngle}, "A_ROLLANGLE"},
{{A_ChangeRollAngleRelative},"A_CHANGEROLLANGLERELATIVE"},
{{A_ChangeRollAngleAbsolute},"A_CHANGEROLLANGLEABSOLUTE"},
{{A_PlaySound}, "A_PLAYSOUND"},
{{A_FindTarget}, "A_FINDTARGET"},
{{A_FindTracer}, "A_FINDTRACER"},
{{A_SetTics}, "A_SETTICS"},
{{A_SetRandomTics}, "A_SETRANDOMTICS"},
{{A_ChangeColorRelative}, "A_CHANGECOLORRELATIVE"},
{{A_ChangeColorAbsolute}, "A_CHANGECOLORABSOLUTE"},
{{A_MoveRelative}, "A_MOVERELATIVE"},
{{A_MoveAbsolute}, "A_MOVEABSOLUTE"},
{{A_Thrust}, "A_THRUST"},
{{A_ZThrust}, "A_ZTHRUST"},
{{A_SetTargetsTarget}, "A_SETTARGETSTARGET"},
{{A_SetObjectFlags}, "A_SETOBJECTFLAGS"},
{{A_SetObjectFlags2}, "A_SETOBJECTFLAGS2"},
{{A_RandomState}, "A_RANDOMSTATE"},
{{A_RandomStateRange}, "A_RANDOMSTATERANGE"},
{{A_DualAction}, "A_DUALACTION"},
{{A_RemoteAction}, "A_REMOTEACTION"},
{{A_ToggleFlameJet}, "A_TOGGLEFLAMEJET"},
{{A_ItemPop}, "A_ITEMPOP"}, // SRB2kart
{{A_JawzChase}, "A_JAWZCHASE"}, // SRB2kart
{{A_JawzExplode}, "A_JAWZEXPLODE"}, // SRB2kart
{{A_SPBChase}, "A_SPBCHASE"}, // SRB2kart
{{A_MineExplode}, "A_MINEEXPLODE"}, // SRB2kart
{{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, // SRB2kart
{{A_LightningFollowPlayer},"A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart
{{A_FZBoomFlash}, "A_FZBOOMFLASH"}, //SRB2kart
{{A_FZBoomSmoke}, "A_FZBOOMSMOKE"}, //SRB2kart
{{A_RandomShadowFrame}, "A_RANDOMSHADOWFRAME"}, //SRB2kart
{{A_RoamingShadowThinker}, "A_ROAMINGSHADOWTHINKER"}, //SRB2kart
{{A_MayonakaArrow}, "A_MAYONAKAARROW"}, //SRB2kart
{{A_ReaperThinker}, "A_REAPERTHINKER"}, //SRB2kart
{{A_MementosTPParticles}, "A_MEMENTOSTPPARTICLES"}, //SRB2kart
{{A_FlameParticle}, "A_FLAMEPARTICLE"}, // SRB2kart
{{A_OrbitNights}, "A_ORBITNIGHTS"},
{{A_GhostMe}, "A_GHOSTME"},
{{A_SetObjectState}, "A_SETOBJECTSTATE"},
{{A_SetObjectTypeState}, "A_SETOBJECTTYPESTATE"},
{{A_KnockBack}, "A_KNOCKBACK"},
{{A_PushAway}, "A_PUSHAWAY"},
{{A_RingDrain}, "A_RINGDRAIN"},
{{A_SplitShot}, "A_SPLITSHOT"},
{{A_MissileSplit}, "A_MISSILESPLIT"},
{{A_MultiShot}, "A_MULTISHOT"},
{{A_InstaLoop}, "A_INSTALOOP"},
{{A_Custom3DRotate}, "A_CUSTOM3DROTATE"},
{{A_SearchForPlayers}, "A_SEARCHFORPLAYERS"},
{{A_CheckRandom}, "A_CHECKRANDOM"},
{{A_CheckTargetRings}, "A_CHECKTARGETRINGS"},
{{A_CheckRings}, "A_CHECKRINGS"},
{{A_CheckTotalRings}, "A_CHECKTOTALRINGS"},
{{A_CheckHealth}, "A_CHECKHEALTH"},
{{A_CheckRange}, "A_CHECKRANGE"},
{{A_CheckHeight}, "A_CHECKHEIGHT"},
{{A_CheckTrueRange}, "A_CHECKTRUERANGE"},
{{A_CheckThingCount}, "A_CHECKTHINGCOUNT"},
{{A_CheckAmbush}, "A_CHECKAMBUSH"},
{{A_CheckCustomValue}, "A_CHECKCUSTOMVALUE"},
{{A_CheckCusValMemo}, "A_CHECKCUSVALMEMO"},
{{A_SetCustomValue}, "A_SETCUSTOMVALUE"},
{{A_UseCusValMemo}, "A_USECUSVALMEMO"},
{{A_RelayCustomValue}, "A_RELAYCUSTOMVALUE"},
{{A_CusValAction}, "A_CUSVALACTION"},
{{A_ForceStop}, "A_FORCESTOP"},
{{A_ForceWin}, "A_FORCEWIN"},
{{A_SpikeRetract}, "A_SPIKERETRACT"},
{{A_InfoState}, "A_INFOSTATE"},
{{A_Repeat}, "A_REPEAT"},
{{A_SetScale}, "A_SETSCALE"},
{{A_RemoteDamage}, "A_REMOTEDAMAGE"},
{{A_HomingChase}, "A_HOMINGCHASE"},
{{A_TrapShot}, "A_TRAPSHOT"},
{{A_VileTarget}, "A_VILETARGET"},
{{A_VileAttack}, "A_VILEATTACK"},
{{A_VileFire}, "A_VILEFIRE"},
{{A_BrakChase}, "A_BRAKCHASE"},
{{A_BrakFireShot}, "A_BRAKFIRESHOT"},
{{A_BrakLobShot}, "A_BRAKLOBSHOT"},
{{A_NapalmScatter}, "A_NAPALMSCATTER"},
{{A_SpawnFreshCopy}, "A_SPAWNFRESHCOPY"},
{NULL, "NONE"},
{{NULL}, "NONE"},
// This NULL entry must be the last in the list
{NULL, NULL},
{{NULL}, NULL},
};
static void readframe(MYFILE *f, INT32 num)
@@ -1710,7 +1662,7 @@ static void readframe(MYFILE *f, INT32 num)
for (z = 0; actionpointers[z].name; z++)
{
if (actionpointers[z].action == states[num].action)
if (actionpointers[z].action.acv == states[num].action.acv)
{
break;
}
@@ -1719,17 +1671,17 @@ static void readframe(MYFILE *f, INT32 num)
z = 0;
found = LUA_SetLuaAction(&states[num], actiontocompare);
if (!found)
while (actionpointers[z].name)
{
while (actionpointers[z].name)
if (fastcmp(actiontocompare, actionpointers[z].name))
{
if (fastcmp(actiontocompare, actionpointers[z].name))
{
states[num].action = actionpointers[z].action;
found = true;
break;
}
z++;
states[num].action = actionpointers[z].action;
states[num].action.acv = actionpointers[z].action.acv; // assign
states[num].action.acp1 = actionpointers[z].action.acp1;
found = true;
break;
}
z++;
}
if (!found)
@@ -1807,7 +1759,7 @@ static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[])
* \sa readmaincfg()
* \author Graue <graue@oceanbase.org>
*/
/*static boolean GoodDataFileName(const char *s)
static boolean GoodDataFileName(const char *s)
{
const char *p;
const char *tail = ".dat";
@@ -1827,7 +1779,7 @@ static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[])
if (fasticmp(s, "online.dat")) return false; // SRB2Kart online replay folder
return true;
}*/
}
static void reademblemdata(MYFILE *f, INT32 num)
{
@@ -2605,10 +2557,10 @@ static void readmaincfg(MYFILE *f)
{
maxXtraLife = (UINT8)get_number(word2);
}
else if (fastcmp(word, "GAMEDATA"))
{
// just ignore it but dont throw a warning
/*size_t filenamelen;
size_t filenamelen;
// Check the data filename so that mods
// can't write arbitrary files.
@@ -2632,7 +2584,7 @@ static void readmaincfg(MYFILE *f)
// can't use sprintf since there is %u in savegamename
strcatbf(savegamename, srb2home, PATHSEP);
refreshdirmenu |= REFRESHDIR_GAMEDATA;*/
refreshdirmenu |= REFRESHDIR_GAMEDATA;
}
else if (fastcmp(word, "RESETDATA"))
{
@@ -3198,7 +3150,7 @@ void DEH_LoadDehackedLump(lumpnum_t lumpnum)
// RegEx to generate this from info.h: ^\tS_([^,]+), --> \t"S_\1",
// I am leaving the prefixes solely for clarity to programmers,
// because sadly no one remembers this place while searching for full state names.
const char *const STATE_LIST[] = { // array length left dynamic for sanity testing later.
static const char *const STATE_LIST[] = { // array length left dynamic for sanity testing later.
"S_NULL",
"S_UNKNOWN",
"S_INVISIBLE", // state for invisible sprite
@@ -6412,7 +6364,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
// I am leaving the prefixes solely for clarity to programmers,
// because sadly no one remembers this place while searching for full state names.
const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity testing later.
static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity testing later.
"MT_NULL",
"MT_UNKNOWN",
@@ -7203,7 +7155,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
#endif
};
const char *const MOBJFLAG_LIST[] = {
static const char *const MOBJFLAG_LIST[] = {
"SPECIAL",
"SOLID",
"SHOOTABLE",
@@ -7239,7 +7191,7 @@ const char *const MOBJFLAG_LIST[] = {
};
// \tMF2_(\S+).*// (.+) --> \t"\1", // \2
const char *const MOBJFLAG2_LIST[] = {
static const char *const MOBJFLAG2_LIST[] = {
"AXIS", // It's a NiGHTS axis! (For faster checking)
"TWOD", // Moves like it's in a 2D level
"DONTRESPAWN", // Don't respawn this object!
@@ -7272,7 +7224,7 @@ const char *const MOBJFLAG2_LIST[] = {
NULL
};
const char *const MOBJEFLAG_LIST[] = {
static const char *const MOBJEFLAG_LIST[] = {
"ONGROUND", // The mobj stands on solid floor (not on another mobj or in air)
"JUSTHITFLOOR", // The mobj just hit the floor while falling, this is cleared on next frame
"TOUCHWATER", // The mobj stands in a sector with water, and touches the surface
@@ -7290,14 +7242,14 @@ const char *const MOBJEFLAG_LIST[] = {
NULL
};
const char *const MAPTHINGFLAG_LIST[4] = {
static const char *const MAPTHINGFLAG_LIST[4] = {
NULL,
"OBJECTFLIP", // Reverse gravity flag for objects.
"OBJECTSPECIAL", // Special flag used with certain objects.
"AMBUSH" // Deaf monsters/do not react to sound.
};
const char *const PLAYERFLAG_LIST[] = {
static const char *const PLAYERFLAG_LIST[] = {
// Flip camera angle with gravity flip prefrence.
"FLIPCAM",
@@ -7369,7 +7321,7 @@ const char *const PLAYERFLAG_LIST[] = {
};
// Linedef flags
const char *const ML_LIST[16] = {
static const char *const ML_LIST[16] = {
"IMPASSIBLE",
"BLOCKMONSTERS",
"TWOSIDED",
@@ -7390,7 +7342,7 @@ const char *const ML_LIST[16] = {
// This DOES differ from r_draw's Color_Names, unfortunately.
// Also includes Super colors
const char *COLOR_ENUMS[] = { // Rejigged for Kart.
static const char *COLOR_ENUMS[] = { // Rejigged for Kart.
"NONE", // SKINCOLOR_NONE
"WHITE", // SKINCOLOR_WHITE
"SILVER", // SKINCOLOR_SILVER
@@ -7558,7 +7510,7 @@ const char *COLOR_ENUMS[] = { // Rejigged for Kart.
"CSUPER5" // SKINCOLOR_CSUPER5,
};
const char *const POWERS_LIST[] = {
static const char *const POWERS_LIST[] = {
"INVULNERABILITY",
"SNEAKERS",
"FLASHING",
@@ -7593,7 +7545,7 @@ const char *const POWERS_LIST[] = {
"INGOOP" // In goop
};
const char *const KARTSTUFF_LIST[] = {
static const char *const KARTSTUFF_LIST[] = {
"POSITION",
"OLDPOSITION",
"POSITIONDELAY",
@@ -7680,7 +7632,7 @@ const char *const KARTSTUFF_LIST[] = {
"GROWCANCEL"
};
const char *const HUDITEMS_LIST[] = {
static const char *const HUDITEMS_LIST[] = {
"LIVESNAME",
"LIVESPIC",
"LIVESNUM",
@@ -7769,18 +7721,7 @@ struct {
{"FF_HORIZONTALFLIP",FF_HORIZONTALFLIP},
{"FF_PAPERSPRITE",FF_PAPERSPRITE},
{"FF_ANIMATE",FF_ANIMATE},
// brightness
{"FF_BRIGHTMASK",FF_BRIGHTMASK},
{"FF_FULLBRIGHT",FF_FULLBRIGHT},
{"FF_SEMIBRIGHT",FF_SEMIBRIGHT},
{"FF_FULLDARK",FF_FULLDARK},
// blending
{"FF_BLENDMASK",FF_BLENDMASK},
{"FF_BLENDSHIFT",FF_BRIGHTMASK},
{"FF_ADD",FF_ADD},
{"FF_SUBTRACT",FF_SUBTRACT},
{"FF_REVERSESUBTRACT",FF_REVERSESUBTRACT},
{"FF_MODULATE",FF_MODULATE},
{"FF_TRANSMASK",FF_TRANSMASK},
{"FF_TRANSSHIFT",FF_TRANSSHIFT},
// new preshifted translucency (used in source)
@@ -7816,15 +7757,6 @@ struct {
{"tr_trans90",tr_trans90},
{"NUMTRANSMAPS",NUMTRANSMAPS},
// Alpha styles (blend modes)
{"AST_COPY",AST_COPY},
{"AST_TRANSLUCENT",AST_TRANSLUCENT},
{"AST_ADD",AST_ADD},
{"AST_SUBTRACT",AST_SUBTRACT},
{"AST_REVERSESUBTRACT",AST_REVERSESUBTRACT},
{"AST_MODULATE",AST_MODULATE},
{"AST_OVERLAY",AST_OVERLAY},
// Type of levels
{"TOL_SP",TOL_SP},
{"TOL_COOP",TOL_COOP},
@@ -7848,7 +7780,6 @@ struct {
{"LF_NORELOAD",LF_NORELOAD},
{"LF_NOZONE",LF_NOZONE},
{"LF_SECTIONRACE",LF_SECTIONRACE},
{"LF_SUBTRACTNUM",LF_SUBTRACTNUM},
// And map flags
{"LF2_HIDEINMENU",LF2_HIDEINMENU},
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS},
@@ -8190,14 +8121,6 @@ struct {
{"V_CHARCOLORSHIFT",V_CHARCOLORSHIFT},
{"V_ALPHASHIFT",V_ALPHASHIFT},
// Blending
{"V_BLENDSHIFT",V_BLENDSHIFT},
{"V_BLENDMASK",V_BLENDMASK},
{"B_ADD",B_ADD},
{"B_SUBTRACT",B_SUBTRACT},
{"B_REVERSESUBTRACT",B_REVERSESUBTRACT},
{"B_MODULATE",B_MODULATE},
//Kick Reasons
{"KR_KICK",KR_KICK},
{"KR_PINGLIMIT",KR_PINGLIMIT},
@@ -8533,13 +8456,13 @@ static inline int lib_freeslot(lua_State *L)
// Arguments: mobj_t actor, int var1, int var2
static inline int lib_action(lua_State *L)
{
actionf_p1 *action = lua_touserdata(L,lua_upvalueindex(1));
actionf_t *action = lua_touserdata(L,lua_upvalueindex(1));
mobj_t *actor = *((mobj_t **)luaL_checkudata(L,1,META_MOBJ));
var1 = (INT32)luaL_optinteger(L,2,0);
var2 = (INT32)luaL_optinteger(L,3,0);
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
(*action)(actor);
action->acp1(actor);
return 0;
}
@@ -8622,16 +8545,6 @@ static int lua_enumlib_mariomode_get(lua_State *L)
return 1;
}
static int lua_enumlib_replayfreecam_get(lua_State *L)
{
if (dedicated) // huh?
lua_pushboolean(L, false);
else
lua_pushboolean(L, camera[R_GetViewNumber()].freecam);
return 1;
}
static int lua_enumlib_twodlevel_get(lua_State *L)
{
lua_pushboolean(L, twodlevel);
@@ -8646,7 +8559,7 @@ static int lua_enumlib_modifiedgame_get(lua_State *L)
static int lua_enumlib_server_get(lua_State *L)
{
if ((!multiplayer || !(netgame || demo.playback)) && !players[serverplayer].ingame)
if ((!multiplayer || !(netgame || demo.playback)) && !playeringame[serverplayer])
return 0;
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
return 1;
@@ -8654,7 +8567,7 @@ static int lua_enumlib_server_get(lua_State *L)
static int lua_enumlib_consoleplayer_get(lua_State *L)
{
if (consoleplayer < 0 || !players[consoleplayer].ingame)
if (consoleplayer < 0 || !playeringame[consoleplayer])
return 0;
LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER);
return 1;
@@ -9236,6 +9149,8 @@ int LUA_EnumLib(lua_State *L)
PUSHGETTER(globalweather, u8);
PUSHGETTER(levelskynum, i32);
PUSHGETTER(globallevelskynum, i32);
PUSHGETTER(mapmusflags, u16);
PUSHGETTER(mapmusposition, u32);
PUSHGETTER(gravity, fxp);
PUSHGETTER(gamespeed, u8);
PUSHGETTER(encoremode, bool);
@@ -9250,19 +9165,9 @@ int LUA_EnumLib(lua_State *L)
PUSHGETTER(racecountdown, u32);
PUSHGETTER(exitcountdown, u32);
lua_pushcfunction(L, lua_glib_new_getter);
lua_pushliteral(L, "mapmusflags");
lua_glib_push_u16_getter(L, &mapmusic.flags);
lua_call(L, 2, 0);
lua_pushcfunction(L, lua_glib_new_getter);
lua_pushliteral(L, "mapmusposition");
lua_glib_push_u32_getter(L, &mapmusic.position);
lua_call(L, 2, 0);
lua_pushcfunction(L, lua_glib_new_getter);
lua_pushliteral(L, "mapmusname");
lua_glib_push_str_getter(L, mapmusic.name);
lua_glib_push_str_getter(L, mapmusname);
lua_call(L, 2, 0);
lua_pushcfunction(L, lua_glib_new_getter);
@@ -9317,7 +9222,7 @@ int LUA_EnumLib(lua_State *L)
lua_pushcfunction(L, lua_glib_new_getter);
lua_pushliteral(L, "replayfreecam");
lua_pushcfunction(L, lua_enumlib_replayfreecam_get);
lua_glib_push_bool_getter(L, &demo.freecam);
lua_call(L, 2, 0);
if (!mathlib)
@@ -9353,15 +9258,13 @@ int LUA_SOCLib(lua_State *L)
const char *LUA_GetActionName(void *action)
{
actionf_p1 *act = (actionf_p1 *)action;
actionf_t *act = (actionf_t *)action;
size_t z;
for (z = 0; actionpointers[z].name; z++)
{
if (actionpointers[z].action == *act)
if (actionpointers[z].action.acv == act->acv)
return actionpointers[z].name;
}
return NULL;
}
@@ -9374,6 +9277,8 @@ void LUA_SetActionByName(void *state, const char *actiontocompare)
if (fasticmp(actiontocompare, actionpointers[z].name))
{
st->action = actionpointers[z].action;
st->action.acv = actionpointers[z].action.acv; // assign
st->action.acp1 = actionpointers[z].action.acp1;
return;
}
}
-20
View File
@@ -14,26 +14,6 @@
#define __DEHACKED_H__
#include "m_fixed.h" // for get_number
#include "info.h"
// Free slot names
// The crazy word-reading stuff uses these.
extern char *FREE_STATES[NUMSTATEFREESLOTS];
extern char *FREE_MOBJS[NUMMOBJFREESLOTS];
extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
extern const char *const STATE_LIST[];
extern const char *const MOBJTYPE_LIST[];
extern const char *const MOBJFLAG_LIST[];
extern const char *const MOBJFLAG2_LIST[]; // \tMF2_(\S+).*// (.+) --> \t"\1", // \2
extern const char *const MOBJEFLAG_LIST[];
extern const char *const MAPTHINGFLAG_LIST[4];
extern const char *const PLAYERFLAG_LIST[];
extern const char *const ML_LIST[]; // Linedef flags
extern const char *COLOR_ENUMS[];
extern const char *const POWERS_LIST[];
extern const char *const KARTSTUFF_LIST[];
extern const char *const HUDITEMS_LIST[];
void DEH_LoadDehackedLump(lumpnum_t lumpnum);
void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump);
+2 -2
View File
@@ -489,7 +489,7 @@ void DRPC_UpdatePresence(void)
{
#endif
discordPresence.state = "Private";
#ifdef MASTERSERVER
#ifdef MASTERSERVER
}
#endif
@@ -602,7 +602,7 @@ void DRPC_UpdatePresence(void)
}
// Character info
if (Playing() && players[consoleplayer].ingame && !players[consoleplayer].spectator)
if (Playing() && playeringame[consoleplayer] && !players[consoleplayer].spectator)
{
// Supported skin names
static const char *supportedSkins[] = {
-3
View File
@@ -89,9 +89,6 @@ typedef struct
UINT16 sidenum[2];
} ATTRPACK maplinedef_t;
//#define INT_MIN (-2147483647 - 1)
//#define INT_MAX 2147483647
//
// LineDef attributes.
//
+30 -38
View File
@@ -21,6 +21,7 @@
#define SOUND_DUMMY 0
#define SOUND_SDL 1
#define SOUND_MIXER 2
#define SOUND_FMOD 3
#ifndef SOUND
#ifdef HAVE_SDL
@@ -28,6 +29,9 @@
// Use Mixer interface?
#ifdef HAVE_MIXER
#define SOUND SOUND_MIXER
#ifdef HW3SOUND
#undef HW3SOUND
#endif
#endif
// Use generic SDL interface.
@@ -36,8 +40,18 @@
#endif
#else // No SDL.
// No more interfaces. :(
#define SOUND SOUND_DUMMY
// Use FMOD?
#ifdef HAVE_FMOD
#define SOUND SOUND_FMOD
#ifdef HW3SOUND
#undef HW3SOUND
#endif
#else
// No more interfaces. :(
#define SOUND SOUND_DUMMY
#endif
#endif
#endif
@@ -113,8 +127,8 @@ extern char logfilename[1024];
#else
#define VERSION 1 // Game version
#define SUBVERSION 6 // more precise version number
#define VERSIONSTRING "Saturn - NetPlus"
#define VERSIONSTRINGW L"Saturn - NetPlus lel"
#define VERSIONSTRING "Saturn v7.2"
#define VERSIONSTRINGW L"Saturn v7.2"
// Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates!
// And change CMakeLists.txt (not src/, but in root), for CMake users!
// AND appveyor.yml, for the build bots!
@@ -508,30 +522,15 @@ extern boolean capslock;
// i_system.c, replace getchar() once the keyboard has been appropriated
INT32 I_GetKey(void);
/* http://www.cse.yorku.ca/~oz/hash.html */
static inline
UINT32 quickncasehash (const char *p, size_t n)
{
size_t i = 0;
UINT32 x = 5381;
while (i < n && p[i])
{
x = (x * 33) ^ tolower(p[i]);
i++;
}
return x;
}
#ifndef min // Double-Check with WATTCP-32's cdefs.h
#define min(x, y) (((x) < (y)) ? (x) : (y))
#endif
#ifndef max // Double-Check with WATTCP-32's cdefs.h
#define max(x, y) (((x) > (y)) ? (x) : (y))
#endif
#ifndef CLAMP
#define CLAMP(x, y, z) ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x)))
#define CLAMP(x, min_val, max_val) ((x) < (min_val) ? (min_val) : ((x) > (max_val) ? (max_val) : (x)))
#endif
#ifndef M_PIl
@@ -547,19 +546,6 @@ UINT32 quickncasehash (const char *p, size_t n)
#define DBL_EPSILON 2.2204460492503131e-16l
#endif
#if defined(__GNUC__) || defined(__clang__)
#ifndef LIKELY
#define LIKELY(x) __builtin_expect(!!(x), 1)
#endif
#ifndef UNLIKELY
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#endif
#else
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#endif
// An assert-type mechanism.
#ifdef PARANOIA
#define I_Assert(e) ((e) ? (void)0 : I_Error("assert failed: %s, file %s, line %d", #e, __FILE__, __LINE__))
@@ -584,15 +570,21 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
#ifndef NONET
//-- SATURN __
/// Enable gamestate resynching between Saturn servers and clients
/// Like SRB2 and RR does
/// Still highly experimental
#ifdef DOSATURNSYNCH
#define SATURNSYNCH
/// Detect if a client is on Saturn in the clientconfig.
/// To seperately allow them to join or block joining from vanilla clients.
#ifdef DOSATURNJOIN
#define SATURNJOIN
#endif
#endif
/// Server detection for if a connecting client is on Saturn.
/// This also enables gamestate resynching between Saturn servers and clients
/// Like SRB2 and RR does
/// For stuff like extra synching, etc.
#ifdef DOSATURNPAK
#define SATURNPAK
#endif
@@ -647,12 +639,12 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Sprite rotation
#define ROTSPRITE
#define ROTANGLES 180 // Needs to be a divisor of 360 (45, 60, 90, 120...)
#define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...)
#define ROTANGDIFF (360 / ROTANGLES)
#if defined (HAVE_CURL) && ! defined (NONET)
#define MASTERSERVER
//#define HOLEPUNCH
#define HOLEPUNCH
#else
#undef UPDATE_ALERT
#endif
+27 -45
View File
@@ -30,26 +30,16 @@
// =============================
// Selected by user.
typedef struct
{
char name[7]; // Music name, up to 6-character name
void *data; // Music lump
UINT16 flags; // Track and reset bit
boolean looping; // Is this music looping?
UINT32 position; // Position to jump to
UINT32 resume; // Saved Position when music was stopped
UINT32 fadeinms; // Fade in time in ms (used for queue)
} music_t;
extern music_t mapmusic;
extern INT16 gamemap;
extern char mapmusname[7];
extern UINT16 mapmusflags;
extern UINT32 mapmusposition;
extern UINT32 mapmusresume;
#define MUSIC_TRACKMASK 0x0FFF // ----************
#define MUSIC_RELOADRESET 0x8000 // *---------------
#define MUSIC_FORCERESET 0x4000 // -*--------------
// Use other bits if necessary.
extern INT16 gamemap;
extern INT16 maptol;
extern UINT8 globalweather;
extern INT32 curWeather;
@@ -222,15 +212,6 @@ typedef struct
char value[256]; // 255 usable characters. If this seriously isn't enough then wtf.
} customoption_t;
typedef struct
{
boolean use_custom_light;
UINT8 light_contrast; ///< Range of wall lighting. 0 is no lighting.
SINT8 sprite_backlight; ///< Subtract from wall lighting for sprites only.
boolean use_light_angle; ///< When false, wall lighting is evenly distributed. When true, wall lighting is directional.
angle_t light_angle; ///< Angle of directional wall lighting.
} mapheader_lighting_t;
/** Map header information.
*/
typedef struct
@@ -244,7 +225,7 @@ typedef struct
INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end.
char musname[7]; ///< Music track to play. "" for no music.
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
UINT32 muspos; ///< Music position to jump to.
UINT32 muspos; ///< Music position to jump to.
char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave.
INT16 skynum; ///< Sky number to use.
@@ -276,11 +257,7 @@ typedef struct
// SRB2kart
//boolean automap; ///< Displays a level's white map outline in modified games
fixed_t mobj_scale; ///< Replacement for TOL_ERZ3
mapheader_lighting_t lighting; ///< Wall and sprite lighting
mapheader_lighting_t lighting_encore; ///< Alternative lighting for Encore mode
boolean use_encore_lighting; ///< Whether to use separate Encore lighting
fixed_t mobj_scale; ///< Replacement for TOL_ERZ3
// Music stuff.
UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds
@@ -299,7 +276,6 @@ typedef struct
#define LF_NORELOAD 8 ///< Don't reload level on death
#define LF_NOZONE 16 ///< Don't include "ZONE" on level title
#define LF_SECTIONRACE 32 ///< Section race level
#define LF_SUBTRACTNUM 64 ///< Use subtractive position number (for bright levels)
#define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu
#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen
@@ -362,6 +338,9 @@ enum GameType // SRB2Kart
// String names for gametypes
extern const char *Gametype_Names[NUMGAMETYPES];
extern tic_t totalplaytime;
extern UINT32 matchesplayed;
extern UINT8 stagefailed;
// Emeralds stored as bits to throw savegame hackers off.
@@ -475,14 +454,6 @@ extern tic_t racecountdown, exitcountdown;
extern fixed_t gravity;
extern fixed_t mapobjectscale;
extern struct maplighting
{
UINT8 contrast;
SINT8 backlight;
boolean directional;
angle_t angle;
} maplighting;
//for CTF balancing
extern INT16 autobalance;
extern INT16 teamscramble;
@@ -511,6 +482,7 @@ extern boolean startedInFreePlay;
extern boolean legitimateexit;
extern boolean comebackshowninfo;
extern tic_t curlap, bestlap;
extern INT16 votelevels[4][2];
extern SINT8 votes[MAXPLAYERS];
@@ -530,11 +502,6 @@ extern UINT32 timesBeatenWithEmeralds;
// WAD, partly set at startup time.
extern tic_t gametic;
extern tic_t simtic; // current tic at simulation, if applicable (if no simulation happened, this=gametic)
extern tic_t targetsimtic; // the target sim tic, if applicable
extern tic_t smoothedTic; // current game tic when smoothing is enabled (\todo: could cause problems if game objects care about gametic)
extern boolean canSimulate;
extern tic_t finaltargetsimtic;
#define localgametic leveltime
// Player spawn spots.
@@ -542,6 +509,18 @@ extern mapthing_t *playerstarts[MAXPLAYERS]; // Cooperative
extern mapthing_t *bluectfstarts[MAXPLAYERS]; // CTF
extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF
#define WAYPOINTSEQUENCESIZE 256
#define NUMWAYPOINTSEQUENCES 256
extern mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE];
extern UINT16 numwaypoints[NUMWAYPOINTSEQUENCES];
void P_AddWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint);
mobj_t *P_GetFirstWaypoint(UINT8 sequence);
mobj_t *P_GetLastWaypoint(UINT8 sequence);
mobj_t *P_GetPreviousWaypoint(mobj_t *current, boolean wrap);
mobj_t *P_GetNextWaypoint(mobj_t *current, boolean wrap);
mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo);
// =====================================
// Internal parameters, used for engine.
// =====================================
@@ -562,6 +541,9 @@ extern FILE *debugfile;
extern INT32 debugload;
#endif
// if true, load all graphics at level load
extern boolean precache;
// wipegamestate can be set to -1
// to force a wipe on the next draw
extern gamestate_t wipegamestate;
@@ -581,7 +563,7 @@ extern consvar_t cv_downloading; // allow clients to downloading WADs.
extern consvar_t cv_nettimeout; // SRB2Kart: Advanced server options menu
extern consvar_t cv_jointimeout;
extern consvar_t cv_maxping;
extern ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
extern ticcmd_t netcmds[TICQUEUE][MAXPLAYERS];
extern INT32 serverplayer;
extern INT32 adminplayers[MAXPLAYERS];
+26 -34
View File
@@ -17,8 +17,6 @@
#ifndef __DOOMTYPE__
#define __DOOMTYPE__
#include "stdbool.h"
#if defined (_WIN32)
//#define WIN32_LEAN_AND_MEAN
#define RPC_NO_WINDOWS_H
@@ -157,11 +155,23 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
#define STRBUFCPY(dst,src) strlcpy(dst, src, sizeof dst)
/* Boolean type definition */
#ifdef _WIN32
#define boolean bool
#else
typedef bool boolean;
#endif
// \note __BYTEBOOL__ used to be set above if "macintosh" was defined,
// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now?
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
//faB: clean that up !!
#if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward
#include "stdbool.h"
#elif defined (_WIN32)
#define false FALSE // use windows types
#define true TRUE
#define boolean BOOL
#else
typedef enum {false, true} boolean;
#endif
#endif // __BYTEBOOL__
/* 7.18.2.1 Limits of exact-width integer types */
#ifndef INT8_MIN
@@ -332,6 +342,15 @@ union FColorRGBA
} ATTRPACK;
typedef union FColorRGBA RGBA_t;
typedef enum
{
POSTIMG_WATER = 1, // Underwater screen effect.
POSTIMG_MOTION = 1<<1, // Unused motion blur effect.
POSTIMG_FLIP = 1<<2, // Flipcam screen effect.
POSTIMG_HEAT = 1<<3, // Heatwave screen effect.
POSTIMG_MIRROR = 1<<4, // encore screen effect.
} postimgflag_t;
typedef UINT32 lumpnum_t; // 16 : 16 unsigned long (wad num: lump num)
#define LUMPERROR UINT32_MAX
@@ -346,33 +365,6 @@ typedef UINT32 tic_t;
#define UINT2RGBA(a) (UINT32)((a&0xff)<<24)|((a&0xff00)<<8)|((a&0xff0000)>>8)|(((UINT32)a&0xff000000)>>24)
#endif
#define TOSTR(x) #x
typedef UINT8 bitarray_t;
#define BIT_ARRAY_SIZE(n) (((n) + 7) >> 3)
static inline int
in_bit_array (const bitarray_t * const array, const int value)
{
return (array[value >> 3] & (1<<(value & 7)));
}
static inline void
set_bit_array (bitarray_t * const array, const int value)
{
array[value >> 3] |= (1<<(value & 7));
}
static inline void
unset_bit_array (bitarray_t * const array, const int value)
{
array[value >> 3] &= ~(1<<(value & 7));
}
#define intsign(n) \
((n) < 0 ? -1 : (n) > 0 ? 1 : 0)
typedef UINT64 precise_t;
#endif //__DOOMTYPE__
+21
View File
@@ -0,0 +1,21 @@
#include "../doomdef.h"
#include "../d_main.h"
#include "../m_argv.h"
int main(int argc, char **argv)
{
myargc = argc;
myargv = argv; /// \todo pull out path to exe from this string
// startup SRB2
CONS_Printf("Setting up SRB2...\n");
D_SRB2Main();
CONS_Printf("Entering main game loop...\n");
// never return
D_SRB2Loop();
// return to OS
#ifndef __GNUC__
return 0;
#endif
}
+6
View File
@@ -0,0 +1,6 @@
#include "../i_net.h"
boolean I_InitNetwork(void)
{
return false;
}
+217
View File
@@ -0,0 +1,217 @@
#include "../i_sound.h"
UINT8 sound_started = 0;
void *I_GetSfx(sfxinfo_t *sfx)
{
(void)sfx;
return NULL;
}
void I_FreeSfx(sfxinfo_t *sfx)
{
(void)sfx;
}
void I_StartupSound(void){}
void I_ShutdownSound(void){}
void I_UpdateSound(void){};
//
// SFX I/O
//
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel)
{
(void)id;
(void)vol;
(void)sep;
(void)pitch;
(void)priority;
(void)channel;
return -1;
}
void I_StopSound(INT32 handle)
{
(void)handle;
}
boolean I_SoundIsPlaying(INT32 handle)
{
(void)handle;
return false;
}
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch)
{
(void)handle;
(void)vol;
(void)sep;
(void)pitch;
}
void I_SetSfxVolume(UINT8 volume)
{
(void)volume;
}
/// ------------------------
// MUSIC SYSTEM
/// ------------------------
void I_InitMusic(void){}
void I_ShutdownMusic(void){}
/// ------------------------
// MUSIC PROPERTIES
/// ------------------------
musictype_t I_SongType(void)
{
return MU_NONE;
}
boolean I_SongPlaying(void)
{
return false;
}
boolean I_SongPaused(void)
{
return false;
}
/// ------------------------
// MUSIC EFFECTS
/// ------------------------
boolean I_SetSongSpeed(float speed)
{
(void)speed;
return false;
}
/// ------------------------
// MUSIC SEEKING
/// ------------------------
UINT32 I_GetSongLength(void)
{
return 0;
}
boolean I_SetSongLoopPoint(UINT32 looppoint)
{
(void)looppoint;
return false;
}
UINT32 I_GetSongLoopPoint(void)
{
return 0;
}
boolean I_SetSongPosition(UINT32 position)
{
(void)position;
return false;
}
UINT32 I_GetSongPosition(void)
{
return 0;
}
/// ------------------------
// MUSIC PLAYBACK
/// ------------------------
boolean I_LoadSong(char *data, size_t len)
{
(void)data;
(void)len;
return -1;
}
void I_UnloadSong(void)
{
(void)handle;
}
boolean I_PlaySong(boolean looping)
{
(void)handle;
(void)looping;
return false;
}
void I_StopSong(void)
{
(void)handle;
}
void I_PauseSong(void)
{
(void)handle;
}
void I_ResumeSong(void)
{
(void)handle;
}
void I_SetMusicVolume(UINT8 volume)
{
(void)volume;
}
boolean I_SetSongTrack(INT32 track)
{
(void)track;
return false;
}
/// ------------------------
// MUSIC FADING
/// ------------------------
void I_SetInternalMusicVolume(UINT8 volume)
{
(void)volume;
}
void I_StopFadingSong(void)
{
}
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)source_volume;
(void)ms;
return false;
}
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
{
(void)target_volume;
(void)ms;
return false;
}
boolean I_FadeOutStopSong(UINT32 ms)
{
(void)ms;
return false;
}
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
{
(void)ms;
(void)looping;
return false;
}
+178
View File
@@ -0,0 +1,178 @@
#include "../doomdef.h"
#include "../i_system.h"
UINT8 graphics_started = 0;
UINT8 keyboard_started = 0;
size_t I_GetFreeMem(size_t *total)
{
*total = 0;
return 0;
}
void I_Sleep(UINT32 ms){}
precise_t I_GetPreciseTime(void) {
return 0;
}
UINT64 I_GetPrecisePrecision(void) {
return 1000000;
}
void I_GetEvent(void){}
void I_OsPolling(void){}
ticcmd_t *I_BaseTiccmd(void)
{
return NULL;
}
ticcmd_t *I_BaseTiccmd2(void)
{
return NULL;
}
void I_Quit(void)
{
exit(0);
}
void I_Error(const char *error, ...)
{
(void)error;
exit(-1);
}
void I_Tactile(FFType Type, const JoyFF_t *Effect)
{
(void)Type;
(void)Effect;
}
void I_Tactile2(FFType Type, const JoyFF_t *Effect)
{
(void)Type;
(void)Effect;
}
void I_JoyScale(void){}
void I_JoyScale2(void){}
void I_InitJoystick(void){}
void I_InitJoystick2(void){}
INT32 I_NumJoys(void)
{
return 0;
}
const char *I_GetJoyName(INT32 joyindex)
{
(void)joyindex;
return NULL;
}
#ifndef NOMUMBLE
void I_UpdateMumble(const mobj_t *mobj, const listener_t listener)
{
(void)mobj;
(void)listener;
}
#endif
void I_OutputMsg(const char *error, ...)
{
(void)error;
}
void I_StartupMouse(void){}
void I_StartupMouse2(void){}
void I_StartupKeyboard(void){}
INT32 I_GetKey(void)
{
return 0;
}
void I_StartupTimer(void){}
void I_AddExitFunc(void (*func)())
{
(void)func;
}
void I_RemoveExitFunc(void (*func)())
{
(void)func;
}
INT32 I_StartupSystem(void)
{
return -1;
}
void I_ShutdownSystem(void){}
void I_GetDiskFreeSpace(INT64* freespace)
{
*freespace = 0;
}
char *I_GetUserName(void)
{
return NULL;
}
INT32 I_mkdir(const char *dirname, INT32 unixright)
{
(void)dirname;
(void)unixright;
return -1;
}
const char *I_LocateWad(void)
{
return NULL;
}
void I_GetJoystickEvents(void){}
void I_GetJoystick2Events(void){}
void I_GetMouseEvents(void){}
char *I_GetEnv(const char *name)
{
(void)name;
return NULL;
}
INT32 I_PutEnv(char *variable)
{
(void)variable;
return -1;
}
INT32 I_ClipboardCopy(const char *data, size_t size)
{
(void)data;
(void)size;
return -1;
}
char *I_ClipboardPaste(void)
{
return NULL;
}
void I_RegisterSysCommands(void) {}
#include "../sdl/dosstr.c"
+67
View File
@@ -0,0 +1,67 @@
#include "../doomdef.h"
#include "../command.h"
#include "../i_video.h"
rendermode_t rendermode = render_none;
boolean highcolor = false;
boolean allow_fullscreen = false;
consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
void I_StartupGraphics(void){}
void I_ShutdownGraphics(void){}
void I_SetPalette(RGBA_t *palette)
{
(void)palette;
}
INT32 VID_NumModes(void)
{
return 0;
}
INT32 VID_GetModeForSize(INT32 w, INT32 h)
{
(void)w;
(void)h;
return 0;
}
void VID_PrepareModeList(void){}
INT32 VID_SetMode(INT32 modenum)
{
(void)modenum;
return 0;
}
const char *VID_GetModeName(INT32 modenum)
{
(void)modenum;
return NULL;
}
void I_UpdateNoBlit(void){}
void I_FinishUpdate(void){}
void I_UpdateNoVsync(void) {}
void I_WaitVBL(INT32 count)
{
(void)count;
}
void I_ReadScreen(UINT8 *scr)
{
(void)scr;
}
void I_BeginRead(void){}
void I_EndRead(void){}
+34 -38
View File
@@ -149,7 +149,7 @@ static UINT8 F_WriteText(void)
static void F_NewCutscene(const char *basetext)
{
cutscene_basetext = basetext;
memset(cutscene_disptext, 0, sizeof(cutscene_disptext));
memset(cutscene_disptext,0,sizeof(cutscene_disptext));
cutscene_writeptr = cutscene_baseptr = 0;
cutscene_textspeed = 9;
cutscene_textcount = TICRATE/2;
@@ -164,14 +164,14 @@ static void F_SkyScroll(INT32 scrollspeed)
patch_t *pat, *pat2;
INT32 anim2 = 0;
pat = W_CachePatchName("TITLEBG1", PU_PATCH_LOWPRIORITY);
pat2 = W_CachePatchName("TITLEBG2", PU_PATCH_LOWPRIORITY);
pat = W_CachePatchName("TITLEBG1", PU_CACHE);
pat2 = W_CachePatchName("TITLEBG2", PU_CACHE);
w = (vid.width / vid.dupx)<<FRACBITS;
// The scroll offset MUST be clamped before shifting by FRACBITS, or else it'll overflow in about 3 minutes
animtimer = ((((finalecount * scrollspeed) % (pat->width*16))<<FRACBITS) + (R_GetMenuUncap() * scrollspeed))/16;
anim2 = (pat2->width<<FRACBITS) - ((((finalecount * scrollspeed) % (pat2->width*16))<<FRACBITS) + (R_GetMenuUncap() * scrollspeed))/16;
animtimer = ((((finalecount * scrollspeed) % (SHORT(pat->width)*16))<<FRACBITS) + (R_GetMenuUncap() * scrollspeed))/16;
anim2 = (SHORT(pat2->width)<<FRACBITS) - ((((finalecount * scrollspeed) % (SHORT(pat2->width)*16))<<FRACBITS) + (R_GetMenuUncap() * scrollspeed))/16;
// SRB2Kart: F_DrawPatchCol is over-engineered; recoded to be less shitty and error-prone
if (rendermode != render_none)
@@ -183,15 +183,15 @@ static void F_SkyScroll(INT32 scrollspeed)
while (x < w)
{
V_DrawFixedPatch(x, y, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT, pat, NULL);
x += pat->width<<FRACBITS;
x += SHORT(pat->width)<<FRACBITS;
}
x = -anim2;
y = (BASEVIDHEIGHT - pat2->height)<<FRACBITS;
y = (BASEVIDHEIGHT - SHORT(pat2->height))<<FRACBITS;
while (x < w)
{
V_DrawFixedPatch(x, y, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, pat2, NULL);
x += pat2->width<<FRACBITS;
x += SHORT(pat2->width)<<FRACBITS;
}
}
@@ -263,7 +263,7 @@ void F_IntroDrawer(void)
// DRAW A FULL PIC INSTEAD OF FLAT!
if (intro_scenenum == 0)
{
background = W_CachePatchName("KARTKREW", PU_PATCH_LOWPRIORITY);
background = W_CachePatchName("KARTKREW", PU_CACHE);
highres = true;
}
@@ -534,15 +534,8 @@ static const char *credits[] = {
"\"Sunflower\" aka \"AnimeSonic\"",
"\"Yuz\" aka \"Yuzler\"",
"\"Democrab\"",
"\"EXpand\"",
"\"Expand\" aka \"Maver\"",
"\"Nexit\"",
"\"Spee\"",
"\"Jin\"",
"\"riomccloud\"",
"\"chromaticpipe\"",
"\"Achii\"",
"\"Anonimus\"",
"\"scizor300\"",
"",
"\1Special Thanks",
"SEGA",
@@ -630,10 +623,10 @@ void F_CreditDrawer(void)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
// Draw background
V_DrawSciencePatch(0, 0 - FixedMul(32<<FRACBITS, FixedDiv(credbgtimer%TICRATE, TICRATE)), V_SNAPTOTOP, W_CachePatchName("CREDTILE", PU_PATCH_LOWPRIORITY), FRACUNIT);
V_DrawSciencePatch(0, 0 - FixedMul(32<<FRACBITS, FixedDiv(credbgtimer%TICRATE, TICRATE)), V_SNAPTOTOP, W_CachePatchName("CREDTILE", PU_CACHE), FRACUNIT);
V_DrawSciencePatch(0, 0 - FixedMul(40<<FRACBITS, FixedDiv(credbgtimer%(TICRATE/2), (TICRATE/2))), V_SNAPTOTOP, W_CachePatchName("CREDZIGZ", PU_PATCH_LOWPRIORITY), FRACUNIT);
V_DrawSciencePatch(320<<FRACBITS, 0 - FixedMul(40<<FRACBITS, FixedDiv(credbgtimer%(TICRATE/2), (TICRATE/2))), V_SNAPTOTOP|V_FLIP, W_CachePatchName("CREDZIGZ", PU_PATCH_LOWPRIORITY), FRACUNIT);
V_DrawSciencePatch(0, 0 - FixedMul(40<<FRACBITS, FixedDiv(credbgtimer%(TICRATE/2), (TICRATE/2))), V_SNAPTOTOP, W_CachePatchName("CREDZIGZ", PU_CACHE), FRACUNIT);
V_DrawSciencePatch(320<<FRACBITS, 0 - FixedMul(40<<FRACBITS, FixedDiv(credbgtimer%(TICRATE/2), (TICRATE/2))), V_SNAPTOTOP|V_FLIP, W_CachePatchName("CREDZIGZ", PU_CACHE), FRACUNIT);
// Draw pictures
for (i = 0; credits_pics[i].patch; i++)
@@ -647,7 +640,7 @@ void F_CreditDrawer(void)
sc = FRACUNIT; // quick hack so I don't have to add another field to credits_pics
}
V_DrawFixedPatch(credits_pics[i].x<<FRACBITS, (credits_pics[i].y<<FRACBITS) - 4*(animtimer<<FRACBITS)/5, sc, 0, W_CachePatchName(credits_pics[i].patch, PU_PATCH), colormap);
V_DrawFixedPatch(credits_pics[i].x<<FRACBITS, (credits_pics[i].y<<FRACBITS) - 4*(animtimer<<FRACBITS)/5, sc, 0, W_CachePatchName(credits_pics[i].patch, PU_CACHE), colormap);
}
// Dim the background
@@ -846,9 +839,9 @@ void F_GameEvaluationDrawer(void)
patchname[4] = 'A'+(char)i;
if (emeralds & (1<<i))
V_DrawScaledPatch(x, y, 0, W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(x, y, 0, W_CachePatchName(patchname, PU_CACHE));
else
V_DrawTranslucentPatch(x, y, TRANSLEVEL, W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY));
V_DrawTranslucentPatch(x, y, TRANSLEVEL, W_CachePatchName(patchname, PU_CACHE));
eemeralds_cur += INTERVAL;
}
@@ -864,6 +857,9 @@ void F_GameEvaluationDrawer(void)
if (ALL7EMERALDS(emeralds))
++timesBeatenWithEmeralds;
/*if (ultimatemode)
++timesBeatenUltimate;*/
if (M_UpdateUnlockablesAndExtraEmblems(false))
S_StartSound(NULL, sfx_ncitem);
@@ -874,10 +870,10 @@ void F_GameEvaluationDrawer(void)
if (finalecount >= 5*TICRATE)
{
if (drawemblem)
V_DrawScaledPatch(120, 192, 0, W_CachePatchName("NWNGA0", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(120, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE));
if (drawchaosemblem)
V_DrawScaledPatch(200, 192, 0, W_CachePatchName("NWNGA0", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(200, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE));
V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:");
@@ -972,10 +968,10 @@ void F_StartTitleScreen(void)
demoDelayLeft = demoDelayTime;
demoIdleLeft = demoIdleTime;
ttbanner = W_CachePatchName("TTKBANNR", PU_PATCH_LOWPRIORITY);
ttkart = W_CachePatchName("TTKART", PU_PATCH_LOWPRIORITY);
ttcheckers = W_CachePatchName("TTCHECK", PU_PATCH_LOWPRIORITY);
ttkflash = W_CachePatchName("TTKFLASH", PU_PATCH_LOWPRIORITY);
ttbanner = W_CachePatchName("TTKBANNR", PU_LEVEL);
ttkart = W_CachePatchName("TTKART", PU_LEVEL);
ttcheckers = W_CachePatchName("TTCHECK", PU_LEVEL);
ttkflash = W_CachePatchName("TTKFLASH", PU_LEVEL);
}
// (no longer) De-Demo'd Title Screen
@@ -1010,7 +1006,7 @@ void F_TitleScreenDrawer(void)
else
{
INT32 transval = 0;
if (finalecount <= (50+(9<<1)))
transval = (finalecount - 50)>>1;
@@ -1057,8 +1053,8 @@ void F_TitleScreenTicker(boolean run)
return;
// are demos disabled?
if (!cv_rollingdemos.value || modifiedgame) // occasionally mappacks supply invalid replays which means the game crashes almost always when you idle on the titlescreen too long
return; // we check for all addons since added luas/socs and stuff like that makes them desynch like crazy so why would you even watch them?
if (!cv_rollingdemos.value)
return;
// Wait for a while (for the music to finish, preferably)
// before starting demos
@@ -1190,7 +1186,7 @@ void F_StartWaitingPlayers(void)
for (i = 0; i < 2; i++)
{
sprframe = &skins[randskin].spritedef.spriteframes[(6+(i*3)) & FF_FRAMEMASK];
driver[i] = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE);
driver[i] = W_CachePatchNum(sprframe->lumppat[1], PU_LEVEL);
}
}
@@ -1259,15 +1255,15 @@ void F_ContinueDrawer(void)
ncontinues = 20;
if (imcontinuing)
contsonic = W_CachePatchName("CONT2", PU_PATCH_LOWPRIORITY);
contsonic = W_CachePatchName("CONT2", PU_CACHE);
else
contsonic = W_CachePatchName("CONT1", PU_PATCH_LOWPRIORITY);
contsonic = W_CachePatchName("CONT1", PU_CACHE);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawCenteredString(BASEVIDWIDTH/2, 100, 0, "CONTINUE?");
// Draw a Sonic!
V_DrawScaledPatch((BASEVIDWIDTH - contsonic->width)/2, 32, 0, contsonic);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(contsonic->width))/2, 32, 0, contsonic);
// Draw the continue markers! Show continues minus one.
x -= ncontinues * 6;
@@ -1486,10 +1482,10 @@ void F_CutsceneDrawer(void)
{
if (cutscenes[cutnum]->scene[scenenum].pichires[picnum])
V_DrawSmallScaledPatch(picxpos, picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE));
else
V_DrawScaledPatch(picxpos,picypos, 0,
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH_LOWPRIORITY));
W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE));
}
if (dofadenow && rendermode != render_none)
+1 -1
View File
@@ -273,7 +273,7 @@ static void F_DoWipe(fademask_t *fademask)
else
{
// pointer to transtable that this mask would use
transtbl = R_GetTranslucencyTable((9 - *mask) + 1);
transtbl = transtables + ((9 - *mask)<<FF_TRANSSHIFT);
// DRAWING LOOP
while (draw_linestogo--)
+6 -11
View File
@@ -327,8 +327,7 @@ char menupath[1024];
size_t menupathindex[menudepth];
size_t menudepthleft = menudepth;
char menusearchbuf[MAXSTRINGLENGTH+1];
textinput_t menusearch;
char menusearch[MAXSTRINGLENGTH+1];
char **dirmenu, **coredirmenu; // core only local for this file
size_t sizedirmenu, sizecoredirmenu; // ditto
@@ -498,7 +497,7 @@ static boolean filemenucmp(char *haystack, char *needle)
strupr(localhaystack);
if (cv_addons_search_type.value)
return (strstr(localhaystack, needle) != 0);
return (!strncmp(localhaystack, needle, menusearch.length));
return (!strncmp(localhaystack, needle, menusearch[0]));
}
void closefilemenu(boolean validsize)
@@ -564,7 +563,7 @@ void searchfilemenu(char *tempname)
first = (((UINT8)(coredirmenu[0][DIR_TYPE]) == EXT_UP) ? 1 : 0); // skip UP...
if (!menusearch.length)
if (!menusearch[0])
{
if (dirmenu)
Z_Free(dirmenu);
@@ -591,7 +590,7 @@ void searchfilemenu(char *tempname)
return;
}
strcpy(localmenusearch, menusearch.buffer);
strcpy(localmenusearch, menusearch+1);
if (!cv_addons_search_case.value)
strupr(localmenusearch);
@@ -653,7 +652,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL
}
else
M_TextInputInit(&menusearch, menusearchbuf, MAXSTRINGLENGTH+1);
menusearch[0] = menusearch[1] = 0; // clear search
if (!(dirhandle = opendir(menupath))) // get directory
{
@@ -661,10 +660,6 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
return false;
}
if (dirmenu != coredirmenu)
Z_Free(dirmenu);
dirmenu = NULL;
for (; sizecoredirmenu > 0; sizecoredirmenu--) // clear out existing items
{
Z_Free(coredirmenu[sizecoredirmenu-1]);
@@ -801,7 +796,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
}
else if (ext == EXT_TXT)
{
if (!strncmp(dent->d_name, "log-", 4) || !strcmp(dent->d_name, "errorlog.txt"))
if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt"))
ext |= EXT_LOADED;
}
+1 -3
View File
@@ -7,7 +7,6 @@
#include "doomdef.h"
#include "d_netfil.h"
#include "m_menu.h" // MAXSTRINGLENGTH
#include "m_textinput.h"
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
@@ -35,8 +34,7 @@ extern char menupath[1024];
extern size_t menupathindex[menudepth];
extern size_t menudepthleft;
extern char menusearchbuf[MAXSTRINGLENGTH+1];
extern textinput_t menusearch;
extern char menusearch[MAXSTRINGLENGTH+1];
extern char **dirmenu;
extern size_t sizedirmenu;
+1517 -1307
View File
File diff suppressed because it is too large. Load diff
+43 -89
View File
@@ -17,7 +17,6 @@
#include "doomdef.h"
#include "doomstat.h"
#include "d_event.h"
#include "p_saveg.h"
#include "m_textinput.h"
extern char gamedatafilename[64];
@@ -32,8 +31,9 @@ extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
extern INT32 player_name_changes[MAXPLAYERS];
extern player_t players[MAXPLAYERS];
extern boolean playeringame[MAXPLAYERS];
extern savebuffer_t demobuf;
extern UINT8 *demo_p;
// ======================================
// DEMO playback/recording related stuff.
@@ -41,7 +41,6 @@ extern savebuffer_t demobuf;
// demoplaying back and demo recording
extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality, cv_maxdemosize, cv_demochangemap;
extern consvar_t cv_demodateformat;
// Publicly-accessible demo vars
struct demovars_s {
@@ -66,6 +65,9 @@ struct demovars_s {
DSM_WILLSAVE,
DSM_SAVED
} savemode;
boolean freecam;
};
extern struct demovars_s demo;
@@ -83,8 +85,6 @@ typedef struct menudemo_s {
menudemotype_e type;
char title[65]; // Null-terminated for string prints
char date[11]; // date when replay was recorded
char version[12]; // combined version and subversion
UINT16 map;
UINT8 addonstatus; // What do we need to do addon-wise to play this demo?
UINT8 gametype;
@@ -117,24 +117,15 @@ extern consvar_t cv_songcredits;
extern consvar_t cv_showfreeplay;
extern consvar_t cv_growmusic, cv_supermusic;
extern consvar_t cv_pauseifunfocused;
extern consvar_t cv_invertmouse;
extern consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_moveaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_camturnaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_camstrafeaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_brakeaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_aimaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_lookaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_lookbackaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_fireaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_driftaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_custom1axis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_custom2axis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_custom3axis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_xdeadzone[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_ydeadzone[MAXSPLITSCREENPLAYERS];
//extern consvar_t cv_crosshair, cv_crosshair2, cv_crosshair3, cv_crosshair4;
extern consvar_t cv_invertmouse/*, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove*/;
extern consvar_t cv_invertmouse2/*, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2*/;
extern consvar_t cv_useranalog, cv_useranalog2, cv_useranalog3, cv_useranalog4;
extern consvar_t cv_analog, cv_analog2, cv_analog3, cv_analog4;
extern consvar_t cv_turnaxis,cv_moveaxis,cv_brakeaxis,cv_aimaxis,cv_lookaxis,cv_fireaxis,cv_driftaxis,cv_lookbackaxis,cv_custom1axis,cv_custom2axis,cv_custom3axis,cv_xdeadzone,cv_ydeadzone;
extern consvar_t cv_turnaxis2,cv_moveaxis2,cv_brakeaxis2,cv_aimaxis2,cv_lookaxis2,cv_fireaxis2,cv_driftaxis2,cv_lookbackaxis2,cv_custom1axis2,cv_custom2axis2,cv_custom3axis2,cv_xdeadzone2,cv_ydeadzone2;
extern consvar_t cv_turnaxis3,cv_moveaxis3,cv_brakeaxis3,cv_aimaxis3,cv_lookaxis3,cv_fireaxis3,cv_driftaxis3,cv_lookbackaxis3,cv_custom1axis3,cv_custom2axis3,cv_custom3axis3,cv_xdeadzone3,cv_ydeadzone3;
extern consvar_t cv_turnaxis4,cv_moveaxis4,cv_brakeaxis4,cv_aimaxis4,cv_lookaxis4,cv_fireaxis4,cv_driftaxis4,cv_lookbackaxis4,cv_custom1axis4,cv_custom2axis4,cv_custom3axis4,cv_xdeadzone4,cv_ydeadzone4;
extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff;
// Hud offsets
@@ -148,47 +139,38 @@ extern consvar_t cv_##name##_yoffset;
DECL_HUD_OFFSET_X(name)\
DECL_HUD_OFFSET_Y(name)
DECL_HUD_OFFSET(item); // Item box
DECL_HUD_OFFSET(time); // Time
DECL_HUD_OFFSET(laps); // Number of laps
DECL_HUD_OFFSET(dnft); // Countdown (did not finish timer)
DECL_HUD_OFFSET(speed); // Speedometer
DECL_HUD_OFFSET(posi); // Position in race
DECL_HUD_OFFSET(wheel); // RA Wheel
DECL_HUD_OFFSET(face); // Mini rankings
DECL_HUD_OFFSET(stcd); // Starting countdown
DECL_HUD_OFFSET(item); // Item box
DECL_HUD_OFFSET(time); // Time
DECL_HUD_OFFSET(laps); // Number of laps
DECL_HUD_OFFSET(dnft); // Countdown (did not finish timer)
DECL_HUD_OFFSET(speed); // Speedometer
DECL_HUD_OFFSET(posi); // Position in race
DECL_HUD_OFFSET(face); // Mini rankings
DECL_HUD_OFFSET(stcd); // Starting countdown
DECL_HUD_OFFSET_Y(chek); // Check gfx
DECL_HUD_OFFSET(mini); // Minimap
DECL_HUD_OFFSET(want); // Wanted
DECL_HUD_OFFSET(stat); // Stats
DECL_HUD_OFFSET(mini); // Minimap
DECL_HUD_OFFSET(want); // Wanted
DECL_HUD_OFFSET(stat); // Stats
#undef DECL_HUD_OFFSET
#undef DECL_HUD_OFFSET_X
#undef DECL_HUD_OFFSET_Y
extern consvar_t cv_showinput;
extern consvar_t cv_posanim;
extern consvar_t cv_smallposnum;
extern consvar_t cv_newspeedometer;
extern consvar_t cv_saltyhop;
extern consvar_t cv_saltyheight;
extern consvar_t cv_saltyhopsfx;
extern consvar_t cv_saltysquish;
extern consvar_t cv_saltyroll;
extern consvar_t cv_driftsparkpulse;
extern consvar_t cv_gravstretch;
extern consvar_t cv_sloperoll;
extern consvar_t cv_spriteroll;
extern consvar_t cv_sliptideroll;
extern consvar_t cv_slamsound;
extern consvar_t cv_sloperolldist;
extern consvar_t cv_sparkroll;
extern consvar_t cv_spinoutroll;
extern consvar_t cv_squishdance, cv_squishdancespeed;
extern consvar_t cv_playerblendeffects;
extern consvar_t cv_cechotoggle;
@@ -201,8 +183,6 @@ typedef enum
AXISNONE = 0,
AXISTURN,
AXISMOVE,
AXISCAMTURN,
AXISCAMSTRAFE,
AXISBRAKE,
AXISAIM,
AXISLOOK,
@@ -240,6 +220,8 @@ extern angle_t localangle[MAXSPLITSCREENPLAYERS];
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
extern boolean camspin[MAXSPLITSCREENPLAYERS]; // SRB2Kart
extern tic_t directortoggletimer;
//
// GAME
//
@@ -284,6 +266,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost);
// A normal game starts at map 1, but a warp test can start elsewhere
void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar,
UINT8 ssplayers, boolean FLS);
void G_DoLoadLevel(boolean resetplayer);
void G_LoadDemoInfo(menudemo_t *pdemo);
void G_LoadDemoTitle(menudemo_t *pdemo); // For use in replay search feature
@@ -373,7 +356,6 @@ extern demoghost *ghosts;
#define DFILE_ERROR_CANNOTLOAD 0x04 // Files are missing and cannot be loaded.
#define DFILE_ERROR_EXTRAFILES 0x05 // Extra files outside of the replay's file list are loaded.
void G_ResetDemoRecording(void);
void G_DoPlayDemo(char *defdemoname);
void G_TimeDemo(const char *name);
void G_AddGhost(char *defdemoname);
@@ -387,24 +369,16 @@ boolean G_CheckDemoStatus(void);
void G_SaveDemo(void);
boolean G_DemoTitleResponder(event_t *ev);
#define G_GametypeHasTeams() (G_IsGameType(GT_TEAMMATCH) || G_IsGameType(GT_CTF))
#define G_BattleGametype() (G_IsGameType(GT_MATCH))
#define G_RaceGametype() (G_IsGameType(GT_RACE))
#define G_TagGametype() (G_IsGameType(GT_TAG) || G_IsGameType(GT_HIDEANDSEEK))
FUNCINLINE static ATTRINLINE boolean G_IsGameType(int type)
{
return (gametype == type);
}
FUNCINLINE static ATTRINLINE boolean G_GametypeHasSpectators(void)
{
return (netgame || (multiplayer && demo.playback));
}
INT32 G_GetGametypeByName(const char *gametypestr);
boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void);
boolean G_GametypeHasTeams(void);
boolean G_GametypeHasSpectators(void);
boolean G_BattleGametype(void);
UINT8 G_SometimesGetDifferentGametype(UINT8 prefgametype);
UINT8 G_GetGametypeColor(INT16 gt);
boolean G_RaceGametype(void);
boolean G_TagGametype(void);
void G_ExitLevel(void);
void G_NextLevel(void);
void G_Continue(void);
@@ -434,6 +408,7 @@ void G_SetRetryFlag(void);
void G_ClearRetryFlag(void);
boolean G_GetRetryFlag(void);
void G_LoadGameData(void);
void G_LoadGameSettings(void);
@@ -448,32 +423,13 @@ void G_ClearRecords(void);
tic_t G_GetBestTime(INT16 map);
// Time utility functions
FUNCMATH INT32 G_TicsToHours(tic_t tics);
FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full);
FUNCMATH INT32 G_TicsToSeconds(tic_t tics);
FUNCMATH INT32 G_TicsToCentiseconds(tic_t tics);
FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
FUNCINLINE static ATTRINLINE FUNCMATH INT32 G_TicsToHours(tic_t tics)
{
return tics/(3600*TICRATE);
}
FUNCINLINE static ATTRINLINE FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full)
{
return full ? (tics/(60*TICRATE)) : (tics/(60*TICRATE)%60);
}
FUNCINLINE static ATTRINLINE FUNCMATH INT32 G_TicsToSeconds(tic_t tics)
{
return (tics/TICRATE)%60;
}
FUNCINLINE static ATTRINLINE FUNCMATH INT32 G_TicsToCentiseconds(tic_t tics)
{
return (INT32)((tics%TICRATE) * (100.00f/TICRATE));
}
FUNCINLINE static ATTRINLINE FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics)
{
return (INT32)((tics%TICRATE) * (1000.00f/TICRATE));
}
boolean K_DirectorIsPlayerAlone(void); // idk where else to put this lol
// Don't split up TOL handling
INT16 G_TOLFlag(INT32 pgametype);
@@ -481,6 +437,4 @@ INT16 G_TOLFlag(INT32 pgametype);
INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer);
void G_AddMapToBuffer(INT16 map);
void G_FixCamera(UINT8 view);
#endif
+270 -170
View File
@@ -20,8 +20,6 @@
#include "d_net.h"
#include "console.h"
#include "m_menu.h"
#include "i_system.h"
#include "i_video.h"
#include "r_draw.h"
@@ -35,7 +33,9 @@ static CV_PossibleValue_t turnsmooth_cons_t[] = {{2, "Slow"}, {1, "Fast"}, {0, "
// mouse values are used once
consvar_t cv_mousesens = {"mousesens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mousesens2 = {"mousesens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouseysens = {"mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mouseysens2 = {"mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_turnsmooth = {"turnsmoothing", "Slow", CV_SAVE, turnsmooth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -58,35 +58,44 @@ consvar_t cv_rumble[MAXSPLITSCREENPLAYERS] = {
{"rumble4", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, rumble_off_handle4, 0, NULL, NULL, 0, 0, NULL}
};
static CV_PossibleValue_t gamepadled_cons_t[] = {{0, "Off"}, {1, "Skincolor"}, {2, "Mobjcolor"}, {0, NULL}};
consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS] = {
{"gamepadled", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle, 0, NULL, NULL, 0, 0, NULL},
{"gamepadled2", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle2, 0, NULL, NULL, 0, 0, NULL},
{"gamepadled3", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle3, 0, NULL, NULL, 0, 0, NULL},
{"gamepadled4", "Skincolor", CV_SAVE|CV_CALL|CV_NOINIT, gamepadled_cons_t, led_off_handle4, 0, NULL, NULL, 0, 0, NULL}
{"gamepadled", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle, 0, NULL, NULL, 0, 0, NULL},
{"gamepadled2", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle2, 0, NULL, NULL, 0, 0, NULL},
{"gamepadled3", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle3, 0, NULL, NULL, 0, 0, NULL},
{"gamepadled4", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle4, 0, NULL, NULL, 0, 0, NULL}
};
consvar_t cv_ledpowerup[MAXSPLITSCREENPLAYERS] = {
{"ledpowerup", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle, 0, NULL, NULL, 0, 0, NULL},
{"ledpowerup2", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle2, 0, NULL, NULL, 0, 0, NULL},
{"ledpowerup3", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle3, 0, NULL, NULL, 0, 0, NULL},
{"ledpowerup4", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, led_off_handle4, 0, NULL, NULL, 0, 0, NULL}
};
static void rumble_off_handle(void)
{
if (!cv_rumble[0].value)
if (cv_rumble[0].value == 0)
G_ResetPlayerDeviceRumble(0);
}
static void rumble_off_handle2(void)
{
if (!cv_rumble[1].value)
if (cv_rumble[1].value == 0)
G_ResetPlayerDeviceRumble(1);
}
static void rumble_off_handle3(void)
{
if (!cv_rumble[2].value)
if (cv_rumble[2].value == 0)
G_ResetPlayerDeviceRumble(2);
}
static void rumble_off_handle4(void)
{
if (!cv_rumble[3].value)
if (cv_rumble[3].value == 0)
G_ResetPlayerDeviceRumble(3);
}
@@ -95,16 +104,19 @@ static void led_off_handle(void)
G_ResetPlayerGamepadIndicatorColor(0);
}
static void led_off_handle2(void)
{
G_ResetPlayerGamepadIndicatorColor(1);
}
static void led_off_handle3(void)
{
G_ResetPlayerGamepadIndicatorColor(2);
}
static void led_off_handle4(void)
{
G_ResetPlayerGamepadIndicatorColor(3);
@@ -113,6 +125,8 @@ static void led_off_handle4(void)
INT32 mousex, mousey;
INT32 mlooky; // like mousey but with a custom sensitivity for mlook
INT32 mouse2x, mouse2y, mlook2y;
// joystick values are repeated
INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET],
joy3xmove[JOYAXISSET], joy3ymove[JOYAXISSET], joy4xmove[JOYAXISSET], joy4ymove[JOYAXISSET];
@@ -121,7 +135,10 @@ joy3xmove[JOYAXISSET], joy3ymove[JOYAXISSET], joy4xmove[JOYAXISSET], joy4ymove[J
UINT8 gamekeydown[NUMINPUTS];
// two key codes (or virtual key) per game control
INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][2];
INT32 gamecontrol[num_gamecontrols][2];
INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player
INT32 gamecontrol3[num_gamecontrols][2]; // tertiary splitscreen player
INT32 gamecontrol4[num_gamecontrols][2]; // quarternary splitscreen player
typedef struct
{
@@ -131,6 +148,7 @@ typedef struct
} dclick_t;
static dclick_t mousedclicks[MOUSEBUTTONS];
static dclick_t joydclicks[JOYBUTTONS + JOYHATS*4];
static dclick_t mouse2dclicks[MOUSEBUTTONS];
static dclick_t joy2dclicks[JOYBUTTONS + JOYHATS*4];
static dclick_t joy3dclicks[JOYBUTTONS + JOYHATS*4];
static dclick_t joy4dclicks[JOYBUTTONS + JOYHATS*4];
@@ -215,6 +233,14 @@ void G_MapEventsToControls(event_t *ev)
if (ev->data3 != INT32_MAX) joy4ymove[i] = ev->data3;
break;
case ev_mouse2: // buttons are virtual keys
if (menuactive || CON_Ready() || chat_on)
break;
mouse2x = (INT32)(ev->data2*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f));
mouse2y = (INT32)(ev->data3*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f));
mlook2y = (INT32)(ev->data3*((cv_mouseysens2.value*cv_mousesens2.value)/110.0f + 0.1f));
break;
default:
break;
}
@@ -232,6 +258,12 @@ void G_MapEventsToControls(event_t *ev)
gamekeydown[KEY_DBLJOY1+i] = flag;
}
for (i = 0; i < MOUSEBUTTONS; i++)
{
flag = G_CheckDoubleClick(gamekeydown[KEY_2MOUSE1+i], &mouse2dclicks[i]);
gamekeydown[KEY_DBL2MOUSE1+i] = flag;
}
for (i = 0; i < JOYBUTTONS + JOYHATS*4; i++)
{
flag = G_CheckDoubleClick(gamekeydown[KEY_2JOY1+i], &joy2dclicks[i]);
@@ -251,26 +283,6 @@ void G_MapEventsToControls(event_t *ev)
}
}
void G_ResetControls(void)
{
memset(gamekeydown, 0, NUMINPUTS);
memset(joyxmove, 0, sizeof(joyxmove));
memset(joyymove, 0, sizeof(joyymove));
memset(joy2xmove, 0, sizeof(joy2xmove));
memset(joy2ymove, 0, sizeof(joy2ymove));
memset(joy3xmove, 0, sizeof(joy3xmove));
memset(joy3ymove, 0, sizeof(joy3ymove));
memset(joy4xmove, 0, sizeof(joy4xmove));
memset(joy4ymove, 0, sizeof(joy4ymove));
// reset those just in case the game missed the keyup event
memset(dpadscrollstate, false, sizeof(dpadscrollstate));
}
//
// General double-click detection routine for any kind of input.
//
@@ -389,8 +401,18 @@ static keyname_t keynames[] =
{KEY_MOUSE1+5,"MOUSE6"},
{KEY_MOUSE1+6,"MOUSE7"},
{KEY_MOUSE1+7,"MOUSE8"},
{KEY_2MOUSE1+0,"SEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2
{KEY_2MOUSE1+1,"SEC_MOUSE1"},
{KEY_2MOUSE1+2,"SEC_MOUSE3"},
{KEY_2MOUSE1+3,"SEC_MOUSE4"},
{KEY_2MOUSE1+4,"SEC_MOUSE5"},
{KEY_2MOUSE1+5,"SEC_MOUSE6"},
{KEY_2MOUSE1+6,"SEC_MOUSE7"},
{KEY_2MOUSE1+7,"SEC_MOUSE8"},
{KEY_MOUSEWHEELUP, "Wheel 1 UP"},
{KEY_MOUSEWHEELDOWN, "Wheel 1 Down"},
{KEY_2MOUSEWHEELUP, "Wheel 2 UP"},
{KEY_2MOUSEWHEELDOWN, "Wheel 2 Down"},
{KEY_JOY1+0, "JOY1"},
{KEY_JOY1+1, "JOY2"},
@@ -401,7 +423,7 @@ static keyname_t keynames[] =
{KEY_JOY1+6, "JOY7"},
{KEY_JOY1+7, "JOY8"},
{KEY_JOY1+8, "JOY9"},
#if !defined (NOMOREJOYBTN_1S)
// we use up to 32 buttons in DirectInput
{KEY_JOY1+9, "JOY10"},
@@ -454,6 +476,14 @@ static keyname_t keynames[] =
{KEY_DBLMOUSE1+5, "DBLMOUSE6"},
{KEY_DBLMOUSE1+6, "DBLMOUSE7"},
{KEY_DBLMOUSE1+7, "DBLMOUSE8"},
{KEY_DBL2MOUSE1+0, "DBLSEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2
{KEY_DBL2MOUSE1+1, "DBLSEC_MOUSE1"},
{KEY_DBL2MOUSE1+2, "DBLSEC_MOUSE3"},
{KEY_DBL2MOUSE1+3, "DBLSEC_MOUSE4"},
{KEY_DBL2MOUSE1+4, "DBLSEC_MOUSE5"},
{KEY_DBL2MOUSE1+5, "DBLSEC_MOUSE6"},
{KEY_DBL2MOUSE1+6, "DBLSEC_MOUSE7"},
{KEY_DBL2MOUSE1+7, "DBLSEC_MOUSE8"},
{KEY_DBLJOY1+0, "DBLJOY1"},
{KEY_DBLJOY1+1, "DBLJOY2"},
@@ -838,6 +868,7 @@ static keyname_t keynames[] =
{KEY_DBL4HAT1+13, "DBLFOR_HATDOWN4"},
{KEY_DBL4HAT1+14, "DBLFOR_HATLEFT4"},
{KEY_DBL4HAT1+15, "DBLFOR_HATRIGHT4"},
};
static const char *gamecontrolname[num_gamecontrols] =
@@ -871,106 +902,149 @@ static const char *gamecontrolname[num_gamecontrols] =
"custom2",
"custom3",
"director",
"freecam",
"camfloat",
"camsink",
"strafeleft",
"straferight",
};
#define NUMKEYNAMES (sizeof (keynames)/sizeof (keyname_t))
#include "k_kart.h"
UINT16 G_GetSkinColor(INT32 playernum)
INT32 G_GetDeviceForPlayer(INT32 player)
{
if (gamestate == GS_LEVEL)
switch (player)
{
player_t *player = &players[displayplayers[playernum]];
if (player)
{
// make rgb rainbow vomit when invul or flash blue when grow
if ((cv_gamepadled[playernum].value == 2) && player->mo && player->mo->color)
return player->mo->color;
// take actual player skincolour when ingame
if (player->skincolor)
return player->skincolor;
}
case 0:
return cv_usejoystick.value;
break;
case 1:
return cv_usejoystick2.value;
break;
case 2:
return cv_usejoystick3.value;
break;
case 3:
return cv_usejoystick4.value;
break;
default:
return 0;
break;
}
}
inline UINT16 G_GetSkinColor(INT32 player)
{
// make rgb rainbow vomit when invul or flash blue when grow
if (cv_ledpowerup[player].value && gamestate == GS_LEVEL && players[displayplayers[player]].mo && (players[displayplayers[player]].kartstuff[k_invincibilitytimer] || players[displayplayers[player]].powers[pw_invulnerability] || players[displayplayers[player]].kartstuff[k_growshrinktimer]))
return players[displayplayers[player]].mo->color;
// take actual player skincolour when ingame
if (gamestate == GS_LEVEL && players[displayplayers[player]].skincolor)
return players[displayplayers[player]].skincolor;
// otherwise just fallback to whatever the cvar is
switch (playernum)
switch (player)
{
case 0:
return cv_playercolor.value;
break;
case 1:
return cv_playercolor2.value;
break;
case 2:
return cv_playercolor3.value;
break;
case 3:
return cv_playercolor4.value;
break;
default:
return 0;
break;
}
return 0;
}
void G_SetPlayerGamepadIndicatorColor(INT32 playernum, UINT16 color)
void G_SetPlayerGamepadIndicatorColor(INT32 player, UINT16 color)
{
INT32 device;
UINT16 skincolor;
byteColor_t byte_color;
I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS);
I_Assert(player >= 0 && player < MAXSPLITSCREENPLAYERS);
if (cv_gamepadled[playernum].value == 0)
if (cv_gamepadled[player].value == 0)
return;
device = G_GetDeviceForPlayer(player);
if (device <= 0)
{
return;
}
skincolor = color ? color : G_GetSkinColor(playernum);
skincolor = color ? color : G_GetSkinColor(player);
byte_color = V_GetColor(colortranslations[skincolor][8]).s;
I_SetGamepadIndicatorColor(playernum, byte_color.red, byte_color.green, byte_color.blue);
I_SetGamepadIndicatorColor(device, byte_color.red, byte_color.green, byte_color.blue);
}
static void G_ResetPlayerGamepadIndicatorColor(INT32 playernum)
static void G_ResetPlayerGamepadIndicatorColor(INT32 player)
{
if (cv_gamepadled[playernum].value == 0)
if (cv_gamepadled[player].value == 0)
{
I_SetGamepadIndicatorColor(playernum, 0, 0, 255);
INT32 device = G_GetDeviceForPlayer(player);
if (device <= 0)
return;
I_SetGamepadIndicatorColor(device, 0, 0, 255);
}
else
G_SetPlayerGamepadIndicatorColor(playernum, 0);
G_SetPlayerGamepadIndicatorColor(player, 0);
}
static void G_ResetPlayerDeviceRumble(INT32 playernum)
static void G_ResetPlayerDeviceRumble(INT32 player)
{
I_GamepadRumble(playernum, 0, 0, 0);
INT32 device_id;
device_id = G_GetDeviceForPlayer(player);
if (device_id < 1)
{
return;
}
I_GamepadRumble(device_id, 0, 0, 0);
}
void G_ResetAllDeviceRumbles(void)
{
int i;
int devices;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
devices = I_NumJoys();
for (i = 0; i < devices; i++)
{
I_GamepadRumble(i, 0, 0, 0);
INT32 device_id = G_GetDeviceForPlayer(i);
I_GamepadRumble(device_id, 0, 0, 0);
}
}
void G_PlayerDeviceRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration)
void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength, UINT32 duration)
{
I_Assert(playernum >= 0 && playernum < MAXSPLITSCREENPLAYERS);
INT32 device_id;
if (cv_rumble[playernum].value == 0)
if (cv_rumble[player].value == 0)
{
return;
}
I_GamepadRumble(playernum, low_strength, high_strength, duration);
device_id = G_GetDeviceForPlayer(player);
if (device_id < 1)
{
return;
}
I_GamepadRumble(device_id, low_strength, high_strength, duration);
}
//
@@ -984,14 +1058,13 @@ void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control)
void G_ClearAllControlKeys(void)
{
INT32 i, k;
for (k = 0; k < MAXSPLITSCREENPLAYERS; k++)
INT32 i;
for (i = 0; i < num_gamecontrols; i++)
{
for (i = 0; i < num_gamecontrols; i++)
{
G_ClearControlKeys(gamecontrol[k], i);
}
G_ClearControlKeys(gamecontrol, i);
G_ClearControlKeys(gamecontrolbis, i);
G_ClearControlKeys(gamecontrol3, i);
G_ClearControlKeys(gamecontrol4, i);
}
}
@@ -1030,7 +1103,7 @@ INT32 G_KeyStringtoNum(const char *keystr)
if (!keystr[0])
return 0;
if (!keystr[0] || (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z'))
if (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z')
return keystr[0];
if (!strncmp(keystr, "KEY", 3) && keystr[3] >= '0' && keystr[3] <= '9')
@@ -1049,131 +1122,158 @@ void G_Controldefault(UINT8 player)
if (player == 0 || player == 1)
{
// Main controls
gamecontrol[0][gc_aimforward ][0] = KEY_UPARROW;
gamecontrol[0][gc_aimbackward][0] = KEY_DOWNARROW;
gamecontrol[0][gc_turnleft ][0] = KEY_LEFTARROW;
gamecontrol[0][gc_turnright ][0] = KEY_RIGHTARROW;
gamecontrol[0][gc_accelerate ][0] = 'a';
gamecontrol[0][gc_drift ][0] = 's';
gamecontrol[0][gc_brake ][0] = 'd';
gamecontrol[0][gc_fire ][0] = KEY_SPACE;
gamecontrol[0][gc_lookback ][0] = KEY_LSHIFT;
gamecontrol[gc_aimforward ][0] = KEY_UPARROW;
gamecontrol[gc_aimbackward][0] = KEY_DOWNARROW;
gamecontrol[gc_turnleft ][0] = KEY_LEFTARROW;
gamecontrol[gc_turnright ][0] = KEY_RIGHTARROW;
gamecontrol[gc_accelerate ][0] = 'a';
gamecontrol[gc_drift ][0] = 's';
gamecontrol[gc_brake ][0] = 'd';
gamecontrol[gc_fire ][0] = KEY_SPACE;
gamecontrol[gc_lookback ][0] = KEY_LSHIFT;
gamecontrol[0][gc_accelerate ][1] = KEY_JOY1+0; // A
gamecontrol[0][gc_lookback ][1] = KEY_JOY1+2; // X
gamecontrol[0][gc_brake ][1] = KEY_JOY1+1; // B
gamecontrol[0][gc_fire ][1] = KEY_JOY1+9; // LB
gamecontrol[0][gc_drift ][1] = KEY_JOY1+10; // RB
gamecontrol[gc_accelerate ][1] = KEY_JOY1+0; // A
gamecontrol[gc_lookback ][1] = KEY_JOY1+2; // X
gamecontrol[gc_brake ][1] = KEY_JOY1+1; // B
gamecontrol[gc_fire ][1] = KEY_JOY1+9; // LB
gamecontrol[gc_drift ][1] = KEY_JOY1+10; // RB
// Extra controls
gamecontrol[0][gc_pause ][0] = KEY_PAUSE;
gamecontrol[0][gc_console ][0] = KEY_CONSOLE;
gamecontrol[0][gc_screenshot ][0] = KEY_F8;
gamecontrol[0][gc_recordgif ][0] = KEY_F9;
gamecontrol[0][gc_viewpoint ][0] = KEY_F12;
gamecontrol[0][gc_talkkey ][0] = 't';
gamecontrol[gc_pause ][0] = KEY_PAUSE;
gamecontrol[gc_console ][0] = KEY_CONSOLE;
gamecontrol[gc_screenshot ][0] = KEY_F8;
gamecontrol[gc_recordgif ][0] = KEY_F9;
gamecontrol[gc_viewpoint ][0] = KEY_F12;
gamecontrol[gc_talkkey ][0] = 't';
//gamecontrol[gc_teamkey ][0] = 'y';
gamecontrol[0][gc_scores ][0] = KEY_TAB;
gamecontrol[0][gc_spectate ][0] = '\'';
gamecontrol[0][gc_lookup ][0] = KEY_PGUP;
gamecontrol[0][gc_lookdown ][0] = KEY_PGDN;
gamecontrol[0][gc_centerview ][0] = KEY_END;
gamecontrol[0][gc_camreset ][0] = KEY_HOME;
gamecontrol[0][gc_camtoggle ][0] = KEY_BACKSPACE;
gamecontrol[gc_scores ][0] = KEY_TAB;
gamecontrol[gc_spectate ][0] = '\'';
gamecontrol[gc_lookup ][0] = KEY_PGUP;
gamecontrol[gc_lookdown ][0] = KEY_PGDN;
gamecontrol[gc_centerview ][0] = KEY_END;
gamecontrol[gc_camreset ][0] = KEY_HOME;
gamecontrol[gc_camtoggle ][0] = KEY_BACKSPACE;
gamecontrol[0][gc_viewpoint ][1] = KEY_JOY1+3; // Y
gamecontrol[0][gc_pause ][1] = KEY_JOY1+4; // Back
gamecontrol[0][gc_systemmenu ][0] = KEY_JOY1+6; // Start
//gamecontrol[0][gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up
//gamecontrol[0][gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down // absolutely fucking NOT
gamecontrol[0][gc_talkkey ][1] = KEY_HAT1+1; // D-Pad Down
gamecontrol[0][gc_scores ][1] = KEY_HAT1+0; // D-Pad Up
gamecontrol[gc_viewpoint ][1] = KEY_JOY1+3; // Y
gamecontrol[gc_pause ][1] = KEY_JOY1+4; // Back
gamecontrol[gc_systemmenu ][0] = KEY_JOY1+6; // Start
//gamecontrol[gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up
//gamecontrol[gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down // absolutely fucking NOT
gamecontrol[gc_talkkey ][1] = KEY_HAT1+1; // D-Pad Down
gamecontrol[gc_scores ][1] = KEY_HAT1+0; // D-Pad Up
}
if (player == 0 || player == 2)
{
// Player 2 controls
gamecontrol[1][gc_accelerate ][0] = KEY_2JOY1+0; // A
gamecontrol[1][gc_lookback ][0] = KEY_2JOY1+2; // X
gamecontrol[1][gc_brake ][0] = KEY_2JOY1+1; // B
gamecontrol[1][gc_fire ][0] = KEY_2JOY1+9; // LB
gamecontrol[1][gc_drift ][0] = KEY_2JOY1+10; // RB
gamecontrolbis[gc_accelerate ][0] = KEY_2JOY1+0; // A
gamecontrolbis[gc_lookback ][0] = KEY_2JOY1+2; // X
gamecontrolbis[gc_brake ][0] = KEY_2JOY1+1; // B
gamecontrolbis[gc_fire ][0] = KEY_2JOY1+9; // LB
gamecontrolbis[gc_drift ][0] = KEY_2JOY1+10; // RB
}
if (player == 0 || player == 3)
{
// Player 3 controls
gamecontrol[2][gc_accelerate ][0] = KEY_3JOY1+0; // A
gamecontrol[2][gc_lookback ][0] = KEY_3JOY1+2; // X
gamecontrol[2][gc_brake ][0] = KEY_3JOY1+1; // B
gamecontrol[2][gc_fire ][0] = KEY_3JOY1+9; // LB
gamecontrol[2][gc_drift ][0] = KEY_3JOY1+10; // RB
gamecontrol3[gc_accelerate ][0] = KEY_3JOY1+0; // A
gamecontrol3[gc_lookback ][0] = KEY_3JOY1+2; // X
gamecontrol3[gc_brake ][0] = KEY_3JOY1+1; // B
gamecontrol3[gc_fire ][0] = KEY_3JOY1+9; // LB
gamecontrol3[gc_drift ][0] = KEY_3JOY1+10; // RB
}
if (player == 0 || player == 4)
{
// Player 4 controls
gamecontrol[3][gc_accelerate ][0] = KEY_4JOY1+0; // A
gamecontrol[3][gc_lookback ][0] = KEY_4JOY1+2; // X
gamecontrol[3][gc_brake ][0] = KEY_4JOY1+1; // B
gamecontrol[3][gc_fire ][0] = KEY_4JOY1+9; // LB
gamecontrol[3][gc_drift ][0] = KEY_4JOY1+10; // RB
gamecontrol4[gc_accelerate ][0] = KEY_4JOY1+0; // A
gamecontrol4[gc_lookback ][0] = KEY_4JOY1+2; // X
gamecontrol4[gc_brake ][0] = KEY_4JOY1+1; // B
gamecontrol4[gc_fire ][0] = KEY_4JOY1+9; // LB
gamecontrol4[gc_drift ][0] = KEY_4JOY1+10; // RB
}
}
void G_SaveKeySetting(FILE *f)
{
INT32 i, k;
INT32 i;
static const char *controltext[MAXSPLITSCREENPLAYERS] = {
"setcontrol",
"setcontrol2",
"setcontrol3",
"setcontrol4"
};
for (k = 0; k < MAXSPLITSCREENPLAYERS; k++)
for (i = 1; i < num_gamecontrols; i++)
{
for (i = 1; i < num_gamecontrols; i++)
{
fprintf(f, "%s \"%s\" \"%s\"", controltext[k], gamecontrolname[i],
G_KeynumToString(gamecontrol[k][i][0]));
fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i],
G_KeynumToString(gamecontrol[i][0]));
if (gamecontrol[k][i][1])
fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrol[k][i][1]));
else
fprintf(f, "\n");
}
if (gamecontrol[i][1])
fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrol[i][1]));
else
fprintf(f, "\n");
}
for (i = 1; i < num_gamecontrols; i++)
{
fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i],
G_KeynumToString(gamecontrolbis[i][0]));
if (gamecontrolbis[i][1])
fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrolbis[i][1]));
else
fprintf(f, "\n");
}
for (i = 1; i < num_gamecontrols; i++)
{
fprintf(f, "setcontrol3 \"%s\" \"%s\"", gamecontrolname[i],
G_KeynumToString(gamecontrol3[i][0]));
if (gamecontrol3[i][1])
fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrol3[i][1]));
else
fprintf(f, "\n");
}
for (i = 1; i < num_gamecontrols; i++)
{
fprintf(f, "setcontrol4 \"%s\" \"%s\"", gamecontrolname[i],
G_KeynumToString(gamecontrol4[i][0]));
if (gamecontrol4[i][1])
fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrol4[i][1]));
else
fprintf(f, "\n");
}
}
INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify)
{
INT32 result = gc_null;
if (cv_controlperkey.value == 1)
{
INT32 i, j, k;
for (k = 0; k < MAXSPLITSCREENPLAYERS; k++)
INT32 i, j;
for (i = 0; i < num_gamecontrols; i++)
{
for (i = 0; i < num_gamecontrols; i++)
for (j = 0; j < 2; j++)
{
for (j = 0; j < 2; j++)
{
if (gamecontrol[k][i][j] == keynum)
{
result = i;
if (modify) gamecontrol[k][i][j] = KEY_NULL;
}
if (result && !modify)
return result;
if (gamecontrol[i][j] == keynum) {
result = i;
if (modify) gamecontrol[i][j] = KEY_NULL;
}
if (gamecontrolbis[i][j] == keynum) {
result = i;
if (modify) gamecontrolbis[i][j] = KEY_NULL;
}
if (gamecontrol3[i][j] == keynum) {
result = i;
if (modify) gamecontrol3[i][j] = KEY_NULL;
}
if (gamecontrol4[i][j] == keynum) {
result = i;
if (modify) gamecontrol4[i][j] = KEY_NULL;
}
if (result && !modify)
return result;
}
}
}
return result;
}
@@ -1327,11 +1427,11 @@ static void setcontrol(INT32 (*gc)[2])
INT32 player;
boolean nestedoverride = false;
if ((void*)gc == (void*)&gamecontrol[3])
if ((void*)gc == (void*)&gamecontrol4)
player = 3;
else if ((void*)gc == (void*)&gamecontrol[2])
else if ((void*)gc == (void*)&gamecontrol3)
player = 2;
else if ((void*)gc == (void*)&gamecontrol[1])
else if ((void*)gc == (void*)&gamecontrolbis)
player = 1;
else
player = 0;
@@ -1394,7 +1494,7 @@ void Command_Setcontrol_f(void)
return;
}
setcontrol(gamecontrol[0]);
setcontrol(gamecontrol);
}
void Command_Setcontrol2_f(void)
@@ -1409,7 +1509,7 @@ void Command_Setcontrol2_f(void)
return;
}
setcontrol(gamecontrol[1]);
setcontrol(gamecontrolbis);
}
void Command_Setcontrol3_f(void)
@@ -1424,7 +1524,7 @@ void Command_Setcontrol3_f(void)
return;
}
setcontrol(gamecontrol[2]);
setcontrol(gamecontrol3);
}
void Command_Setcontrol4_f(void)
@@ -1439,5 +1539,5 @@ void Command_Setcontrol4_f(void)
return;
}
setcontrol(gamecontrol[3]);
setcontrol(gamecontrol4);
}
+22 -18
View File
@@ -41,10 +41,12 @@ typedef enum
KEY_DBLJOY1 = KEY_DBLMOUSE1 + MOUSEBUTTONS,
KEY_DBLHAT1 = KEY_DBLJOY1 + JOYBUTTONS,
KEY_2JOY1 = KEY_DBLHAT1 + MOUSEBUTTONS,
KEY_2MOUSE1 = KEY_DBLHAT1 + JOYHATS*4,
KEY_2JOY1 = KEY_2MOUSE1 + MOUSEBUTTONS,
KEY_2HAT1 = KEY_2JOY1 + JOYBUTTONS,
KEY_DBL2JOY1 = KEY_2HAT1 + MOUSEBUTTONS,
KEY_DBL2MOUSE1 = KEY_2HAT1 + JOYHATS*4,
KEY_DBL2JOY1 = KEY_DBL2MOUSE1 + MOUSEBUTTONS,
KEY_DBL2HAT1 = KEY_DBL2JOY1 + JOYBUTTONS,
KEY_3JOY1 = KEY_DBL2HAT1 + JOYHATS*4,
@@ -61,8 +63,10 @@ typedef enum
KEY_MOUSEWHEELUP = KEY_DBL4HAT1 + JOYHATS*4,
KEY_MOUSEWHEELDOWN = KEY_MOUSEWHEELUP + 1,
KEY_2MOUSEWHEELUP = KEY_MOUSEWHEELDOWN + 1,
KEY_2MOUSEWHEELDOWN = KEY_2MOUSEWHEELUP + 1,
NUMINPUTS = KEY_MOUSEWHEELDOWN + 1,
NUMINPUTS = KEY_2MOUSEWHEELDOWN + 1,
} key_input_e;
typedef enum
@@ -96,22 +100,20 @@ typedef enum
gc_custom2, // Lua scriptable
gc_custom3, // Lua scriptable
gc_director,
gc_freecam, // Toggle for freecam while ingame
gc_camfloat, // alternative button for raising cam
gc_camsink, // alternative button for sinking
gc_strafeleft,
gc_straferight,
num_gamecontrols
} gamecontrols_e;
// mouse values are used once
extern consvar_t cv_mousesens, cv_mouseysens;
extern consvar_t cv_mousesens2, cv_mouseysens2;
extern consvar_t cv_controlperkey, cv_turnsmooth;
extern consvar_t cv_rumble[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_gamepadled[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_ledpowerup[MAXSPLITSCREENPLAYERS];
extern INT32 mousex, mousey;
extern INT32 mlooky; //mousey with mlookSensitivity
extern INT32 mouse2x, mouse2y, mlook2y;
extern INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET],
joy3xmove[JOYAXISSET], joy3ymove[JOYAXISSET], joy4xmove[JOYAXISSET], joy4ymove[JOYAXISSET];
@@ -120,24 +122,26 @@ extern INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET],
extern UINT8 gamekeydown[NUMINPUTS];
// two key codes (or virtual key) per game control
extern INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][2];
#define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[0][gc][0]] || gamekeydown[gamecontrol[0][gc][1]])
#define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrol[1][gc][0]] || gamekeydown[gamecontrol[1][gc][1]])
#define PLAYER3INPUTDOWN(gc) (gamekeydown[gamecontrol[2][gc][0]] || gamekeydown[gamecontrol[2][gc][1]])
#define PLAYER4INPUTDOWN(gc) (gamekeydown[gamecontrol[3][gc][0]] || gamekeydown[gamecontrol[3][gc][1]])
extern INT32 gamecontrol[num_gamecontrols][2];
extern INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player
extern INT32 gamecontrol3[num_gamecontrols][2];
extern INT32 gamecontrol4[num_gamecontrols][2];
#define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]])
#define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]])
#define PLAYER3INPUTDOWN(gc) (gamekeydown[gamecontrol3[gc][0]] || gamekeydown[gamecontrol3[gc][1]])
#define PLAYER4INPUTDOWN(gc) (gamekeydown[gamecontrol4[gc][0]] || gamekeydown[gamecontrol4[gc][1]])
// peace to my little coder fingers!
// check a gamecontrol being active or not
UINT16 G_GetSkinColor(INT32 playernum);
void G_SetPlayerGamepadIndicatorColor(INT32 playernum, UINT16 color);
UINT16 G_GetSkinColor(INT32 player);
INT32 G_GetDeviceForPlayer(INT32 player);
void G_SetPlayerGamepadIndicatorColor(INT32 player, UINT16 color);
void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength, UINT32 duration);
void G_ResetAllDeviceRumbles(void);
void G_PlayerDeviceRumble(INT32 playernum, UINT16 low_strength, UINT16 high_strength, UINT32 duration);
// remaps the input event to a game control.
void G_MapEventsToControls(event_t *ev);
void G_ResetControls(void);
// returns the name of a key
const char *G_KeynumToString(INT32 keynum);
+85
View File
@@ -0,0 +1,85 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright (C) 2001 by DooM Legacy Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//-----------------------------------------------------------------------------
/// \file
/// \brief 3D sound import/export prototypes for low-level hardware interface
#ifndef __HW_3DS_DRV_H__
#define __HW_3DS_DRV_H__
// Use standart hardware API
#include "hw_dll.h"
#include "hws_data.h"
#if defined (HAVE_SDL) || !defined (HWD)
EXPORT void HWRAPI(Shutdown) (void);
#endif
// Use standart Init and Shutdown functions
EXPORT INT32 HWRAPI (Startup) (I_Error_t FatalErrorFunction, snddev_t *snd_dev);
EXPORT u_int HWRAPI (AddSfx) (sfx_data_t *sfx);
EXPORT INT32 HWRAPI (AddSource) (source3D_data_t *src, u_int sfxhandle);
EXPORT INT32 HWRAPI (StartSource) (INT32 handle);
EXPORT void HWRAPI (StopSource) (INT32 handle);
EXPORT INT32 HWRAPI (GetHW3DSVersion) (void);
EXPORT void HWRAPI (BeginFrameUpdate) (void);
EXPORT void HWRAPI (EndFrameUpdate) (void);
EXPORT INT32 HWRAPI (IsPlaying) (INT32 handle);
EXPORT void HWRAPI (UpdateListener) (listener_data_t *data, INT32 num);
EXPORT void HWRAPI (UpdateSourceParms) (INT32 handle, INT32 vol, INT32 sep);
EXPORT void HWRAPI (SetGlobalSfxVolume) (INT32 volume);
EXPORT INT32 HWRAPI (SetCone) (INT32 handle, cone_def_t *cone_def);
EXPORT void HWRAPI (Update3DSource) (INT32 handle, source3D_pos_t *data);
EXPORT INT32 HWRAPI (ReloadSource) (INT32 handle, u_int sfxhandle);
EXPORT void HWRAPI (KillSource) (INT32 handle);
EXPORT void HWRAPI (KillSfx) (u_int sfxhandle);
EXPORT void HWRAPI (GetHW3DSTitle) (char *buf, size_t size);
#if !defined (_CREATE_DLL_)
struct hardware3ds_s
{
Startup pfnStartup;
AddSfx pfnAddSfx;
AddSource pfnAddSource;
StartSource pfnStartSource;
StopSource pfnStopSource;
GetHW3DSVersion pfnGetHW3DSVersion;
BeginFrameUpdate pfnBeginFrameUpdate;
EndFrameUpdate pfnEndFrameUpdate;
IsPlaying pfnIsPlaying;
UpdateListener pfnUpdateListener;
UpdateSourceParms pfnUpdateSourceParms;
SetGlobalSfxVolume pfnSetGlobalSfxVolume;
SetCone pfnSetCone;
Update3DSource pfnUpdate3DSource;
ReloadSource pfnReloadSource;
KillSource pfnKillSource;
KillSfx pfnKillSfx;
Shutdown pfnShutdown;
GetHW3DSTitle pfnGetHW3DSTitle;
};
extern struct hardware3ds_s hw3ds_driver;
#define HW3DS hw3ds_driver
#endif // _CREATE_DLL_
#endif // __HW_3DS_DRV_H__
+996
View File
@@ -0,0 +1,996 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright (C) 2001 by DooM Legacy Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//-----------------------------------------------------------------------------
/// \file
/// \brief Hardware 3D sound general code
#include "../doomdef.h"
#ifdef HW3SOUND
#include "../i_sound.h"
#include "../s_sound.h"
#include "../w_wad.h"
#include "../z_zone.h"
#include "../g_game.h"
#include "../tables.h"
#include "../sounds.h"
#include "../r_main.h"
#include "../r_things.h"
#include "../m_random.h"
#include "../p_local.h"
#include "hw3dsdrv.h"
#include "hw3sound.h"
#define ANGLE2DEG(x) (((double)(x)) / ((double)ANGLE_45/45))
#define NORM_PITCH 128
#define NORM_PRIORITY 64
#define NORM_SEP 128
#if 1
#define TPS(x) (x)
#else //Alam_GBC: MPS, not MPF!
#define TPS(x) ((float)(x)/(float)TICRATE)
#endif
struct hardware3ds_s hw3ds_driver;
typedef struct source_s
{
sfxinfo_t *sfxinfo;
const void *origin;
INT32 handle; // Internal source handle
channel_type_t type; // Sound type (attack, scream, etc)
} source_t;
typedef struct ambient_sdata_s
{
source3D_data_t left;
source3D_data_t right;
} ambient_sdata_t;
typedef struct ambient_source_s
{
source_t left;
source_t right;
} ambient_source_t;
// Static sources
// This sources always creates
static source_t p_attack_source; // Player attack source
static source_t p_attack_source2; // Player2 attack source
static source_t p_scream_source; // Player scream source
static source_t p_scream_source2; // Player2 scream source
static ambient_source_t ambient_source; // Ambinet sound sources
// abuse???
//static source3D_data_t p_attack_sdata; // ?? Now just holds precalculated player attack source data
//static source3D_data_t p_default_sdata;// ?? ---- // ---- // ---- // ---- player scream source data
static ambient_sdata_t ambient_sdata; // Precalculated datas of an ambient sound sources
// Stack of dynamic sources
static source_t *sources = NULL; // Much like original channels
static INT32 num_sources = 0;
// Current mode of 3D sound system
// Default is original (stereo) mode
INT32 hws_mode = HWS_DEFAULT_MODE;
//=============================================================================
void HW3S_SetSourcesNum(void)
{
INT32 i;
// Allocating the internal channels for mixing
// (the maximum number of sounds rendered
// simultaneously) within zone memory.
if (sources)
HW3S_StopSounds();
Z_Free(sources);
if (cv_numChannels.value <= STATIC_SOURCES_NUM)
I_Error("HW3S_SetSourcesNum: Number of sound sources cannot be less than %d\n", STATIC_SOURCES_NUM + 1);
num_sources = cv_numChannels.value - STATIC_SOURCES_NUM;
sources = (source_t *) Z_Malloc(num_sources * sizeof (*sources), PU_STATIC, 0);
// Free all channels for use
for (i = 0; i < num_sources; i++)
{
sources[i].sfxinfo = NULL;
sources[i].type = CT_NORMAL;
sources[i].handle = -1;
}
}
//=============================================================================
static void HW3S_KillSource(INT32 snum)
{
source_t * s = &sources[snum];
if (s->sfxinfo)
{
HW3DS.pfnStopSource(s->handle);
HW3DS.pfnKillSource(s->handle);
s->handle = -1;
s->sfxinfo->usefulness--;
s->origin = NULL;
s->sfxinfo = NULL;
}
}
//=============================================================================
/*
static void HW3S_StopSource(INT32 snum)
{
source_t * s = &sources[snum];
if (s->sfxinfo)
{
// stop the sound playing
HW3DS.pfnStopSource(s->handle);
}
}
*/
//=============================================================================
void HW3S_StopSound(void *origin)
{
INT32 snum;
for (snum = 0; snum < num_sources; snum++)
{
if (sources[snum].sfxinfo && sources[snum].origin == origin)
{
HW3S_KillSource(snum);
break;
}
}
}
void HW3S_StopSoundByID(void *origin, sfxenum_t sfx_id)
{
INT32 snum;
for (snum = 0; snum < num_sources; snum++)
{
if (sources[snum].sfxinfo == &S_sfx[sfx_id] && sources[snum].origin == origin)
{
HW3S_KillSource(snum);
break;
}
}
}
void HW3S_StopSoundByNum(sfxenum_t sfxnum)
{
INT32 snum;
for (snum = 0; snum < num_sources; snum++)
{
if (sources[snum].sfxinfo == &S_sfx[sfxnum])
{
HW3S_KillSource(snum);
break;
}
}
}
//=============================================================================
void HW3S_StopSounds(void)
{
INT32 snum;
// kill all playing sounds at start of level
// (trust me - a good idea)
for (snum = 0; snum < num_sources; snum++)
if (sources[snum].sfxinfo)
HW3S_KillSource(snum);
// Also stop all static sources
HW3DS.pfnStopSource(p_attack_source.handle);
HW3DS.pfnStopSource(p_attack_source2.handle);
HW3DS.pfnStopSource(p_scream_source.handle);
HW3DS.pfnStopSource(p_scream_source2.handle);
HW3DS.pfnStopSource(ambient_source.left.handle);
HW3DS.pfnStopSource(ambient_source.right.handle);
}
//=============================================================================
static INT32 HW3S_GetSource(const void *origin, sfxinfo_t *sfxinfo, boolean splitsound)
{
//
// If none available, return -1. Otherwise source #.
// source number to use
INT32 snum;
source_t * src;
INT32 sep = NORM_SEP, pitch = NORM_PITCH, volume = 255;
(void)splitsound;
// Find an open source
for (snum = 0, src = sources; snum < num_sources; src++, snum++)
{
if (!src->sfxinfo)
break;
#if 0
if (origin && src->origin == origin)
{
HW3S_KillSource(snum);
break;
}
#endif
}
#if 0
// Check to see if it is audible
if (origin && origin != listenmobj)
{
INT32 rc;
rc = S_AdjustSoundParams(listenmobj, origin, &volume, &sep, &pitch, sfxinfo);
if (!rc)
return -1;
}
#else
(void)origin;
(void)pitch;
(void)volume;
(void)sep;
#endif
// None available
if (snum == num_sources)
{
// Look for lower priority
for (snum = 0, src = sources; snum < num_sources; src++, snum++)
if (src->sfxinfo->priority <= sfxinfo->priority)
break;
if (snum == num_sources)
{
// No lower priority. Sorry, Charlie.
return -1;
}
else
{
// Otherwise, kick out lower priority
HW3S_KillSource(snum);
}
}
return snum;
}
//=============================================================================
static void HW3S_FillSourceParameters
(const mobj_t *origin,
source3D_data_t *data,
channel_type_t c_type)
{
fixed_t x = 0, y = 0, z = 0;
data->max_distance = MAX_DISTANCE;
data->min_distance = MIN_DISTANCE;
if (origin && origin != players[displayplayers[0]].mo)
{
data->head_relative = false;
data->pos.momx = TPS(FIXED_TO_FLOAT(origin->momx));
data->pos.momy = TPS(FIXED_TO_FLOAT(origin->momy));
data->pos.momz = TPS(FIXED_TO_FLOAT(origin->momz));
x = origin->x;
y = origin->y;
z = origin->z;
if (c_type == CT_ATTACK)
{
const angle_t an = origin->angle >> ANGLETOFINESHIFT;
x += FixedMul(16*FRACUNIT, FINECOSINE(an));
y += FixedMul(16*FRACUNIT, FINESINE(an));
z += origin->height >> 1;
}
else if (c_type == CT_SCREAM)
z += origin->height - (5 * FRACUNIT);
}
else
{
data->head_relative = true;
data->pos.momx = 0.0f;
data->pos.momy = 0.0f;
data->pos.momz = 0.0f;
}
data->pos.x = FIXED_TO_FLOAT(x);
data->pos.y = FIXED_TO_FLOAT(y);
data->pos.z = FIXED_TO_FLOAT(z);
}
#define HEADER_SIZE 8
//==============================================================
/*
static void make_outphase_sfx(void *dest, void *src, INT32 size)
{
SINT8 *s = (SINT8 *)src + HEADER_SIZE, *d = (SINT8 *)dest + HEADER_SIZE;
M_Memcpy(dest, src, HEADER_SIZE);
size -= HEADER_SIZE;
while (size--)
*d++ = -(*s++);
}
*/
//INT32 HW3S_Start3DSound(const void *origin, source3D_data_t *source_parm, cone_def_t *cone_parm, channel_type_t channel, INT32 sfx_id, INT32 vol, INT32 pitch);
//=============================================================================
INT32 HW3S_I_StartSound(const void *origin_p, source3D_data_t *source_parm, channel_type_t c_type, sfxenum_t sfx_id, INT32 volume, INT32 pitch, INT32 sep)
{
sfxinfo_t *sfx;
const mobj_t *origin = (const mobj_t *)origin_p;
source3D_data_t source3d_data;
INT32 s_num = 0;
source_t *source = NULL;
mobj_t *listenmobj = players[displayplayers[0]].mo; // TODO: Kart 4P does not support sounds properly here
mobj_t *listenmobj2 = NULL;
if (splitscreen) listenmobj2 = players[displayplayers[1]].mo;
if (sound_disabled)
return -1;
sfx = &S_sfx[sfx_id];
if (sfx->skinsound!=-1 && origin && origin->skin)
{
// it redirect player sound to the sound in the skin table
sfx_id = ((skin_t *)origin->skin)->soundsid[sfx->skinsound];
sfx = &S_sfx[sfx_id];
}
if (!sfx->data)
sfx->data = HW3S_GetSfx(sfx);
// judgecutor 08-16-2002
// Sound pitching for both Doom and Heretic
#if 0
if (cv_rndsoundpitch.value)
{
/*if (gamemode != heretic)
{
if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit)
pitch += 8 - (M_RandomByte()&15);
else if (sfx_id != sfx_itemup && sfx_id != sfx_tink)
pitch += 16 - (M_RandomByte()&31);
}
else*/
pitch = 128 + (M_RandomByte() & 7) - (M_RandomByte() & 7);
}
#endif
if (pitch < 0)
pitch = NORMAL_PITCH;
if (pitch > 255)
pitch = 255;
if (sep < 0)
sep = 128;
if (splitscreen && listenmobj2) // Copy the sound for the split player
{
if (c_type != CT_NORMAL && origin && (origin == listenmobj2))
{
if (c_type == CT_ATTACK)
{
if (origin == listenmobj2)
source = &p_attack_source;
else
source = &p_attack_source2;
}
else
{
if (origin == listenmobj2)
source = &p_scream_source;
else
source = &p_scream_source2;
}
if (source->sfxinfo != sfx)
{
HW3DS.pfnStopSource(source->handle);
source->handle = HW3DS.pfnReloadSource(source->handle, sfx->volume);
//I_OutputMsg("PlayerSound data reloaded\n");
}
}
else if (c_type == CT_AMBIENT)
{
// sfx_data_t outphased_sfx;
if (ambient_source.left.sfxinfo != sfx)
{
HW3DS.pfnStopSource(ambient_source.left.handle);
HW3DS.pfnStopSource(ambient_source.right.handle);
// judgecutor:
// Outphased sfx's temporarily not used!!!
/*
outphased_sfx.data = Z_Malloc(sfx_data.length, PU_STATIC, 0);
make_outphase_sfx(outphased_sfx.data, sfx_data.data, sfx_data.length);
outphased_sfx.length = sfx_data.length;
outphased_sfx.id = sfx_data.id;
*/
ambient_source.left.handle = HW3DS.pfnReloadSource(ambient_source.left.handle, (u_int)sfx->length);
//ambient_source.right.handle = HW3DS.pfnReloadSource(ambient_source.right.handle, &outphased_sfx);
ambient_source.right.handle = HW3DS.pfnReloadSource(ambient_source.right.handle, (u_int)sfx->length);
ambient_source.left.sfxinfo = ambient_source.right.sfxinfo = sfx;
//Z_Free(outphased_sfx.data);
}
HW3DS.pfnUpdateSourceParms(ambient_source.left.handle, volume, -1);
HW3DS.pfnUpdateSourceParms(ambient_source.right.handle, volume, -1);
if (sfx->usefulness++ < 0)
sfx->usefulness = -1;
// Ambient sound is special case
HW3DS.pfnStartSource(ambient_source.left.handle);
HW3DS.pfnStartSource(ambient_source.right.handle);
}
else
{
s_num = HW3S_GetSource(origin, sfx, true);
if (s_num < 0)
{
//I_OutputMsg("No free source, aborting\n");
return -1;
}
source = &sources[s_num];
if (origin && c_type == CT_NORMAL)
{
if (!source_parm)
{
source_parm = &source3d_data;
source3d_data.permanent = 0;
HW3S_FillSourceParameters(origin, source_parm, c_type);
}
source->handle = HW3DS.pfnAddSource(source_parm, (u_int)sfx->length);
}
else
source->handle = HW3DS.pfnAddSource(NULL, (u_int)sfx->length);
}
// increase the usefulness
if (sfx->usefulness++ < 0)
sfx->usefulness = -1;
source->sfxinfo = sfx;
source->origin = origin;
HW3DS.pfnStartSource(source->handle);
}
if (c_type != CT_NORMAL && origin && (origin == listenmobj))
{
if (c_type == CT_ATTACK)
{
if (origin == listenmobj)
source = &p_attack_source;
else
source = &p_attack_source2;
}
else
{
if (origin == listenmobj)
source = &p_scream_source;
else
source = &p_scream_source2;
}
if (source->sfxinfo != sfx)
{
HW3DS.pfnStopSource(source->handle);
source->handle = HW3DS.pfnReloadSource(source->handle, sfx->volume);
//I_OutputMsg("PlayerSound data reloaded\n");
}
}
else if (c_type == CT_AMBIENT)
{
// sfx_data_t outphased_sfx;
if (ambient_source.left.sfxinfo != sfx)
{
HW3DS.pfnStopSource(ambient_source.left.handle);
HW3DS.pfnStopSource(ambient_source.right.handle);
// judgecutor:
// Outphased sfx's temporarily not used!!!
/*
outphased_sfx.data = Z_Malloc(sfx_data.length, PU_STATIC, 0);
make_outphase_sfx(outphased_sfx.data, sfx_data.data, sfx_data.length);
outphased_sfx.length = sfx_data.length;
outphased_sfx.id = sfx_data.id;
*/
ambient_source.left.handle = HW3DS.pfnReloadSource(ambient_source.left.handle, (u_int)sfx->length);
//ambient_source.right.handle = HW3DS.pfnReloadSource(ambient_source.right.handle, &outphased_sfx);
ambient_source.right.handle = HW3DS.pfnReloadSource(ambient_source.right.handle, (u_int)sfx->length);
ambient_source.left.sfxinfo = ambient_source.right.sfxinfo = sfx;
//Z_Free(outphased_sfx.data);
}
HW3DS.pfnUpdateSourceParms(ambient_source.left.handle, volume, -1);
HW3DS.pfnUpdateSourceParms(ambient_source.right.handle, volume, -1);
if (sfx->usefulness++ < 0)
sfx->usefulness = -1;
// Ambient sound is special case
HW3DS.pfnStartSource(ambient_source.left.handle);
HW3DS.pfnStartSource(ambient_source.right.handle);
return -1;
}
else
{
s_num = HW3S_GetSource(origin, sfx, false);
if (s_num < 0)
{
//I_OutputMsg("No free source, aborting\n");
return -1;
}
source = &sources[s_num];
if (origin && c_type == CT_NORMAL)
{
if (!source_parm)
{
source_parm = &source3d_data;
source3d_data.permanent = 0;
HW3S_FillSourceParameters(origin, source_parm, c_type);
}
source->handle = HW3DS.pfnAddSource(source_parm, (u_int)sfx->length);
}
else
source->handle = HW3DS.pfnAddSource(NULL, (u_int)sfx->length);
}
// increase the usefulness
if (sfx->usefulness++ < 0)
sfx->usefulness = -1;
source->sfxinfo = sfx;
source->origin = origin;
HW3DS.pfnStartSource(source->handle);
return s_num;
}
// Start normal sound
//=============================================================================
void HW3S_StartSound(const void *origin, sfxenum_t sfx_id)
{
HW3S_I_StartSound(origin, NULL, CT_NORMAL, sfx_id, 255, NORMAL_PITCH, NORMAL_SEP);
}
//=============================================================================
void S_StartAttackSound(const void *origin, sfxenum_t sfx_id)
{
if (hws_mode != HWS_DEFAULT_MODE)
HW3S_I_StartSound(origin, NULL, CT_ATTACK, sfx_id, 255, NORMAL_PITCH, NORMAL_SEP);
else
S_StartSound(origin, sfx_id);
}
void S_StartScreamSound(const void *origin, sfxenum_t sfx_id)
{
if (hws_mode != HWS_DEFAULT_MODE)
HW3S_I_StartSound(origin, NULL, CT_SCREAM, sfx_id, 255, NORMAL_PITCH, NORMAL_SEP);
else
S_StartSound(origin, sfx_id);
}
#if 0 /// NOTE: not used
void S_StartAmbientSound(sfxenum_t sfx_id, INT32 volume)
{
if (hws_mode != HWS_DEFAULT_MODE)
{
volume += 30;
if (volume > 255)
volume = 255;
HW3S_I_StartSound(NULL, NULL, CT_AMBIENT, sfx_id, volume, NORMAL_PITCH, NORMAL_SEP);
}
else
S_StartSoundAtVolume(NULL, sfx_id, volume);
}
#endif
FUNCMATH static inline float AmbientPos(angle_t an)
{
const fixed_t fm = FixedMul(FLOAT_TO_FIXED(MIN_DISTANCE), FINESINE(an>>ANGLETOFINESHIFT));
return FIXED_TO_FLOAT(fm);
}
//=============================================================================
INT32 HW3S_Init(I_Error_t FatalErrorFunction, snddev_t *snd_dev)
{
INT32 succ;
source3D_data_t source_data;
if (HW3DS.pfnStartup(FatalErrorFunction, snd_dev))
{
// Attack source
source_data.head_relative = 1;
source_data.pos.x = 0.0f;
source_data.pos.y = 16.0f;
source_data.pos.z = -FIXED_TO_FLOAT(mobjinfo[MT_PLAYER].height >> 1);
source_data.pos.momx = 0.0f;
source_data.pos.momy = 0.0f;
source_data.pos.momz = 0.0f;
source_data.min_distance = MIN_DISTANCE;
source_data.max_distance = MAX_DISTANCE;
source_data.permanent = 1;
p_attack_source.sfxinfo = NULL;
M_Memcpy(&p_attack_source2, &p_attack_source, sizeof (source_t));
p_attack_source.handle = HW3DS.pfnAddSource(&source_data, sfx_None);
p_attack_source2.handle = HW3DS.pfnAddSource(&source_data, sfx_None);
// Scream source
source_data.pos.y = 0;
source_data.pos.z = 0;
p_scream_source.sfxinfo = NULL;
M_Memcpy(&p_scream_source2, &p_scream_source, sizeof (source_t));
p_scream_source.handle = HW3DS.pfnAddSource(&source_data, sfx_None);
p_scream_source2.handle = HW3DS.pfnAddSource(&source_data, sfx_None);
//FIXED_TO_FLOAT(mobjinfo[MT_PLAYER].height - (5 * FRACUNIT));
// Ambient sources (left and right) at 210 and 330 degree
// relative to listener
memset(&ambient_sdata, 0, sizeof (ambient_sdata));
ambient_sdata.left.head_relative = 1;
ambient_sdata.left.pos.x = ambient_sdata.left.pos.y = AmbientPos(ANG210);
ambient_sdata.left.max_distance = MAX_DISTANCE;
ambient_sdata.left.min_distance = MIN_DISTANCE;
ambient_sdata.left.permanent = 1;
M_Memcpy(&ambient_sdata.right, &ambient_sdata.left, sizeof (source3D_data_t));
ambient_sdata.right.pos.x = -ambient_sdata.left.pos.x;
ambient_source.left.handle = HW3DS.pfnAddSource(&ambient_sdata.left, sfx_None);
ambient_source.right.handle = HW3DS.pfnAddSource(&ambient_sdata.right, sfx_None);
succ = p_attack_source.handle > -1 && p_scream_source.handle > -1 &&
p_attack_source2.handle > -1 && p_scream_source2.handle > -1 &&
ambient_source.left.handle > -1 && ambient_source.right.handle > -1;
//I_OutputMsg("Player handles: attack %d, default %d\n", p_attack_source.handle, p_scream_source.handle);
return succ;
}
return 0;
}
//=============================================================================
INT32 HW3S_GetVersion(void)
{
return HW3DS.pfnGetHW3DSVersion();
}
//=============================================================================
void HW3S_BeginFrameUpdate(void)
{
if (hws_mode != HWS_DEFAULT_MODE)
HW3DS.pfnBeginFrameUpdate();
}
//=============================================================================
void HW3S_EndFrameUpdate(void)
{
if (hws_mode != HWS_DEFAULT_MODE)
HW3DS.pfnEndFrameUpdate();
}
//=============================================================================
INT32 HW3S_SoundIsPlaying(INT32 handle)
{
return HW3DS.pfnIsPlaying(handle);
}
INT32 HW3S_OriginPlaying(void *origin)
{
INT32 snum;
if (!origin)
return 0;
for (snum = 0; snum < num_sources; snum++)
if (sources[snum].origin == origin)
return 1;
return 0;
}
INT32 HW3S_IdPlaying(sfxenum_t id)
{
INT32 snum;
for (snum = 0; snum < num_sources; snum++)
if ((size_t)(sources[snum].sfxinfo - S_sfx) == (size_t)id)
return 1;
return 0;
}
INT32 HW3S_SoundPlaying(void *origin, sfxenum_t id)
{
INT32 snum;
if (!origin)
return 0;
for (snum = 0; snum < num_sources; snum++)
{
if (sources[snum].origin == origin
&& (size_t)(sources[snum].sfxinfo - S_sfx) == (size_t)id)
return 1;
}
return 0;
}
//=============================================================================
static void HW3S_UpdateListener(mobj_t *listener)
{
listener_data_t data;
if (!listener || !listener->player)
return;
if (camera.chase)
{
data.x = FIXED_TO_FLOAT(camera.x);
data.y = FIXED_TO_FLOAT(camera.y);
data.z = FIXED_TO_FLOAT(camera.z + camera.height - (5 * FRACUNIT));
data.f_angle = ANGLE2DEG(camera.angle);
data.h_angle = ANGLE2DEG(camera.aiming);
data.momx = TPS(FIXED_TO_FLOAT(camera.momx));
data.momy = TPS(FIXED_TO_FLOAT(camera.momy));
data.momz = TPS(FIXED_TO_FLOAT(camera.momz));
}
else
{
data.x = FIXED_TO_FLOAT(listener->x);
data.y = FIXED_TO_FLOAT(listener->y);
data.z = FIXED_TO_FLOAT(listener->z + listener->height - (5 * FRACUNIT));
data.f_angle = ANGLE2DEG(listener->angle);
data.h_angle = ANGLE2DEG(listener->player->aiming);
data.momx = TPS(FIXED_TO_FLOAT(listener->momx));
data.momy = TPS(FIXED_TO_FLOAT(listener->momy));
data.momz = TPS(FIXED_TO_FLOAT(listener->momz));
}
HW3DS.pfnUpdateListener(&data, 1);
}
static void HW3S_UpdateListener2(mobj_t *listener)
{
listener_data_t data;
if (!listener || !listener->player)
{
HW3DS.pfnUpdateListener(NULL, 2);
return;
}
if (camera2.chase)
{
data.x = FIXED_TO_FLOAT(camera2.x);
data.y = FIXED_TO_FLOAT(camera2.y);
data.z = FIXED_TO_FLOAT(camera2.z + camera2.height - (5 * FRACUNIT));
data.f_angle = ANGLE2DEG(camera2.angle);
data.h_angle = ANGLE2DEG(camera2.aiming);
data.momx = TPS(FIXED_TO_FLOAT(camera2.momx));
data.momy = TPS(FIXED_TO_FLOAT(camera2.momy));
data.momz = TPS(FIXED_TO_FLOAT(camera2.momz));
}
else
{
data.x = FIXED_TO_FLOAT(listener->x);
data.y = FIXED_TO_FLOAT(listener->y);
data.z = FIXED_TO_FLOAT(listener->z + listener->height - (5 * FRACUNIT));
data.f_angle = ANGLE2DEG(listener->angle);
data.h_angle = ANGLE2DEG(listener->player->aiming);
data.momx = TPS(FIXED_TO_FLOAT(listener->momx));
data.momy = TPS(FIXED_TO_FLOAT(listener->momy));
data.momz = TPS(FIXED_TO_FLOAT(listener->momz));
}
HW3DS.pfnUpdateListener(&data, 2);
}
void HW3S_SetSfxVolume(INT32 volume)
{
HW3DS.pfnSetGlobalSfxVolume(volume);
}
static void HW3S_Update3DSource(source_t *src)
{
source3D_data_t data;
data.permanent = 0;
HW3S_FillSourceParameters(src->origin, &data, src->type);
HW3DS.pfnUpdate3DSource(src->handle, &data.pos);
}
void HW3S_UpdateSources(void)
{
mobj_t *listener = players[displayplayers[0]].mo;
mobj_t *listener2 = NULL;
source_t *src;
INT32 audible, snum, volume, sep, pitch;
if (splitscreen) listener2 = players[displayplayers[1]].mo;
HW3S_UpdateListener2(listener2);
HW3S_UpdateListener(listener);
for (snum = 0, src = sources; snum < num_sources; src++, snum++)
{
if (src->sfxinfo)
{
#if 0
if (HW3DS.pfnIsPlaying(src->handle))
{
if (src->origin)
{
// initialize parameters
volume = 255; // 8 bits internal volume precision
pitch = NORM_PITCH;
sep = NORM_SEP;
// check non-local sounds for distance clipping
// or modify their params
if (src->origin && listener != src->origin && !(listener2 && src->origin == listener2))
{
INT32 audible2;
INT32 volume2 = volume, sep2 = sep, pitch2 = pitch;
audible = S_AdjustSoundParams(listener, src->origin, &volume, &sep, &pitch,
src->sfxinfo);
if (listener2)
{
audible2 = S_AdjustSoundParams(listener2,
src->origin, &volume2, &sep2, &pitch2, src->sfxinfo);
if (audible2 && (!audible || (audible && volume2 > volume)))
{
audible = true;
volume = volume2;
sep = sep2;
pitch = pitch2;
}
}
if (audible)
HW3S_Update3DSource(src); // Update positional sources
else
HW3S_KillSource(snum); //Kill it!
}
}
}
else
{
// Source allocated but stopped. Kill.
HW3S_KillSource(snum);
}
#else
if (src->origin && listener != src->origin && !(listener2 && src->origin == listener2))
HW3S_Update3DSource(src); // Update positional sources
(void)pitch;
(void)sep;
(void)volume;
(void)audible;
#endif
}
}
}
void HW3S_Shutdown(void)
{
HW3DS.pfnShutdown();
}
void *HW3S_GetSfx(sfxinfo_t *sfx)
{
sfx_data_t sfx_data;
if (sfx->lumpnum == LUMPERROR)
sfx->lumpnum = S_GetSfxLumpNum (sfx);
sfx_data.length = W_LumpLength(sfx->lumpnum);
sfx_data.data = Z_Malloc(sfx_data.length, PU_SOUND, &sfx->data);
W_ReadLump(sfx->lumpnum, sfx_data.data);
sfx_data.priority = sfx->priority;
sfx->length = HW3DS.pfnAddSfx(&sfx_data);
Z_ChangeTag(sfx->data, PU_CACHE);
return sfx_data.data;
}
void HW3S_FreeSfx(sfxinfo_t *sfx)
{
INT32 snum;
for (snum = 0; snum < num_sources; snum++)
{
if (sources[snum].sfxinfo == sfx)
{
HW3S_KillSource(snum);
break;
}
}
if (sfx->length > 0)
HW3DS.pfnKillSfx((u_int)sfx->length);
sfx->length = 0;
sfx->lumpnum = LUMPERROR;
Z_Free(sfx->data);
sfx->data = NULL;
}
#endif
+106
View File
@@ -0,0 +1,106 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright (C) 2001 by DooM Legacy Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//-----------------------------------------------------------------------------
/// \file
/// \brief High-level functions of hardware 3D sound
#ifndef __HW3_SOUND_H__
#define __HW3_SOUND_H__
#ifdef HW3SOUND
#include "hws_data.h"
//#include "../s_sound.h"
//#include "../p_mobj.h"
// Default sound mode (original stereo mode)
enum
{
HWS_DEFAULT_MODE = 0,
HWS_DS3D,
HWS_OTHER,
HWS_FMOD3D,
HWS_OPENAL,
};
typedef enum
{
CT_NORMAL = 0,
CT_ATTACK,
CT_SCREAM,
CT_AMBIENT,
} channel_type_t;
extern INT32 hws_mode; // Current sound mode
#if defined (HW3DS) || defined (DOXYGEN)
INT32 HW3S_Init(I_Error_t FatalErrorFunction, snddev_t *snd_dev);
#endif
void HW3S_Shutdown(void);
INT32 HW3S_GetVersion(void);
// Common case - start 3D or 2D source
void HW3S_StartSound(const void *origin, sfxenum_t sfx_id);
// Special cases of 3D sources
void S_StartAmbientSound(sfxenum_t sfx_id, INT32 volume);
void S_StartAttackSound(const void *origin, sfxenum_t sfx_id);
void S_StartScreamSound(const void *origin, sfxenum_t sfx_id);
// Starts 3D sound with specified parameters
// origin - for object movement tracking. NULL are possible value (no movement tracking)
// source_parm - 3D source parameters (position etc.)
// cone_parm - 3D source cone parameters. NULL are possible value (default cone will be used)
// channel -
// sfx_id - sfx id
// vol - sound volume
// pitch - sound pitching value
// Returns: - sound id
INT32 HW3S_I_StartSound(const void *origin, source3D_data_t *source_parm, channel_type_t channel, sfxenum_t sfx_id, INT32 vol, INT32 pitch, INT32 sep);
void HW3S_StopSoundByID(void *origin, sfxenum_t sfx_id);
void HW3S_StopSoundByNum(sfxenum_t sfxnum);
void HW3S_StopSound(void *origin);
void HW3S_StopSounds(void);
void HW3S_BeginFrameUpdate(void);
void HW3S_EndFrameUpdate(void);
void HW3S_UpdateSources(void);
void HW3S_SetSfxVolume(INT32 volume);
// Utility functions
INT32 HW3S_SoundIsPlaying(INT32 handle);
void HW3S_SetSourcesNum(void);
INT32 HW3S_OriginPlaying(void *origin);
INT32 HW3S_IdPlaying(sfxenum_t id);
INT32 HW3S_SoundPlaying(void *origin, sfxenum_t id);
void *HW3S_GetSfx(sfxinfo_t *sfx);
void HW3S_FreeSfx(sfxinfo_t *sfx);
#else // HW3SOUND
//#define S_StartAmbientSound(i,v) S_StartSoundAtVolume(NULL, i, v)
#define S_StartAttackSound S_StartSound
#define S_StartScreamSound S_StartSound
#endif // HW3SOUND
INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source,
INT32 *vol, INT32 *sep, INT32 *pitch, sfxinfo_t *sfxinfo);
#endif // __HW3_SOUND_H__
+43 -53
View File
@@ -15,10 +15,9 @@
#include "hw_main.h"
#include "../i_system.h"
#include "../doomdef.h"
#include "../qs22j.h"
// The texture for the next polygon given to HWR_ProcessPolygon.
// Set with HWR_SetCurrentTexture.
GLMipmap_t *current_texture = NULL;
@@ -65,7 +64,7 @@ void HWR_StartBatching(void)
currently_batching = true;
}
// This replaces the direct calls to GL_SetTexture in cases where batching is available.
// This replaces the direct calls to pfnSetTexture in cases where batching is available.
// The texture selection is saved for the next HWR_ProcessPolygon call.
// Doing this was easier than getting a texture pointer to HWR_ProcessPolygon.
void HWR_SetCurrentTexture(GLMipmap_t *texture)
@@ -76,7 +75,7 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture)
}
else
{
GL_SetTexture(texture);
HWD.pfnSetTexture(texture);
}
}
@@ -88,10 +87,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
if (currently_batching)
{
if (!pSurf)
{
I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to
}
if (polygonArraySize == polygonArrayAllocSize)
{
PolygonArrayEntry* new_array;
@@ -133,8 +129,8 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
}
else
{
GL_SetShader((shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target);
GL_DrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
HWD.pfnSetShader((shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target);
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
}
}
@@ -144,19 +140,27 @@ static int comparePolygons(const void *p1, const void *p2)
PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
int diff;
INT64 diff64;
UINT32 downloaded1 = 0;
UINT32 downloaded2 = 0;
int shader1 = (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) ? -1 : poly1->shader;
int shader2 = (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) ? -1 : poly2->shader;
int shader1 = poly1->shader;
int shader2 = poly2->shader;
// make skywalls and horizon lines first in order
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
shader1 = -1;
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
shader2 = -1;
diff = shader1 - shader2;
if (diff != 0) return diff;
// skywalls and horizon lines must retain their order for horizon lines to work
if (shader1 == -1 && shader2 == -1)
return poly1 - poly2;
diff = shader1 - shader2;
if (diff != 0) return diff;
UINT32 downloaded1 = poly1->texture ? poly1->texture->downloaded : 0; // there should be a opengl texture name here, usable for comparisons
UINT32 downloaded2 = poly2->texture ? poly2->texture->downloaded : 0;
if (poly1->texture)
downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons
if (poly2->texture)
downloaded2 = poly2->texture->downloaded;
diff64 = downloaded1 - downloaded2;
if (diff64 != 0) return diff64;
@@ -175,10 +179,6 @@ static int comparePolygons(const void *p1, const void *p2)
diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start;
if (diff != 0) return diff;
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
if (diff != 0) return diff;
diff = poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional;
return diff;
}
@@ -189,15 +189,21 @@ static int comparePolygonsNoShaders(const void *p1, const void *p2)
int diff;
INT64 diff64;
GLMipmap_t *texture1 = (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) ? NULL : poly1->texture;
GLMipmap_t *texture2 = (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) ? NULL : poly2->texture;
GLMipmap_t *texture1 = poly1->texture;
GLMipmap_t *texture2 = poly2->texture;
UINT32 downloaded1 = 0;
UINT32 downloaded2 = 0;
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
texture1 = NULL;
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
texture2 = NULL;
if (texture1)
downloaded1 = texture1->downloaded; // there should be a opengl texture name here, usable for comparisons
if (texture2)
downloaded2 = texture2->downloaded;
// skywalls and horizon lines must retain their order for horizon lines to work
if (!texture1 && !texture2)
return poly1 - poly2;
UINT32 downloaded1 = texture1 ? texture1->downloaded : 0; // there should be a opengl texture name here, usable for comparisons
UINT32 downloaded2 = texture2 ? texture2->downloaded : 0;
diff64 = downloaded1 - downloaded2;
if (diff64 != 0) return diff64;
@@ -221,7 +227,7 @@ void HWR_RenderBatches(void)
int currentShader;
int nextShader = 0;
GLMipmap_t *currentTexture = NULL;
GLMipmap_t *currentTexture;
GLMipmap_t *nextTexture = NULL;
FBITFIELD currentPolyFlags = 0;
FBITFIELD nextPolyFlags = 0;
@@ -231,17 +237,13 @@ void HWR_RenderBatches(void)
int i;
if (!currently_batching)
{
I_Error("HWR_RenderBatches called without starting batching");
}
nextSurfaceInfo.LightInfo.fade_end = 0;
nextSurfaceInfo.LightInfo.fade_start = 0;
nextSurfaceInfo.LightInfo.light_level = 0;
nextSurfaceInfo.LightInfo.directional = false;
currently_batching = false;// no longer collecting batches
if (!polygonArraySize)
{
ps_hw_numpolys.value.i = ps_hw_numcalls.value.i = ps_hw_numshaders.value.i
@@ -249,7 +251,6 @@ void HWR_RenderBatches(void)
= ps_hw_numcolors.value.i = 0;
return;// nothing to draw
}
// init stats vars
ps_hw_numpolys.value.i = polygonArraySize;
ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0;
@@ -290,15 +291,15 @@ void HWR_RenderBatches(void)
if (cv_glshaders.value && gl_shadersavailable)
{
GL_SetShader(currentShader);
HWD.pfnSetShader(currentShader);
}
if (currentPolyFlags & PF_NoTexture)
currentTexture = NULL;
else
GL_SetTexture(currentTexture);
HWD.pfnSetTexture(currentTexture);
while (1) // note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons)
while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons)
{
int firstIndex;
int lastIndex;
@@ -368,28 +369,23 @@ void HWR_RenderBatches(void)
nextTexture = nextEntry->texture;
nextPolyFlags = nextEntry->polyFlags;
nextSurfaceInfo = nextEntry->surf;
if (nextPolyFlags & PF_NoTexture)
nextTexture = 0;
if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable)
{
changeState = true;
changeShader = true;
}
if (currentTexture != nextTexture)
{
changeState = true;
changeTexture = true;
}
if (currentPolyFlags != nextPolyFlags)
{
changeState = true;
changePolyFlags = true;
}
if (cv_glshaders.value && gl_shadersavailable)
{
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba ||
@@ -397,8 +393,7 @@ void HWR_RenderBatches(void)
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional)
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
{
changeState = true;
changeSurfaceInfo = true;
@@ -417,7 +412,7 @@ void HWR_RenderBatches(void)
if (changeState || stopFlag)
{
// execute draw call
GL_DrawIndexedTriangles(&currentSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray);
HWD.pfnDrawIndexedTriangles(&currentSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray);
// update stats
ps_hw_numcalls.value.i++;
ps_hw_numverts.value.i += finalIndexWritePos;
@@ -425,35 +420,31 @@ void HWR_RenderBatches(void)
finalVertexWritePos = 0;
finalIndexWritePos = 0;
}
else
continue;
else continue;
// if we're here then either its time to stop or time to change state
if (stopFlag)
break;
if (stopFlag) break;
// change state according to change bools and next vars, update current vars and reset bools
if (changeState)
{
if (changeShader)
{
GL_SetShader(nextShader);
HWD.pfnSetShader(nextShader);
currentShader = nextShader;
changeShader = false;
ps_hw_numshaders.value.i++;
}
if (changeTexture)
{
// texture should be already ready for use from calls to GL_SetTexture during batch collection
GL_SetTexture(nextTexture);
// texture should be already ready for use from calls to SetTexture during batch collection
HWD.pfnSetTexture(nextTexture);
currentTexture = nextTexture;
changeTexture = false;
ps_hw_numtextures.value.i++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
@@ -461,7 +452,6 @@ void HWR_RenderBatches(void)
ps_hw_numpolyflags.value.i++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
+1 -3
View File
@@ -15,9 +15,7 @@
#include "hw_defs.h"
#include "hw_data.h"
#include "hw_gl.h"
extern boolean currently_batching;
#include "hw_drv.h"
typedef struct
{
+3 -3
View File
@@ -369,7 +369,7 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
{
//x,y,dx,dy (like a divline)
line_t *line = lseg->linedef;
// portal check
if (!gl_maphasportals && line->special == 40 && lseg->side == 0)
{
@@ -380,7 +380,7 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
if (line2 >= 0) // found it!
gl_maphasportals = 1;
}
p1.x = FIXED_TO_FLOAT(lseg->side ? line->v2->x : line->v1->x);
p1.y = FIXED_TO_FLOAT(lseg->side ? line->v2->y : line->v1->y);
p2.x = FIXED_TO_FLOAT(lseg->side ? line->v1->x : line->v2->x);
@@ -523,7 +523,7 @@ static void loading_status(void)
x = BASEVIDWIDTH/2;
y = BASEVIDHEIGHT/2;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Black background to match fade in effect
//V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_PATCH)); // SRB2 background, ehhh too bright.
//V_DrawPatchFill(W_CachePatchName("SRB2BACK",PU_CACHE)); // SRB2 background, ehhh too bright.
M_DrawTextBox(x-58, y-8, 13, 1);
V_DrawString(x-50, y, V_YELLOWMAP, "Loading...");
V_DrawRightAlignedString(x+50, y, V_YELLOWMAP, s);
+228 -567
View File
File diff suppressed because it is too large. Load diff
+5 -3
View File
@@ -314,6 +314,8 @@ void gld_clipper_Clear(void)
cliphead = NULL;
}
#define RMUL (1.6f/1.333333f)
angle_t gld_FrustumAngle(angle_t tiltangle)
{
double clipfov;
@@ -331,11 +333,11 @@ angle_t gld_FrustumAngle(angle_t tiltangle)
// ok, this is a gross hack that barely works...
// but at least it doesn't overestimate too much...
clipfov = atan(1 / projMatrix[0]) * 360.0f / M_PIl;
clipfov = atan(1 / projMatrix[0]) * 360 / M_PI;
floatangle = 2.0f + (45.0f + (tilt / 1.9f)) * clipfov / 90.0f;
if (floatangle >= 180.0)
return 0xffffffff;
a1 = (angle_t)xs_CRoundToInt(ANG1 * floatangle);
a1 = (angle_t)(ANG1 * (int)floatangle);
return a1;
}
@@ -456,4 +458,4 @@ boolean gld_SphereInFrustum(float x, float y, float z, float radius)
}
return true;
}
#endif
#endif
+33 -29
View File
@@ -23,58 +23,62 @@
typedef enum GLTextureFormat_e
{
GL_TEXFMT_P_8 = 0x01, /* 8-bit palette */
GL_TEXFMT_AP_88 = 0x02, /* 8-bit alpha, 8-bit palette */
GL_TEXFMT_P_8 = 0x01, /* 8-bit palette */
GL_TEXFMT_AP_88 = 0x02, /* 8-bit alpha, 8-bit palette */
GL_TEXFMT_RGBA = 0x10, /* 32 bit RGBA! */
GL_TEXFMT_RGBA = 0x10, /* 32 bit RGBA! */
GL_TEXFMT_ALPHA_8 = 0x20, /* (0..0xFF) alpha */
GL_TEXFMT_INTENSITY_8 = 0x21, /* (0..0xFF) intensity */
GL_TEXFMT_ALPHA_INTENSITY_88 = 0x22,
GL_TEXFMT_ALPHA_8 = 0x20, /* (0..0xFF) alpha */
GL_TEXFMT_INTENSITY_8 = 0x21, /* (0..0xFF) intensity */
GL_TEXFMT_ALPHA_INTENSITY_88 = 0x22,
} GLTextureFormat_t;
// Colormap structure for mipmaps.
struct GLColormap_s
{
const UINT8 *source;
UINT8 data[256];
};
typedef struct GLColormap_s GLColormap_t;
// Texture information (misleadingly named "mipmap" all over the code.)
// The *data pointer holds the address of the graphics data cached in heap memory.
// NULL if the texture is not in SRB2's heap cache.
// data holds the address of the graphics data cached in heap memory
// NULL if the texture is not in Doom heap cache.
struct GLMipmap_s
{
// for UpdateTexture
GLTextureFormat_t format;
void *data;
GLTextureFormat_t format;
void *data;
UINT32 flags;
UINT16 width, height;
UINT32 downloaded; // The GPU has this texture.
UINT32 flags;
UINT16 width, height;
UINT32 downloaded; // tex_downloaded
struct GLMipmap_s *nextcolormap;
struct GLColormap_s *colormap;
struct GLMipmap_s *nextcolormap;
const UINT8 *colormap;
};
typedef struct GLMipmap_s GLMipmap_t;
//
// Level textures, as cached for hardware rendering.
// Doom texture info, as cached for hardware rendering
//
struct GLMapTexture_s
{
GLMipmap_t mipmap;
float scaleX; //used for scaling textures on walls
float scaleX; //used for scaling textures on walls
float scaleY;
};
typedef struct GLMapTexture_s GLMapTexture_t;
// Patch information for the hardware renderer.
// a cached patch as converted to hardware format, holding the original patch_t
// header so that the existing code can retrieve ->width, ->height as usual
// This is returned by W_CachePatchNum()/W_CachePatchName(), when rendermode
// is 'render_opengl'. Else it returns the normal patch_t data.
struct GLPatch_s
{
GLMipmap_t *mipmap;
// the 4 first fields come right away from the original patch_t
INT16 width;
INT16 height;
INT16 leftoffset; // pixels to the left of origin
INT16 topoffset; // pixels below the origin
//
float max_s,max_t;
UINT16 wadnum; // the software patch lump num for when the hardware patch
UINT16 lumpnum; // was flushed, and we need to re-create it
void *rawpatch; // :^)
GLMipmap_t *mipmap;
boolean notfound; // if the texture file was not found, mark it here (used in model texture loading)
};
typedef struct GLPatch_s GLPatch_t;
+39 -76
View File
@@ -121,33 +121,42 @@ typedef struct
poly_t *planepoly; // the generated convex polygon
} extrasubsector_t;
// Kart features
#define USE_FTRANSFORM_ANGLEZ
#define USE_FTRANSFORM_MIRROR
// Vanilla features
//#define USE_MODEL_NEXTFRAME
typedef struct
{
FLOAT x,y,z; // position
FLOAT anglex, angley, anglez; // aimingangle / viewangle
FLOAT scalex, scaley, scalez;
FLOAT fovangle;
#ifdef USE_FTRANSFORM_ANGLEZ
FLOAT anglex,angley,anglez; // aimingangle / viewangle
FLOAT anglex2,anglez2; // secondaries
#else
FLOAT anglex,angley; // aimingangle / viewangle
FLOAT anglex2; // secondaries
#endif
FLOAT scalex,scaley,scalez;
FLOAT spritexscale,spriteyscale;
FLOAT fovxangle, fovyangle;
UINT8 splitscreen;
boolean flip; // screenflip
boolean roll;
boolean rollmodel;
SINT8 rollflip;
FLOAT rollangle;
UINT8 rotaxis;
FLOAT centerx, centery;
FLOAT rollx, rollz;
UINT8 fliptype;
#ifdef USE_FTRANSFORM_MIRROR
boolean mirror; // SRB2Kart: Encore Mode
boolean mirrorflip; // Encore Mode with Flipcam
#endif
boolean shearing; // 14042019
float viewaiming; // 17052019
} FTransform;
enum
{
TRANSFORM_NONE = 0,
TRANSFORM_FLIP = 1 << 0, // screenflip
TRANSFORM_MIRROR = 1 << 1, // SRB2Kart: Encore Mode
TRANSFORM_MIRRORFLIP = TRANSFORM_FLIP|TRANSFORM_MIRROR // SRB2Kart: Encore Mode with Flipcam
};
// Transformed vector, as passed to HWR API
typedef struct
{
@@ -155,41 +164,6 @@ typedef struct
FLOAT s,t;
} FOutVector;
typedef struct vbo_vertex_s
{
float x, y, z;
float u, v;
unsigned char r, g, b, a;
} gl_skyvertex_t;
typedef enum gl_skyloopmode_e
{
HWD_SKYLOOP_FAN,
HWD_SKYLOOP_STRIP
} gl_skyloopmode_t;
typedef struct
{
gl_skyloopmode_t mode;
int vertexcount;
int vertexindex;
boolean use_texture;
} gl_skyloopdef_t;
typedef struct
{
unsigned int vbo;
int rows, columns;
int loopcount;
int detail, vertex_count;
int texture, width, height;
boolean rebuild; // VBO needs to be rebuilt
gl_skyloopdef_t *loops;
gl_skyvertex_t *data;
} gl_sky_t;
// Shader targets used to render specific types of geometry.
// A shader target is resolved to an actual shader with HWR_GetShaderFromTarget.
// The shader returned may be a base shader or a custom shader.
@@ -197,6 +171,7 @@ enum
{
SHADER_NONE = -1,
SHADER_FLOOR = 0,
SHADER_SHADOW,
SHADER_WALL,
SHADER_SPRITE,
SHADER_MODEL,
@@ -205,7 +180,6 @@ enum
SHADER_SKY,
SHADER_PALETTE_POSTPROCESS,
SHADER_UI_COLORMAP_FADE,
SHADER_DOWNSAMPLE,
NUMSHADERTARGETS
};
@@ -228,6 +202,7 @@ enum hwdshaderstage
typedef enum hwdshaderstage hwdshaderstage_t;
// ==========================================================================
// RENDER MODES
// ==========================================================================
@@ -238,22 +213,22 @@ enum EPolyFlags
{
// the first 5 are mutually exclusive
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pixels are discarded (holes in texture)
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pels are discarded (holes in texture)
PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency
PF_Environment = 0x00000004, // Poly should be drawn environment mapped. (Hurdler: used for text drawing)
PF_Additive = 0x00000008, // Source blending factor is additive.
PF_Subtractive = 0x00000010, // Subtractive color blending
PF_ReverseSubtract = 0x00000020, // Reverse subtract, used in wall splats (decals)
PF_Multiplicative = 0x00000040, // Multiplicative color blending
PF_Fog = 0x20000000, // Fog blocks
PF_NoAlphaTest = 0x40000000, // Disables alpha testing
PF_Blending = (PF_Masked|PF_Translucent|PF_Environment|PF_Additive|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Fog) & ~PF_NoAlphaTest,
PF_Additive = 0x00000004, // Poly is added to the frame buffer
PF_Environment = 0x00000008, // Poly should be drawn environment mapped.
// Hurdler: used for text drawing
PF_Substractive = 0x00000010, // for splat
PF_NoAlphaTest = 0x00000020, // hiden param
PF_Fog = 0x00000040, // Fog blocks
PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest,
// other flag bits
PF_Occlude = 0x00000100, // Updates the depth buffer
PF_NoDepthTest = 0x00000200, // Disables the depth test mode
PF_Invisible = 0x00000400, // Disables write to color buffer
PF_Decal = 0x00000800, // Enables polygon offset
PF_Occlude = 0x00000100, // Update the depth buffer
PF_NoDepthTest = 0x00000200, // Disable the depth test mode
PF_Invisible = 0x00000400, // Disable write to color buffer
PF_Decal = 0x00000800, // Enable polygon offset
PF_Modulated = 0x00001000, // Modulation (multiply output with constant RGBA)
// When set, pass the color constant into the FSurfaceInfo -> FlatColor
PF_NoTexture = 0x00002000, // Disable texture
@@ -262,8 +237,7 @@ enum EPolyFlags
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
PF_ForceWrapX = 0x00020000, // Force repeat texture on X
PF_ForceWrapY = 0x00040000, // Forces repeat texture on Y
PF_Ripple = 0x00100000, // Water ripple effect. The current backend doesn't use it for anything.
PF_Skydecal = 0x20000000 // Enables smaller polygon offset, to be used for skywalls only
PF_Ripple = 0x00100000 // Water ripple effect. The current backend doesn't use it for anything.
// 0x20000000
// 0x40000000
// 0x80000000
@@ -296,7 +270,6 @@ struct FLightInfo
FUINT light_level;
FUINT fade_start;
FUINT fade_end;
boolean directional;
};
typedef struct FLightInfo FLightInfo;
@@ -318,9 +291,7 @@ enum hwdsetspecialstate
HWD_SET_TEXTUREFILTERMODE,
HWD_SET_TEXTUREANISOTROPICMODE,
HWD_SET_WIREFRAME,
HWD_SET_MSAA,
HWD_SET_SCREEN_TEXTURES,
@@ -328,8 +299,6 @@ enum hwdsetspecialstate
HWD_SET_PORTAL_MODE,// new portal thing
HWD_SET_STENCIL_LEVEL,
HWD_SET_TEXTURE_FORMAT,
HWD_NUMSTATE
};
typedef enum hwdsetspecialstate hwdspecialstate_t;
@@ -339,11 +308,6 @@ typedef enum hwdsetspecialstate hwdspecialstate_t;
enum hwdshaderinfo
{
HWD_SHADERINFO_LEVELTIME = 1,
HWD_SHADERINFO_LIGHT_X,
HWD_SHADERINFO_LIGHT_Y,
HWD_SHADERINFO_LIGHT_Z,
HWD_SHADERINFO_LIGHT_CONTRAST,
HWD_SHADERINFO_LIGHT_BACKLIGHT,
};
typedef enum hwdshaderinfo hwdshaderinfo_t;
@@ -377,7 +341,6 @@ enum hwdscreentexture
HWD_SCREENTEXTURE_WIPE_END, // destination image for the wipe/fade effect
HWD_SCREENTEXTURE_GENERIC1, // underwater/heat effect, intermission background
HWD_SCREENTEXTURE_GENERIC2, // palette-based colormap fade, final screen texture
HWD_SCREENTEXTURE_VHS,
NUMSCREENTEXTURES, // (generic3 is unused if palette rendering is disabled)
};
typedef enum hwdscreentexture hwdscreentexture_t;
+160 -185
View File
@@ -18,10 +18,9 @@
#include "../doomdef.h"
#ifdef HWRENDER
#include "hw_main.h"
#include "hw_glob.h"
#include "hw_gl.h"
#include "hw_drv.h"
#include "../m_misc.h" //FIL_WriteFile()
#include "../r_draw.h" //viewborderlump
@@ -62,20 +61,16 @@ static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229
static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255};
static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111,127};
static const float FLOATBASEVIDWIDTH = (float)BASEVIDWIDTH;
static const float FLOATBASEVIDHEIGHT = (float)BASEVIDHEIGHT;
//
// -----------------+
// HWR_DrawPatch : Draw a 'tile' graphic
// Notes : x,y : positions relative to the original Doom resolution
// : textes(console+score) + menus + status bar
// -----------------+
void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option)
{
FOutVector v[4];
FBITFIELD flags;
GLPatch_t *hwrPatch;
// 3--2
// | /|
@@ -88,7 +83,6 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
// make patch ready in hardware cache
HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
switch (option & V_SCALEPATCHMASK)
{
@@ -108,17 +102,17 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
if (option & V_NOSCALESTART)
sdupx = sdupy = 2.0f;
v[0].x = v[3].x = (x*sdupx-gpatch->leftoffset*pdupx)/vid.width - 1;
v[2].x = v[1].x = (x*sdupx+(gpatch->width - gpatch->leftoffset)*pdupx)/vid.width - 1;
v[0].y = v[1].y = 1-(y*sdupy-gpatch->topoffset*pdupy)/vid.height;
v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height - gpatch->topoffset)*pdupy)/vid.height;
v[0].x = v[3].x = (x*sdupx-SHORT(gpatch->leftoffset)*pdupx)/vid.width - 1;
v[2].x = v[1].x = (x*sdupx+(SHORT(gpatch->width)-SHORT(gpatch->leftoffset))*pdupx)/vid.width - 1;
v[0].y = v[1].y = 1-(y*sdupy-SHORT(gpatch->topoffset)*pdupy)/vid.height;
v[2].y = v[3].y = 1-(y*sdupy+(SHORT(gpatch->height)-SHORT(gpatch->topoffset))*pdupy)/vid.height;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = hwrPatch->max_s;
v[2].s = v[1].s = gpatch->max_s;
v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = hwrPatch->max_t;
v[2].t = v[3].t = gpatch->max_t;
flags = PF_Translucent|PF_NoDepthTest;
@@ -128,18 +122,16 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
flags |= PF_ForceWrapY;
// clip it since it is used for bunny scroll in doom I
GL_DrawPolygon(NULL, v, 4, flags);
HWD.pfnDrawPolygon(NULL, v, 4, flags);
}
void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, INT32 bflags)
void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap)
{
FOutVector v[4];
FBITFIELD flags;
float cx = FIXED_TO_FLOAT(x);
float cy = FIXED_TO_FLOAT(y);
UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT);
UINT8 blendmode = ((bflags & V_BLENDMASK) >> V_BLENDSHIFT);
GLPatch_t *hwrPatch;
// 3--2
// | /|
@@ -150,17 +142,12 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
if (alphalevel >= 10 && alphalevel < 13)
return;
const float fvw = (float)vid.width;
const float fvh = (float)vid.height;
// make patch ready in hardware cache
if (!colormap)
HWR_GetPatch(gpatch);
else
HWR_GetMappedPatch(gpatch, colormap);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
dupx = (float)vid.dupx;
dupy = (float)vid.dupy;
@@ -191,13 +178,13 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
// left offset
if (option & V_FLIP)
offsetx = (float)(gpatch->width - gpatch->leftoffset) * fscalew;
offsetx = (float)(SHORT(gpatch->width) - SHORT(gpatch->leftoffset)) * fscalew;
else
offsetx = (float)(gpatch->leftoffset) * fscalew;
offsetx = (float)SHORT(gpatch->leftoffset) * fscalew;
// top offset
// TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!?
offsety = (float)(gpatch->topoffset) * fscaleh;
offsety = (float)SHORT(gpatch->topoffset) * fscaleh;
if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs
{
@@ -225,46 +212,56 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
// if it's meant to cover the whole screen, black out the rest
// cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT)
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
{
const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0]));
// Need to temporarily cache the real patch to get the colour of the top left pixel
patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
if (!column->topdelta)
{
const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
}
Z_Free(realpatch);
}
// centre screen
if (fabsf(fvw - FLOATBASEVIDWIDTH * dupx) > 1.0E-36f)
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
{
if (option & V_SNAPTORIGHT)
cx += (fvw - (FLOATBASEVIDWIDTH * dupx));
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(option & V_SNAPTOLEFT))
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2;
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
}
if (fabsf(fvh - FLOATBASEVIDHEIGHT * dupy) > 1.0E-36f)
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
{
if ((option & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
cy += (fvh/2 - (FLOATBASEVIDHEIGHT/2 * dupy));
cy += ((float)vid.height/2 - ((float)BASEVIDHEIGHT/2 * dupy));
else if (option & V_SNAPTOBOTTOM)
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(option & V_SNAPTOTOP))
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2;
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2;
}
}
}
fwidth = (float)(gpatch->width) * fscalew * dupx;
fheight = (float)(gpatch->height) * fscaleh * dupy;
if (pscale != FRACUNIT)
{
fwidth = (float)SHORT(gpatch->width) * fscalew * dupx;
fheight = (float)SHORT(gpatch->height) * fscaleh * dupy;
}
else
{
fwidth = (float)SHORT(gpatch->width) * dupx;
fheight = (float)SHORT(gpatch->height) * dupy;
}
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
cx = -1.0f + (cx / (fvw / 2.0f));
cy = 1.0f - (cy / (fvh / 2.0f));
cx = -1 + (cx / (vid.width/2));
cy = 1 - (cy / (vid.height/2));
// fwidth and fheight are similar
fwidth /= fvw / 2.0f;
fheight /= fvh / 2.0f;
fwidth /= vid.width / 2;
fheight /= vid.height / 2;
// set the polygon vertices to the right positions
v[0].x = v[3].x = cx;
@@ -277,54 +274,48 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
if (option & V_FLIP)
{
v[0].s = v[3].s = hwrPatch->max_s;
v[0].s = v[3].s = gpatch->max_s;
v[2].s = v[1].s = 0.0f;
}
else
{
v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = hwrPatch->max_s;
v[2].s = v[1].s = gpatch->max_s;
}
v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = hwrPatch->max_t;
v[2].t = v[3].t = gpatch->max_t;
// clip it since it is used for bunny scroll in doom I
if (blendmode)
flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest;
else
flags = PF_Translucent|PF_NoDepthTest;
flags = PF_Translucent|PF_NoDepthTest;
if (option & V_WRAPX)
flags |= PF_ForceWrapX;
if (option & V_WRAPY)
flags |= PF_ForceWrapY;
// clip it since it is used for bunny scroll in doom I
if (alphalevel)
{
FSurfaceInfo Surf;
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans];
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans];
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans];
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
flags |= PF_Modulated;
GL_DrawPolygon(&Surf, v, 4, flags);
HWD.pfnDrawPolygon(&Surf, v, 4, flags);
}
else
GL_DrawPolygon(NULL, v, 4, flags);
HWD.pfnDrawPolygon(NULL, v, 4, flags);
}
void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h)
{
FOutVector v[4];
FBITFIELD flags;
float cx = FIXED_TO_FLOAT(x);
float cy = FIXED_TO_FLOAT(y);
UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT);
GLPatch_t *hwrPatch;
// 3--2
// | /|
@@ -335,12 +326,8 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
if (alphalevel >= 10 && alphalevel < 13)
return;
const float fvw = (float)vid.width;
const float fvh = (float)vid.height;
// make patch ready in hardware cache
HWR_GetPatch(gpatch);
hwrPatch = ((GLPatch_t *)gpatch->hardware);
dupx = (float)vid.dupx;
dupy = (float)vid.dupy;
@@ -363,8 +350,8 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
dupx = dupy = (dupx < dupy ? dupx : dupy);
fscale = FIXED_TO_FLOAT(pscale);
cy -= (float)(gpatch->topoffset) * fscale;
cx -= (float)(gpatch->leftoffset) * fscale;
cy -= (float)SHORT(gpatch->topoffset) * fscale;
cx -= (float)SHORT(gpatch->leftoffset) * fscale;
if (!(option & V_NOSCALESTART))
{
@@ -376,32 +363,34 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
// if it's meant to cover the whole screen, black out the rest
// cx and cy are possibly *slightly* off from float maths
// This is done before here compared to software because we directly alter cx and cy to centre
if (cx >= -0.1f && cx <= 0.1f && gpatch->width == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && gpatch->height == BASEVIDHEIGHT)
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
{
const column_t *column = (const column_t *)((const UINT8 *)(gpatch->columns) + (gpatch->columnofs[0]));
// Need to temporarily cache the real patch to get the colour of the top left pixel
patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
if (!column->topdelta)
{
const UINT8 *source = (const UINT8 *)(column) + 3;
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
}
Z_Free(realpatch);
}
// centre screen
if (fabsf(fvw - FLOATBASEVIDWIDTH * dupx) > 1.0E-36f)
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
{
if (option & V_SNAPTORIGHT)
cx += (fvw - (FLOATBASEVIDWIDTH * dupx));
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(option & V_SNAPTOLEFT))
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2;
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
}
if (fabsf(fvh - FLOATBASEVIDHEIGHT * dupy) > 1.0E-36f)
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
{
if ((option & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
cy += (fvh/2 - (FLOATBASEVIDHEIGHT/2 * dupy));
cy += ((float)vid.height/2 - ((float)BASEVIDHEIGHT/2 * dupy));
else if (option & V_SNAPTOBOTTOM)
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(option & V_SNAPTOTOP))
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2;
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2;
}
}
}
@@ -415,11 +404,11 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
if (fheight > h - sy)
fheight = h - sy;
if (fwidth > gpatch->width)
fwidth = gpatch->width;
if (fwidth > SHORT(gpatch->width))
fwidth = SHORT(gpatch->width);
if (fheight > gpatch->height)
fheight = gpatch->height;
if (fheight > SHORT(gpatch->height))
fheight = SHORT(gpatch->height);
if (pscale != FRACUNIT)
{
@@ -433,12 +422,12 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
}
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
cx = -1.0f + (cx / (fvw / 2.0f));
cy = 1.0f - (cy / (fvh / 2.0f));
cx = -1 + (cx / (vid.width/2));
cy = 1 - (cy / (vid.height/2));
// fwidth and fheight are similar
fwidth /= fvw / 2.0f;
fheight /= fvh / 2.0f;
fwidth /= vid.width / 2;
fheight /= vid.height / 2;
// set the polygon vertices to the right positions
v[0].x = v[3].x = cx;
@@ -449,10 +438,10 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = ((sx)/(float)(gpatch->width) )*hwrPatch->max_s;
v[2].s = v[1].s = ((w )/(float)(gpatch->width) )*hwrPatch->max_s;
v[0].t = v[1].t = ((sy)/(float)(gpatch->height))*hwrPatch->max_t;
v[2].t = v[3].t = ((h )/(float)(gpatch->height))*hwrPatch->max_t;
v[0].s = v[3].s = ((sx)/(float)SHORT(gpatch->width) )*gpatch->max_s;
v[2].s = v[1].s = ((w )/(float)SHORT(gpatch->width) )*gpatch->max_s;
v[0].t = v[1].t = ((sy)/(float)SHORT(gpatch->height))*gpatch->max_t;
v[2].t = v[3].t = ((h )/(float)SHORT(gpatch->height))*gpatch->max_t;
flags = PF_Translucent|PF_NoDepthTest;
@@ -466,17 +455,15 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
{
FSurfaceInfo Surf;
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value];
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[cv_translucenthud.value];
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value];
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
flags |= PF_Modulated;
GL_DrawPolygon(&Surf, v, 4, flags);
HWD.pfnDrawPolygon(&Surf, v, 4, flags);
}
else
GL_DrawPolygon(NULL, v, 4, flags);
HWD.pfnDrawPolygon(NULL, v, 4, flags);
}
// ==========================================================================
@@ -552,7 +539,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
// BTW, I see we put 0 for PFs, and If I'm right, that
// means we take the previous PFs as default
// how can we be sure they are ok?
GL_DrawPolygon(NULL, v, 4, PF_NoDepthTest); //PF_Translucent);
HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest); //PF_Translucent);
}
@@ -565,33 +552,33 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum
// 0--1
void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
{
FOutVector v[4];
FSurfaceInfo Surf;
FOutVector v[4];
FSurfaceInfo Surf;
FBITFIELD poly_flags = PF_NoTexture|PF_Modulated|PF_NoDepthTest;
v[0].x = v[3].x = -1.0f;
v[2].x = v[1].x = 1.0f;
v[0].y = v[1].y = -1.0f;
v[2].y = v[3].y = 1.0f;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].x = v[3].x = -1.0f;
v[2].x = v[1].x = 1.0f;
v[0].y = v[1].y = -1.0f;
v[2].y = v[3].y = 1.0f;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = 1.0f;
v[0].t = v[1].t = 1.0f;
v[2].t = v[3].t = 0.0f;
v[0].s = v[3].s = 0.0f;
v[2].s = v[1].s = 1.0f;
v[0].t = v[1].t = 1.0f;
v[2].t = v[3].t = 0.0f;
if (color & 0xFF00) // Do COLORMAP fade.
{
if (color & 0xFF00) // Do COLORMAP fade.
{
if (HWR_ShouldUsePaletteRendering() && cv_glscreentextures.value)
{
const hwdscreentexture_t scr_tex = HWD_SCREENTEXTURE_GENERIC2;
Surf.LightTableId = HWR_GetLightTableID(NULL);
Surf.LightInfo.light_level = strength;
GL_MakeScreenTexture(scr_tex);
GL_SetShader(HWR_GetShaderFromTarget(SHADER_UI_COLORMAP_FADE));
GL_DrawScreenTexture(scr_tex, &Surf, PF_ColorMapped|PF_NoDepthTest);
GL_UnSetShader();
HWD.pfnMakeScreenTexture(scr_tex);
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_UI_COLORMAP_FADE));
HWD.pfnDrawScreenTexture(scr_tex, &Surf, PF_ColorMapped|PF_NoDepthTest);
HWD.pfnUnSetShader();
return;
}
@@ -601,21 +588,21 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
Surf.PolyColor.s.alpha = (strength*8);
poly_flags |= PF_Translucent;
}
}
else // Do TRANSMAP** fade.
{
}
else // Do TRANSMAP** fade.
{
RGBA_t *palette = HWR_GetTexturePalette();
Surf.PolyColor.rgba = palette[color&0xFF].rgba;
if (HWR_ShouldUsePaletteRendering())
if (HWR_ShouldUsePaletteRendering())
Surf.PolyColor.s.alpha = softwaretranstogl[strength];
else
Surf.PolyColor.s.alpha = (UINT8)(strength*25.5f);
poly_flags |= PF_Translucent;
}
}
GL_DrawPolygon(&Surf, v, 4, poly_flags);
HWD.pfnDrawPolygon(&Surf, v, 4, poly_flags);
}
// Draw the console background with translucency support
@@ -642,11 +629,7 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height)
Surf.PolyColor.rgba = UINT2RGBA(color);
Surf.PolyColor.s.alpha = 0x80;
int flags = PF_NoTexture|PF_Modulated|PF_NoDepthTest;
flags |= HWR_GetBlendModeFlag(((B_MODULATE & V_BLENDMASK) >> V_BLENDSHIFT)+1);
GL_DrawPolygon(&Surf, v, 4, flags);
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
}
@@ -667,7 +650,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
INT32 top, side;
INT32 baseviewwidth, baseviewheight;
INT32 basewindowx, basewindowy;
patch_t *patch;
GLPatch_t *patch;
// if (gl_viewwidth == vid.width)
// return;
@@ -716,7 +699,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
// top edge
if (clearlines > basewindowy - 8)
{
patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH);
patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_CACHE);
for (x = 0; x < baseviewwidth; x += 8)
HWR_DrawPatch(patch, basewindowx + x, basewindowy - 8,
0);
@@ -725,7 +708,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
// bottom edge
if (clearlines > basewindowy + baseviewheight)
{
patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH);
patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_CACHE);
for (x = 0; x < baseviewwidth; x += 8)
HWR_DrawPatch(patch, basewindowx + x,
basewindowy + baseviewheight, 0);
@@ -734,7 +717,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
// left edge
if (clearlines > basewindowy)
{
patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH);
patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_CACHE);
for (y = 0; y < baseviewheight && basewindowy + y < clearlines;
y += 8)
{
@@ -746,7 +729,7 @@ void HWR_DrawViewBorder(INT32 clearlines)
// right edge
if (clearlines > basewindowy)
{
patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH);
patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_CACHE);
for (y = 0; y < baseviewheight && basewindowy+y < clearlines;
y += 8)
{
@@ -758,22 +741,22 @@ void HWR_DrawViewBorder(INT32 clearlines)
// Draw beveled corners.
if (clearlines > basewindowy - 8)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TL],
PU_PATCH),
PU_CACHE),
basewindowx - 8, basewindowy - 8, 0);
if (clearlines > basewindowy - 8)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TR],
PU_PATCH),
PU_CACHE),
basewindowx + baseviewwidth, basewindowy - 8, 0);
if (clearlines > basewindowy+baseviewheight)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BL],
PU_PATCH),
PU_CACHE),
basewindowx - 8, basewindowy + baseviewheight, 0);
if (clearlines > basewindowy + baseviewheight)
HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BR],
PU_PATCH),
PU_CACHE),
basewindowx + baseviewwidth,
basewindowy + baseviewheight, 0);
}
@@ -802,7 +785,7 @@ void HWR_drawAMline(const fline_t *fl, INT32 color)
v2.x = ((float)fl->b.x-(vid.width/2.0f))*(2.0f/vid.width);
v2.y = ((float)fl->b.y-(vid.height/2.0f))*(2.0f/vid.height);
GL_Draw2DLine(&v1, &v2, color_rgba);
HWD.pfnDraw2DLine(&v1, &v2, color_rgba);
}
// -----------------+
@@ -827,9 +810,6 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
fy = (float)y;
fw = fh = (float)wh;
const float fvw = (float)vid.width;
const float fvh = (float)vid.height;
if (!(color & V_NOSCALESTART))
{
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
@@ -839,20 +819,20 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
fw *= dupx;
fh *= dupy;
if (fabsf(fvw - (FLOATBASEVIDWIDTH * dupx)) > 1.0E-36f)
if (fabsf((float)vid.width - ((float)BASEVIDWIDTH * dupx)) > 1.0E-36f)
{
if (color & V_SNAPTORIGHT)
fx += (fvw - (FLOATBASEVIDWIDTH * dupx));
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(color & V_SNAPTOLEFT))
fx += (fvw - (FLOATBASEVIDWIDTH * dupx)) / 2;
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
}
if (fabsf(fvh - (FLOATBASEVIDHEIGHT * dupy)) > 1.0E-36f)
if (fabsf((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) > 1.0E-36f)
{
// same thing here
if (color & V_SNAPTOBOTTOM)
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(color & V_SNAPTOTOP))
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy)) / 2;
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
}
}
@@ -873,16 +853,16 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
return;
if (fx + fw > vid.width)
{
fwait = fw - (fvw- fx);
fw = fvw - fx;
fwait = fw - ((float)vid.width - fx);
fw = (float)vid.width - fx;
}
if (fy + fh > vid.height)
fh = fvh - fy;
fh = (float)vid.height - fy;
fx = -1.0f + fx / (fvw / 2.0f);
fy = 1.0f - fy / (fvh / 2.0f);
fw = fw / (fvw / 2.0f);
fh = fh / (fvh / 2.0f);
fx = -1 + fx / (vid.width / 2);
fy = 1 - fy / (vid.height / 2);
fw = fw / (vid.width / 2);
fh = fh / (vid.height / 2);
v[0].x = v[3].x = fx;
v[2].x = v[1].x = fx + fw;
@@ -899,7 +879,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
Surf.PolyColor = palette[color&0xFF];
GL_DrawPolygon(&Surf, v, 4,
HWD.pfnDrawPolygon(&Surf, v, 4,
PF_Modulated|PF_NoTexture|PF_NoDepthTest);
}
@@ -926,9 +906,6 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32
fw = (float)w;
fh = (float)h;
const float fvw = (float)vid.width;
const float fvh = (float)vid.height;
if (!(options & V_NOSCALESTART))
{
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
@@ -941,7 +918,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32
clearColour.green = (float)rgbaColour.s.green / 255;
clearColour.blue = (float)rgbaColour.s.blue / 255;
clearColour.alpha = 1;
GL_ClearBuffer(true, false, false, &clearColour);
HWD.pfnClearBuffer(true, false, false, &clearColour);
return;
}
@@ -950,25 +927,25 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32
fw *= dupx;
fh *= dupy;
if (fabsf(fvw - (FLOATBASEVIDWIDTH * dupx)) > 1.0E-36f)
if (fabsf((float)vid.width - ((float)BASEVIDWIDTH * dupx)) > 1.0E-36f)
{
if (options & V_SNAPTORIGHT)
fx += (fvw - (FLOATBASEVIDWIDTH * dupx));
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(options & V_SNAPTOLEFT))
fx += (fvw - (FLOATBASEVIDWIDTH * dupx)) / 2;
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
}
if (fabsf(fvh - (FLOATBASEVIDHEIGHT * dupy)) > 1.0E-36f)
if (fabsf((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) > 1.0E-36f)
{
// same thing here
if (options & V_SNAPTOBOTTOM)
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(options & V_SNAPTOTOP))
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy)) / 2;
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
}
if (options & V_SPLITSCREEN)
fy += (FLOATBASEVIDHEIGHT * dupy)/2;
fy += ((float)BASEVIDHEIGHT * dupy)/2;
if (options & V_HORZSCREEN)
fx += (FLOATBASEVIDWIDTH * dupx)/2;
fx += ((float)BASEVIDWIDTH * dupx)/2;
}
@@ -988,14 +965,14 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32
if (fw <= 0 || fh <= 0)
return;
if (fx + fw > vid.width)
fw = fvw - fx;
fw = (float)vid.width - fx;
if (fy + fh > vid.height)
fh = fvh - fy;
fh = (float)vid.height - fy;
fx = -1.0f + fx / (fvw / 2.0f);
fy = 1.0f - fy / (fvh / 2.0f);
fw = fw / (fvw / 2.0f);
fh = fh / (fvh / 2.0f);
fx = -1 + fx / (vid.width / 2);
fy = 1 - fy / (vid.height / 2);
fw = fw / (vid.width / 2);
fh = fh / (vid.height / 2);
v[0].x = v[3].x = fx;
v[2].x = v[1].x = fx + fw;
@@ -1012,7 +989,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32
Surf.PolyColor.rgba = UINT2RGBA(color);
Surf.PolyColor.s.alpha = 0x80;
GL_DrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
}
// -----------------+
@@ -1040,9 +1017,6 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
fw = (float)w;
fh = (float)h;
const float fvw = (float)vid.width;
const float fvh = (float)vid.height;
if (!(color & V_NOSCALESTART))
{
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
@@ -1055,7 +1029,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
clearColour.green = (float)rgbaColour.s.green / 255;
clearColour.blue = (float)rgbaColour.s.blue / 255;
clearColour.alpha = 1;
GL_ClearBuffer(true, false, false, &clearColour);
HWD.pfnClearBuffer(true, false, false, &clearColour);
return;
}
@@ -1064,25 +1038,26 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
fw *= dupx;
fh *= dupy;
if (fabsf(fvw - FLOATBASEVIDWIDTH * dupx) > 1.0E-36f)
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
{
if (color & V_SNAPTORIGHT)
fx += (fvw - (FLOATBASEVIDWIDTH * dupx));
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(color & V_SNAPTOLEFT))
fx += (fvw - (FLOATBASEVIDWIDTH * dupx)) / 2;
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
}
if (fabsf(fvh - FLOATBASEVIDHEIGHT * dupy) > 1.0E-36f)
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
{
// same thing here
if (color & V_SNAPTOBOTTOM)
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(color & V_SNAPTOTOP))
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy)) / 2;
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
}
if (color & V_SPLITSCREEN)
fy += (FLOATBASEVIDHEIGHT * dupy)/2;
fy += ((float)BASEVIDHEIGHT * dupy)/2;
if (color & V_HORZSCREEN)
fx += (FLOATBASEVIDWIDTH * dupx)/2;
fx += ((float)BASEVIDWIDTH * dupx)/2;
}
if (fx >= vid.width || fy >= vid.height)
@@ -1101,14 +1076,14 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
if (fw <= 0 || fh <= 0)
return;
if (fx + fw > vid.width)
fw = fvw - fx;
fw = (float)vid.width - fx;
if (fy + fh > vid.height)
fh = fvh - fy;
fh = (float)vid.height - fy;
fx = -1.0f + fx / (fvw / 2.0f);
fy = 1.0f - fy / (fvh / 2.0f);
fw = fw / (fvw / 2.0f);
fh = fh / (fvh / 2.0f);
fx = -1 + fx / (vid.width / 2);
fy = 1 - fy / (vid.height / 2);
fw = fw / (vid.width / 2);
fh = fh / (vid.height / 2);
v[0].x = v[3].x = fx;
v[2].x = v[1].x = fx + fw;
@@ -1132,7 +1107,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
}
GL_DrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
}
#ifdef HAVE_PNG
@@ -1151,7 +1126,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
#define _FILE_OFFSET_BITS 0
#endif
#include "png.h"
#include "png.h"
#ifdef PNG_WRITE_SUPPORTED
#define USE_PNG // PNG is only used if write is supported (see ../m_misc.c)
#endif
@@ -1216,7 +1191,7 @@ UINT8 *HWR_GetScreenshot(void)
return NULL;
// returns 24bit 888 RGB
GL_ReadScreenTexture(HWD_SCREENTEXTURE_GENERIC2, (void *)buf);
HWD.pfnReadScreenTexture(HWD_SCREENTEXTURE_GENERIC2, (void *)buf);
return buf;
}
@@ -1232,7 +1207,7 @@ boolean HWR_Screenshot(const char *pathname)
}
// returns 24bit 888 RGB
GL_ReadScreenTexture(HWD_SCREENTEXTURE_GENERIC2, (void *)buf);
HWD.pfnReadScreenTexture(HWD_SCREENTEXTURE_GENERIC2, (void *)buf);
#ifdef USE_PNG
ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL);
+142
View File
@@ -0,0 +1,142 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2019 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file
/// \brief imports/exports for the GPU hardware low-level interface API
#ifndef __HWR_DRV_H__
#define __HWR_DRV_H__
// this must be here 19991024 by Kin
#include "../screen.h"
#include "hw_data.h"
#include "hw_defs.h"
#include "hw_md2.h"
#include "hw_dll.h"
#include "../doomdef.h"
// ==========================================================================
// STANDARD DLL EXPORTS
// ==========================================================================
EXPORT boolean HWRAPI(Init) (void);
EXPORT void HWRAPI(SetupGLInfo) (void);
EXPORT void HWRAPI(SetTexturePalette) (RGBA_t *ppal);
EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray);
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT16 *dst_data);
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip, float farclip);
EXPORT void HWRAPI(ClearMipMapCache) (void);
//Hurdler: added for backward compatibility
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *stransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform);
EXPORT void HWRAPI(FlushScreenTextures) (void);
EXPORT void HWRAPI(DoScreenWipe) (int wipeStart, int wipeEnd);
EXPORT void HWRAPI(DrawScreenTexture) (int tex, FSurfaceInfo *surf, FBITFIELD polyflags);
EXPORT void HWRAPI(MakeScreenTexture) (int tex);
EXPORT void HWRAPI(DrawScreenFinalTexture) (int tex, INT32 width, INT32 height);
EXPORT void HWRAPI(RenderVhsEffect) (fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize);
#define SCREENVERTS 10
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
// jimita
EXPORT boolean HWRAPI(InitShaders) (void);
EXPORT void HWRAPI(LoadShader) (int slot, char *code, hwdshaderstage_t stage);
EXPORT boolean HWRAPI(CompileShader) (int slot);
EXPORT void HWRAPI(SetShader) (int slot);
EXPORT void HWRAPI(UnSetShader) (void);
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut);
EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable);
EXPORT void HWRAPI(ClearLightTables)(void);
EXPORT void HWRAPI(SetScreenPalette)(RGBA_t *palette);
// ==========================================================================
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM
// ==========================================================================
#if !defined (_CREATE_DLL_)
struct hwdriver_s
{
Init pfnInit;
SetupGLInfo pfnSetupGLInfo;
SetTexturePalette pfnSetTexturePalette;
FinishUpdate pfnFinishUpdate;
Draw2DLine pfnDraw2DLine;
DrawPolygon pfnDrawPolygon;
DrawIndexedTriangles pfnDrawIndexedTriangles;
SetBlend pfnSetBlend;
ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture;
UpdateTexture pfnUpdateTexture;
DeleteTexture pfnDeleteTexture;
ReadScreenTexture pfnReadScreenTexture;
GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache;
SetSpecialState pfnSetSpecialState;
DrawModel pfnDrawModel;
CreateModelVBOs pfnCreateModelVBOs;
SetTransform pfnSetTransform;
GetTextureUsed pfnGetTextureUsed;
PostImgRedraw pfnPostImgRedraw;
FlushScreenTextures pfnFlushScreenTextures;
DoScreenWipe pfnDoScreenWipe;
DrawScreenTexture pfnDrawScreenTexture;
MakeScreenTexture pfnMakeScreenTexture;
RenderVhsEffect pfnRenderVhsEffect;
DrawScreenFinalTexture pfnDrawScreenFinalTexture;
RenderSkyDome pfnRenderSkyDome;
InitShaders pfnInitShaders;
LoadShader pfnLoadShader;
CompileShader pfnCompileShader;
SetShader pfnSetShader;
UnSetShader pfnUnSetShader;
SetShaderInfo pfnSetShaderInfo;
SetPaletteLookup pfnSetPaletteLookup;
CreateLightTable pfnCreateLightTable;
ClearLightTables pfnClearLightTables;
SetScreenPalette pfnSetScreenPalette;
};
extern struct hwdriver_s hwdriver;
#define HWD hwdriver
#endif //not defined _CREATE_DLL_
#endif //__HWR_DRV_H__
-79
View File
@@ -1,79 +0,0 @@
// SONIC ROBO BLAST 2 Kart
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by Jaime "Lactozilla" Passos.
// Copyright (C) 2020 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file hw_gl.h
/// \brief OpenGL low-level interface API
#ifndef __HWR_GL_H__
#define __HWR_GL_H__
#include "../screen.h"
#include "hw_data.h"
#include "hw_defs.h"
#include "hw_md2.h"
#define SCREENVERTS 10
boolean GL_Init(void);
void SetupGLInfo(void);
void GL_SetSpecialState(hwdspecialstate_t IdState, INT32 Value);
void GL_SetTransform(FTransform *stransform);
void GL_SetBlend(FBITFIELD PolyFlags);
void GL_SetPalette(RGBA_t *palette);
void GL_ClearBuffer(FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask, FRGBAFloat * ClearColor);
void GL_DrawPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
void GL_DrawIndexedTriangles(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray);
void GL_Draw2DLine(F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
void GL_DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
#define GL_DrawModel(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface) GL_DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface)
void GL_RenderSkyDome(gl_sky_t *sky);
void GL_UpdateTexture(GLMipmap_t *pTexInfo);
void GL_SetTexture(GLMipmap_t *pTexInfo);
void GL_DeleteTexture(GLMipmap_t *pTexInfo);
void GL_Flush(void);
#define GL_ClearMipMapCache GL_Flush
INT32 GL_GetTextureUsed(void);
void GL_CreateModelVBOs(model_t *model);
void GL_ReadScreenTexture(int tex, UINT16 *dst_data);
void GL_GClipRect(INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip, float farclip);
void GL_MakeScreenTexture(int tex);
void GL_FlushScreenTextures(void);
void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags);
void GL_DoScreenWipe(int wipeStart, int wipeEnd);
void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize);
void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height, boolean useshader);
void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2]);
boolean GL_InitShaders(void);
void GL_LoadShader(int slot, char *code, hwdshaderstage_t stage);
boolean GL_CompileShader(int slot);
void GL_SetShader(int slot);
void GL_UnSetShader(void);
void GL_SetShaderInfo(hwdshaderinfo_t info, INT32 value);
void GL_SetPaletteLookup(UINT8 *lut);
UINT32 GL_CreateLightTable(RGBA_t *hw_lighttable);
void GL_ClearLightTables(void);
void GL_SetScreenPalette(RGBA_t *palette);
#endif // __HWR_GL_H__
+13 -27
View File
@@ -32,7 +32,7 @@ typedef struct gl_vissprite_s
float scale;
float spritexscale, spriteyscale;
float spritexoffset, spriteyoffset;
patch_t *gpatch;
GLPatch_t *gpatch;
boolean flip;
UINT8 translucency; //alpha level 0-255
mobj_t *mobj;
@@ -43,51 +43,37 @@ typedef struct gl_vissprite_s
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
} gl_vissprite_t;
void HWR_ObjectLightLevelPost(gl_vissprite_t *spr, const sector_t *sector, INT32 *lightlevel, boolean model);
// --------
// hw_bsp.c
// --------
extern extrasubsector_t *extrasubsectors;
extern size_t addsubsector;
void HWR_FreeExtraSubsectors(void);
// --------
// hw_cache.c
// --------
void HWR_InitMapTextures(void);
void HWR_LoadMapTextures(size_t pnumtextures);
void HWR_FreeMapTextures(void);
void HWR_InitTextureCache(void);
void HWR_FreeTextureCache(void);
void HWR_FreeMipmapCache(void);
void HWR_FreeExtraSubsectors(void);
patch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
void HWR_GetPatch(patch_t *gpatch);
void HWR_GetMappedPatch(patch_t *gpatch, const UINT8 *colormap);
void HWR_MakePatch(const patch_t *patch, GLPatch_t *glPatch, GLMipmap_t *glMipmap, boolean makebitmap);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
void HWR_PrecacheLevel(void);
GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean noencore);
void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap);
// ^ some flats must NOT be remapped to encore, since we remap them as we cache them for ease, adding a toggle here seems wise.
void HWR_FreeTexture(patch_t *patch);
void HWR_FreeTextureData(patch_t *patch);
void HWR_FreeTextureColormaps(patch_t *patch);
void HWR_ClearAllTextures(void);
void HWR_FreeColormapCache(void);
GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean noencore);
void HWR_GetPatch(GLPatch_t *gpatch);
void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap);
void HWR_MakePatch(patch_t *patch, GLPatch_t *glPatch, GLMipmap_t *glMipmap, boolean makebitmap);
void HWR_UnlockCachedPatch(GLPatch_t *gpatch);
RGBA_t *HWR_GetTexturePalette(void);
void HWR_SetPalette(RGBA_t *palette);
void HWR_SetMapPalette(void);
UINT32 HWR_CreateLightTable(UINT8 *lighttable);
UINT32 HWR_GetLightTableID(extracolormap_t *colormap);
void HWR_ClearLightTables(void);
GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump);
GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
// --------
// hw_draw.c
Loaded 100 of 338 files, more files were not shown because too many files have changed in this diff. Show more