mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-14 00:20:51 +00:00
Merge remote-tracking branch 'origin' into openal
Conflicts: src/sound/fmodsound.cpp
This commit is contained in:
commit
18597a93a7
507 changed files with 30037 additions and 11065 deletions
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/Debug
|
||||||
|
*.ncb
|
||||||
|
*.suo
|
||||||
|
*.pdb
|
||||||
|
*.ilk
|
||||||
|
*.aps
|
||||||
|
/Release
|
||||||
|
/wadsrc_wad
|
||||||
|
*.user
|
||||||
|
/debug
|
||||||
|
/release
|
||||||
|
*/debug
|
||||||
|
*/release
|
||||||
|
/release_gcc
|
||||||
|
/dumb/vc6/dumb_static/release
|
||||||
|
/dumb/vc6/dumb_static/debug
|
||||||
|
/DOOMSTATS.TXT
|
||||||
|
/src/gitinfo.h
|
||||||
|
/src/sc_man_scanner.h
|
||||||
|
/src/xlat/xlat_parser.c
|
||||||
|
/src/xlat/xlat_parser.h
|
||||||
|
/src/xlat/xlat_parser.out
|
||||||
|
/tools/*/debug
|
||||||
|
/tools/*/release
|
||||||
|
/tools/*/*.exe
|
||||||
|
/tools/lemon/build
|
||||||
|
/tools/re2c/build
|
||||||
|
/wadsrc/*.pk3
|
|
@ -1,4 +1,5 @@
|
||||||
cmake_minimum_required( VERSION 2.4 )
|
cmake_minimum_required( VERSION 2.4 )
|
||||||
|
project(ZDoom)
|
||||||
|
|
||||||
IF( NOT CMAKE_BUILD_TYPE )
|
IF( NOT CMAKE_BUILD_TYPE )
|
||||||
SET( CMAKE_BUILD_TYPE Debug CACHE STRING
|
SET( CMAKE_BUILD_TYPE Debug CACHE STRING
|
||||||
|
@ -9,9 +10,11 @@ ENDIF( NOT CMAKE_BUILD_TYPE )
|
||||||
set( ZDOOM_OUTPUT_DIR ${CMAKE_BINARY_DIR} CACHE PATH "Directory where zdoom.pk3 and the executable will be created." )
|
set( ZDOOM_OUTPUT_DIR ${CMAKE_BINARY_DIR} CACHE PATH "Directory where zdoom.pk3 and the executable will be created." )
|
||||||
set( ZDOOM_EXE_NAME "zdoom" CACHE FILEPATH "Name of the executable to create." )
|
set( ZDOOM_EXE_NAME "zdoom" CACHE FILEPATH "Name of the executable to create." )
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
set( PROFILE 0 CACHE BOOL "Enable profiling with gprof for Debug and RelWithDebInfo build types." )
|
set( PROFILE 0 CACHE BOOL "Enable profiling with gprof for Debug and RelWithDebInfo build types." )
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
|
||||||
|
|
||||||
option( NO_FMOD "Disable FMODEx sound support" )
|
option( NO_FMOD "Disable FMODEx sound support" )
|
||||||
option( NO_OPENAL "Disable OpenAL sound support" )
|
option( NO_OPENAL "Disable OpenAL sound support" )
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
cmake_minimum_required( VERSION 2.4 )
|
cmake_minimum_required( VERSION 2.4 )
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUC )
|
if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" )
|
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" )
|
||||||
endif( CMAKE_COMPILER_IS_GNUC )
|
endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
add_definitions( -DBZ_NO_STDIO )
|
add_definitions( -DBZ_NO_STDIO )
|
||||||
add_library( bz2
|
add_library( bz2
|
||||||
|
|
|
@ -11,9 +11,9 @@ endif( NOT CMAKE_BUILD_TYPE MATCHES "Release" )
|
||||||
|
|
||||||
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DDEBUGMODE=1" )
|
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DDEBUGMODE=1" )
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUC )
|
if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-pointer-sign -Wno-uninitialized" )
|
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-pointer-sign -Wno-uninitialized" )
|
||||||
endif( CMAKE_COMPILER_IS_GNUC )
|
endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
CHECK_FUNCTION_EXISTS( itoa ITOA_EXISTS )
|
CHECK_FUNCTION_EXISTS( itoa ITOA_EXISTS )
|
||||||
if( NOT ITOA_EXISTS )
|
if( NOT ITOA_EXISTS )
|
||||||
|
@ -36,6 +36,7 @@ add_library( dumb
|
||||||
src/core/rendsig.c
|
src/core/rendsig.c
|
||||||
src/core/unload.c
|
src/core/unload.c
|
||||||
src/helpers/barray.c
|
src/helpers/barray.c
|
||||||
|
src/helpers/blip_buf.c
|
||||||
src/helpers/clickrem.c
|
src/helpers/clickrem.c
|
||||||
src/helpers/memfile.c
|
src/helpers/memfile.c
|
||||||
src/helpers/resample.c
|
src/helpers/resample.c
|
||||||
|
@ -60,6 +61,8 @@ add_library( dumb
|
||||||
src/it/loadmod2.c
|
src/it/loadmod2.c
|
||||||
src/it/loadmtm.c
|
src/it/loadmtm.c
|
||||||
src/it/loadmtm2.c
|
src/it/loadmtm2.c
|
||||||
|
src/it/loadokt.c
|
||||||
|
src/it/loadokt2.c
|
||||||
src/it/loadoldpsm.c
|
src/it/loadoldpsm.c
|
||||||
src/it/loadoldpsm2.c
|
src/it/loadoldpsm2.c
|
||||||
src/it/loadpsm.c
|
src/it/loadpsm.c
|
||||||
|
@ -83,6 +86,8 @@ add_library( dumb
|
||||||
src/it/readmod.c
|
src/it/readmod.c
|
||||||
src/it/readmod2.c
|
src/it/readmod2.c
|
||||||
src/it/readmtm.c
|
src/it/readmtm.c
|
||||||
|
src/it/readokt.c
|
||||||
|
src/it/readokt2.c
|
||||||
src/it/readoldpsm.c
|
src/it/readoldpsm.c
|
||||||
src/it/readpsm.c
|
src/it/readpsm.c
|
||||||
src/it/readptm.c
|
src/it/readptm.c
|
||||||
|
@ -96,6 +101,6 @@ add_library( dumb
|
||||||
src/it/xmeffect.c )
|
src/it/xmeffect.c )
|
||||||
target_link_libraries( dumb )
|
target_link_libraries( dumb )
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
set_source_files_properties( src/it/filter.cpp PROPERTIES COMPILE_FLAGS -msse )
|
set_source_files_properties( src/it/filter.cpp PROPERTIES COMPILE_FLAGS -msse )
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
|
@ -233,7 +233,6 @@ int32 DUMBEXPORT duh_get_length(DUH *duh);
|
||||||
|
|
||||||
const char *DUMBEXPORT duh_get_tag(DUH *duh, const char *key);
|
const char *DUMBEXPORT duh_get_tag(DUH *duh, const char *key);
|
||||||
|
|
||||||
|
|
||||||
/* Signal Rendering Functions */
|
/* Signal Rendering Functions */
|
||||||
|
|
||||||
typedef struct DUH_SIGRENDERER DUH_SIGRENDERER;
|
typedef struct DUH_SIGRENDERER DUH_SIGRENDERER;
|
||||||
|
@ -396,11 +395,13 @@ void DUMBEXPORT dumb_it_set_global_volume_zero_callback(DUMB_IT_SIGRENDERER *sig
|
||||||
int DUMBCALLBACK dumb_it_callback_terminate(void *data);
|
int DUMBCALLBACK dumb_it_callback_terminate(void *data);
|
||||||
int DUMBCALLBACK dumb_it_callback_midi_block(void *data, int channel, unsigned char midi_byte);
|
int DUMBCALLBACK dumb_it_callback_midi_block(void *data, int channel, unsigned char midi_byte);
|
||||||
|
|
||||||
|
/* dumb_*_mod*: restrict |= 1-Don't read 15 sample files / 2-Use old pattern counting method */
|
||||||
|
|
||||||
DUH *DUMBEXPORT dumb_load_it(const char *filename);
|
DUH *DUMBEXPORT dumb_load_it(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_xm(const char *filename);
|
DUH *DUMBEXPORT dumb_load_xm(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_s3m(const char *filename);
|
DUH *DUMBEXPORT dumb_load_s3m(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_stm(const char *filename);
|
DUH *DUMBEXPORT dumb_load_stm(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_mod(const char *filename, int restrict);
|
DUH *DUMBEXPORT dumb_load_mod(const char *filename, int rstrict);
|
||||||
DUH *DUMBEXPORT dumb_load_ptm(const char *filename);
|
DUH *DUMBEXPORT dumb_load_ptm(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_669(const char *filename);
|
DUH *DUMBEXPORT dumb_load_669(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_psm(const char *filename, int subsong);
|
DUH *DUMBEXPORT dumb_load_psm(const char *filename, int subsong);
|
||||||
|
@ -408,12 +409,13 @@ DUH *DUMBEXPORT dumb_load_old_psm(const char * filename);
|
||||||
DUH *DUMBEXPORT dumb_load_mtm(const char *filename);
|
DUH *DUMBEXPORT dumb_load_mtm(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_riff(const char *filename);
|
DUH *DUMBEXPORT dumb_load_riff(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_asy(const char *filename);
|
DUH *DUMBEXPORT dumb_load_asy(const char *filename);
|
||||||
|
DUH *DUMBEXPORT dumb_load_okt(const char *filename);
|
||||||
|
|
||||||
DUH *DUMBEXPORT dumb_read_it(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_it(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_xm(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_xm(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_s3m(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_s3m(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_stm(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_stm(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_mod(DUMBFILE *f, int restrict);
|
DUH *DUMBEXPORT dumb_read_mod(DUMBFILE *f, int rstrict);
|
||||||
DUH *DUMBEXPORT dumb_read_ptm(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_ptm(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_669(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_669(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_psm(DUMBFILE *f, int subsong);
|
DUH *DUMBEXPORT dumb_read_psm(DUMBFILE *f, int subsong);
|
||||||
|
@ -421,12 +423,13 @@ DUH *DUMBEXPORT dumb_read_old_psm(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_mtm(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_mtm(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_riff(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_riff(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_asy(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_asy(DUMBFILE *f);
|
||||||
|
DUH *DUMBEXPORT dumb_read_okt(DUMBFILE *f);
|
||||||
|
|
||||||
DUH *DUMBEXPORT dumb_load_it_quick(const char *filename);
|
DUH *DUMBEXPORT dumb_load_it_quick(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_xm_quick(const char *filename);
|
DUH *DUMBEXPORT dumb_load_xm_quick(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_s3m_quick(const char *filename);
|
DUH *DUMBEXPORT dumb_load_s3m_quick(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_stm_quick(const char *filename);
|
DUH *DUMBEXPORT dumb_load_stm_quick(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_mod_quick(const char *filename, int restrict);
|
DUH *DUMBEXPORT dumb_load_mod_quick(const char *filename, int rstrict);
|
||||||
DUH *DUMBEXPORT dumb_load_ptm_quick(const char *filename);
|
DUH *DUMBEXPORT dumb_load_ptm_quick(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_669_quick(const char *filename);
|
DUH *DUMBEXPORT dumb_load_669_quick(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_psm_quick(const char *filename, int subsong);
|
DUH *DUMBEXPORT dumb_load_psm_quick(const char *filename, int subsong);
|
||||||
|
@ -434,12 +437,13 @@ DUH *DUMBEXPORT dumb_load_old_psm_quick(const char * filename);
|
||||||
DUH *DUMBEXPORT dumb_load_mtm_quick(const char *filename);
|
DUH *DUMBEXPORT dumb_load_mtm_quick(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_riff_quick(const char *filename);
|
DUH *DUMBEXPORT dumb_load_riff_quick(const char *filename);
|
||||||
DUH *DUMBEXPORT dumb_load_asy_quick(const char *filename);
|
DUH *DUMBEXPORT dumb_load_asy_quick(const char *filename);
|
||||||
|
DUH *DUMBEXPORT dumb_load_okt_quick(const char *filename);
|
||||||
|
|
||||||
DUH *DUMBEXPORT dumb_read_it_quick(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_it_quick(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_xm_quick(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_xm_quick(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_s3m_quick(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_s3m_quick(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_stm_quick(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_stm_quick(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_mod_quick(DUMBFILE *f, int restrict);
|
DUH *DUMBEXPORT dumb_read_mod_quick(DUMBFILE *f, int rstrict);
|
||||||
DUH *DUMBEXPORT dumb_read_ptm_quick(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_ptm_quick(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_669_quick(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_669_quick(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_psm_quick(DUMBFILE *f, int subsong);
|
DUH *DUMBEXPORT dumb_read_psm_quick(DUMBFILE *f, int subsong);
|
||||||
|
@ -447,6 +451,7 @@ DUH *DUMBEXPORT dumb_read_old_psm_quick(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_mtm_quick(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_mtm_quick(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_riff_quick(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_riff_quick(DUMBFILE *f);
|
||||||
DUH *DUMBEXPORT dumb_read_asy_quick(DUMBFILE *f);
|
DUH *DUMBEXPORT dumb_read_asy_quick(DUMBFILE *f);
|
||||||
|
DUH *DUMBEXPORT dumb_read_okt_quick(DUMBFILE *f);
|
||||||
|
|
||||||
int32 DUMBEXPORT dumb_it_build_checkpoints(DUMB_IT_SIGDATA *sigdata, int startorder);
|
int32 DUMBEXPORT dumb_it_build_checkpoints(DUMB_IT_SIGDATA *sigdata, int startorder);
|
||||||
void DUMBEXPORT dumb_it_do_initial_runthrough(DUH *duh);
|
void DUMBEXPORT dumb_it_do_initial_runthrough(DUH *duh);
|
||||||
|
@ -606,6 +611,8 @@ sigdata_t *DUMBEXPORT duh_get_raw_sigdata(DUH *duh, int sig, int32 type);
|
||||||
DUH_SIGRENDERER *DUMBEXPORT duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, int32 pos);
|
DUH_SIGRENDERER *DUMBEXPORT duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, int32 pos);
|
||||||
sigrenderer_t *DUMBEXPORT duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, int32 type);
|
sigrenderer_t *DUMBEXPORT duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, int32 type);
|
||||||
|
|
||||||
|
int DUMBEXPORT duh_add_signal(DUH *duh, DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata);
|
||||||
|
|
||||||
|
|
||||||
/* Standard Signal Types */
|
/* Standard Signal Types */
|
||||||
|
|
||||||
|
@ -662,6 +669,8 @@ typedef struct DUMB_VOLUME_RAMP_INFO DUMB_VOLUME_RAMP_INFO;
|
||||||
|
|
||||||
typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data);
|
typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data);
|
||||||
|
|
||||||
|
#include "internal/blip_buf.h"
|
||||||
|
|
||||||
struct DUMB_RESAMPLER
|
struct DUMB_RESAMPLER
|
||||||
{
|
{
|
||||||
void *src;
|
void *src;
|
||||||
|
@ -679,6 +688,9 @@ struct DUMB_RESAMPLER
|
||||||
signed char x8[3*2];
|
signed char x8[3*2];
|
||||||
} x;
|
} x;
|
||||||
int overshot;
|
int overshot;
|
||||||
|
int last_clock;
|
||||||
|
int last_amp[2];
|
||||||
|
blip_t* blip_buffer[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DUMB_VOLUME_RAMP_INFO
|
struct DUMB_VOLUME_RAMP_INFO
|
||||||
|
|
77
dumb/include/internal/blip_buf.h
Normal file
77
dumb/include/internal/blip_buf.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/** \file
|
||||||
|
Sample buffer that resamples from input clock rate to output sample rate */
|
||||||
|
|
||||||
|
/* blip_buf 1.1.0 */
|
||||||
|
#ifndef BLIP_BUF_H
|
||||||
|
#define BLIP_BUF_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** First parameter of most functions is blip_t*, or const blip_t* if nothing
|
||||||
|
is changed. */
|
||||||
|
typedef struct blip_t blip_t;
|
||||||
|
|
||||||
|
/** Creates new buffer that can hold at most sample_count samples. Sets rates
|
||||||
|
so that there are blip_max_ratio clocks per sample. Returns pointer to new
|
||||||
|
buffer, or NULL if insufficient memory. */
|
||||||
|
blip_t* blip_new( int sample_count );
|
||||||
|
|
||||||
|
blip_t* blip_dup( blip_t* );
|
||||||
|
|
||||||
|
/** Sets approximate input clock rate and output sample rate. For every
|
||||||
|
clock_rate input clocks, approximately sample_rate samples are generated. */
|
||||||
|
void blip_set_rates( blip_t*, double clock_rate, double sample_rate );
|
||||||
|
|
||||||
|
enum { /** Maximum clock_rate/sample_rate ratio. For a given sample_rate,
|
||||||
|
clock_rate must not be greater than sample_rate*blip_max_ratio. */
|
||||||
|
blip_max_ratio = 1 << 20 };
|
||||||
|
|
||||||
|
/** Clears entire buffer. Afterwards, blip_samples_avail() == 0. */
|
||||||
|
void blip_clear( blip_t* );
|
||||||
|
|
||||||
|
/** Adds positive/negative delta into buffer at specified clock time. */
|
||||||
|
void blip_add_delta( blip_t*, unsigned int clock_time, int delta );
|
||||||
|
|
||||||
|
/** Same as blip_add_delta(), but uses faster, lower-quality synthesis. */
|
||||||
|
void blip_add_delta_fast( blip_t*, unsigned int clock_time, int delta );
|
||||||
|
|
||||||
|
/** Length of time frame, in clocks, needed to make sample_count additional
|
||||||
|
samples available. */
|
||||||
|
int blip_clocks_needed( const blip_t*, int sample_count );
|
||||||
|
|
||||||
|
enum { /** Maximum number of samples that can be generated from one time frame. */
|
||||||
|
blip_max_frame = 4000 };
|
||||||
|
|
||||||
|
/** Makes input clocks before clock_duration available for reading as output
|
||||||
|
samples. Also begins new time frame at clock_duration, so that clock time 0 in
|
||||||
|
the new time frame specifies the same clock as clock_duration in the old time
|
||||||
|
frame specified. Deltas can have been added slightly past clock_duration (up to
|
||||||
|
however many clocks there are in two output samples). */
|
||||||
|
void blip_end_frame( blip_t*, unsigned int clock_duration );
|
||||||
|
|
||||||
|
/** Number of buffered samples available for reading. */
|
||||||
|
int blip_samples_avail( const blip_t* );
|
||||||
|
|
||||||
|
/** Reads and removes at most 'count' samples and writes them to 'out'. If
|
||||||
|
'stereo' is true, writes output to every other element of 'out', allowing easy
|
||||||
|
interleaving of two buffers into a stereo sample stream. Outputs 16-bit signed
|
||||||
|
samples. Returns number of samples actually read. */
|
||||||
|
int blip_read_samples( blip_t*, int out [], int count );
|
||||||
|
|
||||||
|
/** Reads the current integrator and returns it */
|
||||||
|
int blip_peek_sample( blip_t* );
|
||||||
|
|
||||||
|
/** Frees buffer. No effect if NULL is passed. */
|
||||||
|
void blip_delete( blip_t* );
|
||||||
|
|
||||||
|
|
||||||
|
/* Deprecated */
|
||||||
|
typedef blip_t blip_buffer_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -54,7 +54,7 @@ sigdata->flags & IT_COMPATIBLE_GXX
|
||||||
* handle ambiguities in the format specification. The correct code in each
|
* handle ambiguities in the format specification. The correct code in each
|
||||||
* case will be determined most likely by experimentation.
|
* case will be determined most likely by experimentation.
|
||||||
*/
|
*/
|
||||||
#define STEREO_SAMPLES_COUNT_AS_TWO
|
//#define STEREO_SAMPLES_COUNT_AS_TWO
|
||||||
#define INVALID_ORDERS_END_SONG
|
#define INVALID_ORDERS_END_SONG
|
||||||
#define INVALID_NOTES_CAUSE_NOTE_CUT
|
#define INVALID_NOTES_CAUSE_NOTE_CUT
|
||||||
#define SUSTAIN_LOOP_OVERRIDES_NORMAL_LOOP
|
#define SUSTAIN_LOOP_OVERRIDES_NORMAL_LOOP
|
||||||
|
@ -300,7 +300,18 @@ struct IT_SAMPLE
|
||||||
#define IT_PTM_NOTE_SLIDE_DOWN_RETRIG 36
|
#define IT_PTM_NOTE_SLIDE_DOWN_RETRIG 36
|
||||||
#define IT_PTM_NOTE_SLIDE_UP_RETRIG 37
|
#define IT_PTM_NOTE_SLIDE_UP_RETRIG 37
|
||||||
|
|
||||||
#define IT_N_EFFECTS 38
|
/* More effects needed for OKT compatibility */
|
||||||
|
#define IT_OKT_NOTE_SLIDE_DOWN 38
|
||||||
|
#define IT_OKT_NOTE_SLIDE_DOWN_ROW 39
|
||||||
|
#define IT_OKT_NOTE_SLIDE_UP 40
|
||||||
|
#define IT_OKT_NOTE_SLIDE_UP_ROW 41
|
||||||
|
#define IT_OKT_ARPEGGIO_3 42
|
||||||
|
#define IT_OKT_ARPEGGIO_4 43
|
||||||
|
#define IT_OKT_ARPEGGIO_5 44
|
||||||
|
#define IT_OKT_VOLUME_SLIDE_DOWN 45
|
||||||
|
#define IT_OKT_VOLUME_SLIDE_UP 46
|
||||||
|
|
||||||
|
#define IT_N_EFFECTS 47
|
||||||
|
|
||||||
/* These represent the top nibble of the command value. */
|
/* These represent the top nibble of the command value. */
|
||||||
#define IT_S_SET_FILTER 0 /* Greyed out in IT... */
|
#define IT_S_SET_FILTER 0 /* Greyed out in IT... */
|
||||||
|
@ -399,6 +410,10 @@ struct IT_PATTERN
|
||||||
|
|
||||||
#define IT_WAS_A_669 1024
|
#define IT_WAS_A_669 1024
|
||||||
|
|
||||||
|
#define IT_WAS_AN_OKT 2048
|
||||||
|
|
||||||
|
#define IT_WAS_AN_STM 4096
|
||||||
|
|
||||||
#define IT_ORDER_END 255
|
#define IT_ORDER_END 255
|
||||||
#define IT_ORDER_SKIP 254
|
#define IT_ORDER_SKIP 254
|
||||||
|
|
||||||
|
@ -452,6 +467,7 @@ struct IT_PLAYING_ENVELOPE
|
||||||
#define IT_PLAYING_SUSTAINOFF 2
|
#define IT_PLAYING_SUSTAINOFF 2
|
||||||
#define IT_PLAYING_FADING 4
|
#define IT_PLAYING_FADING 4
|
||||||
#define IT_PLAYING_DEAD 8
|
#define IT_PLAYING_DEAD 8
|
||||||
|
#define IT_PLAYING_REVERSE 16
|
||||||
|
|
||||||
struct IT_PLAYING
|
struct IT_PLAYING
|
||||||
{
|
{
|
||||||
|
@ -586,7 +602,8 @@ struct IT_CHANNEL
|
||||||
|
|
||||||
unsigned char new_note_action;
|
unsigned char new_note_action;
|
||||||
|
|
||||||
int arpeggio;
|
unsigned int arpeggio;
|
||||||
|
int arpeggio_shift;
|
||||||
unsigned char retrig;
|
unsigned char retrig;
|
||||||
unsigned char xm_retrig;
|
unsigned char xm_retrig;
|
||||||
int retrig_tick;
|
int retrig_tick;
|
||||||
|
@ -601,7 +618,7 @@ struct IT_CHANNEL
|
||||||
int portamento;
|
int portamento;
|
||||||
int toneporta;
|
int toneporta;
|
||||||
int toneslide;
|
int toneslide;
|
||||||
unsigned char toneslide_tick, last_toneslide_tick, ptm_toneslide, ptm_last_toneslide;
|
unsigned char toneslide_tick, last_toneslide_tick, ptm_toneslide, ptm_last_toneslide, okt_toneslide;
|
||||||
unsigned char destnote;
|
unsigned char destnote;
|
||||||
unsigned char toneslide_retrig;
|
unsigned char toneslide_retrig;
|
||||||
|
|
||||||
|
@ -643,6 +660,10 @@ struct IT_CHANNEL
|
||||||
unsigned char xm_lastX1;
|
unsigned char xm_lastX1;
|
||||||
unsigned char xm_lastX2;
|
unsigned char xm_lastX2;
|
||||||
|
|
||||||
|
unsigned char inv_loop_delay;
|
||||||
|
unsigned char inv_loop_speed;
|
||||||
|
int inv_loop_offset;
|
||||||
|
|
||||||
IT_PLAYING *playing;
|
IT_PLAYING *playing;
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
#ifdef BIT_ARRAY_BULLSHIT
|
||||||
|
@ -802,6 +823,7 @@ extern DUH_SIGTYPE_DESC _dumb_sigtype_it;
|
||||||
#define XM_E_NOTE_CUT 0xC
|
#define XM_E_NOTE_CUT 0xC
|
||||||
#define XM_E_NOTE_DELAY 0xD
|
#define XM_E_NOTE_DELAY 0xD
|
||||||
#define XM_E_PATTERN_DELAY 0xE
|
#define XM_E_PATTERN_DELAY 0xE
|
||||||
|
#define XM_E_SET_MIDI_MACRO 0xF
|
||||||
|
|
||||||
#define XM_X_EXTRAFINE_PORTA_UP 1
|
#define XM_X_EXTRAFINE_PORTA_UP 1
|
||||||
#define XM_X_EXTRAFINE_PORTA_DOWN 2
|
#define XM_X_EXTRAFINE_PORTA_DOWN 2
|
||||||
|
@ -880,4 +902,6 @@ void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry);
|
||||||
|
|
||||||
int32 _dumb_it_read_sample_data_adpcm4(IT_SAMPLE *sample, DUMBFILE *f);
|
int32 _dumb_it_read_sample_data_adpcm4(IT_SAMPLE *sample, DUMBFILE *f);
|
||||||
|
|
||||||
|
void _dumb_it_interleave_stereo_sample(IT_SAMPLE *sample);
|
||||||
|
|
||||||
#endif /* INTERNAL_IT_H */
|
#endif /* INTERNAL_IT_H */
|
||||||
|
|
|
@ -130,3 +130,22 @@ DUH *make_duh(
|
||||||
|
|
||||||
return duh;
|
return duh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DUMBEXPORT duh_add_signal(DUH *duh, DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
|
||||||
|
{
|
||||||
|
DUH_SIGNAL **signal;
|
||||||
|
|
||||||
|
if ( !duh || !desc || !sigdata ) return -1;
|
||||||
|
|
||||||
|
signal = ( DUH_SIGNAL ** ) realloc( duh->signal, ( duh->n_signals + 1 ) * sizeof( *duh->signal ) );
|
||||||
|
if ( !signal ) return -1;
|
||||||
|
duh->signal = signal;
|
||||||
|
|
||||||
|
memmove( signal + 1, signal, duh->n_signals * sizeof( *signal ) );
|
||||||
|
duh->n_signals++;
|
||||||
|
|
||||||
|
signal[ 0 ] = make_signal( desc, sigdata );
|
||||||
|
if ( !signal[ 0 ] ) return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -29,16 +29,30 @@
|
||||||
*/
|
*/
|
||||||
sigdata_t *DUMBEXPORT duh_get_raw_sigdata(DUH *duh, int sig, int32 type)
|
sigdata_t *DUMBEXPORT duh_get_raw_sigdata(DUH *duh, int sig, int32 type)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
DUH_SIGNAL *signal;
|
DUH_SIGNAL *signal;
|
||||||
|
|
||||||
if (!duh) return NULL;
|
if (!duh) return NULL;
|
||||||
|
|
||||||
|
if ( sig >= 0 )
|
||||||
|
{
|
||||||
if ((unsigned int)sig >= (unsigned int)duh->n_signals) return NULL;
|
if ((unsigned int)sig >= (unsigned int)duh->n_signals) return NULL;
|
||||||
|
|
||||||
signal = duh->signal[sig];
|
signal = duh->signal[sig];
|
||||||
|
|
||||||
if (signal && signal->desc->type == type)
|
if (signal && signal->desc->type == type)
|
||||||
return signal->sigdata;
|
return signal->sigdata;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( i = 0; i < duh->n_signals; i++ )
|
||||||
|
{
|
||||||
|
signal = duh->signal[i];
|
||||||
|
|
||||||
|
if (signal && signal->desc->type == type)
|
||||||
|
return signal->sigdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
354
dumb/src/helpers/blip_buf.c
Normal file
354
dumb/src/helpers/blip_buf.c
Normal file
|
@ -0,0 +1,354 @@
|
||||||
|
/* blip_buf 1.1.0. http://www.slack.net/~ant/ */
|
||||||
|
|
||||||
|
#include "internal/blip_buf.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Library Copyright (C) 2003-2009 Shay Green. This library is free software;
|
||||||
|
you can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||||
|
General Public License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
|
library 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 Lesser General Public License for more
|
||||||
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
|
#if defined (BLARGG_TEST) && BLARGG_TEST
|
||||||
|
#include "blargg_test.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Equivalent to ULONG_MAX >= 0xFFFFFFFF00000000.
|
||||||
|
Avoids constants that don't fit in 32 bits. */
|
||||||
|
#if ULONG_MAX/0xFFFFFFFF > 0xFFFFFFFF
|
||||||
|
typedef unsigned long fixed_t;
|
||||||
|
enum { pre_shift = 32 };
|
||||||
|
|
||||||
|
#elif defined(ULLONG_MAX)
|
||||||
|
typedef unsigned long long fixed_t;
|
||||||
|
enum { pre_shift = 32 };
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef unsigned fixed_t;
|
||||||
|
enum { pre_shift = 0 };
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum { time_bits = pre_shift + 20 };
|
||||||
|
|
||||||
|
static fixed_t const time_unit = (fixed_t) 1 << time_bits;
|
||||||
|
|
||||||
|
enum { bass_shift = 9 }; /* affects high-pass filter breakpoint frequency */
|
||||||
|
enum { end_frame_extra = 2 }; /* allows deltas slightly after frame length */
|
||||||
|
|
||||||
|
enum { half_width = 8 };
|
||||||
|
enum { buf_extra = half_width*2 + end_frame_extra };
|
||||||
|
enum { phase_bits = 5 };
|
||||||
|
enum { phase_count = 1 << phase_bits };
|
||||||
|
enum { delta_bits = 15 };
|
||||||
|
enum { delta_unit = 1 << delta_bits };
|
||||||
|
enum { frac_bits = time_bits - pre_shift };
|
||||||
|
|
||||||
|
/* We could eliminate avail and encode whole samples in offset, but that would
|
||||||
|
limit the total buffered samples to blip_max_frame. That could only be
|
||||||
|
increased by decreasing time_bits, which would reduce resample ratio accuracy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Sample buffer that resamples to output rate and accumulates samples
|
||||||
|
until they're read out */
|
||||||
|
struct blip_t
|
||||||
|
{
|
||||||
|
fixed_t factor;
|
||||||
|
fixed_t offset;
|
||||||
|
int avail;
|
||||||
|
int size;
|
||||||
|
int integrator;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int buf_t;
|
||||||
|
|
||||||
|
/* probably not totally portable */
|
||||||
|
#define SAMPLES( buf ) ((buf_t*) ((buf) + 1))
|
||||||
|
|
||||||
|
/* Arithmetic (sign-preserving) right shift */
|
||||||
|
#define ARITH_SHIFT( n, shift ) \
|
||||||
|
((n) >> (shift))
|
||||||
|
|
||||||
|
enum { max_sample = +32767 };
|
||||||
|
enum { min_sample = -32768 };
|
||||||
|
|
||||||
|
#define CLAMP( n ) \
|
||||||
|
{\
|
||||||
|
if ( (short) n != n )\
|
||||||
|
n = ARITH_SHIFT( n, 16 ) ^ max_sample;\
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_assumptions( void )
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
#if INT_MAX < 0x7FFFFFFF || UINT_MAX < 0xFFFFFFFF
|
||||||
|
#error "int must be at least 32 bits"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert( (-3 >> 1) == -2 ); /* right shift must preserve sign */
|
||||||
|
|
||||||
|
n = max_sample * 2;
|
||||||
|
CLAMP( n );
|
||||||
|
assert( n == max_sample );
|
||||||
|
|
||||||
|
n = min_sample * 2;
|
||||||
|
CLAMP( n );
|
||||||
|
assert( n == min_sample );
|
||||||
|
|
||||||
|
assert( blip_max_ratio <= time_unit );
|
||||||
|
assert( blip_max_frame <= (fixed_t) -1 >> time_bits );
|
||||||
|
}
|
||||||
|
|
||||||
|
blip_t* blip_new( int size )
|
||||||
|
{
|
||||||
|
blip_t* m;
|
||||||
|
assert( size >= 0 );
|
||||||
|
|
||||||
|
m = (blip_t*) malloc( sizeof *m + (size + buf_extra) * sizeof (buf_t) );
|
||||||
|
if ( m )
|
||||||
|
{
|
||||||
|
m->factor = time_unit / blip_max_ratio;
|
||||||
|
m->size = size;
|
||||||
|
blip_clear( m );
|
||||||
|
check_assumptions();
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
blip_t* blip_dup( blip_t* m )
|
||||||
|
{
|
||||||
|
size_t size = sizeof *m + (m->size + buf_extra) * sizeof(buf_t);
|
||||||
|
blip_t* r = (blip_t*) malloc( size );
|
||||||
|
if ( r ) memcpy( r, m, size );
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_delete( blip_t* m )
|
||||||
|
{
|
||||||
|
if ( m != NULL )
|
||||||
|
{
|
||||||
|
/* Clear fields in case user tries to use after freeing */
|
||||||
|
memset( m, 0, sizeof *m );
|
||||||
|
free( m );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_set_rates( blip_t* m, double clock_rate, double sample_rate )
|
||||||
|
{
|
||||||
|
double factor = time_unit * sample_rate / clock_rate;
|
||||||
|
m->factor = (fixed_t) factor;
|
||||||
|
|
||||||
|
/* Fails if clock_rate exceeds maximum, relative to sample_rate */
|
||||||
|
assert( 0 <= factor - m->factor && factor - m->factor < 1 );
|
||||||
|
|
||||||
|
/* Avoid requiring math.h. Equivalent to
|
||||||
|
m->factor = (int) ceil( factor ) */
|
||||||
|
if ( m->factor < factor )
|
||||||
|
m->factor++;
|
||||||
|
|
||||||
|
/* At this point, factor is most likely rounded up, but could still
|
||||||
|
have been rounded down in the floating-point calculation. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_clear( blip_t* m )
|
||||||
|
{
|
||||||
|
/* We could set offset to 0, factor/2, or factor-1. 0 is suitable if
|
||||||
|
factor is rounded up. factor-1 is suitable if factor is rounded down.
|
||||||
|
Since we don't know rounding direction, factor/2 accommodates either,
|
||||||
|
with the slight loss of showing an error in half the time. Since for
|
||||||
|
a 64-bit factor this is years, the halving isn't a problem. */
|
||||||
|
|
||||||
|
m->offset = m->factor / 2;
|
||||||
|
m->avail = 0;
|
||||||
|
m->integrator = 0;
|
||||||
|
memset( SAMPLES( m ), 0, (m->size + buf_extra) * sizeof (buf_t) );
|
||||||
|
}
|
||||||
|
|
||||||
|
int blip_clocks_needed( const blip_t* m, int samples )
|
||||||
|
{
|
||||||
|
fixed_t needed;
|
||||||
|
|
||||||
|
/* Fails if buffer can't hold that many more samples */
|
||||||
|
assert( samples >= 0 && m->avail + samples <= m->size );
|
||||||
|
|
||||||
|
needed = (fixed_t) samples * time_unit;
|
||||||
|
if ( needed < m->offset )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (int)((needed - m->offset + m->factor - 1) / m->factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_end_frame( blip_t* m, unsigned t )
|
||||||
|
{
|
||||||
|
fixed_t off = t * m->factor + m->offset;
|
||||||
|
m->avail += (int)(off >> time_bits);
|
||||||
|
m->offset = off & (time_unit - 1);
|
||||||
|
|
||||||
|
/* Fails if buffer size was exceeded */
|
||||||
|
assert( m->avail <= m->size );
|
||||||
|
}
|
||||||
|
|
||||||
|
int blip_samples_avail( const blip_t* m )
|
||||||
|
{
|
||||||
|
return m->avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_samples( blip_t* m, int count )
|
||||||
|
{
|
||||||
|
buf_t* buf = SAMPLES( m );
|
||||||
|
int remain = m->avail + buf_extra - count;
|
||||||
|
m->avail -= count;
|
||||||
|
|
||||||
|
memmove( &buf [0], &buf [count], remain * sizeof buf [0] );
|
||||||
|
memset( &buf [remain], 0, count * sizeof buf [0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
int blip_read_samples( blip_t* m, int out [], int count )
|
||||||
|
{
|
||||||
|
assert( count >= 0 );
|
||||||
|
|
||||||
|
if ( count > m->avail )
|
||||||
|
count = m->avail;
|
||||||
|
|
||||||
|
if ( count )
|
||||||
|
{
|
||||||
|
buf_t const* in = SAMPLES( m );
|
||||||
|
buf_t const* end = in + count;
|
||||||
|
int sum = m->integrator;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Eliminate fraction */
|
||||||
|
int s = ARITH_SHIFT( sum, delta_bits - 8 );
|
||||||
|
|
||||||
|
sum += *in++;
|
||||||
|
|
||||||
|
*out = s;
|
||||||
|
out++;
|
||||||
|
|
||||||
|
/* High-pass filter */
|
||||||
|
sum -= s >> (8 - (delta_bits - bass_shift)); //<< (delta_bits - bass_shift - 8);
|
||||||
|
}
|
||||||
|
while ( in != end );
|
||||||
|
m->integrator = sum;
|
||||||
|
|
||||||
|
remove_samples( m, count );
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int blip_peek_sample( blip_t* m )
|
||||||
|
{
|
||||||
|
return ARITH_SHIFT( m->integrator, delta_bits - 8 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Things that didn't help performance on x86:
|
||||||
|
__attribute__((aligned(128)))
|
||||||
|
#define short int
|
||||||
|
restrict
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Sinc_Generator( 0.9, 0.55, 4.5 ) */
|
||||||
|
static short const bl_step [phase_count + 1] [half_width] =
|
||||||
|
{
|
||||||
|
{ 43, -115, 350, -488, 1136, -914, 5861,21022},
|
||||||
|
{ 44, -118, 348, -473, 1076, -799, 5274,21001},
|
||||||
|
{ 45, -121, 344, -454, 1011, -677, 4706,20936},
|
||||||
|
{ 46, -122, 336, -431, 942, -549, 4156,20829},
|
||||||
|
{ 47, -123, 327, -404, 868, -418, 3629,20679},
|
||||||
|
{ 47, -122, 316, -375, 792, -285, 3124,20488},
|
||||||
|
{ 47, -120, 303, -344, 714, -151, 2644,20256},
|
||||||
|
{ 46, -117, 289, -310, 634, -17, 2188,19985},
|
||||||
|
{ 46, -114, 273, -275, 553, 117, 1758,19675},
|
||||||
|
{ 44, -108, 255, -237, 471, 247, 1356,19327},
|
||||||
|
{ 43, -103, 237, -199, 390, 373, 981,18944},
|
||||||
|
{ 42, -98, 218, -160, 310, 495, 633,18527},
|
||||||
|
{ 40, -91, 198, -121, 231, 611, 314,18078},
|
||||||
|
{ 38, -84, 178, -81, 153, 722, 22,17599},
|
||||||
|
{ 36, -76, 157, -43, 80, 824, -241,17092},
|
||||||
|
{ 34, -68, 135, -3, 8, 919, -476,16558},
|
||||||
|
{ 32, -61, 115, 34, -60, 1006, -683,16001},
|
||||||
|
{ 29, -52, 94, 70, -123, 1083, -862,15422},
|
||||||
|
{ 27, -44, 73, 106, -184, 1152,-1015,14824},
|
||||||
|
{ 25, -36, 53, 139, -239, 1211,-1142,14210},
|
||||||
|
{ 22, -27, 34, 170, -290, 1261,-1244,13582},
|
||||||
|
{ 20, -20, 16, 199, -335, 1301,-1322,12942},
|
||||||
|
{ 18, -12, -3, 226, -375, 1331,-1376,12293},
|
||||||
|
{ 15, -4, -19, 250, -410, 1351,-1408,11638},
|
||||||
|
{ 13, 3, -35, 272, -439, 1361,-1419,10979},
|
||||||
|
{ 11, 9, -49, 292, -464, 1362,-1410,10319},
|
||||||
|
{ 9, 16, -63, 309, -483, 1354,-1383, 9660},
|
||||||
|
{ 7, 22, -75, 322, -496, 1337,-1339, 9005},
|
||||||
|
{ 6, 26, -85, 333, -504, 1312,-1280, 8355},
|
||||||
|
{ 4, 31, -94, 341, -507, 1278,-1205, 7713},
|
||||||
|
{ 3, 35, -102, 347, -506, 1238,-1119, 7082},
|
||||||
|
{ 1, 40, -110, 350, -499, 1190,-1021, 6464},
|
||||||
|
{ 0, 43, -115, 350, -488, 1136, -914, 5861}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Shifting by pre_shift allows calculation using unsigned int rather than
|
||||||
|
possibly-wider fixed_t. On 32-bit platforms, this is likely more efficient.
|
||||||
|
And by having pre_shift 32, a 32-bit platform can easily do the shift by
|
||||||
|
simply ignoring the low half. */
|
||||||
|
|
||||||
|
void blip_add_delta( blip_t* m, unsigned time, int delta )
|
||||||
|
{
|
||||||
|
unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift);
|
||||||
|
buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits);
|
||||||
|
|
||||||
|
int const phase_shift = frac_bits - phase_bits;
|
||||||
|
int phase = fixed >> phase_shift & (phase_count - 1);
|
||||||
|
short const* in = bl_step [phase];
|
||||||
|
short const* rev = bl_step [phase_count - phase];
|
||||||
|
|
||||||
|
int interp = fixed >> (phase_shift - delta_bits) & (delta_unit - 1);
|
||||||
|
int delta2 = (delta * interp) >> delta_bits;
|
||||||
|
delta -= delta2;
|
||||||
|
|
||||||
|
/* Fails if buffer size was exceeded */
|
||||||
|
assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] );
|
||||||
|
|
||||||
|
out [0] += in[0]*delta + in[half_width+0]*delta2;
|
||||||
|
out [1] += in[1]*delta + in[half_width+1]*delta2;
|
||||||
|
out [2] += in[2]*delta + in[half_width+2]*delta2;
|
||||||
|
out [3] += in[3]*delta + in[half_width+3]*delta2;
|
||||||
|
out [4] += in[4]*delta + in[half_width+4]*delta2;
|
||||||
|
out [5] += in[5]*delta + in[half_width+5]*delta2;
|
||||||
|
out [6] += in[6]*delta + in[half_width+6]*delta2;
|
||||||
|
out [7] += in[7]*delta + in[half_width+7]*delta2;
|
||||||
|
|
||||||
|
in = rev;
|
||||||
|
out [ 8] += in[7]*delta + in[7-half_width]*delta2;
|
||||||
|
out [ 9] += in[6]*delta + in[6-half_width]*delta2;
|
||||||
|
out [10] += in[5]*delta + in[5-half_width]*delta2;
|
||||||
|
out [11] += in[4]*delta + in[4-half_width]*delta2;
|
||||||
|
out [12] += in[3]*delta + in[3-half_width]*delta2;
|
||||||
|
out [13] += in[2]*delta + in[2-half_width]*delta2;
|
||||||
|
out [14] += in[1]*delta + in[1-half_width]*delta2;
|
||||||
|
out [15] += in[0]*delta + in[0-half_width]*delta2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_add_delta_fast( blip_t* m, unsigned time, int delta )
|
||||||
|
{
|
||||||
|
unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift);
|
||||||
|
buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits);
|
||||||
|
|
||||||
|
int interp = fixed >> (frac_bits - delta_bits) & (delta_unit - 1);
|
||||||
|
int delta2 = delta * interp;
|
||||||
|
|
||||||
|
/* Fails if buffer size was exceeded */
|
||||||
|
assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] );
|
||||||
|
|
||||||
|
out [7] += delta * delta_unit - delta2;
|
||||||
|
out [8] += delta2;
|
||||||
|
}
|
|
@ -95,7 +95,8 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||||
#define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES
|
#define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES
|
||||||
#define RETURN_VOLUME_VARIABLES RETURN_MONO_DEST_VOLUME_VARIABLES
|
#define RETURN_VOLUME_VARIABLES RETURN_MONO_DEST_VOLUME_VARIABLES
|
||||||
#define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO
|
#define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO
|
||||||
#define MIX_ALIAS(op, upd, offset) MONO_DEST_MIX_ALIAS(op, upd, offset)
|
#define MIX_ALIAS(count) MONO_DEST_MIX_ALIAS(count)
|
||||||
|
#define PEEK_ALIAS MONO_DEST_PEEK_ALIAS
|
||||||
#define MIX_LINEAR(op, upd, o0, o1) MONO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
#define MIX_LINEAR(op, upd, o0, o1) MONO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
||||||
#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
|
#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
|
||||||
#define MIX_ZEROS(op) *dst++ op 0
|
#define MIX_ZEROS(op) *dst++ op 0
|
||||||
|
@ -137,7 +138,8 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||||
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
||||||
}
|
}
|
||||||
#define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
#define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
||||||
#define MIX_ALIAS(op, upd, offset) STEREO_DEST_MIX_ALIAS(op, upd, offset)
|
#define MIX_ALIAS(count) STEREO_DEST_MIX_ALIAS(count)
|
||||||
|
#define PEEK_ALIAS STEREO_DEST_PEEK_ALIAS
|
||||||
#define MIX_LINEAR(op, upd, o0, o1) STEREO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
#define MIX_LINEAR(op, upd, o0, o1) STEREO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
||||||
#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) STEREO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
|
#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) STEREO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
|
||||||
#define MIX_ZEROS(op) { *dst++ op 0; *dst++ op 0; }
|
#define MIX_ZEROS(op) { *dst++ op 0; *dst++ op 0; }
|
||||||
|
@ -157,6 +159,9 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||||
#undef MONO_DEST_VOLUME_ZEROS
|
#undef MONO_DEST_VOLUME_ZEROS
|
||||||
#undef MONO_DEST_VOLUME_VARIABLES
|
#undef MONO_DEST_VOLUME_VARIABLES
|
||||||
#undef MONO_DEST_VOLUME_PARAMETERS
|
#undef MONO_DEST_VOLUME_PARAMETERS
|
||||||
|
#undef STEREO_DEST_PEEK_ALIAS
|
||||||
|
#undef MONO_DEST_PEEK_ALIAS
|
||||||
|
#undef POKE_ALIAS
|
||||||
#undef COPYSRC2
|
#undef COPYSRC2
|
||||||
#undef COPYSRC
|
#undef COPYSRC
|
||||||
#undef DIVIDE_BY_SRC_CHANNELS
|
#undef DIVIDE_BY_SRC_CHANNELS
|
||||||
|
|
|
@ -46,12 +46,13 @@
|
||||||
|
|
||||||
int32 dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, VOLUME_PARAMETERS, double delta)
|
int32 dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, VOLUME_PARAMETERS, double delta)
|
||||||
{
|
{
|
||||||
int dt;
|
int dt, inv_dt;
|
||||||
int VOLUME_VARIABLES;
|
int VOLUME_VARIABLES;
|
||||||
long done;
|
long done;
|
||||||
long todo;
|
long todo;
|
||||||
LONG_LONG todo64;
|
LONG_LONG todo64;
|
||||||
int quality;
|
int quality;
|
||||||
|
int blip_samples[256*SRC_CHANNELS];
|
||||||
|
|
||||||
if (!resampler || resampler->dir == 0) return 0;
|
if (!resampler || resampler->dir == 0) return 0;
|
||||||
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
||||||
|
@ -59,6 +60,7 @@ int32 dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, VO
|
||||||
done = 0;
|
done = 0;
|
||||||
dt = (int)(delta * 65536.0 + 0.5);
|
dt = (int)(delta * 65536.0 + 0.5);
|
||||||
if (dt == 0 || dt == 0x80000000) return 0;
|
if (dt == 0 || dt == 0x80000000) return 0;
|
||||||
|
inv_dt = (int)(1.0 / delta * 65536.0 + 0.5);
|
||||||
SET_VOLUME_VARIABLES;
|
SET_VOLUME_VARIABLES;
|
||||||
|
|
||||||
if (VOLUMES_ARE_ZERO) dst = NULL;
|
if (VOLUMES_ARE_ZERO) dst = NULL;
|
||||||
|
@ -104,29 +106,33 @@ int32 dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, VO
|
||||||
subpos = (long)new_subpos & 65535;
|
subpos = (long)new_subpos & 65535;
|
||||||
} else if (quality <= DUMB_RQ_ALIASING) {
|
} else if (quality <= DUMB_RQ_ALIASING) {
|
||||||
/* Aliasing, backwards */
|
/* Aliasing, backwards */
|
||||||
|
int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
|
||||||
SRCTYPE xbuf[2*SRC_CHANNELS];
|
SRCTYPE xbuf[2*SRC_CHANNELS];
|
||||||
SRCTYPE *x = &xbuf[0];
|
SRCTYPE *x = &xbuf[0];
|
||||||
SRCTYPE *xstart;
|
|
||||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||||
while (todo && x < &xbuf[2*SRC_CHANNELS]) {
|
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||||
|
while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
|
||||||
// TODO: check what happens when multiple tempo slides occur per row
|
// TODO: check what happens when multiple tempo slides occur per row
|
||||||
HEAVYASSERT(pos >= resampler->start);
|
HEAVYASSERT(pos >= resampler->start);
|
||||||
MIX_ALIAS(+=, 1, 0);
|
POKE_ALIAS(0);
|
||||||
subpos += dt;
|
pos--;
|
||||||
pos += subpos >> 16;
|
x += SRC_CHANNELS;
|
||||||
x -= (subpos >> 16) * SRC_CHANNELS;
|
}
|
||||||
subpos &= 65535;
|
x = &src[pos*SRC_CHANNELS];
|
||||||
todo--;
|
while ( todo_clocks ) {
|
||||||
|
todo_clocks_set = todo_clocks;
|
||||||
|
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||||
|
todo_clocks -= todo_clocks_set;
|
||||||
|
while ( resampler->last_clock < todo_clocks_set )
|
||||||
|
{
|
||||||
|
POKE_ALIAS(2);
|
||||||
|
pos--;
|
||||||
|
x -= SRC_CHANNELS;
|
||||||
|
}
|
||||||
|
todo = todo_clocks_set >> 16;
|
||||||
|
MIX_ALIAS( todo );
|
||||||
}
|
}
|
||||||
x = xstart = &src[pos*SRC_CHANNELS];
|
|
||||||
LOOP4(todo,
|
|
||||||
MIX_ALIAS(+=, 1, 2);
|
|
||||||
subpos += dt;
|
|
||||||
x += (subpos >> 16) * SRC_CHANNELS;
|
|
||||||
subpos &= 65535;
|
|
||||||
);
|
|
||||||
pos += DIVIDE_BY_SRC_CHANNELS((long)(x - xstart));
|
|
||||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||||
/* Linear interpolation, backwards */
|
/* Linear interpolation, backwards */
|
||||||
SRCTYPE xbuf[3*SRC_CHANNELS];
|
SRCTYPE xbuf[3*SRC_CHANNELS];
|
||||||
|
@ -205,28 +211,32 @@ int32 dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, VO
|
||||||
subpos = (long)new_subpos & 65535;
|
subpos = (long)new_subpos & 65535;
|
||||||
} else if (quality <= DUMB_RQ_ALIASING) {
|
} else if (quality <= DUMB_RQ_ALIASING) {
|
||||||
/* Aliasing, forwards */
|
/* Aliasing, forwards */
|
||||||
|
int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
|
||||||
SRCTYPE xbuf[2*SRC_CHANNELS];
|
SRCTYPE xbuf[2*SRC_CHANNELS];
|
||||||
SRCTYPE *x = &xbuf[0];
|
SRCTYPE *x = &xbuf[0];
|
||||||
SRCTYPE *xstart;
|
|
||||||
COPYSRC(xbuf, 0, resampler->X, 1);
|
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||||
COPYSRC(xbuf, 1, resampler->X, 2);
|
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||||
while (todo && x < &xbuf[2*SRC_CHANNELS]) {
|
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||||
|
while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
|
||||||
HEAVYASSERT(pos < resampler->end);
|
HEAVYASSERT(pos < resampler->end);
|
||||||
MIX_ALIAS(+=, 1, 0);
|
POKE_ALIAS(0);
|
||||||
subpos += dt;
|
pos++;
|
||||||
pos += subpos >> 16;
|
x += SRC_CHANNELS;
|
||||||
x += (subpos >> 16) * SRC_CHANNELS;
|
}
|
||||||
subpos &= 65535;
|
x = &src[pos*SRC_CHANNELS];
|
||||||
todo--;
|
while ( todo_clocks ) {
|
||||||
|
todo_clocks_set = todo_clocks;
|
||||||
|
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||||
|
todo_clocks -= todo_clocks_set;
|
||||||
|
while ( resampler->last_clock < todo_clocks_set )
|
||||||
|
{
|
||||||
|
POKE_ALIAS(-2);
|
||||||
|
pos++;
|
||||||
|
x += SRC_CHANNELS;
|
||||||
|
}
|
||||||
|
todo = todo_clocks_set >> 16;
|
||||||
|
MIX_ALIAS( todo );
|
||||||
}
|
}
|
||||||
x = xstart = &src[pos*SRC_CHANNELS];
|
|
||||||
LOOP4(todo,
|
|
||||||
MIX_ALIAS(+=, 1, -2);
|
|
||||||
subpos += dt;
|
|
||||||
x += (subpos >> 16) * SRC_CHANNELS;
|
|
||||||
subpos &= 65535;
|
|
||||||
);
|
|
||||||
pos += DIVIDE_BY_SRC_CHANNELS((long)(x - xstart));
|
|
||||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||||
/* Linear interpolation, forwards */
|
/* Linear interpolation, forwards */
|
||||||
SRCTYPE xbuf[3*SRC_CHANNELS];
|
SRCTYPE xbuf[3*SRC_CHANNELS];
|
||||||
|
@ -339,7 +349,7 @@ void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETE
|
||||||
HEAVYASSERT(pos >= resampler->start);
|
HEAVYASSERT(pos >= resampler->start);
|
||||||
if (dumb_resampling_quality <= DUMB_RQ_ALIASING) {
|
if (dumb_resampling_quality <= DUMB_RQ_ALIASING) {
|
||||||
/* Aliasing, backwards */
|
/* Aliasing, backwards */
|
||||||
MIX_ALIAS(=, 0, 1);
|
PEEK_ALIAS;
|
||||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||||
/* Linear interpolation, backwards */
|
/* Linear interpolation, backwards */
|
||||||
MIX_LINEAR(=, 0, 2, 1);
|
MIX_LINEAR(=, 0, 2, 1);
|
||||||
|
@ -351,7 +361,7 @@ void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETE
|
||||||
HEAVYASSERT(pos < resampler->end);
|
HEAVYASSERT(pos < resampler->end);
|
||||||
if (dumb_resampling_quality <= DUMB_RQ_ALIASING) {
|
if (dumb_resampling_quality <= DUMB_RQ_ALIASING) {
|
||||||
/* Aliasing */
|
/* Aliasing */
|
||||||
MIX_ALIAS(=, 0, 1);
|
PEEK_ALIAS;
|
||||||
} else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
|
} else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
|
||||||
/* Linear interpolation, forwards */
|
/* Linear interpolation, forwards */
|
||||||
MIX_LINEAR(=, 0, 1, 2);
|
MIX_LINEAR(=, 0, 1, 2);
|
||||||
|
@ -368,6 +378,7 @@ void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETE
|
||||||
#undef MIX_CUBIC
|
#undef MIX_CUBIC
|
||||||
#undef MIX_LINEAR
|
#undef MIX_LINEAR
|
||||||
#undef MIX_ALIAS
|
#undef MIX_ALIAS
|
||||||
|
#undef PEEK_ALIAS
|
||||||
#undef VOLUMES_ARE_ZERO
|
#undef VOLUMES_ARE_ZERO
|
||||||
#undef SET_VOLUME_VARIABLES
|
#undef SET_VOLUME_VARIABLES
|
||||||
#undef RETURN_VOLUME_VARIABLES
|
#undef RETURN_VOLUME_VARIABLES
|
||||||
|
|
|
@ -117,9 +117,9 @@ int dumb_resampling_quality = DUMB_RQ_CUBIC;
|
||||||
*/
|
*/
|
||||||
#define LOOP4(iterator, CONTENT) \
|
#define LOOP4(iterator, CONTENT) \
|
||||||
{ \
|
{ \
|
||||||
while (iterator) { \
|
while ( (iterator)-- ) \
|
||||||
|
{ \
|
||||||
CONTENT; \
|
CONTENT; \
|
||||||
(iterator)--; \
|
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -189,7 +189,7 @@ static void init_cubic(void)
|
||||||
|
|
||||||
#define SRCTYPE sample_t
|
#define SRCTYPE sample_t
|
||||||
#define SRCBITS 24
|
#define SRCBITS 24
|
||||||
#define ALIAS(x, vol) MULSC(x, vol)
|
#define ALIAS(x) (x >> 8)
|
||||||
#define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos))
|
#define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos))
|
||||||
/*
|
/*
|
||||||
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
||||||
|
@ -225,7 +225,7 @@ static void init_cubic(void)
|
||||||
#define SUFFIX _16
|
#define SUFFIX _16
|
||||||
#define SRCTYPE short
|
#define SRCTYPE short
|
||||||
#define SRCBITS 16
|
#define SRCBITS 16
|
||||||
#define ALIAS(x, vol) (x * vol >> 8)
|
#define ALIAS(x) (x)
|
||||||
#define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos))
|
#define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos))
|
||||||
/*
|
/*
|
||||||
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
||||||
|
@ -247,7 +247,7 @@ static void init_cubic(void)
|
||||||
#define SUFFIX _8
|
#define SUFFIX _8
|
||||||
#define SRCTYPE signed char
|
#define SRCTYPE signed char
|
||||||
#define SRCBITS 8
|
#define SRCBITS 8
|
||||||
#define ALIAS(x, vol) (x * vol)
|
#define ALIAS(x) (x << 8)
|
||||||
#define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos)
|
#define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos)
|
||||||
/*
|
/*
|
||||||
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
|
||||||
|
|
|
@ -69,6 +69,11 @@ void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_chann
|
||||||
}
|
}
|
||||||
for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
|
for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
|
||||||
resampler->overshot = -1;
|
resampler->overshot = -1;
|
||||||
|
resampler->last_clock = 0;
|
||||||
|
resampler->last_amp[0] = 0;
|
||||||
|
resampler->last_amp[1] = 0;
|
||||||
|
blip_clear(resampler->blip_buffer[0]);
|
||||||
|
blip_clear(resampler->blip_buffer[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,6 +82,21 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, int32 pos,
|
||||||
{
|
{
|
||||||
DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
|
DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
|
||||||
if (!resampler) return NULL;
|
if (!resampler) return NULL;
|
||||||
|
resampler->blip_buffer[0] = blip_new( 256 );
|
||||||
|
if (!resampler->blip_buffer[0])
|
||||||
|
{
|
||||||
|
free(resampler);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resampler->blip_buffer[1] = blip_new( 256 );
|
||||||
|
if (!resampler->blip_buffer[1])
|
||||||
|
{
|
||||||
|
free(resampler->blip_buffer[0]);
|
||||||
|
free(resampler);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
blip_set_rates(resampler->blip_buffer[0], 65536, 1);
|
||||||
|
blip_set_rates(resampler->blip_buffer[1], 65536, 1);
|
||||||
dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
|
dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
|
||||||
return resampler;
|
return resampler;
|
||||||
}
|
}
|
||||||
|
@ -123,16 +143,41 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, int32 pos,
|
||||||
}
|
}
|
||||||
#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = (float)volr / 16777216.0f
|
#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = (float)volr / 16777216.0f
|
||||||
#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
|
#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
|
||||||
#define MONO_DEST_MIX_ALIAS(op, upd, offset) { \
|
#define POKE_ALIAS(offset) { \
|
||||||
*dst++ op ALIAS(x[offset], vol); \
|
int delta = ALIAS(x[offset]) - resampler->last_amp[0]; \
|
||||||
if ( upd ) UPDATE_VOLUME( volume, vol ); \
|
resampler->last_amp[0] += delta; \
|
||||||
|
if ( delta ) blip_add_delta( resampler->blip_buffer[0], resampler->last_clock, delta ); \
|
||||||
|
resampler->last_clock += inv_dt; \
|
||||||
}
|
}
|
||||||
#define STEREO_DEST_MIX_ALIAS(op, upd, offset) { \
|
#define MONO_DEST_PEEK_ALIAS *dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), vol )
|
||||||
int xm = x[offset]; \
|
#define MONO_DEST_MIX_ALIAS(count) { \
|
||||||
*dst++ op ALIAS(xm, lvol); \
|
int n = 0; \
|
||||||
*dst++ op ALIAS(xm, rvol); \
|
resampler->last_clock -= count * 65536; \
|
||||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||||
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
|
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||||
|
LOOP4( count, \
|
||||||
|
*dst++ += MULSC( blip_samples[n], vol ); \
|
||||||
|
n++; \
|
||||||
|
UPDATE_VOLUME( volume, vol ); \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
#define STEREO_DEST_PEEK_ALIAS { \
|
||||||
|
int sample = blip_peek_sample( resampler->blip_buffer[0] ); \
|
||||||
|
*dst++ = MULSC( sample, lvol ); \
|
||||||
|
*dst++ = MULSC( sample, rvol ); \
|
||||||
|
}
|
||||||
|
#define STEREO_DEST_MIX_ALIAS(count) { \
|
||||||
|
int sample, n = 0; \
|
||||||
|
resampler->last_clock -= count * 65536; \
|
||||||
|
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||||
|
LOOP4( count, \
|
||||||
|
sample = blip_samples[n++]; \
|
||||||
|
*dst++ += MULSC( sample, lvol ); \
|
||||||
|
*dst++ += MULSC( sample, rvol ); \
|
||||||
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
|
); \
|
||||||
}
|
}
|
||||||
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
||||||
*dst++ op MULSC(LINEAR(x[o0], x[o1]), vol); \
|
*dst++ op MULSC(LINEAR(x[o0], x[o1]), vol); \
|
||||||
|
@ -208,16 +253,51 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, int32 pos,
|
||||||
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
||||||
}
|
}
|
||||||
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
||||||
#define MONO_DEST_MIX_ALIAS(op, upd, offset) { \
|
#define POKE_ALIAS(offset) { \
|
||||||
*dst++ op ALIAS(x[(offset)*2], lvol) + ALIAS(x[(offset)*2+1], rvol); \
|
int deltal = ALIAS(x[(offset)*2+0]) - resampler->last_amp[0]; \
|
||||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
int deltar = ALIAS(x[(offset)*2+1]) - resampler->last_amp[1]; \
|
||||||
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
|
resampler->last_amp[0] += deltal; \
|
||||||
|
resampler->last_amp[1] += deltar; \
|
||||||
|
if ( deltal ) blip_add_delta( resampler->blip_buffer[0], resampler->last_clock, deltal ); \
|
||||||
|
if ( deltar ) blip_add_delta( resampler->blip_buffer[1], resampler->last_clock, deltar ); \
|
||||||
|
resampler->last_clock += inv_dt; \
|
||||||
}
|
}
|
||||||
#define STEREO_DEST_MIX_ALIAS(op, upd, offset) { \
|
#define MONO_DEST_PEEK_ALIAS { \
|
||||||
*dst++ op ALIAS(x[(offset)*2], lvol); \
|
*dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ) + \
|
||||||
*dst++ op ALIAS(x[(offset)*2+1], rvol); \
|
MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
|
||||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
}
|
||||||
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
|
#define MONO_DEST_MIX_ALIAS(count) { \
|
||||||
|
int n = 0; \
|
||||||
|
resampler->last_clock -= count * 65536; \
|
||||||
|
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||||
|
blip_end_frame( resampler->blip_buffer[1], count * 65536 ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[1], blip_samples + 256, count ); \
|
||||||
|
LOOP4( count, \
|
||||||
|
*dst++ += MULSC( blip_samples[n], lvol ) + MULSC( blip_samples[256+n], rvol ); \
|
||||||
|
n++; \
|
||||||
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
#define STEREO_DEST_PEEK_ALIAS { \
|
||||||
|
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ); \
|
||||||
|
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
|
||||||
|
}
|
||||||
|
#define STEREO_DEST_MIX_ALIAS(count) { \
|
||||||
|
int n = 0; \
|
||||||
|
resampler->last_clock -= count * 65536; \
|
||||||
|
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||||
|
blip_end_frame( resampler->blip_buffer[1], count * 65536 ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[1], blip_samples + 256, count ); \
|
||||||
|
LOOP4( count, \
|
||||||
|
*dst++ += MULSC( blip_samples[n], lvol); \
|
||||||
|
*dst++ += MULSC( blip_samples[256+n], rvol); \
|
||||||
|
n++; \
|
||||||
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
|
); \
|
||||||
}
|
}
|
||||||
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
||||||
*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol) + MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
|
*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol) + MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
DUMB_IT_SIGDATA *DUMBEXPORT duh_get_it_sigdata(DUH *duh)
|
DUMB_IT_SIGDATA *DUMBEXPORT duh_get_it_sigdata(DUH *duh)
|
||||||
{
|
{
|
||||||
return duh_get_raw_sigdata(duh, 0, SIGTYPE_IT);
|
return duh_get_raw_sigdata(duh, -1, SIGTYPE_IT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,17 +31,70 @@
|
||||||
//#define INVESTIGATE_OLD_INSTRUMENTS
|
//#define INVESTIGATE_OLD_INSTRUMENTS
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tdumbfile_mem_status
|
||||||
static int it_seek(DUMBFILE *f, int32 offset)
|
|
||||||
{
|
{
|
||||||
int32 pos = dumbfile_pos(f);
|
const unsigned char * ptr;
|
||||||
|
unsigned offset, size;
|
||||||
|
} dumbfile_mem_status;
|
||||||
|
|
||||||
if (pos > offset)
|
static int dumbfile_mem_skip(void * f, int32 n)
|
||||||
|
{
|
||||||
|
dumbfile_mem_status * s = (dumbfile_mem_status *) f;
|
||||||
|
s->offset += n;
|
||||||
|
if (s->offset > s->size)
|
||||||
|
{
|
||||||
|
s->offset = s->size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int dumbfile_mem_getc(void * f)
|
||||||
|
{
|
||||||
|
dumbfile_mem_status * s = (dumbfile_mem_status *) f;
|
||||||
|
if (s->offset < s->size)
|
||||||
|
{
|
||||||
|
return *(s->ptr + s->offset++);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int32 dumbfile_mem_getnc(char * ptr, int32 n, void * f)
|
||||||
|
{
|
||||||
|
dumbfile_mem_status * s = (dumbfile_mem_status *) f;
|
||||||
|
int32 max = s->size - s->offset;
|
||||||
|
if (max > n) max = n;
|
||||||
|
if (max)
|
||||||
|
{
|
||||||
|
memcpy(ptr, s->ptr + s->offset, max);
|
||||||
|
s->offset += max;
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static DUMBFILE_SYSTEM mem_dfs = {
|
||||||
|
NULL, // open
|
||||||
|
&dumbfile_mem_skip,
|
||||||
|
&dumbfile_mem_getc,
|
||||||
|
&dumbfile_mem_getnc,
|
||||||
|
NULL // close
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int it_seek(dumbfile_mem_status * s, int32 offset)
|
||||||
|
{
|
||||||
|
if ( (unsigned)offset > s->size )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (pos < offset)
|
s->offset = offset;
|
||||||
if (dumbfile_skip(f, offset - pos))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -306,6 +359,8 @@ static int it_read_envelope(IT_ENVELOPE *envelope, DUMBFILE *f)
|
||||||
envelope->loop_end = dumbfile_getc(f);
|
envelope->loop_end = dumbfile_getc(f);
|
||||||
envelope->sus_loop_start = dumbfile_getc(f);
|
envelope->sus_loop_start = dumbfile_getc(f);
|
||||||
envelope->sus_loop_end = dumbfile_getc(f);
|
envelope->sus_loop_end = dumbfile_getc(f);
|
||||||
|
if (envelope->n_nodes > 25)
|
||||||
|
envelope->n_nodes = 25;
|
||||||
for (n = 0; n < envelope->n_nodes; n++) {
|
for (n = 0; n < envelope->n_nodes; n++) {
|
||||||
envelope->node_y[n] = dumbfile_getc(f);
|
envelope->node_y[n] = dumbfile_getc(f);
|
||||||
envelope->node_t[n] = dumbfile_igetw(f);
|
envelope->node_t[n] = dumbfile_igetw(f);
|
||||||
|
@ -682,15 +737,36 @@ static int32 it_read_sample_data(int cmwt, IT_SAMPLE *sample, unsigned char conv
|
||||||
else
|
else
|
||||||
decompress8(f, sample->data, datasize, ((cmwt >= 0x215) && (convert & 4)));
|
decompress8(f, sample->data, datasize, ((cmwt >= 0x215) && (convert & 4)));
|
||||||
} else if (sample->flags & IT_SAMPLE_16BIT) {
|
} else if (sample->flags & IT_SAMPLE_16BIT) {
|
||||||
|
if (sample->flags & IT_SAMPLE_STEREO) {
|
||||||
|
if (convert & 2) {
|
||||||
|
for (n = 0; n < datasize; n += 2)
|
||||||
|
((short *)sample->data)[n] = dumbfile_mgetw(f);
|
||||||
|
for (n = 1; n < datasize; n += 2)
|
||||||
|
((short *)sample->data)[n] = dumbfile_mgetw(f);
|
||||||
|
} else {
|
||||||
|
for (n = 0; n < datasize; n += 2)
|
||||||
|
((short *)sample->data)[n] = dumbfile_igetw(f);
|
||||||
|
for (n = 1; n < datasize; n += 2)
|
||||||
|
((short *)sample->data)[n] = dumbfile_igetw(f);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (convert & 2)
|
if (convert & 2)
|
||||||
for (n = 0; n < datasize; n++)
|
for (n = 0; n < datasize; n++)
|
||||||
((short *)sample->data)[n] = dumbfile_mgetw(f);
|
((short *)sample->data)[n] = dumbfile_mgetw(f);
|
||||||
else
|
else
|
||||||
for (n = 0; n < datasize; n++)
|
for (n = 0; n < datasize; n++)
|
||||||
((short *)sample->data)[n] = dumbfile_igetw(f);
|
((short *)sample->data)[n] = dumbfile_igetw(f);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (sample->flags & IT_SAMPLE_STEREO) {
|
||||||
|
for (n = 0; n < datasize; n += 2)
|
||||||
|
((signed char *)sample->data)[n] = dumbfile_getc(f);
|
||||||
|
for (n = 1; n < datasize; n += 2)
|
||||||
|
((signed char *)sample->data)[n] = dumbfile_getc(f);
|
||||||
} else
|
} else
|
||||||
for (n = 0; n < datasize; n++)
|
for (n = 0; n < datasize; n++)
|
||||||
((signed char *)sample->data)[n] = dumbfile_getc(f);
|
((signed char *)sample->data)[n] = dumbfile_getc(f);
|
||||||
|
}
|
||||||
|
|
||||||
if (dumbfile_error(f))
|
if (dumbfile_error(f))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -934,13 +1010,58 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
|
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
|
|
||||||
if (dumbfile_mgetl(f) != IT_SIGNATURE)
|
unsigned char *file_buffer = NULL;
|
||||||
|
unsigned int file_size = 0;
|
||||||
|
int block_size;
|
||||||
|
|
||||||
|
dumbfile_mem_status memdata;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
void * temp = realloc( file_buffer, file_size + 32768 );
|
||||||
|
if ( !temp )
|
||||||
|
{
|
||||||
|
if ( file_buffer ) free( file_buffer );
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
file_buffer = temp;
|
||||||
|
block_size = dumbfile_getnc( file_buffer + file_size, 32768, f );
|
||||||
|
if ( block_size < 0 )
|
||||||
|
{
|
||||||
|
free( file_buffer );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
file_size += block_size;
|
||||||
|
}
|
||||||
|
while ( block_size == 32768 );
|
||||||
|
|
||||||
|
memdata.ptr = file_buffer;
|
||||||
|
memdata.offset = 0;
|
||||||
|
memdata.size = file_size;
|
||||||
|
|
||||||
|
f = dumbfile_open_ex(&memdata, &mem_dfs);
|
||||||
|
|
||||||
|
if ( !f )
|
||||||
|
{
|
||||||
|
free( file_buffer );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dumbfile_mgetl(f) != IT_SIGNATURE)
|
||||||
|
{
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
sigdata = malloc(sizeof(*sigdata));
|
sigdata = malloc(sizeof(*sigdata));
|
||||||
|
|
||||||
if (!sigdata)
|
if (!sigdata)
|
||||||
|
{
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
sigdata->song_message = NULL;
|
sigdata->song_message = NULL;
|
||||||
sigdata->order = NULL;
|
sigdata->order = NULL;
|
||||||
|
@ -989,12 +1110,16 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
// XXX sample count
|
// XXX sample count
|
||||||
if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_instruments > 256 || sigdata->n_samples > 4000 || sigdata->n_patterns > 256) {
|
if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_instruments > 256 || sigdata->n_samples > 4000 || sigdata->n_patterns > 256) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sigdata->order = malloc(sigdata->n_orders);
|
sigdata->order = malloc(sigdata->n_orders);
|
||||||
if (!sigdata->order) {
|
if (!sigdata->order) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,6 +1127,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
|
sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
|
||||||
if (!sigdata->instrument) {
|
if (!sigdata->instrument) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1010,6 +1137,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
|
sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
|
||||||
if (!sigdata->sample) {
|
if (!sigdata->sample) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (n = 0; n < sigdata->n_samples; n++)
|
for (n = 0; n < sigdata->n_samples; n++)
|
||||||
|
@ -1020,6 +1149,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
|
sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
|
||||||
if (!sigdata->pattern) {
|
if (!sigdata->pattern) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (n = 0; n < sigdata->n_patterns; n++)
|
for (n = 0; n < sigdata->n_patterns; n++)
|
||||||
|
@ -1032,6 +1163,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
component = malloc(769 * sizeof(*component));
|
component = malloc(769 * sizeof(*component));
|
||||||
if (!component) {
|
if (!component) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,6 +1209,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
if (dumbfile_error(f)) {
|
if (dumbfile_error(f)) {
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1096,6 +1231,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
if (!sigdata->midi) {
|
if (!sigdata->midi) {
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
// Should we be happy with this outcome in some situations?
|
// Should we be happy with this outcome in some situations?
|
||||||
}
|
}
|
||||||
|
@ -1104,6 +1241,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
if (dumbfile_error(f) || dumbfile_skip(f, 8*i)) {
|
if (dumbfile_error(f) || dumbfile_skip(f, 8*i)) {
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Read embedded MIDI configuration */
|
/* Read embedded MIDI configuration */
|
||||||
|
@ -1111,6 +1250,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
if (dumbfile_skip(f, 32*9)) {
|
if (dumbfile_skip(f, 32*9)) {
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
|
@ -1119,6 +1260,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
if (dumbfile_getnc(mididata, 32, f) < 32) {
|
if (dumbfile_getnc(mididata, 32, f) < 32) {
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
sigdata->midi->SFmacroz[i] = 0;
|
sigdata->midi->SFmacroz[i] = 0;
|
||||||
|
@ -1180,6 +1323,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1208,10 +1353,12 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it_seek(f, component[n].offset)) {
|
if (it_seek(&memdata, component[n].offset)) {
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,6 +1374,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
sigdata->song_message[message_length] = 0;
|
sigdata->song_message[message_length] = 0;
|
||||||
|
@ -1243,6 +1392,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1252,6 +1403,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1261,6 +1414,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,10 +1442,12 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
m = component[n].sampfirst;
|
m = component[n].sampfirst;
|
||||||
|
|
||||||
while (m >= 0) {
|
while (m >= 0) {
|
||||||
if (it_seek(f, component[m].offset)) {
|
if (it_seek(&memdata, component[m].offset)) {
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1298,6 +1455,8 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(component);
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1305,9 +1464,70 @@ static sigdata_t *it_load_sigdata(DUMBFILE *f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( n = 0; n < 10; n++ )
|
||||||
|
{
|
||||||
|
if ( dumbfile_getc( f ) == 'X' )
|
||||||
|
{
|
||||||
|
if ( dumbfile_getc( f ) == 'T' )
|
||||||
|
{
|
||||||
|
if ( dumbfile_getc( f ) == 'P' )
|
||||||
|
{
|
||||||
|
if ( dumbfile_getc( f ) == 'M' )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !dumbfile_error( f ) && n < 10 )
|
||||||
|
{
|
||||||
|
unsigned int mptx_id = dumbfile_igetl( f );
|
||||||
|
while ( !dumbfile_error( f ) && mptx_id != DUMB_ID('M','P','T','S') )
|
||||||
|
{
|
||||||
|
unsigned int size = dumbfile_igetw( f );
|
||||||
|
switch (mptx_id)
|
||||||
|
{
|
||||||
|
/* TODO: Add instrument extension readers */
|
||||||
|
|
||||||
|
default:
|
||||||
|
dumbfile_skip(f, size * sigdata->n_instruments);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mptx_id = dumbfile_igetl( f );
|
||||||
|
}
|
||||||
|
|
||||||
|
mptx_id = dumbfile_igetl( f );
|
||||||
|
while ( memdata.offset < file_size )
|
||||||
|
{
|
||||||
|
unsigned int size = dumbfile_igetw( f );
|
||||||
|
switch (mptx_id)
|
||||||
|
{
|
||||||
|
/* TODO: Add more song extension readers */
|
||||||
|
|
||||||
|
case DUMB_ID('D','T','.','.'):
|
||||||
|
if ( size == 2 )
|
||||||
|
sigdata->tempo = dumbfile_igetw( f );
|
||||||
|
else if ( size == 4 )
|
||||||
|
sigdata->tempo = dumbfile_igetl( f );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
dumbfile_skip(f, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mptx_id = dumbfile_igetl( f );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(component);
|
free(component);
|
||||||
|
|
||||||
|
dumbfile_close(f);
|
||||||
|
free(file_buffer);
|
||||||
|
|
||||||
_dumb_it_fix_invalid_orders(sigdata);
|
_dumb_it_fix_invalid_orders(sigdata);
|
||||||
|
|
||||||
return sigdata;
|
return sigdata;
|
||||||
|
@ -1327,9 +1547,11 @@ DUH *DUMBEXPORT dumb_read_it_quick(DUMBFILE *f)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
const char *tag[1][2];
|
const char *tag[2][2];
|
||||||
tag[0][0] = "TITLE";
|
tag[0][0] = "TITLE";
|
||||||
tag[0][1] = ((DUMB_IT_SIGDATA *)sigdata)->name;
|
tag[0][1] = ((DUMB_IT_SIGDATA *)sigdata)->name;
|
||||||
return make_duh(-1, 1, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
tag[1][0] = "FORMAT";
|
||||||
|
tag[1][1] = "IT";
|
||||||
|
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,7 +26,7 @@
|
||||||
* pointer to the DUH struct. When you have finished with it, you must
|
* pointer to the DUH struct. When you have finished with it, you must
|
||||||
* pass the pointer to unload_duh() so that the memory can be freed.
|
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||||
*/
|
*/
|
||||||
DUH *DUMBEXPORT dumb_load_mod_quick(const char *filename, int restrict)
|
DUH *DUMBEXPORT dumb_load_mod_quick(const char *filename, int rstrict)
|
||||||
{
|
{
|
||||||
DUH *duh;
|
DUH *duh;
|
||||||
DUMBFILE *f = dumbfile_open(filename);
|
DUMBFILE *f = dumbfile_open(filename);
|
||||||
|
@ -34,7 +34,7 @@ DUH *DUMBEXPORT dumb_load_mod_quick(const char *filename, int restrict)
|
||||||
if (!f)
|
if (!f)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
duh = dumb_read_mod_quick(f, restrict);
|
duh = dumb_read_mod_quick(f, rstrict);
|
||||||
|
|
||||||
dumbfile_close(f);
|
dumbfile_close(f);
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DUH *DUMBEXPORT dumb_load_mod(const char *filename, int restrict)
|
DUH *DUMBEXPORT dumb_load_mod(const char *filename, int rstrict)
|
||||||
{
|
{
|
||||||
DUH *duh = dumb_load_mod_quick(filename, restrict);
|
DUH *duh = dumb_load_mod_quick(filename, rstrict);
|
||||||
dumb_it_do_initial_runthrough(duh);
|
dumb_it_do_initial_runthrough(duh);
|
||||||
return duh;
|
return duh;
|
||||||
}
|
}
|
||||||
|
|
42
dumb/src/it/loadokt.c
Normal file
42
dumb/src/it/loadokt.c
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* _______ ____ __ ___ ___
|
||||||
|
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||||
|
* | | \ \ | | || | \/ | . .
|
||||||
|
* | | | | | | || ||\ /| |
|
||||||
|
* | | | | | | || || \/ | | ' ' '
|
||||||
|
* | | | | | | || || | | . .
|
||||||
|
* | |_/ / \ \__// || | |
|
||||||
|
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||||
|
* / \
|
||||||
|
* / . \
|
||||||
|
* loadokt.c - Code to read an Oktalyzer module / / \ \
|
||||||
|
* file, opening and closing it for | < / \_
|
||||||
|
* you. | \/ /\ /
|
||||||
|
* \_ / > /
|
||||||
|
* By Chris Moeller. | \ / /
|
||||||
|
* | ' /
|
||||||
|
* \__/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dumb.h"
|
||||||
|
#include "internal/it.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* dumb_load_okt_quick(): loads an OKT file into a DUH struct, returning a
|
||||||
|
* pointer to the DUH struct. When you have finished with it, you must
|
||||||
|
* pass the pointer to unload_duh() so that the memory can be freed.
|
||||||
|
*/
|
||||||
|
DUH *DUMBEXPORT dumb_load_okt_quick(const char *filename)
|
||||||
|
{
|
||||||
|
DUH *duh;
|
||||||
|
DUMBFILE *f = dumbfile_open(filename);
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
duh = dumb_read_okt_quick(f);
|
||||||
|
|
||||||
|
dumbfile_close(f);
|
||||||
|
|
||||||
|
return duh;
|
||||||
|
}
|
29
dumb/src/it/loadokt2.c
Normal file
29
dumb/src/it/loadokt2.c
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/* _______ ____ __ ___ ___
|
||||||
|
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||||
|
* | | \ \ | | || | \/ | . .
|
||||||
|
* | | | | | | || ||\ /| |
|
||||||
|
* | | | | | | || || \/ | | ' ' '
|
||||||
|
* | | | | | | || || | | . .
|
||||||
|
* | |_/ / \ \__// || | |
|
||||||
|
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||||
|
* / \
|
||||||
|
* / . \
|
||||||
|
* loadokt2.c - Function to read an Oktalyzer / / \ \
|
||||||
|
* module file, opening and closing | < / \_
|
||||||
|
* it for you, and do an initial run- | \/ /\ /
|
||||||
|
* through. \_ / > /
|
||||||
|
* | \ / /
|
||||||
|
* By Chris Moeller. | ' /
|
||||||
|
* \__/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dumb.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DUH *DUMBEXPORT dumb_load_okt(const char *filename)
|
||||||
|
{
|
||||||
|
DUH *duh = dumb_load_okt_quick(filename);
|
||||||
|
dumb_it_do_initial_runthrough(duh);
|
||||||
|
return duh;
|
||||||
|
}
|
|
@ -331,6 +331,7 @@ static DUMB_IT_SIGDATA *it_riff_amff_load_sigdata( struct riff * stream )
|
||||||
|
|
||||||
sigdata->n_instruments = 0;
|
sigdata->n_instruments = 0;
|
||||||
sigdata->n_orders = 0;
|
sigdata->n_orders = 0;
|
||||||
|
sigdata->restart_position = 0;
|
||||||
|
|
||||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||||
|
|
||||||
|
@ -553,6 +554,7 @@ static DUMB_IT_SIGDATA *it_riff_am_load_sigdata( struct riff * stream )
|
||||||
|
|
||||||
sigdata->n_instruments = 0;
|
sigdata->n_instruments = 0;
|
||||||
sigdata->n_orders = 0;
|
sigdata->n_orders = 0;
|
||||||
|
sigdata->restart_position = 0;
|
||||||
|
|
||||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char
|
||||||
entry->mask |= IT_ENTRY_INSTRUMENT;
|
entry->mask |= IT_ENTRY_INSTRUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dumb_it_xm_convert_effect( buffer[ pos + 2 ] & 0x0F, buffer[ pos + 3 ], entry, 1 );
|
_dumb_it_xm_convert_effect( buffer[ pos + 2 ], buffer[ pos + 3 ], entry, 1 );
|
||||||
|
|
||||||
if ( entry->mask ) ++entry;
|
if ( entry->mask ) ++entry;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char
|
||||||
|
|
||||||
static int it_asy_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f )
|
static int it_asy_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f )
|
||||||
{
|
{
|
||||||
int finetune;
|
int finetune, key_offset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
21 22 Chars Sample 1 name. If the name is not a full
|
21 22 Chars Sample 1 name. If the name is not a full
|
||||||
|
@ -111,7 +111,7 @@ assumed not to be an instrument name, and is probably a message.
|
||||||
sample->default_volume = dumbfile_getc( f ); // Should we be setting global_volume to this instead?
|
sample->default_volume = dumbfile_getc( f ); // Should we be setting global_volume to this instead?
|
||||||
sample->global_volume = 64;
|
sample->global_volume = 64;
|
||||||
if ( sample->default_volume > 64 ) sample->default_volume = 64;
|
if ( sample->default_volume > 64 ) sample->default_volume = 64;
|
||||||
dumbfile_skip( f, 1 ); /* XXX unknown */
|
key_offset = ( signed char ) dumbfile_getc( f ); /* base key offset */
|
||||||
sample->length = dumbfile_igetl( f );
|
sample->length = dumbfile_igetl( f );
|
||||||
sample->loop_start = dumbfile_igetl( f );
|
sample->loop_start = dumbfile_igetl( f );
|
||||||
sample->loop_end = sample->loop_start + dumbfile_igetl( f );
|
sample->loop_end = sample->loop_start + dumbfile_igetl( f );
|
||||||
|
@ -124,7 +124,7 @@ assumed not to be an instrument name, and is probably a message.
|
||||||
sample->flags = IT_SAMPLE_EXISTS;
|
sample->flags = IT_SAMPLE_EXISTS;
|
||||||
|
|
||||||
sample->default_pan = 0;
|
sample->default_pan = 0;
|
||||||
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 );//( int32 )( 16726.0 * pow( DUMB_PITCH_BASE, finetune * 32 ) );
|
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 * pow( DUMB_SEMITONE_BASE, key_offset ) );//( long )( 16726.0 * pow( DUMB_PITCH_BASE, finetune * 32 ) );
|
||||||
sample->finetune = finetune * 32;
|
sample->finetune = finetune * 32;
|
||||||
// the above line might be wrong
|
// the above line might be wrong
|
||||||
|
|
||||||
|
|
|
@ -265,6 +265,7 @@ static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( struct riff * stream )
|
||||||
|
|
||||||
sigdata->n_instruments = 0;
|
sigdata->n_instruments = 0;
|
||||||
sigdata->n_orders = 0;
|
sigdata->n_orders = 0;
|
||||||
|
sigdata->restart_position = 0;
|
||||||
|
|
||||||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||||
|
|
||||||
|
|
|
@ -393,10 +393,12 @@ static DUMBFILE *dumbfile_buffer_mod(DUMBFILE *f, uint32 *fft)
|
||||||
return dumbfile_open_ex(bm, &buffer_mod_dfs);
|
return dumbfile_open_ex(bm, &buffer_mod_dfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DUMBFILE *dumbfile_buffer_mod_2(DUMBFILE *f, int32 *remain)
|
static DUMBFILE *dumbfile_buffer_mod_2(DUMBFILE *f, int n_samples, IT_SAMPLE *sample, int32 *total_sample_size, int32 *remain)
|
||||||
{
|
{
|
||||||
int32 read;
|
int32 read;
|
||||||
|
int sample_number;
|
||||||
BUFFERED_MOD *bm = malloc(sizeof(*bm));
|
BUFFERED_MOD *bm = malloc(sizeof(*bm));
|
||||||
|
unsigned char *ptr;
|
||||||
if (!bm) return NULL;
|
if (!bm) return NULL;
|
||||||
|
|
||||||
bm->buffered = malloc(32768);
|
bm->buffered = malloc(32768);
|
||||||
|
@ -430,6 +432,21 @@ static DUMBFILE *dumbfile_buffer_mod_2(DUMBFILE *f, int32 *remain)
|
||||||
|
|
||||||
if (*remain) {
|
if (*remain) {
|
||||||
bm->ptr = 0;
|
bm->ptr = 0;
|
||||||
|
ptr = bm->buffered + *remain;
|
||||||
|
sample_number = n_samples - 1;
|
||||||
|
*total_sample_size = 0;
|
||||||
|
while (ptr > bm->buffered && sample_number >= 0) {
|
||||||
|
if (sample[sample_number].flags & IT_SAMPLE_EXISTS) {
|
||||||
|
ptr -= (sample[sample_number].length + 1) / 2 + 5 + 16;
|
||||||
|
if (ptr >= bm->buffered && !memcmp(ptr, "ADPCM", 5)) { /* BAH */
|
||||||
|
*total_sample_size += (sample[sample_number].length + 1) / 2 + 5 + 16;
|
||||||
|
} else {
|
||||||
|
*total_sample_size += sample[sample_number].length;
|
||||||
|
ptr -= sample[sample_number].length - ((sample[sample_number].length + 1) / 2 + 5 + 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sample_number--;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
free(bm->buffered);
|
free(bm->buffered);
|
||||||
bm->buffered = NULL;
|
bm->buffered = NULL;
|
||||||
|
@ -441,13 +458,13 @@ static DUMBFILE *dumbfile_buffer_mod_2(DUMBFILE *f, int32 *remain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict)
|
static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int rstrict)
|
||||||
{
|
{
|
||||||
DUMB_IT_SIGDATA *sigdata;
|
DUMB_IT_SIGDATA *sigdata;
|
||||||
int n_channels;
|
int n_channels;
|
||||||
int i;
|
int i;
|
||||||
uint32 fft = 0;
|
uint32 fft = 0;
|
||||||
DUMBFILE *rem;
|
DUMBFILE *rem = NULL;
|
||||||
|
|
||||||
f = dumbfile_buffer_mod(f, &fft);
|
f = dumbfile_buffer_mod(f, &fft);
|
||||||
if (!f)
|
if (!f)
|
||||||
|
@ -550,7 +567,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict)
|
||||||
}
|
}
|
||||||
|
|
||||||
// moo
|
// moo
|
||||||
if ( restrict && sigdata->n_samples == 15 )
|
if ( ( rstrict & 1 ) && sigdata->n_samples == 15 )
|
||||||
{
|
{
|
||||||
free(sigdata);
|
free(sigdata);
|
||||||
dumbfile_close(f);
|
dumbfile_close(f);
|
||||||
|
@ -629,12 +646,48 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict)
|
||||||
if (sigdata->n_samples == 31)
|
if (sigdata->n_samples == 31)
|
||||||
dumbfile_skip(f, 4);
|
dumbfile_skip(f, 4);
|
||||||
|
|
||||||
/* Work out how many patterns there are. */
|
|
||||||
sigdata->n_patterns = -1;
|
sigdata->n_patterns = -1;
|
||||||
|
|
||||||
|
if ( ( rstrict & 2 ) )
|
||||||
|
{
|
||||||
|
long total_sample_size;
|
||||||
|
long remain;
|
||||||
|
rem = f;
|
||||||
|
f = dumbfile_buffer_mod_2(rem, sigdata->n_samples, sigdata->sample, &total_sample_size, &remain);
|
||||||
|
if (!f) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(rem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (remain > total_sample_size) {
|
||||||
|
sigdata->n_patterns = ( remain - total_sample_size + 4 ) / ( 256 * sigdata->n_pchannels );
|
||||||
|
if (fft == DUMB_ID('M',0,0,0) || fft == DUMB_ID('8',0,0,0)) {
|
||||||
|
remain -= sigdata->n_patterns * 256 * sigdata->n_pchannels;
|
||||||
|
if (dumbfile_skip(f, remain - total_sample_size)) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
dumbfile_close(rem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
for (i = 0; i < 128; i++)
|
for (i = 0; i < 128; i++)
|
||||||
if (sigdata->n_patterns < sigdata->order[i])
|
{
|
||||||
|
if (sigdata->order[i] > sigdata->n_patterns)
|
||||||
sigdata->n_patterns = sigdata->order[i];
|
sigdata->n_patterns = sigdata->order[i];
|
||||||
|
}
|
||||||
sigdata->n_patterns++;
|
sigdata->n_patterns++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( sigdata->n_patterns <= 0 ) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
dumbfile_close(f);
|
||||||
|
if (rem) dumbfile_close(rem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* May as well try to save a tiny bit of memory. */
|
/* May as well try to save a tiny bit of memory. */
|
||||||
if (sigdata->n_orders < 128) {
|
if (sigdata->n_orders < 128) {
|
||||||
|
@ -646,6 +699,7 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict)
|
||||||
if (!sigdata->pattern) {
|
if (!sigdata->pattern) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
dumbfile_close(f);
|
dumbfile_close(f);
|
||||||
|
if (rem) dumbfile_close(rem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (i = 0; i < sigdata->n_patterns; i++)
|
for (i = 0; i < sigdata->n_patterns; i++)
|
||||||
|
@ -653,10 +707,11 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict)
|
||||||
|
|
||||||
/* Read in the patterns */
|
/* Read in the patterns */
|
||||||
{
|
{
|
||||||
unsigned char *buffer = malloc(256 * n_channels); /* 64 rows * 4 bytes */
|
unsigned char *buffer = malloc(256 * sigdata->n_pchannels); /* 64 rows * 4 bytes */
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
dumbfile_close(f);
|
dumbfile_close(f);
|
||||||
|
if (rem) dumbfile_close(rem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (i = 0; i < sigdata->n_patterns; i++) {
|
for (i = 0; i < sigdata->n_patterns; i++) {
|
||||||
|
@ -664,40 +719,13 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict)
|
||||||
free(buffer);
|
free(buffer);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
dumbfile_close(f);
|
dumbfile_close(f);
|
||||||
|
if (rem) dumbfile_close(rem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
rem = NULL;
|
|
||||||
|
|
||||||
/* uggly */
|
|
||||||
if (fft == DUMB_ID('M',0,0,0) || fft == DUMB_ID('8',0,0,0)) {
|
|
||||||
int32 skip;
|
|
||||||
int32 remain;
|
|
||||||
rem = f;
|
|
||||||
f = dumbfile_buffer_mod_2(rem, &remain);
|
|
||||||
if (!f) {
|
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
|
||||||
dumbfile_close(rem);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
for (skip = 0, i = 0; i < sigdata->n_samples; i++) {
|
|
||||||
if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) {
|
|
||||||
skip += sigdata->sample[i].length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (remain - skip) {
|
|
||||||
if (dumbfile_skip(f, remain - skip)) {
|
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
|
||||||
dumbfile_close(f);
|
|
||||||
dumbfile_close(rem);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And finally, the sample data */
|
/* And finally, the sample data */
|
||||||
for (i = 0; i < sigdata->n_samples; i++) {
|
for (i = 0; i < sigdata->n_samples; i++) {
|
||||||
if (it_mod_read_sample_data(&sigdata->sample[i], f, fft)) {
|
if (it_mod_read_sample_data(&sigdata->sample[i], f, fft)) {
|
||||||
|
@ -727,8 +755,8 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
dumbfile_close(f); /* Destroy the BUFFERED_MOD DUMBFILE we were using. */
|
dumbfile_close(f); /* Destroy the BUFFERED_MOD DUMBFILE we were using. */
|
||||||
|
if (rem) dumbfile_close(rem); /* And the BUFFERED_MOD DUMBFILE used to pre-read the signature. */
|
||||||
/* The DUMBFILE originally passed to our function is intact. */
|
/* The DUMBFILE originally passed to our function is intact. */
|
||||||
if (rem) dumbfile_close(rem);
|
|
||||||
|
|
||||||
/* Now let's initialise the remaining variables, and we're done! */
|
/* Now let's initialise the remaining variables, and we're done! */
|
||||||
sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
|
sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
|
||||||
|
@ -758,13 +786,13 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DUH *DUMBEXPORT dumb_read_mod_quick(DUMBFILE *f, int restrict)
|
DUH *DUMBEXPORT dumb_read_mod_quick(DUMBFILE *f, int rstrict)
|
||||||
{
|
{
|
||||||
sigdata_t *sigdata;
|
sigdata_t *sigdata;
|
||||||
|
|
||||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||||
|
|
||||||
sigdata = it_mod_load_sigdata(f, restrict);
|
sigdata = it_mod_load_sigdata(f, rstrict);
|
||||||
|
|
||||||
if (!sigdata)
|
if (!sigdata)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DUH *DUMBEXPORT dumb_read_mod(DUMBFILE *f, int restrict)
|
DUH *DUMBEXPORT dumb_read_mod(DUMBFILE *f, int rstrict)
|
||||||
{
|
{
|
||||||
DUH *duh = dumb_read_mod_quick(f, restrict);
|
DUH *duh = dumb_read_mod_quick(f, rstrict);
|
||||||
dumb_it_do_initial_runthrough(duh);
|
dumb_it_do_initial_runthrough(duh);
|
||||||
return duh;
|
return duh;
|
||||||
}
|
}
|
||||||
|
|
558
dumb/src/it/readokt.c
Normal file
558
dumb/src/it/readokt.c
Normal file
|
@ -0,0 +1,558 @@
|
||||||
|
/* _______ ____ __ ___ ___
|
||||||
|
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||||
|
* | | \ \ | | || | \/ | . .
|
||||||
|
* | | | | | | || ||\ /| |
|
||||||
|
* | | | | | | || || \/ | | ' ' '
|
||||||
|
* | | | | | | || || | | . .
|
||||||
|
* | |_/ / \ \__// || | |
|
||||||
|
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||||
|
* / \
|
||||||
|
* / . \
|
||||||
|
* readokt.c - Code to read an Oktalyzer module / / \ \
|
||||||
|
* from an open file. | < / \_
|
||||||
|
* | \/ /\ /
|
||||||
|
* By Chris Moeller. \_ / > /
|
||||||
|
* | \ / /
|
||||||
|
* | ' /
|
||||||
|
* \__/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "dumb.h"
|
||||||
|
#include "internal/it.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int it_okt_read_pattern(IT_PATTERN *pattern, const unsigned char *data, int length, int n_channels)
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
int channel;
|
||||||
|
int row;
|
||||||
|
int n_rows;
|
||||||
|
IT_ENTRY *entry;
|
||||||
|
|
||||||
|
if (length < 2) return -1;
|
||||||
|
|
||||||
|
n_rows = (data[0] << 8) | data[1];
|
||||||
|
if (!n_rows) n_rows = 64;
|
||||||
|
|
||||||
|
if (length < 2 + (n_rows * n_channels * 4)) return -1;
|
||||||
|
|
||||||
|
pattern->n_rows = n_rows;
|
||||||
|
|
||||||
|
/* compute number of entries */
|
||||||
|
pattern->n_entries = n_rows; /* Account for the row end markers */
|
||||||
|
pos = 2;
|
||||||
|
for (row = 0; row < pattern->n_rows; row++) {
|
||||||
|
for (channel = 0; channel < n_channels; channel++) {
|
||||||
|
if (data[pos+0] | data[pos+2])
|
||||||
|
pattern->n_entries++;
|
||||||
|
pos += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern->entry = (IT_ENTRY *) malloc(pattern->n_entries * sizeof(*pattern->entry));
|
||||||
|
if (!pattern->entry)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
entry = pattern->entry;
|
||||||
|
pos = 2;
|
||||||
|
for (row = 0; row < n_rows; row++) {
|
||||||
|
for (channel = 0; channel < n_channels; channel++) {
|
||||||
|
if (data[pos+0] | data[pos+2]) {
|
||||||
|
entry->channel = channel;
|
||||||
|
entry->mask = 0;
|
||||||
|
|
||||||
|
if (data[pos+0] > 0 && data[pos+0] <= 36) {
|
||||||
|
entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT;
|
||||||
|
|
||||||
|
entry->note = data[pos+0] + 35;
|
||||||
|
entry->instrument = data[pos+1] + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->effect = 0;
|
||||||
|
entry->effectvalue = data[pos+3];
|
||||||
|
|
||||||
|
switch (data[pos+2]) {
|
||||||
|
case 2: if (data[pos+3]) entry->effect = IT_PORTAMENTO_DOWN; break; // XXX code calls this rs_portu, but it's adding to the period, which decreases the pitch
|
||||||
|
case 13: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN; break;
|
||||||
|
case 21: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN_ROW; break;
|
||||||
|
|
||||||
|
case 1: if (data[pos+3]) entry->effect = IT_PORTAMENTO_UP; break; // XXX same deal here, increasing the pitch
|
||||||
|
case 17: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP; break;
|
||||||
|
case 30: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP_ROW; break;
|
||||||
|
|
||||||
|
case 10: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_3; break;
|
||||||
|
case 11: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_4; break;
|
||||||
|
case 12: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_5; break;
|
||||||
|
|
||||||
|
case 15: entry->effect = IT_S; entry->effectvalue = EFFECT_VALUE(IT_S_SET_FILTER, data[pos+3] & 0x0F); break;
|
||||||
|
|
||||||
|
case 25: entry->effect = IT_JUMP_TO_ORDER; break;
|
||||||
|
|
||||||
|
case 27: entry->note = IT_NOTE_OFF; entry->mask |= IT_ENTRY_NOTE; break;
|
||||||
|
|
||||||
|
case 28: entry->effect = IT_SET_SPEED; break;
|
||||||
|
|
||||||
|
case 31:
|
||||||
|
if ( data[pos+3] <= 0x40 ) entry->effect = IT_SET_CHANNEL_VOLUME;
|
||||||
|
else if ( data[pos+3] <= 0x50 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x40; }
|
||||||
|
else if ( data[pos+3] <= 0x60 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP; entry->effectvalue = data[pos+3] - 0x50; }
|
||||||
|
else if ( data[pos+3] <= 0x70 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x50; }
|
||||||
|
else if ( data[pos+3] <= 0x80 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP; entry->effectvalue = data[pos+3] - 0x60; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( entry->effect ) entry->mask |= IT_ENTRY_EFFECT;
|
||||||
|
|
||||||
|
entry++;
|
||||||
|
}
|
||||||
|
pos += 4;
|
||||||
|
}
|
||||||
|
IT_SET_END_ROW(entry);
|
||||||
|
entry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void it_okt_read_sample_header(IT_SAMPLE *sample, const unsigned char * data)
|
||||||
|
{
|
||||||
|
int loop_start, loop_length;
|
||||||
|
|
||||||
|
memcpy(sample->name, data, 20);
|
||||||
|
sample->name[20] = 0;
|
||||||
|
|
||||||
|
sample->filename[0] = 0;
|
||||||
|
|
||||||
|
sample->length = (data[20] << 24) | (data[21] << 16) | (data[22] << 8) | data[23];
|
||||||
|
sample->global_volume = 64;
|
||||||
|
sample->default_volume = data[29];
|
||||||
|
loop_start = ((data[24] << 8) | data[25]) << 1;
|
||||||
|
loop_length = ((data[26] << 8) | data[27]) << 1;
|
||||||
|
sample->sus_loop_start = loop_start;
|
||||||
|
sample->sus_loop_end = loop_start + loop_length;
|
||||||
|
|
||||||
|
if (sample->length <= 0) {
|
||||||
|
sample->flags = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sample->flags = IT_SAMPLE_EXISTS;
|
||||||
|
|
||||||
|
sample->default_pan = 0;
|
||||||
|
sample->C5_speed = (int)( AMIGA_CLOCK / 214.0 ); //(long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
|
||||||
|
sample->finetune = 0;
|
||||||
|
|
||||||
|
if (sample->sus_loop_end > sample->length)
|
||||||
|
sample->sus_loop_end = sample->length;
|
||||||
|
|
||||||
|
if (loop_length > 2)
|
||||||
|
sample->flags |= IT_SAMPLE_SUS_LOOP;
|
||||||
|
|
||||||
|
sample->vibrato_speed = 0;
|
||||||
|
sample->vibrato_depth = 0;
|
||||||
|
sample->vibrato_rate = 0;
|
||||||
|
sample->vibrato_waveform = 0; // do we have to set _all_ these?
|
||||||
|
sample->max_resampling_quality = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int it_okt_read_sample_data(IT_SAMPLE *sample, const char * data, int length)
|
||||||
|
{
|
||||||
|
if (length && sample->length) {
|
||||||
|
if (length < sample->length) {
|
||||||
|
sample->length = length;
|
||||||
|
if (length < sample->sus_loop_end) sample->sus_loop_end = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
sample->data = malloc(length);
|
||||||
|
|
||||||
|
if (!sample->data)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(sample->data, data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct IFF_CHUNK IFF_CHUNK;
|
||||||
|
typedef struct IFF_CHUNKED IFF_CHUNKED;
|
||||||
|
|
||||||
|
struct IFF_CHUNK
|
||||||
|
{
|
||||||
|
unsigned type;
|
||||||
|
unsigned char * data;
|
||||||
|
unsigned size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IFF_CHUNKED
|
||||||
|
{
|
||||||
|
unsigned chunk_count;
|
||||||
|
IFF_CHUNK * chunks;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static IFF_CHUNKED *dumbfile_read_okt(DUMBFILE *f)
|
||||||
|
{
|
||||||
|
IFF_CHUNKED *mod = (IFF_CHUNKED *) malloc(sizeof(*mod));
|
||||||
|
if (!mod) return NULL;
|
||||||
|
|
||||||
|
mod->chunk_count = 0;
|
||||||
|
mod->chunks = 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
long bytes_read;
|
||||||
|
IFF_CHUNK * chunk = ( IFF_CHUNK * ) realloc( mod->chunks, ( mod->chunk_count + 1 ) * sizeof( IFF_CHUNK ) );
|
||||||
|
if ( !chunk )
|
||||||
|
{
|
||||||
|
if ( mod->chunks ) free( mod->chunks );
|
||||||
|
free( mod );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
mod->chunks = chunk;
|
||||||
|
chunk += mod->chunk_count;
|
||||||
|
|
||||||
|
bytes_read = dumbfile_mgetl( f );
|
||||||
|
if ( bytes_read < 0 ) break;
|
||||||
|
|
||||||
|
chunk->type = bytes_read;
|
||||||
|
chunk->size = dumbfile_mgetl( f );
|
||||||
|
|
||||||
|
if ( dumbfile_error( f ) ) break;
|
||||||
|
|
||||||
|
chunk->data = (unsigned char *) malloc( chunk->size );
|
||||||
|
if ( !chunk->data )
|
||||||
|
{
|
||||||
|
free( mod->chunks );
|
||||||
|
free( mod );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_read = dumbfile_getnc( ( char * ) chunk->data, chunk->size, f );
|
||||||
|
if ( bytes_read < (long)chunk->size )
|
||||||
|
{
|
||||||
|
if ( bytes_read <= 0 ) {
|
||||||
|
free( chunk->data );
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
chunk->size = bytes_read;
|
||||||
|
mod->chunk_count++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod->chunk_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !mod->chunk_count ) {
|
||||||
|
if ( mod->chunks ) free(mod->chunks);
|
||||||
|
free(mod);
|
||||||
|
mod = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_okt(IFF_CHUNKED * mod)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
if (mod)
|
||||||
|
{
|
||||||
|
if (mod->chunks)
|
||||||
|
{
|
||||||
|
for (i = 0; i < mod->chunk_count; i++)
|
||||||
|
{
|
||||||
|
if (mod->chunks[i].data) free(mod->chunks[i].data);
|
||||||
|
}
|
||||||
|
free(mod->chunks);
|
||||||
|
}
|
||||||
|
free(mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const IFF_CHUNK * get_chunk_by_type(IFF_CHUNKED * mod, unsigned type, unsigned offset)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
if (mod)
|
||||||
|
{
|
||||||
|
if (mod->chunks)
|
||||||
|
{
|
||||||
|
for (i = 0; i < mod->chunk_count; i++)
|
||||||
|
{
|
||||||
|
if (mod->chunks[i].type == type)
|
||||||
|
{
|
||||||
|
if (!offset) return &mod->chunks[i];
|
||||||
|
else offset--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_chunk_count(IFF_CHUNKED *mod, unsigned type)
|
||||||
|
{
|
||||||
|
unsigned i, count = 0;
|
||||||
|
if (mod)
|
||||||
|
{
|
||||||
|
if (mod->chunks)
|
||||||
|
{
|
||||||
|
for (i = 0; i < mod->chunk_count; i++)
|
||||||
|
{
|
||||||
|
if (mod->chunks[i].type == type) count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static DUMB_IT_SIGDATA *it_okt_load_sigdata(DUMBFILE *f)
|
||||||
|
{
|
||||||
|
DUMB_IT_SIGDATA *sigdata;
|
||||||
|
unsigned n_channels;
|
||||||
|
unsigned i, j, k, l;
|
||||||
|
IFF_CHUNKED *mod;
|
||||||
|
const IFF_CHUNK *chunk;
|
||||||
|
|
||||||
|
char signature[8];
|
||||||
|
|
||||||
|
if (dumbfile_getnc(signature, 8, f) < 8 ||
|
||||||
|
memcmp(signature, "OKTASONG", 8)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod = dumbfile_read_okt(f);
|
||||||
|
if (!mod)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sigdata = (DUMB_IT_SIGDATA *) malloc(sizeof(*sigdata));
|
||||||
|
if (!sigdata) {
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->name[0] = 0;
|
||||||
|
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('S','P','E','E'), 0);
|
||||||
|
if (!chunk || chunk->size < 2) {
|
||||||
|
free(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->speed = (chunk->data[0] << 8) | chunk->data[1];
|
||||||
|
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0);
|
||||||
|
if (!chunk || chunk->size < 32) {
|
||||||
|
free(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->n_samples = chunk->size / 32;
|
||||||
|
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0);
|
||||||
|
if (!chunk || chunk->size < 8) {
|
||||||
|
free(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
n_channels = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
j = (chunk->data[i * 2] << 8) | chunk->data[i * 2 + 1];
|
||||||
|
if (!j) n_channels++;
|
||||||
|
else if (j == 1) n_channels += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!n_channels) {
|
||||||
|
free(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->n_pchannels = n_channels;
|
||||||
|
|
||||||
|
sigdata->sample = (IT_SAMPLE *) malloc(sigdata->n_samples * sizeof(*sigdata->sample));
|
||||||
|
if (!sigdata->sample) {
|
||||||
|
free(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->song_message = NULL;
|
||||||
|
sigdata->order = NULL;
|
||||||
|
sigdata->instrument = NULL;
|
||||||
|
sigdata->pattern = NULL;
|
||||||
|
sigdata->midi = NULL;
|
||||||
|
sigdata->checkpoint = NULL;
|
||||||
|
|
||||||
|
sigdata->n_instruments = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < (unsigned)sigdata->n_samples; i++)
|
||||||
|
sigdata->sample[i].data = NULL;
|
||||||
|
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('S','A','M','P'), 0);
|
||||||
|
|
||||||
|
for (i = 0; i < (unsigned)sigdata->n_samples; i++) {
|
||||||
|
it_okt_read_sample_header(&sigdata->sample[i], chunk->data + 32 * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->restart_position = 0;
|
||||||
|
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('P','L','E','N'), 0);
|
||||||
|
if (!chunk || chunk->size < 2) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->n_orders = (chunk->data[0] << 8) | chunk->data[1];
|
||||||
|
// what if this is > 128?
|
||||||
|
|
||||||
|
if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('P','A','T','T'), 0);
|
||||||
|
if (!chunk || chunk->size < (unsigned)sigdata->n_orders) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->order = (unsigned char *) malloc(sigdata->n_orders);
|
||||||
|
if (!sigdata->order) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(sigdata->order, chunk->data, sigdata->n_orders);
|
||||||
|
|
||||||
|
/* Work out how many patterns there are. */
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('S','L','E','N'), 0);
|
||||||
|
if (!chunk || chunk->size < 2) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->n_patterns = (chunk->data[0] << 8) | chunk->data[1];
|
||||||
|
|
||||||
|
j = get_chunk_count(mod, DUMB_ID('P','B','O','D'));
|
||||||
|
if (sigdata->n_patterns > (int)j) sigdata->n_patterns = (int)j;
|
||||||
|
|
||||||
|
if (!sigdata->n_patterns) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigdata->pattern = (IT_PATTERN *) malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
|
||||||
|
if (!sigdata->pattern) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (i = 0; i < (unsigned)sigdata->n_patterns; i++)
|
||||||
|
sigdata->pattern[i].entry = NULL;
|
||||||
|
|
||||||
|
/* Read in the patterns */
|
||||||
|
for (i = 0; i < (unsigned)sigdata->n_patterns; i++) {
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('P','B','O','D'), i);
|
||||||
|
if (it_okt_read_pattern(&sigdata->pattern[i], chunk->data, chunk->size, n_channels) != 0) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And finally, the sample data */
|
||||||
|
k = get_chunk_count(mod, DUMB_ID('S','B','O','D'));
|
||||||
|
for (i = 0, j = 0; i < (unsigned)sigdata->n_samples, j < k; i++) {
|
||||||
|
if (sigdata->sample[i].flags & IT_SAMPLE_EXISTS) {
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('S','B','O','D'), j);
|
||||||
|
if (it_okt_read_sample_data(&sigdata->sample[i], (const char *)chunk->data, chunk->size)) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
free_okt(mod);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; i < (unsigned)sigdata->n_samples; i++) {
|
||||||
|
sigdata->sample[i].flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = get_chunk_by_type(mod, DUMB_ID('C','M','O','D'), 0);
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < n_channels, j < 4; j++) {
|
||||||
|
k = (chunk->data[j * 2] << 8) | chunk->data[j * 2 + 1];
|
||||||
|
l = (j == 1 || j == 2) ? 48 : 16;
|
||||||
|
if (k == 0) {
|
||||||
|
sigdata->channel_pan[i++] = l;
|
||||||
|
}
|
||||||
|
else if (k == 1) {
|
||||||
|
sigdata->channel_pan[i++] = l;
|
||||||
|
sigdata->channel_pan[i++] = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free_okt(mod);
|
||||||
|
|
||||||
|
/* Now let's initialise the remaining variables, and we're done! */
|
||||||
|
sigdata->flags = IT_WAS_AN_OKT | IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
|
||||||
|
|
||||||
|
sigdata->global_volume = 128;
|
||||||
|
sigdata->mixing_volume = 48;
|
||||||
|
/* We want 50 ticks per second; 50/6 row advances per second;
|
||||||
|
* 50*10=500 row advances per minute; 500/4=125 beats per minute.
|
||||||
|
*/
|
||||||
|
sigdata->tempo = 125;
|
||||||
|
sigdata->pan_separation = 128;
|
||||||
|
|
||||||
|
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||||
|
memset(sigdata->channel_pan + n_channels, 32, DUMB_IT_N_CHANNELS - n_channels);
|
||||||
|
|
||||||
|
_dumb_it_fix_invalid_orders(sigdata);
|
||||||
|
|
||||||
|
return sigdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DUH *DUMBEXPORT dumb_read_okt_quick(DUMBFILE *f)
|
||||||
|
{
|
||||||
|
sigdata_t *sigdata;
|
||||||
|
|
||||||
|
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||||
|
|
||||||
|
sigdata = it_okt_load_sigdata(f);
|
||||||
|
|
||||||
|
if (!sigdata)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
{
|
||||||
|
const char *tag[1][2];
|
||||||
|
tag[0][0] = "FORMAT";
|
||||||
|
tag[0][1] = "Oktalyzer";
|
||||||
|
return make_duh(-1, 1, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
||||||
|
}
|
||||||
|
}
|
29
dumb/src/it/readokt2.c
Normal file
29
dumb/src/it/readokt2.c
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/* _______ ____ __ ___ ___
|
||||||
|
* \ _ \ \ / \ / \ \ / / ' ' '
|
||||||
|
* | | \ \ | | || | \/ | . .
|
||||||
|
* | | | | | | || ||\ /| |
|
||||||
|
* | | | | | | || || \/ | | ' ' '
|
||||||
|
* | | | | | | || || | | . .
|
||||||
|
* | |_/ / \ \__// || | |
|
||||||
|
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
||||||
|
* / \
|
||||||
|
* / . \
|
||||||
|
* readokt2.c - Function to read an Oktalyzer / / \ \
|
||||||
|
* module from an open file and do | < / \_
|
||||||
|
* an initial run-through. | \/ /\ /
|
||||||
|
* \_ / > /
|
||||||
|
* | \ / /
|
||||||
|
* By Chris Moeller. | ' /
|
||||||
|
* \__/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dumb.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DUH *DUMBEXPORT dumb_read_okt(DUMBFILE *f)
|
||||||
|
{
|
||||||
|
DUH *duh = dumb_read_okt_quick(f);
|
||||||
|
dumb_it_do_initial_runthrough(duh);
|
||||||
|
return duh;
|
||||||
|
}
|
|
@ -296,7 +296,7 @@ static int it_old_psm_read_patterns(IT_PATTERN * pattern, DUMBFILE * f, int num,
|
||||||
if (flags & 0x80) {
|
if (flags & 0x80) {
|
||||||
if ((*ptr < 60) && (channel < pchans)) {
|
if ((*ptr < 60) && (channel < pchans)) {
|
||||||
entry->mask |= IT_ENTRY_NOTE;
|
entry->mask |= IT_ENTRY_NOTE;
|
||||||
entry->note = *ptr + 36;
|
entry->note = *ptr + 35;
|
||||||
}
|
}
|
||||||
ptr++;
|
ptr++;
|
||||||
if (*ptr) {
|
if (*ptr) {
|
||||||
|
|
|
@ -557,8 +557,8 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sigdata->global_volume = dumbfile_getc(f) << 1;
|
sigdata->global_volume = dumbfile_getc(f) * 16 / 11;
|
||||||
if ( !sigdata->global_volume || sigdata->global_volume > 128 ) sigdata->global_volume = 128;
|
if ( !sigdata->global_volume || sigdata->global_volume > 93 ) sigdata->global_volume = 93;
|
||||||
sigdata->speed = dumbfile_getc(f);
|
sigdata->speed = dumbfile_getc(f);
|
||||||
if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo?
|
if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo?
|
||||||
sigdata->tempo = dumbfile_getc(f);
|
sigdata->tempo = dumbfile_getc(f);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
// IT_STEREO... :o
|
// IT_STEREO... :o
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "dumb.h"
|
#include "dumb.h"
|
||||||
#include "internal/it.h"
|
#include "internal/it.h"
|
||||||
|
@ -28,14 +29,16 @@
|
||||||
#define strnicmp strncasecmp
|
#define strnicmp strncasecmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int it_stm_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f )
|
static int it_stm_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, unsigned short *offset )
|
||||||
{
|
{
|
||||||
dumbfile_getnc( sample->filename, 12, f );
|
dumbfile_getnc( sample->filename, 12, f );
|
||||||
sample->filename[12] = 0;
|
sample->filename[12] = 0;
|
||||||
|
|
||||||
memcpy( sample->name, sample->filename, 13 );
|
memcpy( sample->name, sample->filename, 13 );
|
||||||
|
|
||||||
dumbfile_skip( f, 2 + 2 );
|
dumbfile_skip( f, 2 );
|
||||||
|
|
||||||
|
*offset = dumbfile_igetw( f );
|
||||||
|
|
||||||
sample->length = dumbfile_igetw( f );
|
sample->length = dumbfile_igetw( f );
|
||||||
sample->loop_start = dumbfile_igetw( f );
|
sample->loop_start = dumbfile_igetw( f );
|
||||||
|
@ -78,24 +81,15 @@ static int it_stm_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f )
|
||||||
return dumbfile_error(f);
|
return dumbfile_error(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int it_stm_read_sample_data( IT_SAMPLE *sample, DUMBFILE *f )
|
static int it_stm_read_sample_data( IT_SAMPLE *sample, void *data_block, long offset )
|
||||||
{
|
{
|
||||||
int32 n;
|
|
||||||
|
|
||||||
if ( ! sample->length ) return 0;
|
if ( ! sample->length ) return 0;
|
||||||
|
|
||||||
n = dumbfile_pos( f );
|
|
||||||
if ( n & 15 ) {
|
|
||||||
if ( dumbfile_skip( f, 16 - ( n & 15 ) ) )
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sample->data = malloc( sample->length );
|
sample->data = malloc( sample->length );
|
||||||
if (!sample->data)
|
if (!sample->data)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ( dumbfile_getnc( sample->data, sample->length, f ) != sample->length )
|
memcpy( sample->data, (unsigned char*)data_block + offset, sample->length );
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -141,10 +135,6 @@ static int it_stm_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char
|
||||||
entry->effectvalue = buffer[ pos + 3 ];
|
entry->effectvalue = buffer[ pos + 3 ];
|
||||||
if ( entry->instrument && entry->instrument < 32 )
|
if ( entry->instrument && entry->instrument < 32 )
|
||||||
entry->mask |= IT_ENTRY_INSTRUMENT;
|
entry->mask |= IT_ENTRY_INSTRUMENT;
|
||||||
if ( note == 0xFC || note == 0xFE ) {
|
|
||||||
entry->mask |= IT_ENTRY_NOTE;
|
|
||||||
entry->note = IT_NOTE_CUT;
|
|
||||||
}
|
|
||||||
if ( note < 251 ) {
|
if ( note < 251 ) {
|
||||||
entry->mask |= IT_ENTRY_NOTE;
|
entry->mask |= IT_ENTRY_NOTE;
|
||||||
entry->note = ( note >> 4 ) * 12 + ( note & 0x0F );
|
entry->note = ( note >> 4 ) * 12 + ( note & 0x0F );
|
||||||
|
@ -154,7 +144,7 @@ static int it_stm_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char
|
||||||
entry->mask |= IT_ENTRY_EFFECT;
|
entry->mask |= IT_ENTRY_EFFECT;
|
||||||
switch ( entry->effect ) {
|
switch ( entry->effect ) {
|
||||||
case IT_SET_SPEED:
|
case IT_SET_SPEED:
|
||||||
entry->effectvalue >>= 4;
|
/* taken care of in the renderer */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IT_BREAK_TO_ROW:
|
case IT_BREAK_TO_ROW:
|
||||||
|
@ -192,14 +182,20 @@ static int it_stm_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static DUMB_IT_SIGDATA *it_stm_load_sigdata(DUMBFILE *f /*, int * version*/)
|
static DUMB_IT_SIGDATA *it_stm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
{
|
{
|
||||||
DUMB_IT_SIGDATA *sigdata;
|
DUMB_IT_SIGDATA *sigdata;
|
||||||
|
|
||||||
char tracker_name[ 8 ];
|
char tracker_name[ 8 ];
|
||||||
|
|
||||||
|
unsigned short sample_offset[ 31 ];
|
||||||
|
|
||||||
|
void *data_block;
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
long o, p, q;
|
||||||
|
|
||||||
sigdata = malloc(sizeof(*sigdata));
|
sigdata = malloc(sizeof(*sigdata));
|
||||||
if (!sigdata) return NULL;
|
if (!sigdata) return NULL;
|
||||||
|
|
||||||
|
@ -227,8 +223,7 @@ static DUMB_IT_SIGDATA *it_stm_load_sigdata(DUMBFILE *f /*, int * version*/)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* *version = dumbfile_mgetw(f); */
|
*version = dumbfile_mgetw(f);
|
||||||
dumbfile_skip( f, 2 );
|
|
||||||
|
|
||||||
sigdata->song_message = NULL;
|
sigdata->song_message = NULL;
|
||||||
sigdata->order = NULL;
|
sigdata->order = NULL;
|
||||||
|
@ -247,10 +242,11 @@ static DUMB_IT_SIGDATA *it_stm_load_sigdata(DUMBFILE *f /*, int * version*/)
|
||||||
sigdata->pan_separation = 128;
|
sigdata->pan_separation = 128;
|
||||||
|
|
||||||
/** WARNING: which ones? */
|
/** WARNING: which ones? */
|
||||||
sigdata->flags = IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M;
|
sigdata->flags = IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M | IT_WAS_AN_STM | IT_STEREO;
|
||||||
|
|
||||||
sigdata->speed = dumbfile_getc(f) >> 4;
|
n = dumbfile_getc(f);
|
||||||
if ( sigdata->speed < 1 ) sigdata->speed = 1;
|
if ( n < 32 ) n = 32;
|
||||||
|
sigdata->speed = n;
|
||||||
sigdata->n_patterns = dumbfile_getc(f);
|
sigdata->n_patterns = dumbfile_getc(f);
|
||||||
sigdata->global_volume = dumbfile_getc(f) << 1;
|
sigdata->global_volume = dumbfile_getc(f) << 1;
|
||||||
if ( sigdata->global_volume > 128 ) sigdata->global_volume = 128;
|
if ( sigdata->global_volume > 128 ) sigdata->global_volume = 128;
|
||||||
|
@ -287,7 +283,7 @@ static DUMB_IT_SIGDATA *it_stm_load_sigdata(DUMBFILE *f /*, int * version*/)
|
||||||
sigdata->channel_pan[ 3 ] = 16;
|
sigdata->channel_pan[ 3 ] = 16;
|
||||||
|
|
||||||
for ( n = 0; n < sigdata->n_samples; ++n ) {
|
for ( n = 0; n < sigdata->n_samples; ++n ) {
|
||||||
if ( it_stm_read_sample_header( &sigdata->sample[ n ], f ) ) {
|
if ( it_stm_read_sample_header( &sigdata->sample[ n ], f, &sample_offset[ n ] ) ) {
|
||||||
_dumb_it_unload_sigdata( sigdata );
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -300,7 +296,8 @@ static DUMB_IT_SIGDATA *it_stm_load_sigdata(DUMBFILE *f /*, int * version*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Orders, byte each, length = sigdata->n_orders (should be even) */
|
/* Orders, byte each, length = sigdata->n_orders (should be even) */
|
||||||
dumbfile_getnc( sigdata->order, 128, f );
|
dumbfile_getnc( sigdata->order, *version >= 0x200 ? 128 : 64, f );
|
||||||
|
if (*version < 0x200) memset( sigdata->order + 64, 0xFF, 64 );
|
||||||
sigdata->restart_position = 0;
|
sigdata->restart_position = 0;
|
||||||
|
|
||||||
for ( n = 127; n >= 0; --n ) {
|
for ( n = 127; n >= 0; --n ) {
|
||||||
|
@ -332,54 +329,105 @@ static DUMB_IT_SIGDATA *it_stm_load_sigdata(DUMBFILE *f /*, int * version*/)
|
||||||
free( buffer );
|
free( buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o = LONG_MAX;
|
||||||
|
p = 0;
|
||||||
|
|
||||||
for ( n = 0; n < sigdata->n_samples; ++n ) {
|
for ( n = 0; n < sigdata->n_samples; ++n ) {
|
||||||
if ( it_stm_read_sample_data( &sigdata->sample[ n ], f ) ) {
|
if ((sigdata->sample[ n ].flags & IT_SAMPLE_EXISTS) && sample_offset[ n ]) {
|
||||||
|
q = ((long)sample_offset[ n ]) * 16;
|
||||||
|
if (q < o) {
|
||||||
|
o = q;
|
||||||
|
}
|
||||||
|
if (q + sigdata->sample[ n ].length > p) {
|
||||||
|
p = q + sigdata->sample[ n ].length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sigdata->sample[ n ].flags = 0;
|
||||||
|
sigdata->sample[ n ].length = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data_block = malloc( p - o );
|
||||||
|
if ( !data_block ) {
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( n = 0, q = o / 16; n < sigdata->n_samples; ++n ) {
|
||||||
|
if ( sample_offset[ n ] ) {
|
||||||
|
sample_offset[ n ] = (unsigned short)(sample_offset[ n ] - q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
q = o - dumbfile_pos( f );
|
||||||
|
p -= o;
|
||||||
|
o = 0;
|
||||||
|
if ( q >= 0 ) dumbfile_skip( f, q );
|
||||||
|
else {
|
||||||
|
o = -q;
|
||||||
|
memset ( data_block, 0, o );
|
||||||
|
}
|
||||||
|
if ( dumbfile_getnc( (char*)data_block + o, p - o, f ) != p - o ) {
|
||||||
|
free( data_block );
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( n = 0; n < sigdata->n_samples; ++n ) {
|
||||||
|
if ( it_stm_read_sample_data( &sigdata->sample[ n ], data_block, ((long)sample_offset[ n ]) * 16 ) ) {
|
||||||
|
free( data_block );
|
||||||
_dumb_it_unload_sigdata( sigdata );
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free( data_block );
|
||||||
|
|
||||||
_dumb_it_fix_invalid_orders(sigdata);
|
_dumb_it_fix_invalid_orders(sigdata);
|
||||||
|
|
||||||
return sigdata;
|
return sigdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static char hexdigit(int in)
|
|
||||||
{
|
|
||||||
if (in < 10) return in + '0';
|
|
||||||
else return in + 'A' - 10;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
DUH *DUMBEXPORT dumb_read_stm_quick(DUMBFILE *f)
|
DUH *DUMBEXPORT dumb_read_stm_quick(DUMBFILE *f)
|
||||||
{
|
{
|
||||||
sigdata_t *sigdata;
|
sigdata_t *sigdata;
|
||||||
/*int ver;*/
|
int ver;
|
||||||
|
|
||||||
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
|
||||||
|
|
||||||
sigdata = it_stm_load_sigdata(f /*, &ver*/);
|
sigdata = it_stm_load_sigdata(f , &ver);
|
||||||
|
|
||||||
if (!sigdata)
|
if (!sigdata)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
/*char version[16];*/
|
char version[16];
|
||||||
const char *tag[2][2];
|
const char *tag[2][2];
|
||||||
tag[0][0] = "TITLE";
|
tag[0][0] = "TITLE";
|
||||||
tag[0][1] = ((DUMB_IT_SIGDATA *)sigdata)->name;
|
tag[0][1] = ((DUMB_IT_SIGDATA *)sigdata)->name;
|
||||||
tag[1][0] = "FORMAT";
|
tag[1][0] = "FORMAT";
|
||||||
tag[1][1] = "STM";
|
version[0] = 'S';
|
||||||
/*version[0] = 'S';
|
|
||||||
version[1] = 'T';
|
version[1] = 'T';
|
||||||
version[2] = 'M';
|
version[2] = 'M';
|
||||||
version[3] = ' ';
|
version[3] = ' ';
|
||||||
version[4] = 'v';
|
version[4] = 'v';
|
||||||
version[5] = hexdigit((ver >> 8) & 15);
|
version[5] = '0' + ((ver >> 8) & 15);
|
||||||
version[6] = '.';
|
version[6] = '.';
|
||||||
version[7] = hexdigit((ver >> 4) & 15);
|
if ((ver & 255) > 99)
|
||||||
version[8] = hexdigit(ver & 15);
|
{
|
||||||
|
version[7] = '0' + ((ver & 255) / 100 );
|
||||||
|
version[8] = '0' + (((ver & 255) / 10) % 10);
|
||||||
|
version[9] = '0' + ((ver & 255) % 10);
|
||||||
|
version[10] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
version[7] = '0' + ((ver & 255) / 10);
|
||||||
|
version[8] = '0' + ((ver & 255) % 10);
|
||||||
version[9] = 0;
|
version[9] = 0;
|
||||||
tag[1][1] = (const char *) &version;*/
|
}
|
||||||
|
tag[1][1] = (const char *) &version;
|
||||||
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
return make_duh(-1, 2, (const char *const (*)[2])tag, 1, &descptr, &sigdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,11 +111,20 @@ typedef struct XM_INSTRUMENT_EXTRA
|
||||||
int vibrato_sweep; /* 0-0xFF */
|
int vibrato_sweep; /* 0-0xFF */
|
||||||
int vibrato_depth; /* 0-0x0F */
|
int vibrato_depth; /* 0-0x0F */
|
||||||
int vibrato_speed; /* 0-0x3F */
|
int vibrato_speed; /* 0-0x3F */
|
||||||
|
int sample_header_size;
|
||||||
}
|
}
|
||||||
XM_INSTRUMENT_EXTRA;
|
XM_INSTRUMENT_EXTRA;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Trims off trailing white space, usually added by the tracker on file creation
|
||||||
|
*/
|
||||||
|
static void trim_whitespace(char *ptr, size_t size)
|
||||||
|
{
|
||||||
|
char *p = ptr + size - 1;
|
||||||
|
while (p >= ptr && *p <= 0x20) *p-- = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
/* Frees the original block if it can't resize it or if size is 0, and acts
|
/* Frees the original block if it can't resize it or if size is 0, and acts
|
||||||
* as malloc if ptr is NULL.
|
* as malloc if ptr is NULL.
|
||||||
*/
|
*/
|
||||||
|
@ -329,7 +338,7 @@ static int it_xm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels,
|
||||||
|
|
||||||
static int it_xm_make_envelope(IT_ENVELOPE *envelope, const unsigned short *data, int y_offset)
|
static int it_xm_make_envelope(IT_ENVELOPE *envelope, const unsigned short *data, int y_offset)
|
||||||
{
|
{
|
||||||
int i, pos;
|
int i, pos, val;
|
||||||
|
|
||||||
if (envelope->n_nodes > 12) {
|
if (envelope->n_nodes > 12) {
|
||||||
/* XXX
|
/* XXX
|
||||||
|
@ -346,12 +355,13 @@ static int it_xm_make_envelope(IT_ENVELOPE *envelope, const unsigned short *data
|
||||||
pos = 0;
|
pos = 0;
|
||||||
for (i = 0; i < envelope->n_nodes; i++) {
|
for (i = 0; i < envelope->n_nodes; i++) {
|
||||||
envelope->node_t[i] = data[pos++];
|
envelope->node_t[i] = data[pos++];
|
||||||
if (data[pos] > 64) {
|
val = data[pos++];
|
||||||
TRACE("XM error: out-of-range envelope node (node_y[%d]=%d)\n", i, data[pos]);
|
if (val > 64) {
|
||||||
envelope->n_nodes = 0;
|
TRACE("XM error: out-of-range envelope node (node_y[%d]=%d)\n", i, val);
|
||||||
return -1;
|
/* FT2 seems to simply clip the value */
|
||||||
|
val = 64;
|
||||||
}
|
}
|
||||||
envelope->node_y[i] = (signed char)(data[pos++] + y_offset);
|
envelope->node_y[i] = (signed char)(val + y_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -359,21 +369,153 @@ static int it_xm_make_envelope(IT_ENVELOPE *envelope, const unsigned short *data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct LIMITED_XM LIMITED_XM;
|
||||||
|
|
||||||
|
struct LIMITED_XM
|
||||||
|
{
|
||||||
|
unsigned char *buffered;
|
||||||
|
long ptr, limit, allocated;
|
||||||
|
DUMBFILE *remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
struct DUMBFILE
|
||||||
|
{
|
||||||
|
DUMBFILE_SYSTEM *dfs;
|
||||||
|
void *file;
|
||||||
|
long pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int limit_xm_resize(void *f, long n)
|
||||||
|
{
|
||||||
|
DUMBFILE *df = f;
|
||||||
|
LIMITED_XM *lx = df->file;
|
||||||
|
if (lx->buffered || n) {
|
||||||
|
if (n > lx->allocated) {
|
||||||
|
unsigned char *buffered = realloc( lx->buffered, n );
|
||||||
|
if ( !buffered ) return -1;
|
||||||
|
lx->buffered = buffered;
|
||||||
|
memset( buffered + lx->allocated, 0, n - lx->allocated );
|
||||||
|
lx->allocated = n;
|
||||||
|
}
|
||||||
|
if ( dumbfile_getnc( lx->buffered, n, lx->remaining ) < n ) return -1;
|
||||||
|
} else if (!n) {
|
||||||
|
if ( lx->buffered ) free( lx->buffered );
|
||||||
|
lx->buffered = NULL;
|
||||||
|
lx->allocated = 0;
|
||||||
|
}
|
||||||
|
lx->limit = n;
|
||||||
|
lx->ptr = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int limit_xm_skip_end(void *f, int32 n)
|
||||||
|
{
|
||||||
|
DUMBFILE *df = f;
|
||||||
|
LIMITED_XM *lx = df->file;
|
||||||
|
return dumbfile_skip( lx->remaining, n );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int limit_xm_skip(void *f, int32 n)
|
||||||
|
{
|
||||||
|
LIMITED_XM *lx = f;
|
||||||
|
lx->ptr += n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int limit_xm_getc(void *f)
|
||||||
|
{
|
||||||
|
LIMITED_XM *lx = f;
|
||||||
|
if (lx->ptr >= lx->allocated) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return lx->buffered[lx->ptr++];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static long limit_xm_getnc(char *ptr, int32 n, void *f)
|
||||||
|
{
|
||||||
|
LIMITED_XM *lx = f;
|
||||||
|
int left;
|
||||||
|
left = lx->allocated - lx->ptr;
|
||||||
|
if (n > left) {
|
||||||
|
if (left > 0) {
|
||||||
|
memcpy( ptr, lx->buffered + lx->ptr, left );
|
||||||
|
memset( ptr + left, 0, n - left );
|
||||||
|
} else {
|
||||||
|
memset( ptr, 0, n );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy( ptr, lx->buffered + lx->ptr, n );
|
||||||
|
}
|
||||||
|
lx->ptr += n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void limit_xm_close(void *f)
|
||||||
|
{
|
||||||
|
LIMITED_XM *lx = f;
|
||||||
|
if (lx->buffered) free(lx->buffered);
|
||||||
|
/* Do NOT close lx->remaining */
|
||||||
|
free(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DUMBFILE_SYSTEM limit_xm_dfs = {
|
||||||
|
NULL,
|
||||||
|
&limit_xm_skip,
|
||||||
|
&limit_xm_getc,
|
||||||
|
&limit_xm_getnc,
|
||||||
|
&limit_xm_close
|
||||||
|
};
|
||||||
|
|
||||||
|
static DUMBFILE *dumbfile_limit_xm(DUMBFILE *f)
|
||||||
|
{
|
||||||
|
LIMITED_XM * lx = malloc(sizeof(*lx));
|
||||||
|
lx->remaining = f;
|
||||||
|
lx->buffered = NULL;
|
||||||
|
lx->ptr = 0;
|
||||||
|
lx->limit = 0;
|
||||||
|
lx->allocated = 0;
|
||||||
|
return dumbfile_open_ex( lx, &limit_xm_dfs );
|
||||||
|
}
|
||||||
|
|
||||||
static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA *extra, DUMBFILE *f)
|
static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA *extra, DUMBFILE *f)
|
||||||
{
|
{
|
||||||
uint32 size, bytes_read;
|
uint32 size, bytes_read;
|
||||||
unsigned short vol_points[24];
|
unsigned short vol_points[24];
|
||||||
unsigned short pan_points[24];
|
unsigned short pan_points[24];
|
||||||
int i, type;
|
int i, type;
|
||||||
|
const unsigned long max_size = 4 + 22 + 1 + 2 + 4 + 96 + 48 + 48 + 1 * 14 + 2 + 2;
|
||||||
|
unsigned long skip_end = 0;
|
||||||
|
|
||||||
/* Header size. Tends to be more than the actual size of the structure.
|
/* Header size. Tends to be more than the actual size of the structure.
|
||||||
* So unread bytes must be skipped before reading the first sample
|
* So unread bytes must be skipped before reading the first sample
|
||||||
* header.
|
* header.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if ( limit_xm_resize( f, 4 ) < 0 ) return -1;
|
||||||
|
|
||||||
size = dumbfile_igetl(f);
|
size = dumbfile_igetl(f);
|
||||||
|
|
||||||
|
if ( size == 0 ) size = max_size;
|
||||||
|
else if ( size > max_size )
|
||||||
|
{
|
||||||
|
skip_end = size - max_size;
|
||||||
|
size = max_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( limit_xm_resize( f, size - 4 ) < 0 ) return -1;
|
||||||
|
|
||||||
dumbfile_getnc(instrument->name, 22, f);
|
dumbfile_getnc(instrument->name, 22, f);
|
||||||
instrument->name[22] = 0;
|
instrument->name[22] = 0;
|
||||||
|
trim_whitespace(instrument->name, 22);
|
||||||
instrument->filename[0] = 0;
|
instrument->filename[0] = 0;
|
||||||
dumbfile_skip(f, 1); /* Instrument type. Should be 0, but seems random. */
|
dumbfile_skip(f, 1); /* Instrument type. Should be 0, but seems random. */
|
||||||
extra->n_samples = dumbfile_igetw(f);
|
extra->n_samples = dumbfile_igetw(f);
|
||||||
|
@ -385,12 +527,11 @@ static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA
|
||||||
|
|
||||||
if (extra->n_samples) {
|
if (extra->n_samples) {
|
||||||
/* sample header size */
|
/* sample header size */
|
||||||
dumbfile_skip(f, 4); // XXX can't be trusted, as there are trackers that write the wrong value here
|
|
||||||
/*i = dumbfile_igetl(f);
|
/*i = dumbfile_igetl(f);
|
||||||
if (i && i != 0x28) { // XXX some crap with 0 here
|
if (!i || i > 0x28) i = 0x28;*/
|
||||||
TRACE("XM error: unexpected sample header size\n");
|
dumbfile_skip(f, 4);
|
||||||
return -1;
|
i = 0x28;
|
||||||
}*/
|
extra->sample_header_size = i;
|
||||||
|
|
||||||
/* sample map */
|
/* sample map */
|
||||||
for (i = 0; i < 96; i++) {
|
for (i = 0; i < 96; i++) {
|
||||||
|
@ -476,7 +617,10 @@ static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA
|
||||||
for (i = 0; i < 96; i++)
|
for (i = 0; i < 96; i++)
|
||||||
instrument->map_sample[i] = 0;
|
instrument->map_sample[i] = 0;
|
||||||
|
|
||||||
if (dumbfile_skip(f, size - bytes_read))
|
if (size > bytes_read && dumbfile_skip(f, size - bytes_read))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (skip_end && limit_xm_skip_end(f, skip_end))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
instrument->new_note_action = NNA_NOTE_CUT;
|
instrument->new_note_action = NNA_NOTE_CUT;
|
||||||
|
@ -531,6 +675,7 @@ static int it_xm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
|
||||||
|
|
||||||
dumbfile_getnc(sample->name, 22, f);
|
dumbfile_getnc(sample->name, 22, f);
|
||||||
sample->name[22] = 0;
|
sample->name[22] = 0;
|
||||||
|
trim_whitespace(sample->name, 22);
|
||||||
|
|
||||||
sample->filename[0] = 0;
|
sample->filename[0] = 0;
|
||||||
|
|
||||||
|
@ -785,6 +930,7 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
sigdata->name[20] = 0;
|
sigdata->name[20] = 0;
|
||||||
|
trim_whitespace(sigdata->name, 20);
|
||||||
|
|
||||||
if (dumbfile_getc(f) != 0x1A) {
|
if (dumbfile_getc(f) != 0x1A) {
|
||||||
TRACE("XM error: 0x1A not found\n");
|
TRACE("XM error: 0x1A not found\n");
|
||||||
|
@ -924,16 +1070,24 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
for (i = 0; i < sigdata->n_instruments; i++) {
|
for (i = 0; i < sigdata->n_instruments; i++) {
|
||||||
XM_INSTRUMENT_EXTRA extra;
|
XM_INSTRUMENT_EXTRA extra;
|
||||||
|
|
||||||
if (it_xm_read_instrument(&sigdata->instrument[i], &extra, f) < 0) {
|
DUMBFILE * lf = dumbfile_limit_xm( f );
|
||||||
|
if ( !lf ) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_xm_read_instrument(&sigdata->instrument[i], &extra, lf) < 0) {
|
||||||
// XXX
|
// XXX
|
||||||
if ( ! i )
|
if ( ! i )
|
||||||
{
|
{
|
||||||
TRACE("XM error: instrument %d\n", i+1);
|
TRACE("XM error: instrument %d\n", i+1);
|
||||||
|
dumbfile_close( lf );
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
dumbfile_close( lf );
|
||||||
sigdata->n_instruments = i;
|
sigdata->n_instruments = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -948,17 +1102,31 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
|
|
||||||
sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples));
|
sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples));
|
||||||
if (!sigdata->sample) {
|
if (!sigdata->sample) {
|
||||||
|
dumbfile_close( lf );
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (j = total_samples; j < total_samples+extra.n_samples; j++)
|
for (j = total_samples; j < total_samples+extra.n_samples; j++)
|
||||||
sigdata->sample[j].data = NULL;
|
sigdata->sample[j].data = NULL;
|
||||||
|
|
||||||
|
if ( limit_xm_resize( lf, 0 ) < 0 ) {
|
||||||
|
dumbfile_close( lf );
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* read instrument's samples */
|
/* read instrument's samples */
|
||||||
for (j = 0; j < extra.n_samples; j++) {
|
for (j = 0; j < extra.n_samples; j++) {
|
||||||
IT_SAMPLE *sample = &sigdata->sample[total_samples+j];
|
IT_SAMPLE *sample = &sigdata->sample[total_samples+j];
|
||||||
int b = it_xm_read_sample_header(sample, f);
|
int b;
|
||||||
|
if ( limit_xm_resize( lf, extra.sample_header_size ) < 0 ) {
|
||||||
|
dumbfile_close( lf );
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
b = it_xm_read_sample_header(sample, lf);
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
|
dumbfile_close( lf );
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -975,12 +1143,15 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
}
|
}
|
||||||
for (j = 0; j < extra.n_samples; j++) {
|
for (j = 0; j < extra.n_samples; j++) {
|
||||||
if (it_xm_read_sample_data(&sigdata->sample[total_samples+j], roguebytes[j], f) != 0) {
|
if (it_xm_read_sample_data(&sigdata->sample[total_samples+j], roguebytes[j], f) != 0) {
|
||||||
|
dumbfile_close( lf );
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total_samples += extra.n_samples;
|
total_samples += extra.n_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dumbfile_close( lf );
|
||||||
}
|
}
|
||||||
|
|
||||||
sigdata->n_samples = total_samples;
|
sigdata->n_samples = total_samples;
|
||||||
|
@ -1012,8 +1183,16 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
for (i = 0; i < sigdata->n_instruments; i++) {
|
for (i = 0; i < sigdata->n_instruments; i++) {
|
||||||
XM_INSTRUMENT_EXTRA extra;
|
XM_INSTRUMENT_EXTRA extra;
|
||||||
|
|
||||||
if (it_xm_read_instrument(&sigdata->instrument[i], &extra, f) < 0) {
|
DUMBFILE * lf = dumbfile_limit_xm( f );
|
||||||
|
if ( !lf ) {
|
||||||
|
free(roguebytes);
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_xm_read_instrument(&sigdata->instrument[i], &extra, lf) < 0) {
|
||||||
TRACE("XM error: instrument %d\n", i+1);
|
TRACE("XM error: instrument %d\n", i+1);
|
||||||
|
dumbfile_close(lf);
|
||||||
free(roguebytes);
|
free(roguebytes);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1026,6 +1205,7 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
|
|
||||||
sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples));
|
sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples));
|
||||||
if (!sigdata->sample) {
|
if (!sigdata->sample) {
|
||||||
|
dumbfile_close( lf );
|
||||||
free(roguebytes);
|
free(roguebytes);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1033,10 +1213,24 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
for (j = total_samples; j < total_samples+extra.n_samples; j++)
|
for (j = total_samples; j < total_samples+extra.n_samples; j++)
|
||||||
sigdata->sample[j].data = NULL;
|
sigdata->sample[j].data = NULL;
|
||||||
|
|
||||||
|
if ( limit_xm_resize( lf, 0 ) < 0 ) {
|
||||||
|
dumbfile_close( lf );
|
||||||
|
free( roguebytes );
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* read instrument's samples */
|
/* read instrument's samples */
|
||||||
for (j = 0; j < extra.n_samples; j++) {
|
for (j = 0; j < extra.n_samples; j++) {
|
||||||
IT_SAMPLE *sample = &sigdata->sample[total_samples+j];
|
IT_SAMPLE *sample = &sigdata->sample[total_samples+j];
|
||||||
int b = it_xm_read_sample_header(sample, f);
|
int b;
|
||||||
|
if ( limit_xm_resize( lf, extra.sample_header_size ) < 0 ) {
|
||||||
|
dumbfile_close( lf );
|
||||||
|
free( roguebytes );
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
b = it_xm_read_sample_header(sample, lf);
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
free(roguebytes);
|
free(roguebytes);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
@ -1055,6 +1249,8 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
}
|
}
|
||||||
total_samples += extra.n_samples;
|
total_samples += extra.n_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dumbfile_close( lf );
|
||||||
}
|
}
|
||||||
|
|
||||||
sigdata->n_samples = total_samples;
|
sigdata->n_samples = total_samples;
|
||||||
|
|
|
@ -167,6 +167,7 @@ if (log) printf(" - %2d %02X", effect, value);
|
||||||
case XM_SET_GLOBAL_VOLUME:
|
case XM_SET_GLOBAL_VOLUME:
|
||||||
effect = IT_SET_GLOBAL_VOLUME;
|
effect = IT_SET_GLOBAL_VOLUME;
|
||||||
value *= 2;
|
value *= 2;
|
||||||
|
if (value > 128) value = 128;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XM_KEY_OFF:
|
case XM_KEY_OFF:
|
||||||
|
@ -187,6 +188,7 @@ if (log) printf(" - %2d %02X", effect, value);
|
||||||
case EBASE+XM_E_SET_PANNING: effect = SBASE+IT_S_SET_PAN; break;
|
case EBASE+XM_E_SET_PANNING: effect = SBASE+IT_S_SET_PAN; break;
|
||||||
case EBASE+XM_E_FINE_VOLSLIDE_UP: effect = IT_XM_FINE_VOLSLIDE_UP; break;
|
case EBASE+XM_E_FINE_VOLSLIDE_UP: effect = IT_XM_FINE_VOLSLIDE_UP; break;
|
||||||
case EBASE+XM_E_FINE_VOLSLIDE_DOWN: effect = IT_XM_FINE_VOLSLIDE_DOWN; break;
|
case EBASE+XM_E_FINE_VOLSLIDE_DOWN: effect = IT_XM_FINE_VOLSLIDE_DOWN; break;
|
||||||
|
case EBASE+XM_E_SET_MIDI_MACRO: effect = SBASE+IT_S_SET_MIDI_MACRO; break;
|
||||||
|
|
||||||
case EBASE + XM_E_FINE_PORTA_UP:
|
case EBASE + XM_E_FINE_PORTA_UP:
|
||||||
effect = IT_PORTAMENTO_UP;
|
effect = IT_PORTAMENTO_UP;
|
||||||
|
|
|
@ -877,6 +877,10 @@
|
||||||
RelativePath="..\..\src\helpers\barray.c"
|
RelativePath="..\..\src\helpers\barray.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\helpers\blip_buf.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\helpers\clickrem.c"
|
RelativePath="..\..\src\helpers\clickrem.c"
|
||||||
>
|
>
|
||||||
|
@ -1560,6 +1564,14 @@
|
||||||
RelativePath="..\..\src\it\loadmtm2.c"
|
RelativePath="..\..\src\it\loadmtm2.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\it\loadokt.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\it\loadokt2.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\it\loadoldpsm.c"
|
RelativePath="..\..\src\it\loadoldpsm.c"
|
||||||
>
|
>
|
||||||
|
@ -1778,6 +1790,14 @@
|
||||||
RelativePath="..\..\src\it\readmtm.c"
|
RelativePath="..\..\src\it\readmtm.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\it\readokt.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\it\readokt2.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\it\readoldpsm.c"
|
RelativePath="..\..\src\it\readoldpsm.c"
|
||||||
>
|
>
|
||||||
|
@ -1960,6 +1980,10 @@
|
||||||
<Filter
|
<Filter
|
||||||
Name="internal"
|
Name="internal"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\internal\blip_buf.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\internal\dumb.h"
|
RelativePath="..\..\include\internal\dumb.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -6,7 +6,7 @@ if( NOT CMAKE_BUILD_TYPE MATCHES "Release" )
|
||||||
set( CMAKE_BUILD_TYPE "RelWithDebInfo" )
|
set( CMAKE_BUILD_TYPE "RelWithDebInfo" )
|
||||||
endif( NOT CMAKE_BUILD_TYPE MATCHES "Release" )
|
endif( NOT CMAKE_BUILD_TYPE MATCHES "Release" )
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" )
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" )
|
||||||
if( NOT PROFILE )
|
if( NOT PROFILE )
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer" )
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer" )
|
||||||
|
@ -15,7 +15,7 @@ if( CMAKE_COMPILER_IS_GNUCXX )
|
||||||
if( HAVE_NO_ARRAY_BOUNDS )
|
if( HAVE_NO_ARRAY_BOUNDS )
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-array-bounds" )
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-array-bounds" )
|
||||||
endif( HAVE_NO_ARRAY_BOUNDS )
|
endif( HAVE_NO_ARRAY_BOUNDS )
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
add_library( gme
|
add_library( gme
|
||||||
gme/Blip_Buffer.cpp
|
gme/Blip_Buffer.cpp
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// deprecated
|
// deprecated
|
||||||
Music_Emu::load;
|
using Music_Emu::load;
|
||||||
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
||||||
{ return load_remaining_( &h, sizeof h, in ); }
|
{ return load_remaining_( &h, sizeof h, in ); }
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// deprecated
|
// deprecated
|
||||||
Music_Emu::load;
|
using Music_Emu::load;
|
||||||
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
||||||
{ return load_remaining_( &h, sizeof h, in ); }
|
{ return load_remaining_( &h, sizeof h, in ); }
|
||||||
enum { gym_rate = 60 };
|
enum { gym_rate = 60 };
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
void ignore_silence( bool disable = true );
|
void ignore_silence( bool disable = true );
|
||||||
|
|
||||||
// Info for current track
|
// Info for current track
|
||||||
Gme_File::track_info;
|
using Gme_File::track_info;
|
||||||
blargg_err_t track_info( track_info_t* out ) const;
|
blargg_err_t track_info( track_info_t* out ) const;
|
||||||
|
|
||||||
// Sound customization
|
// Sound customization
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// deprecated
|
// deprecated
|
||||||
Music_Emu::load;
|
using Music_Emu::load;
|
||||||
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
||||||
{ return load_remaining_( &h, sizeof h, in ); }
|
{ return load_remaining_( &h, sizeof h, in ); }
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
public:
|
public:
|
||||||
// deprecated
|
// deprecated
|
||||||
struct header_t { char tag [4]; };
|
struct header_t { char tag [4]; };
|
||||||
Music_Emu::load;
|
using Music_Emu::load;
|
||||||
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
||||||
{ return load_remaining_( &h, sizeof h, in ); }
|
{ return load_remaining_( &h, sizeof h, in ); }
|
||||||
void disable_playlist( bool = true ); // use clear_playlist()
|
void disable_playlist( bool = true ); // use clear_playlist()
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// deprecated
|
// deprecated
|
||||||
Music_Emu::load;
|
using Music_Emu::load;
|
||||||
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
||||||
{ return load_remaining_( &h, sizeof h, in ); }
|
{ return load_remaining_( &h, sizeof h, in ); }
|
||||||
byte const* trailer() const; // use track_info()
|
byte const* trailer() const; // use track_info()
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// deprecated
|
// deprecated
|
||||||
Music_Emu::load;
|
using Music_Emu::load;
|
||||||
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
|
||||||
{ return load_remaining_( &h, sizeof h, in ); }
|
{ return load_remaining_( &h, sizeof h, in ); }
|
||||||
byte const* gd3_data( int* size_out = 0 ) const; // use track_info()
|
byte const* gd3_data( int* size_out = 0 ) const; // use track_info()
|
||||||
|
|
|
@ -8,9 +8,9 @@ if( MSVC )
|
||||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4554 /wd4102" )
|
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4554 /wd4102" )
|
||||||
endif( MSVC )
|
endif( MSVC )
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" )
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" )
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
|
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||||
add_definitions( -DINFNAN_CHECK -DMULTIPLE_THREADS )
|
add_definitions( -DINFNAN_CHECK -DMULTIPLE_THREADS )
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
cmake_minimum_required( VERSION 2.4 )
|
cmake_minimum_required( VERSION 2.4 )
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUC )
|
if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" )
|
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" )
|
||||||
endif( CMAKE_COMPILER_IS_GNUC )
|
endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
add_library( jpeg
|
add_library( jpeg
|
||||||
jcomapi.c
|
jcomapi.c
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
cmake_minimum_required( VERSION 2.4 )
|
cmake_minimum_required( VERSION 2.4 )
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUC )
|
if( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" )
|
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" )
|
||||||
endif( CMAKE_COMPILER_IS_GNUC )
|
endif( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
set( LZMA_FILES
|
set( LZMA_FILES
|
||||||
C/Archive/7z/7zDecode.c
|
C/Archive/7z/7zDecode.c
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
This version of ZDoom must be compiled with any version between 4.22 and 4.28 inclusive.
|
This version of ZDoom must be compiled with any version between 4.22 and 4.28 inclusive or 4.34.
|
||||||
Use of the latest 4.26 is recommended though due to technical issues with 4.28.
|
Use of the latest 4.26 is recommended though due to technical issues with 4.28.
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,13 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
||||||
blockprojectiles = <bool>;// Line blocks all projectiles
|
blockprojectiles = <bool>;// Line blocks all projectiles
|
||||||
blockuse = <bool>; // Line blocks all use actions
|
blockuse = <bool>; // Line blocks all use actions
|
||||||
blocksight = <bool>; // Line blocks monster line of sight
|
blocksight = <bool>; // Line blocks monster line of sight
|
||||||
|
locknumber = <int>; // Line special is locked
|
||||||
|
arg0str = <string>; // Alternate string-based version of arg0
|
||||||
|
|
||||||
|
* Note about arg0str
|
||||||
|
|
||||||
|
For lines with ACS specials (80-86 and 226), if arg0str is present and non-null, it
|
||||||
|
will be used as the name of the script to execute, and arg0 will be ignored.
|
||||||
}
|
}
|
||||||
|
|
||||||
sidedef
|
sidedef
|
||||||
|
@ -135,6 +141,9 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
||||||
light = <integer>; // This side's light level. Default is 0.
|
light = <integer>; // This side's light level. Default is 0.
|
||||||
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
|
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
|
||||||
// relative to the owning sector's light level.
|
// relative to the owning sector's light level.
|
||||||
|
lightfog = <bool>; // true = This side's relative lighting is used even in
|
||||||
|
// foggy sectors. Default is to disable relative
|
||||||
|
// lighting in foggy sectors.
|
||||||
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
|
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
|
||||||
smoothlighting = <bool>; // Use smooth fake contrast.
|
smoothlighting = <bool>; // Use smooth fake contrast.
|
||||||
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
|
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
|
||||||
|
@ -193,6 +202,12 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
||||||
conversation = <int> // Assigns a conversation dialogue to this thing.
|
conversation = <int> // Assigns a conversation dialogue to this thing.
|
||||||
// Parameter is the conversation ID, 0 meaning none.
|
// Parameter is the conversation ID, 0 meaning none.
|
||||||
countsecret = <bool>; // Picking up this actor counts as a secret.
|
countsecret = <bool>; // Picking up this actor counts as a secret.
|
||||||
|
arg0str = <string>; // Alternate string-based version of arg0
|
||||||
|
|
||||||
|
* Note about arg0str
|
||||||
|
|
||||||
|
For things with ACS specials (80-86 and 226), if arg0str is present and non-null, it
|
||||||
|
will be used as the name of the script to execute, and arg0 will be ignored.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -303,6 +318,16 @@ Removed remarks of 8 being the maximum number of player classes/skill levels the
|
||||||
Added renderstyleceiling and renderstylefloor sector properties
|
Added renderstyleceiling and renderstylefloor sector properties
|
||||||
Added Sector_Set3DFloor to list of specials that need to be handled for line ID remapping
|
Added Sector_Set3DFloor to list of specials that need to be handled for line ID remapping
|
||||||
|
|
||||||
|
1.18 17.02.2012
|
||||||
|
Added arg0str linedef property.
|
||||||
|
Standardized whitespace.
|
||||||
|
|
||||||
|
1.19 24.02.2012
|
||||||
|
Added back locknumber property.
|
||||||
|
|
||||||
|
1.20 25.02.2012
|
||||||
|
Added arg0str thing property.
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
EOF
|
EOF
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
===============================================================================
|
===============================================================================
|
||||||
Universal Strife Dialog Format Specification v2.0 - 08/20/10
|
Universal Strife Dialog Format Specification v2.1 - 01/06/13
|
||||||
|
|
||||||
Written by Braden "Blzut3" Obrzut - admin@maniacsvault.net
|
Written by Braden "Blzut3" Obrzut - admin@maniacsvault.net
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ Graf Zahl
|
||||||
Quasar
|
Quasar
|
||||||
et al.
|
et al.
|
||||||
|
|
||||||
Copyright (c) 2010 Braden Obrzut.
|
Copyright (c) 2013 Braden Obrzut.
|
||||||
Permission is granted to copy, distribute and/or modify this document
|
Permission is granted to copy, distribute and/or modify this document
|
||||||
under the terms of the GNU Free Documentation License, Version 1.2
|
under the terms of the GNU Free Documentation License, Version 1.2
|
||||||
or any later version published by the Free Software Foundation;
|
or any later version published by the Free Software Foundation;
|
||||||
|
@ -19,6 +19,14 @@ et al.
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
|
||||||
|
=======================================
|
||||||
|
Changes in v2.1
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
* Pages are specified as starting as being indexed from 1 instead of 0. While
|
||||||
|
this technically renders the spec incompatible, all known implementations
|
||||||
|
used this convention as it was inline with the binary format.
|
||||||
|
|
||||||
=======================================
|
=======================================
|
||||||
I. Grammar / Syntax
|
I. Grammar / Syntax
|
||||||
=======================================
|
=======================================
|
||||||
|
@ -77,7 +85,7 @@ conversation // Starts a dialog.
|
||||||
actor = <integer>; // mobj for this conversation's actor. If previously
|
actor = <integer>; // mobj for this conversation's actor. If previously
|
||||||
// used, this will override the previous conversation.
|
// used, this will override the previous conversation.
|
||||||
|
|
||||||
page // Starts a new page. Pages are automatically numbered starting at 0.
|
page // Starts a new page. Pages are automatically numbered starting at 1.
|
||||||
{
|
{
|
||||||
name = <string>; // Name that goes in the upper left hand corner
|
name = <string>; // Name that goes in the upper left hand corner
|
||||||
panel = <string>; // Name of lump to render as the background.
|
panel = <string>; // Name of lump to render as the background.
|
||||||
|
@ -105,14 +113,14 @@ conversation // Starts a dialog.
|
||||||
|
|
||||||
// The amount of an item needed to successfully pick this option.
|
// The amount of an item needed to successfully pick this option.
|
||||||
// This can be repeated, but only the first will be shown (provided
|
// This can be repeated, but only the first will be shown (provided
|
||||||
// diaplaycost is true). All costs must be satisfied for success.
|
// displaycost is true). All costs must be satisfied for success.
|
||||||
cost
|
cost
|
||||||
{
|
{
|
||||||
item = <integer>; // Item that is required for this option.
|
item = <integer>; // Item that is required for this option.
|
||||||
amount = <integer>; // Minimum amount of the item needed.
|
amount = <integer>; // Minimum amount of the item needed.
|
||||||
}
|
}
|
||||||
|
|
||||||
displaycost = <bool>; // Weather the cost should be
|
displaycost = <bool>; // Whether the cost should be
|
||||||
// displayed with the option.
|
// displayed with the option.
|
||||||
// If no cost is specified this should
|
// If no cost is specified this should
|
||||||
// be ignored.
|
// be ignored.
|
||||||
|
|
|
@ -10,14 +10,14 @@ include( CheckCXXCompilerFlag )
|
||||||
include( FindPkgConfig )
|
include( FindPkgConfig )
|
||||||
|
|
||||||
option( NO_ASM "Disable assembly code" )
|
option( NO_ASM "Disable assembly code" )
|
||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
option( NO_STRIP "Do not strip Release or MinSizeRel builds" )
|
option( NO_STRIP "Do not strip Release or MinSizeRel builds" )
|
||||||
# At least some versions of Xcode fail if you strip with the linker
|
# At least some versions of Xcode fail if you strip with the linker
|
||||||
# instead of the separate strip utility.
|
# instead of the separate strip utility.
|
||||||
if( APPLE )
|
if( APPLE )
|
||||||
set( NO_STRIP ON )
|
set( NO_STRIP ON )
|
||||||
endif( APPLE )
|
endif( APPLE )
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" )
|
option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" )
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ set( MINOR_VERSIONS "50" "49" "48" "47" "46" "45" "44" "43" "42" "41"
|
||||||
"27" "26" "25" "24" "23" "22" "21" "20" "21" "19" "18" "17" "16"
|
"27" "26" "25" "24" "23" "22" "21" "20" "21" "19" "18" "17" "16"
|
||||||
"15" "14" "13" "12" "11" "10" "09" "08" "07" "06" "05" "04" "03"
|
"15" "14" "13" "12" "11" "10" "09" "08" "07" "06" "05" "04" "03"
|
||||||
"02" "01" "00" )
|
"02" "01" "00" )
|
||||||
set( MAJOR_VERSIONS "30" "28" "26" "24" "22" "20" )
|
set( MAJOR_VERSIONS "44" "34" "28" "26" "24" "22" "20" )
|
||||||
set( FMOD_DIR_VERSIONS ${FMOD_DIR_VERSIONS} "../fmod" )
|
set( FMOD_DIR_VERSIONS ${FMOD_DIR_VERSIONS} "../fmod" )
|
||||||
foreach( majver ${MAJOR_VERSIONS} )
|
foreach( majver ${MAJOR_VERSIONS} )
|
||||||
foreach( minver ${MINOR_VERSIONS} )
|
foreach( minver ${MINOR_VERSIONS} )
|
||||||
|
@ -401,7 +401,7 @@ endif( NO_OPENAL )
|
||||||
|
|
||||||
# Search for FluidSynth
|
# Search for FluidSynth
|
||||||
|
|
||||||
include( ../FindFluidSynth.cmake )
|
find_package( FluidSynth )
|
||||||
|
|
||||||
# Search for NASM
|
# Search for NASM
|
||||||
|
|
||||||
|
@ -503,7 +503,7 @@ endif( NOT NO_ASM )
|
||||||
set( SSE_MATTERS NO )
|
set( SSE_MATTERS NO )
|
||||||
|
|
||||||
# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it.
|
# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it.
|
||||||
if( CMAKE_SIZEOF_VOID_P MATCHES "4" )
|
if( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc )
|
||||||
CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH )
|
CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH )
|
||||||
CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 )
|
CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 )
|
||||||
if( CAN_DO_MFPMATH )
|
if( CAN_DO_MFPMATH )
|
||||||
|
@ -515,7 +515,7 @@ if( CMAKE_SIZEOF_VOID_P MATCHES "4" )
|
||||||
set( SSE2_ENABLE -arch:SSE2 )
|
set( SSE2_ENABLE -arch:SSE2 )
|
||||||
set( SSE_MATTERS YES )
|
set( SSE_MATTERS YES )
|
||||||
endif( CAN_DO_MFPMATH )
|
endif( CAN_DO_MFPMATH )
|
||||||
endif( CMAKE_SIZEOF_VOID_P MATCHES "4" )
|
endif( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc )
|
||||||
|
|
||||||
if( SSE_MATTERS )
|
if( SSE_MATTERS )
|
||||||
if( WIN32 )
|
if( WIN32 )
|
||||||
|
@ -535,7 +535,7 @@ endif( SSE_MATTERS )
|
||||||
|
|
||||||
# Set up flags for GCC
|
# Set up flags for GCC
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
if( PROFILE )
|
if( PROFILE )
|
||||||
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" )
|
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg" )
|
||||||
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg" )
|
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg" )
|
||||||
|
@ -547,24 +547,24 @@ if( CMAKE_COMPILER_IS_GNUCXX )
|
||||||
if( NOT PROFILE )
|
if( NOT PROFILE )
|
||||||
set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" )
|
set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" )
|
||||||
endif( NOT PROFILE )
|
endif( NOT PROFILE )
|
||||||
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${REL_CXX_FLAGS}" )
|
set( CMAKE_CXX_FLAGS_RELEASE "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}" )
|
||||||
set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${REL_CXX_FLAGS}" )
|
set( CMAKE_CXX_FLAGS_MINSIZEREL "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_MINSIZEREL}" )
|
||||||
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${REL_CXX_FLAGS}" )
|
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" )
|
||||||
|
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused -Wextra -Wno-missing-field-initializers" )
|
set( CMAKE_CXX_FLAGS "-Wall -Wno-unused -Wextra -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS}" )
|
||||||
|
|
||||||
# Remove extra warnings when using the official DirectX headers.
|
# Remove extra warnings when using the official DirectX headers.
|
||||||
# Also, TDM-GCC 4.4.0 no longer accepts glibc-style printf formats as valid,
|
# Also, TDM-GCC 4.4.0 no longer accepts glibc-style printf formats as valid,
|
||||||
# which is a royal pain. The previous version I had been using was fine with them.
|
# which is a royal pain. The previous version I had been using was fine with them.
|
||||||
if( WIN32 )
|
if( WIN32 )
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas -Wno-comment -Wno-format" )
|
set( CMAKE_CXX_FLAGS "-Wno-unknown-pragmas -Wno-comment -Wno-format ${CMAKE_CXX_FLAGS}" )
|
||||||
endif( WIN32 )
|
endif( WIN32 )
|
||||||
|
|
||||||
if( NOT NO_STRIP )
|
if( NOT NO_STRIP )
|
||||||
set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -s" )
|
set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -s" )
|
||||||
set (CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} -s" )
|
set (CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} -s" )
|
||||||
endif( NOT NO_STRIP )
|
endif( NOT NO_STRIP )
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
# Check for functions that may or may not exist.
|
# Check for functions that may or may not exist.
|
||||||
|
|
||||||
|
@ -588,13 +588,6 @@ if( NOT STRNICMP_EXISTS )
|
||||||
add_definitions( -Dstrnicmp=strncasecmp )
|
add_definitions( -Dstrnicmp=strncasecmp )
|
||||||
endif( NOT STRNICMP_EXISTS )
|
endif( NOT STRNICMP_EXISTS )
|
||||||
|
|
||||||
if( NOT WIN32 )
|
|
||||||
CHECK_FUNCTION_EXISTS( sigtimedwait SIGTIMEDWAIT_EXISTS )
|
|
||||||
if( SIGTIMEDWAIT_EXISTS )
|
|
||||||
add_definitions( -DHAVE_SIGTIMEDWAIT )
|
|
||||||
endif( SIGTIMEDWAIT_EXISTS )
|
|
||||||
endif( NOT WIN32)
|
|
||||||
|
|
||||||
if( NOT MSVC )
|
if( NOT MSVC )
|
||||||
add_definitions( -D__forceinline=inline )
|
add_definitions( -D__forceinline=inline )
|
||||||
endif( NOT MSVC )
|
endif( NOT MSVC )
|
||||||
|
@ -634,10 +627,12 @@ if( BACKPATCH )
|
||||||
add_definitions( -DBACKPATCH )
|
add_definitions( -DBACKPATCH )
|
||||||
endif( BACKPATCH )
|
endif( BACKPATCH )
|
||||||
|
|
||||||
# Update svnrevision.h
|
# Update gitinfo.h
|
||||||
|
|
||||||
|
get_target_property( UPDATEREVISION_EXE updaterevision LOCATION )
|
||||||
|
|
||||||
add_custom_target( revision_check ALL
|
add_custom_target( revision_check ALL
|
||||||
COMMAND ${CMAKE_BINARY_DIR}/tools/updaterevision/updaterevision . src/svnrevision.h
|
COMMAND ${UPDATEREVISION_EXE} src/gitinfo.h
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
DEPENDS updaterevision )
|
DEPENDS updaterevision )
|
||||||
|
|
||||||
|
@ -678,15 +673,15 @@ if( WIN32 )
|
||||||
win32/i_system.cpp
|
win32/i_system.cpp
|
||||||
win32/st_start.cpp
|
win32/st_start.cpp
|
||||||
win32/win32video.cpp )
|
win32/win32video.cpp )
|
||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
# CMake is not set up to compile and link rc files with GCC. :(
|
# CMake is not set up to compile and link rc files with GCC. :(
|
||||||
add_custom_command( OUTPUT zdoom-rc.o
|
add_custom_command( OUTPUT zdoom-rc.o
|
||||||
COMMAND windres -o zdoom-rc.o -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zdoom.rc
|
COMMAND windres -o zdoom-rc.o -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zdoom.rc
|
||||||
DEPENDS win32/zdoom.rc )
|
DEPENDS win32/zdoom.rc )
|
||||||
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} zdoom-rc.o )
|
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} zdoom-rc.o )
|
||||||
else( CMAKE_COMPILER_IS_GNUCXX )
|
else( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} win32/zdoom.rc )
|
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} win32/zdoom.rc )
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
else( WIN32 )
|
else( WIN32 )
|
||||||
set( SYSTEM_SOURCES_DIR sdl )
|
set( SYSTEM_SOURCES_DIR sdl )
|
||||||
set( SYSTEM_SOURCES
|
set( SYSTEM_SOURCES
|
||||||
|
@ -701,7 +696,7 @@ else( WIN32 )
|
||||||
sdl/sdlvideo.cpp
|
sdl/sdlvideo.cpp
|
||||||
sdl/st_start.cpp )
|
sdl/st_start.cpp )
|
||||||
if( APPLE )
|
if( APPLE )
|
||||||
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} sdl/SDLMain.m sdl/iwadpicker_cocoa.mm )
|
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} sdl/SDLMain.m sdl/iwadpicker_cocoa.mm sdl/i_system_cocoa.mm )
|
||||||
endif( APPLE )
|
endif( APPLE )
|
||||||
endif( WIN32 )
|
endif( WIN32 )
|
||||||
|
|
||||||
|
@ -717,21 +712,19 @@ else( NO_ASM )
|
||||||
ADD_ASM_FILE( asm_ia32 tmap2 )
|
ADD_ASM_FILE( asm_ia32 tmap2 )
|
||||||
ADD_ASM_FILE( asm_ia32 tmap3 )
|
ADD_ASM_FILE( asm_ia32 tmap3 )
|
||||||
endif( X64 )
|
endif( X64 )
|
||||||
if( WIN32 )
|
|
||||||
if( NOT X64 )
|
|
||||||
ADD_ASM_FILE( win32 wrappers )
|
|
||||||
endif( NOT X64 )
|
|
||||||
endif( WIN32 )
|
|
||||||
endif( NO_ASM )
|
endif( NO_ASM )
|
||||||
|
|
||||||
|
get_target_property( LEMON_EXE lemon LOCATION )
|
||||||
|
get_target_property( RE2C_EXE re2c LOCATION )
|
||||||
|
|
||||||
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h
|
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y .
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y .
|
||||||
COMMAND ${CMAKE_BINARY_DIR}/tools/lemon/lemon xlat_parser.y
|
COMMAND ${LEMON_EXE} xlat_parser.y
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y )
|
DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y )
|
||||||
|
|
||||||
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h
|
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h
|
||||||
COMMAND ${CMAKE_BINARY_DIR}/tools/re2c/re2c --no-generation-date -s -o ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h ${CMAKE_CURRENT_SOURCE_DIR}/sc_man_scanner.re
|
COMMAND ${RE2C_EXE} --no-generation-date -s -o ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h ${CMAKE_CURRENT_SOURCE_DIR}/sc_man_scanner.re
|
||||||
DEPENDS re2c ${CMAKE_CURRENT_SOURCE_DIR}/sc_man_scanner.re )
|
DEPENDS re2c ${CMAKE_CURRENT_SOURCE_DIR}/sc_man_scanner.re )
|
||||||
|
|
||||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
|
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||||
|
@ -754,7 +747,37 @@ elseif( FLUIDSYNTH_FOUND )
|
||||||
add_definitions( -DHAVE_FLUIDSYNTH )
|
add_definitions( -DHAVE_FLUIDSYNTH )
|
||||||
endif( DYN_FLUIDSYNTH )
|
endif( DYN_FLUIDSYNTH )
|
||||||
|
|
||||||
|
# Project files should be aware of the header files. We can GLOB these since
|
||||||
|
# there's generally a new cpp for every header so this file will get changed
|
||||||
|
if( WIN32 )
|
||||||
|
set( EXTRA_HEADER_DIRS win32/*.h )
|
||||||
|
else( WIN32 )
|
||||||
|
set( EXTRA_HEADER_DIRS sdl/*.h )
|
||||||
|
endif( WIN32 )
|
||||||
|
file( GLOB HEADER_FILES
|
||||||
|
${EXTRA_HEADER_DIRS}
|
||||||
|
fragglescript/*.h
|
||||||
|
g_doom/*.h
|
||||||
|
g_heretic/*.h
|
||||||
|
g_hexen/*.h
|
||||||
|
g_raven/*.h
|
||||||
|
g_shared/*.h
|
||||||
|
g_strife/*.h
|
||||||
|
intermission/*.h
|
||||||
|
menu/*.h
|
||||||
|
oplsynth/*.h
|
||||||
|
r_data/*.h
|
||||||
|
resourcefiles/*.h
|
||||||
|
sfmt/*.h
|
||||||
|
sound/*.h
|
||||||
|
textures/*.h
|
||||||
|
thingdef/*.h
|
||||||
|
xlat/*.h
|
||||||
|
*.h
|
||||||
|
)
|
||||||
|
|
||||||
add_executable( zdoom WIN32
|
add_executable( zdoom WIN32
|
||||||
|
${HEADER_FILES}
|
||||||
autostart.cpp
|
autostart.cpp
|
||||||
${ASM_SOURCES}
|
${ASM_SOURCES}
|
||||||
${SYSTEM_SOURCES}
|
${SYSTEM_SOURCES}
|
||||||
|
@ -803,6 +826,7 @@ add_executable( zdoom WIN32
|
||||||
g_skill.cpp
|
g_skill.cpp
|
||||||
gameconfigfile.cpp
|
gameconfigfile.cpp
|
||||||
gi.cpp
|
gi.cpp
|
||||||
|
gitinfo.cpp
|
||||||
hu_scores.cpp
|
hu_scores.cpp
|
||||||
i_net.cpp
|
i_net.cpp
|
||||||
info.cpp
|
info.cpp
|
||||||
|
@ -892,6 +916,7 @@ add_executable( zdoom WIN32
|
||||||
tables.cpp
|
tables.cpp
|
||||||
teaminfo.cpp
|
teaminfo.cpp
|
||||||
tempfiles.cpp
|
tempfiles.cpp
|
||||||
|
v_blend.cpp
|
||||||
v_collection.cpp
|
v_collection.cpp
|
||||||
v_draw.cpp
|
v_draw.cpp
|
||||||
v_font.cpp
|
v_font.cpp
|
||||||
|
@ -967,6 +992,8 @@ add_executable( zdoom WIN32
|
||||||
oplsynth/music_opldumper_mididevice.cpp
|
oplsynth/music_opldumper_mididevice.cpp
|
||||||
oplsynth/music_opl_mididevice.cpp
|
oplsynth/music_opl_mididevice.cpp
|
||||||
oplsynth/opl_mus_player.cpp
|
oplsynth/opl_mus_player.cpp
|
||||||
|
oplsynth/dosbox/opl.cpp
|
||||||
|
oplsynth/OPL3.cpp
|
||||||
resourcefiles/ancientzip.cpp
|
resourcefiles/ancientzip.cpp
|
||||||
resourcefiles/file_7z.cpp
|
resourcefiles/file_7z.cpp
|
||||||
resourcefiles/file_grp.cpp
|
resourcefiles/file_grp.cpp
|
||||||
|
@ -1025,6 +1052,7 @@ add_executable( zdoom WIN32
|
||||||
thingdef/thingdef_data.cpp
|
thingdef/thingdef_data.cpp
|
||||||
thingdef/thingdef_exp.cpp
|
thingdef/thingdef_exp.cpp
|
||||||
thingdef/thingdef_expression.cpp
|
thingdef/thingdef_expression.cpp
|
||||||
|
thingdef/thingdef_function.cpp
|
||||||
thingdef/thingdef_parse.cpp
|
thingdef/thingdef_parse.cpp
|
||||||
thingdef/thingdef_properties.cpp
|
thingdef/thingdef_properties.cpp
|
||||||
thingdef/thingdef_states.cpp
|
thingdef/thingdef_states.cpp
|
||||||
|
@ -1098,7 +1126,7 @@ if( NOT WIN32 )
|
||||||
COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make
|
COMMAND chmod +x ${CMAKE_CURRENT_BINARY_DIR}/link-make
|
||||||
COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make )
|
COMMAND /bin/sh -c ${CMAKE_CURRENT_BINARY_DIR}/link-make )
|
||||||
endif( NOT WIN32 )
|
endif( NOT WIN32 )
|
||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
# GCC misoptimizes this file
|
# GCC misoptimizes this file
|
||||||
set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" )
|
set_source_files_properties( oplsynth/fmopl.cpp PROPERTIES COMPILE_FLAGS "-fno-tree-dominator-opts -fno-tree-fre" )
|
||||||
|
|
||||||
|
@ -1106,4 +1134,8 @@ if( CMAKE_COMPILER_IS_GNUCXX )
|
||||||
if( SSE_MATTERS )
|
if( SSE_MATTERS )
|
||||||
set_source_files_properties( x86.cpp PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" )
|
set_source_files_properties( x86.cpp PROPERTIES COMPILE_FLAGS "-msse2 -mmmx" )
|
||||||
endif( SSE_MATTERS )
|
endif( SSE_MATTERS )
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
|
||||||
|
if( MSVC )
|
||||||
|
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO")
|
||||||
|
endif( MSVC )
|
||||||
|
|
|
@ -36,7 +36,7 @@ DEFINE_SPECIAL(ClearForceField, 34, 1, 1, 1) // [RH] Remove Strife's forcefie
|
||||||
DEFINE_SPECIAL(Floor_RaiseByValueTimes8, 35, 3, 3, 3)
|
DEFINE_SPECIAL(Floor_RaiseByValueTimes8, 35, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(Floor_LowerByValueTimes8, 36, 3, 3, 3)
|
DEFINE_SPECIAL(Floor_LowerByValueTimes8, 36, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(Floor_MoveToValue, 37, 3, 4, 4)
|
DEFINE_SPECIAL(Floor_MoveToValue, 37, 3, 4, 4)
|
||||||
DEFINE_SPECIAL(Ceiling_Waggle, 38, 5, 5, 4) // [RH] Complement of Floor_Waggle
|
DEFINE_SPECIAL(Ceiling_Waggle, 38, 5, 5, 5) // [RH] Complement of Floor_Waggle
|
||||||
DEFINE_SPECIAL(Teleport_ZombieChanger, 39, 2, 2, 2) // [RH] Needed for Strife
|
DEFINE_SPECIAL(Teleport_ZombieChanger, 39, 2, 2, 2) // [RH] Needed for Strife
|
||||||
DEFINE_SPECIAL(Ceiling_LowerByValue, 40, 3, 3, 3)
|
DEFINE_SPECIAL(Ceiling_LowerByValue, 40, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(Ceiling_RaiseByValue, 41, 3, 3, 3)
|
DEFINE_SPECIAL(Ceiling_RaiseByValue, 41, 3, 3, 3)
|
||||||
|
@ -69,7 +69,7 @@ DEFINE_SPECIAL(Floor_RaiseInstant, 67, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(Floor_MoveToValueTimes8, 68, 4, 4, 4)
|
DEFINE_SPECIAL(Floor_MoveToValueTimes8, 68, 4, 4, 4)
|
||||||
DEFINE_SPECIAL(Ceiling_MoveToValueTimes8, 69, 4, 4, 4)
|
DEFINE_SPECIAL(Ceiling_MoveToValueTimes8, 69, 4, 4, 4)
|
||||||
DEFINE_SPECIAL(Teleport, 70, 1, 3, 3)
|
DEFINE_SPECIAL(Teleport, 70, 1, 3, 3)
|
||||||
DEFINE_SPECIAL(Teleport_NoFog, 71, 1, 3, 3)
|
DEFINE_SPECIAL(Teleport_NoFog, 71, 1, 4, 4)
|
||||||
DEFINE_SPECIAL(ThrustThing, 72, 2, 4, 4)
|
DEFINE_SPECIAL(ThrustThing, 72, 2, 4, 4)
|
||||||
DEFINE_SPECIAL(DamageThing, 73, 1, 2, 2)
|
DEFINE_SPECIAL(DamageThing, 73, 1, 2, 2)
|
||||||
DEFINE_SPECIAL(Teleport_NewMap, 74, 2, 3, 3)
|
DEFINE_SPECIAL(Teleport_NewMap, 74, 2, 3, 3)
|
||||||
|
@ -82,7 +82,7 @@ DEFINE_SPECIAL(ACS_Execute, 80, 1, 5, 5)
|
||||||
DEFINE_SPECIAL(ACS_Suspend, 81, 2, 2, 2)
|
DEFINE_SPECIAL(ACS_Suspend, 81, 2, 2, 2)
|
||||||
DEFINE_SPECIAL(ACS_Terminate, 82, 2, 2, 2)
|
DEFINE_SPECIAL(ACS_Terminate, 82, 2, 2, 2)
|
||||||
DEFINE_SPECIAL(ACS_LockedExecute, 83, 5, 5, 5)
|
DEFINE_SPECIAL(ACS_LockedExecute, 83, 5, 5, 5)
|
||||||
DEFINE_SPECIAL(ACS_ExecuteWithResult, 84, 1, 4, 4)
|
DEFINE_SPECIAL(ACS_ExecuteWithResult, 84, 1, 5, 5)
|
||||||
DEFINE_SPECIAL(ACS_LockedExecuteDoor, 85, 5, 5, 5)
|
DEFINE_SPECIAL(ACS_LockedExecuteDoor, 85, 5, 5, 5)
|
||||||
DEFINE_SPECIAL(Polyobj_MoveToSpot, 86, 3, 3, 3)
|
DEFINE_SPECIAL(Polyobj_MoveToSpot, 86, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(Polyobj_Stop, 87, 1, 1, 1)
|
DEFINE_SPECIAL(Polyobj_Stop, 87, 1, 1, 1)
|
||||||
|
@ -97,7 +97,7 @@ DEFINE_SPECIAL(FloorAndCeiling_LowerByValue, 95, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(FloorAndCeiling_RaiseByValue, 96, 3, 3, 3)
|
DEFINE_SPECIAL(FloorAndCeiling_RaiseByValue, 96, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(Ceiling_LowerAndCrushDist, 97, 3, 5, 5)
|
DEFINE_SPECIAL(Ceiling_LowerAndCrushDist, 97, 3, 5, 5)
|
||||||
DEFINE_SPECIAL(Sector_SetTranslucent, 98, 3, 4, 4)
|
DEFINE_SPECIAL(Sector_SetTranslucent, 98, 3, 4, 4)
|
||||||
|
DEFINE_SPECIAL(Floor_RaiseAndCrushDoom, 99, 3, 4, 4)
|
||||||
DEFINE_SPECIAL(Scroll_Texture_Left, 100, -1, -1, 2)
|
DEFINE_SPECIAL(Scroll_Texture_Left, 100, -1, -1, 2)
|
||||||
DEFINE_SPECIAL(Scroll_Texture_Right, 101, -1, -1, 2)
|
DEFINE_SPECIAL(Scroll_Texture_Right, 101, -1, -1, 2)
|
||||||
DEFINE_SPECIAL(Scroll_Texture_Up, 102, -1, -1, 2)
|
DEFINE_SPECIAL(Scroll_Texture_Up, 102, -1, -1, 2)
|
||||||
|
@ -146,6 +146,7 @@ DEFINE_SPECIAL(Sector_Set3DFloor, 160, -1, -1, 5)
|
||||||
DEFINE_SPECIAL(Sector_SetContents, 161, -1, -1, 3)
|
DEFINE_SPECIAL(Sector_SetContents, 161, -1, -1, 3)
|
||||||
|
|
||||||
// [RH] Begin new specials for ZDoom
|
// [RH] Begin new specials for ZDoom
|
||||||
|
DEFINE_SPECIAL(Ceiling_CrushAndRaiseDist, 168, 3, 5, 5)
|
||||||
DEFINE_SPECIAL(Generic_Crusher2, 169, 5, 5, 5)
|
DEFINE_SPECIAL(Generic_Crusher2, 169, 5, 5, 5)
|
||||||
DEFINE_SPECIAL(Sector_SetCeilingScale2, 170, 3, 3, 3)
|
DEFINE_SPECIAL(Sector_SetCeilingScale2, 170, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(Sector_SetFloorScale2, 171, 3, 3, 3)
|
DEFINE_SPECIAL(Sector_SetFloorScale2, 171, 3, 3, 3)
|
||||||
|
@ -205,7 +206,7 @@ DEFINE_SPECIAL(Scroll_Ceiling, 224, 4, 4, 5)
|
||||||
DEFINE_SPECIAL(Scroll_Texture_Offsets, 225, -1, -1, 1)
|
DEFINE_SPECIAL(Scroll_Texture_Offsets, 225, -1, -1, 1)
|
||||||
DEFINE_SPECIAL(ACS_ExecuteAlways, 226, 1, 5, 5)
|
DEFINE_SPECIAL(ACS_ExecuteAlways, 226, 1, 5, 5)
|
||||||
DEFINE_SPECIAL(PointPush_SetForce, 227, -1, -1, 4)
|
DEFINE_SPECIAL(PointPush_SetForce, 227, -1, -1, 4)
|
||||||
DEFINE_SPECIAL(Plat_RaiseAndStayTx0, 228, 2, 2, 2)
|
DEFINE_SPECIAL(Plat_RaiseAndStayTx0, 228, 2, 3, 3)
|
||||||
DEFINE_SPECIAL(Thing_SetGoal, 229, 3, 4, 4)
|
DEFINE_SPECIAL(Thing_SetGoal, 229, 3, 4, 4)
|
||||||
DEFINE_SPECIAL(Plat_UpByValueStayTx, 230, 3, 3, 3)
|
DEFINE_SPECIAL(Plat_UpByValueStayTx, 230, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(Plat_ToggleCeiling, 231, 1, 1, 1)
|
DEFINE_SPECIAL(Plat_ToggleCeiling, 231, 1, 1, 1)
|
||||||
|
@ -219,7 +220,7 @@ DEFINE_SPECIAL(Floor_RaiseToLowestCeiling, 238, 2, 2, 2)
|
||||||
DEFINE_SPECIAL(Floor_RaiseByValueTxTy, 239, 3, 3, 3)
|
DEFINE_SPECIAL(Floor_RaiseByValueTxTy, 239, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(Floor_RaiseByTexture, 240, 2, 2, 2)
|
DEFINE_SPECIAL(Floor_RaiseByTexture, 240, 2, 2, 2)
|
||||||
DEFINE_SPECIAL(Floor_LowerToLowestTxTy, 241, 2, 2, 2)
|
DEFINE_SPECIAL(Floor_LowerToLowestTxTy, 241, 2, 2, 2)
|
||||||
DEFINE_SPECIAL(Floor_LowerToHighest, 242, 3, 3, 3)
|
DEFINE_SPECIAL(Floor_LowerToHighest, 242, 3, 4, 4)
|
||||||
DEFINE_SPECIAL(Exit_Normal, 243, 1, 1, 1)
|
DEFINE_SPECIAL(Exit_Normal, 243, 1, 1, 1)
|
||||||
DEFINE_SPECIAL(Exit_Secret, 244, 1, 1, 1)
|
DEFINE_SPECIAL(Exit_Secret, 244, 1, 1, 1)
|
||||||
DEFINE_SPECIAL(Elevator_RaiseToNearest, 245, 2, 2, 2)
|
DEFINE_SPECIAL(Elevator_RaiseToNearest, 245, 2, 2, 2)
|
||||||
|
@ -228,7 +229,7 @@ DEFINE_SPECIAL(Elevator_LowerToNearest, 247, 2, 2, 2)
|
||||||
DEFINE_SPECIAL(HealThing, 248, 1, 2, 2)
|
DEFINE_SPECIAL(HealThing, 248, 1, 2, 2)
|
||||||
DEFINE_SPECIAL(Door_CloseWaitOpen, 249, 3, 4, 4)
|
DEFINE_SPECIAL(Door_CloseWaitOpen, 249, 3, 4, 4)
|
||||||
DEFINE_SPECIAL(Floor_Donut, 250, 3, 3, 3)
|
DEFINE_SPECIAL(Floor_Donut, 250, 3, 3, 3)
|
||||||
DEFINE_SPECIAL(FloorAndCeiling_LowerRaise, 251, 3, 3, 4)
|
DEFINE_SPECIAL(FloorAndCeiling_LowerRaise, 251, 3, 4, 4)
|
||||||
DEFINE_SPECIAL(Ceiling_RaiseToNearest, 252, 2, 2, 2)
|
DEFINE_SPECIAL(Ceiling_RaiseToNearest, 252, 2, 2, 2)
|
||||||
DEFINE_SPECIAL(Ceiling_LowerToLowest, 253, 2, 2, 2)
|
DEFINE_SPECIAL(Ceiling_LowerToLowest, 253, 2, 2, 2)
|
||||||
DEFINE_SPECIAL(Ceiling_LowerToFloor, 254, 2, 2, 2)
|
DEFINE_SPECIAL(Ceiling_LowerToFloor, 254, 2, 2, 2)
|
||||||
|
|
71
src/actor.h
71
src/actor.h
|
@ -30,9 +30,7 @@
|
||||||
#include "dthinker.h"
|
#include "dthinker.h"
|
||||||
|
|
||||||
|
|
||||||
// States are tied to finite states are
|
// States are tied to finite states are tied to animation frames.
|
||||||
// tied to animation frames.
|
|
||||||
// Needs precompiled tables/data structures.
|
|
||||||
#include "info.h"
|
#include "info.h"
|
||||||
|
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
|
@ -40,6 +38,7 @@
|
||||||
#include "r_data/renderstyle.h"
|
#include "r_data/renderstyle.h"
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "memarena.h"
|
#include "memarena.h"
|
||||||
|
#include "g_level.h"
|
||||||
|
|
||||||
struct subsector_t;
|
struct subsector_t;
|
||||||
//
|
//
|
||||||
|
@ -266,8 +265,8 @@ enum
|
||||||
|
|
||||||
// --- mobj.flags5 ---
|
// --- mobj.flags5 ---
|
||||||
|
|
||||||
MF5_FASTER = 0x00000001, // moves faster when DF_FAST_MONSTERS or nightmare is on.
|
MF5_DONTDRAIN = 0x00000001, // cannot be drained health from.
|
||||||
MF5_FASTMELEE = 0x00000002, // has a faster melee attack when DF_FAST_MONSTERS or nightmare is on.
|
/* = 0x00000002, */
|
||||||
MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances.
|
MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances.
|
||||||
/* = 0x00000008, */
|
/* = 0x00000008, */
|
||||||
MF5_COUNTSECRET = 0x00000010, // From Doom 64: actor acts like a secret
|
MF5_COUNTSECRET = 0x00000010, // From Doom 64: actor acts like a secret
|
||||||
|
@ -330,6 +329,8 @@ enum
|
||||||
MF6_DONTCORPSE = 0x02000000, // [RC] Don't autoset MF_CORPSE upon death and don't force Crash state change.
|
MF6_DONTCORPSE = 0x02000000, // [RC] Don't autoset MF_CORPSE upon death and don't force Crash state change.
|
||||||
MF6_POISONALWAYS = 0x04000000, // Always apply poison, even when target can't take the damage.
|
MF6_POISONALWAYS = 0x04000000, // Always apply poison, even when target can't take the damage.
|
||||||
MF6_DOHARMSPECIES = 0x08000000, // Do hurt one's own species with projectiles.
|
MF6_DOHARMSPECIES = 0x08000000, // Do hurt one's own species with projectiles.
|
||||||
|
MF6_INTRYMOVE = 0x10000000, // Executing P_TryMove
|
||||||
|
MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim.
|
||||||
|
|
||||||
// --- mobj.renderflags ---
|
// --- mobj.renderflags ---
|
||||||
|
|
||||||
|
@ -400,7 +401,7 @@ enum EBounceFlags
|
||||||
BOUNCE_Ceilings = 1<<2, // bounces off of ceilings
|
BOUNCE_Ceilings = 1<<2, // bounces off of ceilings
|
||||||
BOUNCE_Actors = 1<<3, // bounces off of some actors
|
BOUNCE_Actors = 1<<3, // bounces off of some actors
|
||||||
BOUNCE_AllActors = 1<<4, // bounces off of all actors (requires BOUNCE_Actors to be set, too)
|
BOUNCE_AllActors = 1<<4, // bounces off of all actors (requires BOUNCE_Actors to be set, too)
|
||||||
BOUNCE_AutoOff = 1<<5, // when bouncing off a floor, if the new Z velocity is below 3.0, disable further bouncing
|
BOUNCE_AutoOff = 1<<5, // when bouncing off a sector plane, if the new Z velocity is below 3.0, disable further bouncing
|
||||||
BOUNCE_HereticType = 1<<6, // goes into Death state when bouncing on floors or ceilings
|
BOUNCE_HereticType = 1<<6, // goes into Death state when bouncing on floors or ceilings
|
||||||
|
|
||||||
BOUNCE_UseSeeSound = 1<<7, // compatibility fallback. This will only be set by
|
BOUNCE_UseSeeSound = 1<<7, // compatibility fallback. This will only be set by
|
||||||
|
@ -412,6 +413,8 @@ enum EBounceFlags
|
||||||
// MBF bouncing is a bit different from other modes as Killough coded many special behavioral cases
|
// MBF bouncing is a bit different from other modes as Killough coded many special behavioral cases
|
||||||
// for them that are not present in ZDoom, so it is necessary to identify it properly.
|
// for them that are not present in ZDoom, so it is necessary to identify it properly.
|
||||||
BOUNCE_MBF = 1<<12, // This in itself is not a valid mode, but replaces MBF's MF_BOUNCE flag.
|
BOUNCE_MBF = 1<<12, // This in itself is not a valid mode, but replaces MBF's MF_BOUNCE flag.
|
||||||
|
BOUNCE_AutoOffFloorOnly = 1<<13, // like BOUNCE_AutoOff, but only on floors
|
||||||
|
BOUNCE_UseBounceState = 1<<14, // Use Bounce[.*] states
|
||||||
|
|
||||||
BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType | BOUNCE_MBF,
|
BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType | BOUNCE_MBF,
|
||||||
|
|
||||||
|
@ -581,15 +584,14 @@ public:
|
||||||
bool AdjustReflectionAngle (AActor *thing, angle_t &angle);
|
bool AdjustReflectionAngle (AActor *thing, angle_t &angle);
|
||||||
|
|
||||||
// Returns true if this actor is within melee range of its target
|
// Returns true if this actor is within melee range of its target
|
||||||
bool CheckMeleeRange ();
|
bool CheckMeleeRange();
|
||||||
|
|
||||||
// BeginPlay: Called just after the actor is created
|
virtual void BeginPlay(); // Called immediately after the actor is created
|
||||||
virtual void BeginPlay ();
|
virtual void PostBeginPlay(); // Called immediately before the actor's first tick
|
||||||
virtual void PostBeginPlay ();
|
virtual void LevelSpawned(); // Called after BeginPlay if this actor was spawned by the world
|
||||||
// LevelSpawned: Called after BeginPlay if this actor was spawned by the world
|
virtual void HandleSpawnFlags(); // Translates SpawnFlags into in-game flags.
|
||||||
virtual void LevelSpawned ();
|
|
||||||
// Translates SpawnFlags into in-game flags.
|
virtual void MarkPrecacheSounds() const; // Marks sounds used by this actor for precaching.
|
||||||
virtual void HandleSpawnFlags ();
|
|
||||||
|
|
||||||
virtual void Activate (AActor *activator);
|
virtual void Activate (AActor *activator);
|
||||||
virtual void Deactivate (AActor *activator);
|
virtual void Deactivate (AActor *activator);
|
||||||
|
@ -597,11 +599,11 @@ public:
|
||||||
virtual void Tick ();
|
virtual void Tick ();
|
||||||
|
|
||||||
// Called when actor dies
|
// Called when actor dies
|
||||||
virtual void Die (AActor *source, AActor *inflictor);
|
virtual void Die (AActor *source, AActor *inflictor, int dmgflags = 0);
|
||||||
|
|
||||||
// Perform some special damage action. Returns the amount of damage to do.
|
// Perform some special damage action. Returns the amount of damage to do.
|
||||||
// Returning -1 signals the damage routine to exit immediately
|
// Returning -1 signals the damage routine to exit immediately
|
||||||
virtual int DoSpecialDamage (AActor *target, int damage);
|
virtual int DoSpecialDamage (AActor *target, int damage, FName damagetype);
|
||||||
|
|
||||||
// Like DoSpecialDamage, but called on the actor receiving the damage.
|
// Like DoSpecialDamage, but called on the actor receiving the damage.
|
||||||
virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype);
|
virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype);
|
||||||
|
@ -656,6 +658,9 @@ public:
|
||||||
// Tosses an item out of the inventory.
|
// Tosses an item out of the inventory.
|
||||||
virtual AInventory *DropInventory (AInventory *item);
|
virtual AInventory *DropInventory (AInventory *item);
|
||||||
|
|
||||||
|
// Removes all items from the inventory.
|
||||||
|
void ClearInventory();
|
||||||
|
|
||||||
// Returns true if this view is considered "local" for the player.
|
// Returns true if this view is considered "local" for the player.
|
||||||
bool CheckLocalView (int playernum) const;
|
bool CheckLocalView (int playernum) const;
|
||||||
|
|
||||||
|
@ -696,7 +701,7 @@ public:
|
||||||
virtual bool Massacre ();
|
virtual bool Massacre ();
|
||||||
|
|
||||||
// Transforms the actor into a finely-ground paste
|
// Transforms the actor into a finely-ground paste
|
||||||
bool Grind(bool items);
|
virtual bool Grind(bool items);
|
||||||
|
|
||||||
// Is the other actor on my team?
|
// Is the other actor on my team?
|
||||||
bool IsTeammate (AActor *other);
|
bool IsTeammate (AActor *other);
|
||||||
|
@ -707,9 +712,20 @@ public:
|
||||||
// Do I hate the other actor?
|
// Do I hate the other actor?
|
||||||
bool IsHostile (AActor *other);
|
bool IsHostile (AActor *other);
|
||||||
|
|
||||||
|
inline bool IsNoClip2() const;
|
||||||
|
|
||||||
// What species am I?
|
// What species am I?
|
||||||
virtual FName GetSpecies();
|
virtual FName GetSpecies();
|
||||||
|
|
||||||
|
fixed_t GetBobOffset(fixed_t ticfrac=0) const
|
||||||
|
{
|
||||||
|
if (!(flags2 & MF2_FLOATBOB))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return finesine[MulScale22(((FloatBobPhase + level.maptime) << FRACBITS) + ticfrac, FINEANGLES) & FINEMASK] * 8;
|
||||||
|
}
|
||||||
|
|
||||||
// Enter the crash state
|
// Enter the crash state
|
||||||
void Crash();
|
void Crash();
|
||||||
|
|
||||||
|
@ -763,6 +779,10 @@ public:
|
||||||
return bloodcls;
|
return bloodcls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void SetFriendPlayer(player_t *player);
|
||||||
|
|
||||||
|
bool IsVisibleToPlayer() const;
|
||||||
|
|
||||||
// Calculate amount of missile damage
|
// Calculate amount of missile damage
|
||||||
virtual int GetMissileDamage(int mask, int add);
|
virtual int GetMissileDamage(int mask, int add);
|
||||||
|
|
||||||
|
@ -773,6 +793,8 @@ public:
|
||||||
const char *GetTag(const char *def = NULL) const;
|
const char *GetTag(const char *def = NULL) const;
|
||||||
void SetTag(const char *def);
|
void SetTag(const char *def);
|
||||||
|
|
||||||
|
// Triggers SECSPAC_Exit/SECSPAC_Enter and related events if oldsec != current sector
|
||||||
|
void CheckSectorTransition(sector_t *oldsec);
|
||||||
|
|
||||||
// info for drawing
|
// info for drawing
|
||||||
// NOTE: The first member variable *must* be x.
|
// NOTE: The first member variable *must* be x.
|
||||||
|
@ -814,6 +836,10 @@ public:
|
||||||
DWORD flags4; // [RH] Even more flags!
|
DWORD flags4; // [RH] Even more flags!
|
||||||
DWORD flags5; // OMG! We need another one.
|
DWORD flags5; // OMG! We need another one.
|
||||||
DWORD flags6; // Shit! Where did all the flags go?
|
DWORD flags6; // Shit! Where did all the flags go?
|
||||||
|
|
||||||
|
// [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
|
||||||
|
DWORD VisibleToTeam;
|
||||||
|
|
||||||
int special1; // Special info
|
int special1; // Special info
|
||||||
int special2; // Special info
|
int special2; // Special info
|
||||||
int health;
|
int health;
|
||||||
|
@ -845,6 +871,8 @@ public:
|
||||||
int special; // special
|
int special; // special
|
||||||
int args[5]; // special arguments
|
int args[5]; // special arguments
|
||||||
|
|
||||||
|
int accuracy, stamina; // [RH] Strife stats -- [XA] moved here for DECORATE/ACS access.
|
||||||
|
|
||||||
AActor *inext, **iprev;// Links to other mobjs in same bucket
|
AActor *inext, **iprev;// Links to other mobjs in same bucket
|
||||||
TObjPtr<AActor> goal; // Monster's goal if not chasing anything
|
TObjPtr<AActor> goal; // Monster's goal if not chasing anything
|
||||||
int waterlevel; // 0=none, 1=feet, 2=waist, 3=eyes
|
int waterlevel; // 0=none, 1=feet, 2=waist, 3=eyes
|
||||||
|
@ -950,6 +978,7 @@ private:
|
||||||
static FSharedStringArena mStringPropertyData;
|
static FSharedStringArena mStringPropertyData;
|
||||||
|
|
||||||
friend class FActorIterator;
|
friend class FActorIterator;
|
||||||
|
friend bool P_IsTIDUsed(int tid);
|
||||||
|
|
||||||
sector_t *LinkToWorldForMapThing ();
|
sector_t *LinkToWorldForMapThing ();
|
||||||
|
|
||||||
|
@ -978,6 +1007,11 @@ public:
|
||||||
return GetClass()->ActorInfo->FindState(2, names, exact);
|
return GetClass()->ActorInfo->FindState(2, names, exact);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FState *FindState(int numnames, FName *names, bool exact = false) const
|
||||||
|
{
|
||||||
|
return GetClass()->ActorInfo->FindState(numnames, names, exact);
|
||||||
|
}
|
||||||
|
|
||||||
bool HasSpecialDeathStates () const;
|
bool HasSpecialDeathStates () const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1044,6 +1078,9 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool P_IsTIDUsed(int tid);
|
||||||
|
int P_FindUniqueTID(int start_tid, int limit);
|
||||||
|
|
||||||
inline AActor *Spawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
|
inline AActor *Spawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
|
||||||
{
|
{
|
||||||
return AActor::StaticSpawn (type, x, y, z, allowreplacement);
|
return AActor::StaticSpawn (type, x, y, z, allowreplacement);
|
||||||
|
|
150
src/am_map.cpp
150
src/am_map.cpp
|
@ -40,6 +40,8 @@
|
||||||
#include "c_bind.h"
|
#include "c_bind.h"
|
||||||
#include "farchive.h"
|
#include "farchive.h"
|
||||||
#include "r_renderer.h"
|
#include "r_renderer.h"
|
||||||
|
#include "r_sky.h"
|
||||||
|
#include "sbar.h"
|
||||||
|
|
||||||
#include "m_cheat.h"
|
#include "m_cheat.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
@ -308,6 +310,7 @@ struct islope_t
|
||||||
static TArray<mline_t> MapArrow;
|
static TArray<mline_t> MapArrow;
|
||||||
static TArray<mline_t> CheatMapArrow;
|
static TArray<mline_t> CheatMapArrow;
|
||||||
static TArray<mline_t> CheatKey;
|
static TArray<mline_t> CheatKey;
|
||||||
|
static TArray<mline_t> EasyKey;
|
||||||
|
|
||||||
#define R (MAPUNIT)
|
#define R (MAPUNIT)
|
||||||
// [RH] Avoid lots of warnings without compiler-specific #pragmas
|
// [RH] Avoid lots of warnings without compiler-specific #pragmas
|
||||||
|
@ -536,10 +539,12 @@ void AM_StaticInit()
|
||||||
MapArrow.Clear();
|
MapArrow.Clear();
|
||||||
CheatMapArrow.Clear();
|
CheatMapArrow.Clear();
|
||||||
CheatKey.Clear();
|
CheatKey.Clear();
|
||||||
|
EasyKey.Clear();
|
||||||
|
|
||||||
if (gameinfo.mMapArrow.IsNotEmpty()) AM_ParseArrow(MapArrow, gameinfo.mMapArrow);
|
if (gameinfo.mMapArrow.IsNotEmpty()) AM_ParseArrow(MapArrow, gameinfo.mMapArrow);
|
||||||
if (gameinfo.mCheatMapArrow.IsNotEmpty()) AM_ParseArrow(CheatMapArrow, gameinfo.mCheatMapArrow);
|
if (gameinfo.mCheatMapArrow.IsNotEmpty()) AM_ParseArrow(CheatMapArrow, gameinfo.mCheatMapArrow);
|
||||||
AM_ParseArrow(CheatKey, "maparrows/key.txt");
|
AM_ParseArrow(CheatKey, "maparrows/key.txt");
|
||||||
|
AM_ParseArrow(EasyKey, "maparrows/ravenkey.txt");
|
||||||
if (MapArrow.Size() == 0) I_FatalError("No automap arrow defined");
|
if (MapArrow.Size() == 0) I_FatalError("No automap arrow defined");
|
||||||
|
|
||||||
char namebuf[9];
|
char namebuf[9];
|
||||||
|
@ -1077,7 +1082,7 @@ void AM_Stop ()
|
||||||
{
|
{
|
||||||
automapactive = false;
|
automapactive = false;
|
||||||
stopped = true;
|
stopped = true;
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
V_SetBorderNeedRefresh();
|
||||||
viewactive = true;
|
viewactive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1155,7 +1160,10 @@ void AM_NewResolution()
|
||||||
|
|
||||||
CCMD (togglemap)
|
CCMD (togglemap)
|
||||||
{
|
{
|
||||||
|
if (gameaction == ga_nothing)
|
||||||
|
{
|
||||||
gameaction = ga_togglemap;
|
gameaction = ga_togglemap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -1173,7 +1181,7 @@ void AM_ToggleMap ()
|
||||||
if (dmflags2 & DF2_NO_AUTOMAP)
|
if (dmflags2 & DF2_NO_AUTOMAP)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SB_state = screen->GetPageCount ();
|
ST_SetNeedRefresh();
|
||||||
if (!automapactive)
|
if (!automapactive)
|
||||||
{
|
{
|
||||||
AM_Start ();
|
AM_Start ();
|
||||||
|
@ -1184,7 +1192,7 @@ void AM_ToggleMap ()
|
||||||
if (am_overlay==1 && viewactive)
|
if (am_overlay==1 && viewactive)
|
||||||
{
|
{
|
||||||
viewactive = false;
|
viewactive = false;
|
||||||
SB_state = screen->GetPageCount ();
|
ST_SetNeedRefresh();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1605,9 +1613,10 @@ void AM_drawSubsectors()
|
||||||
angle_t rotation;
|
angle_t rotation;
|
||||||
sector_t tempsec;
|
sector_t tempsec;
|
||||||
int floorlight, ceilinglight;
|
int floorlight, ceilinglight;
|
||||||
|
fixed_t scalex, scaley;
|
||||||
double originx, originy;
|
double originx, originy;
|
||||||
FDynamicColormap *colormap;
|
FDynamicColormap *colormap;
|
||||||
|
mpoint_t originpt;
|
||||||
|
|
||||||
for (int i = 0; i < numsubsectors; ++i)
|
for (int i = 0; i < numsubsectors; ++i)
|
||||||
{
|
{
|
||||||
|
@ -1636,27 +1645,17 @@ void AM_drawSubsectors()
|
||||||
// For lighting and texture determination
|
// For lighting and texture determination
|
||||||
sector_t *sec = Renderer->FakeFlat (subsectors[i].render_sector, &tempsec, &floorlight, &ceilinglight, false);
|
sector_t *sec = Renderer->FakeFlat (subsectors[i].render_sector, &tempsec, &floorlight, &ceilinglight, false);
|
||||||
// Find texture origin.
|
// Find texture origin.
|
||||||
mpoint_t originpt = { -sec->GetXOffset(sector_t::floor) >> FRACTOMAPBITS,
|
originpt.x = -sec->GetXOffset(sector_t::floor) >> FRACTOMAPBITS;
|
||||||
sec->GetYOffset(sector_t::floor) >> FRACTOMAPBITS };
|
originpt.y = sec->GetYOffset(sector_t::floor) >> FRACTOMAPBITS;
|
||||||
rotation = 0 - sec->GetAngle(sector_t::floor);
|
rotation = 0 - sec->GetAngle(sector_t::floor);
|
||||||
// Apply the floor's rotation to the texture origin.
|
|
||||||
if (rotation != 0)
|
|
||||||
{
|
|
||||||
AM_rotate(&originpt.x, &originpt.y, rotation);
|
|
||||||
}
|
|
||||||
// Apply the automap's rotation to the texture origin.
|
|
||||||
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
|
||||||
{
|
|
||||||
rotation += ANG90 - players[consoleplayer].camera->angle;
|
|
||||||
AM_rotatePoint(&originpt.x, &originpt.y);
|
|
||||||
}
|
|
||||||
originx = f_x + ((originpt.x - m_x) * scale / float(1 << 24));
|
|
||||||
originy = f_y + (f_h - (originpt.y - m_y) * scale / float(1 << 24));
|
|
||||||
// Coloring for the polygon
|
// Coloring for the polygon
|
||||||
colormap = sec->ColorMap;
|
colormap = sec->ColorMap;
|
||||||
|
|
||||||
FTextureID maptex = sec->GetTexture(sector_t::floor);
|
FTextureID maptex = sec->GetTexture(sector_t::floor);
|
||||||
|
|
||||||
|
scalex = sec->GetXScale(sector_t::floor);
|
||||||
|
scaley = sec->GetYScale(sector_t::floor);
|
||||||
|
|
||||||
#ifdef _3DFLOORS
|
#ifdef _3DFLOORS
|
||||||
|
|
||||||
if (sec->e->XFloor.ffloors.Size())
|
if (sec->e->XFloor.ffloors.Size())
|
||||||
|
@ -1670,6 +1669,7 @@ void AM_drawSubsectors()
|
||||||
// (Make the comparison in floating point to avoid overflows and improve performance.)
|
// (Make the comparison in floating point to avoid overflows and improve performance.)
|
||||||
double secx;
|
double secx;
|
||||||
double secy;
|
double secy;
|
||||||
|
double seczb, seczt;
|
||||||
double cmpz = FIXED2DBL(viewz);
|
double cmpz = FIXED2DBL(viewz);
|
||||||
|
|
||||||
if (players[consoleplayer].camera && sec == players[consoleplayer].camera->Sector)
|
if (players[consoleplayer].camera && sec == players[consoleplayer].camera->Sector)
|
||||||
|
@ -1683,17 +1683,33 @@ void AM_drawSubsectors()
|
||||||
secx = FIXED2DBL(sec->soundorg[0]);
|
secx = FIXED2DBL(sec->soundorg[0]);
|
||||||
secy = FIXED2DBL(sec->soundorg[1]);
|
secy = FIXED2DBL(sec->soundorg[1]);
|
||||||
}
|
}
|
||||||
|
seczb = floorplane->ZatPoint(secx, secy);
|
||||||
|
seczt = sec->ceilingplane.ZatPoint(secx, secy);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < sec->e->XFloor.ffloors.Size(); ++i)
|
for (unsigned int i = 0; i < sec->e->XFloor.ffloors.Size(); ++i)
|
||||||
{
|
{
|
||||||
F3DFloor *rover = sec->e->XFloor.ffloors[i];
|
F3DFloor *rover = sec->e->XFloor.ffloors[i];
|
||||||
if (!(rover->flags & FF_EXISTS)) continue;
|
if (!(rover->flags & FF_EXISTS)) continue;
|
||||||
if (rover->flags & FF_FOG) continue;
|
if (rover->flags & FF_FOG) continue;
|
||||||
|
if (!(rover->flags & FF_RENDERPLANES)) continue;
|
||||||
if (rover->alpha == 0) continue;
|
if (rover->alpha == 0) continue;
|
||||||
if (rover->top.plane->ZatPoint(secx, secy) < cmpz)
|
double roverz = rover->top.plane->ZatPoint(secx, secy);
|
||||||
|
// Ignore 3D floors that are above or below the sector itself:
|
||||||
|
// they are hidden. Since 3D floors are sorted top to bottom,
|
||||||
|
// if we get below the sector floor, we can stop.
|
||||||
|
if (roverz > seczt) continue;
|
||||||
|
if (roverz < seczb) break;
|
||||||
|
if (roverz < cmpz)
|
||||||
{
|
{
|
||||||
maptex = *(rover->top.texture);
|
maptex = *(rover->top.texture);
|
||||||
floorplane = rover->top.plane;
|
floorplane = rover->top.plane;
|
||||||
|
sector_t *model = rover->top.model;
|
||||||
|
int selector = (rover->flags & FF_INVERTPLANES) ? sector_t::floor : sector_t::ceiling;
|
||||||
|
rotation = 0 - model->GetAngle(selector);
|
||||||
|
scalex = model->GetXScale(selector);
|
||||||
|
scaley = model->GetYScale(selector);
|
||||||
|
originpt.x = -model->GetXOffset(selector) >> FRACTOMAPBITS;
|
||||||
|
originpt.y = model->GetYOffset(selector) >> FRACTOMAPBITS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1703,6 +1719,24 @@ void AM_drawSubsectors()
|
||||||
colormap = light->extra_colormap;
|
colormap = light->extra_colormap;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (maptex == skyflatnum)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the floor's rotation to the texture origin.
|
||||||
|
if (rotation != 0)
|
||||||
|
{
|
||||||
|
AM_rotate(&originpt.x, &originpt.y, rotation);
|
||||||
|
}
|
||||||
|
// Apply the automap's rotation to the texture origin.
|
||||||
|
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
||||||
|
{
|
||||||
|
rotation += ANG90 - players[consoleplayer].camera->angle;
|
||||||
|
AM_rotatePoint(&originpt.x, &originpt.y);
|
||||||
|
}
|
||||||
|
originx = f_x + ((originpt.x - m_x) * scale / float(1 << 24));
|
||||||
|
originy = f_y + (f_h - (originpt.y - m_y) * scale / float(1 << 24));
|
||||||
|
|
||||||
// If this subsector has not actually been seen yet (because you are cheating
|
// If this subsector has not actually been seen yet (because you are cheating
|
||||||
// to see it on the map), tint and desaturate it.
|
// to see it on the map), tint and desaturate it.
|
||||||
|
@ -1719,16 +1753,20 @@ void AM_drawSubsectors()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the polygon.
|
// Draw the polygon.
|
||||||
|
FTexture *pic = TexMan(maptex);
|
||||||
|
if (pic != NULL && pic->UseType != FTexture::TEX_Null)
|
||||||
|
{
|
||||||
screen->FillSimplePoly(TexMan(maptex),
|
screen->FillSimplePoly(TexMan(maptex),
|
||||||
&points[0], points.Size(),
|
&points[0], points.Size(),
|
||||||
originx, originy,
|
originx, originy,
|
||||||
scale / (FIXED2FLOAT(sec->GetXScale(sector_t::floor)) * float(1 << MAPBITS)),
|
scale / (FIXED2DBL(scalex) * float(1 << MAPBITS)),
|
||||||
scale / (FIXED2FLOAT(sec->GetYScale(sector_t::floor)) * float(1 << MAPBITS)),
|
scale / (FIXED2DBL(scaley) * float(1 << MAPBITS)),
|
||||||
rotation,
|
rotation,
|
||||||
colormap,
|
colormap,
|
||||||
floorlight
|
floorlight
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -1907,6 +1945,7 @@ void AM_drawWalls (bool allmap)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
static mline_t l;
|
static mline_t l;
|
||||||
|
int lock, color;
|
||||||
|
|
||||||
for (i = 0; i < numlines; i++)
|
for (i = 0; i < numlines; i++)
|
||||||
{
|
{
|
||||||
|
@ -1942,8 +1981,16 @@ void AM_drawWalls (bool allmap)
|
||||||
AM_drawMline(&l, SecretWallColor);
|
AM_drawMline(&l, SecretWallColor);
|
||||||
else
|
else
|
||||||
AM_drawMline(&l, WallColor);
|
AM_drawMline(&l, WallColor);
|
||||||
}
|
} else if (lines[i].locknumber > 0) { // [Dusk] specials w/ locknumbers
|
||||||
else if ((lines[i].special == Teleport ||
|
lock = lines[i].locknumber;
|
||||||
|
color = P_GetMapColorForLock(lock);
|
||||||
|
|
||||||
|
AMColor c;
|
||||||
|
if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color));
|
||||||
|
else c = LockedColor;
|
||||||
|
|
||||||
|
AM_drawMline (&l, c);
|
||||||
|
} else if ((lines[i].special == Teleport ||
|
||||||
lines[i].special == Teleport_NoFog ||
|
lines[i].special == Teleport_NoFog ||
|
||||||
lines[i].special == Teleport_ZombieChanger ||
|
lines[i].special == Teleport_ZombieChanger ||
|
||||||
lines[i].special == Teleport_Line) &&
|
lines[i].special == Teleport_Line) &&
|
||||||
|
@ -1969,13 +2016,12 @@ void AM_drawWalls (bool allmap)
|
||||||
if (am_colorset == 0 || am_colorset == 3) // Raven games show door colors
|
if (am_colorset == 0 || am_colorset == 3) // Raven games show door colors
|
||||||
{
|
{
|
||||||
int P_GetMapColorForLock(int lock);
|
int P_GetMapColorForLock(int lock);
|
||||||
int lock;
|
|
||||||
|
|
||||||
if (lines[i].special==Door_LockedRaise || lines[i].special==Door_Animated)
|
if (lines[i].special==Door_LockedRaise || lines[i].special==Door_Animated)
|
||||||
lock=lines[i].args[3];
|
lock=lines[i].args[3];
|
||||||
else lock=lines[i].args[4];
|
else lock=lines[i].args[4];
|
||||||
|
|
||||||
int color = P_GetMapColorForLock(lock);
|
color = P_GetMapColorForLock(lock);
|
||||||
|
|
||||||
AMColor c;
|
AMColor c;
|
||||||
|
|
||||||
|
@ -2240,6 +2286,49 @@ void AM_drawPlayers ()
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
void AM_drawKeys ()
|
||||||
|
{
|
||||||
|
AMColor color;
|
||||||
|
mpoint_t p;
|
||||||
|
angle_t angle;
|
||||||
|
|
||||||
|
TThinkerIterator<AKey> it;
|
||||||
|
AKey *key;
|
||||||
|
|
||||||
|
while ((key = it.Next()) != NULL)
|
||||||
|
{
|
||||||
|
p.x = key->x >> FRACTOMAPBITS;
|
||||||
|
p.y = key->y >> FRACTOMAPBITS;
|
||||||
|
angle = key->angle;
|
||||||
|
|
||||||
|
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
||||||
|
{
|
||||||
|
AM_rotatePoint (&p.x, &p.y);
|
||||||
|
angle += ANG90 - players[consoleplayer].camera->angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
color = ThingColor;
|
||||||
|
if (key->flags & MF_SPECIAL)
|
||||||
|
{
|
||||||
|
// Find the key's own color.
|
||||||
|
// Only works correctly if single-key locks have lower numbers than any-key locks.
|
||||||
|
// That is the case for all default keys, however.
|
||||||
|
int P_GetMapColorForKey (AInventory * key);
|
||||||
|
int c = P_GetMapColorForKey(key);
|
||||||
|
|
||||||
|
if (c >= 0) color.FromRGB(RPART(c), GPART(c), BPART(c));
|
||||||
|
else color = ThingColor_CountItem;
|
||||||
|
AM_drawLineCharacter(&EasyKey[0], EasyKey.Size(), 0, 0, color, p.x, p.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
void AM_drawThings ()
|
void AM_drawThings ()
|
||||||
{
|
{
|
||||||
AMColor color;
|
AMColor color;
|
||||||
|
@ -2278,7 +2367,12 @@ void AM_drawThings ()
|
||||||
// That is the case for all default keys, however.
|
// That is the case for all default keys, however.
|
||||||
if (t->IsKindOf(RUNTIME_CLASS(AKey)))
|
if (t->IsKindOf(RUNTIME_CLASS(AKey)))
|
||||||
{
|
{
|
||||||
if (am_showkeys)
|
if (G_SkillProperty(SKILLP_EasyKey))
|
||||||
|
{
|
||||||
|
// Already drawn by AM_drawKeys(), so don't draw again
|
||||||
|
color.Index = -1;
|
||||||
|
}
|
||||||
|
else if (am_showkeys)
|
||||||
{
|
{
|
||||||
int P_GetMapColorForKey (AInventory * key);
|
int P_GetMapColorForKey (AInventory * key);
|
||||||
int c = P_GetMapColorForKey(static_cast<AKey *>(t));
|
int c = P_GetMapColorForKey(static_cast<AKey *>(t));
|
||||||
|
@ -2500,6 +2594,8 @@ void AM_Drawer ()
|
||||||
|
|
||||||
AM_drawWalls(allmap);
|
AM_drawWalls(allmap);
|
||||||
AM_drawPlayers();
|
AM_drawPlayers();
|
||||||
|
if (G_SkillProperty(SKILLP_EasyKey))
|
||||||
|
AM_drawKeys();
|
||||||
if (am_cheat >= 2 || allthings)
|
if (am_cheat >= 2 || allthings)
|
||||||
AM_drawThings();
|
AM_drawThings();
|
||||||
|
|
||||||
|
|
|
@ -51,15 +51,16 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam)
|
||||||
players[i].mo = NULL;
|
players[i].mo = NULL;
|
||||||
}
|
}
|
||||||
botinfo_t *bot = botinfo;
|
botinfo_t *bot = botinfo;
|
||||||
while (bot && stricmp (players[i].userinfo.netname, bot->name))
|
while (bot && stricmp (players[i].userinfo.GetName(), bot->name))
|
||||||
bot = bot->next;
|
bot = bot->next;
|
||||||
if (bot)
|
if (bot)
|
||||||
{
|
{
|
||||||
bot->inuse = false;
|
bot->inuse = false;
|
||||||
bot->lastteam = keepTeam ? players[i].userinfo.team : TEAM_NONE;
|
bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE;
|
||||||
}
|
}
|
||||||
players[i].~player_t();
|
players[i].~player_t();
|
||||||
::new(&players[i]) player_t;
|
::new(&players[i]) player_t;
|
||||||
|
players[i].userinfo.Reset();
|
||||||
playeringame[i] = false;
|
playeringame[i] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ void FCajunMaster::Main (int buf)
|
||||||
//Check if player should go observer. Or un observe
|
//Check if player should go observer. Or un observe
|
||||||
if (bot_observer && !observer && !netgame)
|
if (bot_observer && !observer && !netgame)
|
||||||
{
|
{
|
||||||
Printf ("%s is now observer\n", players[consoleplayer].userinfo.netname);
|
Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName());
|
||||||
observer = true;
|
observer = true;
|
||||||
players[consoleplayer].mo->UnlinkFromWorld ();
|
players[consoleplayer].mo->UnlinkFromWorld ();
|
||||||
players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY;
|
players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY;
|
||||||
|
@ -149,7 +149,7 @@ void FCajunMaster::Main (int buf)
|
||||||
}
|
}
|
||||||
else if (!bot_observer && observer && !netgame) //Go back
|
else if (!bot_observer && observer && !netgame) //Go back
|
||||||
{
|
{
|
||||||
Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.netname);
|
Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName());
|
||||||
observer = false;
|
observer = false;
|
||||||
players[consoleplayer].mo->UnlinkFromWorld ();
|
players[consoleplayer].mo->UnlinkFromWorld ();
|
||||||
players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY;
|
players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY;
|
||||||
|
@ -218,7 +218,7 @@ void FCajunMaster::End ()
|
||||||
{
|
{
|
||||||
if (deathmatch)
|
if (deathmatch)
|
||||||
{
|
{
|
||||||
getspawned.Push(players[i].userinfo.netname);
|
getspawned.Push(players[i].userinfo.GetName());
|
||||||
}
|
}
|
||||||
CleanBotstuff (&players[i]);
|
CleanBotstuff (&players[i]);
|
||||||
}
|
}
|
||||||
|
@ -353,7 +353,7 @@ void FCajunMaster::DoAddBot (int bnum, char *info)
|
||||||
if (!deathmatch && playerstarts[bnum].type == 0)
|
if (!deathmatch && playerstarts[bnum].type == 0)
|
||||||
{
|
{
|
||||||
Printf ("%s tried to join, but there was no player %d start\n",
|
Printf ("%s tried to join, but there was no player %d start\n",
|
||||||
players[bnum].userinfo.netname, bnum+1);
|
players[bnum].userinfo.GetName(), bnum+1);
|
||||||
ClearPlayer (bnum, false); // Make the bot inactive again
|
ClearPlayer (bnum, false); // Make the bot inactive again
|
||||||
if (botnum > 0)
|
if (botnum > 0)
|
||||||
{
|
{
|
||||||
|
@ -370,9 +370,9 @@ void FCajunMaster::DoAddBot (int bnum, char *info)
|
||||||
botingame[bnum] = true;
|
botingame[bnum] = true;
|
||||||
|
|
||||||
if (teamplay)
|
if (teamplay)
|
||||||
Printf ("%s joined the %s team\n", players[bnum].userinfo.netname,Teams[players[bnum].userinfo.team].GetName ());
|
Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName());
|
||||||
else
|
else
|
||||||
Printf ("%s joined the game\n", players[bnum].userinfo.netname);
|
Printf ("%s joined the game\n", players[bnum].userinfo.GetName());
|
||||||
|
|
||||||
G_DoReborn (bnum, true);
|
G_DoReborn (bnum, true);
|
||||||
if (StatusBar != NULL)
|
if (StatusBar != NULL)
|
||||||
|
@ -474,6 +474,7 @@ static void appendinfo (char *&front, const char *back)
|
||||||
{
|
{
|
||||||
size_t newlen = strlen (back) + 2;
|
size_t newlen = strlen (back) + 2;
|
||||||
newstr = new char[newlen];
|
newstr = new char[newlen];
|
||||||
|
newstr[0] = 0;
|
||||||
}
|
}
|
||||||
strcat (newstr, "\\");
|
strcat (newstr, "\\");
|
||||||
strcat (newstr, back);
|
strcat (newstr, back);
|
||||||
|
|
|
@ -231,7 +231,7 @@ bool AnnounceKill (AActor *killer, AActor *killee)
|
||||||
|
|
||||||
if (killer == NULL)
|
if (killer == NULL)
|
||||||
{ // The world killed the player
|
{ // The world killed the player
|
||||||
if (killee->player->userinfo.gender == GENDER_MALE)
|
if (killee->player->userinfo.GetGender() == GENDER_MALE)
|
||||||
{ // Only males have scrotums to separate
|
{ // Only males have scrotums to separate
|
||||||
choice = &WorldKillSounds[rannum % 3];
|
choice = &WorldKillSounds[rannum % 3];
|
||||||
}
|
}
|
||||||
|
@ -244,11 +244,11 @@ bool AnnounceKill (AActor *killer, AActor *killee)
|
||||||
else if (killer == killee)
|
else if (killer == killee)
|
||||||
{ // The player killed self
|
{ // The player killed self
|
||||||
choice = &SuicideSounds[rannum & 3];
|
choice = &SuicideSounds[rannum & 3];
|
||||||
killerName = killer->player->userinfo.netname;
|
killerName = killer->player->userinfo.GetName();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Another player did the killing
|
{ // Another player did the killing
|
||||||
if (killee->player->userinfo.gender == GENDER_MALE)
|
if (killee->player->userinfo.GetGender() == GENDER_MALE)
|
||||||
{ // Only males can be castrated
|
{ // Only males can be castrated
|
||||||
choice = &KillSounds[rannum % countof(KillSounds)];
|
choice = &KillSounds[rannum % countof(KillSounds)];
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ bool AnnounceKill (AActor *killer, AActor *killee)
|
||||||
{
|
{
|
||||||
choice = &KillSounds[rannum % (countof(KillSounds) - 1)];
|
choice = &KillSounds[rannum % (countof(KillSounds) - 1)];
|
||||||
}
|
}
|
||||||
killerName = killer->player->userinfo.netname;
|
killerName = killer->player->userinfo.GetName();
|
||||||
|
|
||||||
// Blood only plays the announcement sound on the killer's
|
// Blood only plays the announcement sound on the killer's
|
||||||
// computer. I think it sounds neater to also hear it on
|
// computer. I think it sounds neater to also hear it on
|
||||||
|
@ -269,8 +269,8 @@ bool AnnounceKill (AActor *killer, AActor *killee)
|
||||||
{
|
{
|
||||||
char assembled[1024];
|
char assembled[1024];
|
||||||
|
|
||||||
SexMessage (message, assembled, killee->player->userinfo.gender,
|
SexMessage (message, assembled, killee->player->userinfo.GetGender(),
|
||||||
killee->player->userinfo.netname, killerName);
|
killee->player->userinfo.GetName(), killerName);
|
||||||
Printf (PRINT_MEDIUM, "%s\n", assembled);
|
Printf (PRINT_MEDIUM, "%s\n", assembled);
|
||||||
}
|
}
|
||||||
if (playSound)
|
if (playSound)
|
||||||
|
@ -301,8 +301,8 @@ bool AnnounceTelefrag (AActor *killer, AActor *killee)
|
||||||
{
|
{
|
||||||
char assembled[1024];
|
char assembled[1024];
|
||||||
|
|
||||||
SexMessage (message, assembled, killee->player->userinfo.gender,
|
SexMessage (message, assembled, killee->player->userinfo.GetGender(),
|
||||||
killee->player->userinfo.netname, killer->player->userinfo.netname);
|
killee->player->userinfo.GetName(), killer->player->userinfo.GetName());
|
||||||
Printf (PRINT_MEDIUM, "%s\n", assembled);
|
Printf (PRINT_MEDIUM, "%s\n", assembled);
|
||||||
}
|
}
|
||||||
if (killee->CheckLocalView (consoleplayer) ||
|
if (killee->CheckLocalView (consoleplayer) ||
|
||||||
|
|
|
@ -829,6 +829,7 @@ bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds)
|
||||||
bool dclick;
|
bool dclick;
|
||||||
int dclickspot;
|
int dclickspot;
|
||||||
BYTE dclickmask;
|
BYTE dclickmask;
|
||||||
|
unsigned int nowtime;
|
||||||
|
|
||||||
if (ev->type != EV_KeyDown && ev->type != EV_KeyUp)
|
if (ev->type != EV_KeyDown && ev->type != EV_KeyUp)
|
||||||
return false;
|
return false;
|
||||||
|
@ -841,10 +842,11 @@ bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds)
|
||||||
dclick = false;
|
dclick = false;
|
||||||
|
|
||||||
// This used level.time which didn't work outside a level.
|
// This used level.time which didn't work outside a level.
|
||||||
if (DClickTime[ev->data1] > I_MSTime() && ev->type == EV_KeyDown)
|
nowtime = I_MSTime();
|
||||||
|
if (doublebinds != NULL && DClickTime[ev->data1] > nowtime && ev->type == EV_KeyDown)
|
||||||
{
|
{
|
||||||
// Key pressed for a double click
|
// Key pressed for a double click
|
||||||
if (doublebinds != NULL) binding = doublebinds->GetBinding(ev->data1);
|
binding = doublebinds->GetBinding(ev->data1);
|
||||||
DClicked[dclickspot] |= dclickmask;
|
DClicked[dclickspot] |= dclickmask;
|
||||||
dclick = true;
|
dclick = true;
|
||||||
}
|
}
|
||||||
|
@ -853,11 +855,11 @@ bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds)
|
||||||
if (ev->type == EV_KeyDown)
|
if (ev->type == EV_KeyDown)
|
||||||
{ // Key pressed for a normal press
|
{ // Key pressed for a normal press
|
||||||
binding = binds->GetBinding(ev->data1);
|
binding = binds->GetBinding(ev->data1);
|
||||||
DClickTime[ev->data1] = I_MSTime() + 571;
|
DClickTime[ev->data1] = nowtime + 571;
|
||||||
}
|
}
|
||||||
else if (DClicked[dclickspot] & dclickmask)
|
else if (doublebinds != NULL && DClicked[dclickspot] & dclickmask)
|
||||||
{ // Key released from a double click
|
{ // Key released from a double click
|
||||||
if (doublebinds != NULL) binding = doublebinds->GetBinding(ev->data1);
|
binding = doublebinds->GetBinding(ev->data1);
|
||||||
DClicked[dclickspot] &= ~dclickmask;
|
DClicked[dclickspot] &= ~dclickmask;
|
||||||
DClickTime[ev->data1] = 0;
|
DClickTime[ev->data1] = 0;
|
||||||
dclick = true;
|
dclick = true;
|
||||||
|
|
|
@ -175,6 +175,15 @@ CCMD (noclip)
|
||||||
Net_WriteByte (CHT_NOCLIP);
|
Net_WriteByte (CHT_NOCLIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCMD (noclip2)
|
||||||
|
{
|
||||||
|
if (CheckCheatmode())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Net_WriteByte (DEM_GENERICCHEAT);
|
||||||
|
Net_WriteByte (CHT_NOCLIP2);
|
||||||
|
}
|
||||||
|
|
||||||
CCMD (powerup)
|
CCMD (powerup)
|
||||||
{
|
{
|
||||||
if (CheckCheatmode ())
|
if (CheckCheatmode ())
|
||||||
|
@ -245,7 +254,7 @@ CCMD (chase)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Check if we're allowed to use chasecam.
|
// Check if we're allowed to use chasecam.
|
||||||
if (gamestate != GS_LEVEL || (!(dmflags2 & DF2_CHASECAM) && CheckCheatmode ()))
|
if (gamestate != GS_LEVEL || (!(dmflags2 & DF2_CHASECAM) && deathmatch && CheckCheatmode ()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Net_WriteByte (DEM_GENERICCHEAT);
|
Net_WriteByte (DEM_GENERICCHEAT);
|
||||||
|
@ -320,7 +329,7 @@ CCMD (hxvisit)
|
||||||
|
|
||||||
CCMD (changemap)
|
CCMD (changemap)
|
||||||
{
|
{
|
||||||
if (who == NULL)
|
if (who == NULL || !usergame)
|
||||||
{
|
{
|
||||||
Printf ("Use the map command when not in a game.\n");
|
Printf ("Use the map command when not in a game.\n");
|
||||||
return;
|
return;
|
||||||
|
@ -386,7 +395,7 @@ CCMD (take)
|
||||||
|
|
||||||
CCMD (gameversion)
|
CCMD (gameversion)
|
||||||
{
|
{
|
||||||
Printf ("%s : " __DATE__ "\n", DOTVERSIONSTR);
|
Printf ("%s @ %s\nCommit %s", GetVersionString(), GetGitTime(), GetGitHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
CCMD (print)
|
CCMD (print)
|
||||||
|
@ -451,9 +460,9 @@ CCMD (puke)
|
||||||
{
|
{
|
||||||
int argc = argv.argc();
|
int argc = argv.argc();
|
||||||
|
|
||||||
if (argc < 2 || argc > 5)
|
if (argc < 2 || argc > 6)
|
||||||
{
|
{
|
||||||
Printf ("Usage: puke <script> [arg1] [arg2] [arg3]\n");
|
Printf ("Usage: puke <script> [arg1] [arg2] [arg3] [arg4]\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -463,8 +472,8 @@ CCMD (puke)
|
||||||
{ // Script 0 is reserved for Strife support. It is not pukable.
|
{ // Script 0 is reserved for Strife support. It is not pukable.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int arg[3] = { 0, 0, 0 };
|
int arg[4] = { 0, 0, 0, 0 };
|
||||||
int argn = MIN (argc - 2, 3), i;
|
int argn = MIN<int>(argc - 2, countof(arg)), i;
|
||||||
|
|
||||||
for (i = 0; i < argn; ++i)
|
for (i = 0; i < argn; ++i)
|
||||||
{
|
{
|
||||||
|
@ -489,6 +498,44 @@ CCMD (puke)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCMD (pukename)
|
||||||
|
{
|
||||||
|
int argc = argv.argc();
|
||||||
|
|
||||||
|
if (argc < 2 || argc > 7)
|
||||||
|
{
|
||||||
|
Printf ("Usage: pukename \"<script>\" [\"always\"] [arg1] [arg2] [arg3] [arg4]\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool always = false;
|
||||||
|
int argstart = 2;
|
||||||
|
int arg[4] = { 0, 0, 0, 0 };
|
||||||
|
int argn = 0, i;
|
||||||
|
|
||||||
|
if (argc > 2)
|
||||||
|
{
|
||||||
|
if (stricmp(argv[2], "always") == 0)
|
||||||
|
{
|
||||||
|
always = true;
|
||||||
|
argstart = 3;
|
||||||
|
}
|
||||||
|
argn = MIN<int>(argc - argstart, countof(arg));
|
||||||
|
for (i = 0; i < argn; ++i)
|
||||||
|
{
|
||||||
|
arg[i] = atoi(argv[argstart + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Net_WriteByte(DEM_RUNNAMEDSCRIPT);
|
||||||
|
Net_WriteString(argv[1]);
|
||||||
|
Net_WriteByte(argn | (always << 7));
|
||||||
|
for (i = 0; i < argn; ++i)
|
||||||
|
{
|
||||||
|
Net_WriteLong(arg[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CCMD (special)
|
CCMD (special)
|
||||||
{
|
{
|
||||||
int argc = argv.argc();
|
int argc = argv.argc();
|
||||||
|
@ -911,9 +958,16 @@ CCMD(thaw)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CCMD(nextmap)
|
CCMD(nextmap)
|
||||||
{
|
{
|
||||||
char * next=NULL;
|
if (netgame)
|
||||||
|
{
|
||||||
|
Printf ("Use "TEXTCOLOR_BOLD"changemap"TEXTCOLOR_NORMAL" instead. "TEXTCOLOR_BOLD"Nextmap"
|
||||||
|
TEXTCOLOR_NORMAL" is for single-player only.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *next = NULL;
|
||||||
|
|
||||||
if (*level.nextmap) next = level.nextmap;
|
if (*level.nextmap)
|
||||||
|
next = level.nextmap;
|
||||||
|
|
||||||
if (next != NULL && strncmp(next, "enDSeQ", 6))
|
if (next != NULL && strncmp(next, "enDSeQ", 6))
|
||||||
{
|
{
|
||||||
|
@ -932,9 +986,16 @@ CCMD(nextmap)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CCMD(nextsecret)
|
CCMD(nextsecret)
|
||||||
{
|
{
|
||||||
char * next=NULL;
|
if (netgame)
|
||||||
|
{
|
||||||
|
Printf ("Use "TEXTCOLOR_BOLD"changemap"TEXTCOLOR_NORMAL" instead. "TEXTCOLOR_BOLD"Nextsecret"
|
||||||
|
TEXTCOLOR_NORMAL" is for single-player only.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *next = NULL;
|
||||||
|
|
||||||
if (*level.secretmap) next = level.secretmap;
|
if (*level.secretmap)
|
||||||
|
next = level.secretmap;
|
||||||
|
|
||||||
if (next != NULL && strncmp(next, "enDSeQ", 6))
|
if (next != NULL && strncmp(next, "enDSeQ", 6))
|
||||||
{
|
{
|
||||||
|
@ -1050,7 +1111,8 @@ CCMD(secret)
|
||||||
{
|
{
|
||||||
FString levelname;
|
FString levelname;
|
||||||
level_info_t *info = FindLevelInfo(mapname);
|
level_info_t *info = FindLevelInfo(mapname);
|
||||||
levelname.Format("%s - %s\n", mapname, info->LevelName.GetChars());
|
const char *ln = !(info->flags & LEVEL_LOOKUPLEVELNAME)? info->LevelName.GetChars() : GStrings[info->LevelName.GetChars()];
|
||||||
|
levelname.Format("%s - %s\n", mapname, ln);
|
||||||
size_t llen = levelname.Len() - 1;
|
size_t llen = levelname.Len() - 1;
|
||||||
for(size_t ii=0; ii<llen; ii++) levelname += '-';
|
for(size_t ii=0; ii<llen; ii++) levelname += '-';
|
||||||
Printf(TEXTCOLOR_YELLOW"%s\n", levelname.GetChars());
|
Printf(TEXTCOLOR_YELLOW"%s\n", levelname.GetChars());
|
||||||
|
|
|
@ -768,7 +768,7 @@ void AddToConsole (int printlevel, const char *text)
|
||||||
// The line start is outside the buffer.
|
// The line start is outside the buffer.
|
||||||
// Make space for the newly inserted stuff.
|
// Make space for the newly inserted stuff.
|
||||||
size_t movesize = work-linestart;
|
size_t movesize = work-linestart;
|
||||||
memmove(work + movesize, work, strlen(work));
|
memmove(work + movesize, work, strlen(work)+1);
|
||||||
work_p += movesize;
|
work_p += movesize;
|
||||||
linestart = work;
|
linestart = work;
|
||||||
}
|
}
|
||||||
|
@ -1134,7 +1134,7 @@ void C_DrawConsole (bool hw2d)
|
||||||
(viewwindowx || viewwindowy) &&
|
(viewwindowx || viewwindowy) &&
|
||||||
viewactive)
|
viewactive)
|
||||||
{
|
{
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
V_SetBorderNeedRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
oldbottom = ConBottom;
|
oldbottom = ConBottom;
|
||||||
|
@ -1167,9 +1167,9 @@ void C_DrawConsole (bool hw2d)
|
||||||
if (ConBottom >= 12)
|
if (ConBottom >= 12)
|
||||||
{
|
{
|
||||||
screen->DrawText (ConFont, CR_ORANGE, SCREENWIDTH - 8 -
|
screen->DrawText (ConFont, CR_ORANGE, SCREENWIDTH - 8 -
|
||||||
ConFont->StringWidth ("v" DOTVERSIONSTR),
|
ConFont->StringWidth (GetVersionString()),
|
||||||
ConBottom - ConFont->GetHeight() - 4,
|
ConBottom - ConFont->GetHeight() - 4,
|
||||||
"v" DOTVERSIONSTR, TAG_DONE);
|
GetVersionString(), TAG_DONE);
|
||||||
if (TickerMax)
|
if (TickerMax)
|
||||||
{
|
{
|
||||||
char tickstr[256];
|
char tickstr[256];
|
||||||
|
@ -1224,8 +1224,8 @@ void C_DrawConsole (bool hw2d)
|
||||||
{
|
{
|
||||||
screen->Dim (PalEntry ((unsigned char)(player->BlendR*255), (unsigned char)(player->BlendG*255), (unsigned char)(player->BlendB*255)),
|
screen->Dim (PalEntry ((unsigned char)(player->BlendR*255), (unsigned char)(player->BlendG*255), (unsigned char)(player->BlendB*255)),
|
||||||
player->BlendA, 0, ConBottom, screen->GetWidth(), screen->GetHeight() - ConBottom);
|
player->BlendA, 0, ConBottom, screen->GetWidth(), screen->GetHeight() - ConBottom);
|
||||||
SB_state = screen->GetPageCount ();
|
ST_SetNeedRefresh();
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
V_SetBorderNeedRefresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
161
src/c_cvars.cpp
161
src/c_cvars.cpp
|
@ -132,10 +132,10 @@ FBaseCVar::~FBaseCVar ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBaseCVar::ForceSet (UCVarValue value, ECVarType type)
|
void FBaseCVar::ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend)
|
||||||
{
|
{
|
||||||
DoSet (value, type);
|
DoSet (value, type);
|
||||||
if (Flags & CVAR_USERINFO)
|
if ((Flags & CVAR_USERINFO) && !nouserinfosend && !(Flags & CVAR_IGNORE))
|
||||||
D_UserInfoChanged (this);
|
D_UserInfoChanged (this);
|
||||||
if (m_UseCallback)
|
if (m_UseCallback)
|
||||||
Callback ();
|
Callback ();
|
||||||
|
@ -266,7 +266,7 @@ static GUID cGUID;
|
||||||
static char truestr[] = "true";
|
static char truestr[] = "true";
|
||||||
static char falsestr[] = "false";
|
static char falsestr[] = "false";
|
||||||
|
|
||||||
char *FBaseCVar::ToString (UCVarValue value, ECVarType type)
|
const char *FBaseCVar::ToString (UCVarValue value, ECVarType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -849,9 +849,7 @@ UCVarValue FStringCVar::GetFavoriteRepDefault (ECVarType *type) const
|
||||||
|
|
||||||
void FStringCVar::SetGenericRepDefault (UCVarValue value, ECVarType type)
|
void FStringCVar::SetGenericRepDefault (UCVarValue value, ECVarType type)
|
||||||
{
|
{
|
||||||
if (DefaultValue)
|
ReplaceString(&DefaultValue, ToString(value, type));
|
||||||
delete[] DefaultValue;
|
|
||||||
DefaultValue = ToString (value, type);
|
|
||||||
if (Flags & CVAR_ISDEFAULT)
|
if (Flags & CVAR_ISDEFAULT)
|
||||||
{
|
{
|
||||||
SetGenericRep (value, type);
|
SetGenericRep (value, type);
|
||||||
|
@ -1274,52 +1272,56 @@ static int STACK_ARGS sortcvars (const void *a, const void *b)
|
||||||
|
|
||||||
void FilterCompactCVars (TArray<FBaseCVar *> &cvars, DWORD filter)
|
void FilterCompactCVars (TArray<FBaseCVar *> &cvars, DWORD filter)
|
||||||
{
|
{
|
||||||
FBaseCVar *cvar = CVars;
|
// Accumulate all cvars that match the filter flags.
|
||||||
while (cvar)
|
for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->m_Next)
|
||||||
{
|
{
|
||||||
if (cvar->Flags & filter)
|
if ((cvar->Flags & filter) && !(cvar->Flags & CVAR_IGNORE))
|
||||||
cvars.Push (cvar);
|
cvars.Push(cvar);
|
||||||
cvar = cvar->m_Next;
|
|
||||||
}
|
}
|
||||||
if (cvars.Size () > 0)
|
// Now sort them, so they're in a deterministic order and not whatever
|
||||||
|
// order the linker put them in.
|
||||||
|
if (cvars.Size() > 0)
|
||||||
{
|
{
|
||||||
cvars.ShrinkToFit ();
|
qsort(&cvars[0], cvars.Size(), sizeof(FBaseCVar *), sortcvars);
|
||||||
qsort (&cvars[0], cvars.Size(), sizeof(FBaseCVar *), sortcvars);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C_WriteCVars (BYTE **demo_p, DWORD filter, bool compact)
|
void C_WriteCVars (BYTE **demo_p, DWORD filter, bool compact)
|
||||||
{
|
{
|
||||||
FBaseCVar *cvar = CVars;
|
FString dump = C_GetMassCVarString(filter, compact);
|
||||||
BYTE *ptr = *demo_p;
|
size_t dumplen = dump.Len() + 1; // include terminating \0
|
||||||
|
memcpy(*demo_p, dump.GetChars(), dumplen);
|
||||||
|
*demo_p += dumplen;
|
||||||
|
}
|
||||||
|
|
||||||
|
FString C_GetMassCVarString (DWORD filter, bool compact)
|
||||||
|
{
|
||||||
|
FBaseCVar *cvar;
|
||||||
|
FString dump;
|
||||||
|
|
||||||
if (compact)
|
if (compact)
|
||||||
{
|
{
|
||||||
TArray<FBaseCVar *> cvars;
|
TArray<FBaseCVar *> cvars;
|
||||||
ptr += sprintf ((char *)ptr, "\\\\%ux", filter);
|
dump.AppendFormat("\\\\%ux", filter);
|
||||||
FilterCompactCVars (cvars, filter);
|
FilterCompactCVars(cvars, filter);
|
||||||
while (cvars.Pop (cvar))
|
while (cvars.Pop (cvar))
|
||||||
{
|
{
|
||||||
UCVarValue val = cvar->GetGenericRep (CVAR_String);
|
UCVarValue val = cvar->GetGenericRep(CVAR_String);
|
||||||
ptr += sprintf ((char *)ptr, "\\%s", val.String);
|
dump << '\\' << val.String;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cvar = CVars;
|
for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next)
|
||||||
while (cvar)
|
|
||||||
{
|
{
|
||||||
if ((cvar->Flags & filter) && !(cvar->Flags & CVAR_NOSAVE))
|
if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE|CVAR_IGNORE)))
|
||||||
{
|
{
|
||||||
UCVarValue val = cvar->GetGenericRep (CVAR_String);
|
UCVarValue val = cvar->GetGenericRep(CVAR_String);
|
||||||
ptr += sprintf ((char *)ptr, "\\%s\\%s",
|
dump << '\\' << cvar->GetName() << '\\' << val.String;
|
||||||
cvar->GetName (), val.String);
|
|
||||||
}
|
|
||||||
cvar = cvar->m_Next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
*demo_p = ptr + 1;
|
return dump;
|
||||||
}
|
}
|
||||||
|
|
||||||
void C_ReadCVars (BYTE **demo_p)
|
void C_ReadCVars (BYTE **demo_p)
|
||||||
|
@ -1390,58 +1392,42 @@ void C_ReadCVars (BYTE **demo_p)
|
||||||
*demo_p += strlen (*((char **)demo_p)) + 1;
|
*demo_p += strlen (*((char **)demo_p)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct backup_s
|
struct FCVarBackup
|
||||||
{
|
{
|
||||||
char *name, *string;
|
FString Name, String;
|
||||||
} CVarBackups[MAX_DEMOCVARS];
|
};
|
||||||
|
static TArray<FCVarBackup> CVarBackups;
|
||||||
static int numbackedup = 0;
|
|
||||||
|
|
||||||
void C_BackupCVars (void)
|
void C_BackupCVars (void)
|
||||||
{
|
{
|
||||||
struct backup_s *backup = CVarBackups;
|
assert(CVarBackups.Size() == 0);
|
||||||
FBaseCVar *cvar = CVars;
|
CVarBackups.Clear();
|
||||||
|
|
||||||
while (cvar)
|
FCVarBackup backup;
|
||||||
|
|
||||||
|
for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->m_Next)
|
||||||
{
|
{
|
||||||
if ((cvar->Flags & (CVAR_SERVERINFO|CVAR_DEMOSAVE))
|
if ((cvar->Flags & (CVAR_SERVERINFO|CVAR_DEMOSAVE)) && !(cvar->Flags & CVAR_LATCH))
|
||||||
&& !(cvar->Flags & CVAR_LATCH))
|
|
||||||
{
|
{
|
||||||
if (backup == &CVarBackups[MAX_DEMOCVARS])
|
backup.Name = cvar->GetName();
|
||||||
I_Error ("C_BackupDemoCVars: Too many cvars to save (%d)", MAX_DEMOCVARS);
|
backup.String = cvar->GetGenericRep(CVAR_String).String;
|
||||||
backup->name = copystring (cvar->GetName());
|
CVarBackups.Push(backup);
|
||||||
backup->string = copystring (cvar->GetGenericRep (CVAR_String).String);
|
|
||||||
backup++;
|
|
||||||
}
|
}
|
||||||
cvar = cvar->m_Next;
|
|
||||||
}
|
}
|
||||||
numbackedup = int(backup - CVarBackups);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void C_RestoreCVars (void)
|
void C_RestoreCVars (void)
|
||||||
{
|
{
|
||||||
struct backup_s *backup = CVarBackups;
|
for (unsigned int i = 0; i < CVarBackups.Size(); ++i)
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = numbackedup; i; i--, backup++)
|
|
||||||
{
|
{
|
||||||
cvar_set (backup->name, backup->string);
|
cvar_set(CVarBackups[i].Name, CVarBackups[i].String);
|
||||||
}
|
}
|
||||||
C_ForgetCVars();
|
C_ForgetCVars();
|
||||||
}
|
}
|
||||||
|
|
||||||
void C_ForgetCVars (void)
|
void C_ForgetCVars (void)
|
||||||
{
|
{
|
||||||
struct backup_s *backup = CVarBackups;
|
CVarBackups.Clear();
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = numbackedup; i; i--, backup++)
|
|
||||||
{
|
|
||||||
delete[] backup->name;
|
|
||||||
delete[] backup->string;
|
|
||||||
backup->name = backup->string = NULL;
|
|
||||||
}
|
|
||||||
numbackedup = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev)
|
FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev)
|
||||||
|
@ -1489,6 +1475,30 @@ FBaseCVar *FindCVarSub (const char *var_name, int namelen)
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// C_CreateCVar
|
||||||
|
//
|
||||||
|
// Create a new cvar with the specified name and type. It should not already
|
||||||
|
// exist.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, DWORD flags)
|
||||||
|
{
|
||||||
|
assert(FindCVar(var_name, NULL) == NULL);
|
||||||
|
flags |= CVAR_AUTO;
|
||||||
|
switch (var_type)
|
||||||
|
{
|
||||||
|
case CVAR_Bool: return new FBoolCVar(var_name, 0, flags);
|
||||||
|
case CVAR_Int: return new FIntCVar(var_name, 0, flags);
|
||||||
|
case CVAR_Float: return new FFloatCVar(var_name, 0, flags);
|
||||||
|
case CVAR_String: return new FStringCVar(var_name, NULL, flags);
|
||||||
|
case CVAR_Color: return new FColorCVar(var_name, 0, flags);
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UnlatchCVars (void)
|
void UnlatchCVars (void)
|
||||||
{
|
{
|
||||||
FLatchedValue var;
|
FLatchedValue var;
|
||||||
|
@ -1522,33 +1532,14 @@ void C_SetCVarsToDefaults (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C_ArchiveCVars (FConfigFile *f, int type)
|
void C_ArchiveCVars (FConfigFile *f, uint32 filter)
|
||||||
{
|
{
|
||||||
// type 0: Game-specific cvars
|
|
||||||
// type 1: Global cvars
|
|
||||||
// type 2: Unknown cvars
|
|
||||||
// type 3: Unknown global cvars
|
|
||||||
// type 4: User info cvars
|
|
||||||
// type 5: Server info cvars
|
|
||||||
static const DWORD filters[6] =
|
|
||||||
{
|
|
||||||
CVAR_ARCHIVE,
|
|
||||||
CVAR_ARCHIVE|CVAR_GLOBALCONFIG,
|
|
||||||
CVAR_ARCHIVE|CVAR_AUTO,
|
|
||||||
CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_AUTO,
|
|
||||||
CVAR_ARCHIVE|CVAR_USERINFO,
|
|
||||||
CVAR_ARCHIVE|CVAR_SERVERINFO
|
|
||||||
};
|
|
||||||
|
|
||||||
FBaseCVar *cvar = CVars;
|
FBaseCVar *cvar = CVars;
|
||||||
DWORD filter;
|
|
||||||
|
|
||||||
filter = filters[type];
|
|
||||||
|
|
||||||
while (cvar)
|
while (cvar)
|
||||||
{
|
{
|
||||||
if ((cvar->Flags &
|
if ((cvar->Flags &
|
||||||
(CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_AUTO|CVAR_USERINFO|CVAR_SERVERINFO|CVAR_NOSAVE))
|
(CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_MOD|CVAR_AUTO|CVAR_USERINFO|CVAR_SERVERINFO|CVAR_NOSAVE))
|
||||||
== filter)
|
== filter)
|
||||||
{
|
{
|
||||||
UCVarValue val;
|
UCVarValue val;
|
||||||
|
@ -1679,7 +1670,7 @@ void FBaseCVar::ListVars (const char *filter, bool plain)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
++count;
|
++count;
|
||||||
Printf ("%c%c%c %s : :%s\n",
|
Printf ("%c%c%c%c%c %s = %s\n",
|
||||||
flags & CVAR_ARCHIVE ? 'A' : ' ',
|
flags & CVAR_ARCHIVE ? 'A' : ' ',
|
||||||
flags & CVAR_USERINFO ? 'U' :
|
flags & CVAR_USERINFO ? 'U' :
|
||||||
flags & CVAR_SERVERINFO ? 'S' :
|
flags & CVAR_SERVERINFO ? 'S' :
|
||||||
|
@ -1687,6 +1678,8 @@ void FBaseCVar::ListVars (const char *filter, bool plain)
|
||||||
flags & CVAR_NOSET ? '-' :
|
flags & CVAR_NOSET ? '-' :
|
||||||
flags & CVAR_LATCH ? 'L' :
|
flags & CVAR_LATCH ? 'L' :
|
||||||
flags & CVAR_UNSETTABLE ? '*' : ' ',
|
flags & CVAR_UNSETTABLE ? '*' : ' ',
|
||||||
|
flags & CVAR_MOD ? 'M' : ' ',
|
||||||
|
flags & CVAR_IGNORE ? 'X' : ' ',
|
||||||
var->GetName(),
|
var->GetName(),
|
||||||
var->GetGenericRep (CVAR_String).String);
|
var->GetGenericRep (CVAR_String).String);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ enum
|
||||||
CVAR_GLOBALCONFIG = 1024, // cvar is saved to global config section
|
CVAR_GLOBALCONFIG = 1024, // cvar is saved to global config section
|
||||||
CVAR_VIDEOCONFIG = 2048, // cvar is saved to video config section (not implemented)
|
CVAR_VIDEOCONFIG = 2048, // cvar is saved to video config section (not implemented)
|
||||||
CVAR_NOSAVE = 4096, // when used with CVAR_SERVERINFO, do not save var to savegame
|
CVAR_NOSAVE = 4096, // when used with CVAR_SERVERINFO, do not save var to savegame
|
||||||
|
CVAR_MOD = 8192, // cvar was defined by a mod
|
||||||
|
CVAR_IGNORE = 16384,// do not send cvar across the network/inaccesible from ACS (dummy mod cvar)
|
||||||
};
|
};
|
||||||
|
|
||||||
union UCVarValue
|
union UCVarValue
|
||||||
|
@ -68,7 +70,7 @@ union UCVarValue
|
||||||
bool Bool;
|
bool Bool;
|
||||||
int Int;
|
int Int;
|
||||||
float Float;
|
float Float;
|
||||||
char *String;
|
const char *String;
|
||||||
const GUID *pGUID;
|
const GUID *pGUID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,9 +98,10 @@ public:
|
||||||
|
|
||||||
inline const char *GetName () const { return Name; }
|
inline const char *GetName () const { return Name; }
|
||||||
inline uint32 GetFlags () const { return Flags; }
|
inline uint32 GetFlags () const { return Flags; }
|
||||||
|
inline FBaseCVar *GetNext() const { return m_Next; }
|
||||||
|
|
||||||
void CmdSet (const char *newval);
|
void CmdSet (const char *newval);
|
||||||
void ForceSet (UCVarValue value, ECVarType type);
|
void ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend=false);
|
||||||
void SetGenericRep (UCVarValue value, ECVarType type);
|
void SetGenericRep (UCVarValue value, ECVarType type);
|
||||||
void ResetToDefault ();
|
void ResetToDefault ();
|
||||||
void SetArchiveBit () { Flags |= CVAR_ARCHIVE; }
|
void SetArchiveBit () { Flags |= CVAR_ARCHIVE; }
|
||||||
|
@ -129,7 +132,7 @@ protected:
|
||||||
static bool ToBool (UCVarValue value, ECVarType type);
|
static bool ToBool (UCVarValue value, ECVarType type);
|
||||||
static int ToInt (UCVarValue value, ECVarType type);
|
static int ToInt (UCVarValue value, ECVarType type);
|
||||||
static float ToFloat (UCVarValue value, ECVarType type);
|
static float ToFloat (UCVarValue value, ECVarType type);
|
||||||
static char *ToString (UCVarValue value, ECVarType type);
|
static const char *ToString (UCVarValue value, ECVarType type);
|
||||||
static const GUID *ToGUID (UCVarValue value, ECVarType type);
|
static const GUID *ToGUID (UCVarValue value, ECVarType type);
|
||||||
static UCVarValue FromBool (bool value, ECVarType type);
|
static UCVarValue FromBool (bool value, ECVarType type);
|
||||||
static UCVarValue FromInt (int value, ECVarType type);
|
static UCVarValue FromInt (int value, ECVarType type);
|
||||||
|
@ -150,18 +153,22 @@ private:
|
||||||
static bool m_UseCallback;
|
static bool m_UseCallback;
|
||||||
static bool m_DoNoSet;
|
static bool m_DoNoSet;
|
||||||
|
|
||||||
friend void C_WriteCVars (BYTE **demo_p, uint32 filter, bool compact);
|
friend FString C_GetMassCVarString (uint32 filter, bool compact);
|
||||||
friend void C_ReadCVars (BYTE **demo_p);
|
friend void C_ReadCVars (BYTE **demo_p);
|
||||||
friend void C_BackupCVars (void);
|
friend void C_BackupCVars (void);
|
||||||
friend FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev);
|
friend FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev);
|
||||||
friend FBaseCVar *FindCVarSub (const char *var_name, int namelen);
|
friend FBaseCVar *FindCVarSub (const char *var_name, int namelen);
|
||||||
friend void UnlatchCVars (void);
|
friend void UnlatchCVars (void);
|
||||||
friend void C_ArchiveCVars (FConfigFile *f, int type);
|
friend void C_ArchiveCVars (FConfigFile *f, uint32 filter);
|
||||||
friend void C_SetCVarsToDefaults (void);
|
friend void C_SetCVarsToDefaults (void);
|
||||||
friend void FilterCompactCVars (TArray<FBaseCVar *> &cvars, uint32 filter);
|
friend void FilterCompactCVars (TArray<FBaseCVar *> &cvars, uint32 filter);
|
||||||
friend void C_DeinitConsole();
|
friend void C_DeinitConsole();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns a string with all cvars whose flags match filter. In compact mode,
|
||||||
|
// the cvar names are omitted to save space.
|
||||||
|
FString C_GetMassCVarString (uint32 filter, bool compact=false);
|
||||||
|
|
||||||
// Writes all cvars that could effect demo sync to *demo_p. These are
|
// Writes all cvars that could effect demo sync to *demo_p. These are
|
||||||
// cvars that have either CVAR_SERVERINFO or CVAR_DEMOSAVE set.
|
// cvars that have either CVAR_SERVERINFO or CVAR_DEMOSAVE set.
|
||||||
void C_WriteCVars (BYTE **demo_p, uint32 filter, bool compact=false);
|
void C_WriteCVars (BYTE **demo_p, uint32 filter, bool compact=false);
|
||||||
|
@ -177,11 +184,14 @@ void C_BackupCVars (void);
|
||||||
FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev);
|
FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev);
|
||||||
FBaseCVar *FindCVarSub (const char *var_name, int namelen);
|
FBaseCVar *FindCVarSub (const char *var_name, int namelen);
|
||||||
|
|
||||||
|
// Create a new cvar with the specified name and type
|
||||||
|
FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, DWORD flags);
|
||||||
|
|
||||||
// Called from G_InitNew()
|
// Called from G_InitNew()
|
||||||
void UnlatchCVars (void);
|
void UnlatchCVars (void);
|
||||||
|
|
||||||
// archive cvars to FILE f
|
// archive cvars to FILE f
|
||||||
void C_ArchiveCVars (FConfigFile *f, int type);
|
void C_ArchiveCVars (FConfigFile *f, uint32 filter);
|
||||||
|
|
||||||
// initialize cvars to default values after they are created
|
// initialize cvars to default values after they are created
|
||||||
void C_SetCVarsToDefaults (void);
|
void C_SetCVarsToDefaults (void);
|
||||||
|
@ -404,10 +414,6 @@ inline FBaseCVar *cvar_forceset (const char *var_name, const BYTE *value) { retu
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Maximum number of cvars that can be saved across a demo. If you need
|
|
||||||
// to save more, bump this up.
|
|
||||||
#define MAX_DEMOCVARS 32
|
|
||||||
|
|
||||||
// Restore demo cvars. Called after demo playback to restore all cvars
|
// Restore demo cvars. Called after demo playback to restore all cvars
|
||||||
// that might possibly have been changed during the course of demo playback.
|
// that might possibly have been changed during the course of demo playback.
|
||||||
void C_RestoreCVars (void);
|
void C_RestoreCVars (void);
|
||||||
|
@ -425,5 +431,6 @@ void C_ForgetCVars (void);
|
||||||
|
|
||||||
#define EXTERN_CVAR(type,name) extern F##type##CVar name;
|
#define EXTERN_CVAR(type,name) extern F##type##CVar name;
|
||||||
|
|
||||||
|
extern FBaseCVar *CVars;
|
||||||
|
|
||||||
#endif //__C_CVARS_H__
|
#endif //__C_CVARS_H__
|
||||||
|
|
|
@ -1019,32 +1019,7 @@ FConsoleAlias::~FConsoleAlias ()
|
||||||
m_Command[1] = m_Command[0] = FString();
|
m_Command[1] = m_Command[0] = FString();
|
||||||
}
|
}
|
||||||
|
|
||||||
FString BuildString (int argc, char **argv)
|
// Given an argument vector, reconstitute the command line it could have been produced from.
|
||||||
{
|
|
||||||
if (argc == 1)
|
|
||||||
{
|
|
||||||
return *argv;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FString buf;
|
|
||||||
int arg;
|
|
||||||
|
|
||||||
for (arg = 0; arg < argc; arg++)
|
|
||||||
{
|
|
||||||
if (strchr (argv[arg], ' '))
|
|
||||||
{
|
|
||||||
buf.AppendFormat ("\"%s\" ", argv[arg]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buf.AppendFormat ("%s ", argv[arg]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FString BuildString (int argc, FString *argv)
|
FString BuildString (int argc, FString *argv)
|
||||||
{
|
{
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
|
@ -1058,8 +1033,23 @@ FString BuildString (int argc, FString *argv)
|
||||||
|
|
||||||
for (arg = 0; arg < argc; arg++)
|
for (arg = 0; arg < argc; arg++)
|
||||||
{
|
{
|
||||||
if (strchr (argv[arg], ' '))
|
if (strchr(argv[arg], '"'))
|
||||||
|
{ // If it contains one or more quotes, we need to escape them.
|
||||||
|
buf << '"';
|
||||||
|
long substr_start = 0, quotepos;
|
||||||
|
while ((quotepos = argv[arg].IndexOf('"', substr_start)) >= 0)
|
||||||
{
|
{
|
||||||
|
if (substr_start < quotepos)
|
||||||
|
{
|
||||||
|
buf << argv[arg].Mid(substr_start, quotepos - substr_start);
|
||||||
|
}
|
||||||
|
buf << "\\\"";
|
||||||
|
substr_start = quotepos + 1;
|
||||||
|
}
|
||||||
|
buf << argv[arg].Mid(substr_start) << "\" ";
|
||||||
|
}
|
||||||
|
else if (strchr(argv[arg], ' '))
|
||||||
|
{ // If it contains a space, it needs to be quoted.
|
||||||
buf << '"' << argv[arg] << "\" ";
|
buf << '"' << argv[arg] << "\" ";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -61,7 +61,6 @@ void C_SetAlias (const char *name, const char *cmd);
|
||||||
void C_ClearAliases ();
|
void C_ClearAliases ();
|
||||||
|
|
||||||
// build a single string out of multiple strings
|
// build a single string out of multiple strings
|
||||||
FString BuildString (int argc, char **argv);
|
|
||||||
FString BuildString (int argc, FString *argv);
|
FString BuildString (int argc, FString *argv);
|
||||||
|
|
||||||
// Class that can parse command lines
|
// Class that can parse command lines
|
||||||
|
|
|
@ -537,6 +537,7 @@ void CreatePath(const char *fn)
|
||||||
}
|
}
|
||||||
if (mkdir(copy, 0755) == -1)
|
if (mkdir(copy, 0755) == -1)
|
||||||
{ // failed
|
{ // failed
|
||||||
|
free(copy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
exists: if (p != NULL)
|
exists: if (p != NULL)
|
||||||
|
@ -550,7 +551,7 @@ exists: if (p != NULL)
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// strbin1 -- In-place version
|
// strbin -- In-place version
|
||||||
//
|
//
|
||||||
// [RH] Replaces the escape sequences in a string with actual escaped characters.
|
// [RH] Replaces the escape sequences in a string with actual escaped characters.
|
||||||
// This operation is done in-place. The result is the new length of the string.
|
// This operation is done in-place. The result is the new length of the string.
|
||||||
|
@ -600,18 +601,20 @@ int strbin (char *str)
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
c = 0;
|
c = 0;
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
p++;
|
p++;
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
c <<= 4;
|
|
||||||
if (*p >= '0' && *p <= '9')
|
if (*p >= '0' && *p <= '9')
|
||||||
c += *p-'0';
|
c = (c << 4) + *p-'0';
|
||||||
else if (*p >= 'a' && *p <= 'f')
|
else if (*p >= 'a' && *p <= 'f')
|
||||||
c += 10 + *p-'a';
|
c = (c << 4) + 10 + *p-'a';
|
||||||
else if (*p >= 'A' && *p <= 'F')
|
else if (*p >= 'A' && *p <= 'F')
|
||||||
c += 10 + *p-'A';
|
c = (c << 4) + 10 + *p-'A';
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
p--;
|
||||||
break;
|
break;
|
||||||
p++;
|
}
|
||||||
}
|
}
|
||||||
*str++ = c;
|
*str++ = c;
|
||||||
break;
|
break;
|
||||||
|
@ -650,7 +653,7 @@ int strbin (char *str)
|
||||||
// strbin1 -- String-creating version
|
// strbin1 -- String-creating version
|
||||||
//
|
//
|
||||||
// [RH] Replaces the escape sequences in a string with actual escaped characters.
|
// [RH] Replaces the escape sequences in a string with actual escaped characters.
|
||||||
// This operation is done in-place.
|
// The result is a new string.
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
@ -698,18 +701,20 @@ FString strbin1 (const char *start)
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
c = 0;
|
c = 0;
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
p++;
|
p++;
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
c <<= 4;
|
|
||||||
if (*p >= '0' && *p <= '9')
|
if (*p >= '0' && *p <= '9')
|
||||||
c += *p-'0';
|
c = (c << 4) + *p-'0';
|
||||||
else if (*p >= 'a' && *p <= 'f')
|
else if (*p >= 'a' && *p <= 'f')
|
||||||
c += 10 + *p-'a';
|
c = (c << 4) + 10 + *p-'a';
|
||||||
else if (*p >= 'A' && *p <= 'F')
|
else if (*p >= 'A' && *p <= 'F')
|
||||||
c += 10 + *p-'A';
|
c = (c << 4) + 10 + *p-'A';
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
p--;
|
||||||
break;
|
break;
|
||||||
p++;
|
}
|
||||||
}
|
}
|
||||||
result << c;
|
result << c;
|
||||||
break;
|
break;
|
||||||
|
@ -751,7 +756,7 @@ FString strbin1 (const char *start)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void CleanseString(char *str)
|
char *CleanseString(char *str)
|
||||||
{
|
{
|
||||||
char *escape = strrchr(str, TEXTCOLOR_ESCAPE);
|
char *escape = strrchr(str, TEXTCOLOR_ESCAPE);
|
||||||
if (escape != NULL)
|
if (escape != NULL)
|
||||||
|
@ -769,6 +774,7 @@ void CleanseString(char *str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -47,7 +47,7 @@ const char *myasctime ();
|
||||||
|
|
||||||
int strbin (char *str);
|
int strbin (char *str);
|
||||||
FString strbin1 (const char *start);
|
FString strbin1 (const char *start);
|
||||||
void CleanseString (char *str);
|
char *CleanseString (char *str);
|
||||||
|
|
||||||
void CreatePath(const char * fn);
|
void CreatePath(const char * fn);
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
|
#include "w_wad.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -58,8 +59,15 @@
|
||||||
struct FCompatOption
|
struct FCompatOption
|
||||||
{
|
{
|
||||||
const char *Name;
|
const char *Name;
|
||||||
int CompatFlags;
|
DWORD CompatFlags;
|
||||||
int BCompatFlags;
|
int WhichSlot;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SLOT_COMPAT,
|
||||||
|
SLOT_COMPAT2,
|
||||||
|
SLOT_BCOMPAT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -67,7 +75,12 @@ enum
|
||||||
CP_END,
|
CP_END,
|
||||||
CP_CLEARFLAGS,
|
CP_CLEARFLAGS,
|
||||||
CP_SETFLAGS,
|
CP_SETFLAGS,
|
||||||
CP_SETSPECIAL
|
CP_SETSPECIAL,
|
||||||
|
CP_CLEARSPECIAL,
|
||||||
|
CP_SETACTIVATION,
|
||||||
|
CP_SECTORFLOOROFFSET,
|
||||||
|
CP_SETWALLYSCALE,
|
||||||
|
CP_SETTHINGZ,
|
||||||
};
|
};
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
@ -77,6 +90,7 @@ enum
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
extern TArray<FMapThing> MapThingsConverted;
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
@ -86,44 +100,58 @@ TMap<FMD5Holder, FCompatValues, FMD5HashTraits> BCompatMap;
|
||||||
|
|
||||||
static FCompatOption Options[] =
|
static FCompatOption Options[] =
|
||||||
{
|
{
|
||||||
{ "setslopeoverflow", 0, BCOMPATF_SETSLOPEOVERFLOW },
|
{ "setslopeoverflow", BCOMPATF_SETSLOPEOVERFLOW, SLOT_BCOMPAT },
|
||||||
{ "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED },
|
{ "resetplayerspeed", BCOMPATF_RESETPLAYERSPEED, SLOT_BCOMPAT },
|
||||||
{ "vileghosts", 0, BCOMPATF_VILEGHOSTS },
|
{ "vileghosts", BCOMPATF_VILEGHOSTS, SLOT_BCOMPAT },
|
||||||
{ "ignoreteleporttags", 0, BCOMPATF_BADTELEPORTERS },
|
{ "ignoreteleporttags", BCOMPATF_BADTELEPORTERS, SLOT_BCOMPAT },
|
||||||
|
{ "rebuildnodes", BCOMPATF_REBUILDNODES, SLOT_BCOMPAT },
|
||||||
|
|
||||||
// list copied from g_mapinfo.cpp
|
// list copied from g_mapinfo.cpp
|
||||||
{ "shorttex", COMPATF_SHORTTEX, 0 },
|
{ "shorttex", COMPATF_SHORTTEX, SLOT_COMPAT },
|
||||||
{ "stairs", COMPATF_STAIRINDEX, 0 },
|
{ "stairs", COMPATF_STAIRINDEX, SLOT_COMPAT },
|
||||||
{ "limitpain", COMPATF_LIMITPAIN, 0 },
|
{ "limitpain", COMPATF_LIMITPAIN, SLOT_COMPAT },
|
||||||
{ "nopassover", COMPATF_NO_PASSMOBJ, 0 },
|
{ "nopassover", COMPATF_NO_PASSMOBJ, SLOT_COMPAT },
|
||||||
{ "notossdrops", COMPATF_NOTOSSDROPS, 0 },
|
{ "notossdrops", COMPATF_NOTOSSDROPS, SLOT_COMPAT },
|
||||||
{ "useblocking", COMPATF_USEBLOCKING, 0 },
|
{ "useblocking", COMPATF_USEBLOCKING, SLOT_COMPAT },
|
||||||
{ "nodoorlight", COMPATF_NODOORLIGHT, 0 },
|
{ "nodoorlight", COMPATF_NODOORLIGHT, SLOT_COMPAT },
|
||||||
{ "ravenscroll", COMPATF_RAVENSCROLL, 0 },
|
{ "ravenscroll", COMPATF_RAVENSCROLL, SLOT_COMPAT },
|
||||||
{ "soundtarget", COMPATF_SOUNDTARGET, 0 },
|
{ "soundtarget", COMPATF_SOUNDTARGET, SLOT_COMPAT },
|
||||||
{ "dehhealth", COMPATF_DEHHEALTH, 0 },
|
{ "dehhealth", COMPATF_DEHHEALTH, SLOT_COMPAT },
|
||||||
{ "trace", COMPATF_TRACE, 0 },
|
{ "trace", COMPATF_TRACE, SLOT_COMPAT },
|
||||||
{ "dropoff", COMPATF_DROPOFF, 0 },
|
{ "dropoff", COMPATF_DROPOFF, SLOT_COMPAT },
|
||||||
{ "boomscroll", COMPATF_BOOMSCROLL, 0 },
|
{ "boomscroll", COMPATF_BOOMSCROLL, SLOT_COMPAT },
|
||||||
{ "invisibility", COMPATF_INVISIBILITY, 0 },
|
{ "invisibility", COMPATF_INVISIBILITY, SLOT_COMPAT },
|
||||||
{ "silentinstantfloors", COMPATF_SILENT_INSTANT_FLOORS, 0 },
|
{ "silentinstantfloors", COMPATF_SILENT_INSTANT_FLOORS, SLOT_COMPAT },
|
||||||
{ "sectorsounds", COMPATF_SECTORSOUNDS, 0 },
|
{ "sectorsounds", COMPATF_SECTORSOUNDS, SLOT_COMPAT },
|
||||||
{ "missileclip", COMPATF_MISSILECLIP, 0 },
|
{ "missileclip", COMPATF_MISSILECLIP, SLOT_COMPAT },
|
||||||
{ "crossdropoff", COMPATF_CROSSDROPOFF, 0 },
|
{ "crossdropoff", COMPATF_CROSSDROPOFF, SLOT_COMPAT },
|
||||||
{ "wallrun", COMPATF_WALLRUN, 0 }, // [GZ] Added for CC MAP29
|
{ "wallrun", COMPATF_WALLRUN, SLOT_COMPAT }, // [GZ] Added for CC MAP29
|
||||||
{ "anybossdeath", COMPATF_ANYBOSSDEATH, 0}, // [GZ] Added for UAC_DEAD
|
{ "anybossdeath", COMPATF_ANYBOSSDEATH, SLOT_COMPAT },// [GZ] Added for UAC_DEAD
|
||||||
{ "mushroom", COMPATF_MUSHROOM, 0},
|
{ "mushroom", COMPATF_MUSHROOM, SLOT_COMPAT },
|
||||||
{ "mbfmonstermove", COMPATF_MBFMONSTERMOVE, 0 },
|
{ "mbfmonstermove", COMPATF_MBFMONSTERMOVE, SLOT_COMPAT },
|
||||||
{ "corpsegibs", COMPATF_CORPSEGIBS, 0 },
|
{ "corpsegibs", COMPATF_CORPSEGIBS, SLOT_COMPAT },
|
||||||
{ "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 },
|
{ "noblockfriends", COMPATF_NOBLOCKFRIENDS, SLOT_COMPAT },
|
||||||
{ "spritesort", COMPATF_SPRITESORT, 0 },
|
{ "spritesort", COMPATF_SPRITESORT, SLOT_COMPAT },
|
||||||
{ "hitscan", COMPATF_HITSCAN, 0 },
|
{ "hitscan", COMPATF_HITSCAN, SLOT_COMPAT },
|
||||||
{ "lightlevel", COMPATF_LIGHT, 0 },
|
{ "lightlevel", COMPATF_LIGHT, SLOT_COMPAT },
|
||||||
{ "polyobj", COMPATF_POLYOBJ, 0 },
|
{ "polyobj", COMPATF_POLYOBJ, SLOT_COMPAT },
|
||||||
{ "maskedmidtex", COMPATF_MASKEDMIDTEX, 0 },
|
{ "maskedmidtex", COMPATF_MASKEDMIDTEX, SLOT_COMPAT },
|
||||||
|
{ "badangles", COMPATF2_BADANGLES, SLOT_COMPAT2 },
|
||||||
|
{ "floormove", COMPATF2_FLOORMOVE, SLOT_COMPAT2 },
|
||||||
|
|
||||||
{ NULL, 0, 0 }
|
{ NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *const LineSides[] =
|
||||||
|
{
|
||||||
|
"Front", "Back", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const WallTiers[] =
|
||||||
|
{
|
||||||
|
"Top", "Mid", "Bot", NULL
|
||||||
|
};
|
||||||
|
|
||||||
static TArray<int> CompatParams;
|
static TArray<int> CompatParams;
|
||||||
static int ii_compatparams;
|
static int ii_compatparams;
|
||||||
|
|
||||||
|
@ -189,15 +217,13 @@ void ParseCompatibility()
|
||||||
md5array.Push(md5);
|
md5array.Push(md5);
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
} while (!sc.Compare("{"));
|
} while (!sc.Compare("{"));
|
||||||
flags.CompatFlags = 0;
|
memset(flags.CompatFlags, 0, sizeof(flags.CompatFlags));
|
||||||
flags.BCompatFlags = 0;
|
|
||||||
flags.ExtCommandIndex = ~0u;
|
flags.ExtCommandIndex = ~0u;
|
||||||
while (sc.GetString())
|
while (sc.GetString())
|
||||||
{
|
{
|
||||||
if ((i = sc.MatchString(&Options[0].Name, sizeof(*Options))) >= 0)
|
if ((i = sc.MatchString(&Options[0].Name, sizeof(*Options))) >= 0)
|
||||||
{
|
{
|
||||||
flags.CompatFlags |= Options[i].CompatFlags;
|
flags.CompatFlags[Options[i].WhichSlot] |= Options[i].CompatFlags;
|
||||||
flags.BCompatFlags |= Options[i].BCompatFlags;
|
|
||||||
}
|
}
|
||||||
else if (sc.Compare("clearlineflags"))
|
else if (sc.Compare("clearlineflags"))
|
||||||
{
|
{
|
||||||
|
@ -226,12 +252,59 @@ void ParseCompatibility()
|
||||||
|
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
CompatParams.Push(P_FindLineSpecial(sc.String, NULL, NULL));
|
CompatParams.Push(P_FindLineSpecial(sc.String, NULL, NULL));
|
||||||
for(int i=0;i<5;i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
sc.MustGetNumber();
|
sc.MustGetNumber();
|
||||||
CompatParams.Push(sc.Number);
|
CompatParams.Push(sc.Number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (sc.Compare("clearlinespecial"))
|
||||||
|
{
|
||||||
|
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
|
||||||
|
CompatParams.Push(CP_CLEARSPECIAL);
|
||||||
|
sc.MustGetNumber();
|
||||||
|
CompatParams.Push(sc.Number);
|
||||||
|
}
|
||||||
|
else if (sc.Compare("setactivation"))
|
||||||
|
{
|
||||||
|
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
|
||||||
|
CompatParams.Push(CP_SETACTIVATION);
|
||||||
|
sc.MustGetNumber();
|
||||||
|
CompatParams.Push(sc.Number);
|
||||||
|
sc.MustGetNumber();
|
||||||
|
CompatParams.Push(sc.Number);
|
||||||
|
}
|
||||||
|
else if (sc.Compare("sectorflooroffset"))
|
||||||
|
{
|
||||||
|
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
|
||||||
|
CompatParams.Push(CP_SECTORFLOOROFFSET);
|
||||||
|
sc.MustGetNumber();
|
||||||
|
CompatParams.Push(sc.Number);
|
||||||
|
sc.MustGetFloat();
|
||||||
|
CompatParams.Push(FLOAT2FIXED(sc.Float));
|
||||||
|
}
|
||||||
|
else if (sc.Compare("setwallyscale"))
|
||||||
|
{
|
||||||
|
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
|
||||||
|
CompatParams.Push(CP_SETWALLYSCALE);
|
||||||
|
sc.MustGetNumber();
|
||||||
|
CompatParams.Push(sc.Number);
|
||||||
|
sc.MustGetString();
|
||||||
|
CompatParams.Push(sc.MustMatchString(LineSides));
|
||||||
|
sc.MustGetString();
|
||||||
|
CompatParams.Push(sc.MustMatchString(WallTiers));
|
||||||
|
sc.MustGetFloat();
|
||||||
|
CompatParams.Push(FLOAT2FIXED(sc.Float));
|
||||||
|
}
|
||||||
|
else if (sc.Compare("setthingz"))
|
||||||
|
{
|
||||||
|
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
|
||||||
|
CompatParams.Push(CP_SETTHINGZ);
|
||||||
|
sc.MustGetNumber();
|
||||||
|
CompatParams.Push(sc.Number);
|
||||||
|
sc.MustGetFloat();
|
||||||
|
CompatParams.Push(FLOAT2FIXED(sc.Float));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sc.UnGet();
|
sc.UnGet();
|
||||||
|
@ -261,6 +334,7 @@ void CheckCompatibility(MapData *map)
|
||||||
{
|
{
|
||||||
FMD5Holder md5;
|
FMD5Holder md5;
|
||||||
FCompatValues *flags;
|
FCompatValues *flags;
|
||||||
|
bool onlyparams = true;
|
||||||
|
|
||||||
// When playing Doom IWAD levels force COMPAT_SHORTTEX and COMPATF_LIGHT.
|
// When playing Doom IWAD levels force COMPAT_SHORTTEX and COMPATF_LIGHT.
|
||||||
// I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt.
|
// I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt.
|
||||||
|
@ -269,23 +343,29 @@ void CheckCompatibility(MapData *map)
|
||||||
{
|
{
|
||||||
ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT;
|
ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT;
|
||||||
if (gameinfo.flags & GI_COMPATSTAIRS) ii_compatflags |= COMPATF_STAIRINDEX;
|
if (gameinfo.flags & GI_COMPATSTAIRS) ii_compatflags |= COMPATF_STAIRINDEX;
|
||||||
|
ii_compatflags2 = 0;
|
||||||
ib_compatflags = 0;
|
ib_compatflags = 0;
|
||||||
ii_compatparams = -1;
|
ii_compatparams = -1;
|
||||||
}
|
}
|
||||||
else if (Wads.GetLumpFile(map->lumpnum) == 1 && (gameinfo.flags & GI_COMPATPOLY1) && Wads.CheckLumpName(map->lumpnum, "MAP36"))
|
else if (Wads.GetLumpFile(map->lumpnum) == 1 && (gameinfo.flags & GI_COMPATPOLY1) && Wads.CheckLumpName(map->lumpnum, "MAP36"))
|
||||||
{
|
{
|
||||||
ii_compatflags = COMPATF_POLYOBJ;
|
ii_compatflags = COMPATF_POLYOBJ;
|
||||||
|
ii_compatflags2 = 0;
|
||||||
ib_compatflags = 0;
|
ib_compatflags = 0;
|
||||||
ii_compatparams = -1;
|
ii_compatparams = -1;
|
||||||
}
|
}
|
||||||
else if (Wads.GetLumpFile(map->lumpnum) == 2 && (gameinfo.flags & GI_COMPATPOLY2) && Wads.CheckLumpName(map->lumpnum, "MAP47"))
|
else if (Wads.GetLumpFile(map->lumpnum) == 2 && (gameinfo.flags & GI_COMPATPOLY2) && Wads.CheckLumpName(map->lumpnum, "MAP47"))
|
||||||
{
|
{
|
||||||
ii_compatflags = COMPATF_POLYOBJ;
|
ii_compatflags = COMPATF_POLYOBJ;
|
||||||
|
ii_compatflags2 = 0;
|
||||||
ib_compatflags = 0;
|
ib_compatflags = 0;
|
||||||
ii_compatparams = -1;
|
ii_compatparams = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
onlyparams = false;
|
||||||
|
}
|
||||||
|
|
||||||
map->GetChecksum(md5.Bytes);
|
map->GetChecksum(md5.Bytes);
|
||||||
|
|
||||||
flags = BCompatMap.CheckKey(md5);
|
flags = BCompatMap.CheckKey(md5);
|
||||||
|
@ -297,25 +377,40 @@ void CheckCompatibility(MapData *map)
|
||||||
{
|
{
|
||||||
Printf("%02X", md5.Bytes[j]);
|
Printf("%02X", md5.Bytes[j]);
|
||||||
}
|
}
|
||||||
if (flags != NULL) Printf(", cflags = %08x, bflags = %08x\n", flags->CompatFlags, flags->BCompatFlags);
|
if (flags != NULL)
|
||||||
else Printf("\n");
|
{
|
||||||
|
Printf(", cflags = %08x, cflags2 = %08x, bflags = %08x\n",
|
||||||
|
flags->CompatFlags[SLOT_COMPAT], flags->CompatFlags[SLOT_COMPAT2], flags->CompatFlags[SLOT_BCOMPAT]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf("\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags != NULL)
|
if (flags != NULL)
|
||||||
{
|
{
|
||||||
ii_compatflags = flags->CompatFlags;
|
if (!onlyparams)
|
||||||
ib_compatflags = flags->BCompatFlags;
|
{
|
||||||
|
ii_compatflags = flags->CompatFlags[SLOT_COMPAT];
|
||||||
|
ii_compatflags2 = flags->CompatFlags[SLOT_COMPAT2];
|
||||||
|
ib_compatflags = flags->CompatFlags[SLOT_BCOMPAT];
|
||||||
|
}
|
||||||
ii_compatparams = flags->ExtCommandIndex;
|
ii_compatparams = flags->ExtCommandIndex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (!onlyparams)
|
||||||
{
|
{
|
||||||
ii_compatflags = 0;
|
ii_compatflags = 0;
|
||||||
|
ii_compatflags2 = 0;
|
||||||
ib_compatflags = 0;
|
ib_compatflags = 0;
|
||||||
ii_compatparams = -1;
|
|
||||||
}
|
}
|
||||||
|
ii_compatparams = -1;
|
||||||
}
|
}
|
||||||
// Reset i_compatflags
|
// Reset i_compatflags
|
||||||
compatflags.Callback();
|
compatflags.Callback();
|
||||||
|
compatflags2.Callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -368,6 +463,61 @@ void SetCompatibilityParams()
|
||||||
i+=8;
|
i+=8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CP_CLEARSPECIAL:
|
||||||
|
{
|
||||||
|
if (CompatParams[i+1] < numlines)
|
||||||
|
{
|
||||||
|
line_t *line = &lines[CompatParams[i+1]];
|
||||||
|
line->special = 0;
|
||||||
|
memset(line->args, 0, sizeof(line->args));
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CP_SETACTIVATION:
|
||||||
|
{
|
||||||
|
if (CompatParams[i+1] < numlines)
|
||||||
|
{
|
||||||
|
line_t *line = &lines[CompatParams[i+1]];
|
||||||
|
line->activation = CompatParams[i+2];
|
||||||
|
}
|
||||||
|
i += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CP_SECTORFLOOROFFSET:
|
||||||
|
{
|
||||||
|
if (CompatParams[i+1] < numsectors)
|
||||||
|
{
|
||||||
|
sector_t *sec = §ors[CompatParams[i+1]];
|
||||||
|
sec->floorplane.ChangeHeight(CompatParams[i+2]);
|
||||||
|
sec->ChangePlaneTexZ(sector_t::floor, CompatParams[i+2]);
|
||||||
|
}
|
||||||
|
i += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CP_SETWALLYSCALE:
|
||||||
|
{
|
||||||
|
if (CompatParams[i+1] < numlines)
|
||||||
|
{
|
||||||
|
side_t *side = lines[CompatParams[i+1]].sidedef[CompatParams[i+2]];
|
||||||
|
if (side != NULL)
|
||||||
|
{
|
||||||
|
side->SetTextureYScale(CompatParams[i+3], CompatParams[i+4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CP_SETTHINGZ:
|
||||||
|
{
|
||||||
|
// When this is called, the things haven't been spawned yet so we can alter the position inside the MapThings array.
|
||||||
|
if ((unsigned)CompatParams[i+1] < MapThingsConverted.Size())
|
||||||
|
{
|
||||||
|
MapThingsConverted[CompatParams[i+1]].z = CompatParams[i+2];
|
||||||
|
}
|
||||||
|
i += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,5 +566,5 @@ CCMD (mapchecksum)
|
||||||
|
|
||||||
CCMD (hiddencompatflags)
|
CCMD (hiddencompatflags)
|
||||||
{
|
{
|
||||||
Printf("%08x %08x\n", ii_compatflags, ib_compatflags);
|
Printf("%08x %08x %08x\n", ii_compatflags, ii_compatflags2, ib_compatflags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,7 @@ union FMD5Holder
|
||||||
|
|
||||||
struct FCompatValues
|
struct FCompatValues
|
||||||
{
|
{
|
||||||
int CompatFlags;
|
int CompatFlags[3];
|
||||||
int BCompatFlags;
|
|
||||||
unsigned int ExtCommandIndex;
|
unsigned int ExtCommandIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,12 @@
|
||||||
|
|
||||||
#include "doomtype.h"
|
#include "doomtype.h"
|
||||||
#include "configfile.h"
|
#include "configfile.h"
|
||||||
|
#include "m_random.h"
|
||||||
|
|
||||||
#define READBUFFERSIZE 256
|
#define READBUFFERSIZE 256
|
||||||
|
|
||||||
|
static FRandom pr_endtag;
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
//
|
//
|
||||||
// FConfigFile Constructor
|
// FConfigFile Constructor
|
||||||
|
@ -53,6 +56,8 @@ FConfigFile::FConfigFile ()
|
||||||
LastSectionPtr = &Sections;
|
LastSectionPtr = &Sections;
|
||||||
CurrentEntry = NULL;
|
CurrentEntry = NULL;
|
||||||
PathName = "";
|
PathName = "";
|
||||||
|
OkayToWrite = true;
|
||||||
|
FileExisted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
|
@ -70,6 +75,8 @@ FConfigFile::FConfigFile (const char *pathname,
|
||||||
CurrentEntry = NULL;
|
CurrentEntry = NULL;
|
||||||
ChangePathName (pathname);
|
ChangePathName (pathname);
|
||||||
LoadConfigFile (nosechandler, userdata);
|
LoadConfigFile (nosechandler, userdata);
|
||||||
|
OkayToWrite = true;
|
||||||
|
FileExisted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
|
@ -85,6 +92,8 @@ FConfigFile::FConfigFile (const FConfigFile &other)
|
||||||
CurrentEntry = NULL;
|
CurrentEntry = NULL;
|
||||||
ChangePathName (other.PathName);
|
ChangePathName (other.PathName);
|
||||||
*this = other;
|
*this = other;
|
||||||
|
OkayToWrite = other.OkayToWrite;
|
||||||
|
FileExisted = other.FileExisted;
|
||||||
}
|
}
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
|
@ -587,11 +596,15 @@ void FConfigFile::LoadConfigFile (void (*nosechandler)(const char *pathname, FCo
|
||||||
FILE *file = fopen (PathName, "r");
|
FILE *file = fopen (PathName, "r");
|
||||||
bool succ;
|
bool succ;
|
||||||
|
|
||||||
|
FileExisted = false;
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
succ = ReadConfig (file);
|
succ = ReadConfig (file);
|
||||||
fclose (file);
|
fclose (file);
|
||||||
|
FileExisted = succ;
|
||||||
|
|
||||||
if (!succ)
|
if (!succ)
|
||||||
{ // First valid line did not define a section
|
{ // First valid line did not define a section
|
||||||
|
@ -669,13 +682,68 @@ bool FConfigFile::ReadConfig (void *file)
|
||||||
whiteprobe++;
|
whiteprobe++;
|
||||||
}
|
}
|
||||||
*(whiteprobe - 1) = 0;
|
*(whiteprobe - 1) = 0;
|
||||||
|
// Check for multi-line value
|
||||||
|
if (whiteprobe[0] == '<' && whiteprobe[1] == '<' && whiteprobe[2] == '<' && whiteprobe[3] != '\0')
|
||||||
|
{
|
||||||
|
ReadMultiLineValue (file, section, start, whiteprobe + 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
NewConfigEntry (section, start, whiteprobe);
|
NewConfigEntry (section, start, whiteprobe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: ReadMultiLineValue
|
||||||
|
//
|
||||||
|
// Reads a multi-line value, with format as follows:
|
||||||
|
//
|
||||||
|
// key=<<<ENDTAG
|
||||||
|
// ... blah blah blah ...
|
||||||
|
// >>>ENDTAG
|
||||||
|
//
|
||||||
|
// The final ENDTAG must be on a line all by itself.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
|
FConfigFile::FConfigEntry *FConfigFile::ReadMultiLineValue(void *file, FConfigSection *section, const char *key, const char *endtag)
|
||||||
|
{
|
||||||
|
char readbuf[READBUFFERSIZE];
|
||||||
|
FString value;
|
||||||
|
size_t endlen = strlen(endtag);
|
||||||
|
|
||||||
|
// Keep on reading lines until we reach a line that matches >>>endtag
|
||||||
|
while (ReadLine(readbuf, READBUFFERSIZE, file) != NULL)
|
||||||
|
{
|
||||||
|
// Does the start of this line match the endtag?
|
||||||
|
if (readbuf[0] == '>' && readbuf[1] == '>' && readbuf[2] == '>' &&
|
||||||
|
strncmp(readbuf + 3, endtag, endlen) == 0)
|
||||||
|
{ // Is there nothing but line break characters after the match?
|
||||||
|
size_t i;
|
||||||
|
for (i = endlen + 3; readbuf[i] != '\0'; ++i)
|
||||||
|
{
|
||||||
|
if (readbuf[i] != '\n' && readbuf[i] != '\r')
|
||||||
|
{ // Not a line break character
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (readbuf[i] == '\0')
|
||||||
|
{ // We're done; strip the previous line's line breaks, since it's not part of the value.
|
||||||
|
value.StripRight("\n\r");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Append this line to the value.
|
||||||
|
value << readbuf;
|
||||||
|
}
|
||||||
|
return NewConfigEntry(section, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
//
|
//
|
||||||
// FConfigFile :: ReadLine
|
// FConfigFile :: ReadLine
|
||||||
|
@ -695,6 +763,13 @@ char *FConfigFile::ReadLine (char *string, int n, void *file) const
|
||||||
|
|
||||||
bool FConfigFile::WriteConfigFile () const
|
bool FConfigFile::WriteConfigFile () const
|
||||||
{
|
{
|
||||||
|
if (!OkayToWrite && FileExisted)
|
||||||
|
{ // Pretend it was written anyway so that the user doesn't get
|
||||||
|
// any "config not written" notifications, but only if the file
|
||||||
|
// already existed. Otherwise, let it write out a default one.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
FILE *file = fopen (PathName, "w");
|
FILE *file = fopen (PathName, "w");
|
||||||
FConfigSection *section;
|
FConfigSection *section;
|
||||||
FConfigEntry *entry;
|
FConfigEntry *entry;
|
||||||
|
@ -715,7 +790,16 @@ bool FConfigFile::WriteConfigFile () const
|
||||||
fprintf (file, "[%s]\n", section->Name);
|
fprintf (file, "[%s]\n", section->Name);
|
||||||
while (entry != NULL)
|
while (entry != NULL)
|
||||||
{
|
{
|
||||||
|
if (strpbrk(entry->Value, "\r\n") == NULL)
|
||||||
|
{ // Single-line value
|
||||||
fprintf (file, "%s=%s\n", entry->Key, entry->Value);
|
fprintf (file, "%s=%s\n", entry->Key, entry->Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Multi-line value
|
||||||
|
const char *endtag = GenerateEndTag(entry->Value);
|
||||||
|
fprintf (file, "%s=<<<%s\n%s\n>>>%s\n", entry->Key,
|
||||||
|
endtag, entry->Value, endtag);
|
||||||
|
}
|
||||||
entry = entry->Next;
|
entry = entry->Next;
|
||||||
}
|
}
|
||||||
section = section->Next;
|
section = section->Next;
|
||||||
|
@ -725,6 +809,44 @@ bool FConfigFile::WriteConfigFile () const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: GenerateEndTag
|
||||||
|
//
|
||||||
|
// Generates a terminator sequence for multi-line values that does
|
||||||
|
// not appear anywhere in the value.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
|
const char *FConfigFile::GenerateEndTag(const char *value)
|
||||||
|
{
|
||||||
|
static const char Base64Table[] =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
|
||||||
|
static char EndTag[25] = "EOV-";
|
||||||
|
|
||||||
|
// Try different 20-character sequences until we find one that
|
||||||
|
// isn't in the value. We create the sequences by generating two
|
||||||
|
// 64-bit random numbers and Base64 encoding the first 15 bytes
|
||||||
|
// from them.
|
||||||
|
union { QWORD rand_num[2]; BYTE rand_bytes[16]; };
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rand_num[0] = pr_endtag.GenRand64();
|
||||||
|
rand_num[1] = pr_endtag.GenRand64();
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
DWORD three_bytes = (rand_bytes[i*3] << 16) | (rand_bytes[i*3+1] << 8) | (rand_bytes[i*3+2]);
|
||||||
|
EndTag[4+i*4 ] = Base64Table[rand_bytes[i*3] >> 2];
|
||||||
|
EndTag[4+i*4+1] = Base64Table[((rand_bytes[i*3] & 3) << 4) | (rand_bytes[i*3+1] >> 4)];
|
||||||
|
EndTag[4+i*4+2] = Base64Table[((rand_bytes[i*3+1] & 15) << 2) | (rand_bytes[i*3+2] >> 6)];
|
||||||
|
EndTag[4+i*4+3] = Base64Table[rand_bytes[i*3+2] & 63];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (strstr(value, EndTag) != NULL);
|
||||||
|
return EndTag;
|
||||||
|
}
|
||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
//
|
//
|
||||||
// FConfigFile :: WriteCommentHeader
|
// FConfigFile :: WriteCommentHeader
|
||||||
|
|
|
@ -78,6 +78,10 @@ protected:
|
||||||
|
|
||||||
virtual char *ReadLine (char *string, int n, void *file) const;
|
virtual char *ReadLine (char *string, int n, void *file) const;
|
||||||
bool ReadConfig (void *file);
|
bool ReadConfig (void *file);
|
||||||
|
static const char *GenerateEndTag(const char *value);
|
||||||
|
|
||||||
|
bool OkayToWrite;
|
||||||
|
bool FileExisted;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct FConfigEntry
|
struct FConfigEntry
|
||||||
|
@ -107,6 +111,7 @@ private:
|
||||||
FConfigEntry *FindEntry (FConfigSection *section, const char *key) const;
|
FConfigEntry *FindEntry (FConfigSection *section, const char *key) const;
|
||||||
FConfigSection *NewConfigSection (const char *name);
|
FConfigSection *NewConfigSection (const char *name);
|
||||||
FConfigEntry *NewConfigEntry (FConfigSection *section, const char *key, const char *value);
|
FConfigEntry *NewConfigEntry (FConfigSection *section, const char *key, const char *value);
|
||||||
|
FConfigEntry *ReadMultiLineValue (void *file, FConfigSection *section, const char *key, const char *terminator);
|
||||||
void SetSectionNote (FConfigSection *section, const char *note);
|
void SetSectionNote (FConfigSection *section, const char *note);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -273,7 +273,9 @@ void CT_Drawer (void)
|
||||||
|
|
||||||
if (players[consoleplayer].camera != NULL &&
|
if (players[consoleplayer].camera != NULL &&
|
||||||
(Button_ShowScores.bDown ||
|
(Button_ShowScores.bDown ||
|
||||||
players[consoleplayer].camera->health <= 0))
|
players[consoleplayer].camera->health <= 0) &&
|
||||||
|
// Don't draw during intermission, since it has its own scoreboard in wi_stuff.cpp.
|
||||||
|
gamestate != GS_INTERMISSION)
|
||||||
{
|
{
|
||||||
HU_DrawScores (&players[consoleplayer]);
|
HU_DrawScores (&players[consoleplayer]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,6 +162,41 @@ struct CodePointerAlias
|
||||||
};
|
};
|
||||||
static TArray<CodePointerAlias> MBFCodePointers;
|
static TArray<CodePointerAlias> MBFCodePointers;
|
||||||
|
|
||||||
|
struct AmmoPerAttack
|
||||||
|
{
|
||||||
|
actionf_p func;
|
||||||
|
int ammocount;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_ACTION(A_Punch)
|
||||||
|
DECLARE_ACTION(A_FirePistol)
|
||||||
|
DECLARE_ACTION(A_FireShotgun)
|
||||||
|
DECLARE_ACTION(A_FireShotgun2)
|
||||||
|
DECLARE_ACTION(A_FireCGun)
|
||||||
|
DECLARE_ACTION(A_FireMissile)
|
||||||
|
DECLARE_ACTION_PARAMS(A_Saw)
|
||||||
|
DECLARE_ACTION(A_FirePlasma)
|
||||||
|
DECLARE_ACTION(A_FireBFG)
|
||||||
|
DECLARE_ACTION(A_FireOldBFG)
|
||||||
|
DECLARE_ACTION(A_FireRailgun)
|
||||||
|
|
||||||
|
// Default ammo use of the various weapon attacks
|
||||||
|
static AmmoPerAttack AmmoPerAttacks[] = {
|
||||||
|
{ AF_A_Punch, 0},
|
||||||
|
{ AF_A_FirePistol, 1},
|
||||||
|
{ AF_A_FireShotgun, 1},
|
||||||
|
{ AF_A_FireShotgun2, 2},
|
||||||
|
{ AF_A_FireCGun, 1},
|
||||||
|
{ AF_A_FireMissile, 1},
|
||||||
|
{ AFP_A_Saw, 0},
|
||||||
|
{ AF_A_FirePlasma, 1},
|
||||||
|
{ AF_A_FireBFG, -1}, // uses deh.BFGCells
|
||||||
|
{ AF_A_FireOldBFG, 1},
|
||||||
|
{ AF_A_FireRailgun, 1},
|
||||||
|
{ NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Miscellaneous info that used to be constant
|
// Miscellaneous info that used to be constant
|
||||||
DehInfo deh =
|
DehInfo deh =
|
||||||
{
|
{
|
||||||
|
@ -183,6 +218,7 @@ DehInfo deh =
|
||||||
255, // Rocket explosion style, 255=use cvar
|
255, // Rocket explosion style, 255=use cvar
|
||||||
FRACUNIT*2/3, // Rocket explosion alpha
|
FRACUNIT*2/3, // Rocket explosion alpha
|
||||||
false, // .NoAutofreeze
|
false, // .NoAutofreeze
|
||||||
|
40, // BFG cells per shot
|
||||||
};
|
};
|
||||||
|
|
||||||
// Doom identified pickup items by their sprites. ZDoom prefers to use their
|
// Doom identified pickup items by their sprites. ZDoom prefers to use their
|
||||||
|
@ -692,7 +728,10 @@ void SetDehParams(FState * state, int codepointer)
|
||||||
break;
|
break;
|
||||||
case MBF_PlaySound:
|
case MBF_PlaySound:
|
||||||
StateParams.Set(ParamIndex+0, new FxConstant(SoundMap[value1-1], *pos)); // soundid
|
StateParams.Set(ParamIndex+0, new FxConstant(SoundMap[value1-1], *pos)); // soundid
|
||||||
StateParams.Set(ParamIndex+4, new FxConstant((value2?ATTN_NONE:ATTN_NORM), *pos)); // attenuation
|
StateParams.Set(ParamIndex+1, new FxConstant(CHAN_BODY, *pos)); // channel
|
||||||
|
StateParams.Set(ParamIndex+2, new FxConstant(1.0, *pos)); // volume
|
||||||
|
StateParams.Set(ParamIndex+3, new FxConstant(false, *pos)); // looping
|
||||||
|
StateParams.Set(ParamIndex+4, new FxConstant((value2 ? ATTN_NONE : ATTN_NORM), *pos)); // attenuation
|
||||||
break;
|
break;
|
||||||
case MBF_RandomJump:
|
case MBF_RandomJump:
|
||||||
StateParams.Set(ParamIndex+0, new FxConstant(2, *pos)); // count
|
StateParams.Set(ParamIndex+0, new FxConstant(2, *pos)); // count
|
||||||
|
@ -1087,6 +1126,15 @@ static int PatchThing (int thingy)
|
||||||
value[0] &= ~MF_TRANSLUCENT; // clean the slot
|
value[0] &= ~MF_TRANSLUCENT; // clean the slot
|
||||||
vchanged[2] = true; value[2] |= 2; // let the TRANSLUCxx code below handle it
|
vchanged[2] = true; value[2] |= 2; // let the TRANSLUCxx code below handle it
|
||||||
}
|
}
|
||||||
|
if ((info->flags & MF_MISSILE) && (info->flags2 & MF2_NOTELEPORT)
|
||||||
|
&& !(value[0] & MF_MISSILE))
|
||||||
|
{
|
||||||
|
// ZDoom gives missiles flags that did not exist in Doom: MF2_NOTELEPORT,
|
||||||
|
// MF2_IMPACT, and MF2_PCROSS. The NOTELEPORT one can be a problem since
|
||||||
|
// some projectile actors (those new to Doom II) were not excluded from
|
||||||
|
// triggering line effects and can teleport when the missile flag is removed.
|
||||||
|
info->flags2 &= ~MF2_NOTELEPORT;
|
||||||
|
}
|
||||||
info->flags = value[0];
|
info->flags = value[0];
|
||||||
}
|
}
|
||||||
if (vchanged[1])
|
if (vchanged[1])
|
||||||
|
@ -1182,15 +1230,24 @@ static int PatchThing (int thingy)
|
||||||
PushTouchedActor(const_cast<PClass *>(type));
|
PushTouchedActor(const_cast<PClass *>(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make MF3_ISMONSTER match MF_COUNTKILL
|
// If MF_COUNTKILL is set, make sure the other standard monster flags are
|
||||||
|
// set, too. And vice versa.
|
||||||
|
if (thingy != 1) // don't mess with the player's flags
|
||||||
|
{
|
||||||
if (info->flags & MF_COUNTKILL)
|
if (info->flags & MF_COUNTKILL)
|
||||||
{
|
{
|
||||||
|
info->flags2 |= MF2_PUSHWALL | MF2_MCROSS | MF2_PASSMOBJ;
|
||||||
info->flags3 |= MF3_ISMONSTER;
|
info->flags3 |= MF3_ISMONSTER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
info->flags2 &= ~(MF2_PUSHWALL | MF2_MCROSS);
|
||||||
info->flags3 &= ~MF3_ISMONSTER;
|
info->flags3 &= ~MF3_ISMONSTER;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// Everything that's altered here gets the CANUSEWALLS flag, just in case
|
||||||
|
// it calls P_Move().
|
||||||
|
info->flags4 |= MF4_CANUSEWALLS;
|
||||||
if (patchedStates)
|
if (patchedStates)
|
||||||
{
|
{
|
||||||
statedef.InstallStates(type->ActorInfo, info);
|
statedef.InstallStates(type->ActorInfo, info);
|
||||||
|
@ -1296,7 +1353,7 @@ static int PatchFrame (int frameNum)
|
||||||
|
|
||||||
if (keylen == 8 && stricmp (Line1, "Duration") == 0)
|
if (keylen == 8 && stricmp (Line1, "Duration") == 0)
|
||||||
{
|
{
|
||||||
tics = clamp (val, -1, 65534);
|
tics = clamp (val, -1, SHRT_MAX);
|
||||||
}
|
}
|
||||||
else if (keylen == 9 && stricmp (Line1, "Unknown 1") == 0)
|
else if (keylen == 9 && stricmp (Line1, "Unknown 1") == 0)
|
||||||
{
|
{
|
||||||
|
@ -1571,6 +1628,7 @@ static int PatchWeapon (int weapNum)
|
||||||
else if (stricmp (Line1, "Ammo use") == 0 || stricmp (Line1, "Ammo per shot") == 0)
|
else if (stricmp (Line1, "Ammo use") == 0 || stricmp (Line1, "Ammo per shot") == 0)
|
||||||
{
|
{
|
||||||
info->AmmoUse1 = val;
|
info->AmmoUse1 = val;
|
||||||
|
info->flags6 |= MF6_INTRYMOVE; // flag the weapon for postprocessing (reuse a flag that can't be set by external means)
|
||||||
}
|
}
|
||||||
else if (stricmp (Line1, "Min ammo") == 0)
|
else if (stricmp (Line1, "Min ammo") == 0)
|
||||||
{
|
{
|
||||||
|
@ -1724,7 +1782,7 @@ static int PatchMisc (int dummy)
|
||||||
{
|
{
|
||||||
if (stricmp (Line1, "BFG Cells/Shot") == 0)
|
if (stricmp (Line1, "BFG Cells/Shot") == 0)
|
||||||
{
|
{
|
||||||
((AWeapon*)GetDefaultByName ("BFG9000"))->AmmoUse1 = atoi (Line2);
|
deh.BFGCells = atoi (Line2);
|
||||||
}
|
}
|
||||||
else if (stricmp (Line1, "Rocket Explosion Style") == 0)
|
else if (stricmp (Line1, "Rocket Explosion Style") == 0)
|
||||||
{
|
{
|
||||||
|
@ -2279,6 +2337,28 @@ int D_LoadDehLumps()
|
||||||
{
|
{
|
||||||
count += D_LoadDehLump(lumpnum);
|
count += D_LoadDehLump(lumpnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 == PatchSize)
|
||||||
|
{
|
||||||
|
// No DEH/BEX patch is loaded yet, try to find lump(s) with specific extensions
|
||||||
|
|
||||||
|
for (lumpnum = 0, lastlump = Wads.GetNumLumps();
|
||||||
|
lumpnum < lastlump;
|
||||||
|
++lumpnum)
|
||||||
|
{
|
||||||
|
const char* const fullName = Wads.GetLumpFullName(lumpnum);
|
||||||
|
const char* const extension = strrchr(fullName, '.');
|
||||||
|
|
||||||
|
const bool isDehOrBex = NULL != extension
|
||||||
|
&& (0 == stricmp(extension, ".deh") || 0 == stricmp(extension, ".bex"));
|
||||||
|
|
||||||
|
if (isDehOrBex)
|
||||||
|
{
|
||||||
|
count += D_LoadDehLump(lumpnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2482,8 +2562,6 @@ static void UnloadDehSupp ()
|
||||||
BitNames.ShrinkToFit();
|
BitNames.ShrinkToFit();
|
||||||
StyleNames.Clear();
|
StyleNames.Clear();
|
||||||
StyleNames.ShrinkToFit();
|
StyleNames.ShrinkToFit();
|
||||||
WeaponNames.Clear();
|
|
||||||
WeaponNames.ShrinkToFit();
|
|
||||||
AmmoNames.Clear();
|
AmmoNames.Clear();
|
||||||
AmmoNames.ShrinkToFit();
|
AmmoNames.ShrinkToFit();
|
||||||
|
|
||||||
|
@ -2776,6 +2854,7 @@ static bool LoadDehSupp ()
|
||||||
}
|
}
|
||||||
else if (sc.Compare("WeaponNames"))
|
else if (sc.Compare("WeaponNames"))
|
||||||
{
|
{
|
||||||
|
WeaponNames.Clear(); // This won't be cleared by UnloadDEHSupp so we need to do it here explicitly
|
||||||
sc.MustGetStringName("{");
|
sc.MustGetStringName("{");
|
||||||
while (!sc.CheckString("}"))
|
while (!sc.CheckString("}"))
|
||||||
{
|
{
|
||||||
|
@ -2882,6 +2961,55 @@ void FinishDehPatch ()
|
||||||
StateMap.ShrinkToFit();
|
StateMap.ShrinkToFit();
|
||||||
TouchedActors.Clear();
|
TouchedActors.Clear();
|
||||||
TouchedActors.ShrinkToFit();
|
TouchedActors.ShrinkToFit();
|
||||||
|
|
||||||
|
// Now it gets nasty: We have to fiddle around with the weapons' ammo use info to make Doom's original
|
||||||
|
// ammo consumption work as intended.
|
||||||
|
|
||||||
|
for(unsigned i = 0; i < WeaponNames.Size(); i++)
|
||||||
|
{
|
||||||
|
AWeapon *weap = (AWeapon*)GetDefaultByType(WeaponNames[i]);
|
||||||
|
bool found = false;
|
||||||
|
if (weap->flags6 & MF6_INTRYMOVE)
|
||||||
|
{
|
||||||
|
// Weapon sets an explicit amount of ammo to use so we won't need any special processing here
|
||||||
|
weap->flags6 &= ~MF6_INTRYMOVE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weap->WeaponFlags |= WIF_DEHAMMO;
|
||||||
|
weap->AmmoUse1 = 0;
|
||||||
|
// to allow proper checks in CheckAmmo we have to find the first attack pointer in the Fire sequence
|
||||||
|
// and set its default ammo use as the weapon's AmmoUse1.
|
||||||
|
|
||||||
|
TMap<FState*, bool> StateVisited;
|
||||||
|
|
||||||
|
FState *state = WeaponNames[i]->ActorInfo->FindState(NAME_Fire);
|
||||||
|
while (state != NULL)
|
||||||
|
{
|
||||||
|
bool *check = StateVisited.CheckKey(state);
|
||||||
|
if (check != NULL && *check)
|
||||||
|
{
|
||||||
|
break; // State has already been checked so we reached a loop
|
||||||
|
}
|
||||||
|
StateVisited[state] = true;
|
||||||
|
for(unsigned j = 0; AmmoPerAttacks[j].func != NULL; j++)
|
||||||
|
{
|
||||||
|
if (state->ActionFunc == AmmoPerAttacks[j].func)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
int use = AmmoPerAttacks[j].ammocount;
|
||||||
|
if (use < 0) use = deh.BFGCells;
|
||||||
|
weap->AmmoUse1 = use;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) break;
|
||||||
|
state = state->GetNextState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WeaponNames.Clear();
|
||||||
|
WeaponNames.ShrinkToFit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModifyDropAmount(AInventory *inv, int dropamount);
|
void ModifyDropAmount(AInventory *inv, int dropamount);
|
||||||
|
|
|
@ -63,6 +63,7 @@ typedef enum
|
||||||
ga_newgame2,
|
ga_newgame2,
|
||||||
ga_loadgame,
|
ga_loadgame,
|
||||||
ga_loadgamehidecon,
|
ga_loadgamehidecon,
|
||||||
|
ga_loadgameplaydemo,
|
||||||
ga_autoloadgame,
|
ga_autoloadgame,
|
||||||
ga_savegame,
|
ga_savegame,
|
||||||
ga_autosave,
|
ga_autosave,
|
||||||
|
@ -89,8 +90,8 @@ typedef enum
|
||||||
BT_CROUCH = 1<<3,
|
BT_CROUCH = 1<<3,
|
||||||
BT_TURN180 = 1<<4,
|
BT_TURN180 = 1<<4,
|
||||||
BT_ALTATTACK = 1<<5, // Press your other "Fire".
|
BT_ALTATTACK = 1<<5, // Press your other "Fire".
|
||||||
BT_RELOAD = 1<<6, // Not connected to anything at the moment.
|
BT_RELOAD = 1<<6, // [XA] Reload key. Causes state jump in A_WeaponReady.
|
||||||
BT_ZOOM = 1<<7, // Neither is this.
|
BT_ZOOM = 1<<7, // [XA] Zoom key. Ditto.
|
||||||
|
|
||||||
// The rest are all ignored by the play simulation and are for scripts.
|
// The rest are all ignored by the play simulation and are for scripts.
|
||||||
BT_SPEED = 1<<8,
|
BT_SPEED = 1<<8,
|
||||||
|
|
|
@ -413,7 +413,7 @@ int FIWadManager::IdentifyVersion (TArray<FString> &wadfiles, const char *iwad,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iwadparm == NULL || wads[0].Path.IsEmpty())
|
if (iwadparm == NULL || wads[0].Path.IsEmpty() || mIWads[wads[0].Type].Required.IsNotEmpty())
|
||||||
{
|
{
|
||||||
if (GameConfig->SetSection ("IWADSearch.Directories"))
|
if (GameConfig->SetSection ("IWADSearch.Directories"))
|
||||||
{
|
{
|
||||||
|
@ -441,7 +441,8 @@ int FIWadManager::IdentifyVersion (TArray<FString> &wadfiles, const char *iwad,
|
||||||
"heretic shadow of the serpent riders/base",
|
"heretic shadow of the serpent riders/base",
|
||||||
"hexen/base",
|
"hexen/base",
|
||||||
"hexen deathkings of the dark citadel/base",
|
"hexen deathkings of the dark citadel/base",
|
||||||
"ultimate doom/base"
|
"ultimate doom/base",
|
||||||
|
"DOOM 3 BFG Edition/base/wads"
|
||||||
};
|
};
|
||||||
steam_path += "/SteamApps/common/";
|
steam_path += "/SteamApps/common/";
|
||||||
for (i = 0; i < countof(steam_dirs); ++i)
|
for (i = 0; i < countof(steam_dirs); ++i)
|
||||||
|
|
301
src/d_main.cpp
301
src/d_main.cpp
|
@ -106,6 +106,7 @@
|
||||||
#include "po_man.h"
|
#include "po_man.h"
|
||||||
#include "resourcefiles/resourcefile.h"
|
#include "resourcefiles/resourcefile.h"
|
||||||
#include "r_renderer.h"
|
#include "r_renderer.h"
|
||||||
|
#include "p_local.h"
|
||||||
|
|
||||||
#ifdef USE_POLYMOST
|
#ifdef USE_POLYMOST
|
||||||
#include "r_polymost.h"
|
#include "r_polymost.h"
|
||||||
|
@ -157,7 +158,6 @@ EXTERN_CVAR (Bool, sv_unlimited_pickup)
|
||||||
|
|
||||||
extern int testingmode;
|
extern int testingmode;
|
||||||
extern bool setmodeneeded;
|
extern bool setmodeneeded;
|
||||||
extern bool netdemo;
|
|
||||||
extern int NewWidth, NewHeight, NewBits, DisplayBits;
|
extern int NewWidth, NewHeight, NewBits, DisplayBits;
|
||||||
EXTERN_CVAR (Bool, st_scale)
|
EXTERN_CVAR (Bool, st_scale)
|
||||||
extern bool gameisdead;
|
extern bool gameisdead;
|
||||||
|
@ -515,8 +515,8 @@ CVAR (Flag, sv_nocountendmonst, dmflags2, DF2_NOCOUNTENDMONST);
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int i_compatflags; // internal compatflags composed from the compatflags CVAR and MAPINFO settings
|
int i_compatflags, i_compatflags2; // internal compatflags composed from the compatflags CVAR and MAPINFO settings
|
||||||
int ii_compatflags, ib_compatflags;
|
int ii_compatflags, ii_compatflags2, ib_compatflags;
|
||||||
|
|
||||||
EXTERN_CVAR(Int, compatmode)
|
EXTERN_CVAR(Int, compatmode)
|
||||||
|
|
||||||
|
@ -526,19 +526,30 @@ static int GetCompatibility(int mask)
|
||||||
else return (mask & ~level.info->compatmask) | (level.info->compatflags & level.info->compatmask);
|
else return (mask & ~level.info->compatmask) | (level.info->compatflags & level.info->compatmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int GetCompatibility2(int mask)
|
||||||
|
{
|
||||||
|
return (level.info == NULL) ? mask
|
||||||
|
: (mask & ~level.info->compatmask2) | (level.info->compatflags2 & level.info->compatmask2);
|
||||||
|
}
|
||||||
|
|
||||||
CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
||||||
{
|
{
|
||||||
int old = i_compatflags;
|
int old = i_compatflags;
|
||||||
i_compatflags = GetCompatibility(self) | ii_compatflags;
|
i_compatflags = GetCompatibility(self) | ii_compatflags;
|
||||||
if ((old ^i_compatflags) & COMPATF_POLYOBJ)
|
if ((old ^ i_compatflags) & COMPATF_POLYOBJ)
|
||||||
{
|
{
|
||||||
FPolyObj::ClearAllSubsectorLinks();
|
FPolyObj::ClearAllSubsectorLinks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR (Int, compatflags2, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
||||||
|
{
|
||||||
|
i_compatflags2 = GetCompatibility2(self) | ii_compatflags2;
|
||||||
|
}
|
||||||
|
|
||||||
CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||||
{
|
{
|
||||||
int v;
|
int v, w = 0;
|
||||||
|
|
||||||
switch (self)
|
switch (self)
|
||||||
{
|
{
|
||||||
|
@ -551,6 +562,7 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||||
v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT|
|
v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT|
|
||||||
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_DEHHEALTH|COMPATF_CROSSDROPOFF|
|
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_DEHHEALTH|COMPATF_CROSSDROPOFF|
|
||||||
COMPATF_LIGHT;
|
COMPATF_LIGHT;
|
||||||
|
w= COMPATF2_FLOORMOVE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set)
|
case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set)
|
||||||
|
@ -558,6 +570,7 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||||
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN|
|
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN|
|
||||||
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|
|
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|
|
||||||
COMPATF_WALLRUN|COMPATF_NOTOSSDROPS|COMPATF_LIGHT|COMPATF_MASKEDMIDTEX;
|
COMPATF_WALLRUN|COMPATF_NOTOSSDROPS|COMPATF_LIGHT|COMPATF_MASKEDMIDTEX;
|
||||||
|
w = COMPATF2_BADANGLES|COMPATF2_FLOORMOVE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // Boom compat mode
|
case 3: // Boom compat mode
|
||||||
|
@ -573,19 +586,20 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||||
COMPATF_MBFMONSTERMOVE|COMPATF_NOBLOCKFRIENDS;
|
COMPATF_MBFMONSTERMOVE|COMPATF_NOBLOCKFRIENDS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: // Boom with some added settings to reenable spme 'broken' behavior
|
case 6: // Boom with some added settings to reenable some 'broken' behavior
|
||||||
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP|COMPATF_NO_PASSMOBJ|
|
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP|COMPATF_NO_PASSMOBJ|
|
||||||
COMPATF_INVISIBILITY|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|COMPATF_WALLRUN|COMPATF_NOTOSSDROPS;
|
COMPATF_INVISIBILITY|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|COMPATF_WALLRUN|COMPATF_NOTOSSDROPS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
compatflags = v;
|
compatflags = v;
|
||||||
|
compatflags2 = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVAR (Flag, compat_shortTex, compatflags, COMPATF_SHORTTEX);
|
CVAR (Flag, compat_shortTex, compatflags, COMPATF_SHORTTEX);
|
||||||
CVAR (Flag, compat_stairs, compatflags, COMPATF_STAIRINDEX);
|
CVAR (Flag, compat_stairs, compatflags, COMPATF_STAIRINDEX);
|
||||||
CVAR (Flag, compat_limitpain, compatflags, COMPATF_LIMITPAIN);
|
CVAR (Flag, compat_limitpain, compatflags, COMPATF_LIMITPAIN);
|
||||||
CVAR (Flag, compat_silentpickup,compatflags, COMPATF_SILENTPICKUP);
|
CVAR (Flag, compat_silentpickup, compatflags, COMPATF_SILENTPICKUP);
|
||||||
CVAR (Flag, compat_nopassover, compatflags, COMPATF_NO_PASSMOBJ);
|
CVAR (Flag, compat_nopassover, compatflags, COMPATF_NO_PASSMOBJ);
|
||||||
CVAR (Flag, compat_soundslots, compatflags, COMPATF_MAGICSILENCE);
|
CVAR (Flag, compat_soundslots, compatflags, COMPATF_MAGICSILENCE);
|
||||||
CVAR (Flag, compat_wallrun, compatflags, COMPATF_WALLRUN);
|
CVAR (Flag, compat_wallrun, compatflags, COMPATF_WALLRUN);
|
||||||
|
@ -598,22 +612,24 @@ CVAR (Flag, compat_dehhealth, compatflags, COMPATF_DEHHEALTH);
|
||||||
CVAR (Flag, compat_trace, compatflags, COMPATF_TRACE);
|
CVAR (Flag, compat_trace, compatflags, COMPATF_TRACE);
|
||||||
CVAR (Flag, compat_dropoff, compatflags, COMPATF_DROPOFF);
|
CVAR (Flag, compat_dropoff, compatflags, COMPATF_DROPOFF);
|
||||||
CVAR (Flag, compat_boomscroll, compatflags, COMPATF_BOOMSCROLL);
|
CVAR (Flag, compat_boomscroll, compatflags, COMPATF_BOOMSCROLL);
|
||||||
CVAR (Flag, compat_invisibility,compatflags, COMPATF_INVISIBILITY);
|
CVAR (Flag, compat_invisibility, compatflags, COMPATF_INVISIBILITY);
|
||||||
CVAR (Flag, compat_silentinstantfloors,compatflags, COMPATF_SILENT_INSTANT_FLOORS);
|
CVAR (Flag, compat_silentinstantfloors, compatflags, COMPATF_SILENT_INSTANT_FLOORS);
|
||||||
CVAR (Flag, compat_sectorsounds,compatflags, COMPATF_SECTORSOUNDS);
|
CVAR (Flag, compat_sectorsounds, compatflags, COMPATF_SECTORSOUNDS);
|
||||||
CVAR (Flag, compat_missileclip, compatflags, COMPATF_MISSILECLIP);
|
CVAR (Flag, compat_missileclip, compatflags, COMPATF_MISSILECLIP);
|
||||||
CVAR (Flag, compat_crossdropoff,compatflags, COMPATF_CROSSDROPOFF);
|
CVAR (Flag, compat_crossdropoff, compatflags, COMPATF_CROSSDROPOFF);
|
||||||
CVAR (Flag, compat_anybossdeath,compatflags, COMPATF_ANYBOSSDEATH);
|
CVAR (Flag, compat_anybossdeath, compatflags, COMPATF_ANYBOSSDEATH);
|
||||||
CVAR (Flag, compat_minotaur, compatflags, COMPATF_MINOTAUR);
|
CVAR (Flag, compat_minotaur, compatflags, COMPATF_MINOTAUR);
|
||||||
CVAR (Flag, compat_mushroom, compatflags, COMPATF_MUSHROOM);
|
CVAR (Flag, compat_mushroom, compatflags, COMPATF_MUSHROOM);
|
||||||
CVAR (Flag, compat_mbfmonstermove,compatflags, COMPATF_MBFMONSTERMOVE);
|
CVAR (Flag, compat_mbfmonstermove, compatflags, COMPATF_MBFMONSTERMOVE);
|
||||||
CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS);
|
CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS);
|
||||||
CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS);
|
CVAR (Flag, compat_noblockfriends, compatflags, COMPATF_NOBLOCKFRIENDS);
|
||||||
CVAR (Flag, compat_spritesort, compatflags,COMPATF_SPRITESORT);
|
CVAR (Flag, compat_spritesort, compatflags, COMPATF_SPRITESORT);
|
||||||
CVAR (Flag, compat_hitscan, compatflags,COMPATF_HITSCAN);
|
CVAR (Flag, compat_hitscan, compatflags, COMPATF_HITSCAN);
|
||||||
CVAR (Flag, compat_light, compatflags,COMPATF_LIGHT);
|
CVAR (Flag, compat_light, compatflags, COMPATF_LIGHT);
|
||||||
CVAR (Flag, compat_polyobj, compatflags,COMPATF_POLYOBJ);
|
CVAR (Flag, compat_polyobj, compatflags, COMPATF_POLYOBJ);
|
||||||
CVAR (Flag, compat_maskedmidtex,compatflags,COMPATF_MASKEDMIDTEX);
|
CVAR (Flag, compat_maskedmidtex, compatflags, COMPATF_MASKEDMIDTEX);
|
||||||
|
CVAR (Flag, compat_badangles, compatflags2, COMPATF2_BADANGLES);
|
||||||
|
CVAR (Flag, compat_floormove, compatflags2, COMPATF2_FLOORMOVE);
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -665,6 +681,8 @@ void D_Display ()
|
||||||
// Reload crosshair if transitioned to a different size
|
// Reload crosshair if transitioned to a different size
|
||||||
ST_LoadCrosshair (true);
|
ST_LoadCrosshair (true);
|
||||||
AM_NewResolution ();
|
AM_NewResolution ();
|
||||||
|
// Reset the mouse cursor in case the bit depth changed
|
||||||
|
vid_cursor.Callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,21 +697,21 @@ void D_Display ()
|
||||||
|
|
||||||
if (screen->Lock (false))
|
if (screen->Lock (false))
|
||||||
{
|
{
|
||||||
SB_state = screen->GetPageCount ();
|
ST_SetNeedRefresh();
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
V_SetBorderNeedRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Allow temporarily disabling wipes
|
// [RH] Allow temporarily disabling wipes
|
||||||
if (NoWipe)
|
if (NoWipe)
|
||||||
{
|
{
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
V_SetBorderNeedRefresh();
|
||||||
NoWipe--;
|
NoWipe--;
|
||||||
wipe = false;
|
wipe = false;
|
||||||
wipegamestate = gamestate;
|
wipegamestate = gamestate;
|
||||||
}
|
}
|
||||||
else if (gamestate != wipegamestate && gamestate != GS_FULLCONSOLE && gamestate != GS_TITLELEVEL)
|
else if (gamestate != wipegamestate && gamestate != GS_FULLCONSOLE && gamestate != GS_TITLELEVEL)
|
||||||
{ // save the current screen if about to wipe
|
{ // save the current screen if about to wipe
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
V_SetBorderNeedRefresh();
|
||||||
switch (wipegamestate)
|
switch (wipegamestate)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -756,13 +774,14 @@ void D_Display ()
|
||||||
}
|
}
|
||||||
screen->SetBlendingRect(viewwindowx, viewwindowy,
|
screen->SetBlendingRect(viewwindowx, viewwindowy,
|
||||||
viewwindowx + viewwidth, viewwindowy + viewheight);
|
viewwindowx + viewwidth, viewwindowy + viewheight);
|
||||||
P_CheckPlayerSprites();
|
P_PredictPlayer(&players[consoleplayer]);
|
||||||
Renderer->RenderView(&players[consoleplayer]);
|
Renderer->RenderView(&players[consoleplayer]);
|
||||||
|
P_UnPredictPlayer();
|
||||||
if ((hw2d = screen->Begin2D(viewactive)))
|
if ((hw2d = screen->Begin2D(viewactive)))
|
||||||
{
|
{
|
||||||
// Redraw everything every frame when using 2D accel
|
// Redraw everything every frame when using 2D accel
|
||||||
SB_state = screen->GetPageCount();
|
ST_SetNeedRefresh();
|
||||||
BorderNeedRefresh = screen->GetPageCount();
|
V_SetBorderNeedRefresh();
|
||||||
}
|
}
|
||||||
Renderer->DrawRemainingPlayerSprites();
|
Renderer->DrawRemainingPlayerSprites();
|
||||||
screen->DrawBlendingRect();
|
screen->DrawBlendingRect();
|
||||||
|
@ -783,17 +802,22 @@ void D_Display ()
|
||||||
|
|
||||||
if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10)
|
if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10)
|
||||||
{
|
{
|
||||||
|
StatusBar->DrawBottomStuff (HUD_AltHud);
|
||||||
if (DrawFSHUD || automapactive) DrawHUD();
|
if (DrawFSHUD || automapactive) DrawHUD();
|
||||||
StatusBar->DrawTopStuff (HUD_None);
|
StatusBar->Draw (HUD_AltHud);
|
||||||
|
StatusBar->DrawTopStuff (HUD_AltHud);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (viewheight == SCREENHEIGHT && viewactive && screenblocks > 10)
|
if (viewheight == SCREENHEIGHT && viewactive && screenblocks > 10)
|
||||||
{
|
{
|
||||||
StatusBar->Draw (DrawFSHUD ? HUD_Fullscreen : HUD_None);
|
EHudState state = DrawFSHUD ? HUD_Fullscreen : HUD_None;
|
||||||
StatusBar->DrawTopStuff (DrawFSHUD ? HUD_Fullscreen : HUD_None);
|
StatusBar->DrawBottomStuff (state);
|
||||||
|
StatusBar->Draw (state);
|
||||||
|
StatusBar->DrawTopStuff (state);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
StatusBar->DrawBottomStuff (HUD_StatusBar);
|
||||||
StatusBar->Draw (HUD_StatusBar);
|
StatusBar->Draw (HUD_StatusBar);
|
||||||
StatusBar->DrawTopStuff (HUD_StatusBar);
|
StatusBar->DrawTopStuff (HUD_StatusBar);
|
||||||
}
|
}
|
||||||
|
@ -912,6 +936,7 @@ void D_Display ()
|
||||||
|
|
||||||
void D_ErrorCleanup ()
|
void D_ErrorCleanup ()
|
||||||
{
|
{
|
||||||
|
savegamerestore = false;
|
||||||
screen->Unlock ();
|
screen->Unlock ();
|
||||||
bglobal.RemoveAllBots (true);
|
bglobal.RemoveAllBots (true);
|
||||||
D_QuitNetGame ();
|
D_QuitNetGame ();
|
||||||
|
@ -1210,12 +1235,17 @@ void D_DoAdvanceDemo (void)
|
||||||
static int pagecount;
|
static int pagecount;
|
||||||
const char *pagename = NULL;
|
const char *pagename = NULL;
|
||||||
|
|
||||||
|
advancedemo = false;
|
||||||
|
|
||||||
|
if (gameaction != ga_nothing)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
V_SetBlend (0,0,0,0);
|
V_SetBlend (0,0,0,0);
|
||||||
players[consoleplayer].playerstate = PST_LIVE; // not reborn
|
players[consoleplayer].playerstate = PST_LIVE; // not reborn
|
||||||
advancedemo = false;
|
|
||||||
usergame = false; // no save / end game here
|
usergame = false; // no save / end game here
|
||||||
paused = 0;
|
paused = 0;
|
||||||
gameaction = ga_nothing;
|
|
||||||
|
|
||||||
// [RH] If you want something more dynamic for your title, create a map
|
// [RH] If you want something more dynamic for your title, create a map
|
||||||
// and name it TITLEMAP. That map will be loaded and used as the title.
|
// and name it TITLEMAP. That map will be loaded and used as the title.
|
||||||
|
@ -1248,7 +1278,7 @@ void D_DoAdvanceDemo (void)
|
||||||
Advisory = NULL;
|
Advisory = NULL;
|
||||||
if (!M_DemoNoPlay)
|
if (!M_DemoNoPlay)
|
||||||
{
|
{
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
V_SetBorderNeedRefresh();
|
||||||
democount++;
|
democount++;
|
||||||
mysnprintf (demoname + 4, countof(demoname) - 4, "%d", democount);
|
mysnprintf (demoname + 4, countof(demoname) - 4, "%d", democount);
|
||||||
if (Wads.CheckNumForName (demoname) < 0)
|
if (Wads.CheckNumForName (demoname) < 0)
|
||||||
|
@ -1328,6 +1358,136 @@ CCMD (endgame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ParseCVarInfo
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void ParseCVarInfo()
|
||||||
|
{
|
||||||
|
int lump, lastlump = 0;
|
||||||
|
bool addedcvars = false;
|
||||||
|
|
||||||
|
while ((lump = Wads.FindLump("CVARINFO", &lastlump)) != -1)
|
||||||
|
{
|
||||||
|
FScanner sc(lump);
|
||||||
|
sc.SetCMode(true);
|
||||||
|
|
||||||
|
while (sc.GetToken())
|
||||||
|
{
|
||||||
|
FString cvarname;
|
||||||
|
char *cvardefault = NULL;
|
||||||
|
ECVarType cvartype = CVAR_Dummy;
|
||||||
|
int cvarflags = CVAR_MOD|CVAR_ARCHIVE;
|
||||||
|
FBaseCVar *cvar;
|
||||||
|
|
||||||
|
// Check for flag tokens.
|
||||||
|
while (sc.TokenType == TK_Identifier)
|
||||||
|
{
|
||||||
|
if (stricmp(sc.String, "server") == 0)
|
||||||
|
{
|
||||||
|
cvarflags |= CVAR_SERVERINFO;
|
||||||
|
}
|
||||||
|
else if (stricmp(sc.String, "user") == 0)
|
||||||
|
{
|
||||||
|
cvarflags |= CVAR_USERINFO;
|
||||||
|
}
|
||||||
|
else if (stricmp(sc.String, "noarchive") == 0)
|
||||||
|
{
|
||||||
|
cvarflags &= ~CVAR_ARCHIVE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc.ScriptError("Unknown cvar attribute '%s'", sc.String);
|
||||||
|
}
|
||||||
|
sc.MustGetAnyToken();
|
||||||
|
}
|
||||||
|
// Do some sanity checks.
|
||||||
|
if ((cvarflags & (CVAR_SERVERINFO|CVAR_USERINFO)) == 0 ||
|
||||||
|
(cvarflags & (CVAR_SERVERINFO|CVAR_USERINFO)) == (CVAR_SERVERINFO|CVAR_USERINFO))
|
||||||
|
{
|
||||||
|
sc.ScriptError("One of 'server' or 'user' must be specified");
|
||||||
|
}
|
||||||
|
// The next token must be the cvar type.
|
||||||
|
if (sc.TokenType == TK_Bool)
|
||||||
|
{
|
||||||
|
cvartype = CVAR_Bool;
|
||||||
|
}
|
||||||
|
else if (sc.TokenType == TK_Int)
|
||||||
|
{
|
||||||
|
cvartype = CVAR_Int;
|
||||||
|
}
|
||||||
|
else if (sc.TokenType == TK_Float)
|
||||||
|
{
|
||||||
|
cvartype = CVAR_Float;
|
||||||
|
}
|
||||||
|
else if (sc.TokenType == TK_Color)
|
||||||
|
{
|
||||||
|
cvartype = CVAR_Color;
|
||||||
|
}
|
||||||
|
else if (sc.TokenType == TK_String)
|
||||||
|
{
|
||||||
|
cvartype = CVAR_String;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc.ScriptError("Bad cvar type '%s'", sc.String);
|
||||||
|
}
|
||||||
|
// The next token must be the cvar name.
|
||||||
|
sc.MustGetToken(TK_Identifier);
|
||||||
|
if (FindCVar(sc.String, NULL) != NULL)
|
||||||
|
{
|
||||||
|
sc.ScriptError("cvar '%s' already exists", sc.String);
|
||||||
|
}
|
||||||
|
cvarname = sc.String;
|
||||||
|
// A default value is optional and signalled by a '=' token.
|
||||||
|
if (sc.CheckToken('='))
|
||||||
|
{
|
||||||
|
switch (cvartype)
|
||||||
|
{
|
||||||
|
case CVAR_Bool:
|
||||||
|
if (!sc.CheckToken(TK_True) && !sc.CheckToken(TK_False))
|
||||||
|
{
|
||||||
|
sc.ScriptError("Expected true or false");
|
||||||
|
}
|
||||||
|
cvardefault = sc.String;
|
||||||
|
break;
|
||||||
|
case CVAR_Int:
|
||||||
|
sc.MustGetNumber();
|
||||||
|
cvardefault = sc.String;
|
||||||
|
break;
|
||||||
|
case CVAR_Float:
|
||||||
|
sc.MustGetFloat();
|
||||||
|
cvardefault = sc.String;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sc.MustGetString();
|
||||||
|
cvardefault = sc.String;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now create the cvar.
|
||||||
|
cvar = C_CreateCVar(cvarname, cvartype, cvarflags);
|
||||||
|
if (cvardefault != NULL)
|
||||||
|
{
|
||||||
|
UCVarValue val;
|
||||||
|
val.String = cvardefault;
|
||||||
|
cvar->SetGenericRepDefault(val, CVAR_String);
|
||||||
|
}
|
||||||
|
// To be like C and ACS, require a semicolon after everything.
|
||||||
|
sc.MustGetToken(';');
|
||||||
|
addedcvars = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Only load mod cvars from the config if we defined some, so we don't
|
||||||
|
// clutter up the cvar space when not playing mods with custom cvars.
|
||||||
|
if (addedcvars)
|
||||||
|
{
|
||||||
|
GameConfig->DoModSetup (gameinfo.ConfigName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// D_AddFile
|
// D_AddFile
|
||||||
|
@ -1681,6 +1841,25 @@ static FString ParseGameInfo(TArray<FString> &pwads, const char *fn, const char
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
DoomStartupInfo.BkColor = V_GetColor(NULL, sc.String);
|
DoomStartupInfo.BkColor = V_GetColor(NULL, sc.String);
|
||||||
}
|
}
|
||||||
|
else if (!nextKey.CompareNoCase("STARTUPTYPE"))
|
||||||
|
{
|
||||||
|
sc.MustGetString();
|
||||||
|
FString sttype = sc.String;
|
||||||
|
if (!sttype.CompareNoCase("DOOM"))
|
||||||
|
DoomStartupInfo.Type = FStartupInfo::DoomStartup;
|
||||||
|
else if (!sttype.CompareNoCase("HERETIC"))
|
||||||
|
DoomStartupInfo.Type = FStartupInfo::HereticStartup;
|
||||||
|
else if (!sttype.CompareNoCase("HEXEN"))
|
||||||
|
DoomStartupInfo.Type = FStartupInfo::HexenStartup;
|
||||||
|
else if (!sttype.CompareNoCase("STRIFE"))
|
||||||
|
DoomStartupInfo.Type = FStartupInfo::StrifeStartup;
|
||||||
|
else DoomStartupInfo.Type = FStartupInfo::DefaultStartup;
|
||||||
|
}
|
||||||
|
else if (!nextKey.CompareNoCase("STARTUPSONG"))
|
||||||
|
{
|
||||||
|
sc.MustGetString();
|
||||||
|
DoomStartupInfo.Song = sc.String;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return iwad;
|
return iwad;
|
||||||
}
|
}
|
||||||
|
@ -2010,6 +2189,21 @@ static void CheckCmdLine()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FinalGC
|
||||||
|
//
|
||||||
|
// If this doesn't free everything, the debug CRT will let us know.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static void FinalGC()
|
||||||
|
{
|
||||||
|
Args = NULL;
|
||||||
|
GC::FullGC();
|
||||||
|
GC::DelSoftRootHead(); // the soft root head will not be collected by a GC so we have to do it explicitly
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// D_DoomMain
|
// D_DoomMain
|
||||||
|
@ -2028,6 +2222,7 @@ void D_DoomMain (void)
|
||||||
|
|
||||||
D_DoomInit();
|
D_DoomInit();
|
||||||
PClass::StaticInit ();
|
PClass::StaticInit ();
|
||||||
|
atterm(FinalGC);
|
||||||
|
|
||||||
// [RH] Make sure zdoom.pk3 is always loaded,
|
// [RH] Make sure zdoom.pk3 is always loaded,
|
||||||
// as it contains magic stuff we need.
|
// as it contains magic stuff we need.
|
||||||
|
@ -2100,6 +2295,9 @@ void D_DoomMain (void)
|
||||||
allwads.ShrinkToFit();
|
allwads.ShrinkToFit();
|
||||||
SetMapxxFlag();
|
SetMapxxFlag();
|
||||||
|
|
||||||
|
// Now that wads are loaded, define mod-specific cvars.
|
||||||
|
ParseCVarInfo();
|
||||||
|
|
||||||
// [RH] Initialize localizable strings.
|
// [RH] Initialize localizable strings.
|
||||||
GStrings.LoadStrings (false);
|
GStrings.LoadStrings (false);
|
||||||
|
|
||||||
|
@ -2127,8 +2325,14 @@ void D_DoomMain (void)
|
||||||
S_Init ();
|
S_Init ();
|
||||||
|
|
||||||
Printf ("ST_Init: Init startup screen.\n");
|
Printf ("ST_Init: Init startup screen.\n");
|
||||||
if (!restart) StartScreen = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5);
|
if (!restart)
|
||||||
else StartScreen = new FStartupScreen(0);
|
{
|
||||||
|
StartScreen = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartScreen = new FStartupScreen(0);
|
||||||
|
}
|
||||||
|
|
||||||
ParseCompatibility();
|
ParseCompatibility();
|
||||||
|
|
||||||
|
@ -2137,14 +2341,17 @@ void D_DoomMain (void)
|
||||||
// [RH] Load sound environments
|
// [RH] Load sound environments
|
||||||
S_ParseReverbDef ();
|
S_ParseReverbDef ();
|
||||||
|
|
||||||
|
// [RH] Parse any SNDINFO lumps
|
||||||
|
Printf ("S_InitData: Load sound definitions.\n");
|
||||||
|
S_InitData ();
|
||||||
|
|
||||||
// [RH] Parse through all loaded mapinfo lumps
|
// [RH] Parse through all loaded mapinfo lumps
|
||||||
Printf ("G_ParseMapInfo: Load map definitions.\n");
|
Printf ("G_ParseMapInfo: Load map definitions.\n");
|
||||||
G_ParseMapInfo (iwad_info->MapInfo);
|
G_ParseMapInfo (iwad_info->MapInfo);
|
||||||
ReadStatistics();
|
ReadStatistics();
|
||||||
|
|
||||||
// [RH] Parse any SNDINFO lumps
|
// MUSINFO must be parsed after MAPINFO
|
||||||
Printf ("S_InitData: Load sound definitions.\n");
|
S_ParseMusInfo();
|
||||||
S_InitData ();
|
|
||||||
|
|
||||||
Printf ("Texman.Init: Init texture manager.\n");
|
Printf ("Texman.Init: Init texture manager.\n");
|
||||||
TexMan.Init();
|
TexMan.Init();
|
||||||
|
@ -2275,6 +2482,7 @@ void D_DoomMain (void)
|
||||||
|
|
||||||
delete StartScreen;
|
delete StartScreen;
|
||||||
StartScreen = NULL;
|
StartScreen = NULL;
|
||||||
|
S_Sound (CHAN_BODY, "misc/startupdone", 1, ATTN_NONE);
|
||||||
|
|
||||||
if (Args->CheckParm("-norun"))
|
if (Args->CheckParm("-norun"))
|
||||||
{
|
{
|
||||||
|
@ -2282,6 +2490,16 @@ void D_DoomMain (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
V_Init2();
|
V_Init2();
|
||||||
|
UpdateJoystickMenu(NULL);
|
||||||
|
|
||||||
|
v = Args->CheckValue ("-loadgame");
|
||||||
|
if (v)
|
||||||
|
{
|
||||||
|
FString file(v);
|
||||||
|
FixPathSeperator (file);
|
||||||
|
DefaultExtension (file, ".zds");
|
||||||
|
G_LoadGame (file);
|
||||||
|
}
|
||||||
|
|
||||||
v = Args->CheckValue("-playdemo");
|
v = Args->CheckValue("-playdemo");
|
||||||
if (v != NULL)
|
if (v != NULL)
|
||||||
|
@ -2298,15 +2516,6 @@ void D_DoomMain (void)
|
||||||
D_DoomLoop (); // never returns
|
D_DoomLoop (); // never returns
|
||||||
}
|
}
|
||||||
|
|
||||||
v = Args->CheckValue ("-loadgame");
|
|
||||||
if (v)
|
|
||||||
{
|
|
||||||
FString file(v);
|
|
||||||
FixPathSeperator (file);
|
|
||||||
DefaultExtension (file, ".zds");
|
|
||||||
G_LoadGame (file);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gameaction != ga_loadgame && gameaction != ga_loadgamehidecon)
|
if (gameaction != ga_loadgame && gameaction != ga_loadgamehidecon)
|
||||||
{
|
{
|
||||||
if (autostart || netgame)
|
if (autostart || netgame)
|
||||||
|
|
11
src/d_main.h
11
src/d_main.h
|
@ -94,6 +94,17 @@ struct FStartupInfo
|
||||||
FString Name;
|
FString Name;
|
||||||
DWORD FgColor; // Foreground color for title banner
|
DWORD FgColor; // Foreground color for title banner
|
||||||
DWORD BkColor; // Background color for title banner
|
DWORD BkColor; // Background color for title banner
|
||||||
|
FString Song;
|
||||||
|
int Type;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DefaultStartup,
|
||||||
|
DoomStartup,
|
||||||
|
HereticStartup,
|
||||||
|
HexenStartup,
|
||||||
|
StrifeStartup,
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FStartupInfo DoomStartupInfo;
|
extern FStartupInfo DoomStartupInfo;
|
||||||
|
|
193
src/d_net.cpp
193
src/d_net.cpp
|
@ -59,9 +59,9 @@
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
|
#include "p_spec.h"
|
||||||
int P_StartScript (AActor *who, line_t *where, int script, char *map, bool backSide,
|
#include "hardware.h"
|
||||||
int arg0, int arg1, int arg2, int always, bool wantResultCode, bool net);
|
#include "intermission/intermission.h"
|
||||||
|
|
||||||
EXTERN_CVAR (Int, disableautosave)
|
EXTERN_CVAR (Int, disableautosave)
|
||||||
EXTERN_CVAR (Int, autosavecount)
|
EXTERN_CVAR (Int, autosavecount)
|
||||||
|
@ -108,6 +108,8 @@ int resendcount[MAXNETNODES];
|
||||||
|
|
||||||
unsigned int lastrecvtime[MAXPLAYERS]; // [RH] Used for pings
|
unsigned int lastrecvtime[MAXPLAYERS]; // [RH] Used for pings
|
||||||
unsigned int currrecvtime[MAXPLAYERS];
|
unsigned int currrecvtime[MAXPLAYERS];
|
||||||
|
unsigned int lastglobalrecvtime; // Identify the last time a packet was recieved.
|
||||||
|
bool hadlate;
|
||||||
|
|
||||||
int nodeforplayer[MAXPLAYERS];
|
int nodeforplayer[MAXPLAYERS];
|
||||||
int playerfornode[MAXNETNODES];
|
int playerfornode[MAXNETNODES];
|
||||||
|
@ -121,6 +123,7 @@ void G_BuildTiccmd (ticcmd_t *cmd);
|
||||||
void D_DoAdvanceDemo (void);
|
void D_DoAdvanceDemo (void);
|
||||||
|
|
||||||
static void SendSetup (DWORD playersdetected[MAXNETNODES], BYTE gotsetup[MAXNETNODES], int len);
|
static void SendSetup (DWORD playersdetected[MAXNETNODES], BYTE gotsetup[MAXNETNODES], int len);
|
||||||
|
static void RunScript(BYTE **stream, APlayerPawn *pawn, int snum, int argn, int always);
|
||||||
|
|
||||||
int reboundpacket;
|
int reboundpacket;
|
||||||
BYTE reboundstore[MAX_MSGLEN];
|
BYTE reboundstore[MAX_MSGLEN];
|
||||||
|
@ -135,7 +138,18 @@ static int oldentertics;
|
||||||
|
|
||||||
extern bool advancedemo;
|
extern bool advancedemo;
|
||||||
|
|
||||||
CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CUSTOM_CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
{
|
||||||
|
// Do not use the separate FPS limit timer if we are limiting FPS with this.
|
||||||
|
if (self)
|
||||||
|
{
|
||||||
|
I_SetFPSLimit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I_SetFPSLimit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// [RH] Special "ticcmds" get stored in here
|
// [RH] Special "ticcmds" get stored in here
|
||||||
static struct TicSpecial
|
static struct TicSpecial
|
||||||
|
@ -299,6 +313,8 @@ void Net_ClearBuffers ()
|
||||||
oldentertics = entertic;
|
oldentertics = entertic;
|
||||||
gametic = 0;
|
gametic = 0;
|
||||||
maketic = 0;
|
maketic = 0;
|
||||||
|
|
||||||
|
lastglobalrecvtime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -584,21 +600,24 @@ void PlayerIsGone (int netnode, int netconsole)
|
||||||
if (deathmatch)
|
if (deathmatch)
|
||||||
{
|
{
|
||||||
Printf ("%s left the game with %d frags\n",
|
Printf ("%s left the game with %d frags\n",
|
||||||
players[netconsole].userinfo.netname,
|
players[netconsole].userinfo.GetName(),
|
||||||
players[netconsole].fragcount);
|
players[netconsole].fragcount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Printf ("%s left the game\n", players[netconsole].userinfo.netname);
|
Printf ("%s left the game\n", players[netconsole].userinfo.GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Revert to your own view if spying through the player who left
|
// [RH] Revert each player to their own view if spying through the player who left
|
||||||
if (players[consoleplayer].camera == players[netconsole].mo)
|
for (int ii = 0; ii < MAXPLAYERS; ++ii)
|
||||||
{
|
{
|
||||||
players[consoleplayer].camera = players[consoleplayer].mo;
|
if (playeringame[ii] && players[ii].camera == players[netconsole].mo)
|
||||||
if (StatusBar != NULL)
|
|
||||||
{
|
{
|
||||||
StatusBar->AttachToPlayer (&players[consoleplayer]);
|
players[ii].camera = players[ii].mo;
|
||||||
|
if (ii == consoleplayer && StatusBar != NULL)
|
||||||
|
{
|
||||||
|
StatusBar->AttachToPlayer (&players[ii]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,6 +628,11 @@ void PlayerIsGone (int netnode, int netconsole)
|
||||||
P_DisconnectEffect (players[netconsole].mo);
|
P_DisconnectEffect (players[netconsole].mo);
|
||||||
players[netconsole].mo->player = NULL;
|
players[netconsole].mo->player = NULL;
|
||||||
players[netconsole].mo->Destroy ();
|
players[netconsole].mo->Destroy ();
|
||||||
|
if (!(players[netconsole].mo->ObjectFlags & OF_EuthanizeMe))
|
||||||
|
{ // We just destroyed a morphed player, so now the original player
|
||||||
|
// has taken their place. Destroy that one too.
|
||||||
|
players[netconsole].mo->Destroy();
|
||||||
|
}
|
||||||
players[netconsole].mo = NULL;
|
players[netconsole].mo = NULL;
|
||||||
players[netconsole].camera = NULL;
|
players[netconsole].camera = NULL;
|
||||||
}
|
}
|
||||||
|
@ -626,7 +650,7 @@ void PlayerIsGone (int netnode, int netconsole)
|
||||||
{
|
{
|
||||||
Net_Arbitrator = i;
|
Net_Arbitrator = i;
|
||||||
players[i].settings_controller = true;
|
players[i].settings_controller = true;
|
||||||
Printf ("%s is the new arbitrator\n", players[i].userinfo.netname);
|
Printf ("%s is the new arbitrator\n", players[i].userinfo.GetName());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -681,6 +705,8 @@ void GetPackets (void)
|
||||||
continue; // extra setup packet
|
continue; // extra setup packet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastglobalrecvtime = I_GetTime (false); //Update the last time a packet was recieved
|
||||||
|
|
||||||
netnode = doomcom.remotenode;
|
netnode = doomcom.remotenode;
|
||||||
netconsole = playerfornode[netnode] & ~PL_DRONE;
|
netconsole = playerfornode[netnode] & ~PL_DRONE;
|
||||||
|
|
||||||
|
@ -748,6 +774,7 @@ void GetPackets (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netbuffer[0] & NCMD_QUITTERS)
|
if (netbuffer[0] & NCMD_QUITTERS)
|
||||||
|
|
||||||
{
|
{
|
||||||
numplayers = netbuffer[k++];
|
numplayers = netbuffer[k++];
|
||||||
for (int i = 0; i < numplayers; ++i)
|
for (int i = 0; i < numplayers; ++i)
|
||||||
|
@ -1340,7 +1367,7 @@ bool DoArbitrate (void *userdata)
|
||||||
data->playersdetected[0] |= 1 << netbuffer[1];
|
data->playersdetected[0] |= 1 << netbuffer[1];
|
||||||
|
|
||||||
StartScreen->NetMessage ("Found %s (node %d, player %d)",
|
StartScreen->NetMessage ("Found %s (node %d, player %d)",
|
||||||
players[netbuffer[1]].userinfo.netname,
|
players[netbuffer[1]].userinfo.GetName(),
|
||||||
node, netbuffer[1]+1);
|
node, netbuffer[1]+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1799,6 +1826,33 @@ void TryRunTics (void)
|
||||||
if (lowtic < gametic)
|
if (lowtic < gametic)
|
||||||
I_Error ("TryRunTics: lowtic < gametic");
|
I_Error ("TryRunTics: lowtic < gametic");
|
||||||
|
|
||||||
|
// [Ed850] Check to see the last time a packet was recieved.
|
||||||
|
// If it's longer then 3 seconds, a node has likely stalled. Check which one and re-request its last packet.
|
||||||
|
if(I_GetTime(false) - lastglobalrecvtime >= TICRATE*3)
|
||||||
|
{
|
||||||
|
int latenode = 0; // Node 0 is the local player, and should always be the highest
|
||||||
|
lastglobalrecvtime = I_GetTime(false); //Bump the count
|
||||||
|
|
||||||
|
if(NetMode == NET_PeerToPeer || consoleplayer == Net_Arbitrator)
|
||||||
|
{
|
||||||
|
for (i = 0; i < doomcom.numnodes; i++)
|
||||||
|
if (nodeingame[i] && nettics[i] < nettics[latenode])
|
||||||
|
latenode = i;
|
||||||
|
}
|
||||||
|
else if (nodeingame[nodeforplayer[Net_Arbitrator]] &&
|
||||||
|
nettics[nodeforplayer[Net_Arbitrator]] < nettics[0])
|
||||||
|
{ // Likely a packet server game. Only check the packet host.
|
||||||
|
latenode = Net_Arbitrator;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debugfile)
|
||||||
|
fprintf (debugfile, "lost tics from %i (%i to %i)\n",
|
||||||
|
latenode, nettics[latenode], gametic);
|
||||||
|
|
||||||
|
if(latenode != 0) // Send resend request to late node (if not yourself... somehow). Also mark the node as waiting to display it in the hud.
|
||||||
|
remoteresend[latenode] = players[playerfornode[latenode]].waiting = hadlate = true;
|
||||||
|
}
|
||||||
|
|
||||||
// don't stay in here forever -- give the menu a chance to work
|
// don't stay in here forever -- give the menu a chance to work
|
||||||
if (I_GetTime (false) - entertic >= TICRATE/3)
|
if (I_GetTime (false) - entertic >= TICRATE/3)
|
||||||
{
|
{
|
||||||
|
@ -1808,6 +1862,13 @@ void TryRunTics (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hadlate)
|
||||||
|
{
|
||||||
|
hadlate = false;
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
players[i].waiting = false;
|
||||||
|
}
|
||||||
|
|
||||||
// run the count tics
|
// run the count tics
|
||||||
if (counts > 0)
|
if (counts > 0)
|
||||||
{
|
{
|
||||||
|
@ -1947,12 +2008,12 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
{
|
{
|
||||||
case DEM_SAY:
|
case DEM_SAY:
|
||||||
{
|
{
|
||||||
const char *name = players[player].userinfo.netname;
|
const char *name = players[player].userinfo.GetName();
|
||||||
BYTE who = ReadByte (stream);
|
BYTE who = ReadByte (stream);
|
||||||
|
|
||||||
s = ReadString (stream);
|
s = ReadString (stream);
|
||||||
CleanseString (s);
|
CleanseString (s);
|
||||||
if (((who & 1) == 0) || players[player].userinfo.team == TEAM_NONE)
|
if (((who & 1) == 0) || players[player].userinfo.GetTeam() == TEAM_NONE)
|
||||||
{ // Said to everyone
|
{ // Said to everyone
|
||||||
if (who & 2)
|
if (who & 2)
|
||||||
{
|
{
|
||||||
|
@ -1964,7 +2025,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
}
|
}
|
||||||
S_Sound (CHAN_VOICE | CHAN_UI, gameinfo.chatSound, 1, ATTN_NONE);
|
S_Sound (CHAN_VOICE | CHAN_UI, gameinfo.chatSound, 1, ATTN_NONE);
|
||||||
}
|
}
|
||||||
else if (players[player].userinfo.team == players[consoleplayer].userinfo.team)
|
else if (players[player].userinfo.GetTeam() == players[consoleplayer].userinfo.GetTeam())
|
||||||
{ // Said only to members of the player's team
|
{ // Said only to members of the player's team
|
||||||
if (who & 2)
|
if (who & 2)
|
||||||
{
|
{
|
||||||
|
@ -2058,10 +2119,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEM_CENTERVIEW:
|
case DEM_CENTERVIEW:
|
||||||
if (players[player].mo != NULL)
|
players[player].centering = true;
|
||||||
{
|
|
||||||
players[player].mo->pitch = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEM_INVUSEALL:
|
case DEM_INVUSEALL:
|
||||||
|
@ -2227,7 +2285,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
paused = player + 1;
|
paused = player + 1;
|
||||||
S_PauseSound (false, false);
|
S_PauseSound (false, false);
|
||||||
}
|
}
|
||||||
BorderNeedRefresh = screen->GetPageCount ();
|
V_SetBorderNeedRefresh();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2313,18 +2371,17 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
{
|
{
|
||||||
int snum = ReadWord (stream);
|
int snum = ReadWord (stream);
|
||||||
int argn = ReadByte (stream);
|
int argn = ReadByte (stream);
|
||||||
int arg[3] = { 0, 0, 0 };
|
|
||||||
|
|
||||||
for (i = 0; i < argn; ++i)
|
RunScript(stream, players[player].mo, snum, argn, (type == DEM_RUNSCRIPT2) ? ACS_ALWAYS : 0);
|
||||||
{
|
|
||||||
int argval = ReadLong(stream);
|
|
||||||
if ((unsigned)i < countof(arg))
|
|
||||||
{
|
|
||||||
arg[i] = argval;
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
P_StartScript (players[player].mo, NULL, snum, level.mapname, false,
|
|
||||||
arg[0], arg[1], arg[2], type == DEM_RUNSCRIPT2, false, true);
|
case DEM_RUNNAMEDSCRIPT:
|
||||||
|
{
|
||||||
|
char *sname = ReadString(stream);
|
||||||
|
int argn = ReadByte(stream);
|
||||||
|
|
||||||
|
RunScript(stream, players[player].mo, -FName(sname), argn & 127, (argn & 128) ? ACS_ALWAYS : 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2351,9 +2408,10 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
|
|
||||||
case DEM_CROUCH:
|
case DEM_CROUCH:
|
||||||
if (gamestate == GS_LEVEL && players[player].mo != NULL &&
|
if (gamestate == GS_LEVEL && players[player].mo != NULL &&
|
||||||
players[player].health > 0 && !(players[player].oldbuttons & BT_JUMP))
|
players[player].health > 0 && !(players[player].oldbuttons & BT_JUMP) &&
|
||||||
|
!P_IsPlayerTotallyFrozen(&players[player]))
|
||||||
{
|
{
|
||||||
players[player].crouching = players[player].crouchdir<0? 1 : -1;
|
players[player].crouching = players[player].crouchdir < 0 ? 1 : -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2374,7 +2432,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
players[playernum].settings_controller = true;
|
players[playernum].settings_controller = true;
|
||||||
|
|
||||||
if (consoleplayer == playernum || consoleplayer == Net_Arbitrator)
|
if (consoleplayer == playernum || consoleplayer == Net_Arbitrator)
|
||||||
Printf ("%s has been added to the controller list.\n", players[playernum].userinfo.netname);
|
Printf ("%s has been added to the controller list.\n", players[playernum].userinfo.GetName());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2384,7 +2442,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
players[playernum].settings_controller = false;
|
players[playernum].settings_controller = false;
|
||||||
|
|
||||||
if (consoleplayer == playernum || consoleplayer == Net_Arbitrator)
|
if (consoleplayer == playernum || consoleplayer == Net_Arbitrator)
|
||||||
Printf ("%s has been removed from the controller list.\n", players[playernum].userinfo.netname);
|
Printf ("%s has been removed from the controller list.\n", players[playernum].userinfo.GetName());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2419,17 +2477,27 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEM_SETSLOT:
|
case DEM_SETSLOT:
|
||||||
|
case DEM_SETSLOTPNUM:
|
||||||
{
|
{
|
||||||
|
int pnum;
|
||||||
|
if (type == DEM_SETSLOTPNUM)
|
||||||
|
{
|
||||||
|
pnum = ReadByte(stream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pnum = player;
|
||||||
|
}
|
||||||
unsigned int slot = ReadByte(stream);
|
unsigned int slot = ReadByte(stream);
|
||||||
int count = ReadByte(stream);
|
int count = ReadByte(stream);
|
||||||
if (slot < NUM_WEAPON_SLOTS)
|
if (slot < NUM_WEAPON_SLOTS)
|
||||||
{
|
{
|
||||||
players[player].weapons.Slots[slot].Clear();
|
players[pnum].weapons.Slots[slot].Clear();
|
||||||
}
|
}
|
||||||
for(i = 0; i < count; ++i)
|
for(i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
const PClass *wpn = Net_ReadWeapon(stream);
|
const PClass *wpn = Net_ReadWeapon(stream);
|
||||||
players[player].weapons.AddSlot(slot, wpn, player == consoleplayer);
|
players[pnum].weapons.AddSlot(slot, wpn, pnum == consoleplayer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2450,6 +2518,19 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEM_SETPITCHLIMIT:
|
||||||
|
players[player].MinPitch = ReadByte(stream) * -ANGLE_1; // up
|
||||||
|
players[player].MaxPitch = ReadByte(stream) * ANGLE_1; // down
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEM_ADVANCEINTER:
|
||||||
|
F_AdvanceIntermission();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEM_REVERTCAMERA:
|
||||||
|
players[player].camera = players[player].mo;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
I_Error ("Unknown net command: %d", type);
|
I_Error ("Unknown net command: %d", type);
|
||||||
break;
|
break;
|
||||||
|
@ -2459,6 +2540,23 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
delete[] s;
|
delete[] s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used by DEM_RUNSCRIPT, DEM_RUNSCRIPT2, and DEM_RUNNAMEDSCRIPT
|
||||||
|
static void RunScript(BYTE **stream, APlayerPawn *pawn, int snum, int argn, int always)
|
||||||
|
{
|
||||||
|
int arg[4] = { 0, 0, 0, 0 };
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < argn; ++i)
|
||||||
|
{
|
||||||
|
int argval = ReadLong(stream);
|
||||||
|
if ((unsigned)i < countof(arg))
|
||||||
|
{
|
||||||
|
arg[i] = argval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
P_StartScript(pawn, NULL, snum, level.mapname, arg, MIN<int>(countof(arg), argn), ACS_NET | always);
|
||||||
|
}
|
||||||
|
|
||||||
void Net_SkipCommand (int type, BYTE **stream)
|
void Net_SkipCommand (int type, BYTE **stream)
|
||||||
{
|
{
|
||||||
BYTE t;
|
BYTE t;
|
||||||
|
@ -2547,6 +2645,11 @@ void Net_SkipCommand (int type, BYTE **stream)
|
||||||
skip = 3 + *(*stream + 2) * 4;
|
skip = 3 + *(*stream + 2) * 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEM_RUNNAMEDSCRIPT:
|
||||||
|
skip = strlen((char *)(*stream)) + 2;
|
||||||
|
skip += ((*(*stream + skip - 1)) & 127) * 4;
|
||||||
|
break;
|
||||||
|
|
||||||
case DEM_RUNSPECIAL:
|
case DEM_RUNSPECIAL:
|
||||||
skip = 2 + *(*stream + 1) * 4;
|
skip = 2 + *(*stream + 1) * 4;
|
||||||
break;
|
break;
|
||||||
|
@ -2556,9 +2659,10 @@ void Net_SkipCommand (int type, BYTE **stream)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEM_SETSLOT:
|
case DEM_SETSLOT:
|
||||||
|
case DEM_SETSLOTPNUM:
|
||||||
{
|
{
|
||||||
skip = 2;
|
skip = 2 + (type == DEM_SETSLOTPNUM);
|
||||||
for(int numweapons = (*stream)[1]; numweapons > 0; numweapons--)
|
for(int numweapons = (*stream)[skip-1]; numweapons > 0; numweapons--)
|
||||||
{
|
{
|
||||||
skip += 1 + ((*stream)[skip] >> 7);
|
skip += 1 + ((*stream)[skip] >> 7);
|
||||||
}
|
}
|
||||||
|
@ -2570,6 +2674,9 @@ void Net_SkipCommand (int type, BYTE **stream)
|
||||||
skip = 2 + ((*stream)[1] >> 7);
|
skip = 2 + ((*stream)[1] >> 7);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEM_SETPITCHLIMIT:
|
||||||
|
skip = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
@ -2586,7 +2693,7 @@ CCMD (pings)
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
if (playeringame[i])
|
if (playeringame[i])
|
||||||
Printf ("% 4d %s\n", currrecvtime[i] - lastrecvtime[i],
|
Printf ("% 4d %s\n", currrecvtime[i] - lastrecvtime[i],
|
||||||
players[i].userinfo.netname);
|
players[i].userinfo.GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2608,13 +2715,13 @@ static void Network_Controller (int playernum, bool add)
|
||||||
|
|
||||||
if (players[playernum].settings_controller && add)
|
if (players[playernum].settings_controller && add)
|
||||||
{
|
{
|
||||||
Printf ("%s is already on the setting controller list.\n", players[playernum].userinfo.netname);
|
Printf ("%s is already on the setting controller list.\n", players[playernum].userinfo.GetName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!players[playernum].settings_controller && !add)
|
if (!players[playernum].settings_controller && !add)
|
||||||
{
|
{
|
||||||
Printf ("%s is not on the setting controller list.\n", players[playernum].userinfo.netname);
|
Printf ("%s is not on the setting controller list.\n", players[playernum].userinfo.GetName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2713,7 +2820,7 @@ CCMD (net_listcontrollers)
|
||||||
|
|
||||||
if (players[i].settings_controller)
|
if (players[i].settings_controller)
|
||||||
{
|
{
|
||||||
Printf ("- %s\n", players[i].userinfo.netname);
|
Printf ("- %s\n", players[i].userinfo.GetName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,22 +92,6 @@ enum
|
||||||
|
|
||||||
const char *GenderNames[3] = { "male", "female", "other" };
|
const char *GenderNames[3] = { "male", "female", "other" };
|
||||||
|
|
||||||
static const char *UserInfoStrings[] =
|
|
||||||
{
|
|
||||||
"name",
|
|
||||||
"autoaim",
|
|
||||||
"color",
|
|
||||||
"skin",
|
|
||||||
"team",
|
|
||||||
"gender",
|
|
||||||
"neverswitchonpickup",
|
|
||||||
"movebob",
|
|
||||||
"stillbob",
|
|
||||||
"playerclass",
|
|
||||||
"colorset",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
// Replace \ with %/ and % with %%
|
// Replace \ with %/ and % with %%
|
||||||
FString D_EscapeUserInfo (const char *str)
|
FString D_EscapeUserInfo (const char *str)
|
||||||
{
|
{
|
||||||
|
@ -192,11 +176,12 @@ void D_GetPlayerColor (int player, float *h, float *s, float *v, FPlayerColorSet
|
||||||
{
|
{
|
||||||
userinfo_t *info = &players[player].userinfo;
|
userinfo_t *info = &players[player].userinfo;
|
||||||
FPlayerColorSet *colorset = NULL;
|
FPlayerColorSet *colorset = NULL;
|
||||||
int color;
|
uint32 color;
|
||||||
|
int team;
|
||||||
|
|
||||||
if (players[player].mo != NULL)
|
if (players[player].mo != NULL)
|
||||||
{
|
{
|
||||||
colorset = P_GetPlayerColorSet(players[player].mo->GetClass()->TypeName, info->colorset);
|
colorset = P_GetPlayerColorSet(players[player].mo->GetClass()->TypeName, info->GetColorSet());
|
||||||
}
|
}
|
||||||
if (colorset != NULL)
|
if (colorset != NULL)
|
||||||
{
|
{
|
||||||
|
@ -204,25 +189,28 @@ void D_GetPlayerColor (int player, float *h, float *s, float *v, FPlayerColorSet
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
color = info->color;
|
color = info->GetColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f,
|
RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f,
|
||||||
h, s, v);
|
h, s, v);
|
||||||
|
|
||||||
if (teamplay && TeamLibrary.IsValidTeam(info->team) && !Teams[info->team].GetAllowCustomPlayerColor ())
|
if (teamplay && TeamLibrary.IsValidTeam((team = info->GetTeam())) && !Teams[team].GetAllowCustomPlayerColor())
|
||||||
{
|
{
|
||||||
// In team play, force the player to use the team's hue
|
// In team play, force the player to use the team's hue
|
||||||
// and adjust the saturation and value so that the team
|
// and adjust the saturation and value so that the team
|
||||||
// hue is visible in the final color.
|
// hue is visible in the final color.
|
||||||
float ts, tv;
|
float ts, tv;
|
||||||
int tcolor = Teams[info->team].GetPlayerColor ();
|
int tcolor = Teams[team].GetPlayerColor ();
|
||||||
|
|
||||||
RGBtoHSV (RPART(tcolor)/255.f, GPART(tcolor)/255.f, BPART(tcolor)/255.f,
|
RGBtoHSV (RPART(tcolor)/255.f, GPART(tcolor)/255.f, BPART(tcolor)/255.f,
|
||||||
h, &ts, &tv);
|
h, &ts, &tv);
|
||||||
|
|
||||||
*s = clamp(ts + *s * 0.15f - 0.075f, 0.f, 1.f);
|
*s = clamp(ts + *s * 0.15f - 0.075f, 0.f, 1.f);
|
||||||
*v = clamp(tv + *v * 0.5f - 0.25f, 0.f, 1.f);
|
*v = clamp(tv + *v * 0.5f - 0.25f, 0.f, 1.f);
|
||||||
|
|
||||||
|
// Make sure not to pass back any colorset in teamplay.
|
||||||
|
colorset = NULL;
|
||||||
}
|
}
|
||||||
if (set != NULL)
|
if (set != NULL)
|
||||||
{
|
{
|
||||||
|
@ -261,9 +249,10 @@ int D_PickRandomTeam ()
|
||||||
{
|
{
|
||||||
if (playeringame[i])
|
if (playeringame[i])
|
||||||
{
|
{
|
||||||
if (TeamLibrary.IsValidTeam (players[i].userinfo.team))
|
team = players[i].userinfo.GetTeam();
|
||||||
|
if (TeamLibrary.IsValidTeam(team))
|
||||||
{
|
{
|
||||||
if (Teams[players[i].userinfo.team].m_iPresent++ == 0)
|
if (Teams[team].m_iPresent++ == 0)
|
||||||
{
|
{
|
||||||
numTeams++;
|
numTeams++;
|
||||||
}
|
}
|
||||||
|
@ -275,7 +264,7 @@ int D_PickRandomTeam ()
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
team = pr_pickteam() % Teams.Size ();
|
team = pr_pickteam() % Teams.Size();
|
||||||
} while (Teams[team].m_iPresent != 0);
|
} while (Teams[team].m_iPresent != 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -316,7 +305,7 @@ static void UpdateTeam (int pnum, int team, bool update)
|
||||||
{
|
{
|
||||||
userinfo_t *info = &players[pnum].userinfo;
|
userinfo_t *info = &players[pnum].userinfo;
|
||||||
|
|
||||||
if ((dmflags2 & DF2_NO_TEAM_SWITCH) && (alwaysapplydmflags || deathmatch) && TeamLibrary.IsValidTeam (info->team))
|
if ((dmflags2 & DF2_NO_TEAM_SWITCH) && (alwaysapplydmflags || deathmatch) && TeamLibrary.IsValidTeam (info->GetTeam()))
|
||||||
{
|
{
|
||||||
Printf ("Team changing has been disabled!\n");
|
Printf ("Team changing has been disabled!\n");
|
||||||
return;
|
return;
|
||||||
|
@ -328,19 +317,15 @@ static void UpdateTeam (int pnum, int team, bool update)
|
||||||
{
|
{
|
||||||
team = TEAM_NONE;
|
team = TEAM_NONE;
|
||||||
}
|
}
|
||||||
oldteam = info->team;
|
oldteam = info->GetTeam();
|
||||||
info->team = team;
|
team = info->TeamChanged(team);
|
||||||
|
|
||||||
if (teamplay && !TeamLibrary.IsValidTeam (info->team))
|
if (update && oldteam != team)
|
||||||
{ // Force players onto teams in teamplay mode
|
|
||||||
info->team = D_PickRandomTeam ();
|
|
||||||
}
|
|
||||||
if (update && oldteam != info->team)
|
|
||||||
{
|
{
|
||||||
if (TeamLibrary.IsValidTeam (info->team))
|
if (TeamLibrary.IsValidTeam (team))
|
||||||
Printf ("%s joined the %s team\n", info->netname, Teams[info->team].GetName ());
|
Printf ("%s joined the %s team\n", info->GetName(), Teams[team].GetName ());
|
||||||
else
|
else
|
||||||
Printf ("%s is now a loner\n", info->netname);
|
Printf ("%s is now a loner\n", info->GetName());
|
||||||
}
|
}
|
||||||
// Let the player take on the team's color
|
// Let the player take on the team's color
|
||||||
R_BuildPlayerTranslation (pnum);
|
R_BuildPlayerTranslation (pnum);
|
||||||
|
@ -348,25 +333,28 @@ static void UpdateTeam (int pnum, int team, bool update)
|
||||||
{
|
{
|
||||||
StatusBar->AttachToPlayer (&players[pnum]);
|
StatusBar->AttachToPlayer (&players[pnum]);
|
||||||
}
|
}
|
||||||
if (!TeamLibrary.IsValidTeam (info->team))
|
// Double-check
|
||||||
info->team = TEAM_NONE;
|
if (!TeamLibrary.IsValidTeam (team))
|
||||||
|
{
|
||||||
|
*static_cast<FIntCVar *>((*info)[NAME_Team]) = TEAM_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int D_GetFragCount (player_t *player)
|
int D_GetFragCount (player_t *player)
|
||||||
{
|
{
|
||||||
if (!teamplay || !TeamLibrary.IsValidTeam (player->userinfo.team))
|
const int team = player->userinfo.GetTeam();
|
||||||
|
if (!teamplay || !TeamLibrary.IsValidTeam(team))
|
||||||
{
|
{
|
||||||
return player->fragcount;
|
return player->fragcount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Count total frags for this player's team
|
// Count total frags for this player's team
|
||||||
const int team = player->userinfo.team;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < MAXPLAYERS; ++i)
|
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && players[i].userinfo.team == team)
|
if (playeringame[i] && players[i].userinfo.GetTeam() == team)
|
||||||
{
|
{
|
||||||
count += players[i].fragcount;
|
count += players[i].fragcount;
|
||||||
}
|
}
|
||||||
|
@ -378,37 +366,146 @@ int D_GetFragCount (player_t *player)
|
||||||
void D_SetupUserInfo ()
|
void D_SetupUserInfo ()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
userinfo_t *coninfo = &players[consoleplayer].userinfo;
|
userinfo_t *coninfo;
|
||||||
|
|
||||||
|
// Reset everybody's userinfo to a default state.
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
memset (&players[i].userinfo, 0, sizeof(userinfo_t));
|
{
|
||||||
|
players[i].userinfo.Reset();
|
||||||
|
}
|
||||||
|
// Initialize the console player's user info
|
||||||
|
coninfo = &players[consoleplayer].userinfo;
|
||||||
|
|
||||||
strncpy (coninfo->netname, name, MAXPLAYERNAME);
|
for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->GetNext())
|
||||||
if (teamplay && !TeamLibrary.IsValidTeam (team))
|
|
||||||
{
|
{
|
||||||
coninfo->team = D_PickRandomTeam ();
|
if ((cvar->GetFlags() & (CVAR_USERINFO|CVAR_IGNORE)) == CVAR_USERINFO)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
coninfo->team = team;
|
FBaseCVar **newcvar;
|
||||||
}
|
FName cvarname(cvar->GetName());
|
||||||
if (autoaim > 35.f || autoaim < 0.f)
|
|
||||||
|
switch (cvarname.GetIndex())
|
||||||
{
|
{
|
||||||
coninfo->aimdist = ANGLE_1*35;
|
// Some cvars don't copy their original value directly.
|
||||||
|
case NAME_Team: coninfo->TeamChanged(team); break;
|
||||||
|
case NAME_Skin: coninfo->SkinChanged(skin); break;
|
||||||
|
case NAME_Gender: coninfo->GenderChanged(gender); break;
|
||||||
|
case NAME_PlayerClass: coninfo->PlayerClassChanged(playerclass); break;
|
||||||
|
// The rest do.
|
||||||
|
default:
|
||||||
|
newcvar = coninfo->CheckKey(cvarname);
|
||||||
|
(*newcvar)->SetGenericRep(cvar->GetGenericRep(CVAR_String), CVAR_String);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
}
|
||||||
|
R_BuildPlayerTranslation(consoleplayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void userinfo_t::Reset()
|
||||||
|
{
|
||||||
|
// Clear this player's userinfo.
|
||||||
|
TMapIterator<FName, FBaseCVar *> it(*this);
|
||||||
|
TMap<FName, FBaseCVar *>::Pair *pair;
|
||||||
|
|
||||||
|
while (it.NextPair(pair))
|
||||||
{
|
{
|
||||||
coninfo->aimdist = abs ((int)(autoaim * (float)ANGLE_1));
|
delete pair->Value;
|
||||||
}
|
}
|
||||||
coninfo->color = color;
|
Clear();
|
||||||
coninfo->colorset = colorset;
|
|
||||||
coninfo->skin = R_FindSkin (skin, 0);
|
// Create userinfo vars for this player, initialized to their defaults.
|
||||||
coninfo->gender = D_GenderToInt (gender);
|
for (FBaseCVar *cvar = CVars; cvar != NULL; cvar = cvar->GetNext())
|
||||||
coninfo->neverswitch = neverswitchonpickup;
|
{
|
||||||
coninfo->MoveBob = (fixed_t)(65536.f * movebob);
|
if ((cvar->GetFlags() & (CVAR_USERINFO|CVAR_IGNORE)) == CVAR_USERINFO)
|
||||||
coninfo->StillBob = (fixed_t)(65536.f * stillbob);
|
{
|
||||||
coninfo->PlayerClass = D_PlayerClassToInt (playerclass);
|
ECVarType type;
|
||||||
R_BuildPlayerTranslation (consoleplayer);
|
FName cvarname(cvar->GetName());
|
||||||
|
FBaseCVar *newcvar;
|
||||||
|
|
||||||
|
// Some cvars have different types for their shadow copies.
|
||||||
|
switch (cvarname.GetIndex())
|
||||||
|
{
|
||||||
|
case NAME_Skin: type = CVAR_Int; break;
|
||||||
|
case NAME_Gender: type = CVAR_Int; break;
|
||||||
|
case NAME_PlayerClass: type = CVAR_Int; break;
|
||||||
|
default: type = cvar->GetRealType(); break;
|
||||||
|
}
|
||||||
|
newcvar = C_CreateCVar(NULL, type, cvar->GetFlags() & CVAR_MOD);
|
||||||
|
newcvar->SetGenericRepDefault(cvar->GetGenericRepDefault(CVAR_String), CVAR_String);
|
||||||
|
Insert(cvarname, newcvar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int userinfo_t::TeamChanged(int team)
|
||||||
|
{
|
||||||
|
if (teamplay && !TeamLibrary.IsValidTeam(team))
|
||||||
|
{ // Force players onto teams in teamplay mode
|
||||||
|
team = D_PickRandomTeam();
|
||||||
|
}
|
||||||
|
*static_cast<FIntCVar *>((*this)[NAME_Team]) = team;
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
|
||||||
|
int userinfo_t::SkinChanged(const char *skinname)
|
||||||
|
{
|
||||||
|
int skinnum = R_FindSkin(skinname, 0);
|
||||||
|
*static_cast<FIntCVar *>((*this)[NAME_Skin]) = skinnum;
|
||||||
|
return skinnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int userinfo_t::SkinNumChanged(int skinnum)
|
||||||
|
{
|
||||||
|
*static_cast<FIntCVar *>((*this)[NAME_Skin]) = skinnum;
|
||||||
|
return skinnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int userinfo_t::GenderChanged(const char *gendername)
|
||||||
|
{
|
||||||
|
int gendernum = D_GenderToInt(gendername);
|
||||||
|
*static_cast<FIntCVar *>((*this)[NAME_Gender]) = gendernum;
|
||||||
|
return gendernum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int userinfo_t::PlayerClassChanged(const char *classname)
|
||||||
|
{
|
||||||
|
int classnum = D_PlayerClassToInt(classname);
|
||||||
|
*static_cast<FIntCVar *>((*this)[NAME_PlayerClass]) = classnum;
|
||||||
|
return classnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int userinfo_t::PlayerClassNumChanged(int classnum)
|
||||||
|
{
|
||||||
|
*static_cast<FIntCVar *>((*this)[NAME_PlayerClass]) = classnum;
|
||||||
|
return classnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int userinfo_t::ColorSetChanged(int setnum)
|
||||||
|
{
|
||||||
|
*static_cast<FIntCVar *>((*this)[NAME_ColorSet]) = setnum;
|
||||||
|
return setnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 userinfo_t::ColorChanged(const char *colorname)
|
||||||
|
{
|
||||||
|
FColorCVar *color = static_cast<FColorCVar *>((*this)[NAME_Color]);
|
||||||
|
assert(color != NULL);
|
||||||
|
UCVarValue val;
|
||||||
|
val.String = const_cast<char *>(colorname);
|
||||||
|
color->SetGenericRep(val, CVAR_String);
|
||||||
|
*static_cast<FIntCVar *>((*this)[NAME_ColorSet]) = -1;
|
||||||
|
return *color;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 userinfo_t::ColorChanged(uint32 colorval)
|
||||||
|
{
|
||||||
|
FColorCVar *color = static_cast<FColorCVar *>((*this)[NAME_Color]);
|
||||||
|
assert(color != NULL);
|
||||||
|
UCVarValue val;
|
||||||
|
val.Int = colorval;
|
||||||
|
color->SetGenericRep(val, CVAR_Int);
|
||||||
|
// This version is called by the menu code. Do not implicitly set colorset.
|
||||||
|
return colorval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_UserInfoChanged (FBaseCVar *cvar)
|
void D_UserInfoChanged (FBaseCVar *cvar)
|
||||||
|
@ -500,7 +597,7 @@ static const char *SetServerVar (char *name, ECVarType type, BYTE **stream, bool
|
||||||
{
|
{
|
||||||
if (playeringame[i])
|
if (playeringame[i])
|
||||||
{
|
{
|
||||||
UpdateTeam (i, players[i].userinfo.team, true);
|
UpdateTeam (i, players[i].userinfo.GetTeam(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -569,113 +666,131 @@ void D_DoServerInfoChange (BYTE **stream, bool singlebit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
|
static int STACK_ARGS userinfosortfunc(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
if (i >= MAXPLAYERS)
|
TMap<FName, FBaseCVar *>::ConstPair *pair1 = *(TMap<FName, FBaseCVar *>::ConstPair **)a;
|
||||||
{
|
TMap<FName, FBaseCVar *>::ConstPair *pair2 = *(TMap<FName, FBaseCVar *>::ConstPair **)b;
|
||||||
WriteByte (0, stream);
|
return stricmp(pair1->Key.GetChars(), pair2->Key.GetChars());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
userinfo_t *info = &players[i].userinfo;
|
|
||||||
|
|
||||||
const PClass *type = PlayerClasses[info->PlayerClass].Type;
|
|
||||||
|
|
||||||
if (!compact)
|
|
||||||
{
|
|
||||||
sprintf (*((char **)stream),
|
|
||||||
"\\name\\%s"
|
|
||||||
"\\autoaim\\%g"
|
|
||||||
"\\color\\%x %x %x"
|
|
||||||
"\\colorset\\%d"
|
|
||||||
"\\skin\\%s"
|
|
||||||
"\\team\\%d"
|
|
||||||
"\\gender\\%s"
|
|
||||||
"\\neverswitchonpickup\\%d"
|
|
||||||
"\\movebob\\%g"
|
|
||||||
"\\stillbob\\%g"
|
|
||||||
"\\playerclass\\%s"
|
|
||||||
,
|
|
||||||
D_EscapeUserInfo(info->netname).GetChars(),
|
|
||||||
(double)info->aimdist / (float)ANGLE_1,
|
|
||||||
info->colorset,
|
|
||||||
RPART(info->color), GPART(info->color), BPART(info->color),
|
|
||||||
D_EscapeUserInfo(skins[info->skin].name).GetChars(),
|
|
||||||
info->team,
|
|
||||||
info->gender == GENDER_FEMALE ? "female" :
|
|
||||||
info->gender == GENDER_NEUTER ? "other" : "male",
|
|
||||||
info->neverswitch,
|
|
||||||
(float)(info->MoveBob) / 65536.f,
|
|
||||||
(float)(info->StillBob) / 65536.f,
|
|
||||||
info->PlayerClass == -1 ? "Random" :
|
|
||||||
D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf (*((char **)stream),
|
|
||||||
"\\"
|
|
||||||
"\\%s" // name
|
|
||||||
"\\%g" // autoaim
|
|
||||||
"\\%x %x %x" // color
|
|
||||||
"\\%s" // skin
|
|
||||||
"\\%d" // team
|
|
||||||
"\\%s" // gender
|
|
||||||
"\\%d" // neverswitchonpickup
|
|
||||||
"\\%g" // movebob
|
|
||||||
"\\%g" // stillbob
|
|
||||||
"\\%s" // playerclass
|
|
||||||
"\\%d" // colorset
|
|
||||||
,
|
|
||||||
D_EscapeUserInfo(info->netname).GetChars(),
|
|
||||||
(double)info->aimdist / (float)ANGLE_1,
|
|
||||||
RPART(info->color), GPART(info->color), BPART(info->color),
|
|
||||||
D_EscapeUserInfo(skins[info->skin].name).GetChars(),
|
|
||||||
info->team,
|
|
||||||
info->gender == GENDER_FEMALE ? "female" :
|
|
||||||
info->gender == GENDER_NEUTER ? "other" : "male",
|
|
||||||
info->neverswitch,
|
|
||||||
(float)(info->MoveBob) / 65536.f,
|
|
||||||
(float)(info->StillBob) / 65536.f,
|
|
||||||
info->PlayerClass == -1 ? "Random" :
|
|
||||||
D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars(),
|
|
||||||
info->colorset
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*stream += strlen (*((char **)stream)) + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
|
static int STACK_ARGS namesortfunc(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
userinfo_t *info = &players[i].userinfo;
|
FName *name1 = (FName *)a;
|
||||||
|
FName *name2 = (FName *)b;
|
||||||
|
return stricmp(name1->GetChars(), name2->GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
|
void D_WriteUserInfoStrings (int pnum, BYTE **stream, bool compact)
|
||||||
|
{
|
||||||
|
if (pnum >= MAXPLAYERS)
|
||||||
|
{
|
||||||
|
WriteByte (0, stream);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
userinfo_t *info = &players[pnum].userinfo;
|
||||||
|
TArray<TMap<FName, FBaseCVar *>::Pair *> userinfo_pairs(info->CountUsed());
|
||||||
|
TMap<FName, FBaseCVar *>::Iterator it(*info);
|
||||||
|
TMap<FName, FBaseCVar *>::Pair *pair;
|
||||||
|
UCVarValue cval;
|
||||||
|
|
||||||
|
// Create a simple array of all userinfo cvars
|
||||||
|
while (it.NextPair(pair))
|
||||||
|
{
|
||||||
|
userinfo_pairs.Push(pair);
|
||||||
|
}
|
||||||
|
// For compact mode, these need to be sorted. Verbose mode doesn't matter.
|
||||||
|
if (compact)
|
||||||
|
{
|
||||||
|
qsort(&userinfo_pairs[0], userinfo_pairs.Size(), sizeof(pair), userinfosortfunc);
|
||||||
|
// Compact mode is signified by starting the string with two backslash characters.
|
||||||
|
// We output one now. The second will be output as part of the first value.
|
||||||
|
*(*stream)++ = '\\';
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < userinfo_pairs.Size(); ++i)
|
||||||
|
{
|
||||||
|
pair = userinfo_pairs[i];
|
||||||
|
|
||||||
|
if (!compact)
|
||||||
|
{ // In verbose mode, prepend the cvar's name
|
||||||
|
*stream += sprintf(*((char **)stream), "\\%s\\", pair->Key.GetChars());
|
||||||
|
}
|
||||||
|
// A few of these need special handling for compatibility reasons.
|
||||||
|
switch (pair->Key.GetIndex())
|
||||||
|
{
|
||||||
|
case NAME_Gender:
|
||||||
|
*stream += sprintf(*((char **)stream), "\\%s",
|
||||||
|
*static_cast<FIntCVar *>(pair->Value) == GENDER_FEMALE ? "female" :
|
||||||
|
*static_cast<FIntCVar *>(pair->Value) == GENDER_NEUTER ? "other" : "male");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAME_PlayerClass:
|
||||||
|
*stream += sprintf(*((char **)stream), "\\%s", info->GetPlayerClassNum() == -1 ? "Random" :
|
||||||
|
D_EscapeUserInfo(info->GetPlayerClassType()->Meta.GetMetaString(APMETA_DisplayName)).GetChars());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAME_Skin:
|
||||||
|
*stream += sprintf(*((char **)stream), "\\%s", D_EscapeUserInfo(skins[info->GetSkin()].name).GetChars());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
cval = pair->Value->GetGenericRep(CVAR_String);
|
||||||
|
*stream += sprintf(*((char **)stream), "\\%s", cval.String);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*(*stream)++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update)
|
||||||
|
{
|
||||||
|
userinfo_t *info = &players[pnum].userinfo;
|
||||||
|
TArray<FName> compact_names(info->CountUsed());
|
||||||
|
FBaseCVar **cvar_ptr;
|
||||||
const char *ptr = *((const char **)stream);
|
const char *ptr = *((const char **)stream);
|
||||||
const char *breakpt;
|
const char *breakpt;
|
||||||
FString value;
|
FString value;
|
||||||
bool compact;
|
bool compact;
|
||||||
int infotype = -1;
|
FName keyname;
|
||||||
|
unsigned int infotype = 0;
|
||||||
|
|
||||||
if (*ptr++ != '\\')
|
if (*ptr++ != '\\')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
compact = (*ptr == '\\') ? ptr++, true : false;
|
compact = (*ptr == '\\') ? ptr++, true : false;
|
||||||
|
|
||||||
if (i < MAXPLAYERS)
|
// We need the cvar names in sorted order for compact mode
|
||||||
|
if (compact)
|
||||||
{
|
{
|
||||||
for (;;)
|
TMap<FName, FBaseCVar *>::Iterator it(*info);
|
||||||
{
|
TMap<FName, FBaseCVar *>::Pair *pair;
|
||||||
int j;
|
|
||||||
|
|
||||||
breakpt = strchr (ptr, '\\');
|
while (it.NextPair(pair))
|
||||||
|
{
|
||||||
|
compact_names.Push(pair->Key);
|
||||||
|
}
|
||||||
|
qsort(&compact_names[0], compact_names.Size(), sizeof(FName), namesortfunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pnum < MAXPLAYERS)
|
||||||
|
{
|
||||||
|
for (breakpt = ptr; breakpt != NULL; ptr = breakpt + 1)
|
||||||
|
{
|
||||||
|
breakpt = strchr(ptr, '\\');
|
||||||
|
|
||||||
if (compact)
|
if (compact)
|
||||||
{
|
{
|
||||||
|
// Compact has just the value.
|
||||||
|
if (infotype >= compact_names.Size())
|
||||||
|
{ // Too many entries! OMG!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
keyname = compact_names[infotype++];
|
||||||
value = D_UnescapeUserInfo(ptr, breakpt != NULL ? breakpt - ptr : strlen(ptr));
|
value = D_UnescapeUserInfo(ptr, breakpt != NULL ? breakpt - ptr : strlen(ptr));
|
||||||
infotype++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Verbose has both the key name and its value.
|
||||||
assert(breakpt != NULL);
|
assert(breakpt != NULL);
|
||||||
// A malicious remote machine could invalidate the above assert.
|
// A malicious remote machine could invalidate the above assert.
|
||||||
if (breakpt == NULL)
|
if (breakpt == NULL)
|
||||||
|
@ -691,154 +806,187 @@ void D_ReadUserInfoStrings (int i, BYTE **stream, bool update)
|
||||||
{
|
{
|
||||||
value = D_UnescapeUserInfo(valstart, strlen(valstart));
|
value = D_UnescapeUserInfo(valstart, strlen(valstart));
|
||||||
}
|
}
|
||||||
|
keyname = FName(ptr, valstart - ptr - 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
for (j = 0;
|
// A few of these need special handling.
|
||||||
UserInfoStrings[j] && strnicmp (UserInfoStrings[j], ptr, valstart - ptr - 1) != 0;
|
switch (keyname)
|
||||||
++j)
|
|
||||||
{ }
|
|
||||||
if (UserInfoStrings[j] == NULL)
|
|
||||||
{
|
{
|
||||||
infotype = -1;
|
case NAME_Gender:
|
||||||
}
|
info->GenderChanged(value);
|
||||||
else
|
|
||||||
{
|
|
||||||
infotype = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (infotype)
|
|
||||||
{
|
|
||||||
case INFO_Autoaim: {
|
|
||||||
double angles;
|
|
||||||
|
|
||||||
angles = atof (value);
|
|
||||||
if (angles > 35.f || angles < 0.f)
|
|
||||||
{
|
|
||||||
info->aimdist = ANGLE_1*35;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info->aimdist = abs ((int)(angles * (float)ANGLE_1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INFO_Name:
|
case NAME_PlayerClass:
|
||||||
{
|
info->PlayerClassChanged(value);
|
||||||
char oldname[MAXPLAYERNAME+1];
|
|
||||||
|
|
||||||
strcpy (oldname, info->netname);
|
|
||||||
strncpy (info->netname, value, MAXPLAYERNAME);
|
|
||||||
info->netname[MAXPLAYERNAME] = 0;
|
|
||||||
CleanseString(info->netname);
|
|
||||||
|
|
||||||
if (update && strcmp (oldname, info->netname) != 0)
|
|
||||||
{
|
|
||||||
Printf ("%s is now known as %s\n", oldname, info->netname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INFO_Team:
|
case NAME_Skin:
|
||||||
UpdateTeam (i, atoi(value), update);
|
info->SkinChanged(value);
|
||||||
break;
|
if (players[pnum].mo != NULL)
|
||||||
|
|
||||||
case INFO_Color:
|
|
||||||
case INFO_ColorSet:
|
|
||||||
if (infotype == INFO_Color)
|
|
||||||
{
|
{
|
||||||
info->color = V_GetColorFromString (NULL, value);
|
if (players[pnum].cls != NULL &&
|
||||||
}
|
!(players[pnum].mo->flags4 & MF4_NOSKIN) &&
|
||||||
else
|
players[pnum].mo->state->sprite ==
|
||||||
{
|
GetDefaultByType (players[pnum].cls)->SpawnState->sprite)
|
||||||
info->colorset = atoi(value);
|
|
||||||
}
|
|
||||||
R_BuildPlayerTranslation (i);
|
|
||||||
if (StatusBar != NULL && i == StatusBar->GetPlayer())
|
|
||||||
{
|
|
||||||
StatusBar->AttachToPlayer (&players[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INFO_Skin:
|
|
||||||
info->skin = R_FindSkin (value, players[i].CurrentPlayerClass);
|
|
||||||
if (players[i].mo != NULL)
|
|
||||||
{
|
|
||||||
if (players[i].cls != NULL &&
|
|
||||||
players[i].mo->state->sprite ==
|
|
||||||
GetDefaultByType (players[i].cls)->SpawnState->sprite)
|
|
||||||
{ // Only change the sprite if the player is using a standard one
|
{ // Only change the sprite if the player is using a standard one
|
||||||
players[i].mo->sprite = skins[info->skin].sprite;
|
players[pnum].mo->sprite = skins[info->GetSkin()].sprite;
|
||||||
players[i].mo->scaleX = skins[info->skin].ScaleX;
|
|
||||||
players[i].mo->scaleY = skins[info->skin].ScaleY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Rebuild translation in case the new skin uses a different range
|
// Rebuild translation in case the new skin uses a different range
|
||||||
// than the old one.
|
// than the old one.
|
||||||
R_BuildPlayerTranslation (i);
|
R_BuildPlayerTranslation(pnum);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INFO_Gender:
|
case NAME_Team:
|
||||||
info->gender = D_GenderToInt (value);
|
UpdateTeam(pnum, atoi(value), update);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INFO_NeverSwitchOnPickup:
|
case NAME_Color:
|
||||||
if (value[0] >= '0' && value[0] <= '9')
|
info->ColorChanged(value);
|
||||||
{
|
|
||||||
info->neverswitch = atoi (value) ? true : false;
|
|
||||||
}
|
|
||||||
else if (stricmp (value, "true") == 0)
|
|
||||||
{
|
|
||||||
info->neverswitch = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info->neverswitch = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INFO_MoveBob:
|
|
||||||
info->MoveBob = (fixed_t)(atof (value) * 65536.f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INFO_StillBob:
|
|
||||||
info->StillBob = (fixed_t)(atof (value) * 65536.f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INFO_PlayerClass:
|
|
||||||
info->PlayerClass = D_PlayerClassToInt (value);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
cvar_ptr = info->CheckKey(keyname);
|
||||||
|
if (cvar_ptr != NULL)
|
||||||
|
{
|
||||||
|
assert(*cvar_ptr != NULL);
|
||||||
|
UCVarValue val;
|
||||||
|
FString oldname;
|
||||||
|
|
||||||
|
if (keyname == NAME_Name)
|
||||||
|
{
|
||||||
|
val = (*cvar_ptr)->GetGenericRep(CVAR_String);
|
||||||
|
oldname = val.String;
|
||||||
|
}
|
||||||
|
val.String = CleanseString(value.LockBuffer());
|
||||||
|
(*cvar_ptr)->SetGenericRep(val, CVAR_String);
|
||||||
|
value.UnlockBuffer();
|
||||||
|
if (keyname == NAME_Name && update && oldname != value)
|
||||||
|
{
|
||||||
|
Printf("%s is now known as %s\n", oldname.GetChars(), value.GetChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (keyname == NAME_Color || keyname == NAME_ColorSet)
|
||||||
if (breakpt)
|
|
||||||
{
|
{
|
||||||
ptr = breakpt + 1;
|
R_BuildPlayerTranslation(pnum);
|
||||||
}
|
if (StatusBar != NULL && pnum == StatusBar->GetPlayer())
|
||||||
else
|
|
||||||
{
|
{
|
||||||
break;
|
StatusBar->AttachToPlayer(&players[pnum]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*stream += strlen (*((char **)stream)) + 1;
|
*stream += strlen (*((char **)stream)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReadCompatibleUserInfo(FArchive &arc, userinfo_t &info)
|
||||||
|
{
|
||||||
|
char netname[MAXPLAYERNAME + 1];
|
||||||
|
BYTE team;
|
||||||
|
int aimdist, color, colorset, skin, gender;
|
||||||
|
bool neverswitch;
|
||||||
|
//fixed_t movebob, stillbob; These were never serialized!
|
||||||
|
//int playerclass; "
|
||||||
|
|
||||||
|
info.Reset();
|
||||||
|
|
||||||
|
arc.Read(&netname, sizeof(netname));
|
||||||
|
arc << team << aimdist << color << skin << gender << neverswitch << colorset;
|
||||||
|
|
||||||
|
*static_cast<FStringCVar *>(info[NAME_Name]) = netname;
|
||||||
|
*static_cast<FIntCVar *>(info[NAME_Team]) = team;
|
||||||
|
*static_cast<FFloatCVar *>(info[NAME_Autoaim]) = (float)aimdist / ANGLE_1;
|
||||||
|
*static_cast<FIntCVar *>(info[NAME_Skin]) = skin;
|
||||||
|
*static_cast<FIntCVar *>(info[NAME_Gender]) = gender;
|
||||||
|
*static_cast<FBoolCVar *>(info[NAME_NeverSwitchOnPickup]) = neverswitch;
|
||||||
|
*static_cast<FIntCVar *>(info[NAME_ColorSet]) = colorset;
|
||||||
|
|
||||||
|
UCVarValue val;
|
||||||
|
val.Int = color;
|
||||||
|
static_cast<FColorCVar *>(info[NAME_Color])->SetGenericRep(val, CVAR_Int);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteUserInfo(FArchive &arc, userinfo_t &info)
|
||||||
|
{
|
||||||
|
TMapIterator<FName, FBaseCVar *> it(info);
|
||||||
|
TMap<FName, FBaseCVar *>::Pair *pair;
|
||||||
|
FName name;
|
||||||
|
UCVarValue val;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while (it.NextPair(pair))
|
||||||
|
{
|
||||||
|
name = pair->Key;
|
||||||
|
arc << name;
|
||||||
|
switch (name.GetIndex())
|
||||||
|
{
|
||||||
|
case NAME_Skin:
|
||||||
|
arc.WriteString(skins[info.GetSkin()].name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAME_PlayerClass:
|
||||||
|
i = info.GetPlayerClassNum();
|
||||||
|
arc.WriteString(i == -1 ? "Random" : PlayerClasses[i].Type->Meta.GetMetaString(APMETA_DisplayName));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
val = pair->Value->GetGenericRep(CVAR_String);
|
||||||
|
arc.WriteString(val.String);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name = NAME_None;
|
||||||
|
arc << name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadUserInfo(FArchive &arc, userinfo_t &info)
|
||||||
|
{
|
||||||
|
FName name;
|
||||||
|
FBaseCVar **cvar;
|
||||||
|
char *str = NULL;
|
||||||
|
UCVarValue val;
|
||||||
|
|
||||||
|
info.Reset();
|
||||||
|
for (arc << name; name != NAME_None; arc << name)
|
||||||
|
{
|
||||||
|
cvar = info.CheckKey(name);
|
||||||
|
arc << str;
|
||||||
|
if (cvar != NULL && *cvar != NULL)
|
||||||
|
{
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case NAME_Team: info.TeamChanged(atoi(str)); break;
|
||||||
|
case NAME_Skin: info.SkinChanged(str); break;
|
||||||
|
case NAME_PlayerClass: info.PlayerClassChanged(str); break;
|
||||||
|
default:
|
||||||
|
val.String = str;
|
||||||
|
(*cvar)->SetGenericRep(val, CVAR_String);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (str != NULL)
|
||||||
|
{
|
||||||
|
delete[] str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FArchive &operator<< (FArchive &arc, userinfo_t &info)
|
FArchive &operator<< (FArchive &arc, userinfo_t &info)
|
||||||
{
|
{
|
||||||
if (arc.IsStoring ())
|
if (SaveVersion < 4253)
|
||||||
{
|
{
|
||||||
arc.Write (&info.netname, sizeof(info.netname));
|
ReadCompatibleUserInfo(arc, info);
|
||||||
|
}
|
||||||
|
else if (arc.IsStoring())
|
||||||
|
{
|
||||||
|
WriteUserInfo(arc, info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
arc.Read (&info.netname, sizeof(info.netname));
|
ReadUserInfo(arc, info);
|
||||||
}
|
}
|
||||||
arc << info.team << info.aimdist << info.color
|
|
||||||
<< info.skin << info.gender << info.neverswitch
|
|
||||||
<< info.colorset;
|
|
||||||
return arc;
|
return arc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,27 +1000,51 @@ CCMD (playerinfo)
|
||||||
{
|
{
|
||||||
if (playeringame[i])
|
if (playeringame[i])
|
||||||
{
|
{
|
||||||
Printf ("%d. %s\n", i, players[i].userinfo.netname);
|
Printf("%d. %s\n", i, players[i].userinfo.GetName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i = atoi (argv[1]);
|
int i = atoi(argv[1]);
|
||||||
|
|
||||||
|
if (i < 0 || i >= MAXPLAYERS)
|
||||||
|
{
|
||||||
|
Printf("Bad player number\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
userinfo_t *ui = &players[i].userinfo;
|
userinfo_t *ui = &players[i].userinfo;
|
||||||
Printf ("Name: %s\n", ui->netname);
|
|
||||||
Printf ("Team: %s (%d)\n", ui->team == TEAM_NONE ? "None" : Teams[ui->team].GetName (), ui->team);
|
if (!playeringame[i])
|
||||||
Printf ("Aimdist: %d\n", ui->aimdist);
|
{
|
||||||
Printf ("Color: %06x\n", ui->color);
|
Printf(TEXTCOLOR_ORANGE "Player %d is not in the game\n", i);
|
||||||
Printf ("ColorSet: %d\n", ui->colorset);
|
}
|
||||||
Printf ("Skin: %s (%d)\n", skins[ui->skin].name, ui->skin);
|
|
||||||
Printf ("Gender: %s (%d)\n", GenderNames[ui->gender], ui->gender);
|
// Print special info
|
||||||
Printf ("NeverSwitch: %d\n", ui->neverswitch);
|
Printf("%20s: %s\n", "Name", ui->GetName());
|
||||||
Printf ("MoveBob: %g\n", ui->MoveBob/65536.f);
|
Printf("%20s: %s (%d)\n", "Team", ui->GetTeam() == TEAM_NONE ? "None" : Teams[ui->GetTeam()].GetName(), ui->GetTeam());
|
||||||
Printf ("StillBob: %g\n", ui->StillBob/65536.f);
|
Printf("%20s: %s (%d)\n", "Skin", skins[ui->GetSkin()].name, ui->GetSkin());
|
||||||
Printf ("PlayerClass: %s (%d)\n",
|
Printf("%20s: %s (%d)\n", "Gender", GenderNames[ui->GetGender()], ui->GetGender());
|
||||||
ui->PlayerClass == -1 ? "Random" : PlayerClasses[ui->PlayerClass].Type->Meta.GetMetaString (APMETA_DisplayName),
|
Printf("%20s: %s (%d)\n", "PlayerClass",
|
||||||
ui->PlayerClass);
|
ui->GetPlayerClassNum() == -1 ? "Random" : ui->GetPlayerClassType()->Meta.GetMetaString (APMETA_DisplayName),
|
||||||
if (argv.argc() > 2) PrintMiscActorInfo(players[i].mo);
|
ui->GetPlayerClassNum());
|
||||||
|
|
||||||
|
// Print generic info
|
||||||
|
TMapIterator<FName, FBaseCVar *> it(*ui);
|
||||||
|
TMap<FName, FBaseCVar *>::Pair *pair;
|
||||||
|
|
||||||
|
while (it.NextPair(pair))
|
||||||
|
{
|
||||||
|
if (pair->Key != NAME_Name && pair->Key != NAME_Team && pair->Key != NAME_Skin &&
|
||||||
|
pair->Key != NAME_Gender && pair->Key != NAME_PlayerClass)
|
||||||
|
{
|
||||||
|
UCVarValue val = pair->Value->GetGenericRep(CVAR_String);
|
||||||
|
Printf("%20s: %s\n", pair->Key.GetChars(), val.String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argv.argc() > 2)
|
||||||
|
{
|
||||||
|
PrintMiscActorInfo(players[i].mo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
203
src/d_player.h
203
src/d_player.h
|
@ -90,6 +90,7 @@ public:
|
||||||
virtual void AddInventory (AInventory *item);
|
virtual void AddInventory (AInventory *item);
|
||||||
virtual void RemoveInventory (AInventory *item);
|
virtual void RemoveInventory (AInventory *item);
|
||||||
virtual bool UseInventory (AInventory *item);
|
virtual bool UseInventory (AInventory *item);
|
||||||
|
virtual void MarkPrecacheSounds () const;
|
||||||
|
|
||||||
virtual void PlayIdle ();
|
virtual void PlayIdle ();
|
||||||
virtual void PlayRunning ();
|
virtual void PlayRunning ();
|
||||||
|
@ -107,7 +108,7 @@ public:
|
||||||
void GiveDefaultInventory ();
|
void GiveDefaultInventory ();
|
||||||
void PlayAttacking ();
|
void PlayAttacking ();
|
||||||
void PlayAttacking2 ();
|
void PlayAttacking2 ();
|
||||||
const char *GetSoundClass ();
|
const char *GetSoundClass () const;
|
||||||
|
|
||||||
enum EInvulState
|
enum EInvulState
|
||||||
{
|
{
|
||||||
|
@ -118,7 +119,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void BeginPlay ();
|
void BeginPlay ();
|
||||||
void Die (AActor *source, AActor *inflictor);
|
void Die (AActor *source, AActor *inflictor, int dmgflags);
|
||||||
|
|
||||||
int crouchsprite;
|
int crouchsprite;
|
||||||
int MaxHealth;
|
int MaxHealth;
|
||||||
|
@ -130,6 +131,8 @@ public:
|
||||||
|
|
||||||
// [GRB] Player class properties
|
// [GRB] Player class properties
|
||||||
fixed_t JumpZ;
|
fixed_t JumpZ;
|
||||||
|
fixed_t GruntSpeed;
|
||||||
|
fixed_t FallingScreamMinSpeed, FallingScreamMaxSpeed;
|
||||||
fixed_t ViewHeight;
|
fixed_t ViewHeight;
|
||||||
fixed_t ForwardMove1, ForwardMove2;
|
fixed_t ForwardMove1, ForwardMove2;
|
||||||
fixed_t SideMove1, SideMove2;
|
fixed_t SideMove1, SideMove2;
|
||||||
|
@ -159,6 +162,8 @@ class APlayerChunk : public APlayerPawn
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PPF_NOTHRUSTWHENINVUL = 1, // Attacks do not thrust the player if they are invulnerable.
|
PPF_NOTHRUSTWHENINVUL = 1, // Attacks do not thrust the player if they are invulnerable.
|
||||||
|
PPF_CANSUPERMORPH = 2, // Being remorphed into this class can give you a Tome of Power
|
||||||
|
PPF_CROUCHABLEMORPH = 4, // This morphed player can crouch
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -191,22 +196,29 @@ typedef enum
|
||||||
CF_INSTANTWEAPSWITCH= 1 << 11, // [RH] Switch weapons instantly
|
CF_INSTANTWEAPSWITCH= 1 << 11, // [RH] Switch weapons instantly
|
||||||
CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use
|
CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use
|
||||||
CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted
|
CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted
|
||||||
CF_WEAPONREADY = 1 << 14, // [RH] Weapon is in the ready state and can fire its primary attack
|
|
||||||
CF_TIMEFREEZE = 1 << 15, // Player has an active time freezer
|
|
||||||
CF_DRAIN = 1 << 16, // Player owns a drain powerup
|
CF_DRAIN = 1 << 16, // Player owns a drain powerup
|
||||||
CF_REGENERATION = 1 << 17, // Player owns a regeneration artifact
|
|
||||||
CF_HIGHJUMP = 1 << 18, // more Skulltag flags. Implementation not guaranteed though. ;)
|
CF_HIGHJUMP = 1 << 18, // more Skulltag flags. Implementation not guaranteed though. ;)
|
||||||
CF_REFLECTION = 1 << 19,
|
CF_REFLECTION = 1 << 19,
|
||||||
CF_PROSPERITY = 1 << 20,
|
CF_PROSPERITY = 1 << 20,
|
||||||
CF_DOUBLEFIRINGSPEED= 1 << 21, // Player owns a double firing speed artifact
|
CF_DOUBLEFIRINGSPEED= 1 << 21, // Player owns a double firing speed artifact
|
||||||
CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths.
|
CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths.
|
||||||
CF_INFINITEAMMO = 1 << 23, // Player owns an infinite ammo artifact
|
CF_INFINITEAMMO = 1 << 23, // Player owns an infinite ammo artifact
|
||||||
CF_WEAPONBOBBING = 1 << 24, // [HW] Bob weapon while the player is moving
|
|
||||||
CF_WEAPONREADYALT = 1 << 25, // Weapon can fire its secondary attack
|
|
||||||
CF_WEAPONSWITCHOK = 1 << 26, // It is okay to switch away from this weapon
|
|
||||||
CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die
|
CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die
|
||||||
|
CF_NOCLIP2 = 1 << 30, // [RH] More Quake-like noclip
|
||||||
} cheat_t;
|
} cheat_t;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
WF_WEAPONREADY = 1 << 0, // [RH] Weapon is in the ready state and can fire its primary attack
|
||||||
|
WF_WEAPONBOBBING = 1 << 1, // [HW] Bob weapon while the player is moving
|
||||||
|
WF_WEAPONREADYALT = 1 << 2, // Weapon can fire its secondary attack
|
||||||
|
WF_WEAPONSWITCHOK = 1 << 3, // It is okay to switch away from this weapon
|
||||||
|
WF_DISABLESWITCH = 1 << 4, // Disable weapon switching completely
|
||||||
|
WF_WEAPONRELOADOK = 1 << 5, // [XA] Okay to reload this weapon.
|
||||||
|
WF_WEAPONZOOMOK = 1 << 6, // [XA] Okay to use weapon zoom function.
|
||||||
|
WF_REFIRESWITCHOK = 1 << 7, // Mirror WF_WEAPONSWITCHOK for A_ReFire
|
||||||
|
};
|
||||||
|
|
||||||
#define WPIECE1 1
|
#define WPIECE1 1
|
||||||
#define WPIECE2 2
|
#define WPIECE2 2
|
||||||
#define WPIECE3 4
|
#define WPIECE3 4
|
||||||
|
@ -216,6 +228,29 @@ typedef enum
|
||||||
|
|
||||||
#define MAXPLAYERNAME 15
|
#define MAXPLAYERNAME 15
|
||||||
|
|
||||||
|
// [GRB] Custom player classes
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PCF_NOMENU = 1, // Hide in new game menu
|
||||||
|
};
|
||||||
|
|
||||||
|
class FPlayerClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FPlayerClass ();
|
||||||
|
FPlayerClass (const FPlayerClass &other);
|
||||||
|
~FPlayerClass ();
|
||||||
|
|
||||||
|
bool CheckSkin (int skin);
|
||||||
|
|
||||||
|
const PClass *Type;
|
||||||
|
DWORD Flags;
|
||||||
|
TArray<int> Skins;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern TArray<FPlayerClass> PlayerClasses;
|
||||||
|
|
||||||
|
// User info (per-player copies of each CVAR_USERINFO cvar)
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
GENDER_MALE,
|
GENDER_MALE,
|
||||||
|
@ -223,20 +258,80 @@ enum
|
||||||
GENDER_NEUTER
|
GENDER_NEUTER
|
||||||
};
|
};
|
||||||
|
|
||||||
struct userinfo_t
|
struct userinfo_t : TMap<FName,FBaseCVar *>
|
||||||
{
|
{
|
||||||
char netname[MAXPLAYERNAME+1];
|
int GetAimDist() const
|
||||||
BYTE team;
|
{
|
||||||
int aimdist;
|
if (dmflags2 & DF2_NOAUTOAIM)
|
||||||
int color;
|
{
|
||||||
int colorset;
|
return 0;
|
||||||
int skin;
|
}
|
||||||
int gender;
|
|
||||||
bool neverswitch;
|
|
||||||
fixed_t MoveBob, StillBob;
|
|
||||||
int PlayerClass;
|
|
||||||
|
|
||||||
int GetAimDist() const { return (dmflags2 & DF2_NOAUTOAIM)? 0 : aimdist; }
|
float aim = *static_cast<FFloatCVar *>(*CheckKey(NAME_Autoaim));
|
||||||
|
if (aim > 35 || aim < 0)
|
||||||
|
{
|
||||||
|
return ANGLE_1*35;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return xs_RoundToInt(fabs(aim * ANGLE_1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const char *GetName() const
|
||||||
|
{
|
||||||
|
return *static_cast<FStringCVar *>(*CheckKey(NAME_Name));
|
||||||
|
}
|
||||||
|
int GetTeam() const
|
||||||
|
{
|
||||||
|
return *static_cast<FIntCVar *>(*CheckKey(NAME_Team));
|
||||||
|
}
|
||||||
|
int GetColorSet() const
|
||||||
|
{
|
||||||
|
return *static_cast<FIntCVar *>(*CheckKey(NAME_ColorSet));
|
||||||
|
}
|
||||||
|
uint32 GetColor() const
|
||||||
|
{
|
||||||
|
return *static_cast<FColorCVar *>(*CheckKey(NAME_Color));
|
||||||
|
}
|
||||||
|
bool GetNeverSwitch() const
|
||||||
|
{
|
||||||
|
return *static_cast<FBoolCVar *>(*CheckKey(NAME_NeverSwitchOnPickup));
|
||||||
|
}
|
||||||
|
fixed_t GetMoveBob() const
|
||||||
|
{
|
||||||
|
return FLOAT2FIXED(*static_cast<FFloatCVar *>(*CheckKey(NAME_MoveBob)));
|
||||||
|
}
|
||||||
|
fixed_t GetStillBob() const
|
||||||
|
{
|
||||||
|
return FLOAT2FIXED(*static_cast<FFloatCVar *>(*CheckKey(NAME_StillBob)));
|
||||||
|
}
|
||||||
|
int GetPlayerClassNum() const
|
||||||
|
{
|
||||||
|
return *static_cast<FIntCVar *>(*CheckKey(NAME_PlayerClass));
|
||||||
|
}
|
||||||
|
const PClass *GetPlayerClassType() const
|
||||||
|
{
|
||||||
|
return PlayerClasses[GetPlayerClassNum()].Type;
|
||||||
|
}
|
||||||
|
int GetSkin() const
|
||||||
|
{
|
||||||
|
return *static_cast<FIntCVar *>(*CheckKey(NAME_Skin));
|
||||||
|
}
|
||||||
|
int GetGender() const
|
||||||
|
{
|
||||||
|
return *static_cast<FIntCVar *>(*CheckKey(NAME_Gender));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
int TeamChanged(int team);
|
||||||
|
int SkinChanged(const char *skinname);
|
||||||
|
int SkinNumChanged(int skinnum);
|
||||||
|
int GenderChanged(const char *gendername);
|
||||||
|
int PlayerClassChanged(const char *classname);
|
||||||
|
int PlayerClassNumChanged(int classnum);
|
||||||
|
uint32 ColorChanged(const char *colorname);
|
||||||
|
uint32 ColorChanged(uint32 colorval);
|
||||||
|
int ColorSetChanged(int setnum);
|
||||||
};
|
};
|
||||||
|
|
||||||
FArchive &operator<< (FArchive &arc, userinfo_t &info);
|
FArchive &operator<< (FArchive &arc, userinfo_t &info);
|
||||||
|
@ -256,6 +351,7 @@ public:
|
||||||
|
|
||||||
void SetLogNumber (int num);
|
void SetLogNumber (int num);
|
||||||
void SetLogText (const char *text);
|
void SetLogText (const char *text);
|
||||||
|
void SendPitchLimits() const;
|
||||||
|
|
||||||
APlayerPawn *mo;
|
APlayerPawn *mo;
|
||||||
BYTE playerstate;
|
BYTE playerstate;
|
||||||
|
@ -282,6 +378,8 @@ public:
|
||||||
|
|
||||||
bool centering;
|
bool centering;
|
||||||
BYTE turnticks;
|
BYTE turnticks;
|
||||||
|
|
||||||
|
|
||||||
bool attackdown;
|
bool attackdown;
|
||||||
bool usedown;
|
bool usedown;
|
||||||
DWORD oldbuttons;
|
DWORD oldbuttons;
|
||||||
|
@ -297,17 +395,22 @@ public:
|
||||||
int lastkilltime; // [RH] For multikills
|
int lastkilltime; // [RH] For multikills
|
||||||
BYTE multicount;
|
BYTE multicount;
|
||||||
BYTE spreecount; // [RH] Keep track of killing sprees
|
BYTE spreecount; // [RH] Keep track of killing sprees
|
||||||
|
BYTE WeaponState;
|
||||||
|
|
||||||
AWeapon *ReadyWeapon;
|
AWeapon *ReadyWeapon;
|
||||||
AWeapon *PendingWeapon; // WP_NOCHANGE if not changing
|
AWeapon *PendingWeapon; // WP_NOCHANGE if not changing
|
||||||
|
|
||||||
int cheats; // bit flags
|
int cheats; // bit flags
|
||||||
|
int timefreezer; // Player has an active time freezer
|
||||||
short refire; // refired shots are less accurate
|
short refire; // refired shots are less accurate
|
||||||
short inconsistant;
|
short inconsistant;
|
||||||
|
bool waiting;
|
||||||
int killcount, itemcount, secretcount; // for intermission
|
int killcount, itemcount, secretcount; // for intermission
|
||||||
int damagecount, bonuscount;// for screen flashing
|
int damagecount, bonuscount;// for screen flashing
|
||||||
int hazardcount; // for delayed Strife damage
|
int hazardcount; // for delayed Strife damage
|
||||||
int poisoncount; // screen flash for poison damage
|
int poisoncount; // screen flash for poison damage
|
||||||
|
FName poisontype; // type of poison damage to apply
|
||||||
|
FName poisonpaintype; // type of Pain state to enter for poison damage
|
||||||
TObjPtr<AActor> poisoner; // NULL for non-player actors
|
TObjPtr<AActor> poisoner; // NULL for non-player actors
|
||||||
TObjPtr<AActor> attacker; // who did damage (NULL for floors)
|
TObjPtr<AActor> attacker; // who did damage (NULL for floors)
|
||||||
int extralight; // so gun flashes light up areas
|
int extralight; // so gun flashes light up areas
|
||||||
|
@ -327,8 +430,6 @@ public:
|
||||||
|
|
||||||
int air_finished; // [RH] Time when you start drowning
|
int air_finished; // [RH] Time when you start drowning
|
||||||
|
|
||||||
WORD accuracy, stamina; // [RH] Strife stats
|
|
||||||
|
|
||||||
FName LastDamageType; // [RH] For damage-specific pain and death sounds
|
FName LastDamageType; // [RH] For damage-specific pain and death sounds
|
||||||
|
|
||||||
//Added by MC:
|
//Added by MC:
|
||||||
|
@ -342,9 +443,9 @@ public:
|
||||||
|
|
||||||
|
|
||||||
TObjPtr<AActor> enemy; // The dead meat.
|
TObjPtr<AActor> enemy; // The dead meat.
|
||||||
TObjPtr<AActor> missile; // A threathing missile that got to be avoided.
|
TObjPtr<AActor> missile; // A threatening missile that needs to be avoided.
|
||||||
TObjPtr<AActor> mate; // Friend (used for grouping in templay or coop.
|
TObjPtr<AActor> mate; // Friend (used for grouping in teamplay or coop).
|
||||||
TObjPtr<AActor> last_mate; // If bots mate dissapeared (not if died) that mate is
|
TObjPtr<AActor> last_mate; // If bots mate disappeared (not if died) that mate is
|
||||||
// pointed to by this. Allows bot to roam to it if
|
// pointed to by this. Allows bot to roam to it if
|
||||||
// necessary.
|
// necessary.
|
||||||
|
|
||||||
|
@ -380,6 +481,9 @@ public:
|
||||||
|
|
||||||
FString LogText; // [RH] Log for Strife
|
FString LogText; // [RH] Log for Strife
|
||||||
|
|
||||||
|
int MinPitch; // Viewpitch limits (negative is up, positive is down)
|
||||||
|
int MaxPitch;
|
||||||
|
|
||||||
SBYTE crouching;
|
SBYTE crouching;
|
||||||
SBYTE crouchdir;
|
SBYTE crouchdir;
|
||||||
fixed_t crouchfactor;
|
fixed_t crouchfactor;
|
||||||
|
@ -407,6 +511,11 @@ public:
|
||||||
crouchviewdelta = 0;
|
crouchviewdelta = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CanCrouch() const
|
||||||
|
{
|
||||||
|
return morphTics == 0 || mo->PlayerFlags & PPF_CROUCHABLEMORPH;
|
||||||
|
}
|
||||||
|
|
||||||
int GetSpawnClass();
|
int GetSpawnClass();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -415,31 +524,31 @@ extern player_t players[MAXPLAYERS];
|
||||||
|
|
||||||
FArchive &operator<< (FArchive &arc, player_t *&p);
|
FArchive &operator<< (FArchive &arc, player_t *&p);
|
||||||
|
|
||||||
void P_CheckPlayerSprites();
|
void P_CheckPlayerSprite(AActor *mo, int &spritenum, fixed_t &scalex, fixed_t &scaley);
|
||||||
|
|
||||||
|
inline void AActor::SetFriendPlayer(player_t *player)
|
||||||
|
{
|
||||||
|
if (player == NULL)
|
||||||
|
{
|
||||||
|
FriendPlayer = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FriendPlayer = int(player - players) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool AActor::IsNoClip2() const
|
||||||
|
{
|
||||||
|
if (player != NULL && player->mo == this)
|
||||||
|
{
|
||||||
|
return (player->cheats & CF_NOCLIP2) != 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#define CROUCHSPEED (FRACUNIT/12)
|
#define CROUCHSPEED (FRACUNIT/12)
|
||||||
|
|
||||||
// [GRB] Custom player classes
|
bool P_IsPlayerTotallyFrozen(const player_t *player);
|
||||||
enum
|
|
||||||
{
|
|
||||||
PCF_NOMENU = 1, // Hide in new game menu
|
|
||||||
};
|
|
||||||
|
|
||||||
class FPlayerClass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FPlayerClass ();
|
|
||||||
FPlayerClass (const FPlayerClass &other);
|
|
||||||
~FPlayerClass ();
|
|
||||||
|
|
||||||
bool CheckSkin (int skin);
|
|
||||||
|
|
||||||
const PClass *Type;
|
|
||||||
DWORD Flags;
|
|
||||||
TArray<int> Skins;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern TArray<FPlayerClass> PlayerClasses;
|
|
||||||
|
|
||||||
#endif // __D_PLAYER_H__
|
#endif // __D_PLAYER_H__
|
||||||
|
|
|
@ -217,10 +217,10 @@ int PackUserCmd (const usercmd_t *ucmd, const usercmd_t *basis, BYTE **stream)
|
||||||
buttons_changed = ucmd->buttons ^ basis->buttons;
|
buttons_changed = ucmd->buttons ^ basis->buttons;
|
||||||
if (buttons_changed != 0)
|
if (buttons_changed != 0)
|
||||||
{
|
{
|
||||||
BYTE bytes[4] = { ucmd->buttons & 0x7F,
|
BYTE bytes[4] = { BYTE(ucmd->buttons & 0x7F),
|
||||||
(ucmd->buttons >> 7) & 0x7F,
|
BYTE((ucmd->buttons >> 7) & 0x7F),
|
||||||
(ucmd->buttons >> 14) & 0x7F,
|
BYTE((ucmd->buttons >> 14) & 0x7F),
|
||||||
(ucmd->buttons >> 21) & 0xFF };
|
BYTE((ucmd->buttons >> 21) & 0xFF) };
|
||||||
|
|
||||||
flags |= UCMDF_BUTTONS;
|
flags |= UCMDF_BUTTONS;
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,11 @@ enum EDemoCommand
|
||||||
DEM_CONVCLOSE, // 60
|
DEM_CONVCLOSE, // 60
|
||||||
DEM_CONVNULL, // 61
|
DEM_CONVNULL, // 61
|
||||||
DEM_RUNSPECIAL, // 62 Byte: Special number, Byte: Arg count, Ints: Args
|
DEM_RUNSPECIAL, // 62 Byte: Special number, Byte: Arg count, Ints: Args
|
||||||
|
DEM_SETPITCHLIMIT, // 63 Byte: Up limit, Byte: Down limit (in degrees)
|
||||||
|
DEM_ADVANCEINTER, // 64 Advance intermission screen state
|
||||||
|
DEM_RUNNAMEDSCRIPT, // 65 String: Script name, Byte: Arg count + Always flag; each arg is a 4-byte int
|
||||||
|
DEM_REVERTCAMERA, // 66
|
||||||
|
DEM_SETSLOTPNUM, // 67 Byte: player number, the rest is the same as DEM_SETSLOT
|
||||||
};
|
};
|
||||||
|
|
||||||
// The following are implemented by cht_DoCheat in m_cheat.cpp
|
// The following are implemented by cht_DoCheat in m_cheat.cpp
|
||||||
|
@ -213,7 +218,8 @@ enum ECheatCommand
|
||||||
CHT_GIMMIEI,
|
CHT_GIMMIEI,
|
||||||
CHT_GIMMIEJ,
|
CHT_GIMMIEJ,
|
||||||
CHT_GIMMIEZ,
|
CHT_GIMMIEZ,
|
||||||
CHT_BUDDHA
|
CHT_BUDDHA,
|
||||||
|
CHT_NOCLIP2
|
||||||
};
|
};
|
||||||
|
|
||||||
void StartChunk (int id, BYTE **stream);
|
void StartChunk (int id, BYTE **stream);
|
||||||
|
|
|
@ -631,7 +631,10 @@ void FDecalLib::ParseGenerator (FScanner &sc)
|
||||||
}
|
}
|
||||||
|
|
||||||
actor->DecalGenerator = decal;
|
actor->DecalGenerator = decal;
|
||||||
|
if (decal != NULL)
|
||||||
|
{
|
||||||
decal->Users.Push (type);
|
decal->Users.Push (type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FDecalLib::ParseFader (FScanner &sc)
|
void FDecalLib::ParseFader (FScanner &sc)
|
||||||
|
@ -1121,16 +1124,19 @@ FDecalLib::FTranslation *FDecalLib::FTranslation::LocateTranslation (DWORD start
|
||||||
const FDecalTemplate *FDecalGroup::GetDecal () const
|
const FDecalTemplate *FDecalGroup::GetDecal () const
|
||||||
{
|
{
|
||||||
const FDecalBase *decal = Choices.PickEntry ();
|
const FDecalBase *decal = Choices.PickEntry ();
|
||||||
const FDecalBase *remember;
|
const FDecalBase *remember = decal;
|
||||||
|
|
||||||
// Repeatedly GetDecal() until the result is constant, since
|
// Repeatedly GetDecal() until the result is constant, since
|
||||||
// the choice might be another FDecalGroup.
|
// the choice might be another FDecalGroup.
|
||||||
|
if (decal != NULL)
|
||||||
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
remember = decal;
|
remember = decal;
|
||||||
decal = decal->GetDecal ();
|
decal = decal->GetDecal ();
|
||||||
} while (decal != remember);
|
} while (decal != NULL && decal != remember);
|
||||||
return static_cast<const FDecalTemplate *>(decal);
|
}
|
||||||
|
return static_cast<const FDecalTemplate *>(remember);
|
||||||
}
|
}
|
||||||
|
|
||||||
FDecalAnimator::FDecalAnimator (const char *name)
|
FDecalAnimator::FDecalAnimator (const char *name)
|
||||||
|
|
|
@ -453,8 +453,9 @@ size_t DObject::PropagateMark()
|
||||||
GC::Mark((DObject **)((BYTE *)this + *offsets));
|
GC::Mark((DObject **)((BYTE *)this + *offsets));
|
||||||
offsets++;
|
offsets++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return info->Size;
|
return info->Size;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
|
size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
|
||||||
|
|
|
@ -242,8 +242,10 @@ static DObject **SweepList(DObject **p, size_t count, size_t *finalize_count)
|
||||||
// be in a thinker list, then I need to add write barriers for every time a
|
// be in a thinker list, then I need to add write barriers for every time a
|
||||||
// thinker pointer is changed. This seems easier and perfectly reasonable, since
|
// thinker pointer is changed. This seems easier and perfectly reasonable, since
|
||||||
// a live thinker that isn't on a thinker list isn't much of a thinker.
|
// a live thinker that isn't on a thinker list isn't much of a thinker.
|
||||||
assert(!curr->IsKindOf(RUNTIME_CLASS(DThinker)) || (curr->ObjectFlags & OF_Sentinel));
|
|
||||||
assert(!curr->IsKindOf(RUNTIME_CLASS(DInterpolation)));
|
// However, this can happen during deletion of the thinker list while cleaning up
|
||||||
|
// from a savegame error so we can't assume that any thinker that gets here is an error.
|
||||||
|
|
||||||
curr->Destroy();
|
curr->Destroy();
|
||||||
}
|
}
|
||||||
curr->ObjectFlags |= OF_Cleanup;
|
curr->ObjectFlags |= OF_Cleanup;
|
||||||
|
@ -305,6 +307,7 @@ static void MarkRoot()
|
||||||
DThinker::MarkRoots();
|
DThinker::MarkRoots();
|
||||||
FCanvasTextureInfo::Mark();
|
FCanvasTextureInfo::Mark();
|
||||||
Mark(DACSThinker::ActiveThinker);
|
Mark(DACSThinker::ActiveThinker);
|
||||||
|
Mark(level.DefaultSkybox);
|
||||||
// Mark dead bodies.
|
// Mark dead bodies.
|
||||||
for (i = 0; i < BODYQUESIZE; ++i)
|
for (i = 0; i < BODYQUESIZE; ++i)
|
||||||
{
|
{
|
||||||
|
@ -531,7 +534,12 @@ void Barrier(DObject *pointing, DObject *pointed)
|
||||||
|
|
||||||
void DelSoftRootHead()
|
void DelSoftRootHead()
|
||||||
{
|
{
|
||||||
if (SoftRoots != NULL) delete SoftRoots;
|
if (SoftRoots != NULL)
|
||||||
|
{
|
||||||
|
// Don't let the destructor print a warning message
|
||||||
|
SoftRoots->ObjectFlags |= OF_YesReallyDelete;
|
||||||
|
delete SoftRoots;
|
||||||
|
}
|
||||||
SoftRoots = NULL;
|
SoftRoots = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -357,8 +357,8 @@ unsigned int PClass::Extend(unsigned int extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Like FindClass but creates a placeholder if no class
|
// Like FindClass but creates a placeholder if no class
|
||||||
// is found. CreateDerivedClass will automatcally fill in
|
// is found. CreateDerivedClass will automatically fill
|
||||||
// the placeholder when the actual class is defined.
|
// in the placeholder when the actual class is defined.
|
||||||
const PClass *PClass::FindClassTentative (FName name)
|
const PClass *PClass::FindClassTentative (FName name)
|
||||||
{
|
{
|
||||||
if (name == NAME_None)
|
if (name == NAME_None)
|
||||||
|
|
|
@ -400,11 +400,25 @@ enum EMapThingFlags
|
||||||
STF_ALTSHADOW = 0x0200,
|
STF_ALTSHADOW = 0x0200,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A simplified mapthing for player starts
|
||||||
|
struct FPlayerStart
|
||||||
|
{
|
||||||
|
fixed_t x, y, z;
|
||||||
|
short angle, type;
|
||||||
|
|
||||||
|
FPlayerStart() { }
|
||||||
|
FPlayerStart(const FMapThing *mthing)
|
||||||
|
: x(mthing->x), y(mthing->y), z(mthing->z),
|
||||||
|
angle(mthing->angle),
|
||||||
|
type(mthing->type)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
// Player spawn spots for deathmatch.
|
// Player spawn spots for deathmatch.
|
||||||
extern TArray<FMapThing> deathmatchstarts;
|
extern TArray<FPlayerStart> deathmatchstarts;
|
||||||
|
|
||||||
// Player spawn spots.
|
// Player spawn spots.
|
||||||
extern FMapThing playerstarts[MAXPLAYERS];
|
extern FPlayerStart playerstarts[MAXPLAYERS];
|
||||||
|
extern TArray<FPlayerStart> AllPlayerStarts;
|
||||||
|
|
||||||
|
|
||||||
#endif // __DOOMDATA__
|
#endif // __DOOMDATA__
|
||||||
|
|
|
@ -333,7 +333,10 @@ enum
|
||||||
COMPATF_HITSCAN = 1 << 28, // Hitscans use original blockmap anf hit check code.
|
COMPATF_HITSCAN = 1 << 28, // Hitscans use original blockmap anf hit check code.
|
||||||
COMPATF_LIGHT = 1 << 29, // Find neighboring light level like Doom
|
COMPATF_LIGHT = 1 << 29, // Find neighboring light level like Doom
|
||||||
COMPATF_POLYOBJ = 1 << 30, // Draw polyobjects the old fashioned way
|
COMPATF_POLYOBJ = 1 << 30, // Draw polyobjects the old fashioned way
|
||||||
COMPATF_MASKEDMIDTEX = 1 << 31, // Ignore compositing when drawing masked midtextures
|
COMPATF_MASKEDMIDTEX = 1u << 31, // Ignore compositing when drawing masked midtextures
|
||||||
|
|
||||||
|
COMPATF2_BADANGLES = 1 << 0, // It is impossible to face directly NSEW.
|
||||||
|
COMPATF2_FLOORMOVE = 1 << 1, // Use the same floor motion behavior as Doom.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Emulate old bugs for select maps. These are not exposed by a cvar
|
// Emulate old bugs for select maps. These are not exposed by a cvar
|
||||||
|
@ -345,6 +348,7 @@ enum
|
||||||
BCOMPATF_VILEGHOSTS = 1 << 2, // Monsters' radius and height aren't restored properly when resurrected.
|
BCOMPATF_VILEGHOSTS = 1 << 2, // Monsters' radius and height aren't restored properly when resurrected.
|
||||||
BCOMPATF_BADTELEPORTERS = 1 << 3, // Ignore tags on Teleport specials
|
BCOMPATF_BADTELEPORTERS = 1 << 3, // Ignore tags on Teleport specials
|
||||||
BCOMPATF_BADPORTALS = 1 << 4, // Restores the old unstable portal behavior
|
BCOMPATF_BADPORTALS = 1 << 4, // Restores the old unstable portal behavior
|
||||||
|
BCOMPATF_REBUILDNODES = 1 << 5, // Force node rebuild
|
||||||
};
|
};
|
||||||
|
|
||||||
// phares 3/20/98:
|
// phares 3/20/98:
|
||||||
|
|
|
@ -230,6 +230,7 @@ struct DehInfo
|
||||||
BYTE ExplosionStyle;
|
BYTE ExplosionStyle;
|
||||||
fixed_t ExplosionAlpha;
|
fixed_t ExplosionAlpha;
|
||||||
int NoAutofreeze;
|
int NoAutofreeze;
|
||||||
|
int BFGCells;
|
||||||
};
|
};
|
||||||
extern DehInfo deh;
|
extern DehInfo deh;
|
||||||
EXTERN_CVAR (Int, infighting)
|
EXTERN_CVAR (Int, infighting)
|
||||||
|
@ -240,6 +241,7 @@ EXTERN_CVAR (Int, dmflags);
|
||||||
EXTERN_CVAR (Int, dmflags2); // [BC]
|
EXTERN_CVAR (Int, dmflags2); // [BC]
|
||||||
|
|
||||||
EXTERN_CVAR (Int, compatflags);
|
EXTERN_CVAR (Int, compatflags);
|
||||||
extern int i_compatflags, ii_compatflags, ib_compatflags;
|
EXTERN_CVAR (Int, compatflags2);
|
||||||
|
extern int i_compatflags, i_compatflags2, ii_compatflags, ii_compatflags2, ib_compatflags;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -223,7 +223,7 @@ DMover::EResult DMover::MovePlane (fixed_t speed, fixed_t dest, int crush,
|
||||||
//destheight = (dest < m_Sector->ceilingheight) ? dest : m_Sector->ceilingheight;
|
//destheight = (dest < m_Sector->ceilingheight) ? dest : m_Sector->ceilingheight;
|
||||||
if ((m_Sector->ceilingplane.a | m_Sector->ceilingplane.b |
|
if ((m_Sector->ceilingplane.a | m_Sector->ceilingplane.b |
|
||||||
m_Sector->floorplane.a | m_Sector->floorplane.b) == 0 &&
|
m_Sector->floorplane.a | m_Sector->floorplane.b) == 0 &&
|
||||||
-dest > m_Sector->ceilingplane.d)
|
(!(i_compatflags2 & COMPATF2_FLOORMOVE) && -dest > m_Sector->ceilingplane.d))
|
||||||
{
|
{
|
||||||
dest = -m_Sector->ceilingplane.d;
|
dest = -m_Sector->ceilingplane.d;
|
||||||
}
|
}
|
||||||
|
@ -292,7 +292,7 @@ DMover::EResult DMover::MovePlane (fixed_t speed, fixed_t dest, int crush,
|
||||||
//destheight = (dest > m_Sector->floorheight) ? dest : m_Sector->floorheight;
|
//destheight = (dest > m_Sector->floorheight) ? dest : m_Sector->floorheight;
|
||||||
if ((m_Sector->ceilingplane.a | m_Sector->ceilingplane.b |
|
if ((m_Sector->ceilingplane.a | m_Sector->ceilingplane.b |
|
||||||
m_Sector->floorplane.a | m_Sector->floorplane.b) == 0 &&
|
m_Sector->floorplane.a | m_Sector->floorplane.b) == 0 &&
|
||||||
dest < -m_Sector->floorplane.d)
|
(!(i_compatflags2 & COMPATF2_FLOORMOVE) && dest < -m_Sector->floorplane.d))
|
||||||
{
|
{
|
||||||
dest = -m_Sector->floorplane.d;
|
dest = -m_Sector->floorplane.d;
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,19 +192,10 @@ void DThinker::SerializeAll(FArchive &arc, bool hubLoad)
|
||||||
statcount--;
|
statcount--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (class CDoomError &err)
|
catch (class CDoomError &)
|
||||||
{
|
{
|
||||||
bSerialOverride = false;
|
bSerialOverride = false;
|
||||||
|
DestroyAllThinkers();
|
||||||
// DestroyAllThinkers cannot be called here. It will try to delete the corrupted
|
|
||||||
// object table left behind by the serializer and crash.
|
|
||||||
// Trying to continue is not an option here because the garbage collector will
|
|
||||||
// crash the next time it runs.
|
|
||||||
// Even making this a fatal error will crash but at least the message can be seen
|
|
||||||
// before the crash - which is not the case with all other options.
|
|
||||||
|
|
||||||
//DestroyAllThinkers();
|
|
||||||
I_FatalError("%s", err.GetMessage());
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
bSerialOverride = false;
|
bSerialOverride = false;
|
||||||
|
@ -457,7 +448,7 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
|
||||||
NextToThink = node->NextThinker;
|
NextToThink = node->NextThinker;
|
||||||
if (node->ObjectFlags & OF_JustSpawned)
|
if (node->ObjectFlags & OF_JustSpawned)
|
||||||
{
|
{
|
||||||
node->ObjectFlags &= ~OF_JustSpawned;
|
// Leave OF_JustSpawn set until after Tick() so the ticker can check it.
|
||||||
if (dest != NULL)
|
if (dest != NULL)
|
||||||
{ // Move thinker from this list to the destination list
|
{ // Move thinker from this list to the destination list
|
||||||
node->Remove();
|
node->Remove();
|
||||||
|
@ -472,7 +463,8 @@ int DThinker::TickThinkers (FThinkerList *list, FThinkerList *dest)
|
||||||
|
|
||||||
if (!(node->ObjectFlags & OF_EuthanizeMe))
|
if (!(node->ObjectFlags & OF_EuthanizeMe))
|
||||||
{ // Only tick thinkers not scheduled for destruction
|
{ // Only tick thinkers not scheduled for destruction
|
||||||
node->Tick ();
|
node->Tick();
|
||||||
|
node->ObjectFlags &= ~OF_JustSpawned;
|
||||||
GC::CheckGC();
|
GC::CheckGC();
|
||||||
}
|
}
|
||||||
node = NextToThink;
|
node = NextToThink;
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
|
#include "m_misc.h"
|
||||||
#include "dobject.h"
|
#include "dobject.h"
|
||||||
|
|
||||||
// These are special tokens found in the data stream of an archive.
|
// These are special tokens found in the data stream of an archive.
|
||||||
|
@ -405,7 +406,7 @@ void FCompressedFile::Explode ()
|
||||||
if (r != Z_OK || newlen != expandsize)
|
if (r != Z_OK || newlen != expandsize)
|
||||||
{
|
{
|
||||||
M_Free (expand);
|
M_Free (expand);
|
||||||
I_Error ("Could not decompress cfile");
|
I_Error ("Could not decompress buffer: %s", M_ZLibError(r).GetChars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -497,7 +498,18 @@ bool FCompressedMemFile::Reopen ()
|
||||||
m_Mode = EReading;
|
m_Mode = EReading;
|
||||||
m_Buffer = m_ImplodedBuffer;
|
m_Buffer = m_ImplodedBuffer;
|
||||||
m_SourceFromMem = true;
|
m_SourceFromMem = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
Explode ();
|
Explode ();
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
// If we just leave things as they are, m_Buffer and m_ImplodedBuffer
|
||||||
|
// both point to the same memory block and both will try to free it.
|
||||||
|
m_Buffer = NULL;
|
||||||
|
m_SourceFromMem = false;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
m_SourceFromMem = false;
|
m_SourceFromMem = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -560,6 +572,20 @@ bool FCompressedMemFile::IsOpen () const
|
||||||
return !!m_Buffer;
|
return !!m_Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FCompressedMemFile::GetSizes(unsigned int &compressed, unsigned int &uncompressed) const
|
||||||
|
{
|
||||||
|
if (m_ImplodedBuffer != NULL)
|
||||||
|
{
|
||||||
|
compressed = BigLong(*(unsigned int *)m_ImplodedBuffer);
|
||||||
|
uncompressed = BigLong(*(unsigned int *)(m_ImplodedBuffer + 4));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
compressed = 0;
|
||||||
|
uncompressed = m_BufferSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FPNGChunkFile::FPNGChunkFile (FILE *file, DWORD id)
|
FPNGChunkFile::FPNGChunkFile (FILE *file, DWORD id)
|
||||||
: FCompressedFile (file, EWriting, true, false), m_ChunkID (id)
|
: FCompressedFile (file, EWriting, true, false), m_ChunkID (id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -124,6 +124,7 @@ public:
|
||||||
bool Reopen (); // Re-opens imploded file for reading only
|
bool Reopen (); // Re-opens imploded file for reading only
|
||||||
void Close ();
|
void Close ();
|
||||||
bool IsOpen () const;
|
bool IsOpen () const;
|
||||||
|
void GetSizes(unsigned int &one, unsigned int &two) const;
|
||||||
|
|
||||||
void Serialize (FArchive &arc);
|
void Serialize (FArchive &arc);
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
|
#include "m_misc.h"
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -145,11 +146,16 @@ long FileReader::Read (void *buffer, long len)
|
||||||
|
|
||||||
char *FileReader::Gets(char *strbuf, int len)
|
char *FileReader::Gets(char *strbuf, int len)
|
||||||
{
|
{
|
||||||
if (len <= 0) return 0;
|
if (len <= 0 || FilePos >= StartPos + Length) return NULL;
|
||||||
char *p = fgets(strbuf, len, File);
|
char *p = fgets(strbuf, len, File);
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
{
|
{
|
||||||
FilePos = ftell(File) - StartPos;
|
int old = FilePos;
|
||||||
|
FilePos = ftell(File);
|
||||||
|
if (FilePos - StartPos > Length)
|
||||||
|
{
|
||||||
|
strbuf[Length - old + StartPos] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -218,7 +224,7 @@ FileReaderZ::FileReaderZ (FileReader &file, bool zip)
|
||||||
|
|
||||||
if (err != Z_OK)
|
if (err != Z_OK)
|
||||||
{
|
{
|
||||||
I_Error ("FileReaderZ: inflateInit failed: %d\n", err);
|
I_Error ("FileReaderZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -774,7 +774,7 @@ void FParser::SF_PlayerName(void)
|
||||||
if(plnum !=-1)
|
if(plnum !=-1)
|
||||||
{
|
{
|
||||||
t_return.type = svt_string;
|
t_return.type = svt_string;
|
||||||
t_return.string = players[plnum].userinfo.netname;
|
t_return.string = players[plnum].userinfo.GetName();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3367,7 +3367,7 @@ void FParser::SF_RadiusAttack()
|
||||||
|
|
||||||
if (spot && source)
|
if (spot && source)
|
||||||
{
|
{
|
||||||
P_RadiusAttack(spot, source, damage, damage, NAME_None, true);
|
P_RadiusAttack(spot, source, damage, damage, NAME_None, RADF_HURTSOURCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3747,7 +3747,7 @@ void FParser::SF_LineAttack()
|
||||||
angle = (intvalue(t_argv[1]) * (ANG45 / 45));
|
angle = (intvalue(t_argv[1]) * (ANG45 / 45));
|
||||||
slope = P_AimLineAttack(mo, angle, MISSILERANGE);
|
slope = P_AimLineAttack(mo, angle, MISSILERANGE);
|
||||||
|
|
||||||
P_LineAttack(mo, angle, MISSILERANGE, slope, damage, NAME_None, NAME_BulletPuff);
|
P_LineAttack(mo, angle, MISSILERANGE, slope, damage, NAME_Hitscan, NAME_BulletPuff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4256,7 +4256,7 @@ void FParser::SF_SpawnShot2(void)
|
||||||
S_Sound (mo, CHAN_VOICE, mo->SeeSound, 1, ATTN_NORM);
|
S_Sound (mo, CHAN_VOICE, mo->SeeSound, 1, ATTN_NORM);
|
||||||
mo->target = source;
|
mo->target = source;
|
||||||
P_ThrustMobj(mo, mo->angle = source->angle, mo->Speed);
|
P_ThrustMobj(mo, mo->angle = source->angle, mo->Speed);
|
||||||
if (!P_CheckMissileSpawn(mo)) mo = NULL;
|
if (!P_CheckMissileSpawn(mo, source->radius)) mo = NULL;
|
||||||
}
|
}
|
||||||
t_return.value.mobj = mo;
|
t_return.value.mobj = mo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,7 +316,7 @@ bool FScriptLoader::ParseInfo(MapData * map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
delete lump;
|
delete[] lump;
|
||||||
return HasScripts;
|
return HasScripts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ void T_LoadScripts(MapData *map)
|
||||||
// the default translator is being used.
|
// the default translator is being used.
|
||||||
// Custom translators will not be patched.
|
// Custom translators will not be patched.
|
||||||
if ((gameinfo.gametype == GAME_Doom || gameinfo.gametype == GAME_Heretic) && level.info->Translator.IsEmpty() &&
|
if ((gameinfo.gametype == GAME_Doom || gameinfo.gametype == GAME_Heretic) && level.info->Translator.IsEmpty() &&
|
||||||
level.maptype == MAPTYPE_DOOM && SimpleLineTranslations[272 - 2*HasScripts].special == FS_Execute)
|
level.maptype == MAPTYPE_DOOM && SimpleLineTranslations.Size() > 272 && SimpleLineTranslations[272 - 2*HasScripts].special == FS_Execute)
|
||||||
{
|
{
|
||||||
FLineTrans t = SimpleLineTranslations[270];
|
FLineTrans t = SimpleLineTranslations[270];
|
||||||
SimpleLineTranslations[270] = SimpleLineTranslations[272];
|
SimpleLineTranslations[270] = SimpleLineTranslations[272];
|
||||||
|
|
|
@ -123,8 +123,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
S_Sound (self, CHAN_WEAPON, snd, 1, ATTN_NORM);
|
S_Sound (self, CHAN_WEAPON, snd, 1, ATTN_NORM);
|
||||||
P_TraceBleed (dmg, target);
|
int newdam = P_DamageMobj (target, self, self, dmg, NAME_None);
|
||||||
P_DamageMobj (target, self, self, dmg, NAME_None);
|
P_TraceBleed (newdam > 0 ? newdam : dmg, target);
|
||||||
|
|
||||||
an = self->angle >> ANGLETOFINESHIFT;
|
an = self->angle >> ANGLETOFINESHIFT;
|
||||||
fire = self->tracer;
|
fire = self->tracer;
|
||||||
|
@ -136,7 +136,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack)
|
||||||
target->y - FixedMul (24*FRACUNIT, finesine[an]),
|
target->y - FixedMul (24*FRACUNIT, finesine[an]),
|
||||||
target->z);
|
target->z);
|
||||||
|
|
||||||
P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, false);
|
P_RadiusAttack (fire, self, blastdmg, blastrad, dmgtype, 0);
|
||||||
}
|
}
|
||||||
target->velz = Scale(thrust, 1000, target->Mass);
|
target->velz = Scale(thrust, 1000, target->Mass);
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,17 +78,23 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainDie)
|
||||||
|
|
||||||
// New dmflag: Kill all boss spawned monsters before ending the level.
|
// New dmflag: Kill all boss spawned monsters before ending the level.
|
||||||
if (dmflags2 & DF2_KILLBOSSMONST)
|
if (dmflags2 & DF2_KILLBOSSMONST)
|
||||||
|
{
|
||||||
|
int count; // Repeat until we have no more boss-spawned monsters.
|
||||||
|
do // (e.g. Pain Elementals can spawn more to kill upon death.)
|
||||||
{
|
{
|
||||||
TThinkerIterator<AActor> it;
|
TThinkerIterator<AActor> it;
|
||||||
AActor *mo;
|
AActor *mo;
|
||||||
|
count = 0;
|
||||||
while ((mo = it.Next()))
|
while ((mo = it.Next()))
|
||||||
{
|
{
|
||||||
if (mo->flags4 & MF4_BOSSSPAWNED)
|
if (mo->health > 0 && mo->flags4 & MF4_BOSSSPAWNED)
|
||||||
{
|
{
|
||||||
P_DamageMobj(mo, self, self, mo->health, NAME_None,
|
P_DamageMobj(mo, self, self, mo->health, NAME_None,
|
||||||
DMG_NO_ARMOR|DMG_FORCED|DMG_THRUSTLESS|DMG_NO_FACTOR);
|
DMG_NO_ARMOR|DMG_FORCED|DMG_THRUSTLESS|DMG_NO_FACTOR);
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} while (count != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_ExitLevel (0, false);
|
G_ExitLevel (0, false);
|
||||||
|
@ -118,12 +124,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit)
|
||||||
// spawn brain missile
|
// spawn brain missile
|
||||||
spit = P_SpawnMissile (self, targ, spawntype);
|
spit = P_SpawnMissile (self, targ, spawntype);
|
||||||
|
|
||||||
|
if (spit != NULL)
|
||||||
|
{
|
||||||
// Boss cubes should move freely to their destination so it's
|
// Boss cubes should move freely to their destination so it's
|
||||||
// probably best to disable all collision detection for them.
|
// probably best to disable all collision detection for them.
|
||||||
if (spit->flags & MF_NOCLIP) spit->flags5 |= MF5_NOINTERACTION;
|
if (spit->flags & MF_NOCLIP) spit->flags5 |= MF5_NOINTERACTION;
|
||||||
|
|
||||||
if (spit != NULL)
|
|
||||||
{
|
|
||||||
spit->target = targ;
|
spit->target = targ;
|
||||||
spit->master = self;
|
spit->master = self;
|
||||||
// [RH] Do this correctly for any trajectory. Doom would divide by 0
|
// [RH] Do this correctly for any trajectory. Doom would divide by 0
|
||||||
|
@ -258,9 +264,14 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
|
||||||
{
|
{
|
||||||
newmobj->CopyFriendliness (eye, false);
|
newmobj->CopyFriendliness (eye, false);
|
||||||
}
|
}
|
||||||
if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true, NULL))
|
// Make it act as if it was around when the player first made noise
|
||||||
newmobj->SetState (newmobj->SeeState);
|
// (if the player has made noise).
|
||||||
|
newmobj->LastHeard = newmobj->Sector->SoundTarget;
|
||||||
|
|
||||||
|
if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true, NULL))
|
||||||
|
{
|
||||||
|
newmobj->SetState (newmobj->SeeState);
|
||||||
|
}
|
||||||
if (!(newmobj->ObjectFlags & OF_EuthanizeMe))
|
if (!(newmobj->ObjectFlags & OF_EuthanizeMe))
|
||||||
{
|
{
|
||||||
// telefrag anything in this spot
|
// telefrag anything in this spot
|
||||||
|
|
|
@ -10,8 +10,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_BruisAttack)
|
||||||
{
|
{
|
||||||
int damage = (pr_bruisattack()%8+1)*10;
|
int damage = (pr_bruisattack()%8+1)*10;
|
||||||
S_Sound (self, CHAN_WEAPON, "baron/melee", 1, ATTN_NORM);
|
S_Sound (self, CHAN_WEAPON, "baron/melee", 1, ATTN_NORM);
|
||||||
P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||||
P_TraceBleed (damage, self->target, self);
|
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_HeadAttack)
|
||||||
{
|
{
|
||||||
int damage = (pr_headattack()%6+1)*10;
|
int damage = (pr_headattack()%6+1)*10;
|
||||||
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
|
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
|
||||||
P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||||
P_TraceBleed (damage, self->target, self);
|
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SargAttack)
|
||||||
if (self->CheckMeleeRange ())
|
if (self->CheckMeleeRange ())
|
||||||
{
|
{
|
||||||
int damage = ((pr_sargattack()%10)+1)*4;
|
int damage = ((pr_sargattack()%10)+1)*4;
|
||||||
P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||||
P_TraceBleed (damage, self->target, self);
|
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_TroopAttack)
|
||||||
{
|
{
|
||||||
int damage = (pr_troopattack()%8+1)*3;
|
int damage = (pr_troopattack()%8+1)*3;
|
||||||
S_Sound (self, CHAN_WEAPON, "imp/melee", 1, ATTN_NORM);
|
S_Sound (self, CHAN_WEAPON, "imp/melee", 1, ATTN_NORM);
|
||||||
P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||||
P_TraceBleed (damage, self->target, self);
|
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,7 @@
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_BarrelDestroy)
|
DEFINE_ACTION_FUNCTION(AActor, A_BarrelDestroy)
|
||||||
{
|
{
|
||||||
if ((dmflags2 & DF2_BARRELS_RESPAWN) &&
|
if (dmflags2 & DF2_BARRELS_RESPAWN)
|
||||||
(deathmatch || alwaysapplydmflags))
|
|
||||||
{
|
{
|
||||||
self->height = self->GetDefault()->height;
|
self->height = self->GetDefault()->height;
|
||||||
self->renderflags |= RF_INVISIBLE;
|
self->renderflags |= RF_INVISIBLE;
|
||||||
|
@ -50,4 +49,3 @@ DEFINE_ACTION_FUNCTION(AActor, A_BarrelDestroy)
|
||||||
self->Destroy ();
|
self->Destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue