mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-02-17 09:01:22 +00:00
Merge commit '772a5724313f2ad0bd6828fcc28545a9ee5e6068' into scripting
Conflicts: src/p_pspr.cpp src/thingdef/thingdef_codeptr.cpp
This commit is contained in:
commit
cfcd2668cc
94 changed files with 6367 additions and 965 deletions
|
@ -123,7 +123,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS( GME
|
||||||
if( MSVC )
|
if( MSVC )
|
||||||
# Eliminate unreferenced functions and data
|
# Eliminate unreferenced functions and data
|
||||||
# Perform identical COMDAT folding
|
# Perform identical COMDAT folding
|
||||||
set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt /TSAWARE" )
|
set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt /TSAWARE /LARGEADDRESSAWARE" )
|
||||||
|
|
||||||
# String pooling
|
# String pooling
|
||||||
# Function-level linking
|
# Function-level linking
|
||||||
|
|
|
@ -39,7 +39,6 @@ add_library( dumb
|
||||||
src/helpers/memfile.c
|
src/helpers/memfile.c
|
||||||
src/helpers/clickrem.c
|
src/helpers/clickrem.c
|
||||||
src/helpers/barray.c
|
src/helpers/barray.c
|
||||||
src/helpers/tarray.c
|
|
||||||
src/it/xmeffect.c
|
src/it/xmeffect.c
|
||||||
src/it/readxm2.c
|
src/it/readxm2.c
|
||||||
src/it/readxm.c
|
src/it/readxm.c
|
||||||
|
|
|
@ -36,24 +36,24 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define DUMB_MAJOR_VERSION 0
|
#define DUMB_MAJOR_VERSION 1
|
||||||
#define DUMB_MINOR_VERSION 9
|
#define DUMB_MINOR_VERSION 0
|
||||||
#define DUMB_REVISION_VERSION 3
|
#define DUMB_REVISION_VERSION 0
|
||||||
|
|
||||||
#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION)
|
#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION)
|
||||||
|
|
||||||
#define DUMB_VERSION_STR "0.9.3"
|
#define DUMB_VERSION_STR "1.0.0"
|
||||||
|
|
||||||
#define DUMB_NAME "DUMB v" DUMB_VERSION_STR
|
#define DUMB_NAME "DUMB v" DUMB_VERSION_STR
|
||||||
|
|
||||||
#define DUMB_YEAR 2005
|
#define DUMB_YEAR 2015
|
||||||
#define DUMB_MONTH 8
|
#define DUMB_MONTH 1
|
||||||
#define DUMB_DAY 7
|
#define DUMB_DAY 17
|
||||||
|
|
||||||
#define DUMB_YEAR_STR2 "05"
|
#define DUMB_YEAR_STR2 "15"
|
||||||
#define DUMB_YEAR_STR4 "2005"
|
#define DUMB_YEAR_STR4 "2015"
|
||||||
#define DUMB_MONTH_STR1 "8"
|
#define DUMB_MONTH_STR1 "1"
|
||||||
#define DUMB_DAY_STR1 "7"
|
#define DUMB_DAY_STR1 "17"
|
||||||
|
|
||||||
#if DUMB_MONTH < 10
|
#if DUMB_MONTH < 10
|
||||||
#define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1
|
#define DUMB_MONTH_STR2 "0" DUMB_MONTH_STR1
|
||||||
|
@ -606,10 +606,6 @@ typedef void (*DUH_SIGRENDERER_GET_CURRENT_SAMPLE)(
|
||||||
sample_t *samples
|
sample_t *samples
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef int32 (*DUH_SIGRENDERER_GET_POSITION)(
|
|
||||||
sigrenderer_t *sigrenderer
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef void (*DUH_END_SIGRENDERER)(sigrenderer_t *sigrenderer);
|
typedef void (*DUH_END_SIGRENDERER)(sigrenderer_t *sigrenderer);
|
||||||
|
|
||||||
typedef void (*DUH_UNLOAD_SIGDATA)(sigdata_t *sigdata);
|
typedef void (*DUH_UNLOAD_SIGDATA)(sigdata_t *sigdata);
|
||||||
|
@ -625,7 +621,6 @@ typedef struct DUH_SIGTYPE_DESC
|
||||||
DUH_SIGRENDERER_SET_SIGPARAM sigrenderer_set_sigparam;
|
DUH_SIGRENDERER_SET_SIGPARAM sigrenderer_set_sigparam;
|
||||||
DUH_SIGRENDERER_GENERATE_SAMPLES sigrenderer_generate_samples;
|
DUH_SIGRENDERER_GENERATE_SAMPLES sigrenderer_generate_samples;
|
||||||
DUH_SIGRENDERER_GET_CURRENT_SAMPLE sigrenderer_get_current_sample;
|
DUH_SIGRENDERER_GET_CURRENT_SAMPLE sigrenderer_get_current_sample;
|
||||||
DUH_SIGRENDERER_GET_POSITION sigrenderer_get_position;
|
|
||||||
DUH_END_SIGRENDERER end_sigrenderer;
|
DUH_END_SIGRENDERER end_sigrenderer;
|
||||||
DUH_UNLOAD_SIGDATA unload_sigdata;
|
DUH_UNLOAD_SIGDATA unload_sigdata;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "barray.h"
|
#include "barray.h"
|
||||||
#include "tarray.h"
|
|
||||||
|
|
||||||
|
|
||||||
/** TO DO: THINK ABOUT THE FOLLOWING:
|
/** TO DO: THINK ABOUT THE FOLLOWING:
|
||||||
|
@ -724,21 +723,6 @@ struct DUMB_IT_SIGRENDERER
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
#ifdef BIT_ARRAY_BULLSHIT
|
||||||
/* bit array, which rows are played, only checked by pattern break or loop commands */
|
/* bit array, which rows are played, only checked by pattern break or loop commands */
|
||||||
void * played;
|
void * played;
|
||||||
|
|
||||||
/*
|
|
||||||
Loop indicator for internal processes, may also be useful for external processes
|
|
||||||
0 - Not looped
|
|
||||||
1 - Looped
|
|
||||||
-1 - Continued past loop
|
|
||||||
*/
|
|
||||||
int looped;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Kept until looped
|
|
||||||
*/
|
|
||||||
LONG_LONG time_played;
|
|
||||||
|
|
||||||
void * row_timekeeper;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int32 gvz_time;
|
int32 gvz_time;
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
#ifndef _T_ARRAY_H_
|
|
||||||
#define _T_ARRAY_H_
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifndef LONG_LONG
|
|
||||||
#if defined __GNUC__ || defined __INTEL_COMPILER || defined __MWERKS__
|
|
||||||
#define LONG_LONG long long
|
|
||||||
#elif defined _MSC_VER || defined __WATCOMC__
|
|
||||||
#define LONG_LONG __int64
|
|
||||||
#elif defined __sgi
|
|
||||||
#define LONG_LONG long long
|
|
||||||
#else
|
|
||||||
#error 64-bit integer type unknown
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void * timekeeping_array_create(size_t size);
|
|
||||||
void timekeeping_array_destroy(void * array);
|
|
||||||
void * timekeeping_array_dup(void * array);
|
|
||||||
|
|
||||||
void timekeeping_array_reset(void * array, size_t loop_start);
|
|
||||||
|
|
||||||
void timekeeping_array_push(void * array, size_t index, LONG_LONG time);
|
|
||||||
void timekeeping_array_bump(void * array, size_t index);
|
|
||||||
|
|
||||||
unsigned int timekeeping_array_get_count(void * array, size_t index);
|
|
||||||
|
|
||||||
LONG_LONG timekeeping_array_get_item(void * array, size_t index);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -37,7 +37,6 @@ SOURCES += \
|
||||||
../../src/helpers/memfile.c \
|
../../src/helpers/memfile.c \
|
||||||
../../src/helpers/clickrem.c \
|
../../src/helpers/clickrem.c \
|
||||||
../../src/helpers/barray.c \
|
../../src/helpers/barray.c \
|
||||||
../../src/helpers/tarray.c \
|
|
||||||
../../src/it/xmeffect.c \
|
../../src/it/xmeffect.c \
|
||||||
../../src/it/readxm2.c \
|
../../src/it/readxm2.c \
|
||||||
../../src/it/readxm.c \
|
../../src/it/readxm.c \
|
||||||
|
@ -109,7 +108,6 @@ HEADERS += \
|
||||||
../../include/internal/it.h \
|
../../include/internal/it.h \
|
||||||
../../include/internal/dumb.h \
|
../../include/internal/dumb.h \
|
||||||
../../include/internal/barray.h \
|
../../include/internal/barray.h \
|
||||||
../../include/internal/tarray.h \
|
|
||||||
../../include/internal/aldumb.h \
|
../../include/internal/aldumb.h \
|
||||||
../../include/internal/sinc_resampler.h \
|
../../include/internal/sinc_resampler.h \
|
||||||
../../include/internal/stack_alloc.h \
|
../../include/internal/stack_alloc.h \
|
||||||
|
|
|
@ -147,15 +147,7 @@ int DUMBEXPORT duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer)
|
||||||
|
|
||||||
int32 DUMBEXPORT duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
|
int32 DUMBEXPORT duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
|
||||||
{
|
{
|
||||||
DUH_SIGRENDERER_GET_POSITION proc;
|
return sigrenderer ? sigrenderer->pos : -1;
|
||||||
|
|
||||||
if (!sigrenderer) return -1;
|
|
||||||
|
|
||||||
proc = sigrenderer->desc->sigrenderer_get_position;
|
|
||||||
if (proc)
|
|
||||||
return (*proc)(sigrenderer->sigrenderer);
|
|
||||||
else
|
|
||||||
return sigrenderer->pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,175 +0,0 @@
|
||||||
#include "internal/tarray.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
Structures which contain the play times of each pattern and row combination in the song,
|
|
||||||
not guaranteed to be valid for the whole song until the loop status is no longer zero.
|
|
||||||
The initial count and restart count will both be zero on song start, then both will be
|
|
||||||
incremented until the song loops. Restart count will be reset to zero on loop for all
|
|
||||||
rows which have a time equal to or greater than the loop start point, so time keeping
|
|
||||||
functions will know which timestamp the song is currently located at.
|
|
||||||
|
|
||||||
Timestamp lists are guaranteed to be allocated in blocks of 16 timestamps at a time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
We don't need full timekeeping because the player loop only wants the first play time
|
|
||||||
of the loop start order/row. We also don't really want full timekeeping because it
|
|
||||||
involves a lot of memory allocations, which is also slow.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#undef FULL_TIMEKEEPING
|
|
||||||
|
|
||||||
typedef struct DUMB_IT_ROW_TIME
|
|
||||||
{
|
|
||||||
unsigned int count, restart_count;
|
|
||||||
#ifndef FULL_TIMEKEEPING
|
|
||||||
LONG_LONG first_time;
|
|
||||||
#else
|
|
||||||
LONG_LONG * times;
|
|
||||||
#endif
|
|
||||||
} DUMB_IT_ROW_TIME;
|
|
||||||
|
|
||||||
void * timekeeping_array_create(size_t size)
|
|
||||||
{
|
|
||||||
size_t * _size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * size );
|
|
||||||
if ( _size ) {
|
|
||||||
*_size = size;
|
|
||||||
}
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void timekeeping_array_destroy(void * array)
|
|
||||||
{
|
|
||||||
#ifdef FULL_TIMEKEEPING
|
|
||||||
size_t i;
|
|
||||||
size_t * size = (size_t *) array;
|
|
||||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
|
||||||
|
|
||||||
for (i = 0; i < *size; i++) {
|
|
||||||
if (s[i].times) free(s[i].times);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
free(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
void * timekeeping_array_dup(void * array)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
size_t * size = (size_t *) array;
|
|
||||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
|
||||||
size_t * new_size = (size_t *) calloc( 1, sizeof(size_t) + sizeof(DUMB_IT_ROW_TIME) * *size );
|
|
||||||
if ( new_size ) {
|
|
||||||
DUMB_IT_ROW_TIME * new_s = (DUMB_IT_ROW_TIME *)(new_size + 1);
|
|
||||||
|
|
||||||
*new_size = *size;
|
|
||||||
|
|
||||||
for (i = 0; i < *size; i++) {
|
|
||||||
new_s[i].count = s[i].count;
|
|
||||||
new_s[i].restart_count = s[i].restart_count;
|
|
||||||
|
|
||||||
#ifndef FULL_TIMEKEEPING
|
|
||||||
new_s[i].first_time = s[i].first_time;
|
|
||||||
#else
|
|
||||||
if ( s[i].times ) {
|
|
||||||
size_t time_count = ( s[i].count + 15 ) & ~15;
|
|
||||||
new_s[i].times = (LONG_LONG *) malloc( sizeof(LONG_LONG) * time_count );
|
|
||||||
if ( new_s[i].times == (void *)0 ) {
|
|
||||||
timekeeping_array_destroy( new_size );
|
|
||||||
return (void *) 0;
|
|
||||||
}
|
|
||||||
memcpy( new_s[i].times, s[i].times, sizeof(LONG_LONG) * s[i].count );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void timekeeping_array_reset(void * array, size_t loop_start)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
size_t * size = (size_t *) array;
|
|
||||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
|
||||||
|
|
||||||
DUMB_IT_ROW_TIME * s_loop_start = s + loop_start;
|
|
||||||
LONG_LONG loop_start_time;
|
|
||||||
|
|
||||||
if ( loop_start >= *size || s_loop_start->count < 1 ) return;
|
|
||||||
|
|
||||||
#ifndef FULL_TIMEKEEPING
|
|
||||||
loop_start_time = s_loop_start->first_time;
|
|
||||||
#else
|
|
||||||
loop_start_time = s_loop_start->times[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for ( i = 0; i < *size; i++ ) {
|
|
||||||
#ifndef FULL_TIMEKEEPING
|
|
||||||
if ( s[i].count && s[i].first_time >= loop_start_time ) {
|
|
||||||
#else
|
|
||||||
if ( s[i].count && s[i].times[0] >= loop_start_time ) {
|
|
||||||
#endif
|
|
||||||
s[i].restart_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void timekeeping_array_push(void * array, size_t index, LONG_LONG time)
|
|
||||||
{
|
|
||||||
#ifdef FULL_TIMEKEEPING
|
|
||||||
size_t i;
|
|
||||||
size_t time_count;
|
|
||||||
#endif
|
|
||||||
size_t * size = (size_t *) array;
|
|
||||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
|
||||||
|
|
||||||
if (index >= *size) return;
|
|
||||||
|
|
||||||
#ifndef FULL_TIMEKEEPING
|
|
||||||
if ( !s[index].count++ )
|
|
||||||
s[index].first_time = time;
|
|
||||||
#else
|
|
||||||
time_count = ( s[index].count + 16 ) & ~15;
|
|
||||||
|
|
||||||
s[index].times = (LONG_LONG *) realloc( s[index].times, sizeof(LONG_LONG) * time_count );
|
|
||||||
|
|
||||||
s[index].times[s[index].count++] = time;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void timekeeping_array_bump(void * array, size_t index)
|
|
||||||
{
|
|
||||||
size_t * size = (size_t *) array;
|
|
||||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
|
||||||
|
|
||||||
if (index >= *size) return;
|
|
||||||
|
|
||||||
s[index].restart_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int timekeeping_array_get_count(void * array, size_t index)
|
|
||||||
{
|
|
||||||
size_t * size = (size_t *) array;
|
|
||||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
|
||||||
|
|
||||||
if (index >= *size) return 0;
|
|
||||||
|
|
||||||
return s[index].count;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONG_LONG timekeeping_array_get_item(void * array, size_t index)
|
|
||||||
{
|
|
||||||
size_t * size = (size_t *) array;
|
|
||||||
DUMB_IT_ROW_TIME * s = (DUMB_IT_ROW_TIME *)(size + 1);
|
|
||||||
|
|
||||||
if (index >= *size || s[index].restart_count >= s[index].count) return 0;
|
|
||||||
|
|
||||||
#ifndef FULL_TIMEKEEPING
|
|
||||||
return s[index].first_time;
|
|
||||||
#else
|
|
||||||
return s[index].times[s[index].restart_count];
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -290,12 +290,15 @@ static int it_read_envelope(IT_ENVELOPE *envelope, DUMBFILE *f)
|
||||||
|
|
||||||
envelope->flags = dumbfile_getc(f);
|
envelope->flags = dumbfile_getc(f);
|
||||||
envelope->n_nodes = dumbfile_getc(f);
|
envelope->n_nodes = dumbfile_getc(f);
|
||||||
|
if(envelope->n_nodes > 25) {
|
||||||
|
TRACE("IT error: wrong number of envelope nodes (%d)\n", envelope->n_nodes);
|
||||||
|
envelope->n_nodes = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
envelope->loop_start = dumbfile_getc(f);
|
envelope->loop_start = dumbfile_getc(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);
|
||||||
|
|
|
@ -352,10 +352,6 @@ static DUMB_IT_SIGRENDERER *dup_sigrenderer(DUMB_IT_SIGRENDERER *src, int n_chan
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
#ifdef BIT_ARRAY_BULLSHIT
|
||||||
dst->played = bit_array_dup(src->played);
|
dst->played = bit_array_dup(src->played);
|
||||||
|
|
||||||
dst->looped = src->looped;
|
|
||||||
dst->time_played = src->time_played;
|
|
||||||
dst->row_timekeeper = timekeeping_array_dup(src->row_timekeeper);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dst->gvz_time = src->gvz_time;
|
dst->gvz_time = src->gvz_time;
|
||||||
|
@ -2221,9 +2217,6 @@ Yxy This uses a table 4 times larger (hence 4 times slower) than
|
||||||
bit_array_set(sigrenderer->played, sigrenderer->order * 256 + sigrenderer->row);
|
bit_array_set(sigrenderer->played, sigrenderer->order * 256 + sigrenderer->row);
|
||||||
#endif
|
#endif
|
||||||
sigrenderer->speed = 0;
|
sigrenderer->speed = 0;
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
sigrenderer->looped = 1;
|
|
||||||
#endif
|
|
||||||
if (sigrenderer->callbacks->xm_speed_zero && (*sigrenderer->callbacks->xm_speed_zero)(sigrenderer->callbacks->xm_speed_zero_data))
|
if (sigrenderer->callbacks->xm_speed_zero && (*sigrenderer->callbacks->xm_speed_zero)(sigrenderer->callbacks->xm_speed_zero_data))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -4341,8 +4334,6 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
|
||||||
/* Fix play tracking and timekeeping for orders containing skip commands */
|
/* Fix play tracking and timekeeping for orders containing skip commands */
|
||||||
for (n = 0; n < 256; n++) {
|
for (n = 0; n < 256; n++) {
|
||||||
bit_array_set(sigrenderer->played, sigrenderer->processorder * 256 + n);
|
bit_array_set(sigrenderer->played, sigrenderer->processorder * 256 + n);
|
||||||
timekeeping_array_push(sigrenderer->row_timekeeper, sigrenderer->processorder * 256 + n, sigrenderer->time_played);
|
|
||||||
timekeeping_array_bump(sigrenderer->row_timekeeper, sigrenderer->processorder * 256 + n);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -4367,9 +4358,6 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
|
||||||
&& bit_array_test(sigrenderer->played, sigrenderer->processorder * 256 + sigrenderer->processrow)
|
&& bit_array_test(sigrenderer->played, sigrenderer->processorder * 256 + sigrenderer->processrow)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
sigrenderer->looped = 1;
|
|
||||||
#endif
|
|
||||||
if (sigrenderer->callbacks->loop) {
|
if (sigrenderer->callbacks->loop) {
|
||||||
if ((*sigrenderer->callbacks->loop)(sigrenderer->callbacks->loop_data))
|
if ((*sigrenderer->callbacks->loop)(sigrenderer->callbacks->loop_data))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -4413,13 +4401,6 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
if (sigrenderer->looped == 0) {
|
|
||||||
timekeeping_array_push(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row, sigrenderer->time_played);
|
|
||||||
}
|
|
||||||
timekeeping_array_bump(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!(sigdata->flags & IT_WAS_A_669))
|
if (!(sigdata->flags & IT_WAS_A_669))
|
||||||
reset_effects(sigrenderer);
|
reset_effects(sigrenderer);
|
||||||
|
|
||||||
|
@ -4471,9 +4452,6 @@ static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
|
||||||
sigrenderer->gvz_time += (int)(t >> 16);
|
sigrenderer->gvz_time += (int)(t >> 16);
|
||||||
sigrenderer->gvz_sub_time = (int)t & 65535;
|
sigrenderer->gvz_sub_time = (int)t & 65535;
|
||||||
if (sigrenderer->gvz_time >= 65536 * 12) {
|
if (sigrenderer->gvz_time >= 65536 * 12) {
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
sigrenderer->looped = 1;
|
|
||||||
#endif
|
|
||||||
if ((*sigrenderer->callbacks->global_volume_zero)(sigrenderer->callbacks->global_volume_zero_data))
|
if ((*sigrenderer->callbacks->global_volume_zero)(sigrenderer->callbacks->global_volume_zero_data))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -5288,10 +5266,6 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
#ifdef BIT_ARRAY_BULLSHIT
|
||||||
sigrenderer->played = bit_array_create(sigdata->n_orders * 256);
|
sigrenderer->played = bit_array_create(sigdata->n_orders * 256);
|
||||||
|
|
||||||
sigrenderer->looped = 0;
|
|
||||||
sigrenderer->time_played = 0;
|
|
||||||
sigrenderer->row_timekeeper = timekeeping_array_create(sigdata->n_orders * 256);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -5310,8 +5284,6 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha
|
||||||
/* Fix for played order detection for songs which have skips at the start of the orders list */
|
/* Fix for played order detection for songs which have skips at the start of the orders list */
|
||||||
for (n = 0; n < 256; n++) {
|
for (n = 0; n < 256; n++) {
|
||||||
bit_array_set(sigrenderer->played, order * 256 + n);
|
bit_array_set(sigrenderer->played, order * 256 + n);
|
||||||
timekeeping_array_push(sigrenderer->row_timekeeper, order * 256 + n, 0);
|
|
||||||
timekeeping_array_bump(sigrenderer->row_timekeeper, order * 256 + n);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -5324,6 +5296,10 @@ static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_cha
|
||||||
sigrenderer->time_left = 0;
|
sigrenderer->time_left = 0;
|
||||||
sigrenderer->sub_time_left = 0;
|
sigrenderer->sub_time_left = 0;
|
||||||
|
|
||||||
|
#ifdef BIT_ARRAY_BULLSHIT
|
||||||
|
sigrenderer->played = bit_array_create(sigdata->n_orders * 256);
|
||||||
|
#endif
|
||||||
|
|
||||||
sigrenderer->gvz_time = 0;
|
sigrenderer->gvz_time = 0;
|
||||||
sigrenderer->gvz_sub_time = 0;
|
sigrenderer->gvz_sub_time = 0;
|
||||||
|
|
||||||
|
@ -5482,10 +5458,6 @@ static sigrenderer_t *it_start_sigrenderer(DUH *duh, sigdata_t *vsigdata, int n_
|
||||||
while (pos > 0 && pos >= sigrenderer->time_left) {
|
while (pos > 0 && pos >= sigrenderer->time_left) {
|
||||||
render(sigrenderer, 0, 1.0f, 0, sigrenderer->time_left, NULL);
|
render(sigrenderer, 0, 1.0f, 0, sigrenderer->time_left, NULL);
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
sigrenderer->time_played += (LONG_LONG)sigrenderer->time_left << 16;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pos -= sigrenderer->time_left;
|
pos -= sigrenderer->time_left;
|
||||||
sigrenderer->time_left = 0;
|
sigrenderer->time_left = 0;
|
||||||
|
|
||||||
|
@ -5498,10 +5470,6 @@ static sigrenderer_t *it_start_sigrenderer(DUH *duh, sigdata_t *vsigdata, int n_
|
||||||
render(sigrenderer, 0, 1.0f, 0, pos, NULL);
|
render(sigrenderer, 0, 1.0f, 0, pos, NULL);
|
||||||
sigrenderer->time_left -= pos;
|
sigrenderer->time_left -= pos;
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
sigrenderer->time_played += (LONG_LONG)pos << 16;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sigrenderer;
|
return sigrenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5517,7 +5485,6 @@ static int32 it_sigrenderer_get_samples(
|
||||||
int32 pos;
|
int32 pos;
|
||||||
int dt;
|
int dt;
|
||||||
int32 todo;
|
int32 todo;
|
||||||
int ret;
|
|
||||||
LONG_LONG t;
|
LONG_LONG t;
|
||||||
|
|
||||||
if (sigrenderer->order < 0) return 0; // problematic
|
if (sigrenderer->order < 0) return 0; // problematic
|
||||||
|
@ -5531,7 +5498,7 @@ static int32 it_sigrenderer_get_samples(
|
||||||
if (!samples) volume = 0;
|
if (!samples) volume = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
todo = (int32)((((LONG_LONG)sigrenderer->time_left << 16) | sigrenderer->sub_time_left) / dt);
|
todo = (long)((((LONG_LONG)sigrenderer->time_left << 16) | sigrenderer->sub_time_left) / dt);
|
||||||
|
|
||||||
if (todo >= size)
|
if (todo >= size)
|
||||||
break;
|
break;
|
||||||
|
@ -5545,28 +5512,9 @@ static int32 it_sigrenderer_get_samples(
|
||||||
sigrenderer->sub_time_left = (int32)t & 65535;
|
sigrenderer->sub_time_left = (int32)t & 65535;
|
||||||
sigrenderer->time_left += (int32)(t >> 16);
|
sigrenderer->time_left += (int32)(t >> 16);
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
if (process_tick(sigrenderer)) {
|
||||||
sigrenderer->time_played += (LONG_LONG)todo * dt;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = process_tick(sigrenderer);
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
sigrenderer->order = -1;
|
sigrenderer->order = -1;
|
||||||
sigrenderer->row = -1;
|
sigrenderer->row = -1;
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
if (sigrenderer->looped == 1) {
|
|
||||||
sigrenderer->looped = -1;
|
|
||||||
size = 0;
|
|
||||||
timekeeping_array_reset(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row);
|
|
||||||
sigrenderer->time_played = timekeeping_array_get_item(sigrenderer->row_timekeeper, sigrenderer->order * 256 + sigrenderer->row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5579,10 +5527,6 @@ static int32 it_sigrenderer_get_samples(
|
||||||
sigrenderer->sub_time_left = (int32)t & 65535;
|
sigrenderer->sub_time_left = (int32)t & 65535;
|
||||||
sigrenderer->time_left += (int32)(t >> 16);
|
sigrenderer->time_left += (int32)(t >> 16);
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
sigrenderer->time_played += (LONG_LONG)size * dt;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (samples)
|
if (samples)
|
||||||
dumb_remove_clicks_array(sigrenderer->n_channels, sigrenderer->click_remover, samples, pos, 512.0f / delta);
|
dumb_remove_clicks_array(sigrenderer->n_channels, sigrenderer->click_remover, samples, pos, 512.0f / delta);
|
||||||
|
|
||||||
|
@ -5634,8 +5578,6 @@ void _dumb_it_end_sigrenderer(sigrenderer_t *vsigrenderer)
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
#ifdef BIT_ARRAY_BULLSHIT
|
||||||
bit_array_destroy(sigrenderer->played);
|
bit_array_destroy(sigrenderer->played);
|
||||||
|
|
||||||
timekeeping_array_destroy(sigrenderer->row_timekeeper);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
free(vsigrenderer);
|
free(vsigrenderer);
|
||||||
|
@ -5644,17 +5586,6 @@ void _dumb_it_end_sigrenderer(sigrenderer_t *vsigrenderer)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
static int32 it_sigrenderer_get_position(sigrenderer_t *vsigrenderer)
|
|
||||||
{
|
|
||||||
DUMB_IT_SIGRENDERER *sigrenderer = vsigrenderer;
|
|
||||||
|
|
||||||
return (int32)(sigrenderer->time_played >> 16);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DUH_SIGTYPE_DESC _dumb_sigtype_it = {
|
DUH_SIGTYPE_DESC _dumb_sigtype_it = {
|
||||||
SIGTYPE_IT,
|
SIGTYPE_IT,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -5662,11 +5593,6 @@ DUH_SIGTYPE_DESC _dumb_sigtype_it = {
|
||||||
NULL,
|
NULL,
|
||||||
&it_sigrenderer_get_samples,
|
&it_sigrenderer_get_samples,
|
||||||
&it_sigrenderer_get_current_sample,
|
&it_sigrenderer_get_current_sample,
|
||||||
#ifdef BIT_ARRAY_BULLSHIT
|
|
||||||
&it_sigrenderer_get_position,
|
|
||||||
#else
|
|
||||||
NULL,
|
|
||||||
#endif
|
|
||||||
&_dumb_it_end_sigrenderer,
|
&_dumb_it_end_sigrenderer,
|
||||||
&_dumb_it_unload_sigdata
|
&_dumb_it_unload_sigdata
|
||||||
};
|
};
|
||||||
|
|
|
@ -320,6 +320,8 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
|
||||||
free( sigdata );
|
free( sigdata );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigdata->n_pchannels = nchannels;
|
||||||
|
|
||||||
memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS );
|
memset( sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS );
|
||||||
|
|
||||||
|
|
|
@ -439,6 +439,7 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dumbfile_seek(f, 352, DFS_SEEK_SET)) {
|
if (dumbfile_seek(f, 352, DFS_SEEK_SET)) {
|
||||||
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -451,12 +452,14 @@ static DUMB_IT_SIGDATA *it_ptm_load_sigdata(DUMBFILE *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dumbfile_seek(f, 608, DFS_SEEK_SET)) {
|
if (dumbfile_seek(f, 608, DFS_SEEK_SET)) {
|
||||||
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < sigdata->n_samples; n++) {
|
for (n = 0; n < sigdata->n_samples; n++) {
|
||||||
if (it_ptm_read_sample_header(&sigdata->sample[n], &component[n_components].offset, f)) {
|
if (it_ptm_read_sample_header(&sigdata->sample[n], &component[n_components].offset, f)) {
|
||||||
|
free(component);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1197,6 +1197,7 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
|
|
||||||
sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
|
sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
|
||||||
if (!sigdata->instrument) {
|
if (!sigdata->instrument) {
|
||||||
|
free(roguebytes);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,6 @@
|
||||||
<ClCompile Include="..\..\src\helpers\sampbuf.c" />
|
<ClCompile Include="..\..\src\helpers\sampbuf.c" />
|
||||||
<ClCompile Include="..\..\src\helpers\silence.c" />
|
<ClCompile Include="..\..\src\helpers\silence.c" />
|
||||||
<ClCompile Include="..\..\src\helpers\stdfile.c" />
|
<ClCompile Include="..\..\src\helpers\stdfile.c" />
|
||||||
<ClCompile Include="..\..\src\helpers\tarray.c" />
|
|
||||||
<ClCompile Include="..\..\src\it\itmisc.c" />
|
<ClCompile Include="..\..\src\it\itmisc.c" />
|
||||||
<ClCompile Include="..\..\src\it\itorder.c" />
|
<ClCompile Include="..\..\src\it\itorder.c" />
|
||||||
<ClCompile Include="..\..\src\it\itrender.c" />
|
<ClCompile Include="..\..\src\it\itrender.c" />
|
||||||
|
@ -210,7 +209,6 @@
|
||||||
<ClInclude Include="..\..\include\internal\lpc.h" />
|
<ClInclude Include="..\..\include\internal\lpc.h" />
|
||||||
<ClInclude Include="..\..\include\internal\riff.h" />
|
<ClInclude Include="..\..\include\internal\riff.h" />
|
||||||
<ClInclude Include="..\..\include\internal\stack_alloc.h" />
|
<ClInclude Include="..\..\include\internal\stack_alloc.h" />
|
||||||
<ClInclude Include="..\..\include\internal\tarray.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
@ -279,9 +279,6 @@
|
||||||
<ClCompile Include="..\..\src\helpers\resampler.c">
|
<ClCompile Include="..\..\src\helpers\resampler.c">
|
||||||
<Filter>src\helpers</Filter>
|
<Filter>src\helpers</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\helpers\tarray.c">
|
|
||||||
<Filter>src\helpers</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\include\dumb.h">
|
<ClInclude Include="..\..\include\dumb.h">
|
||||||
|
@ -314,9 +311,6 @@
|
||||||
<ClInclude Include="..\..\include\internal\resampler.h">
|
<ClInclude Include="..\..\include\internal\resampler.h">
|
||||||
<Filter>include\internal</Filter>
|
<Filter>include\internal</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\include\internal\tarray.h">
|
|
||||||
<Filter>include\internal</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="..\..\src\helpers\resamp3.inc">
|
<CustomBuild Include="..\..\src\helpers\resamp3.inc">
|
||||||
|
|
|
@ -27,7 +27,8 @@ II. Implementation Semantics
|
||||||
II.A : Storage and Retrieval of Data
|
II.A : Storage and Retrieval of Data
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
No changes.
|
Any TEXTMAP lump in the described namespaces must be encoded in ISO 8859-1 which
|
||||||
|
as of this writing is the only character encoding supported by ZDoom.
|
||||||
|
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
II.B : Storage Within Archive Files
|
II.B : Storage Within Archive Files
|
||||||
|
|
|
@ -187,6 +187,7 @@ else( WIN32 )
|
||||||
if( GTK2_FOUND )
|
if( GTK2_FOUND )
|
||||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GTK2_LIBRARIES} )
|
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GTK2_LIBRARIES} )
|
||||||
include_directories( ${GTK2_INCLUDE_DIRS} )
|
include_directories( ${GTK2_INCLUDE_DIRS} )
|
||||||
|
link_directories( ${GTK2_LIBRARY_DIRS} )
|
||||||
else( GTK2_FOUND )
|
else( GTK2_FOUND )
|
||||||
set( NO_GTK ON )
|
set( NO_GTK ON )
|
||||||
endif( GTK2_FOUND )
|
endif( GTK2_FOUND )
|
||||||
|
@ -496,6 +497,11 @@ if( NOT MSVC )
|
||||||
add_definitions( -D__forceinline=inline )
|
add_definitions( -D__forceinline=inline )
|
||||||
endif( NOT MSVC )
|
endif( NOT MSVC )
|
||||||
|
|
||||||
|
# Fix stat in v140_xp (broken in RTM and Update 1 so far)
|
||||||
|
if( MSVC AND MSVC_VERSION EQUAL 1900 AND CMAKE_GENERATOR_TOOLSET STREQUAL "v140_xp" )
|
||||||
|
add_definitions( -D_stat64i32=VS14Stat )
|
||||||
|
endif( MSVC AND MSVC_VERSION EQUAL 1900 AND CMAKE_GENERATOR_TOOLSET STREQUAL "v140_xp" )
|
||||||
|
|
||||||
if( UNIX )
|
if( UNIX )
|
||||||
CHECK_LIBRARY_EXISTS( rt clock_gettime "" CLOCK_GETTIME_IN_RT )
|
CHECK_LIBRARY_EXISTS( rt clock_gettime "" CLOCK_GETTIME_IN_RT )
|
||||||
if( NOT CLOCK_GETTIME_IN_RT )
|
if( NOT CLOCK_GETTIME_IN_RT )
|
||||||
|
@ -919,6 +925,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
||||||
nodebuild_extract.cpp
|
nodebuild_extract.cpp
|
||||||
nodebuild_gl.cpp
|
nodebuild_gl.cpp
|
||||||
nodebuild_utility.cpp
|
nodebuild_utility.cpp
|
||||||
|
pathexpander.cpp
|
||||||
p_3dfloors.cpp
|
p_3dfloors.cpp
|
||||||
p_3dmidtex.cpp
|
p_3dmidtex.cpp
|
||||||
p_acs.cpp
|
p_acs.cpp
|
||||||
|
@ -1095,6 +1102,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
||||||
sound/music_fluidsynth_mididevice.cpp
|
sound/music_fluidsynth_mididevice.cpp
|
||||||
sound/music_softsynth_mididevice.cpp
|
sound/music_softsynth_mididevice.cpp
|
||||||
sound/music_timidity_mididevice.cpp
|
sound/music_timidity_mididevice.cpp
|
||||||
|
sound/music_wildmidi_mididevice.cpp
|
||||||
sound/music_win_mididevice.cpp
|
sound/music_win_mididevice.cpp
|
||||||
sound/oalsound.cpp
|
sound/oalsound.cpp
|
||||||
sound/sndfile_decoder.cpp
|
sound/sndfile_decoder.cpp
|
||||||
|
@ -1137,6 +1145,11 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
||||||
timidity/playmidi.cpp
|
timidity/playmidi.cpp
|
||||||
timidity/resample.cpp
|
timidity/resample.cpp
|
||||||
timidity/timidity.cpp
|
timidity/timidity.cpp
|
||||||
|
wildmidi/file_io.cpp
|
||||||
|
wildmidi/gus_pat.cpp
|
||||||
|
wildmidi/reverb.cpp
|
||||||
|
wildmidi/wildmidi_lib.cpp
|
||||||
|
wildmidi/wm_error.cpp
|
||||||
xlat/parse_xlat.cpp
|
xlat/parse_xlat.cpp
|
||||||
fragglescript/t_fspic.cpp
|
fragglescript/t_fspic.cpp
|
||||||
fragglescript/t_func.cpp
|
fragglescript/t_func.cpp
|
||||||
|
@ -1283,6 +1296,8 @@ source_group("Audio Files\\OPL Synth" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURC
|
||||||
source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h)
|
source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h)
|
||||||
source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$")
|
source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$")
|
||||||
source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$")
|
source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$")
|
||||||
|
source_group("Audio Files\\WildMidi\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/wildmidi/.+\\.h$")
|
||||||
|
source_group("Audio Files\\WildMidi\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/wildmidi/.+\\.cpp$")
|
||||||
source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+")
|
source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+")
|
||||||
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
|
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
|
||||||
source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+")
|
source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+")
|
||||||
|
|
199
src/am_map.cpp
199
src/am_map.cpp
|
@ -2224,6 +2224,154 @@ bool AM_Check3DFloors(line_t *line)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [TP] Check whether a sector can trigger a special that satisfies the provided function.
|
||||||
|
// If found, specialptr and argsptr will be filled by the special and the arguments
|
||||||
|
// If needUseActivated is true, the special must be activated by use.
|
||||||
|
bool AM_checkSectorActions (sector_t *sector, bool (*function)(int, int *), int *specialptr, int **argsptr, bool needUseActivated)
|
||||||
|
{
|
||||||
|
for (ASectorAction* action = sector->SecActTarget; action; action = barrier_cast<ASectorAction *>(action->tracer))
|
||||||
|
{
|
||||||
|
if ((action->IsActivatedByUse() || false == needUseActivated)
|
||||||
|
&& (*function)(action->special, action->args)
|
||||||
|
&& action->CanTrigger (players[consoleplayer].mo))
|
||||||
|
{
|
||||||
|
*specialptr = action->special;
|
||||||
|
*argsptr = action->args;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [TP] Check whether there's a boundary on the provided line for a special that satisfies the provided function.
|
||||||
|
// It's a boundary if the line can activate the special or the line's bordering sectors can activate it.
|
||||||
|
// If found, specialptr and argsptr will be filled with special and args if given.
|
||||||
|
bool AM_checkSpecialBoundary (line_t &line, bool (*function)(int, int *), int *specialptr = NULL, int **argsptr = NULL)
|
||||||
|
{
|
||||||
|
if (specialptr == NULL)
|
||||||
|
{
|
||||||
|
static int sink;
|
||||||
|
specialptr = &sink;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argsptr == NULL)
|
||||||
|
{
|
||||||
|
static int *sink;
|
||||||
|
argsptr = &sink;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the line special qualifies for this
|
||||||
|
if ((line.activation & SPAC_PlayerActivate) && (*function)(line.special, line.args))
|
||||||
|
{
|
||||||
|
*specialptr = line.special;
|
||||||
|
*argsptr = line.args;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check sector actions in the line's front sector -- the action has to be use-activated in order to
|
||||||
|
// show up if this is a one-sided line, because the player cannot trigger sector actions by crossing
|
||||||
|
// a one-sided line (since that's impossible, duh).
|
||||||
|
if (AM_checkSectorActions(line.frontsector, function, specialptr, argsptr, line.backsector == NULL))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// If it has a back sector, check sector actions in that.
|
||||||
|
return (line.backsector && AM_checkSectorActions(line.backsector, function, specialptr, argsptr, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AM_isTeleportSpecial (int special, int *)
|
||||||
|
{
|
||||||
|
return (special == Teleport ||
|
||||||
|
special == Teleport_NoFog ||
|
||||||
|
special == Teleport_ZombieChanger ||
|
||||||
|
special == Teleport_Line);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AM_isTeleportBoundary (line_t &line)
|
||||||
|
{
|
||||||
|
return AM_checkSpecialBoundary(line, &AM_isTeleportSpecial);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AM_isExitSpecial (int special, int *)
|
||||||
|
{
|
||||||
|
return (special == Teleport_NewMap ||
|
||||||
|
special == Teleport_EndGame ||
|
||||||
|
special == Exit_Normal ||
|
||||||
|
special == Exit_Secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AM_isExitBoundary (line_t& line)
|
||||||
|
{
|
||||||
|
return AM_checkSpecialBoundary(line, &AM_isExitSpecial);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AM_isTriggerSpecial (int special, int *)
|
||||||
|
{
|
||||||
|
return LineSpecialsInfo[special] != NULL
|
||||||
|
&& LineSpecialsInfo[special]->max_args >= 0
|
||||||
|
&& special != Door_Open
|
||||||
|
&& special != Door_Close
|
||||||
|
&& special != Door_CloseWaitOpen
|
||||||
|
&& special != Door_Raise
|
||||||
|
&& special != Door_Animated
|
||||||
|
&& special != Generic_Door;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AM_isTriggerBoundary (line_t &line)
|
||||||
|
{
|
||||||
|
return AM_checkSpecialBoundary(line, &AM_isTriggerSpecial);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AM_isLockSpecial (int special, int* args)
|
||||||
|
{
|
||||||
|
return special == Door_LockedRaise
|
||||||
|
|| special == ACS_LockedExecute
|
||||||
|
|| special == ACS_LockedExecuteDoor
|
||||||
|
|| (special == Door_Animated && args[3] != 0)
|
||||||
|
|| (special == Generic_Door && args[4] != 0)
|
||||||
|
|| (special == FS_Execute && args[2] != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AM_isLockBoundary (line_t &line, int *lockptr = NULL)
|
||||||
|
{
|
||||||
|
if (lockptr == NULL)
|
||||||
|
{
|
||||||
|
static int sink;
|
||||||
|
lockptr = &sink;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.locknumber)
|
||||||
|
{
|
||||||
|
*lockptr = line.locknumber;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int special;
|
||||||
|
int *args;
|
||||||
|
bool result = AM_checkSpecialBoundary(line, &AM_isLockSpecial, &special, &args);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
switch (special)
|
||||||
|
{
|
||||||
|
case FS_Execute:
|
||||||
|
*lockptr = args[2];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Door_Animated:
|
||||||
|
case Door_LockedRaise:
|
||||||
|
*lockptr = args[3];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*lockptr = args[4];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// Determines visible lines, draws them.
|
// Determines visible lines, draws them.
|
||||||
|
@ -2271,49 +2419,19 @@ void AM_drawWalls (bool allmap)
|
||||||
AM_drawMline(&l, AMColors.SecretWallColor);
|
AM_drawMline(&l, AMColors.SecretWallColor);
|
||||||
else
|
else
|
||||||
AM_drawMline(&l, AMColors.WallColor);
|
AM_drawMline(&l, AMColors.WallColor);
|
||||||
}
|
}
|
||||||
else if (lines[i].locknumber > 0 && AMColors.displayLocks)
|
else if (AM_isTeleportBoundary(lines[i]) && AMColors.isValid(AMColors.IntraTeleportColor))
|
||||||
{ // [Dusk] specials w/ locknumbers
|
|
||||||
lock = lines[i].locknumber;
|
|
||||||
color = P_GetMapColorForLock(lock);
|
|
||||||
|
|
||||||
AMColor c;
|
|
||||||
if (color >= 0) c.FromRGB(RPART(color), GPART(color), BPART(color));
|
|
||||||
else c = AMColors[AMColors.LockedColor];
|
|
||||||
|
|
||||||
AM_drawMline (&l, c);
|
|
||||||
}
|
|
||||||
else if ((lines[i].special == Teleport ||
|
|
||||||
lines[i].special == Teleport_NoFog ||
|
|
||||||
lines[i].special == Teleport_ZombieChanger ||
|
|
||||||
lines[i].special == Teleport_Line) &&
|
|
||||||
(lines[i].activation & SPAC_PlayerActivate) &&
|
|
||||||
AMColors.isValid(AMColors.IntraTeleportColor))
|
|
||||||
{ // intra-level teleporters
|
{ // intra-level teleporters
|
||||||
AM_drawMline(&l, AMColors.IntraTeleportColor);
|
AM_drawMline(&l, AMColors.IntraTeleportColor);
|
||||||
}
|
}
|
||||||
else if ((lines[i].special == Teleport_NewMap ||
|
else if (AM_isExitBoundary(lines[i]) && AMColors.isValid(AMColors.InterTeleportColor))
|
||||||
lines[i].special == Teleport_EndGame ||
|
|
||||||
lines[i].special == Exit_Normal ||
|
|
||||||
lines[i].special == Exit_Secret) &&
|
|
||||||
AMColors.isValid(AMColors.InterTeleportColor))
|
|
||||||
{ // inter-level/game-ending teleporters
|
{ // inter-level/game-ending teleporters
|
||||||
AM_drawMline(&l, AMColors.InterTeleportColor);
|
AM_drawMline(&l, AMColors.InterTeleportColor);
|
||||||
}
|
}
|
||||||
else if (lines[i].special == Door_LockedRaise ||
|
else if (AM_isLockBoundary(lines[i], &lock))
|
||||||
lines[i].special == ACS_LockedExecute ||
|
|
||||||
lines[i].special == ACS_LockedExecuteDoor ||
|
|
||||||
(lines[i].special == Door_Animated && lines[i].args[3] != 0) ||
|
|
||||||
(lines[i].special == Generic_Door && lines[i].args[4] != 0))
|
|
||||||
{
|
{
|
||||||
if (AMColors.displayLocks)
|
if (AMColors.displayLocks)
|
||||||
{
|
{
|
||||||
int P_GetMapColorForLock(int lock);
|
|
||||||
|
|
||||||
if (lines[i].special==Door_LockedRaise || lines[i].special==Door_Animated)
|
|
||||||
lock=lines[i].args[3];
|
|
||||||
else lock=lines[i].args[4];
|
|
||||||
|
|
||||||
color = P_GetMapColorForLock(lock);
|
color = P_GetMapColorForLock(lock);
|
||||||
|
|
||||||
AMColor c;
|
AMColor c;
|
||||||
|
@ -2328,16 +2446,9 @@ void AM_drawWalls (bool allmap)
|
||||||
AM_drawMline (&l, AMColors.LockedColor); // locked special
|
AM_drawMline (&l, AMColors.LockedColor); // locked special
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (am_showtriggerlines && AMColors.isValid(AMColors.SpecialWallColor)
|
else if (am_showtriggerlines
|
||||||
&& LineSpecialsInfo[lines[i].special] != NULL
|
&& AMColors.isValid(AMColors.SpecialWallColor)
|
||||||
&& LineSpecialsInfo[lines[i].special]->max_args >= 0
|
&& AM_isTriggerBoundary(lines[i]))
|
||||||
&& lines[i].special != Door_Open
|
|
||||||
&& lines[i].special != Door_Close
|
|
||||||
&& lines[i].special != Door_CloseWaitOpen
|
|
||||||
&& lines[i].special != Door_Raise
|
|
||||||
&& lines[i].special != Door_Animated
|
|
||||||
&& lines[i].special != Generic_Door
|
|
||||||
&& (lines[i].activation & SPAC_PlayerActivate))
|
|
||||||
{
|
{
|
||||||
AM_drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do
|
AM_drawMline(&l, AMColors.SpecialWallColor); // wall with special non-door action the player can do
|
||||||
}
|
}
|
||||||
|
|
|
@ -973,7 +973,7 @@ void NetUpdate (void)
|
||||||
{
|
{
|
||||||
I_StartTic ();
|
I_StartTic ();
|
||||||
D_ProcessEvents ();
|
D_ProcessEvents ();
|
||||||
if ((maketic - gametic) / ticdup >= BACKUPTICS/2-1)
|
if (pauseext || (maketic - gametic) / ticdup >= BACKUPTICS/2-1)
|
||||||
break; // can't hold any more
|
break; // can't hold any more
|
||||||
|
|
||||||
//Printf ("mk:%i ",maketic);
|
//Printf ("mk:%i ",maketic);
|
||||||
|
@ -1204,7 +1204,7 @@ void NetUpdate (void)
|
||||||
|
|
||||||
// Send current network delay
|
// Send current network delay
|
||||||
// The number of tics we just made should be removed from the count.
|
// The number of tics we just made should be removed from the count.
|
||||||
netbuffer[k++] = ((maketic - newtics - gametic) / ticdup);
|
netbuffer[k++] = ((maketic - numtics - gametic) / ticdup);
|
||||||
|
|
||||||
if (numtics > 0)
|
if (numtics > 0)
|
||||||
{
|
{
|
||||||
|
@ -1810,7 +1810,8 @@ void TryRunTics (void)
|
||||||
|
|
||||||
// If paused, do not eat more CPU time than we need, because it
|
// If paused, do not eat more CPU time than we need, because it
|
||||||
// will all be wasted anyway.
|
// will all be wasted anyway.
|
||||||
if (pauseext) r_NoInterpolate = true;
|
if (pauseext)
|
||||||
|
r_NoInterpolate = true;
|
||||||
bool doWait = cl_capfps || r_NoInterpolate /*|| netgame*/;
|
bool doWait = cl_capfps || r_NoInterpolate /*|| netgame*/;
|
||||||
|
|
||||||
// get real tics
|
// get real tics
|
||||||
|
@ -1828,6 +1829,9 @@ void TryRunTics (void)
|
||||||
// get available tics
|
// get available tics
|
||||||
NetUpdate ();
|
NetUpdate ();
|
||||||
|
|
||||||
|
if (pauseext)
|
||||||
|
return;
|
||||||
|
|
||||||
lowtic = INT_MAX;
|
lowtic = INT_MAX;
|
||||||
numplaying = 0;
|
numplaying = 0;
|
||||||
for (i = 0; i < doomcom.numnodes; i++)
|
for (i = 0; i < doomcom.numnodes; i++)
|
||||||
|
@ -1935,7 +1939,7 @@ void TryRunTics (void)
|
||||||
C_Ticker ();
|
C_Ticker ();
|
||||||
M_Ticker ();
|
M_Ticker ();
|
||||||
I_GetTime (true);
|
I_GetTime (true);
|
||||||
if (!pauseext) G_Ticker();
|
G_Ticker();
|
||||||
gametic++;
|
gametic++;
|
||||||
|
|
||||||
NetUpdate (); // check for new console commands
|
NetUpdate (); // check for new console commands
|
||||||
|
|
|
@ -242,7 +242,11 @@ enum
|
||||||
WF_WEAPONRELOADOK = 1 << 5, // [XA] Okay to reload this weapon.
|
WF_WEAPONRELOADOK = 1 << 5, // [XA] Okay to reload this weapon.
|
||||||
WF_WEAPONZOOMOK = 1 << 6, // [XA] Okay to use weapon zoom function.
|
WF_WEAPONZOOMOK = 1 << 6, // [XA] Okay to use weapon zoom function.
|
||||||
WF_REFIRESWITCHOK = 1 << 7, // Mirror WF_WEAPONSWITCHOK for A_ReFire
|
WF_REFIRESWITCHOK = 1 << 7, // Mirror WF_WEAPONSWITCHOK for A_ReFire
|
||||||
};
|
WF_USER1OK = 1 << 8, // [MC] Allow pushing of custom state buttons 1-4
|
||||||
|
WF_USER2OK = 1 << 9,
|
||||||
|
WF_USER3OK = 1 << 10,
|
||||||
|
WF_USER4OK = 1 << 11,
|
||||||
|
};
|
||||||
|
|
||||||
#define WPIECE1 1
|
#define WPIECE1 1
|
||||||
#define WPIECE2 2
|
#define WPIECE2 2
|
||||||
|
@ -426,7 +430,7 @@ 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;
|
WORD WeaponState;
|
||||||
|
|
||||||
AWeapon *ReadyWeapon;
|
AWeapon *ReadyWeapon;
|
||||||
AWeapon *PendingWeapon; // WP_NOCHANGE if not changing
|
AWeapon *PendingWeapon; // WP_NOCHANGE if not changing
|
||||||
|
|
|
@ -337,7 +337,7 @@ struct level_info_t
|
||||||
TArray<FSpecialAction> specialactions;
|
TArray<FSpecialAction> specialactions;
|
||||||
|
|
||||||
TArray<FSoundID> PrecacheSounds;
|
TArray<FSoundID> PrecacheSounds;
|
||||||
TArray<FTextureID> PrecacheTextures;
|
TArray<FString> PrecacheTextures;
|
||||||
|
|
||||||
level_info_t()
|
level_info_t()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1077,15 +1077,8 @@ DEFINE_MAP_OPTION(PrecacheTextures, true)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
parse.sc.MustGetString();
|
parse.sc.MustGetString();
|
||||||
FTextureID tex = TexMan.CheckForTexture(parse.sc.String, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_ReturnFirst);
|
//the texture manager is not initialized here so all we can do is store the texture's name.
|
||||||
if (!tex.isValid())
|
info->PrecacheTextures.Push(parse.sc.String);
|
||||||
{
|
|
||||||
parse.sc.ScriptMessage("Unknown texture \"%s\"", parse.sc.String);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info->PrecacheTextures.Push(tex);
|
|
||||||
}
|
|
||||||
} while (parse.sc.CheckString(","));
|
} while (parse.sc.CheckString(","));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -325,8 +325,7 @@ public:
|
||||||
virtual FState *GetReadyState ();
|
virtual FState *GetReadyState ();
|
||||||
virtual FState *GetAtkState (bool hold);
|
virtual FState *GetAtkState (bool hold);
|
||||||
virtual FState *GetAltAtkState (bool hold);
|
virtual FState *GetAltAtkState (bool hold);
|
||||||
virtual FState *GetRelState ();
|
virtual FState *GetStateForButtonName (FName button);
|
||||||
virtual FState *GetZoomState ();
|
|
||||||
|
|
||||||
virtual void PostMorphWeapon ();
|
virtual void PostMorphWeapon ();
|
||||||
virtual void EndPowerup ();
|
virtual void EndPowerup ();
|
||||||
|
|
|
@ -39,6 +39,14 @@
|
||||||
|
|
||||||
IMPLEMENT_CLASS (ASectorAction)
|
IMPLEMENT_CLASS (ASectorAction)
|
||||||
|
|
||||||
|
ASectorAction::ASectorAction (bool activatedByUse) :
|
||||||
|
ActivatedByUse (activatedByUse) {}
|
||||||
|
|
||||||
|
bool ASectorAction::IsActivatedByUse() const
|
||||||
|
{
|
||||||
|
return ActivatedByUse;
|
||||||
|
}
|
||||||
|
|
||||||
void ASectorAction::Destroy ()
|
void ASectorAction::Destroy ()
|
||||||
{
|
{
|
||||||
// Remove ourself from this sector's list of actions
|
// Remove ourself from this sector's list of actions
|
||||||
|
@ -102,12 +110,17 @@ bool ASectorAction::DoTriggerAction (AActor *triggerer, int activationType)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ASectorAction::CanTrigger (AActor *triggerer) const
|
||||||
|
{
|
||||||
|
return special &&
|
||||||
|
((triggerer->player && !(flags & MF_FRIENDLY)) ||
|
||||||
|
((flags & MF_AMBUSH) && (triggerer->flags2 & MF2_MCROSS)) ||
|
||||||
|
((flags2 & MF2_DORMANT) && (triggerer->flags2 & MF2_PCROSS)));
|
||||||
|
}
|
||||||
|
|
||||||
bool ASectorAction::CheckTrigger (AActor *triggerer) const
|
bool ASectorAction::CheckTrigger (AActor *triggerer) const
|
||||||
{
|
{
|
||||||
if (special &&
|
if (CanTrigger(triggerer))
|
||||||
((triggerer->player && !(flags & MF_FRIENDLY)) ||
|
|
||||||
((flags & MF_AMBUSH) && (triggerer->flags2 & MF2_MCROSS)) ||
|
|
||||||
((flags2 & MF2_DORMANT) && (triggerer->flags2 & MF2_PCROSS))))
|
|
||||||
{
|
{
|
||||||
bool res = !!P_ExecuteSpecial(special, NULL, triggerer, false, args[0], args[1],
|
bool res = !!P_ExecuteSpecial(special, NULL, triggerer, false, args[0], args[1],
|
||||||
args[2], args[3], args[4]);
|
args[2], args[3], args[4]);
|
||||||
|
@ -196,6 +209,7 @@ class ASecActUse : public ASectorAction
|
||||||
{
|
{
|
||||||
DECLARE_CLASS (ASecActUse, ASectorAction)
|
DECLARE_CLASS (ASecActUse, ASectorAction)
|
||||||
public:
|
public:
|
||||||
|
ASecActUse() : ASectorAction (true) {}
|
||||||
bool DoTriggerAction (AActor *triggerer, int activationType);
|
bool DoTriggerAction (AActor *triggerer, int activationType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -214,6 +228,7 @@ class ASecActUseWall : public ASectorAction
|
||||||
{
|
{
|
||||||
DECLARE_CLASS (ASecActUseWall, ASectorAction)
|
DECLARE_CLASS (ASecActUseWall, ASectorAction)
|
||||||
public:
|
public:
|
||||||
|
ASecActUseWall() : ASectorAction (true) {}
|
||||||
bool DoTriggerAction (AActor *triggerer, int activationType);
|
bool DoTriggerAction (AActor *triggerer, int activationType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -701,25 +701,15 @@ FState *AWeapon::GetAltAtkState (bool hold)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// AWeapon :: GetRelState
|
// AWeapon :: GetStateForButtonName
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
FState *AWeapon::GetRelState ()
|
FState *AWeapon::GetStateForButtonName (FName button)
|
||||||
{
|
{
|
||||||
return FindState(NAME_Reload);
|
return FindState(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// AWeapon :: GetZoomState
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
FState *AWeapon::GetZoomState ()
|
|
||||||
{
|
|
||||||
return FindState(NAME_Zoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Weapon giver ***********************************************************/
|
/* Weapon giver ***********************************************************/
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,7 @@ DHUDMessage::DHUDMessage (FFont *font, const char *text, float x, float y, int h
|
||||||
NoWrap = false;
|
NoWrap = false;
|
||||||
ClipX = ClipY = ClipWidth = ClipHeight = 0;
|
ClipX = ClipY = ClipWidth = ClipHeight = 0;
|
||||||
WrapWidth = 0;
|
WrapWidth = 0;
|
||||||
|
HandleAspect = true;
|
||||||
Top = y;
|
Top = y;
|
||||||
Next = NULL;
|
Next = NULL;
|
||||||
Lines = NULL;
|
Lines = NULL;
|
||||||
|
@ -196,6 +197,14 @@ void DHUDMessage::Serialize (FArchive &arc)
|
||||||
NoWrap = false;
|
NoWrap = false;
|
||||||
ClipX = ClipY = ClipWidth = ClipHeight = WrapWidth = 0;
|
ClipX = ClipY = ClipWidth = ClipHeight = WrapWidth = 0;
|
||||||
}
|
}
|
||||||
|
if (SaveVersion >= 4525)
|
||||||
|
{
|
||||||
|
arc << HandleAspect;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleAspect = true;
|
||||||
|
}
|
||||||
if (arc.IsLoading ())
|
if (arc.IsLoading ())
|
||||||
{
|
{
|
||||||
Lines = NULL;
|
Lines = NULL;
|
||||||
|
@ -257,7 +266,7 @@ void DHUDMessage::CalcClipCoords(int hudheight)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
screen->VirtualToRealCoordsInt(x, y, w, h,
|
screen->VirtualToRealCoordsInt(x, y, w, h,
|
||||||
HUDWidth, hudheight, false, true);
|
HUDWidth, hudheight, false, HandleAspect);
|
||||||
ClipLeft = x;
|
ClipLeft = x;
|
||||||
ClipTop = y;
|
ClipTop = y;
|
||||||
ClipRight = x + w;
|
ClipRight = x + w;
|
||||||
|
|
|
@ -94,12 +94,13 @@ public:
|
||||||
NoWrap = nowrap;
|
NoWrap = nowrap;
|
||||||
ResetText(SourceText);
|
ResetText(SourceText);
|
||||||
}
|
}
|
||||||
void SetClipRect(int x, int y, int width, int height)
|
void SetClipRect(int x, int y, int width, int height, bool aspect)
|
||||||
{
|
{
|
||||||
ClipX = x;
|
ClipX = x;
|
||||||
ClipY = y;
|
ClipY = y;
|
||||||
ClipWidth = width;
|
ClipWidth = width;
|
||||||
ClipHeight = height;
|
ClipHeight = height;
|
||||||
|
HandleAspect = aspect;
|
||||||
}
|
}
|
||||||
void SetWrapWidth(int wrap)
|
void SetWrapWidth(int wrap)
|
||||||
{
|
{
|
||||||
|
@ -119,6 +120,7 @@ protected:
|
||||||
int HUDWidth, HUDHeight;
|
int HUDWidth, HUDHeight;
|
||||||
int ClipX, ClipY, ClipWidth, ClipHeight, WrapWidth; // in HUD coords
|
int ClipX, ClipY, ClipWidth, ClipHeight, WrapWidth; // in HUD coords
|
||||||
int ClipLeft, ClipTop, ClipRight, ClipBot; // in screen coords
|
int ClipLeft, ClipTop, ClipRight, ClipBot; // in screen coords
|
||||||
|
bool HandleAspect;
|
||||||
EColorRange TextColor;
|
EColorRange TextColor;
|
||||||
FFont *Font;
|
FFont *Font;
|
||||||
FRenderStyle Style;
|
FRenderStyle Style;
|
||||||
|
|
|
@ -223,6 +223,10 @@ xx(Flash)
|
||||||
xx(AltFlash)
|
xx(AltFlash)
|
||||||
xx(Reload)
|
xx(Reload)
|
||||||
xx(Zoom)
|
xx(Zoom)
|
||||||
|
xx(User1)
|
||||||
|
xx(User2)
|
||||||
|
xx(User3)
|
||||||
|
xx(User4)
|
||||||
|
|
||||||
// State names used by ASwitchableDecoration
|
// State names used by ASwitchableDecoration
|
||||||
xx(Active)
|
xx(Active)
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#define HALF_PI (PI*0.5)
|
#define HALF_PI (PI*0.5)
|
||||||
|
|
||||||
EXTERN_CVAR(Int, opl_core)
|
EXTERN_CVAR(Int, opl_core)
|
||||||
|
extern int current_opl_core;
|
||||||
|
|
||||||
OPLio::~OPLio()
|
OPLio::~OPLio()
|
||||||
{
|
{
|
||||||
|
@ -323,7 +324,7 @@ int OPLio::OPLinit(uint numchips, bool stereo, bool initopl3)
|
||||||
{
|
{
|
||||||
assert(numchips >= 1 && numchips <= countof(chips));
|
assert(numchips >= 1 && numchips <= countof(chips));
|
||||||
uint i;
|
uint i;
|
||||||
IsOPL3 = (opl_core == 1 || opl_core == 2 || opl_core == 3);
|
IsOPL3 = (current_opl_core == 1 || current_opl_core == 2 || current_opl_core == 3);
|
||||||
|
|
||||||
memset(chips, 0, sizeof(chips));
|
memset(chips, 0, sizeof(chips));
|
||||||
if (IsOPL3)
|
if (IsOPL3)
|
||||||
|
@ -332,7 +333,7 @@ int OPLio::OPLinit(uint numchips, bool stereo, bool initopl3)
|
||||||
}
|
}
|
||||||
for (i = 0; i < numchips; ++i)
|
for (i = 0; i < numchips; ++i)
|
||||||
{
|
{
|
||||||
OPLEmul *chip = IsOPL3 ? (opl_core == 1 ? DBOPLCreate(stereo) : (opl_core == 2 ? JavaOPLCreate(stereo) : NukedOPL3Create(stereo))) : YM3812Create(stereo);
|
OPLEmul *chip = IsOPL3 ? (current_opl_core == 1 ? DBOPLCreate(stereo) : (current_opl_core == 2 ? JavaOPLCreate(stereo) : NukedOPL3Create(stereo))) : YM3812Create(stereo);
|
||||||
if (chip == NULL)
|
if (chip == NULL)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
void OPL_SetCore(const char *args);
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
|
@ -76,8 +77,9 @@ CVAR(Bool, opl_fullpan, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
OPLMIDIDevice::OPLMIDIDevice()
|
OPLMIDIDevice::OPLMIDIDevice(const char *args)
|
||||||
{
|
{
|
||||||
|
OPL_SetCore(args);
|
||||||
FullPan = opl_fullpan;
|
FullPan = opl_fullpan;
|
||||||
FWadLump data = Wads.OpenLumpName("GENMIDI");
|
FWadLump data = Wads.OpenLumpName("GENMIDI");
|
||||||
OPLloadBank(data);
|
OPLloadBank(data);
|
||||||
|
|
|
@ -262,6 +262,7 @@ protected:
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
OPLDumperMIDIDevice::OPLDumperMIDIDevice(const char *filename)
|
OPLDumperMIDIDevice::OPLDumperMIDIDevice(const char *filename)
|
||||||
|
: OPLMIDIDevice(NULL)
|
||||||
{
|
{
|
||||||
// Replace the standard OPL device with a disk writer.
|
// Replace the standard OPL device with a disk writer.
|
||||||
delete io;
|
delete io;
|
||||||
|
|
|
@ -1264,7 +1264,7 @@ static int UseInventory (AActor *activator, const char *type)
|
||||||
//
|
//
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
static int CheckInventory (AActor *activator, const char *type)
|
static int CheckInventory (AActor *activator, const char *type, bool max)
|
||||||
{
|
{
|
||||||
if (activator == NULL || type == NULL)
|
if (activator == NULL || type == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1275,11 +1275,26 @@ static int CheckInventory (AActor *activator, const char *type)
|
||||||
}
|
}
|
||||||
else if (stricmp (type, "Health") == 0)
|
else if (stricmp (type, "Health") == 0)
|
||||||
{
|
{
|
||||||
|
if (max)
|
||||||
|
{
|
||||||
|
if (activator->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
||||||
|
return static_cast<APlayerPawn *>(activator)->MaxHealth;
|
||||||
|
else
|
||||||
|
return activator->SpawnHealth();
|
||||||
|
}
|
||||||
return activator->health;
|
return activator->health;
|
||||||
}
|
}
|
||||||
|
|
||||||
PClassActor *info = PClass::FindActor (type);
|
PClassActor *info = PClass::FindActor (type);
|
||||||
AInventory *item = activator->FindInventory (info);
|
AInventory *item = activator->FindInventory (info);
|
||||||
|
|
||||||
|
if (max)
|
||||||
|
{
|
||||||
|
if (item)
|
||||||
|
return item->MaxAmount;
|
||||||
|
else
|
||||||
|
return ((AInventory *)GetDefaultByType (info))->MaxAmount;
|
||||||
|
}
|
||||||
return item ? item->Amount : 0;
|
return item ? item->Amount : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4441,6 +4456,7 @@ enum EACSFunctions
|
||||||
ACSF_GetActorRoll,
|
ACSF_GetActorRoll,
|
||||||
ACSF_QuakeEx,
|
ACSF_QuakeEx,
|
||||||
ACSF_Warp, // 92
|
ACSF_Warp, // 92
|
||||||
|
ACSF_GetMaxInventory,
|
||||||
|
|
||||||
/* Zandronum's - these must be skipped when we reach 99!
|
/* Zandronum's - these must be skipped when we reach 99!
|
||||||
-100:ResetMap(0),
|
-100:ResetMap(0),
|
||||||
|
@ -5307,6 +5323,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
|
||||||
ClipRectWidth = argCount > 2 ? args[2] : 0;
|
ClipRectWidth = argCount > 2 ? args[2] : 0;
|
||||||
ClipRectHeight = argCount > 3 ? args[3] : 0;
|
ClipRectHeight = argCount > 3 ? args[3] : 0;
|
||||||
WrapWidth = argCount > 4 ? args[4] : 0;
|
WrapWidth = argCount > 4 ? args[4] : 0;
|
||||||
|
HandleAspect = argCount > 5 ? !!args[5] : true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACSF_SetHUDWrapWidth:
|
case ACSF_SetHUDWrapWidth:
|
||||||
|
@ -5906,11 +5923,19 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
case ACSF_GetMaxInventory:
|
||||||
|
actor = SingleActorFromTID(args[0], activator);
|
||||||
|
if (actor != NULL)
|
||||||
|
{
|
||||||
|
return CheckInventory(actor, FBehavior::StaticLookupString(args[1]), true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7846,7 +7871,7 @@ scriptwait:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
msg->SetClipRect(ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight);
|
msg->SetClipRect(ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight, HandleAspect);
|
||||||
if (WrapWidth != 0)
|
if (WrapWidth != 0)
|
||||||
{
|
{
|
||||||
msg->SetWrapWidth(WrapWidth);
|
msg->SetWrapWidth(WrapWidth);
|
||||||
|
@ -8329,17 +8354,17 @@ scriptwait:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCD_CHECKINVENTORY:
|
case PCD_CHECKINVENTORY:
|
||||||
STACK(1) = CheckInventory (activator, FBehavior::StaticLookupString (STACK(1)));
|
STACK(1) = CheckInventory (activator, FBehavior::StaticLookupString (STACK(1)), false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCD_CHECKACTORINVENTORY:
|
case PCD_CHECKACTORINVENTORY:
|
||||||
STACK(2) = CheckInventory (SingleActorFromTID(STACK(2), NULL),
|
STACK(2) = CheckInventory (SingleActorFromTID(STACK(2), NULL),
|
||||||
FBehavior::StaticLookupString (STACK(1)));
|
FBehavior::StaticLookupString (STACK(1)), false);
|
||||||
sp--;
|
sp--;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCD_CHECKINVENTORYDIRECT:
|
case PCD_CHECKINVENTORYDIRECT:
|
||||||
PushToStack (CheckInventory (activator, FBehavior::StaticLookupString (TAGSTR(uallong(pc[0])))));
|
PushToStack (CheckInventory (activator, FBehavior::StaticLookupString (TAGSTR(uallong(pc[0]))), false));
|
||||||
pc += 1;
|
pc += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -9458,6 +9483,7 @@ DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr
|
||||||
activefont = SmallFont;
|
activefont = SmallFont;
|
||||||
hudwidth = hudheight = 0;
|
hudwidth = hudheight = 0;
|
||||||
ClipRectLeft = ClipRectTop = ClipRectWidth = ClipRectHeight = WrapWidth = 0;
|
ClipRectLeft = ClipRectTop = ClipRectWidth = ClipRectHeight = WrapWidth = 0;
|
||||||
|
HandleAspect = true;
|
||||||
state = SCRIPT_Running;
|
state = SCRIPT_Running;
|
||||||
|
|
||||||
// Hexen waited one second before executing any open scripts. I didn't realize
|
// Hexen waited one second before executing any open scripts. I didn't realize
|
||||||
|
|
|
@ -891,6 +891,7 @@ protected:
|
||||||
int hudwidth, hudheight;
|
int hudwidth, hudheight;
|
||||||
int ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight;
|
int ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight;
|
||||||
int WrapWidth;
|
int WrapWidth;
|
||||||
|
bool HandleAspect;
|
||||||
FBehavior *activeBehavior;
|
FBehavior *activeBehavior;
|
||||||
int InModuleScriptNumber;
|
int InModuleScriptNumber;
|
||||||
|
|
||||||
|
|
|
@ -1347,9 +1347,10 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
|
||||||
int rootnode = npc->ConversationRoot;
|
int rootnode = npc->ConversationRoot;
|
||||||
if (reply->NextNode < 0)
|
if (reply->NextNode < 0)
|
||||||
{
|
{
|
||||||
npc->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1];
|
unsigned next = (unsigned)(rootnode - reply->NextNode - 1);
|
||||||
if (gameaction != ga_slideshow)
|
if (gameaction != ga_slideshow && next < StrifeDialogues.Size())
|
||||||
{
|
{
|
||||||
|
npc->Conversation = StrifeDialogues[next];
|
||||||
P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false);
|
P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2587,6 +2587,7 @@ FUNC(LS_Line_SetBlocking)
|
||||||
ML_BLOCKUSE,
|
ML_BLOCKUSE,
|
||||||
ML_BLOCKSIGHT,
|
ML_BLOCKSIGHT,
|
||||||
ML_BLOCKHITSCAN,
|
ML_BLOCKHITSCAN,
|
||||||
|
ML_SOUNDBLOCK,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
213
src/p_pspr.cpp
213
src/p_pspr.cpp
|
@ -38,6 +38,30 @@
|
||||||
|
|
||||||
// TYPES -------------------------------------------------------------------
|
// TYPES -------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct FGenericButtons
|
||||||
|
{
|
||||||
|
int ReadyFlag; // Flag passed to A_WeaponReady
|
||||||
|
int StateFlag; // Flag set in WeaponState
|
||||||
|
int ButtonFlag; // Button to press
|
||||||
|
ENamedName StateName; // Name of the button/state
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EWRF_Options
|
||||||
|
{
|
||||||
|
WRF_NoBob = 1,
|
||||||
|
WRF_NoSwitch = 1 << 1,
|
||||||
|
WRF_NoPrimary = 1 << 2,
|
||||||
|
WRF_NoSecondary = 1 << 3,
|
||||||
|
WRF_NoFire = WRF_NoPrimary | WRF_NoSecondary,
|
||||||
|
WRF_AllowReload = 1 << 4,
|
||||||
|
WRF_AllowZoom = 1 << 5,
|
||||||
|
WRF_DisableSwitch = 1 << 6,
|
||||||
|
WRF_AllowUser1 = 1 << 7,
|
||||||
|
WRF_AllowUser2 = 1 << 8,
|
||||||
|
WRF_AllowUser3 = 1 << 9,
|
||||||
|
WRF_AllowUser4 = 1 << 10,
|
||||||
|
};
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
@ -57,6 +81,16 @@ CVAR(Int, sv_fastweapons, false, CVAR_SERVERINFO);
|
||||||
static FRandom pr_wpnreadysnd ("WpnReadySnd");
|
static FRandom pr_wpnreadysnd ("WpnReadySnd");
|
||||||
static FRandom pr_gunshot ("GunShot");
|
static FRandom pr_gunshot ("GunShot");
|
||||||
|
|
||||||
|
static const FGenericButtons ButtonChecks[] =
|
||||||
|
{
|
||||||
|
{ WRF_AllowZoom, WF_WEAPONZOOMOK, BT_ZOOM, NAME_Zoom },
|
||||||
|
{ WRF_AllowReload, WF_WEAPONRELOADOK, BT_RELOAD, NAME_Reload },
|
||||||
|
{ WRF_AllowUser1, WF_USER1OK, BT_USER1, NAME_User1 },
|
||||||
|
{ WRF_AllowUser2, WF_USER2OK, BT_USER2, NAME_User2 },
|
||||||
|
{ WRF_AllowUser3, WF_USER3OK, BT_USER3, NAME_User3 },
|
||||||
|
{ WRF_AllowUser4, WF_USER4OK, BT_USER4, NAME_User4 },
|
||||||
|
};
|
||||||
|
|
||||||
// CODE --------------------------------------------------------------------
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -95,7 +129,8 @@ void P_SetPsprite (player_t *player, int position, FState *state, bool nofunctio
|
||||||
|
|
||||||
if (position == ps_weapon && !nofunction)
|
if (position == ps_weapon && !nofunction)
|
||||||
{ // A_WeaponReady will re-set these as needed
|
{ // A_WeaponReady will re-set these as needed
|
||||||
player->WeaponState &= ~(WF_WEAPONREADY | WF_WEAPONREADYALT | WF_WEAPONBOBBING | WF_WEAPONSWITCHOK | WF_WEAPONRELOADOK | WF_WEAPONZOOMOK);
|
player->WeaponState &= ~(WF_WEAPONREADY | WF_WEAPONREADYALT | WF_WEAPONBOBBING | WF_WEAPONSWITCHOK | WF_WEAPONRELOADOK | WF_WEAPONZOOMOK |
|
||||||
|
WF_USER1OK | WF_USER2OK | WF_USER3OK | WF_USER4OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
psp = &player->psprites[position];
|
psp = &player->psprites[position];
|
||||||
|
@ -289,66 +324,6 @@ void P_FireWeaponAlt (player_t *player, FState *state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC P_ReloadWeapon
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void P_ReloadWeapon (player_t *player, FState *state)
|
|
||||||
{
|
|
||||||
AWeapon *weapon;
|
|
||||||
if (player->Bot == NULL && bot_observer)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
weapon = player->ReadyWeapon;
|
|
||||||
if (weapon == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == NULL)
|
|
||||||
{
|
|
||||||
state = weapon->GetRelState();
|
|
||||||
}
|
|
||||||
// [XA] don't change state if still null, so if the modder sets
|
|
||||||
// WRF_RELOAD to true but forgets to define the Reload state, the weapon
|
|
||||||
// won't disappear. ;)
|
|
||||||
if (state != NULL)
|
|
||||||
P_SetPsprite (player, ps_weapon, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC P_ZoomWeapon
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void P_ZoomWeapon (player_t *player, FState *state)
|
|
||||||
{
|
|
||||||
AWeapon *weapon;
|
|
||||||
if (player->Bot == NULL && bot_observer)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
weapon = player->ReadyWeapon;
|
|
||||||
if (weapon == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == NULL)
|
|
||||||
{
|
|
||||||
state = weapon->GetZoomState();
|
|
||||||
}
|
|
||||||
// [XA] don't change state if still null. Same reasons as above.
|
|
||||||
if (state != NULL)
|
|
||||||
P_SetPsprite (player, ps_weapon, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// PROC P_DropWeapon
|
// PROC P_DropWeapon
|
||||||
|
@ -562,22 +537,21 @@ void DoReadyWeaponToBob (AActor *self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoReadyWeaponToReload (AActor *self)
|
void DoReadyWeaponToGeneric(AActor *self, int paramflags)
|
||||||
{
|
{
|
||||||
// Prepare for reload action.
|
int flags = 0;
|
||||||
player_t *player;
|
|
||||||
if (self && (player = self->player))
|
|
||||||
player->WeaponState |= WF_WEAPONRELOADOK;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoReadyWeaponToZoom (AActor *self)
|
for (size_t i = 0; i < countof(ButtonChecks); ++i)
|
||||||
{
|
{
|
||||||
// Prepare for reload action.
|
if (paramflags & ButtonChecks[i].ReadyFlag)
|
||||||
player_t *player;
|
{
|
||||||
if (self && (player = self->player))
|
flags |= ButtonChecks[i].StateFlag;
|
||||||
player->WeaponState |= WF_WEAPONZOOMOK;
|
}
|
||||||
return;
|
}
|
||||||
|
if (self != NULL && self->player != NULL)
|
||||||
|
{
|
||||||
|
self->player->WeaponState |= flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function replaces calls to A_WeaponReady in other codepointers.
|
// This function replaces calls to A_WeaponReady in other codepointers.
|
||||||
|
@ -586,33 +560,18 @@ void DoReadyWeapon(AActor *self)
|
||||||
DoReadyWeaponToBob(self);
|
DoReadyWeaponToBob(self);
|
||||||
DoReadyWeaponToFire(self);
|
DoReadyWeaponToFire(self);
|
||||||
DoReadyWeaponToSwitch(self);
|
DoReadyWeaponToSwitch(self);
|
||||||
DoReadyWeaponToReload(self);
|
DoReadyWeaponToGeneric(self, ~0);
|
||||||
DoReadyWeaponToZoom(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EWRF_Options
|
|
||||||
{
|
|
||||||
WRF_NoBob = 1,
|
|
||||||
WRF_NoSwitch = 2,
|
|
||||||
WRF_NoPrimary = 4,
|
|
||||||
WRF_NoSecondary = 8,
|
|
||||||
WRF_NoFire = WRF_NoPrimary + WRF_NoSecondary,
|
|
||||||
WRF_AllowReload = 16,
|
|
||||||
WRF_AllowZoom = 32,
|
|
||||||
WRF_DisableSwitch = 64,
|
|
||||||
};
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady)
|
DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady)
|
||||||
{
|
{
|
||||||
PARAM_ACTION_PROLOGUE;
|
PARAM_ACTION_PROLOGUE;
|
||||||
PARAM_INT_OPT(flags) { flags = 0; }
|
PARAM_INT_OPT(flags) { flags = 0; }
|
||||||
|
|
||||||
DoReadyWeaponToSwitch(self, !(flags & WRF_NoSwitch));
|
DoReadyWeaponToSwitch(self, !(flags & WRF_NoSwitch));
|
||||||
if ((flags & WRF_NoFire) != WRF_NoFire) DoReadyWeaponToFire(self, !(flags & WRF_NoPrimary), !(flags & WRF_NoSecondary));
|
if ((flags & WRF_NoFire) != WRF_NoFire) DoReadyWeaponToFire(self, !(flags & WRF_NoPrimary), !(flags & WRF_NoSecondary));
|
||||||
if (!(flags & WRF_NoBob)) DoReadyWeaponToBob(self);
|
if (!(flags & WRF_NoBob)) DoReadyWeaponToBob(self);
|
||||||
if ((flags & WRF_AllowReload)) DoReadyWeaponToReload(self);
|
DoReadyWeaponToGeneric(self, flags);
|
||||||
if ((flags & WRF_AllowZoom)) DoReadyWeaponToZoom(self);
|
|
||||||
|
|
||||||
DoReadyWeaponDisableSwitch(self, flags & WRF_DisableSwitch);
|
DoReadyWeaponDisableSwitch(self, flags & WRF_DisableSwitch);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -691,45 +650,40 @@ void P_CheckWeaponSwitch (player_t *player)
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// PROC P_CheckWeaponReload
|
// PROC P_CheckWeaponButtons
|
||||||
//
|
//
|
||||||
// The player can reload the weapon.
|
// Check extra button presses for weapons.
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void P_CheckWeaponReload (player_t *player)
|
static void P_CheckWeaponButtons (player_t *player)
|
||||||
{
|
{
|
||||||
AWeapon *weapon = player->ReadyWeapon;
|
if (player->Bot == NULL && bot_observer)
|
||||||
|
|
||||||
if (weapon == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Check for reload.
|
|
||||||
if ((player->WeaponState & WF_WEAPONRELOADOK) && (player->cmd.ucmd.buttons & BT_RELOAD))
|
|
||||||
{
|
{
|
||||||
P_ReloadWeapon (player, NULL);
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// PROC P_CheckWeaponZoom
|
|
||||||
//
|
|
||||||
// The player can use the weapon's zoom function.
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void P_CheckWeaponZoom (player_t *player)
|
|
||||||
{
|
|
||||||
AWeapon *weapon = player->ReadyWeapon;
|
AWeapon *weapon = player->ReadyWeapon;
|
||||||
|
|
||||||
if (weapon == NULL)
|
if (weapon == NULL)
|
||||||
return;
|
|
||||||
|
|
||||||
// Check for zoom.
|
|
||||||
if ((player->WeaponState & WF_WEAPONZOOMOK) && (player->cmd.ucmd.buttons & BT_ZOOM))
|
|
||||||
{
|
{
|
||||||
P_ZoomWeapon (player, NULL);
|
return;
|
||||||
|
}
|
||||||
|
// The button checks are ordered by precedence. The first one to match a
|
||||||
|
// button press and affect a state change wins.
|
||||||
|
for (size_t i = 0; i < countof(ButtonChecks); ++i)
|
||||||
|
{
|
||||||
|
if ((player->WeaponState & ButtonChecks[i].StateFlag) &&
|
||||||
|
(player->cmd.ucmd.buttons & ButtonChecks[i].ButtonFlag))
|
||||||
|
{
|
||||||
|
FState *state = weapon->GetStateForButtonName(ButtonChecks[i].StateName);
|
||||||
|
// [XA] don't change state if still null, so if the modder
|
||||||
|
// sets WRF_xxx to true but forgets to define the corresponding
|
||||||
|
// state, the weapon won't disappear. ;)
|
||||||
|
if (state != NULL)
|
||||||
|
{
|
||||||
|
P_SetPsprite(player, ps_weapon, state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1126,15 +1080,10 @@ void P_MovePsprites (player_t *player)
|
||||||
{
|
{
|
||||||
P_CheckWeaponFire (player);
|
P_CheckWeaponFire (player);
|
||||||
}
|
}
|
||||||
if (player->WeaponState & WF_WEAPONRELOADOK)
|
|
||||||
{
|
// Check custom buttons
|
||||||
P_CheckWeaponReload (player);
|
P_CheckWeaponButtons(player);
|
||||||
}
|
}
|
||||||
if (player->WeaponState & WF_WEAPONZOOMOK)
|
|
||||||
{
|
|
||||||
P_CheckWeaponZoom (player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FArchive &operator<< (FArchive &arc, pspdef_t &def)
|
FArchive &operator<< (FArchive &arc, pspdef_t &def)
|
||||||
|
|
|
@ -288,16 +288,16 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (activationType == SPAC_Use && (lineActivation & SPAC_MUse) && !mo->player && mo->flags4 & MF4_CANUSEWALLS)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (activationType == SPAC_Push && (lineActivation & SPAC_MPush) && !mo->player && mo->flags2 & MF2_PUSHWALL)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if ((lineActivation & activationType) == 0)
|
if ((lineActivation & activationType) == 0)
|
||||||
{
|
{
|
||||||
if (activationType == SPAC_Use && (lineActivation & SPAC_MUse) && !mo->player && mo->flags4 & MF4_CANUSEWALLS)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (activationType == SPAC_Push && (lineActivation & SPAC_MPush) && !mo->player && mo->flags2 & MF2_PUSHWALL)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (activationType != SPAC_MCross || lineActivation != SPAC_Cross)
|
if (activationType != SPAC_MCross || lineActivation != SPAC_Cross)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -177,10 +177,47 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno)
|
||||||
|
|
||||||
if ((TexMan.FindSwitch(side->GetTexture(side_t::top))) != NULL)
|
if ((TexMan.FindSwitch(side->GetTexture(side_t::top))) != NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Check 3D floors on back side
|
||||||
|
{
|
||||||
|
sector_t * back = line->sidedef[1 - sideno]->sector;
|
||||||
|
for (unsigned i = 0; i < back->e->XFloor.ffloors.Size(); i++)
|
||||||
|
{
|
||||||
|
F3DFloor *rover = back->e->XFloor.ffloors[i];
|
||||||
|
if (!(rover->flags & FF_EXISTS)) continue;
|
||||||
|
if (!(rover->flags & FF_UPPERTEXTURE)) continue;
|
||||||
|
|
||||||
|
if (user->z > rover->top.plane->ZatPoint(checkx, checky) ||
|
||||||
|
user->z + user->height < rover->bottom.plane->ZatPoint(checkx, checky))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// This 3D floor depicts a switch texture in front of the player's eyes
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (user->z + user->height > open.top);
|
return (user->z + user->height > open.top);
|
||||||
}
|
}
|
||||||
else if ((TexMan.FindSwitch(side->GetTexture(side_t::bottom))) != NULL)
|
else if ((TexMan.FindSwitch(side->GetTexture(side_t::bottom))) != NULL)
|
||||||
{
|
{
|
||||||
|
// Check 3D floors on back side
|
||||||
|
{
|
||||||
|
sector_t * back = line->sidedef[1 - sideno]->sector;
|
||||||
|
for (unsigned i = 0; i < back->e->XFloor.ffloors.Size(); i++)
|
||||||
|
{
|
||||||
|
F3DFloor *rover = back->e->XFloor.ffloors[i];
|
||||||
|
if (!(rover->flags & FF_EXISTS)) continue;
|
||||||
|
if (!(rover->flags & FF_LOWERTEXTURE)) continue;
|
||||||
|
|
||||||
|
if (user->z > rover->top.plane->ZatPoint(checkx, checky) ||
|
||||||
|
user->z + user->height < rover->bottom.plane->ZatPoint(checkx, checky))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// This 3D floor depicts a switch texture in front of the player's eyes
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (user->z < open.bottom);
|
return (user->z < open.bottom);
|
||||||
}
|
}
|
||||||
else if ((flags & ML_3DMIDTEX) || (TexMan.FindSwitch(side->GetTexture(side_t::mid))) != NULL)
|
else if ((flags & ML_3DMIDTEX) || (TexMan.FindSwitch(side->GetTexture(side_t::mid))) != NULL)
|
||||||
|
|
|
@ -785,7 +785,7 @@ public:
|
||||||
bool strifetrans = false;
|
bool strifetrans = false;
|
||||||
bool strifetrans2 = false;
|
bool strifetrans2 = false;
|
||||||
FString arg0str, arg1str;
|
FString arg0str, arg1str;
|
||||||
int lineid; // forZDoomTranslated namespace
|
int lineid = -1; // forZDoomTranslated namespace
|
||||||
FString tagstring;
|
FString tagstring;
|
||||||
|
|
||||||
memset(ld, 0, sizeof(*ld));
|
memset(ld, 0, sizeof(*ld));
|
||||||
|
@ -1082,7 +1082,7 @@ public:
|
||||||
maplinedef_t mld;
|
maplinedef_t mld;
|
||||||
memset(&mld, 0, sizeof(mld));
|
memset(&mld, 0, sizeof(mld));
|
||||||
mld.special = ld->special;
|
mld.special = ld->special;
|
||||||
mld.tag = lineid;
|
mld.tag = ld->args[0];
|
||||||
P_TranslateLineDef(ld, &mld);
|
P_TranslateLineDef(ld, &mld);
|
||||||
ld->flags = saved | (ld->flags&(ML_MONSTERSCANACTIVATE|ML_REPEAT_SPECIAL|ML_FIRSTSIDEONLY));
|
ld->flags = saved | (ld->flags&(ML_MONSTERSCANACTIVATE|ML_REPEAT_SPECIAL|ML_FIRSTSIDEONLY));
|
||||||
}
|
}
|
||||||
|
|
|
@ -649,6 +649,10 @@ void APlayerPawn::Serialize (FArchive &arc)
|
||||||
{
|
{
|
||||||
arc << AirCapacity;
|
arc << AirCapacity;
|
||||||
}
|
}
|
||||||
|
if (SaveVersion >= 4526)
|
||||||
|
{
|
||||||
|
arc << ViewHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -3126,6 +3130,12 @@ void player_t::Serialize (FArchive &arc)
|
||||||
WeaponState = ((cheats >> 14) & 1) | ((cheats & (0x37 << 24)) >> (24 - 1));
|
WeaponState = ((cheats >> 14) & 1) | ((cheats & (0x37 << 24)) >> (24 - 1));
|
||||||
cheats &= ~((1 << 14) | (0x37 << 24));
|
cheats &= ~((1 << 14) | (0x37 << 24));
|
||||||
}
|
}
|
||||||
|
if (SaveVersion < 4527)
|
||||||
|
{
|
||||||
|
BYTE oldWeaponState;
|
||||||
|
arc << oldWeaponState;
|
||||||
|
WeaponState = oldWeaponState;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
arc << WeaponState;
|
arc << WeaponState;
|
||||||
|
|
134
src/pathexpander.cpp
Normal file
134
src/pathexpander.cpp
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
** pathexpander.cpp
|
||||||
|
** Utility class for expanding a given path with a range of directories
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2015 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pathexpander.h"
|
||||||
|
#include "cmdlib.h"
|
||||||
|
#include "w_wad.h"
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
static FString BuildPath(const FString &base, const char *name)
|
||||||
|
{
|
||||||
|
FString current;
|
||||||
|
if (base.IsNotEmpty())
|
||||||
|
{
|
||||||
|
current = base;
|
||||||
|
if (current[current.Len() - 1] != '/') current += '/';
|
||||||
|
}
|
||||||
|
current += name;
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// This is meant to find and open files for reading.
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
FileReader *PathExpander::openFileReader(const char *name, int *plumpnum)
|
||||||
|
{
|
||||||
|
FileReader *fp;
|
||||||
|
FString current_filename;
|
||||||
|
|
||||||
|
if (!name || !(*name))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First try the given name */
|
||||||
|
current_filename = name;
|
||||||
|
FixPathSeperator(current_filename);
|
||||||
|
|
||||||
|
|
||||||
|
if (openmode != OM_FILE)
|
||||||
|
{
|
||||||
|
int lumpnum = Wads.CheckNumForFullName(current_filename);
|
||||||
|
if (lumpnum >= 0)
|
||||||
|
{
|
||||||
|
fp = Wads.ReopenLumpNum(lumpnum);
|
||||||
|
if (plumpnum) *plumpnum = lumpnum;
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
if (openmode == OM_LUMP) // search the path list when not loading the main config
|
||||||
|
{
|
||||||
|
for (unsigned int plp = PathList.Size(); plp-- != 0; )
|
||||||
|
{ /* Try along the path then */
|
||||||
|
current_filename = BuildPath(PathList[plp], name);
|
||||||
|
lumpnum = Wads.CheckNumForFullName(current_filename);
|
||||||
|
if (lumpnum >= 0)
|
||||||
|
{
|
||||||
|
fp = Wads.ReopenLumpNum(lumpnum);
|
||||||
|
if (plumpnum) *plumpnum = lumpnum;
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (plumpnum) *plumpnum = -1;
|
||||||
|
|
||||||
|
|
||||||
|
fp = new FileReader;
|
||||||
|
if (fp->Open(current_filename)) return fp;
|
||||||
|
|
||||||
|
if (name[0] != '/')
|
||||||
|
{
|
||||||
|
for (unsigned int plp = PathList.Size(); plp-- != 0; )
|
||||||
|
{ /* Try along the path then */
|
||||||
|
current_filename = BuildPath(PathList[plp], name);
|
||||||
|
if (fp->Open(current_filename)) return fp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete fp;
|
||||||
|
|
||||||
|
/* Nothing could be opened. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This adds a directory to the path list */
|
||||||
|
void PathExpander::addToPathlist(const char *s)
|
||||||
|
{
|
||||||
|
FString copy = s;
|
||||||
|
FixPathSeperator(copy);
|
||||||
|
PathList.Push(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathExpander::clearPathlist()
|
||||||
|
{
|
||||||
|
PathList.Clear();
|
||||||
|
}
|
31
src/pathexpander.h
Normal file
31
src/pathexpander.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef __PATHEXPANDER_H
|
||||||
|
#define __PATHEXPANDER_H
|
||||||
|
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "zstring.h"
|
||||||
|
#include "files.h"
|
||||||
|
|
||||||
|
class PathExpander
|
||||||
|
{
|
||||||
|
TArray<FString> PathList;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int openmode;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OM_FILEORLUMP = 0,
|
||||||
|
OM_LUMP,
|
||||||
|
OM_FILE
|
||||||
|
};
|
||||||
|
|
||||||
|
PathExpander(int om = OM_FILEORLUMP)
|
||||||
|
{
|
||||||
|
openmode = om;
|
||||||
|
}
|
||||||
|
void addToPathlist(const char *s);
|
||||||
|
void clearPathlist();
|
||||||
|
FileReader *openFileReader(const char *name, int *plumpnum);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -194,14 +194,19 @@ class ASectorAction : public AActor
|
||||||
{
|
{
|
||||||
DECLARE_CLASS (ASectorAction, AActor)
|
DECLARE_CLASS (ASectorAction, AActor)
|
||||||
public:
|
public:
|
||||||
|
ASectorAction (bool activatedByUse = false);
|
||||||
void Destroy ();
|
void Destroy ();
|
||||||
void BeginPlay ();
|
void BeginPlay ();
|
||||||
void Activate (AActor *source);
|
void Activate (AActor *source);
|
||||||
void Deactivate (AActor *source);
|
void Deactivate (AActor *source);
|
||||||
bool TriggerAction(AActor *triggerer, int activationType);
|
bool TriggerAction(AActor *triggerer, int activationType);
|
||||||
|
bool CanTrigger (AActor *triggerer) const;
|
||||||
|
bool IsActivatedByUse() const;
|
||||||
protected:
|
protected:
|
||||||
virtual bool DoTriggerAction(AActor *triggerer, int activationType);
|
virtual bool DoTriggerAction(AActor *triggerer, int activationType);
|
||||||
bool CheckTrigger(AActor *triggerer) const;
|
bool CheckTrigger(AActor *triggerer) const;
|
||||||
|
private:
|
||||||
|
bool ActivatedByUse;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ASkyViewpoint;
|
class ASkyViewpoint;
|
||||||
|
|
|
@ -1364,15 +1364,36 @@ static void S_AddSNDINFO (int lump)
|
||||||
case SI_MidiDevice: {
|
case SI_MidiDevice: {
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
FName nm = sc.String;
|
FName nm = sc.String;
|
||||||
|
FScanner::SavedPos save = sc.SavePos();
|
||||||
|
|
||||||
|
sc.SetCMode(true);
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
if (sc.Compare("timidity")) MidiDevices[nm] = MDEV_TIMIDITY;
|
MidiDeviceSetting devset;
|
||||||
else if (sc.Compare("fmod") || sc.Compare("sndsys")) MidiDevices[nm] = MDEV_SNDSYS;
|
if (sc.Compare("timidity")) devset.device = MDEV_TIMIDITY;
|
||||||
else if (sc.Compare("standard")) MidiDevices[nm] = MDEV_MMAPI;
|
else if (sc.Compare("fmod") || sc.Compare("sndsys")) devset.device = MDEV_SNDSYS;
|
||||||
else if (sc.Compare("opl")) MidiDevices[nm] = MDEV_OPL;
|
else if (sc.Compare("standard")) devset.device = MDEV_MMAPI;
|
||||||
else if (sc.Compare("default")) MidiDevices[nm] = MDEV_DEFAULT;
|
else if (sc.Compare("opl")) devset.device = MDEV_OPL;
|
||||||
else if (sc.Compare("fluidsynth")) MidiDevices[nm] = MDEV_FLUIDSYNTH;
|
else if (sc.Compare("default")) devset.device = MDEV_DEFAULT;
|
||||||
else if (sc.Compare("gus")) MidiDevices[nm] = MDEV_GUS;
|
else if (sc.Compare("fluidsynth")) devset.device = MDEV_FLUIDSYNTH;
|
||||||
|
else if (sc.Compare("gus")) devset.device = MDEV_GUS;
|
||||||
|
else if (sc.Compare("wildmidi")) devset.device = MDEV_WILDMIDI;
|
||||||
else sc.ScriptError("Unknown MIDI device %s\n", sc.String);
|
else sc.ScriptError("Unknown MIDI device %s\n", sc.String);
|
||||||
|
|
||||||
|
if (sc.CheckString(","))
|
||||||
|
{
|
||||||
|
sc.SetCMode(false);
|
||||||
|
sc.MustGetString();
|
||||||
|
devset.args = sc.String;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This does not really do what one might expect, because the next token has already been parsed and can be a '$'.
|
||||||
|
// So in order to continue parsing without C-Mode, we need to reset and parse the last token again.
|
||||||
|
sc.SetCMode(false);
|
||||||
|
sc.RestorePos(save);
|
||||||
|
sc.MustGetString();
|
||||||
|
}
|
||||||
|
MidiDevices[nm] = devset;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -2421,11 +2421,8 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
||||||
{
|
{
|
||||||
int lumpnum = -1;
|
int lumpnum = -1;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
int device = MDEV_DEFAULT;
|
|
||||||
MusInfo *handle = NULL;
|
MusInfo *handle = NULL;
|
||||||
|
MidiDeviceSetting *devp = MidiDevices.CheckKey(musicname);
|
||||||
int *devp = MidiDevices.CheckKey(musicname);
|
|
||||||
if (devp != NULL) device = *devp;
|
|
||||||
|
|
||||||
// Strip off any leading file:// component.
|
// Strip off any leading file:// component.
|
||||||
if (strncmp(musicname, "file://", 7) == 0)
|
if (strncmp(musicname, "file://", 7) == 0)
|
||||||
|
@ -2495,7 +2492,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mus_playing.handle = I_RegisterSong (reader, device);
|
mus_playing.handle = I_RegisterSong (reader, devp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -394,10 +394,22 @@ enum EMidiDevice
|
||||||
MDEV_TIMIDITY = 3,
|
MDEV_TIMIDITY = 3,
|
||||||
MDEV_FLUIDSYNTH = 4,
|
MDEV_FLUIDSYNTH = 4,
|
||||||
MDEV_GUS = 5,
|
MDEV_GUS = 5,
|
||||||
|
MDEV_WILDMIDI = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MidiDeviceSetting
|
||||||
|
{
|
||||||
|
int device;
|
||||||
|
FString args;
|
||||||
|
|
||||||
|
MidiDeviceSetting()
|
||||||
|
{
|
||||||
|
device = MDEV_DEFAULT;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef TMap<FName, FName> MusicAliasMap;
|
typedef TMap<FName, FName> MusicAliasMap;
|
||||||
typedef TMap<FName, int> MidiDeviceMap;
|
typedef TMap<FName, MidiDeviceSetting> MidiDeviceMap;
|
||||||
|
|
||||||
extern MusicAliasMap MusicAliases;
|
extern MusicAliasMap MusicAliases;
|
||||||
extern MidiDeviceMap MidiDevices;
|
extern MidiDeviceMap MidiDevices;
|
||||||
|
|
|
@ -44,7 +44,7 @@ extern HWND Window;
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#endif
|
#endif
|
||||||
#ifdef __APPLE__
|
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#elif __sun
|
#elif __sun
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
|
|
|
@ -162,7 +162,7 @@ void I_InitMusic (void)
|
||||||
if (!setatterm)
|
if (!setatterm)
|
||||||
{
|
{
|
||||||
setatterm = true;
|
setatterm = true;
|
||||||
atterm (I_ShutdownMusic);
|
atterm (I_ShutdownMusicExit);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
signal (SIGCHLD, ChildSigHandler);
|
signal (SIGCHLD, ChildSigHandler);
|
||||||
|
@ -178,7 +178,7 @@ void I_InitMusic (void)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void I_ShutdownMusic(void)
|
void I_ShutdownMusic(bool onexit)
|
||||||
{
|
{
|
||||||
if (MusicDown)
|
if (MusicDown)
|
||||||
return;
|
return;
|
||||||
|
@ -189,11 +189,17 @@ void I_ShutdownMusic(void)
|
||||||
assert (currSong == NULL);
|
assert (currSong == NULL);
|
||||||
}
|
}
|
||||||
Timidity::FreeAll();
|
Timidity::FreeAll();
|
||||||
|
if (onexit) WildMidi_Shutdown();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
I_ShutdownMusicWin32();
|
I_ShutdownMusicWin32();
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_ShutdownMusicExit()
|
||||||
|
{
|
||||||
|
I_ShutdownMusic(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -280,6 +286,10 @@ void MusInfo::FluidSettingStr(const char *, const char *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MusInfo::WildMidiSetOption(int opt, int set)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
FString MusInfo::GetStats()
|
FString MusInfo::GetStats()
|
||||||
{
|
{
|
||||||
return "No stats available for this song";
|
return "No stats available for this song";
|
||||||
|
@ -301,21 +311,21 @@ MusInfo *MusInfo::GetWaveDumper(const char *filename, int rate)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static MIDIStreamer *CreateMIDIStreamer(FileReader &reader, EMidiDevice devtype, EMIDIType miditype)
|
static MIDIStreamer *CreateMIDIStreamer(FileReader &reader, EMidiDevice devtype, EMIDIType miditype, const char *args)
|
||||||
{
|
{
|
||||||
switch (miditype)
|
switch (miditype)
|
||||||
{
|
{
|
||||||
case MIDI_MUS:
|
case MIDI_MUS:
|
||||||
return new MUSSong2(reader, devtype);
|
return new MUSSong2(reader, devtype, args);
|
||||||
|
|
||||||
case MIDI_MIDI:
|
case MIDI_MIDI:
|
||||||
return new MIDISong2(reader, devtype);
|
return new MIDISong2(reader, devtype, args);
|
||||||
|
|
||||||
case MIDI_HMI:
|
case MIDI_HMI:
|
||||||
return new HMISong(reader, devtype);
|
return new HMISong(reader, devtype, args);
|
||||||
|
|
||||||
case MIDI_XMI:
|
case MIDI_XMI:
|
||||||
return new XMISong(reader, devtype);
|
return new XMISong(reader, devtype, args);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -377,7 +387,7 @@ static EMIDIType IdentifyMIDIType(DWORD *id, int size)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
MusInfo *I_RegisterSong (FileReader *reader, int device)
|
MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device)
|
||||||
{
|
{
|
||||||
MusInfo *info = NULL;
|
MusInfo *info = NULL;
|
||||||
const char *fmt;
|
const char *fmt;
|
||||||
|
@ -395,12 +405,6 @@ MusInfo *I_RegisterSong (FileReader *reader, int device)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
// non-Windows platforms don't support MDEV_MMAPI so map to MDEV_SNDSYS
|
|
||||||
if (device == MDEV_MMAPI)
|
|
||||||
device = MDEV_SNDSYS;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Check for gzip compression. Some formats are expected to have players
|
// Check for gzip compression. Some formats are expected to have players
|
||||||
// that can handle it, so it simplifies things if we make all songs
|
// that can handle it, so it simplifies things if we make all songs
|
||||||
// gzippable.
|
// gzippable.
|
||||||
|
@ -437,10 +441,15 @@ MusInfo *I_RegisterSong (FileReader *reader, int device)
|
||||||
EMIDIType miditype = IdentifyMIDIType(id, sizeof(id));
|
EMIDIType miditype = IdentifyMIDIType(id, sizeof(id));
|
||||||
if (miditype != MIDI_NOTMIDI)
|
if (miditype != MIDI_NOTMIDI)
|
||||||
{
|
{
|
||||||
EMidiDevice devtype = (EMidiDevice)device;
|
EMidiDevice devtype = device == NULL? MDEV_DEFAULT : (EMidiDevice)device->device;
|
||||||
|
#ifndef _WIN32
|
||||||
|
// non-Windows platforms don't support MDEV_MMAPI so map to MDEV_SNDSYS
|
||||||
|
if (devtype == MDEV_MMAPI)
|
||||||
|
devtype = MDEV_SNDSYS;
|
||||||
|
#endif
|
||||||
|
|
||||||
retry_as_sndsys:
|
retry_as_sndsys:
|
||||||
info = CreateMIDIStreamer(*reader, devtype, miditype);
|
info = CreateMIDIStreamer(*reader, devtype, miditype, device != NULL? device->args.GetChars() : "");
|
||||||
if (info != NULL && !info->IsValid())
|
if (info != NULL && !info->IsValid())
|
||||||
{
|
{
|
||||||
delete info;
|
delete info;
|
||||||
|
@ -454,7 +463,7 @@ retry_as_sndsys:
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (info == NULL && devtype != MDEV_MMAPI && snd_mididevice >= 0)
|
if (info == NULL && devtype != MDEV_MMAPI && snd_mididevice >= 0)
|
||||||
{
|
{
|
||||||
info = CreateMIDIStreamer(*reader, MDEV_MMAPI, miditype);
|
info = CreateMIDIStreamer(*reader, MDEV_MMAPI, miditype, "");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -465,7 +474,7 @@ retry_as_sndsys:
|
||||||
(id[0] == MAKE_ID('D','B','R','A') && id[1] == MAKE_ID('W','O','P','L')) || // DosBox Raw OPL
|
(id[0] == MAKE_ID('D','B','R','A') && id[1] == MAKE_ID('W','O','P','L')) || // DosBox Raw OPL
|
||||||
(id[0] == MAKE_ID('A','D','L','I') && *((BYTE *)id + 4) == 'B')) // Martin Fernandez's modified IMF
|
(id[0] == MAKE_ID('A','D','L','I') && *((BYTE *)id + 4) == 'B')) // Martin Fernandez's modified IMF
|
||||||
{
|
{
|
||||||
info = new OPLMUSSong (*reader);
|
info = new OPLMUSSong (*reader, device != NULL? device->args.GetChars() : "");
|
||||||
}
|
}
|
||||||
// Check for game music
|
// Check for game music
|
||||||
else if ((fmt = GME_CheckFormat(id[0])) != NULL && fmt[0] != '\0')
|
else if ((fmt = GME_CheckFormat(id[0])) != NULL && fmt[0] != '\0')
|
||||||
|
|
|
@ -43,7 +43,8 @@ struct FOptionValues;
|
||||||
// MUSIC I/O
|
// MUSIC I/O
|
||||||
//
|
//
|
||||||
void I_InitMusic ();
|
void I_InitMusic ();
|
||||||
void I_ShutdownMusic ();
|
void I_ShutdownMusic (bool onexit = false);
|
||||||
|
void I_ShutdownMusicExit ();
|
||||||
void I_BuildMIDIMenuList (FOptionValues *);
|
void I_BuildMIDIMenuList (FOptionValues *);
|
||||||
void I_UpdateMusic ();
|
void I_UpdateMusic ();
|
||||||
|
|
||||||
|
@ -52,7 +53,8 @@ void I_SetMusicVolume (float volume);
|
||||||
|
|
||||||
// Registers a song handle to song data.
|
// Registers a song handle to song data.
|
||||||
class MusInfo;
|
class MusInfo;
|
||||||
MusInfo *I_RegisterSong (FileReader *reader, int device);
|
struct MidiDeviceSetting;
|
||||||
|
MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device);
|
||||||
MusInfo *I_RegisterCDSong (int track, int cdid = 0);
|
MusInfo *I_RegisterCDSong (int track, int cdid = 0);
|
||||||
MusInfo *I_RegisterURLSong (const char *url);
|
MusInfo *I_RegisterURLSong (const char *url);
|
||||||
|
|
||||||
|
@ -81,6 +83,7 @@ public:
|
||||||
virtual void FluidSettingInt(const char *setting, int value); // FluidSynth settings
|
virtual void FluidSettingInt(const char *setting, int value); // FluidSynth settings
|
||||||
virtual void FluidSettingNum(const char *setting, double value); // "
|
virtual void FluidSettingNum(const char *setting, double value); // "
|
||||||
virtual void FluidSettingStr(const char *setting, const char *value); // "
|
virtual void FluidSettingStr(const char *setting, const char *value); // "
|
||||||
|
virtual void WildMidiSetOption(int opt, int set);
|
||||||
|
|
||||||
void Start(bool loop, float rel_vol = -1.f, int subsong = 0);
|
void Start(bool loop, float rel_vol = -1.f, int subsong = 0);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "i_music.h"
|
#include "i_music.h"
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "wildmidi/wildmidi_lib.h"
|
||||||
|
|
||||||
void I_InitMusicWin32 ();
|
void I_InitMusicWin32 ();
|
||||||
void I_ShutdownMusicWin32 ();
|
void I_ShutdownMusicWin32 ();
|
||||||
|
@ -101,6 +102,7 @@ public:
|
||||||
virtual void FluidSettingInt(const char *setting, int value);
|
virtual void FluidSettingInt(const char *setting, int value);
|
||||||
virtual void FluidSettingNum(const char *setting, double value);
|
virtual void FluidSettingNum(const char *setting, double value);
|
||||||
virtual void FluidSettingStr(const char *setting, const char *value);
|
virtual void FluidSettingStr(const char *setting, const char *value);
|
||||||
|
virtual void WildMidiSetOption(int opt, int set);
|
||||||
virtual bool Preprocess(MIDIStreamer *song, bool looping);
|
virtual bool Preprocess(MIDIStreamer *song, bool looping);
|
||||||
virtual FString GetStats();
|
virtual FString GetStats();
|
||||||
};
|
};
|
||||||
|
@ -183,7 +185,7 @@ public:
|
||||||
class TimidityPPMIDIDevice : public PseudoMIDIDevice
|
class TimidityPPMIDIDevice : public PseudoMIDIDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TimidityPPMIDIDevice();
|
TimidityPPMIDIDevice(const char *args);
|
||||||
~TimidityPPMIDIDevice();
|
~TimidityPPMIDIDevice();
|
||||||
|
|
||||||
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
||||||
|
@ -218,7 +220,6 @@ protected:
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Base class for software synthesizer MIDI output devices ------------------
|
// Base class for software synthesizer MIDI output devices ------------------
|
||||||
|
|
||||||
class SoftSynthMIDIDevice : public MIDIDevice
|
class SoftSynthMIDIDevice : public MIDIDevice
|
||||||
|
@ -269,7 +270,7 @@ protected:
|
||||||
class OPLMIDIDevice : public SoftSynthMIDIDevice, protected OPLmusicBlock
|
class OPLMIDIDevice : public SoftSynthMIDIDevice, protected OPLmusicBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OPLMIDIDevice();
|
OPLMIDIDevice(const char *args);
|
||||||
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
||||||
void Close();
|
void Close();
|
||||||
int GetTechnology() const;
|
int GetTechnology() const;
|
||||||
|
@ -302,7 +303,7 @@ namespace Timidity { struct Renderer; }
|
||||||
class TimidityMIDIDevice : public SoftSynthMIDIDevice
|
class TimidityMIDIDevice : public SoftSynthMIDIDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TimidityMIDIDevice();
|
TimidityMIDIDevice(const char *args);
|
||||||
~TimidityMIDIDevice();
|
~TimidityMIDIDevice();
|
||||||
|
|
||||||
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
||||||
|
@ -331,6 +332,27 @@ protected:
|
||||||
FILE *File;
|
FILE *File;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// WildMidi implementation of a MIDI device ---------------------------------
|
||||||
|
|
||||||
|
class WildMIDIDevice : public SoftSynthMIDIDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WildMIDIDevice(const char *args);
|
||||||
|
~WildMIDIDevice();
|
||||||
|
|
||||||
|
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
||||||
|
void PrecacheInstruments(const WORD *instruments, int count);
|
||||||
|
FString GetStats();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
WildMidi_Renderer *Renderer;
|
||||||
|
|
||||||
|
void HandleEvent(int status, int parm1, int parm2);
|
||||||
|
void HandleLongEvent(const BYTE *data, int len);
|
||||||
|
void ComputeOutput(float *buffer, int len);
|
||||||
|
void WildMidiSetOption(int opt, int set);
|
||||||
|
};
|
||||||
|
|
||||||
// FluidSynth implementation of a MIDI device -------------------------------
|
// FluidSynth implementation of a MIDI device -------------------------------
|
||||||
|
|
||||||
#ifdef HAVE_FLUIDSYNTH
|
#ifdef HAVE_FLUIDSYNTH
|
||||||
|
@ -344,7 +366,7 @@ struct fluid_synth_t;
|
||||||
class FluidSynthMIDIDevice : public SoftSynthMIDIDevice
|
class FluidSynthMIDIDevice : public SoftSynthMIDIDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FluidSynthMIDIDevice();
|
FluidSynthMIDIDevice(const char *args);
|
||||||
~FluidSynthMIDIDevice();
|
~FluidSynthMIDIDevice();
|
||||||
|
|
||||||
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
int Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata);
|
||||||
|
@ -409,7 +431,7 @@ protected:
|
||||||
class MIDIStreamer : public MusInfo
|
class MIDIStreamer : public MusInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MIDIStreamer(EMidiDevice type);
|
MIDIStreamer(EMidiDevice type, const char *args);
|
||||||
~MIDIStreamer();
|
~MIDIStreamer();
|
||||||
|
|
||||||
void MusicVolumeChanged();
|
void MusicVolumeChanged();
|
||||||
|
@ -427,6 +449,7 @@ public:
|
||||||
void FluidSettingInt(const char *setting, int value);
|
void FluidSettingInt(const char *setting, int value);
|
||||||
void FluidSettingNum(const char *setting, double value);
|
void FluidSettingNum(const char *setting, double value);
|
||||||
void FluidSettingStr(const char *setting, const char *value);
|
void FluidSettingStr(const char *setting, const char *value);
|
||||||
|
void WildMidiSetOption(int opt, int set);
|
||||||
void CreateSMF(TArray<BYTE> &file, int looplimit=0);
|
void CreateSMF(TArray<BYTE> &file, int looplimit=0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -494,6 +517,7 @@ protected:
|
||||||
bool CallbackIsThreaded;
|
bool CallbackIsThreaded;
|
||||||
int LoopLimit;
|
int LoopLimit;
|
||||||
FString DumpFilename;
|
FString DumpFilename;
|
||||||
|
FString Args;
|
||||||
};
|
};
|
||||||
|
|
||||||
// MUS file played with a MIDI stream ---------------------------------------
|
// MUS file played with a MIDI stream ---------------------------------------
|
||||||
|
@ -501,7 +525,7 @@ protected:
|
||||||
class MUSSong2 : public MIDIStreamer
|
class MUSSong2 : public MIDIStreamer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MUSSong2(FileReader &reader, EMidiDevice type);
|
MUSSong2(FileReader &reader, EMidiDevice type, const char *args);
|
||||||
~MUSSong2();
|
~MUSSong2();
|
||||||
|
|
||||||
MusInfo *GetOPLDumper(const char *filename);
|
MusInfo *GetOPLDumper(const char *filename);
|
||||||
|
@ -527,7 +551,7 @@ protected:
|
||||||
class MIDISong2 : public MIDIStreamer
|
class MIDISong2 : public MIDIStreamer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MIDISong2(FileReader &reader, EMidiDevice type);
|
MIDISong2(FileReader &reader, EMidiDevice type, const char *args);
|
||||||
~MIDISong2();
|
~MIDISong2();
|
||||||
|
|
||||||
MusInfo *GetOPLDumper(const char *filename);
|
MusInfo *GetOPLDumper(const char *filename);
|
||||||
|
@ -546,7 +570,7 @@ protected:
|
||||||
struct TrackInfo;
|
struct TrackInfo;
|
||||||
|
|
||||||
void ProcessInitialMetaEvents ();
|
void ProcessInitialMetaEvents ();
|
||||||
DWORD *SendCommand (DWORD *event, TrackInfo *track, DWORD delay);
|
DWORD *SendCommand (DWORD *event, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom);
|
||||||
TrackInfo *FindNextDue ();
|
TrackInfo *FindNextDue ();
|
||||||
|
|
||||||
BYTE *MusHeader;
|
BYTE *MusHeader;
|
||||||
|
@ -584,7 +608,7 @@ protected:
|
||||||
class HMISong : public MIDIStreamer
|
class HMISong : public MIDIStreamer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HMISong(FileReader &reader, EMidiDevice type);
|
HMISong(FileReader &reader, EMidiDevice type, const char *args);
|
||||||
~HMISong();
|
~HMISong();
|
||||||
|
|
||||||
MusInfo *GetOPLDumper(const char *filename);
|
MusInfo *GetOPLDumper(const char *filename);
|
||||||
|
@ -627,7 +651,7 @@ protected:
|
||||||
class XMISong : public MIDIStreamer
|
class XMISong : public MIDIStreamer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
XMISong(FileReader &reader, EMidiDevice type);
|
XMISong(FileReader &reader, EMidiDevice type, const char *args);
|
||||||
~XMISong();
|
~XMISong();
|
||||||
|
|
||||||
MusInfo *GetOPLDumper(const char *filename);
|
MusInfo *GetOPLDumper(const char *filename);
|
||||||
|
@ -690,7 +714,7 @@ protected:
|
||||||
class OPLMUSSong : public StreamSong
|
class OPLMUSSong : public StreamSong
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OPLMUSSong (FileReader &reader);
|
OPLMUSSong (FileReader &reader, const char *args);
|
||||||
~OPLMUSSong ();
|
~OPLMUSSong ();
|
||||||
void Play (bool looping, int subsong);
|
void Play (bool looping, int subsong);
|
||||||
bool IsPlaying ();
|
bool IsPlaying ();
|
||||||
|
|
|
@ -255,7 +255,7 @@ CUSTOM_CVAR(Int, fluid_chorus_type, FLUID_CHORUS_DEFAULT_TYPE, CVAR_ARCHIVE|CVAR
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FluidSynthMIDIDevice::FluidSynthMIDIDevice()
|
FluidSynthMIDIDevice::FluidSynthMIDIDevice(const char *args)
|
||||||
{
|
{
|
||||||
FluidSynth = NULL;
|
FluidSynth = NULL;
|
||||||
FluidSettings = NULL;
|
FluidSettings = NULL;
|
||||||
|
@ -293,7 +293,15 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice()
|
||||||
fluid_reverb_width, fluid_reverb_level);
|
fluid_reverb_width, fluid_reverb_level);
|
||||||
fluid_synth_set_chorus(FluidSynth, fluid_chorus_voices, fluid_chorus_level,
|
fluid_synth_set_chorus(FluidSynth, fluid_chorus_voices, fluid_chorus_level,
|
||||||
fluid_chorus_speed, fluid_chorus_depth, fluid_chorus_type);
|
fluid_chorus_speed, fluid_chorus_depth, fluid_chorus_type);
|
||||||
if (0 == LoadPatchSets(fluid_patchset))
|
|
||||||
|
// try loading a patch set that got specified with $mididevice.
|
||||||
|
int res = 0;
|
||||||
|
if (args != NULL && *args != 0)
|
||||||
|
{
|
||||||
|
res = LoadPatchSets(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == 0 && 0 == LoadPatchSets(fluid_patchset))
|
||||||
{
|
{
|
||||||
#ifdef __unix__
|
#ifdef __unix__
|
||||||
// This is the standard location on Ubuntu.
|
// This is the standard location on Ubuntu.
|
||||||
|
|
|
@ -128,8 +128,8 @@ extern char MIDI_CommonLengths[15];
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
HMISong::HMISong (FileReader &reader, EMidiDevice type)
|
HMISong::HMISong (FileReader &reader, EMidiDevice type, const char *args)
|
||||||
: MIDIStreamer(type), MusHeader(0), Tracks(0)
|
: MIDIStreamer(type, args), MusHeader(0), Tracks(0)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (ExitEvent == NULL)
|
if (ExitEvent == NULL)
|
||||||
|
|
|
@ -11,9 +11,9 @@ static DWORD nummididevices;
|
||||||
static bool nummididevicesset;
|
static bool nummididevicesset;
|
||||||
|
|
||||||
#ifdef HAVE_FLUIDSYNTH
|
#ifdef HAVE_FLUIDSYNTH
|
||||||
#define NUM_DEF_DEVICES 5
|
#define NUM_DEF_DEVICES 6
|
||||||
#else
|
#else
|
||||||
#define NUM_DEF_DEVICES 4
|
#define NUM_DEF_DEVICES 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void AddDefaultMidiDevices(FOptionValues *opt)
|
static void AddDefaultMidiDevices(FOptionValues *opt)
|
||||||
|
@ -33,8 +33,10 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
|
||||||
pair[p+1].Value = -3.0;
|
pair[p+1].Value = -3.0;
|
||||||
pair[p+2].Text = "TiMidity++";
|
pair[p+2].Text = "TiMidity++";
|
||||||
pair[p+2].Value = -2.0;
|
pair[p+2].Value = -2.0;
|
||||||
pair[p+3].Text = "Sound System";
|
pair[p+3].Text = "WildMidi";
|
||||||
pair[p+3].Value = -1.0;
|
pair[p+3].Value = -6.0;
|
||||||
|
pair[p+4].Text = "Sound System";
|
||||||
|
pair[p+4].Value = -1.0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +72,7 @@ CUSTOM_CVAR (Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
if (!nummididevicesset)
|
if (!nummididevicesset)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((self >= (signed)nummididevices) || (self < -5))
|
if ((self >= (signed)nummididevices) || (self < -6))
|
||||||
{
|
{
|
||||||
Printf ("ID out of range. Using default device.\n");
|
Printf ("ID out of range. Using default device.\n");
|
||||||
self = 0;
|
self = 0;
|
||||||
|
@ -166,6 +168,7 @@ CCMD (snd_listmididevices)
|
||||||
MIDIOUTCAPS caps;
|
MIDIOUTCAPS caps;
|
||||||
MMRESULT res;
|
MMRESULT res;
|
||||||
|
|
||||||
|
PrintMidiDevice (-6, "WildMidi", MOD_SWSYNTH, 0);
|
||||||
#ifdef HAVE_FLUIDSYNTH
|
#ifdef HAVE_FLUIDSYNTH
|
||||||
PrintMidiDevice (-5, "FluidSynth", MOD_SWSYNTH, 0);
|
PrintMidiDevice (-5, "FluidSynth", MOD_SWSYNTH, 0);
|
||||||
#endif
|
#endif
|
||||||
|
@ -196,8 +199,8 @@ CCMD (snd_listmididevices)
|
||||||
|
|
||||||
CUSTOM_CVAR(Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CUSTOM_CVAR(Int, snd_mididevice, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
{
|
{
|
||||||
if (self < -5)
|
if (self < -6)
|
||||||
self = -5;
|
self = -6;
|
||||||
else if (self > -1)
|
else if (self > -1)
|
||||||
self = -1;
|
self = -1;
|
||||||
else
|
else
|
||||||
|
@ -211,6 +214,7 @@ void I_BuildMIDIMenuList (FOptionValues *opt)
|
||||||
|
|
||||||
CCMD (snd_listmididevices)
|
CCMD (snd_listmididevices)
|
||||||
{
|
{
|
||||||
|
Printf("%s-6. WildMidi\n", -6 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||||
#ifdef HAVE_FLUIDSYNTH
|
#ifdef HAVE_FLUIDSYNTH
|
||||||
Printf("%s-5. FluidSynth\n", -5 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
Printf("%s-5. FluidSynth\n", -5 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -72,7 +72,7 @@ CUSTOM_CVAR (Int, timidity_frequency, 22050, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
TimidityPPMIDIDevice::TimidityPPMIDIDevice()
|
TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args)
|
||||||
: DiskName("zmid"),
|
: DiskName("zmid"),
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ReadWavePipe(INVALID_HANDLE_VALUE), WriteWavePipe(INVALID_HANDLE_VALUE),
|
ReadWavePipe(INVALID_HANDLE_VALUE), WriteWavePipe(INVALID_HANDLE_VALUE),
|
||||||
|
@ -85,7 +85,13 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice()
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
WavePipe[0] = WavePipe[1] = -1;
|
WavePipe[0] = WavePipe[1] = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (args == NULL || *args == 0) args = timidity_exe;
|
||||||
|
|
||||||
|
CommandLine.Format("%s %s -EFchorus=%s -EFreverb=%s -s%d ",
|
||||||
|
args, *timidity_extargs,
|
||||||
|
*timidity_chorus, *timidity_reverb, *timidity_frequency);
|
||||||
|
|
||||||
if (DiskName == NULL)
|
if (DiskName == NULL)
|
||||||
{
|
{
|
||||||
Printf(PRINT_BOLD, "Could not create temp music file\n");
|
Printf(PRINT_BOLD, "Could not create temp music file\n");
|
||||||
|
@ -187,10 +193,6 @@ int TimidityPPMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWO
|
||||||
Validated = true;
|
Validated = true;
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
CommandLine.Format("%s %s -EFchorus=%s -EFreverb=%s -s%d ",
|
|
||||||
*timidity_exe, *timidity_extargs,
|
|
||||||
*timidity_chorus, *timidity_reverb, *timidity_frequency);
|
|
||||||
|
|
||||||
pipeSize = (timidity_pipe * timidity_frequency / 1000)
|
pipeSize = (timidity_pipe * timidity_frequency / 1000)
|
||||||
<< (timidity_stereo + !timidity_8bit);
|
<< (timidity_stereo + !timidity_8bit);
|
||||||
|
|
||||||
|
|
|
@ -89,12 +89,12 @@ static const BYTE StaticMIDIhead[] =
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
MIDIStreamer::MIDIStreamer(EMidiDevice type)
|
MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args)
|
||||||
:
|
:
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
|
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
|
||||||
#endif
|
#endif
|
||||||
MIDI(0), Division(0), InitialTempo(500000), DeviceType(type)
|
MIDI(0), Division(0), InitialTempo(500000), DeviceType(type), Args(args)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
BufferDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
BufferDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
@ -240,6 +240,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
|
||||||
#ifdef HAVE_FLUIDSYNTH
|
#ifdef HAVE_FLUIDSYNTH
|
||||||
case -5: return MDEV_FLUIDSYNTH;
|
case -5: return MDEV_FLUIDSYNTH;
|
||||||
#endif
|
#endif
|
||||||
|
case -6: return MDEV_WILDMIDI;
|
||||||
default:
|
default:
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return MDEV_MMAPI;
|
return MDEV_MMAPI;
|
||||||
|
@ -268,19 +269,19 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
|
||||||
|
|
||||||
#ifdef HAVE_FLUIDSYNTH
|
#ifdef HAVE_FLUIDSYNTH
|
||||||
case MDEV_FLUIDSYNTH:
|
case MDEV_FLUIDSYNTH:
|
||||||
return new FluidSynthMIDIDevice;
|
return new FluidSynthMIDIDevice(Args);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case MDEV_SNDSYS:
|
case MDEV_SNDSYS:
|
||||||
return new SndSysMIDIDevice;
|
return new SndSysMIDIDevice;
|
||||||
|
|
||||||
case MDEV_GUS:
|
case MDEV_GUS:
|
||||||
return new TimidityMIDIDevice;
|
return new TimidityMIDIDevice(Args);
|
||||||
|
|
||||||
case MDEV_OPL:
|
case MDEV_OPL:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new OPLMIDIDevice;
|
return new OPLMIDIDevice(Args);
|
||||||
}
|
}
|
||||||
catch (CRecoverableError &err)
|
catch (CRecoverableError &err)
|
||||||
{
|
{
|
||||||
|
@ -290,7 +291,10 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
|
||||||
}
|
}
|
||||||
|
|
||||||
case MDEV_TIMIDITY:
|
case MDEV_TIMIDITY:
|
||||||
return new TimidityPPMIDIDevice;
|
return new TimidityPPMIDIDevice(Args);
|
||||||
|
|
||||||
|
case MDEV_WILDMIDI:
|
||||||
|
return new WildMIDIDevice(Args);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -622,6 +626,21 @@ void MIDIStreamer::FluidSettingStr(const char *setting, const char *value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MIDIDeviceStreamer :: WildMidiSetOption
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void MIDIStreamer::WildMidiSetOption(int opt, int set)
|
||||||
|
{
|
||||||
|
if (MIDI != NULL)
|
||||||
|
{
|
||||||
|
MIDI->WildMidiSetOption(opt, set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// MIDIStreamer :: OutputVolume
|
// MIDIStreamer :: OutputVolume
|
||||||
|
@ -1192,9 +1211,15 @@ void MIDIStreamer::CreateSMF(TArray<BYTE> &file, int looplimit)
|
||||||
len--;
|
len--;
|
||||||
file.Push(MIDI_SYSEX);
|
file.Push(MIDI_SYSEX);
|
||||||
WriteVarLen(file, len);
|
WriteVarLen(file, len);
|
||||||
memcpy(&file[file.Reserve(len - 1)], bytes, len);
|
memcpy(&file[file.Reserve(len)], bytes + 1, len);
|
||||||
running_status = 255;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file.Push(MIDI_SYSEXEND);
|
||||||
|
WriteVarLen(file, len);
|
||||||
|
memcpy(&file[file.Reserve(len)], bytes, len);
|
||||||
|
}
|
||||||
|
running_status = 255;
|
||||||
}
|
}
|
||||||
else if (MEVT_EVENTTYPE(event[2]) == 0)
|
else if (MEVT_EVENTTYPE(event[2]) == 0)
|
||||||
{
|
{
|
||||||
|
@ -1512,6 +1537,16 @@ void MIDIDevice::FluidSettingStr(const char *setting, const char *value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MIDIDevice :: WildMidiSetOption
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void MIDIDevice::WildMidiSetOption(int opt, int set)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// MIDIDevice :: GetStats
|
// MIDIDevice :: GetStats
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "m_swap.h"
|
#include "m_swap.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "s_sound.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -92,8 +93,8 @@ static const BYTE CtrlTranslate[15] =
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
MUSSong2::MUSSong2 (FileReader &reader, EMidiDevice type)
|
MUSSong2::MUSSong2 (FileReader &reader, EMidiDevice type, const char *args)
|
||||||
: MIDIStreamer(type), MusHeader(0), MusBuffer(0)
|
: MIDIStreamer(type, args), MusHeader(0), MusBuffer(0)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (ExitEvent == NULL)
|
if (ExitEvent == NULL)
|
||||||
|
@ -210,23 +211,44 @@ bool MUSSong2::CheckDone()
|
||||||
|
|
||||||
void MUSSong2::Precache()
|
void MUSSong2::Precache()
|
||||||
{
|
{
|
||||||
WORD *work = (WORD *)alloca(MusHeader->NumInstruments * sizeof(WORD));
|
TArray<WORD> work(MusHeader->NumInstruments);
|
||||||
const WORD *used = (WORD *)MusHeader + sizeof(MUSHeader) / sizeof(WORD);
|
const BYTE *used = (BYTE *)MusHeader + sizeof(MUSHeader) / sizeof(BYTE);
|
||||||
int i, j;
|
int i, k;
|
||||||
|
|
||||||
for (i = j = 0; i < MusHeader->NumInstruments; ++i)
|
for (i = k = 0; i < MusHeader->NumInstruments; ++i)
|
||||||
{
|
{
|
||||||
WORD instr = LittleShort(used[i]);
|
BYTE instr = used[k++];
|
||||||
|
WORD val;
|
||||||
if (instr < 128)
|
if (instr < 128)
|
||||||
{
|
{
|
||||||
work[j++] = instr;
|
val = instr;
|
||||||
}
|
}
|
||||||
else if (used[i] >= 135 && used[i] <= 181)
|
else if (instr >= 135 && instr <= 188)
|
||||||
{ // Percussions are 100-based, not 128-based, eh?
|
{ // Percussions are 100-based, not 128-based, eh?
|
||||||
work[j++] = instr - 100 + (1 << 14);
|
val = instr - 100 + (1 << 14);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// skip it.
|
||||||
|
val = used[k++];
|
||||||
|
k += val;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numbanks = used[k++];
|
||||||
|
if (numbanks > 0)
|
||||||
|
{
|
||||||
|
for (int b = 0; b < numbanks; b++)
|
||||||
|
{
|
||||||
|
work.Push(val | (used[k++] << 7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
work.Push(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MIDI->PrecacheInstruments(&work[0], j);
|
MIDI->PrecacheInstruments(&work[0], work.Size());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -20,16 +20,25 @@ CUSTOM_CVAR (Int, opl_numchips, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CVAR(Int, opl_core, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR(Int, opl_core, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
int current_opl_core;
|
||||||
|
|
||||||
OPLMUSSong::OPLMUSSong (FileReader &reader)
|
// Get OPL core override from $mididevice
|
||||||
|
void OPL_SetCore(const char *args)
|
||||||
|
{
|
||||||
|
current_opl_core = opl_core;
|
||||||
|
if (args != NULL && *args >= '0' && *args < '4') current_opl_core = *args - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
OPLMUSSong::OPLMUSSong (FileReader &reader, const char *args)
|
||||||
{
|
{
|
||||||
int samples = int(OPL_SAMPLE_RATE / 14);
|
int samples = int(OPL_SAMPLE_RATE / 14);
|
||||||
|
|
||||||
|
OPL_SetCore(args);
|
||||||
Music = new OPLmusicFile (&reader);
|
Music = new OPLmusicFile (&reader);
|
||||||
|
|
||||||
m_Stream = GSnd->CreateStream (FillStream, samples*4,
|
m_Stream = GSnd->CreateStream (FillStream, samples*4,
|
||||||
(opl_core == 0 ? SoundStream::Mono : 0) | SoundStream::Float, int(OPL_SAMPLE_RATE), this);
|
(current_opl_core == 0 ? SoundStream::Mono : 0) | SoundStream::Float, int(OPL_SAMPLE_RATE), this);
|
||||||
if (m_Stream == NULL)
|
if (m_Stream == NULL)
|
||||||
{
|
{
|
||||||
Printf (PRINT_BOLD, "Could not create music stream.\n");
|
Printf (PRINT_BOLD, "Could not create music stream.\n");
|
||||||
|
|
|
@ -102,8 +102,8 @@ char MIDI_CommonLengths[15] = { 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
MIDISong2::MIDISong2 (FileReader &reader, EMidiDevice type)
|
MIDISong2::MIDISong2 (FileReader &reader, EMidiDevice type, const char *args)
|
||||||
: MIDIStreamer(type), MusHeader(0), Tracks(0)
|
: MIDIStreamer(type, args), MusHeader(0), Tracks(0)
|
||||||
{
|
{
|
||||||
int p;
|
int p;
|
||||||
int i;
|
int i;
|
||||||
|
@ -322,7 +322,12 @@ DWORD *MIDISong2::MakeEvents(DWORD *events, DWORD *max_event_p, DWORD max_time)
|
||||||
// Play all events for this tick.
|
// Play all events for this tick.
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
DWORD *new_events = SendCommand(events, TrackDue, time);
|
bool sysex_noroom = false;
|
||||||
|
DWORD *new_events = SendCommand(events, TrackDue, time, max_event_p - events, sysex_noroom);
|
||||||
|
if (sysex_noroom)
|
||||||
|
{
|
||||||
|
return events;
|
||||||
|
}
|
||||||
TrackDue = FindNextDue();
|
TrackDue = FindNextDue();
|
||||||
if (new_events != events)
|
if (new_events != events)
|
||||||
{
|
{
|
||||||
|
@ -366,12 +371,15 @@ void MIDISong2::AdvanceTracks(DWORD time)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay, ptrdiff_t room, bool &sysex_noroom)
|
||||||
{
|
{
|
||||||
DWORD len;
|
DWORD len;
|
||||||
BYTE event, data1 = 0, data2 = 0;
|
BYTE event, data1 = 0, data2 = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
sysex_noroom = false;
|
||||||
|
size_t start_p = track->TrackP;
|
||||||
|
|
||||||
CHECK_FINISHED
|
CHECK_FINISHED
|
||||||
event = track->TrackBegin[track->TrackP++];
|
event = track->TrackBegin[track->TrackP++];
|
||||||
CHECK_FINISHED
|
CHECK_FINISHED
|
||||||
|
@ -588,13 +596,44 @@ DWORD *MIDISong2::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Skip SysEx events just because I don't want to bother with them.
|
// SysEx events could potentially not have enough room in the buffer...
|
||||||
// The old MIDI player ignored them too, so this won't break
|
|
||||||
// anything that played before.
|
|
||||||
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
|
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
|
||||||
{
|
{
|
||||||
len = track->ReadVarLen ();
|
len = track->ReadVarLen();
|
||||||
track->TrackP += len;
|
if (len >= (MAX_EVENTS-1)*3*4)
|
||||||
|
{ // This message will never fit. Throw it away.
|
||||||
|
track->TrackP += len;
|
||||||
|
}
|
||||||
|
else if (len + 12 >= (size_t)room * 4)
|
||||||
|
{ // Not enough room left in this buffer. Backup and wait for the next one.
|
||||||
|
track->TrackP = start_p;
|
||||||
|
sysex_noroom = true;
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events[0] = delay;
|
||||||
|
events[1] = 0;
|
||||||
|
BYTE *msg = (BYTE *)&events[3];
|
||||||
|
if (event == MIDI_SYSEX)
|
||||||
|
{ // Need to add the SysEx marker to the message.
|
||||||
|
events[2] = (MEVT_LONGMSG << 24) | (len + 1);
|
||||||
|
*msg++ = MIDI_SYSEX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
events[2] = (MEVT_LONGMSG << 24) | len;
|
||||||
|
}
|
||||||
|
memcpy(msg, &track->TrackBegin[track->TrackP], len);
|
||||||
|
msg += len;
|
||||||
|
// Must pad with 0
|
||||||
|
while ((size_t)msg & 3)
|
||||||
|
{
|
||||||
|
*msg++ = 0;
|
||||||
|
}
|
||||||
|
events = (DWORD *)msg;
|
||||||
|
track->TrackP += len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (event == MIDI_META)
|
else if (event == MIDI_META)
|
||||||
{
|
{
|
||||||
|
|
|
@ -86,10 +86,10 @@ struct FmtChunk
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
TimidityMIDIDevice::TimidityMIDIDevice()
|
TimidityMIDIDevice::TimidityMIDIDevice(const char *args)
|
||||||
{
|
{
|
||||||
Renderer = NULL;
|
Renderer = NULL;
|
||||||
Renderer = new Timidity::Renderer((float)SampleRate);
|
Renderer = new Timidity::Renderer((float)SampleRate, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -245,6 +245,7 @@ FString TimidityMIDIDevice::GetStats()
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
TimidityWaveWriterMIDIDevice::TimidityWaveWriterMIDIDevice(const char *filename, int rate)
|
TimidityWaveWriterMIDIDevice::TimidityWaveWriterMIDIDevice(const char *filename, int rate)
|
||||||
|
:TimidityMIDIDevice(NULL)
|
||||||
{
|
{
|
||||||
File = fopen(filename, "wb");
|
File = fopen(filename, "wb");
|
||||||
if (File != NULL)
|
if (File != NULL)
|
||||||
|
|
234
src/sound/music_wildmidi_mididevice.cpp
Normal file
234
src/sound/music_wildmidi_mididevice.cpp
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
/*
|
||||||
|
** music_wildmidi_mididevice.cpp
|
||||||
|
** Provides access to WildMidi as a generic MIDI device.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2015 Randy Heit
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
// HEADER FILES ------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "i_musicinterns.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "doomdef.h"
|
||||||
|
#include "m_swap.h"
|
||||||
|
#include "w_wad.h"
|
||||||
|
#include "v_text.h"
|
||||||
|
|
||||||
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TYPES -------------------------------------------------------------------
|
||||||
|
|
||||||
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
|
||||||
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
|
static FString CurrentConfig;
|
||||||
|
|
||||||
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
CVAR(Int, wildmidi_frequency, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
CUSTOM_CVAR(Bool, wildmidi_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
|
{
|
||||||
|
if (currSong != NULL)
|
||||||
|
currSong->WildMidiSetOption(WM_MO_REVERB, *self? WM_MO_REVERB:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, wildmidi_enhanced_resampling, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
|
{
|
||||||
|
if (currSong != NULL)
|
||||||
|
currSong->WildMidiSetOption(WM_MO_ENHANCED_RESAMPLING, *self? WM_MO_ENHANCED_RESAMPLING:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMIDIDevice Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
WildMIDIDevice::WildMIDIDevice(const char *args)
|
||||||
|
{
|
||||||
|
Renderer = NULL;
|
||||||
|
|
||||||
|
if (wildmidi_frequency >= 11025 && wildmidi_frequency < 65536)
|
||||||
|
{ // Use our own sample rate instead of the global one
|
||||||
|
SampleRate = wildmidi_frequency;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Else make sure we're not outside of WildMidi's range
|
||||||
|
SampleRate = clamp(SampleRate, 11025, 65535);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args == NULL || *args == 0) args = wildmidi_config;
|
||||||
|
|
||||||
|
if (CurrentConfig.CompareNoCase(args) != 0 || SampleRate != WildMidi_GetSampleRate())
|
||||||
|
{
|
||||||
|
if (CurrentConfig.IsNotEmpty())
|
||||||
|
{
|
||||||
|
WildMidi_Shutdown();
|
||||||
|
CurrentConfig = "";
|
||||||
|
}
|
||||||
|
if (!WildMidi_Init(args, SampleRate, 0))
|
||||||
|
{
|
||||||
|
CurrentConfig = args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CurrentConfig.IsNotEmpty())
|
||||||
|
{
|
||||||
|
Renderer = new WildMidi_Renderer();
|
||||||
|
int flags = 0;
|
||||||
|
if (wildmidi_enhanced_resampling) flags |= WM_MO_ENHANCED_RESAMPLING;
|
||||||
|
if (wildmidi_reverb) flags |= WM_MO_REVERB;
|
||||||
|
Renderer->SetOption(WM_MO_ENHANCED_RESAMPLING | WM_MO_REVERB, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMIDIDevice Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
WildMIDIDevice::~WildMIDIDevice()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
if (Renderer != NULL)
|
||||||
|
{
|
||||||
|
delete Renderer;
|
||||||
|
}
|
||||||
|
// Do not shut down the device so that it can be reused for the next song being played.
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMIDIDevice :: Open
|
||||||
|
//
|
||||||
|
// Returns 0 on success.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int WildMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
|
||||||
|
{
|
||||||
|
if (Renderer == NULL)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int ret = OpenStream(2, 0, callback, userdata);
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
// Renderer->Reset();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMIDIDevice :: PrecacheInstruments
|
||||||
|
//
|
||||||
|
// Each entry is packed as follows:
|
||||||
|
// Bits 0- 6: Instrument number
|
||||||
|
// Bits 7-13: Bank number
|
||||||
|
// Bit 14: Select drum set if 1, tone bank if 0
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void WildMIDIDevice::PrecacheInstruments(const WORD *instruments, int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
Renderer->LoadInstrument((instruments[i] >> 7) & 127, instruments[i] >> 14, instruments[i] & 127);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMIDIDevice :: HandleEvent
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void WildMIDIDevice::HandleEvent(int status, int parm1, int parm2)
|
||||||
|
{
|
||||||
|
Renderer->ShortEvent(status, parm1, parm2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMIDIDevice :: HandleLongEvent
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void WildMIDIDevice::HandleLongEvent(const BYTE *data, int len)
|
||||||
|
{
|
||||||
|
Renderer->LongEvent(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMIDIDevice :: ComputeOutput
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void WildMIDIDevice::ComputeOutput(float *buffer, int len)
|
||||||
|
{
|
||||||
|
Renderer->ComputeOutput(buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMIDIDevice :: GetStats
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString WildMIDIDevice::GetStats()
|
||||||
|
{
|
||||||
|
FString out;
|
||||||
|
out.Format("%3d voices", Renderer->GetVoiceCount());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMIDIDevice :: GetStats
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void WildMIDIDevice::WildMidiSetOption(int opt, int set)
|
||||||
|
{
|
||||||
|
Renderer->SetOption(opt, set);
|
||||||
|
}
|
|
@ -108,8 +108,8 @@ extern char MIDI_CommonLengths[15];
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
XMISong::XMISong (FileReader &reader, EMidiDevice type)
|
XMISong::XMISong (FileReader &reader, EMidiDevice type, const char *args)
|
||||||
: MIDIStreamer(type), MusHeader(0), Songs(0)
|
: MIDIStreamer(type, args), MusHeader(0), Songs(0)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (ExitEvent == NULL)
|
if (ExitEvent == NULL)
|
||||||
|
|
|
@ -1246,7 +1246,8 @@ void FTextureManager::PrecacheLevel (void)
|
||||||
|
|
||||||
for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++)
|
for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++)
|
||||||
{
|
{
|
||||||
hitlist[level.info->PrecacheTextures[i].GetIndex()] |= FTextureManager::HIT_Wall;
|
FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_ReturnFirst);
|
||||||
|
if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = cnt - 1; i >= 0; i--)
|
for (int i = cnt - 1; i >= 0; i--)
|
||||||
|
|
|
@ -6263,6 +6263,104 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRipMax)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// A_CheckProximity(jump, classname, distance, count, flags, ptr)
|
||||||
|
//
|
||||||
|
// Checks to see if a certain actor class is close to the
|
||||||
|
// actor/pointer within distance, in numbers.
|
||||||
|
//==========================================================================
|
||||||
|
enum CPXFflags
|
||||||
|
{
|
||||||
|
CPXF_ANCESTOR = 1,
|
||||||
|
CPXF_LESSOREQUAL = 1 << 1,
|
||||||
|
CPXF_NOZ = 1 << 2,
|
||||||
|
CPXF_COUNTDEAD = 1 << 3,
|
||||||
|
CPXF_DEADONLY = 1 << 4,
|
||||||
|
CPXF_EXACT = 1 << 5,
|
||||||
|
};
|
||||||
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckProximity)
|
||||||
|
{
|
||||||
|
PARAM_ACTION_PROLOGUE;
|
||||||
|
PARAM_STATE(jump);
|
||||||
|
PARAM_CLASS(classname, AActor);
|
||||||
|
PARAM_FIXED(distance);
|
||||||
|
PARAM_INT_OPT(count) { count = 1; }
|
||||||
|
PARAM_INT(flags) { flags = 0; }
|
||||||
|
PARAM_INT(ptr) { ptr = AAPTR_DEFAULT; }
|
||||||
|
|
||||||
|
ACTION_SET_RESULT(false); //No inventory chain results please.
|
||||||
|
AActor *ref = COPY_AAPTR(self, ptr);
|
||||||
|
|
||||||
|
//We need these to check out.
|
||||||
|
if (!ref || !jump || !classname || distance <= 0)
|
||||||
|
return numret;
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
TThinkerIterator<AActor> it;
|
||||||
|
AActor * mo;
|
||||||
|
|
||||||
|
//[MC] Process of elimination, I think, will get through this as quickly and
|
||||||
|
//efficiently as possible.
|
||||||
|
while ((mo = it.Next()))
|
||||||
|
{
|
||||||
|
if (mo == ref) //Don't count self.
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//Check inheritance for the classname. Taken partly from CheckClass DECORATE function.
|
||||||
|
if (flags & CPXF_ANCESTOR)
|
||||||
|
{
|
||||||
|
if (!(mo->GetClass()->IsAncestorOf(classname)))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//Otherwise, just check for the regular class name.
|
||||||
|
else if (classname != mo->GetClass())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//Make sure it's in range and respect the desire for Z or not.
|
||||||
|
if (P_AproxDistance(ref->x - mo->x, ref->y - mo->y) < distance &&
|
||||||
|
((flags & CPXF_NOZ) ||
|
||||||
|
((ref->z > mo->z && ref->z - (mo->z + mo->height) < distance) ||
|
||||||
|
(ref->z <= mo->z && mo->z - (ref->z + ref->height) < distance))))
|
||||||
|
{
|
||||||
|
if (mo->flags6 & MF6_KILLED)
|
||||||
|
{
|
||||||
|
if (!(flags & (CPXF_COUNTDEAD | CPXF_DEADONLY)))
|
||||||
|
continue;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (flags & CPXF_DEADONLY)
|
||||||
|
continue;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Abort if the number of matching classes nearby is greater, we have obviously succeeded in our goal.
|
||||||
|
if (counter > count)
|
||||||
|
{
|
||||||
|
result = (flags & (CPXF_LESSOREQUAL | CPXF_EXACT)) ? false : true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (counter == count)
|
||||||
|
result = true;
|
||||||
|
else if (counter < count)
|
||||||
|
result = !!((flags & CPXF_LESSOREQUAL) && !(flags & CPXF_EXACT));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
ACTION_JUMP(jump);
|
||||||
|
}
|
||||||
|
return numret;
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
A_CheckBlock
|
A_CheckBlock
|
||||||
(state block, int flags, int ptr)
|
(state block, int flags, int ptr)
|
||||||
|
|
|
@ -35,82 +35,6 @@
|
||||||
namespace Timidity
|
namespace Timidity
|
||||||
{
|
{
|
||||||
|
|
||||||
static TArray<FString> PathList;
|
|
||||||
|
|
||||||
FString BuildPath(FString base, const char *name)
|
|
||||||
{
|
|
||||||
FString current;
|
|
||||||
if (base.IsNotEmpty())
|
|
||||||
{
|
|
||||||
current = base;
|
|
||||||
if (current[current.Len() - 1] != '/') current += '/';
|
|
||||||
}
|
|
||||||
current += name;
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is meant to find and open files for reading. */
|
|
||||||
FileReader *open_filereader(const char *name, int open, int *plumpnum)
|
|
||||||
{
|
|
||||||
FileReader *fp;
|
|
||||||
FString current_filename;
|
|
||||||
|
|
||||||
if (!name || !(*name))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First try the given name */
|
|
||||||
current_filename = name;
|
|
||||||
FixPathSeperator(current_filename);
|
|
||||||
|
|
||||||
int lumpnum = Wads.CheckNumForFullName(current_filename);
|
|
||||||
|
|
||||||
if (open != OM_FILE)
|
|
||||||
{
|
|
||||||
if (lumpnum >= 0)
|
|
||||||
{
|
|
||||||
fp = Wads.ReopenLumpNum(lumpnum);
|
|
||||||
if (plumpnum) *plumpnum = lumpnum;
|
|
||||||
return fp;
|
|
||||||
}
|
|
||||||
if (open == OM_LUMP) // search the path list when not loading the main config
|
|
||||||
{
|
|
||||||
for (unsigned int plp = PathList.Size(); plp-- != 0; )
|
|
||||||
{ /* Try along the path then */
|
|
||||||
current_filename = BuildPath(PathList[plp], name);
|
|
||||||
lumpnum = Wads.CheckNumForFullName(current_filename);
|
|
||||||
if (lumpnum >= 0)
|
|
||||||
{
|
|
||||||
fp = Wads.ReopenLumpNum(lumpnum);
|
|
||||||
if (plumpnum) *plumpnum = lumpnum;
|
|
||||||
return fp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (plumpnum) *plumpnum = -1;
|
|
||||||
|
|
||||||
|
|
||||||
fp = new FileReader;
|
|
||||||
if (fp->Open(current_filename)) return fp;
|
|
||||||
|
|
||||||
if (name[0] != '/')
|
|
||||||
{
|
|
||||||
for (unsigned int plp = PathList.Size(); plp-- != 0; )
|
|
||||||
{ /* Try along the path then */
|
|
||||||
current_filename = BuildPath(PathList[plp], name);
|
|
||||||
if (fp->Open(current_filename)) return fp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete fp;
|
|
||||||
|
|
||||||
/* Nothing could be opened. */
|
|
||||||
current_filename = "";
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This'll allocate memory or die. */
|
/* This'll allocate memory or die. */
|
||||||
|
@ -132,17 +56,5 @@ void *safe_malloc(size_t count)
|
||||||
return 0; // Unreachable.
|
return 0; // Unreachable.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This adds a directory to the path list */
|
|
||||||
void add_to_pathlist(const char *s)
|
|
||||||
{
|
|
||||||
FString copy = s;
|
|
||||||
FixPathSeperator(copy);
|
|
||||||
PathList.Push(copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_pathlist()
|
|
||||||
{
|
|
||||||
PathList.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,7 +142,7 @@ static void reverse_data(sample_t *sp, int ls, int le)
|
||||||
|
|
||||||
TODO: do reverse loops right */
|
TODO: do reverse loops right */
|
||||||
static Instrument *load_instrument(Renderer *song, const char *name, int percussion,
|
static Instrument *load_instrument(Renderer *song, const char *name, int percussion,
|
||||||
int panning, int amp, int note_to_use,
|
int panning, int note_to_use,
|
||||||
int strip_loop, int strip_envelope,
|
int strip_loop, int strip_envelope,
|
||||||
int strip_tail)
|
int strip_tail)
|
||||||
{
|
{
|
||||||
|
@ -159,16 +159,16 @@ static Instrument *load_instrument(Renderer *song, const char *name, int percuss
|
||||||
if (!name) return 0;
|
if (!name) return 0;
|
||||||
|
|
||||||
/* Open patch file */
|
/* Open patch file */
|
||||||
if ((fp = open_filereader(name, openmode, NULL)) == NULL)
|
if ((fp = pathExpander.openFileReader(name, NULL)) == NULL)
|
||||||
{
|
{
|
||||||
/* Try with various extensions */
|
/* Try with various extensions */
|
||||||
FString tmp = name;
|
FString tmp = name;
|
||||||
tmp += ".pat";
|
tmp += ".pat";
|
||||||
if ((fp = open_filereader(tmp, openmode, NULL)) == NULL)
|
if ((fp = pathExpander.openFileReader(tmp, NULL)) == NULL)
|
||||||
{
|
{
|
||||||
#ifdef __unix__ // Windows isn't case-sensitive.
|
#ifdef __unix__ // Windows isn't case-sensitive.
|
||||||
tmp.ToUpper();
|
tmp.ToUpper();
|
||||||
if ((fp = open_filereader(tmp, openmode, NULL)) == NULL)
|
if ((fp = pathExpander.openFileReader(tmp, NULL)) == NULL)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
noluck = true;
|
noluck = true;
|
||||||
|
@ -372,7 +372,6 @@ fail:
|
||||||
{
|
{
|
||||||
sp->modes &= ~(PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD);
|
sp->modes &= ~(PATCH_SUSTAIN | PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD);
|
||||||
}
|
}
|
||||||
sp->modes |= PATCH_T_NO_LOOP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strip_envelope == 1)
|
if (strip_envelope == 1)
|
||||||
|
@ -398,37 +397,6 @@ fail:
|
||||||
patch_data.EnvelopeOffset[k] = patch_data.EnvelopeOffset[0];
|
patch_data.EnvelopeOffset[k] = patch_data.EnvelopeOffset[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sp->modes |= PATCH_T_NO_ENVELOPE;
|
|
||||||
}
|
|
||||||
else if (strip_envelope != 0)
|
|
||||||
{
|
|
||||||
/* Have to make a guess. */
|
|
||||||
if (!(sp->modes & (PATCH_LOOPEN | PATCH_BIDIR | PATCH_BACKWARD)))
|
|
||||||
{
|
|
||||||
/* No loop? Then what's there to sustain? No envelope needed either... */
|
|
||||||
sp->modes |= PATCH_T_NO_ENVELOPE;
|
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " - No loop, removing sustain and envelope\n");
|
|
||||||
}
|
|
||||||
else if (memcmp(patch_data.EnvelopeRate, "??????", 6) == 0 || patch_data.EnvelopeOffset[GF1_RELEASEC] >= 100)
|
|
||||||
{
|
|
||||||
/* Envelope rates all maxed out? Envelope end at a high "offset"?
|
|
||||||
That's a weird envelope. Take it out. */
|
|
||||||
sp->modes |= PATCH_T_NO_ENVELOPE;
|
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " - Weirdness, removing envelope\n");
|
|
||||||
}
|
|
||||||
else if (!(sp->modes & PATCH_SUSTAIN))
|
|
||||||
{
|
|
||||||
/* No sustain? Then no envelope. I don't know if this is
|
|
||||||
justified, but patches without sustain usually don't need the
|
|
||||||
envelope either... at least the Gravis ones. They're mostly
|
|
||||||
drums. I think. */
|
|
||||||
sp->modes |= PATCH_T_NO_ENVELOPE;
|
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " - No sustain, removing envelope\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!(sp->modes & PATCH_NO_SRELEASE))
|
|
||||||
{ // TiMidity thinks that this is an envelope enable flag.
|
|
||||||
sp->modes |= PATCH_T_NO_ENVELOPE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 6; j++)
|
for (j = 0; j < 6; j++)
|
||||||
|
@ -470,29 +438,6 @@ fail:
|
||||||
sp->modes |= PATCH_LOOPEN; /* just in case */
|
sp->modes |= PATCH_LOOPEN; /* just in case */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amp != -1)
|
|
||||||
{
|
|
||||||
sp->volume = (amp) / 100.f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Try to determine a volume scaling factor for the sample.
|
|
||||||
This is a very crude adjustment, but things sound more
|
|
||||||
balanced with it. Still, this should be a runtime option.
|
|
||||||
(This is ignored unless midi_timiditylike is turned on.) */
|
|
||||||
int i;
|
|
||||||
sample_t maxamp = 0, a;
|
|
||||||
sample_t *tmp;
|
|
||||||
for (i = sp->data_length, tmp = sp->data; i; --i)
|
|
||||||
{
|
|
||||||
a = fabsf(*tmp++);
|
|
||||||
if (a > maxamp)
|
|
||||||
maxamp = a;
|
|
||||||
}
|
|
||||||
sp->volume = 1 / maxamp;
|
|
||||||
cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f\n", sp->volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then fractional samples */
|
/* Then fractional samples */
|
||||||
sp->data_length <<= FRACTION_BITS;
|
sp->data_length <<= FRACTION_BITS;
|
||||||
sp->loop_start <<= FRACTION_BITS;
|
sp->loop_start <<= FRACTION_BITS;
|
||||||
|
@ -653,7 +598,6 @@ static int fill_bank(Renderer *song, int dr, int b)
|
||||||
ip = load_instrument(song, bank->tone[i].name,
|
ip = load_instrument(song, bank->tone[i].name,
|
||||||
(dr) ? 1 : 0,
|
(dr) ? 1 : 0,
|
||||||
bank->tone[i].pan,
|
bank->tone[i].pan,
|
||||||
bank->tone[i].amp,
|
|
||||||
(bank->tone[i].note != -1) ? bank->tone[i].note : ((dr) ? i : -1),
|
(bank->tone[i].note != -1) ? bank->tone[i].note : ((dr) ? i : -1),
|
||||||
(bank->tone[i].strip_loop != -1) ? bank->tone[i].strip_loop : ((dr) ? 1 : -1),
|
(bank->tone[i].strip_loop != -1) ? bank->tone[i].strip_loop : ((dr) ? 1 : -1),
|
||||||
(bank->tone[i].strip_envelope != -1) ? bank->tone[i].strip_envelope : ((dr) ? 1 : -1),
|
(bank->tone[i].strip_envelope != -1) ? bank->tone[i].strip_envelope : ((dr) ? 1 : -1),
|
||||||
|
@ -731,7 +675,7 @@ void free_instruments()
|
||||||
int Renderer::set_default_instrument(const char *name)
|
int Renderer::set_default_instrument(const char *name)
|
||||||
{
|
{
|
||||||
Instrument *ip;
|
Instrument *ip;
|
||||||
if ((ip = load_instrument(this, name, 0, -1, -1, -1, 0, 0, 0)) == NULL)
|
if ((ip = load_instrument(this, name, 0, -1, -1, 0, 0, 0)) == NULL)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1141,7 +1141,6 @@ static void load_region_dls(Renderer *song, Sample *sample, DLS_Instrument *ins,
|
||||||
sample->loop_start = rgn->wsmp_loop->ulStart / 2;
|
sample->loop_start = rgn->wsmp_loop->ulStart / 2;
|
||||||
sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2);
|
sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2);
|
||||||
}
|
}
|
||||||
sample->volume = 1.0f;
|
|
||||||
|
|
||||||
if (sample->modes & PATCH_SUSTAIN)
|
if (sample->modes & PATCH_SUSTAIN)
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,7 +54,7 @@ void font_add(const char *filename, int load_order)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FileReader *fp = open_filereader(filename, openmode, NULL);
|
FileReader *fp = pathExpander.openFileReader(filename, NULL);
|
||||||
|
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1441,7 +1441,6 @@ void SFFile::ApplyGeneratorsToRegion(SFGenComposite *gen, SFSample *sfsamp, Rend
|
||||||
sp->root_freq = note_to_freq(sp->scale_note);
|
sp->root_freq = note_to_freq(sp->scale_note);
|
||||||
sp->sample_rate = sfsamp->SampleRate;
|
sp->sample_rate = sfsamp->SampleRate;
|
||||||
sp->key_group = gen->exclusiveClass;
|
sp->key_group = gen->exclusiveClass;
|
||||||
sp->volume = 1;
|
|
||||||
|
|
||||||
// Set key scaling
|
// Set key scaling
|
||||||
if (gen->keynum >= 0 && gen->keynum <= 127)
|
if (gen->keynum >= 0 && gen->keynum <= 127)
|
||||||
|
@ -1502,7 +1501,7 @@ void SFFile::ApplyGeneratorsToRegion(SFGenComposite *gen, SFSample *sfsamp, Rend
|
||||||
|
|
||||||
void SFFile::LoadSample(SFSample *sample)
|
void SFFile::LoadSample(SFSample *sample)
|
||||||
{
|
{
|
||||||
FileReader *fp = open_filereader(Filename, openmode, NULL);
|
FileReader *fp = pathExpander.openFileReader(Filename, NULL);
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, midi_timiditylike)
|
|
||||||
|
|
||||||
namespace Timidity
|
namespace Timidity
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -78,16 +76,7 @@ void GF1Envelope::Init(Renderer *song, Voice *v)
|
||||||
|
|
||||||
void GF1Envelope::Release(Voice *v)
|
void GF1Envelope::Release(Voice *v)
|
||||||
{
|
{
|
||||||
if (midi_timiditylike)
|
if (!(v->sample->modes & PATCH_NO_SRELEASE) || (v->sample->modes & PATCH_FAST_REL))
|
||||||
{
|
|
||||||
if (!(v->sample->modes & PATCH_T_NO_ENVELOPE))
|
|
||||||
{
|
|
||||||
stage = GF1_RELEASE;
|
|
||||||
Recompute(v);
|
|
||||||
}
|
|
||||||
// else ... loop was already turned off by the caller
|
|
||||||
}
|
|
||||||
else if (!(v->sample->modes & PATCH_NO_SRELEASE) || (v->sample->modes & PATCH_FAST_REL))
|
|
||||||
{
|
{
|
||||||
/* ramp out to minimum volume with rate from final release stage */
|
/* ramp out to minimum volume with rate from final release stage */
|
||||||
stage = GF1_RELEASEC+1;
|
stage = GF1_RELEASEC+1;
|
||||||
|
@ -119,23 +108,11 @@ bool GF1Envelope::Recompute(Voice *v)
|
||||||
bUpdating = false;
|
bUpdating = false;
|
||||||
v->status &= ~(VOICE_SUSTAINING | VOICE_LPE);
|
v->status &= ~(VOICE_SUSTAINING | VOICE_LPE);
|
||||||
v->status |= VOICE_RELEASING;
|
v->status |= VOICE_RELEASING;
|
||||||
if (midi_timiditylike)
|
/* play sampled release */
|
||||||
{ /* kill the voice ... or not */
|
|
||||||
if (volume <= 0)
|
|
||||||
{
|
|
||||||
v->status |= VOICE_STOPPING;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* play sampled release */
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newstage == GF1_RELEASE && !(v->status & VOICE_RELEASING) &&
|
if (newstage == GF1_RELEASE && !(v->status & VOICE_RELEASING) && (v->sample->modes & PATCH_SUSTAIN))
|
||||||
((!midi_timiditylike && (v->sample->modes & PATCH_SUSTAIN)) ||
|
|
||||||
(midi_timiditylike && !(v->sample->modes & PATCH_T_NO_ENVELOPE))))
|
|
||||||
{
|
{
|
||||||
v->status |= VOICE_SUSTAINING;
|
v->status |= VOICE_SUSTAINING;
|
||||||
/* Freeze envelope until note turns off. Trumpets want this. */
|
/* Freeze envelope until note turns off. Trumpets want this. */
|
||||||
|
@ -161,10 +138,6 @@ bool GF1Envelope::Recompute(Voice *v)
|
||||||
|
|
||||||
bool GF1Envelope::Update(Voice *v)
|
bool GF1Envelope::Update(Voice *v)
|
||||||
{
|
{
|
||||||
if (midi_timiditylike && (v->sample->modes & PATCH_T_NO_ENVELOPE))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
volume += increment;
|
volume += increment;
|
||||||
if (((increment < 0) && (volume <= target)) || ((increment > 0) && (volume >= target)))
|
if (((increment < 0) && (volume <= target)) || ((increment > 0) && (volume >= target)))
|
||||||
{
|
{
|
||||||
|
@ -182,36 +155,14 @@ void GF1Envelope::ApplyToAmp(Voice *v)
|
||||||
double env_vol = v->attenuation;
|
double env_vol = v->attenuation;
|
||||||
double final_amp;
|
double final_amp;
|
||||||
|
|
||||||
if (midi_timiditylike)
|
final_amp = FINAL_MIX_SCALE;
|
||||||
{
|
if (v->tremolo_phase_increment != 0)
|
||||||
final_amp = v->sample->volume * FINAL_MIX_TIMIDITY_SCALE;
|
{ // [RH] FIXME: This is wrong. Tremolo should offset the
|
||||||
if (v->tremolo_phase_increment != 0)
|
// envelope volume, not scale it.
|
||||||
{
|
env_vol *= v->tremolo_volume;
|
||||||
env_vol *= v->tremolo_volume;
|
|
||||||
}
|
|
||||||
if (!(v->sample->modes & PATCH_T_NO_ENVELOPE))
|
|
||||||
{
|
|
||||||
if (stage > GF1_ATTACK)
|
|
||||||
{
|
|
||||||
env_vol *= pow(2.0, volume * (6.0 / (1 << 30)) - 6.0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
env_vol *= volume / float(1 << 30);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
final_amp = FINAL_MIX_SCALE;
|
|
||||||
if (v->tremolo_phase_increment != 0)
|
|
||||||
{ // [RH] FIXME: This is wrong. Tremolo should offset the
|
|
||||||
// envelope volume, not scale it.
|
|
||||||
env_vol *= v->tremolo_volume;
|
|
||||||
}
|
|
||||||
env_vol *= volume / float(1 << 30);
|
|
||||||
env_vol = calc_gf1_amp(env_vol);
|
|
||||||
}
|
}
|
||||||
|
env_vol *= volume / float(1 << 30);
|
||||||
|
env_vol = calc_gf1_amp(env_vol);
|
||||||
env_vol *= final_amp;
|
env_vol *= final_amp;
|
||||||
v->left_mix = float(env_vol * v->left_offset);
|
v->left_mix = float(env_vol * v->left_offset);
|
||||||
v->right_mix = float(env_vol * v->right_offset);
|
v->right_mix = float(env_vol * v->right_offset);
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
#include "timidity.h"
|
#include "timidity.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, midi_timiditylike)
|
|
||||||
|
|
||||||
namespace Timidity
|
namespace Timidity
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -118,7 +116,7 @@ void Renderer::recompute_freq(int v)
|
||||||
voice[v].sample_increment = (int)(a);
|
voice[v].sample_increment = (int)(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BYTE vol_table[] = {
|
static const BYTE vol_table[] = {
|
||||||
000 /* 000 */, 129 /* 001 */, 145 /* 002 */, 155 /* 003 */,
|
000 /* 000 */, 129 /* 001 */, 145 /* 002 */, 155 /* 003 */,
|
||||||
161 /* 004 */, 166 /* 005 */, 171 /* 006 */, 174 /* 007 */,
|
161 /* 004 */, 166 /* 005 */, 171 /* 006 */, 174 /* 007 */,
|
||||||
177 /* 008 */, 180 /* 009 */, 182 /* 010 */, 185 /* 011 */,
|
177 /* 008 */, 180 /* 009 */, 182 /* 010 */, 185 /* 011 */,
|
||||||
|
@ -161,16 +159,7 @@ void Renderer::recompute_amp(Voice *v)
|
||||||
|
|
||||||
if (v->sample->type == INST_GUS)
|
if (v->sample->type == INST_GUS)
|
||||||
{
|
{
|
||||||
if (midi_timiditylike)
|
v->attenuation = (vol_table[(chanvol * chanexpr) / 127] * vol_table[v->velocity]) * ((127 + 64) / 12419775.f);
|
||||||
{
|
|
||||||
v->attenuation = float(timidityxx_perceived_vol(v->velocity / 127.0) *
|
|
||||||
timidityxx_perceived_vol(chanvol / 127.0) *
|
|
||||||
timidityxx_perceived_vol(chanexpr / 127.0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v->attenuation = (vol_table[(chanvol * chanexpr) / 127] * vol_table[v->velocity]) * ((127 + 64) / 12419775.f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -199,7 +188,7 @@ void Renderer::compute_pan(double pan, int type, float &left_offset, float &righ
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (type == INST_GUS && !midi_timiditylike)
|
if (type == INST_GUS)
|
||||||
{
|
{
|
||||||
/* Original amp equation looks like this:
|
/* Original amp equation looks like this:
|
||||||
* calc_gf1_amp(atten + offset)
|
* calc_gf1_amp(atten + offset)
|
||||||
|
@ -218,9 +207,7 @@ void Renderer::compute_pan(double pan, int type, float &left_offset, float &righ
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* I have no idea what equation, if any, will reproduce the sc_pan_table
|
/* Equal Power Panning for SF2/DLS.
|
||||||
* that TiMidity++ uses, so midi_timiditylike gets the same Equal Power
|
|
||||||
* Panning as SF2/DLS.
|
|
||||||
*/
|
*/
|
||||||
left_offset = (float)sqrt(1 - pan);
|
left_offset = (float)sqrt(1 - pan);
|
||||||
right_offset = (float)sqrt(pan);
|
right_offset = (float)sqrt(pan);
|
||||||
|
@ -561,7 +548,7 @@ void Renderer::finish_note(int i)
|
||||||
v->status &= ~VOICE_SUSTAINING;
|
v->status &= ~VOICE_SUSTAINING;
|
||||||
v->status |= VOICE_RELEASING;
|
v->status |= VOICE_RELEASING;
|
||||||
|
|
||||||
if (!(v->sample->modes & PATCH_NO_SRELEASE) || midi_timiditylike)
|
if (!(v->sample->modes & PATCH_NO_SRELEASE))
|
||||||
{
|
{
|
||||||
v->status &= ~VOICE_LPE; /* sampled release */
|
v->status &= ~VOICE_LPE; /* sampled release */
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
#include "timidity.h"
|
#include "timidity.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, midi_timiditylike)
|
|
||||||
|
|
||||||
namespace Timidity
|
namespace Timidity
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -522,7 +520,7 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
|
||||||
|
|
||||||
if (vp->vibrato_control_ratio)
|
if (vp->vibrato_control_ratio)
|
||||||
{
|
{
|
||||||
if (vp->status & VOICE_LPE && !(midi_timiditylike && vp->sample->modes & PATCH_T_NO_LOOP))
|
if (vp->status & VOICE_LPE)
|
||||||
{
|
{
|
||||||
if (modes & PATCH_BIDIR)
|
if (modes & PATCH_BIDIR)
|
||||||
return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr);
|
return rs_vib_bidir(song->resample_buffer, song->rate, vp, *countptr);
|
||||||
|
@ -536,7 +534,7 @@ sample_t *resample_voice(Renderer *song, Voice *vp, int *countptr)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (vp->status & VOICE_LPE && !(midi_timiditylike && vp->sample->modes & PATCH_T_NO_LOOP))
|
if (vp->status & VOICE_LPE)
|
||||||
{
|
{
|
||||||
if (modes & PATCH_BIDIR)
|
if (modes & PATCH_BIDIR)
|
||||||
return rs_bidir(song->resample_buffer, vp, *countptr);
|
return rs_bidir(song->resample_buffer, vp, *countptr);
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
|
|
||||||
CVAR(String, midi_config, CONFIG_FILE, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR(String, midi_config, CONFIG_FILE, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR(Int, midi_voices, 32, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR(Int, midi_voices, 32, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR(Bool, midi_timiditylike, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|
||||||
CVAR(String, gus_patchdir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR(String, gus_patchdir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR(Bool, midi_dmxgus, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR(Bool, midi_dmxgus, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR(Int, gus_memsize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR(Int, gus_memsize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
@ -42,10 +41,10 @@ CVAR(Int, gus_memsize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
namespace Timidity
|
namespace Timidity
|
||||||
{
|
{
|
||||||
|
|
||||||
|
PathExpander pathExpander;
|
||||||
ToneBank *tonebank[MAXBANK], *drumset[MAXBANK];
|
ToneBank *tonebank[MAXBANK], *drumset[MAXBANK];
|
||||||
|
|
||||||
static FString def_instr_name;
|
static FString def_instr_name;
|
||||||
int openmode = OM_FILEORLUMP;
|
|
||||||
|
|
||||||
static int read_config_file(const char *name, bool ismain)
|
static int read_config_file(const char *name, bool ismain)
|
||||||
{
|
{
|
||||||
|
@ -62,21 +61,21 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ismain) openmode = OM_FILEORLUMP;
|
if (ismain) pathExpander.openmode = PathExpander::OM_FILEORLUMP;
|
||||||
|
|
||||||
if (!(fp = open_filereader(name, openmode, &lumpnum)))
|
if (!(fp = pathExpander.openFileReader(name, &lumpnum)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (ismain)
|
if (ismain)
|
||||||
{
|
{
|
||||||
if (lumpnum > 0)
|
if (lumpnum > 0)
|
||||||
{
|
{
|
||||||
openmode = OM_LUMP;
|
pathExpander.openmode = PathExpander::OM_LUMP;
|
||||||
clear_pathlist(); // when reading from a PK3 we won't want to use any external path
|
pathExpander.clearPathlist(); // when reading from a PK3 we don't want to use any external path
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
openmode = OM_FILE;
|
pathExpander.openmode = PathExpander::OM_FILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,7 +287,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
for (i = 1; i < words; i++)
|
for (i = 1; i < words; i++)
|
||||||
add_to_pathlist(w[i]);
|
pathExpander.addToPathlist(w[i]);
|
||||||
}
|
}
|
||||||
else if (!strcmp(w[0], "source"))
|
else if (!strcmp(w[0], "source"))
|
||||||
{
|
{
|
||||||
|
@ -377,7 +376,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
delete fp;
|
delete fp;
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
bank->tone[i].note = bank->tone[i].amp = bank->tone[i].pan =
|
bank->tone[i].note = bank->tone[i].pan =
|
||||||
bank->tone[i].fontbank = bank->tone[i].fontpreset =
|
bank->tone[i].fontbank = bank->tone[i].fontpreset =
|
||||||
bank->tone[i].fontnote = bank->tone[i].strip_loop =
|
bank->tone[i].fontnote = bank->tone[i].strip_loop =
|
||||||
bank->tone[i].strip_envelope = bank->tone[i].strip_tail = -1;
|
bank->tone[i].strip_envelope = bank->tone[i].strip_tail = -1;
|
||||||
|
@ -415,14 +414,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
*cp++ = 0;
|
*cp++ = 0;
|
||||||
if (!strcmp(w[j], "amp"))
|
if (!strcmp(w[j], "amp"))
|
||||||
{
|
{
|
||||||
k = atoi(cp);
|
/* Ignored */
|
||||||
if ((k < 0 || k > MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9'))
|
|
||||||
{
|
|
||||||
Printf("%s: line %d: amplification must be between 0 and %d\n", name, line, MAX_AMPLIFICATION);
|
|
||||||
delete fp;
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
bank->tone[i].amp = k;
|
|
||||||
}
|
}
|
||||||
else if (!strcmp(w[j], "note"))
|
else if (!strcmp(w[j], "note"))
|
||||||
{
|
{
|
||||||
|
@ -532,15 +524,15 @@ int LoadConfig(const char *filename)
|
||||||
* file itself since that file should contain any other directory
|
* file itself since that file should contain any other directory
|
||||||
* that needs to be added to the search path.
|
* that needs to be added to the search path.
|
||||||
*/
|
*/
|
||||||
clear_pathlist();
|
pathExpander.clearPathlist();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
add_to_pathlist("C:\\TIMIDITY");
|
pathExpander.addToPathlist("C:\\TIMIDITY");
|
||||||
add_to_pathlist("\\TIMIDITY");
|
pathExpander.addToPathlist("\\TIMIDITY");
|
||||||
add_to_pathlist(progdir);
|
pathExpander.addToPathlist(progdir);
|
||||||
#else
|
#else
|
||||||
add_to_pathlist("/usr/local/lib/timidity");
|
pathExpander.addToPathlist("/usr/local/lib/timidity");
|
||||||
add_to_pathlist("/etc/timidity");
|
pathExpander.addToPathlist("/etc/timidity");
|
||||||
add_to_pathlist("/etc");
|
pathExpander.addToPathlist("/etc");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Some functions get aggravated if not even the standard banks are available. */
|
/* Some functions get aggravated if not even the standard banks are available. */
|
||||||
|
@ -579,10 +571,10 @@ int LoadDMXGUS()
|
||||||
if (ultradir.IsNotEmpty())
|
if (ultradir.IsNotEmpty())
|
||||||
{
|
{
|
||||||
ultradir += "/midi";
|
ultradir += "/midi";
|
||||||
add_to_pathlist(ultradir.GetChars());
|
pathExpander.addToPathlist(ultradir.GetChars());
|
||||||
}
|
}
|
||||||
// Load DMXGUS lump and patches from gus_patchdir
|
// Load DMXGUS lump and patches from gus_patchdir
|
||||||
add_to_pathlist(gus_patchdir);
|
pathExpander.addToPathlist(gus_patchdir);
|
||||||
|
|
||||||
char readbuffer[1024];
|
char readbuffer[1024];
|
||||||
long size = data.GetLength();
|
long size = data.GetLength();
|
||||||
|
@ -676,7 +668,7 @@ int LoadDMXGUS()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int val = k % 128;
|
int val = k % 128;
|
||||||
bank->tone[val].note = bank->tone[val].amp = bank->tone[val].pan =
|
bank->tone[val].note = bank->tone[val].pan =
|
||||||
bank->tone[val].fontbank = bank->tone[val].fontpreset =
|
bank->tone[val].fontbank = bank->tone[val].fontpreset =
|
||||||
bank->tone[val].fontnote = bank->tone[val].strip_loop =
|
bank->tone[val].fontnote = bank->tone[val].strip_loop =
|
||||||
bank->tone[val].strip_envelope = bank->tone[val].strip_tail = -1;
|
bank->tone[val].strip_envelope = bank->tone[val].strip_tail = -1;
|
||||||
|
@ -686,8 +678,9 @@ int LoadDMXGUS()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::Renderer(float sample_rate)
|
Renderer::Renderer(float sample_rate, const char *args)
|
||||||
{
|
{
|
||||||
|
// 'args' should be used to load a custom config or DMXGUS, but since setup currently requires a snd_reset call, this will need some refactoring first
|
||||||
rate = sample_rate;
|
rate = sample_rate;
|
||||||
patches = NULL;
|
patches = NULL;
|
||||||
resample_buffer_size = 0;
|
resample_buffer_size = 0;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define TIMIDITY_H
|
#define TIMIDITY_H
|
||||||
|
|
||||||
#include "doomtype.h"
|
#include "doomtype.h"
|
||||||
|
#include "pathexpander.h"
|
||||||
|
|
||||||
class FileReader;
|
class FileReader;
|
||||||
|
|
||||||
|
@ -54,10 +55,6 @@ config.h
|
||||||
volume level of FMOD's built-in MIDI player. */
|
volume level of FMOD's built-in MIDI player. */
|
||||||
#define FINAL_MIX_SCALE 0.5
|
#define FINAL_MIX_SCALE 0.5
|
||||||
|
|
||||||
/* This value is used instead when midi_timiditylike is turned on,
|
|
||||||
because TiMidity++ is louder than a GUS. */
|
|
||||||
#define FINAL_MIX_TIMIDITY_SCALE 0.3
|
|
||||||
|
|
||||||
/* How many bits to use for the fractional part of sample positions.
|
/* How many bits to use for the fractional part of sample positions.
|
||||||
This affects tonal accuracy. The entire position counter must fit
|
This affects tonal accuracy. The entire position counter must fit
|
||||||
in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of
|
in 32 bits, so with FRACTION_BITS equal to 12, the maximum size of
|
||||||
|
@ -172,17 +169,8 @@ extern __inline__ double pow_x87_inline(double x,double y)
|
||||||
common.h
|
common.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define OM_FILEORLUMP 0
|
|
||||||
#define OM_LUMP 1
|
|
||||||
#define OM_FILE 2
|
|
||||||
|
|
||||||
extern void add_to_pathlist(const char *s);
|
|
||||||
extern void clear_pathlist();
|
|
||||||
extern void *safe_malloc(size_t count);
|
extern void *safe_malloc(size_t count);
|
||||||
|
|
||||||
FileReader *open_filereader(const char *name, int open, int *plumpnum);
|
|
||||||
extern int openmode;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
controls.h
|
controls.h
|
||||||
*/
|
*/
|
||||||
|
@ -219,9 +207,6 @@ enum
|
||||||
PATCH_SUSTAIN = (1<<5),
|
PATCH_SUSTAIN = (1<<5),
|
||||||
PATCH_NO_SRELEASE = (1<<6),
|
PATCH_NO_SRELEASE = (1<<6),
|
||||||
PATCH_FAST_REL = (1<<7),
|
PATCH_FAST_REL = (1<<7),
|
||||||
|
|
||||||
PATCH_T_NO_ENVELOPE = (1<<8),
|
|
||||||
PATCH_T_NO_LOOP = (1<<9)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Sample
|
struct Sample
|
||||||
|
@ -247,8 +232,6 @@ struct Sample
|
||||||
short release_vol;
|
short release_vol;
|
||||||
} sf2;
|
} sf2;
|
||||||
} envelope;
|
} envelope;
|
||||||
float
|
|
||||||
volume;
|
|
||||||
sample_t *data;
|
sample_t *data;
|
||||||
SDWORD
|
SDWORD
|
||||||
tremolo_sweep_increment, tremolo_phase_increment,
|
tremolo_sweep_increment, tremolo_phase_increment,
|
||||||
|
@ -324,11 +307,12 @@ struct Instrument
|
||||||
struct ToneBankElement
|
struct ToneBankElement
|
||||||
{
|
{
|
||||||
ToneBankElement() :
|
ToneBankElement() :
|
||||||
note(0), amp(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0)
|
note(0), pan(0), strip_loop(0), strip_envelope(0), strip_tail(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
FString name;
|
FString name;
|
||||||
int note, amp, pan, fontbank, fontpreset, fontnote, strip_loop, strip_envelope, strip_tail;
|
int note, pan, fontbank, fontpreset, fontnote;
|
||||||
|
SBYTE strip_loop, strip_envelope, strip_tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A hack to delay instrument loading until after reading the entire MIDI file. */
|
/* A hack to delay instrument loading until after reading the entire MIDI file. */
|
||||||
|
@ -616,8 +600,6 @@ const double log_of_2 = 0.69314718055994529;
|
||||||
|
|
||||||
#define calc_gf1_amp(x) (pow(2.0,((x)*16.0 - 16.0))) // Actual GUS equation
|
#define calc_gf1_amp(x) (pow(2.0,((x)*16.0 - 16.0))) // Actual GUS equation
|
||||||
#define cb_to_amp(x) (pow(10.0, (x) * (1 / -200.0))) // centibels to amp
|
#define cb_to_amp(x) (pow(10.0, (x) * (1 / -200.0))) // centibels to amp
|
||||||
#define db_to_amp(x) (pow(10.0, (x) * (1 / -20.0))) // decibels to map
|
|
||||||
#define timidityxx_perceived_vol(x) (pow((x), 1.66096404744))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
timidity.h
|
timidity.h
|
||||||
|
@ -627,6 +609,7 @@ int LoadConfig(const char *filename);
|
||||||
int LoadDMXGUS();
|
int LoadDMXGUS();
|
||||||
extern int LoadConfig();
|
extern int LoadConfig();
|
||||||
extern void FreeAll();
|
extern void FreeAll();
|
||||||
|
extern PathExpander pathExpander;
|
||||||
|
|
||||||
extern ToneBank *tonebank[MAXBANK];
|
extern ToneBank *tonebank[MAXBANK];
|
||||||
extern ToneBank *drumset[MAXBANK];
|
extern ToneBank *drumset[MAXBANK];
|
||||||
|
@ -647,7 +630,7 @@ struct Renderer
|
||||||
int voices;
|
int voices;
|
||||||
int lost_notes, cut_notes;
|
int lost_notes, cut_notes;
|
||||||
|
|
||||||
Renderer(float sample_rate);
|
Renderer(float sample_rate, const char *args);
|
||||||
~Renderer();
|
~Renderer();
|
||||||
|
|
||||||
void HandleEvent(int status, int parm1, int parm2);
|
void HandleEvent(int status, int parm1, int parm2);
|
||||||
|
|
|
@ -76,7 +76,7 @@ const char *GetVersionString();
|
||||||
|
|
||||||
// Use 4500 as the base git save version, since it's higher than the
|
// Use 4500 as the base git save version, since it's higher than the
|
||||||
// SVN revision ever got.
|
// SVN revision ever got.
|
||||||
#define SAVEVER 4524
|
#define SAVEVER 4527
|
||||||
|
|
||||||
#define SAVEVERSTRINGIFY2(x) #x
|
#define SAVEVERSTRINGIFY2(x) #x
|
||||||
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
||||||
|
|
|
@ -184,6 +184,7 @@ void FWadCollection::InitMultipleFiles (TArray<FString> &filenames)
|
||||||
}
|
}
|
||||||
RenameNerve();
|
RenameNerve();
|
||||||
RenameSprites();
|
RenameSprites();
|
||||||
|
FixMacHexen();
|
||||||
|
|
||||||
// [RH] Set up hash table
|
// [RH] Set up hash table
|
||||||
FirstLumpIndex = new DWORD[NumLumps];
|
FirstLumpIndex = new DWORD[NumLumps];
|
||||||
|
@ -956,6 +957,41 @@ void FWadCollection::RenameNerve ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FixMacHexen
|
||||||
|
//
|
||||||
|
// Rename unused high resolution font lumps because they are incorrectly
|
||||||
|
// treated as extended characters
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FWadCollection::FixMacHexen()
|
||||||
|
{
|
||||||
|
if (GAME_Hexen != gameinfo.gametype)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = GetFirstLump(IWAD_FILENUM), last = GetLastLump(IWAD_FILENUM); i <= last; ++i)
|
||||||
|
{
|
||||||
|
assert(IWAD_FILENUM == LumpInfo[i].wadnum);
|
||||||
|
|
||||||
|
FResourceLump* const lump = LumpInfo[i].lump;
|
||||||
|
char* const name = lump->Name;
|
||||||
|
|
||||||
|
// Unwanted lumps are named like FONTA??1
|
||||||
|
|
||||||
|
if (8 == strlen(name)
|
||||||
|
&& MAKE_ID('F', 'O', 'N', 'T') == lump->dwName
|
||||||
|
&& 'A' == name[4] && '1' == name[7]
|
||||||
|
&& isdigit(name[5]) && isdigit(name[6]))
|
||||||
|
{
|
||||||
|
name[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// W_FindLump
|
// W_FindLump
|
||||||
|
|
|
@ -238,6 +238,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void RenameSprites();
|
void RenameSprites();
|
||||||
void RenameNerve();
|
void RenameNerve();
|
||||||
|
void FixMacHexen();
|
||||||
void DeleteAll();
|
void DeleteAll();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
94
src/wildmidi/common.h
Normal file
94
src/wildmidi/common.h
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
common.h
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
Copyright (C) Chris Ison 2001-2011
|
||||||
|
Copyright (C) Bret Curtis 2013-2014
|
||||||
|
|
||||||
|
This file is part of WildMIDI.
|
||||||
|
|
||||||
|
WildMIDI is free software: you can redistribute and/or modify the player
|
||||||
|
under the terms of the GNU General Public License and you can redistribute
|
||||||
|
and/or modify the library under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3 of
|
||||||
|
the licenses, or(at your option) any later version.
|
||||||
|
|
||||||
|
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
|
||||||
|
the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with WildMIDI. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COMMON_H
|
||||||
|
#define __COMMON_H
|
||||||
|
|
||||||
|
#define SAMPLE_16BIT 0x01
|
||||||
|
#define SAMPLE_UNSIGNED 0x02
|
||||||
|
#define SAMPLE_LOOP 0x04
|
||||||
|
#define SAMPLE_PINGPONG 0x08
|
||||||
|
#define SAMPLE_REVERSE 0x10
|
||||||
|
#define SAMPLE_SUSTAIN 0x20
|
||||||
|
#define SAMPLE_ENVELOPE 0x40
|
||||||
|
#define SAMPLE_CLAMPED 0x80
|
||||||
|
|
||||||
|
#ifdef DEBUG_SAMPLES
|
||||||
|
#define SAMPLE_CONVERT_DEBUG(dx) printf("\r%s\n",dx)
|
||||||
|
#else
|
||||||
|
#define SAMPLE_CONVERT_DEBUG(dx)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern unsigned short int _WM_SampleRate;
|
||||||
|
|
||||||
|
struct _sample {
|
||||||
|
unsigned long int data_length;
|
||||||
|
unsigned long int loop_start;
|
||||||
|
unsigned long int loop_end;
|
||||||
|
unsigned long int loop_size;
|
||||||
|
unsigned char loop_fraction;
|
||||||
|
unsigned short int rate;
|
||||||
|
unsigned long int freq_low;
|
||||||
|
unsigned long int freq_high;
|
||||||
|
unsigned long int freq_root;
|
||||||
|
unsigned char modes;
|
||||||
|
signed long int env_rate[7];
|
||||||
|
signed long int env_target[7];
|
||||||
|
unsigned long int inc_div;
|
||||||
|
signed short *data;
|
||||||
|
struct _sample *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _env {
|
||||||
|
float time;
|
||||||
|
float level;
|
||||||
|
unsigned char set;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _patch {
|
||||||
|
unsigned short patchid;
|
||||||
|
unsigned char loaded;
|
||||||
|
char *filename;
|
||||||
|
signed short int amp;
|
||||||
|
unsigned char keep;
|
||||||
|
unsigned char remove;
|
||||||
|
struct _env env[6];
|
||||||
|
unsigned char note;
|
||||||
|
unsigned long int inuse_count;
|
||||||
|
struct _sample *first_sample;
|
||||||
|
struct _patch *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set our global defines here */
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LN2
|
||||||
|
#define M_LN2 0.69314718055994530942
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __COMMON_H */
|
112
src/wildmidi/file_io.cpp
Normal file
112
src/wildmidi/file_io.cpp
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
** file_io.cpp
|
||||||
|
** ZDoom compatible file IO interface for WildMIDI
|
||||||
|
** (This file was completely redone to remove the low level IO code references)
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2010 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "../files.h"
|
||||||
|
#include "wm_error.h"
|
||||||
|
#include "file_io.h"
|
||||||
|
#include "pathexpander.h"
|
||||||
|
#include "cmdlib.h"
|
||||||
|
|
||||||
|
static PathExpander wmPathExpander;
|
||||||
|
|
||||||
|
unsigned char *_WM_BufferFile(const char *filename, unsigned long int *size, bool ismain)
|
||||||
|
{
|
||||||
|
FileReader *fp;
|
||||||
|
int lumpnum;
|
||||||
|
|
||||||
|
if (ismain)
|
||||||
|
{
|
||||||
|
wmPathExpander.openmode = PathExpander::OM_FILEORLUMP;
|
||||||
|
wmPathExpander.clearPathlist();
|
||||||
|
#ifdef _WIN32
|
||||||
|
wmPathExpander.addToPathlist("C:\\TIMIDITY");
|
||||||
|
wmPathExpander.addToPathlist("\\TIMIDITY");
|
||||||
|
wmPathExpander.addToPathlist(progdir);
|
||||||
|
#else
|
||||||
|
wmPathExpander.addToPathlist("/usr/local/lib/timidity");
|
||||||
|
wmPathExpander.addToPathlist("/etc/timidity");
|
||||||
|
wmPathExpander.addToPathlist("/etc");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(fp = wmPathExpander.openFileReader(filename, &lumpnum)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (ismain)
|
||||||
|
{
|
||||||
|
if (lumpnum > 0)
|
||||||
|
{
|
||||||
|
wmPathExpander.openmode = PathExpander::OM_LUMP;
|
||||||
|
wmPathExpander.clearPathlist(); // when reading from a PK3 we don't want to use any external path
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wmPathExpander.openmode = PathExpander::OM_FILE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long fsize = fp->GetLength();
|
||||||
|
|
||||||
|
if (fsize > WM_MAXFILESIZE)
|
||||||
|
{
|
||||||
|
/* don't bother loading suspiciously long files */
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LONGFIL, filename, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *data = (unsigned char*)malloc(fsize+1);
|
||||||
|
if (data == NULL)
|
||||||
|
{
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, errno);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, errno);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp->Read(data, fsize);
|
||||||
|
delete fp;
|
||||||
|
data[fsize] = 0;
|
||||||
|
*size = fsize;
|
||||||
|
return data;
|
||||||
|
}
|
33
src/wildmidi/file_io.h
Normal file
33
src/wildmidi/file_io.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
file_io.c
|
||||||
|
|
||||||
|
file handling
|
||||||
|
|
||||||
|
Copyright (C) Chris Ison 2001-2011
|
||||||
|
Copyright (C) Bret Curtis 2013-2014
|
||||||
|
|
||||||
|
This file is part of WildMIDI.
|
||||||
|
|
||||||
|
WildMIDI is free software: you can redistribute and/or modify the player
|
||||||
|
under the terms of the GNU General Public License and you can redistribute
|
||||||
|
and/or modify the library under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3 of
|
||||||
|
the licenses, or(at your option) any later version.
|
||||||
|
|
||||||
|
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
|
||||||
|
the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with WildMIDI. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FILE_IO_H
|
||||||
|
#define __FILE_IO_H
|
||||||
|
|
||||||
|
#define WM_MAXFILESIZE 0x1fffffff
|
||||||
|
extern unsigned char *_WM_BufferFile (const char *filename, unsigned long int *size, bool mainfile = false);
|
||||||
|
|
||||||
|
#endif /* __FILE_IO_H */
|
900
src/wildmidi/gus_pat.cpp
Normal file
900
src/wildmidi/gus_pat.cpp
Normal file
|
@ -0,0 +1,900 @@
|
||||||
|
/*
|
||||||
|
gus_pat.c
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
Copyright (C) Chris Ison 2001-2011
|
||||||
|
Copyright (C) Bret Curtis 2013-2014
|
||||||
|
|
||||||
|
This file is part of WildMIDI.
|
||||||
|
|
||||||
|
WildMIDI is free software: you can redistribute and/or modify the player
|
||||||
|
under the terms of the GNU General Public License and you can redistribute
|
||||||
|
and/or modify the library under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3 of
|
||||||
|
the licenses, or(at your option) any later version.
|
||||||
|
|
||||||
|
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
|
||||||
|
the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with WildMIDI. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gus_pat.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "wm_error.h"
|
||||||
|
#include "file_io.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG_GUSPAT
|
||||||
|
#define GUSPAT_FILENAME_DEBUG(dx) fprintf(stderr,"\r%s\n",dx)
|
||||||
|
|
||||||
|
#define GUSPAT_INT_DEBUG(dx,dy) fprintf(stderr,"\r%s: %i\n",dx,dy)
|
||||||
|
#define GUSPAT_FLOAT_DEBUG(dx,dy) fprintf(stderr,"\r%s: %f\n",dx,dy)
|
||||||
|
#define GUSPAT_START_DEBUG() fprintf(stderr,"\r")
|
||||||
|
#define GUSPAT_MODE_DEBUG(dx,dy,dz) if (dx & dy) fprintf(stderr,"%s",dz)
|
||||||
|
#define GUSPAT_END_DEBUG() fprintf(stderr,"\n")
|
||||||
|
#else
|
||||||
|
#define GUSPAT_FILENAME_DEBUG(dx)
|
||||||
|
#define GUSPAT_INT_DEBUG(dx,dy)
|
||||||
|
#define GUSPAT_FLOAT_DEBUG(dx,dy)
|
||||||
|
#define GUSPAT_START_DEBUG()
|
||||||
|
#define GUSPAT_MODE_DEBUG(dx,dy,dz)
|
||||||
|
#define GUSPAT_END_DEBUG()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sample data conversion functions
|
||||||
|
* convert data to signed shorts
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 8bit signed */
|
||||||
|
static int convert_8s(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((gus_sample->data_length + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = (*read_data++) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR_NEW("(%s:%i) ERROR: calloc failed (%s)", __FUNCTION__, __LINE__,
|
||||||
|
strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit signed ping pong */
|
||||||
|
static int convert_8sp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_start;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((new_length + 2), sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = (*read_data++) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++ << 8);
|
||||||
|
write_data_a = write_data + dloop_length;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + dloop_length;
|
||||||
|
read_end = data + gus_sample->loop_end;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++ << 8);
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data + gus_sample->data_length;
|
||||||
|
if (read_data != read_end) {
|
||||||
|
do {
|
||||||
|
*write_data_b++ = (*read_data++) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
}
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit signed reverse */
|
||||||
|
static int convert_8sr(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
unsigned long int tmp_loop = 0;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((gus_sample->data_length + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data + gus_sample->data_length - 1;
|
||||||
|
do {
|
||||||
|
*write_data-- = (*read_data++) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = gus_sample->data_length - tmp_loop;
|
||||||
|
gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
gus_sample->modes ^= SAMPLE_REVERSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit signed reverse ping pong */
|
||||||
|
static int convert_8srp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data + gus_sample->data_length - 1;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_end;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((new_length + 2), sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = (*read_data--) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data-- << 8);
|
||||||
|
write_data_a = write_data + dloop_length;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + dloop_length;
|
||||||
|
read_end = data + gus_sample->loop_start;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data--) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data-- << 8);
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data - 1;
|
||||||
|
do {
|
||||||
|
*write_data_b++ = (*read_data--) << 8;
|
||||||
|
write_data_b++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit unsigned */
|
||||||
|
static int convert_8u(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((gus_sample->data_length + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
gus_sample->modes ^= SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit unsigned ping pong */
|
||||||
|
static int convert_8up(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_start;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((new_length + 2), sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
write_data_a = write_data + dloop_length;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + dloop_length;
|
||||||
|
read_end = data + gus_sample->loop_end;
|
||||||
|
do {
|
||||||
|
*write_data = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data + gus_sample->data_length;
|
||||||
|
if (read_data != read_end) {
|
||||||
|
do {
|
||||||
|
*write_data_b++ = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
}
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit unsigned reverse */
|
||||||
|
static int convert_8ur(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
unsigned long int tmp_loop = 0;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((gus_sample->data_length + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data + gus_sample->data_length - 1;
|
||||||
|
do {
|
||||||
|
*write_data-- = ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = gus_sample->data_length - tmp_loop;
|
||||||
|
gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
gus_sample->modes ^= SAMPLE_REVERSE | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8bit unsigned reverse ping pong */
|
||||||
|
static int convert_8urp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data + gus_sample->data_length - 1;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_end;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc((new_length + 2), sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data++ = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
write_data_a = write_data + dloop_length;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + dloop_length;
|
||||||
|
read_end = data + gus_sample->loop_start;
|
||||||
|
do {
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data - 1;
|
||||||
|
do {
|
||||||
|
*write_data_b++ = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
} while (read_data != read_end);
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit signed */
|
||||||
|
static int convert_16s(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((gus_sample->data_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = *read_data++;
|
||||||
|
*write_data++ |= (*read_data++) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit signed ping pong */
|
||||||
|
static int convert_16sp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_start;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((new_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data++ |= (*read_data++) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= (*read_data++) << 8;
|
||||||
|
write_data_a = write_data + (dloop_length >> 1);
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + (dloop_length >> 1);
|
||||||
|
read_end = data + gus_sample->loop_end;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= (*read_data++) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = *(read_data++);
|
||||||
|
*write_data |= (*read_data++) << 8;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data + gus_sample->data_length;
|
||||||
|
if (read_data != read_end) {
|
||||||
|
do {
|
||||||
|
*write_data_b = *(read_data++);
|
||||||
|
*write_data_b++ |= (*read_data++) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
}
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG;
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit signed reverse */
|
||||||
|
static int convert_16sr(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
unsigned long int tmp_loop = 0;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((gus_sample->data_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data + (gus_sample->data_length >> 1) - 1;
|
||||||
|
do {
|
||||||
|
*write_data = *read_data++;
|
||||||
|
*write_data-- |= (*read_data++) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = gus_sample->data_length - tmp_loop;
|
||||||
|
gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
gus_sample->modes ^= SAMPLE_REVERSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit signed reverse ping pong */
|
||||||
|
static int convert_16srp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data + gus_sample->data_length - 1;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_end;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((new_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data--) << 8;
|
||||||
|
*write_data++ |= *read_data--;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data-- << 8);
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
write_data_a = write_data + (dloop_length >> 1);
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + (dloop_length >> 1);
|
||||||
|
read_end = data + gus_sample->loop_start;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data--) << 8;
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) << 8);
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data - 1;
|
||||||
|
do {
|
||||||
|
*write_data_b = (*read_data--) << 8;
|
||||||
|
*write_data_b++ |= *read_data--;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit unsigned */
|
||||||
|
static int convert_16u(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((gus_sample->data_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = *read_data++;
|
||||||
|
*write_data++ |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
gus_sample->modes ^= SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit unsigned ping pong */
|
||||||
|
static int convert_16up(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_start;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((new_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data++ |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
write_data_a = write_data + (dloop_length >> 1);
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + (dloop_length >> 1);
|
||||||
|
read_end = data + gus_sample->loop_end;
|
||||||
|
do {
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = (*read_data++);
|
||||||
|
*write_data |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data + gus_sample->data_length;
|
||||||
|
if (read_data != read_end) {
|
||||||
|
do {
|
||||||
|
*write_data_b = (*read_data++);
|
||||||
|
*write_data_b++ |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
}
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG;
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit unsigned reverse */
|
||||||
|
static int convert_16ur(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned char *read_data = data;
|
||||||
|
unsigned char *read_end = data + gus_sample->data_length;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
unsigned long int tmp_loop = 0;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((gus_sample->data_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data + (gus_sample->data_length >> 1) - 1;
|
||||||
|
do {
|
||||||
|
*write_data = *read_data++;
|
||||||
|
*write_data-- |= ((*read_data++) ^ 0x80) << 8;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->data_length - gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = gus_sample->data_length - tmp_loop;
|
||||||
|
gus_sample->loop_fraction = ((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
gus_sample->loop_start >>= 1;
|
||||||
|
gus_sample->loop_end >>= 1;
|
||||||
|
gus_sample->data_length >>= 1;
|
||||||
|
gus_sample->modes ^= SAMPLE_REVERSE | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16bit unsigned reverse ping pong */
|
||||||
|
static int convert_16urp(unsigned char *data, struct _sample *gus_sample) {
|
||||||
|
unsigned long int loop_length = gus_sample->loop_end
|
||||||
|
- gus_sample->loop_start;
|
||||||
|
unsigned long int dloop_length = loop_length * 2;
|
||||||
|
unsigned long int new_length = gus_sample->data_length + dloop_length;
|
||||||
|
unsigned char *read_data = data + gus_sample->data_length - 1;
|
||||||
|
unsigned char *read_end = data + gus_sample->loop_end;
|
||||||
|
signed short int *write_data = NULL;
|
||||||
|
signed short int *write_data_a = NULL;
|
||||||
|
signed short int *write_data_b = NULL;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__);
|
||||||
|
gus_sample->data = (short*)calloc(((new_length >> 1) + 2),
|
||||||
|
sizeof(signed short int));
|
||||||
|
if (gus_sample->data != NULL) {
|
||||||
|
write_data = gus_sample->data;
|
||||||
|
do {
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data++ |= *read_data--;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
write_data_a = write_data + (dloop_length >> 1);
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
write_data++;
|
||||||
|
write_data_b = write_data + (dloop_length >> 1);
|
||||||
|
read_end = data + gus_sample->loop_start;
|
||||||
|
do {
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
*write_data_a-- = *write_data;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
write_data++;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
|
||||||
|
*write_data = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data |= *read_data--;
|
||||||
|
*write_data_b++ = *write_data;
|
||||||
|
read_end = data - 1;
|
||||||
|
do {
|
||||||
|
*write_data_b = ((*read_data--) ^ 0x80) << 8;
|
||||||
|
*write_data_b++ |= *read_data--;
|
||||||
|
} while (read_data < read_end);
|
||||||
|
gus_sample->loop_start += loop_length;
|
||||||
|
gus_sample->loop_end += dloop_length;
|
||||||
|
gus_sample->data_length = new_length;
|
||||||
|
gus_sample->modes ^= SAMPLE_PINGPONG | SAMPLE_REVERSE | SAMPLE_UNSIGNED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, "to parse sample", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sample loading */
|
||||||
|
|
||||||
|
struct _sample * _WM_load_gus_pat(const char *filename, int fix_release) {
|
||||||
|
unsigned char *gus_patch;
|
||||||
|
unsigned long int gus_size;
|
||||||
|
unsigned long int gus_ptr;
|
||||||
|
unsigned char no_of_samples;
|
||||||
|
struct _sample *gus_sample = NULL;
|
||||||
|
struct _sample *first_gus_sample = NULL;
|
||||||
|
unsigned long int i = 0;
|
||||||
|
|
||||||
|
int (*do_convert[])(unsigned char *data, struct _sample *gus_sample) = {
|
||||||
|
convert_8s,
|
||||||
|
convert_16s,
|
||||||
|
convert_8u,
|
||||||
|
convert_16u,
|
||||||
|
convert_8sp,
|
||||||
|
convert_16sp,
|
||||||
|
convert_8up,
|
||||||
|
convert_16up,
|
||||||
|
convert_8sr,
|
||||||
|
convert_16sr,
|
||||||
|
convert_8ur,
|
||||||
|
convert_16ur,
|
||||||
|
convert_8srp,
|
||||||
|
convert_16srp,
|
||||||
|
convert_8urp,
|
||||||
|
convert_16urp
|
||||||
|
};
|
||||||
|
unsigned long int tmp_loop;
|
||||||
|
|
||||||
|
SAMPLE_CONVERT_DEBUG(__FUNCTION__); SAMPLE_CONVERT_DEBUG(filename);
|
||||||
|
|
||||||
|
if ((gus_patch = _WM_BufferFile(filename, &gus_size)) == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (gus_size < 239) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_CORUPT, "(too short)", 0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (memcmp(gus_patch, "GF1PATCH110\0ID#000002", 22)
|
||||||
|
&& memcmp(gus_patch, "GF1PATCH100\0ID#000002", 22)) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(unsupported format)",
|
||||||
|
0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (gus_patch[82] > 1) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(unsupported format)",
|
||||||
|
0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (gus_patch[151] > 1) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_INVALID, "(unsupported format)",
|
||||||
|
0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUSPAT_FILENAME_DEBUG(filename); GUSPAT_INT_DEBUG("voices",gus_patch[83]);
|
||||||
|
|
||||||
|
no_of_samples = gus_patch[198];
|
||||||
|
gus_ptr = 239;
|
||||||
|
while (no_of_samples) {
|
||||||
|
unsigned long int tmp_cnt;
|
||||||
|
if (first_gus_sample == NULL) {
|
||||||
|
first_gus_sample = (struct _sample*)malloc(sizeof(struct _sample));
|
||||||
|
gus_sample = first_gus_sample;
|
||||||
|
} else {
|
||||||
|
gus_sample->next = (struct _sample*)malloc(sizeof(struct _sample));
|
||||||
|
gus_sample = gus_sample->next;
|
||||||
|
}
|
||||||
|
if (gus_sample == NULL) {
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_MEM, NULL, 0);
|
||||||
|
_WM_ERROR(__FUNCTION__, __LINE__, WM_ERR_LOAD, filename, 0);
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gus_sample->next = NULL;
|
||||||
|
gus_sample->loop_fraction = gus_patch[gus_ptr + 7];
|
||||||
|
gus_sample->data_length = (gus_patch[gus_ptr + 11] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 10] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 9] << 8) | gus_patch[gus_ptr + 8];
|
||||||
|
gus_sample->loop_start = (gus_patch[gus_ptr + 15] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 14] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 13] << 8) | gus_patch[gus_ptr + 12];
|
||||||
|
gus_sample->loop_end = (gus_patch[gus_ptr + 19] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 18] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 17] << 8) | gus_patch[gus_ptr + 16];
|
||||||
|
gus_sample->rate = (gus_patch[gus_ptr + 21] << 8)
|
||||||
|
| gus_patch[gus_ptr + 20];
|
||||||
|
gus_sample->freq_low = ((gus_patch[gus_ptr + 25] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 24] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 23] << 8) | gus_patch[gus_ptr + 22]);
|
||||||
|
gus_sample->freq_high = ((gus_patch[gus_ptr + 29] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 28] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 27] << 8) | gus_patch[gus_ptr + 26]);
|
||||||
|
gus_sample->freq_root = ((gus_patch[gus_ptr + 33] << 24)
|
||||||
|
| (gus_patch[gus_ptr + 32] << 16)
|
||||||
|
| (gus_patch[gus_ptr + 31] << 8) | gus_patch[gus_ptr + 30]);
|
||||||
|
|
||||||
|
/* This is done this way instead of ((freq * 1024) / rate) to avoid 32bit overflow. */
|
||||||
|
/* Result is 0.001% inacurate */
|
||||||
|
gus_sample->inc_div = ((gus_sample->freq_root * 512) / gus_sample->rate) * 2;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* We dont use this info at this time, kept in here for info */
|
||||||
|
printf("\rTremolo Sweep: %i, Rate: %i, Depth %i\n",
|
||||||
|
gus_patch[gus_ptr+49], gus_patch[gus_ptr+50], gus_patch[gus_ptr+51]);
|
||||||
|
printf("\rVibrato Sweep: %i, Rate: %i, Depth %i\n",
|
||||||
|
gus_patch[gus_ptr+52], gus_patch[gus_ptr+53], gus_patch[gus_ptr+54]);
|
||||||
|
#endif
|
||||||
|
gus_sample->modes = gus_patch[gus_ptr + 55];
|
||||||
|
GUSPAT_START_DEBUG(); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_16BIT, "16bit "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_UNSIGNED, "Unsigned "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_LOOP, "Loop "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_PINGPONG, "PingPong "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_REVERSE, "Reverse "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_SUSTAIN, "Sustain "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_ENVELOPE, "Envelope "); GUSPAT_MODE_DEBUG(gus_patch[gus_ptr+55], SAMPLE_CLAMPED, "Clamped "); GUSPAT_END_DEBUG();
|
||||||
|
|
||||||
|
if (gus_sample->loop_start > gus_sample->loop_end) {
|
||||||
|
tmp_loop = gus_sample->loop_end;
|
||||||
|
gus_sample->loop_end = gus_sample->loop_start;
|
||||||
|
gus_sample->loop_start = tmp_loop;
|
||||||
|
gus_sample->loop_fraction =
|
||||||
|
((gus_sample->loop_fraction & 0x0f) << 4)
|
||||||
|
| ((gus_sample->loop_fraction & 0xf0) >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FIXME: Experimental Hacky Fix
|
||||||
|
*/
|
||||||
|
if (fix_release) {
|
||||||
|
if (env_time_table[gus_patch[gus_ptr + 40]]
|
||||||
|
< env_time_table[gus_patch[gus_ptr + 41]]) {
|
||||||
|
unsigned char tmp_hack_rate = gus_patch[gus_ptr + 41];
|
||||||
|
gus_patch[gus_ptr + 41] = gus_patch[gus_ptr + 40];
|
||||||
|
gus_patch[gus_ptr + 40] = tmp_hack_rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
if (gus_sample->modes & SAMPLE_ENVELOPE) {
|
||||||
|
unsigned char env_rate = gus_patch[gus_ptr + 37 + i];
|
||||||
|
gus_sample->env_target[i] = 16448 * gus_patch[gus_ptr + 43 + i];
|
||||||
|
GUSPAT_INT_DEBUG("Envelope Level",gus_patch[gus_ptr+43+i]); GUSPAT_FLOAT_DEBUG("Envelope Time",env_time_table[env_rate]);
|
||||||
|
gus_sample->env_rate[i] = (signed long int) (4194303.0
|
||||||
|
/ ((float) _WM_SampleRate * env_time_table[env_rate]));
|
||||||
|
GUSPAT_INT_DEBUG("Envelope Rate",gus_sample->env_rate[i]); GUSPAT_INT_DEBUG("GUSPAT Rate",env_rate);
|
||||||
|
if (gus_sample->env_rate[i] == 0) {
|
||||||
|
_WM_ERROR_NEW("%s: Warning: found invalid envelope(%lu) rate setting in %s. Using %f instead.",
|
||||||
|
__FUNCTION__, i, filename, env_time_table[63]);
|
||||||
|
gus_sample->env_rate[i] = (signed long int) (4194303.0
|
||||||
|
/ ((float) _WM_SampleRate * env_time_table[63]));
|
||||||
|
GUSPAT_FLOAT_DEBUG("Envelope Time",env_time_table[63]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gus_sample->env_target[i] = 4194303;
|
||||||
|
gus_sample->env_rate[i] = (signed long int) (4194303.0
|
||||||
|
/ ((float) _WM_SampleRate * env_time_table[63]));
|
||||||
|
GUSPAT_FLOAT_DEBUG("Envelope Time",env_time_table[63]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gus_sample->env_target[6] = 0;
|
||||||
|
gus_sample->env_rate[6] = (signed long int) (4194303.0
|
||||||
|
/ ((float) _WM_SampleRate * env_time_table[63]));
|
||||||
|
|
||||||
|
gus_ptr += 96;
|
||||||
|
tmp_cnt = gus_sample->data_length;
|
||||||
|
|
||||||
|
if (do_convert[(((gus_sample->modes & 0x18) >> 1)
|
||||||
|
| (gus_sample->modes & 0x03))](&gus_patch[gus_ptr], gus_sample)
|
||||||
|
== -1) {
|
||||||
|
free(gus_patch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gus_ptr += tmp_cnt;
|
||||||
|
gus_sample->loop_start = (gus_sample->loop_start << 10)
|
||||||
|
| (((gus_sample->loop_fraction & 0x0f) << 10) / 16);
|
||||||
|
gus_sample->loop_end = (gus_sample->loop_end << 10)
|
||||||
|
| (((gus_sample->loop_fraction & 0xf0) << 6) / 16);
|
||||||
|
gus_sample->loop_size = gus_sample->loop_end - gus_sample->loop_start;
|
||||||
|
gus_sample->data_length = gus_sample->data_length << 10;
|
||||||
|
no_of_samples--;
|
||||||
|
}
|
||||||
|
free(gus_patch);
|
||||||
|
return first_gus_sample;
|
||||||
|
}
|
77
src/wildmidi/gus_pat.h
Normal file
77
src/wildmidi/gus_pat.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
gus_pat.h
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
Copyright (C) Chris Ison 2001-2011
|
||||||
|
Copyright (C) Bret Curtis 2013-2014
|
||||||
|
|
||||||
|
This file is part of WildMIDI.
|
||||||
|
|
||||||
|
WildMIDI is free software: you can redistribute and/or modify the player
|
||||||
|
under the terms of the GNU General Public License and you can redistribute
|
||||||
|
and/or modify the library under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3 of
|
||||||
|
the licenses, or(at your option) any later version.
|
||||||
|
|
||||||
|
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
|
||||||
|
the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with WildMIDI. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GUS_PAT_H
|
||||||
|
#define __GUS_PAT_H
|
||||||
|
|
||||||
|
/* Guspat Envelope Rate Timings */
|
||||||
|
|
||||||
|
static float env_time_table[] = {
|
||||||
|
/* Row 1 = (4095.0 / (x * ( 1.0 / (1.6 * 14.0) ))) / 1000000.0 */
|
||||||
|
0.0f, 0.091728000f, 0.045864000f, 0.030576000f, 0.022932000f, 0.018345600f, 0.015288000f, 0.013104000f,
|
||||||
|
0.011466000f, 0.010192000f, 0.009172800f, 0.008338909f, 0.007644000f, 0.007056000f, 0.006552000f, 0.006115200f,
|
||||||
|
0.005733000f, 0.005395765f, 0.005096000f, 0.004827789f, 0.004586400f, 0.004368000f, 0.004169455f, 0.003988174f,
|
||||||
|
0.003822000f, 0.003669120f, 0.003528000f, 0.003397333f, 0.003276000f, 0.003163034f, 0.003057600f, 0.002958968f,
|
||||||
|
0.002866500f, 0.002779636f, 0.002697882f, 0.002620800f, 0.002548000f, 0.002479135f, 0.002413895f, 0.002352000f,
|
||||||
|
0.002293200f, 0.002237268f, 0.002184000f, 0.002133209f, 0.002084727f, 0.002038400f, 0.001994087f, 0.001951660f,
|
||||||
|
0.001911000f, 0.001872000f, 0.001834560f, 0.001798588f, 0.001764000f, 0.001730717f, 0.001698667f, 0.001667782f,
|
||||||
|
0.001638000f, 0.001609263f, 0.001581517f, 0.001554712f, 0.001528800f, 0.001503738f, 0.001479484f, 0.001456000f,
|
||||||
|
|
||||||
|
/* Row 2 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 8.0 ))) / 1000000.0 */
|
||||||
|
0.0f, 0.733824000f, 0.366912000f, 0.244608000f, 0.183456000f, 0.146764800f, 0.122304000f, 0.104832000f,
|
||||||
|
0.091728000f, 0.081536000f, 0.073382400f, 0.066711273f, 0.061152000f, 0.056448000f, 0.052416000f, 0.048921600f,
|
||||||
|
0.045864000f, 0.043166118f, 0.040768000f, 0.038622316f, 0.036691200f, 0.034944000f, 0.033355636f, 0.031905391f,
|
||||||
|
0.030576000f, 0.029352960f, 0.028224000f, 0.027178667f, 0.026208000f, 0.025304276f, 0.024460800f, 0.023671742f,
|
||||||
|
0.022932000f, 0.022237091f, 0.021583059f, 0.020966400f, 0.020384000f, 0.019833081f, 0.019311158f, 0.018816000f,
|
||||||
|
0.018345600f, 0.017898146f, 0.017472000f, 0.017065674f, 0.016677818f, 0.016307200f, 0.015952696f, 0.015613277f,
|
||||||
|
0.015288000f, 0.014976000f, 0.014676480f, 0.014388706f, 0.014112000f, 0.013845736f, 0.013589333f, 0.013342255f,
|
||||||
|
0.013104000f, 0.012874105f, 0.012652138f, 0.012437695f, 0.012230400f, 0.012029902f, 0.011835871f, 0.011648000f,
|
||||||
|
|
||||||
|
/* Row 3 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 64.0 ))) / 1000000.0 */
|
||||||
|
0.0f, 5.870592000f, 2.935296000f, 1.956864000f, 1.467648000f, 1.174118400f, 0.978432000f, 0.838656000f,
|
||||||
|
0.733824000f, 0.652288000f, 0.587059200f, 0.533690182f, 0.489216000f, 0.451584000f, 0.419328000f, 0.391372800f,
|
||||||
|
0.366912000f, 0.345328941f, 0.326144000f, 0.308978526f, 0.293529600f, 0.279552000f, 0.266845091f, 0.255243130f,
|
||||||
|
0.244608000f, 0.234823680f, 0.225792000f, 0.217429333f, 0.209664000f, 0.202434207f, 0.195686400f, 0.189373935f,
|
||||||
|
0.183456000f, 0.177896727f, 0.172664471f, 0.167731200f, 0.163072000f, 0.158664649f, 0.154489263f, 0.150528000f,
|
||||||
|
0.146764800f, 0.143185171f, 0.139776000f, 0.136525395f, 0.133422545f, 0.130457600f, 0.127621565f, 0.124906213f,
|
||||||
|
0.122304000f, 0.119808000f, 0.117411840f, 0.115109647f, 0.112896000f, 0.110765887f, 0.108714667f, 0.106738036f,
|
||||||
|
0.104832000f, 0.102992842f, 0.101217103f, 0.099501559f, 0.097843200f, 0.096239213f, 0.094686968f, 0.093184000f,
|
||||||
|
|
||||||
|
/* Row 4 = (4095.0 / (x * ((1.0 / (1.6 * 14.0)) / 512.0))) / 1000000.0 */
|
||||||
|
0.0f, 46.964736000f,23.482368000f,15.654912000f,11.741184000f, 9.392947200f, 7.827456000f, 6.709248000f,
|
||||||
|
5.870592000f, 5.218304000f, 4.696473600f, 4.269521455f, 3.913728000f, 3.612672000f, 3.354624000f, 3.130982400f,
|
||||||
|
2.935296000f, 2.762631529f, 2.609152000f, 2.471828211f, 2.348236800f, 2.236416000f, 2.134760727f, 2.041945043f,
|
||||||
|
1.956864000f, 1.878589440f, 1.806336000f, 1.739434667f, 1.677312000f, 1.619473655f, 1.565491200f, 1.514991484f,
|
||||||
|
1.467648000f, 1.423173818f, 1.381315765f, 1.341849600f, 1.304576000f, 1.269317189f, 1.235914105f, 1.204224000f,
|
||||||
|
1.174118400f, 1.145481366f, 1.118208000f, 1.092203163f, 1.067380364f, 1.043660800f, 1.020972522f, 0.999249702f,
|
||||||
|
0.978432000f, 0.958464000f, 0.939294720f, 0.920877176f, 0.903168000f, 0.886127094f, 0.869717333f, 0.853904291f,
|
||||||
|
0.838656000f, 0.823942737f, 0.809736828f, 0.796012475f, 0.782745600f, 0.769913705f, 0.757495742f, 0.745472000f
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct _sample * _WM_load_gus_pat (const char *filename, int _fix_release);
|
||||||
|
|
||||||
|
#endif /* __GUS_PAT_H */
|
||||||
|
|
398
src/wildmidi/reverb.cpp
Normal file
398
src/wildmidi/reverb.cpp
Normal file
|
@ -0,0 +1,398 @@
|
||||||
|
/*
|
||||||
|
reverb.c
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
Copyright (C) Chris Ison 2001-2011
|
||||||
|
Copyright (C) Bret Curtis 2013-2014
|
||||||
|
|
||||||
|
This file is part of WildMIDI.
|
||||||
|
|
||||||
|
WildMIDI is free software: you can redistribute and/or modify the player
|
||||||
|
under the terms of the GNU General Public License and you can redistribute
|
||||||
|
and/or modify the library under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3 of
|
||||||
|
the licenses, or(at your option) any later version.
|
||||||
|
|
||||||
|
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
|
||||||
|
the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with WildMIDI. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include "config.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "reverb.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
reverb function
|
||||||
|
*/
|
||||||
|
void _WM_reset_reverb(struct _rvb *rvb) {
|
||||||
|
int i, j, k;
|
||||||
|
for (i = 0; i < rvb->l_buf_size; i++) {
|
||||||
|
rvb->l_buf[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < rvb->r_buf_size; i++) {
|
||||||
|
rvb->r_buf[i] = 0;
|
||||||
|
}
|
||||||
|
for (k = 0; k < 8; k++) {
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
for (j = 0; j < 2; j++) {
|
||||||
|
rvb->l_buf_flt_in[k][i][j] = 0;
|
||||||
|
rvb->l_buf_flt_out[k][i][j] = 0;
|
||||||
|
rvb->r_buf_flt_in[k][i][j] = 0;
|
||||||
|
rvb->r_buf_flt_out[k][i][j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
_WM_init_reverb
|
||||||
|
|
||||||
|
=========================
|
||||||
|
Engine Description
|
||||||
|
|
||||||
|
8 reflective points around the room
|
||||||
|
2 speaker positions
|
||||||
|
1 listener position
|
||||||
|
|
||||||
|
Sounds come from the speakers to all points and to the listener.
|
||||||
|
Sound comes from the reflective points to the listener.
|
||||||
|
These sounds are combined, put through a filter that mimics surface absorbtion.
|
||||||
|
The combined sounds are also sent to the reflective points on the opposite side.
|
||||||
|
|
||||||
|
*/
|
||||||
|
struct _rvb *
|
||||||
|
_WM_init_reverb(int rate, float room_x, float room_y, float listen_x,
|
||||||
|
float listen_y) {
|
||||||
|
|
||||||
|
/* filters set at 125Hz, 250Hz, 500Hz, 1000Hz, 2000Hz, 4000Hz */
|
||||||
|
double Freq[] = {125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0};
|
||||||
|
|
||||||
|
/* numbers calculated from
|
||||||
|
* 101.325 kPa, 20 deg C, 50% relative humidity */
|
||||||
|
double dbAirAbs[] = {-0.00044, -0.00131, -0.002728, -0.004665, -0.009887, -0.029665};
|
||||||
|
|
||||||
|
/* modify these to adjust the absorption qualities of the surface.
|
||||||
|
* Remember that lower frequencies are less effected by surfaces
|
||||||
|
* Note: I am currently playing with the values and finding the ideal surfaces
|
||||||
|
* for nice default reverb.
|
||||||
|
*/
|
||||||
|
double dbAttn[8][6] = {
|
||||||
|
{-1.839, -6.205, -8.891, -12.059, -15.935, -20.942},
|
||||||
|
{-0.131, -6.205, -12.059, -20.933, -20.933, -15.944},
|
||||||
|
{-0.131, -6.205, -12.059, -20.933, -20.933, -15.944},
|
||||||
|
{-1.839, -6.205, -8.891, -12.059, -15.935, -20.942},
|
||||||
|
{-1.839, -6.205, -8.891, -12.059, -15.935, -20.942},
|
||||||
|
{-0.131, -6.205, -12.059, -20.933, -20.933, -15.944},
|
||||||
|
{-0.131, -6.205, -12.059, -20.933, -20.933, -15.944},
|
||||||
|
{-1.839, -6.205, -8.891, -12.059, -15.935, -20.942}
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
double dbAttn[6] = {
|
||||||
|
// concrete covered in carpet
|
||||||
|
// -0.175, -0.537, -1.412, -4.437, -7.959, -7.959
|
||||||
|
// pleated drapes
|
||||||
|
-0.630, -3.223, -5.849, -12.041, -10.458, -7.959
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* distance */
|
||||||
|
double SPL_DST[8] = {0.0};
|
||||||
|
double SPR_DST[8] = {0.0};
|
||||||
|
double RFN_DST[8] = {0.0};
|
||||||
|
|
||||||
|
double MAXL_DST = 0.0;
|
||||||
|
double MAXR_DST = 0.0;
|
||||||
|
|
||||||
|
double SPL_LSN_XOFS = 0.0;
|
||||||
|
double SPL_LSN_YOFS = 0.0;
|
||||||
|
double SPL_LSN_DST = 0.0;
|
||||||
|
|
||||||
|
double SPR_LSN_XOFS = 0.0;
|
||||||
|
double SPR_LSN_YOFS = 0.0;
|
||||||
|
double SPR_LSN_DST = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
struct _rvb *rtn_rvb = (struct _rvb*)malloc(sizeof(struct _rvb));
|
||||||
|
int j = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
struct _coord {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct _coord SPL = {2.5, 5.0}; /* Left Speaker Position */
|
||||||
|
struct _coord SPR = {7.5, 5.0}; /* Right Speaker Position */
|
||||||
|
/* position of the reflective points */
|
||||||
|
struct _coord RFN[] = {
|
||||||
|
{ 5.0, 0.0},
|
||||||
|
{ 0.0, 6.66666},
|
||||||
|
{ 0.0, 13.3333},
|
||||||
|
{ 5.0, 20.0},
|
||||||
|
{ 10.0, 20.0},
|
||||||
|
{ 15.0, 13.3333},
|
||||||
|
{ 15.0, 6.66666},
|
||||||
|
{ 10.0, 0.0}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct _coord SPL; /* Left Speaker Position */
|
||||||
|
struct _coord SPR; /* Right Speaker Position */
|
||||||
|
/* position of the reflective points */
|
||||||
|
struct _coord RFN[8];
|
||||||
|
|
||||||
|
SPL.x = room_x / 4.0;
|
||||||
|
SPR.x = room_x / 4.0 * 3.0;
|
||||||
|
SPL.y = room_y / 10.0;
|
||||||
|
SPR.y = room_y / 10.0;
|
||||||
|
|
||||||
|
RFN[0].x = room_x / 3.0;
|
||||||
|
RFN[0].y = 0.0;
|
||||||
|
RFN[1].x = 0.0;
|
||||||
|
RFN[1].y = room_y / 3.0;
|
||||||
|
RFN[2].x = 0.0;
|
||||||
|
RFN[2].y = room_y / 3.0 * 2.0;
|
||||||
|
RFN[3].x = room_x / 3.0;
|
||||||
|
RFN[3].y = room_y;
|
||||||
|
RFN[4].x = room_x / 3.0 * 2.0;
|
||||||
|
RFN[4].y = room_y;
|
||||||
|
RFN[5].x = room_x;
|
||||||
|
RFN[5].y = room_y / 3.0 * 2.0;
|
||||||
|
RFN[6].x = room_x;
|
||||||
|
RFN[6].y = room_y / 3.0;
|
||||||
|
RFN[7].x = room_x / 3.0 * 2.0;
|
||||||
|
RFN[7].y = 0.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPL_LSN_XOFS = SPL.x - listen_x;
|
||||||
|
SPL_LSN_YOFS = SPL.y - listen_y;
|
||||||
|
SPL_LSN_DST = sqrt((SPL_LSN_XOFS * SPL_LSN_XOFS) + (SPL_LSN_YOFS * SPL_LSN_YOFS));
|
||||||
|
|
||||||
|
if (SPL_LSN_DST > MAXL_DST)
|
||||||
|
MAXL_DST = SPL_LSN_DST;
|
||||||
|
|
||||||
|
SPR_LSN_XOFS = SPR.x - listen_x;
|
||||||
|
SPR_LSN_YOFS = SPR.y - listen_y;
|
||||||
|
SPR_LSN_DST = sqrt((SPR_LSN_XOFS * SPR_LSN_XOFS) + (SPR_LSN_YOFS * SPR_LSN_YOFS));
|
||||||
|
|
||||||
|
if (SPR_LSN_DST > MAXR_DST)
|
||||||
|
MAXR_DST = SPR_LSN_DST;
|
||||||
|
|
||||||
|
if (rtn_rvb == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
double SPL_RFL_XOFS = 0;
|
||||||
|
double SPL_RFL_YOFS = 0;
|
||||||
|
double SPR_RFL_XOFS = 0;
|
||||||
|
double SPR_RFL_YOFS = 0;
|
||||||
|
double RFN_XOFS = listen_x - RFN[j].x;
|
||||||
|
double RFN_YOFS = listen_y - RFN[j].y;
|
||||||
|
RFN_DST[j] = sqrt((RFN_XOFS * RFN_XOFS) + (RFN_YOFS * RFN_YOFS));
|
||||||
|
|
||||||
|
SPL_RFL_XOFS = SPL.x - RFN[i].x;
|
||||||
|
SPL_RFL_YOFS = SPL.y - RFN[i].y;
|
||||||
|
SPR_RFL_XOFS = SPR.x - RFN[i].x;
|
||||||
|
SPR_RFL_YOFS = SPR.y - RFN[i].y;
|
||||||
|
SPL_DST[i] = sqrt(
|
||||||
|
(SPL_RFL_XOFS * SPL_RFL_XOFS) + (SPL_RFL_YOFS * SPL_RFL_YOFS));
|
||||||
|
SPR_DST[i] = sqrt(
|
||||||
|
(SPR_RFL_XOFS * SPR_RFL_XOFS) + (SPR_RFL_YOFS * SPR_RFL_YOFS));
|
||||||
|
/*
|
||||||
|
add the 2 distances together and remove the speaker to listener distance
|
||||||
|
so we dont have to delay the initial output
|
||||||
|
*/
|
||||||
|
SPL_DST[i] += RFN_DST[i];
|
||||||
|
|
||||||
|
/* so i dont have to delay speaker output */
|
||||||
|
SPL_DST[i] -= SPL_LSN_DST;
|
||||||
|
|
||||||
|
if (i < 4) {
|
||||||
|
if (SPL_DST[i] > MAXL_DST)
|
||||||
|
MAXL_DST = SPL_DST[i];
|
||||||
|
} else {
|
||||||
|
if (SPL_DST[i] > MAXR_DST)
|
||||||
|
MAXR_DST = SPL_DST[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
SPR_DST[i] += RFN_DST[i];
|
||||||
|
|
||||||
|
/* so i dont have to delay speaker output */
|
||||||
|
SPR_DST[i] -= SPR_LSN_DST;
|
||||||
|
|
||||||
|
if (i < 4) {
|
||||||
|
if (SPR_DST[i] > MAXL_DST)
|
||||||
|
MAXL_DST = SPR_DST[i];
|
||||||
|
} else {
|
||||||
|
if (SPR_DST[i] > MAXR_DST)
|
||||||
|
MAXR_DST = SPR_DST[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
RFN_DST[j] *= 2.0;
|
||||||
|
|
||||||
|
if (j < 4) {
|
||||||
|
if (RFN_DST[j] > MAXL_DST)
|
||||||
|
MAXL_DST = RFN_DST[j];
|
||||||
|
} else {
|
||||||
|
if (RFN_DST[j] > MAXR_DST)
|
||||||
|
MAXR_DST = RFN_DST[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
double srate = (double) rate;
|
||||||
|
double bandwidth = 2.0;
|
||||||
|
double omega = 2.0 * M_PI * Freq[i] / srate;
|
||||||
|
double sn = sin(omega);
|
||||||
|
double cs = cos(omega);
|
||||||
|
double alpha = sn * sinh(M_LN2 / 2 * bandwidth * omega / sn);
|
||||||
|
double A = pow(10.0, ((/*dbAttn[i]*/dbAttn[j][i] +
|
||||||
|
(dbAirAbs[i] * RFN_DST[j])) / 40.0) );
|
||||||
|
/*
|
||||||
|
Peaking band EQ filter
|
||||||
|
*/
|
||||||
|
double b0 = 1 + (alpha * A);
|
||||||
|
double b1 = -2 * cs;
|
||||||
|
double b2 = 1 - (alpha * A);
|
||||||
|
double a0 = 1 + (alpha / A);
|
||||||
|
double a1 = -2 * cs;
|
||||||
|
double a2 = 1 - (alpha / A);
|
||||||
|
|
||||||
|
rtn_rvb->coeff[j][i][0] = (signed int) ((b0 / a0) * 1024.0);
|
||||||
|
rtn_rvb->coeff[j][i][1] = (signed int) ((b1 / a0) * 1024.0);
|
||||||
|
rtn_rvb->coeff[j][i][2] = (signed int) ((b2 / a0) * 1024.0);
|
||||||
|
rtn_rvb->coeff[j][i][3] = (signed int) ((a1 / a0) * 1024.0);
|
||||||
|
rtn_rvb->coeff[j][i][4] = (signed int) ((a2 / a0) * 1024.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init the reverb buffers */
|
||||||
|
rtn_rvb->l_buf_size = (int) ((float) rate * (MAXL_DST / 340.29));
|
||||||
|
rtn_rvb->l_buf = (int*)malloc(
|
||||||
|
sizeof(signed int) * (rtn_rvb->l_buf_size + 1));
|
||||||
|
rtn_rvb->l_out = 0;
|
||||||
|
|
||||||
|
rtn_rvb->r_buf_size = (int) ((float) rate * (MAXR_DST / 340.29));
|
||||||
|
rtn_rvb->r_buf = (int*)malloc(
|
||||||
|
sizeof(signed int) * (rtn_rvb->r_buf_size + 1));
|
||||||
|
rtn_rvb->r_out = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
rtn_rvb->l_sp_in[i] = (int) ((float) rate * (SPL_DST[i] / 340.29));
|
||||||
|
rtn_rvb->l_sp_in[i + 4] = (int) ((float) rate
|
||||||
|
* (SPL_DST[i + 4] / 340.29));
|
||||||
|
rtn_rvb->r_sp_in[i] = (int) ((float) rate * (SPR_DST[i] / 340.29));
|
||||||
|
rtn_rvb->r_sp_in[i + 4] = (int) ((float) rate
|
||||||
|
* (SPR_DST[i + 4] / 340.29));
|
||||||
|
rtn_rvb->l_in[i] = (int) ((float) rate * (RFN_DST[i] / 340.29));
|
||||||
|
rtn_rvb->r_in[i] = (int) ((float) rate * (RFN_DST[i + 4] / 340.29));
|
||||||
|
}
|
||||||
|
|
||||||
|
rtn_rvb->gain = 4;
|
||||||
|
|
||||||
|
_WM_reset_reverb(rtn_rvb);
|
||||||
|
return rtn_rvb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _WM_free_reverb - free up memory used for reverb */
|
||||||
|
void _WM_free_reverb(struct _rvb *rvb) {
|
||||||
|
if (!rvb) return;
|
||||||
|
free(rvb->l_buf);
|
||||||
|
free(rvb->r_buf);
|
||||||
|
free(rvb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _WM_do_reverb(struct _rvb *rvb, signed int *buffer, int size) {
|
||||||
|
int i, j, k;
|
||||||
|
signed int l_buf_flt = 0;
|
||||||
|
signed int r_buf_flt = 0;
|
||||||
|
signed int l_rfl = 0;
|
||||||
|
signed int r_rfl = 0;
|
||||||
|
int vol_div = 64;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i += 2) {
|
||||||
|
signed int tmp_l_val = 0;
|
||||||
|
signed int tmp_r_val = 0;
|
||||||
|
/*
|
||||||
|
add the initial reflections
|
||||||
|
from each speaker, 4 to go the left, 4 go to the right buffers
|
||||||
|
*/
|
||||||
|
tmp_l_val = buffer[i] / vol_div;
|
||||||
|
tmp_r_val = buffer[i + 1] / vol_div;
|
||||||
|
for (j = 0; j < 4; j++) {
|
||||||
|
rvb->l_buf[rvb->l_sp_in[j]] += tmp_l_val;
|
||||||
|
rvb->l_sp_in[j] = (rvb->l_sp_in[j] + 1) % rvb->l_buf_size;
|
||||||
|
rvb->l_buf[rvb->r_sp_in[j]] += tmp_r_val;
|
||||||
|
rvb->r_sp_in[j] = (rvb->r_sp_in[j] + 1) % rvb->l_buf_size;
|
||||||
|
|
||||||
|
rvb->r_buf[rvb->l_sp_in[j + 4]] += tmp_l_val;
|
||||||
|
rvb->l_sp_in[j + 4] = (rvb->l_sp_in[j + 4] + 1) % rvb->r_buf_size;
|
||||||
|
rvb->r_buf[rvb->r_sp_in[j + 4]] += tmp_r_val;
|
||||||
|
rvb->r_sp_in[j + 4] = (rvb->r_sp_in[j + 4] + 1) % rvb->r_buf_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
filter the reverb output and add to buffer
|
||||||
|
*/
|
||||||
|
l_rfl = rvb->l_buf[rvb->l_out];
|
||||||
|
rvb->l_buf[rvb->l_out] = 0;
|
||||||
|
rvb->l_out = (rvb->l_out + 1) % rvb->l_buf_size;
|
||||||
|
|
||||||
|
r_rfl = rvb->r_buf[rvb->r_out];
|
||||||
|
rvb->r_buf[rvb->r_out] = 0;
|
||||||
|
rvb->r_out = (rvb->r_out + 1) % rvb->r_buf_size;
|
||||||
|
|
||||||
|
for (k = 0; k < 8; k++) {
|
||||||
|
for (j = 0; j < 6; j++) {
|
||||||
|
l_buf_flt = ((l_rfl * rvb->coeff[k][j][0])
|
||||||
|
+ (rvb->l_buf_flt_in[k][j][0] * rvb->coeff[k][j][1])
|
||||||
|
+ (rvb->l_buf_flt_in[k][j][1] * rvb->coeff[k][j][2])
|
||||||
|
- (rvb->l_buf_flt_out[k][j][0] * rvb->coeff[k][j][3])
|
||||||
|
- (rvb->l_buf_flt_out[k][j][1] * rvb->coeff[k][j][4]))
|
||||||
|
/ 1024;
|
||||||
|
rvb->l_buf_flt_in[k][j][1] = rvb->l_buf_flt_in[k][j][0];
|
||||||
|
rvb->l_buf_flt_in[k][j][0] = l_rfl;
|
||||||
|
rvb->l_buf_flt_out[k][j][1] = rvb->l_buf_flt_out[k][j][0];
|
||||||
|
rvb->l_buf_flt_out[k][j][0] = l_buf_flt;
|
||||||
|
buffer[i] += l_buf_flt / 8;
|
||||||
|
|
||||||
|
r_buf_flt = ((r_rfl * rvb->coeff[k][j][0])
|
||||||
|
+ (rvb->r_buf_flt_in[k][j][0] * rvb->coeff[k][j][1])
|
||||||
|
+ (rvb->r_buf_flt_in[k][j][1] * rvb->coeff[k][j][2])
|
||||||
|
- (rvb->r_buf_flt_out[k][j][0] * rvb->coeff[k][j][3])
|
||||||
|
- (rvb->r_buf_flt_out[k][j][1] * rvb->coeff[k][j][4]))
|
||||||
|
/ 1024;
|
||||||
|
rvb->r_buf_flt_in[k][j][1] = rvb->r_buf_flt_in[k][j][0];
|
||||||
|
rvb->r_buf_flt_in[k][j][0] = r_rfl;
|
||||||
|
rvb->r_buf_flt_out[k][j][1] = rvb->r_buf_flt_out[k][j][0];
|
||||||
|
rvb->r_buf_flt_out[k][j][0] = r_buf_flt;
|
||||||
|
buffer[i + 1] += r_buf_flt / 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
add filtered result back into the buffers but on the opposite side
|
||||||
|
*/
|
||||||
|
tmp_l_val = buffer[i + 1] / vol_div;
|
||||||
|
tmp_r_val = buffer[i] / vol_div;
|
||||||
|
for (j = 0; j < 4; j++) {
|
||||||
|
rvb->l_buf[rvb->l_in[j]] += tmp_l_val;
|
||||||
|
rvb->l_in[j] = (rvb->l_in[j] + 1) % rvb->l_buf_size;
|
||||||
|
|
||||||
|
rvb->r_buf[rvb->r_in[j]] += tmp_r_val;
|
||||||
|
rvb->r_in[j] = (rvb->r_in[j] + 1) % rvb->r_buf_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
57
src/wildmidi/reverb.h
Normal file
57
src/wildmidi/reverb.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
reverb.h
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
Copyright (C) Chris Ison 2001-2011
|
||||||
|
Copyright (C) Bret Curtis 2013-2014
|
||||||
|
|
||||||
|
This file is part of WildMIDI.
|
||||||
|
|
||||||
|
WildMIDI is free software: you can redistribute and/or modify the player
|
||||||
|
under the terms of the GNU General Public License and you can redistribute
|
||||||
|
and/or modify the library under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3 of
|
||||||
|
the licenses, or(at your option) any later version.
|
||||||
|
|
||||||
|
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
|
||||||
|
the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with WildMIDI. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __REVERB_H
|
||||||
|
#define __REVERB_H
|
||||||
|
|
||||||
|
struct _rvb {
|
||||||
|
/* filter data */
|
||||||
|
signed int l_buf_flt_in[8][6][2];
|
||||||
|
signed int l_buf_flt_out[8][6][2];
|
||||||
|
signed int r_buf_flt_in[8][6][2];
|
||||||
|
signed int r_buf_flt_out[8][6][2];
|
||||||
|
signed int coeff[8][6][5];
|
||||||
|
/* buffer data */
|
||||||
|
signed int *l_buf;
|
||||||
|
signed int *r_buf;
|
||||||
|
int l_buf_size;
|
||||||
|
int r_buf_size;
|
||||||
|
int l_out;
|
||||||
|
int r_out;
|
||||||
|
int l_sp_in[8];
|
||||||
|
int r_sp_in[8];
|
||||||
|
int l_in[4];
|
||||||
|
int r_in[4];
|
||||||
|
int gain;
|
||||||
|
unsigned long int max_reverb_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void _WM_reset_reverb (struct _rvb *rvb);
|
||||||
|
extern struct _rvb *_WM_init_reverb(int rate, float room_x, float room_y, float listen_x, float listen_y);
|
||||||
|
extern void _WM_free_reverb (struct _rvb *rvb);
|
||||||
|
extern void _WM_do_reverb (struct _rvb *rvb, signed int *buffer, int size);
|
||||||
|
|
||||||
|
#endif /* __REVERB_H */
|
3005
src/wildmidi/wildmidi_lib.cpp
Normal file
3005
src/wildmidi/wildmidi_lib.cpp
Normal file
File diff suppressed because it is too large
Load diff
87
src/wildmidi/wildmidi_lib.h
Normal file
87
src/wildmidi/wildmidi_lib.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
wildmidi_lib.h
|
||||||
|
|
||||||
|
Midi Wavetable Processing library
|
||||||
|
|
||||||
|
Copyright (C) Chris Ison 2001-2011
|
||||||
|
Copyright (C) Bret Curtis 2013-2014
|
||||||
|
|
||||||
|
This file is part of WildMIDI.
|
||||||
|
|
||||||
|
WildMIDI is free software: you can redistribute and/or modify the player
|
||||||
|
under the terms of the GNU General Public License and you can redistribute
|
||||||
|
and/or modify the library under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3 of
|
||||||
|
the licenses, or(at your option) any later version.
|
||||||
|
|
||||||
|
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
|
||||||
|
the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with WildMIDI. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WILDMIDI_LIB_H
|
||||||
|
#define WILDMIDI_LIB_H
|
||||||
|
|
||||||
|
#define WM_MO_LOG_VOLUME 0x0001
|
||||||
|
#define WM_MO_ENHANCED_RESAMPLING 0x0002
|
||||||
|
#define WM_MO_REVERB 0x0004
|
||||||
|
#define WM_MO_WHOLETEMPO 0x8000
|
||||||
|
#define WM_MO_ROUNDTEMPO 0x2000
|
||||||
|
|
||||||
|
#define WM_GS_VERSION 0x0001
|
||||||
|
|
||||||
|
#define WM_SYMBOL // we do not need this in ZDoom
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _WM_Info {
|
||||||
|
char *copyright;
|
||||||
|
unsigned long int current_sample;
|
||||||
|
unsigned long int approx_total_samples;
|
||||||
|
unsigned short int mixer_options;
|
||||||
|
unsigned long int total_midi_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void midi;
|
||||||
|
|
||||||
|
WM_SYMBOL const char * WildMidi_GetString (unsigned short int info);
|
||||||
|
WM_SYMBOL int WildMidi_Init (const char * config_file, unsigned short int rate, unsigned short int options);
|
||||||
|
WM_SYMBOL int WildMidi_MasterVolume (unsigned char master_volume);
|
||||||
|
WM_SYMBOL int WildMidi_SetOption (midi * handle, unsigned short int options, unsigned short int setting);
|
||||||
|
WM_SYMBOL int WildMidi_Close (midi * handle);
|
||||||
|
WM_SYMBOL int WildMidi_Shutdown (void);
|
||||||
|
WM_SYMBOL int WildMidi_GetSampleRate (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
class WildMidi_Renderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WildMidi_Renderer();
|
||||||
|
~WildMidi_Renderer();
|
||||||
|
|
||||||
|
void ShortEvent(int status, int parm1, int parm2);
|
||||||
|
void LongEvent(const unsigned char *data, int len);
|
||||||
|
void ComputeOutput(float *buffer, int len);
|
||||||
|
void LoadInstrument(int bank, int percussion, int instr);
|
||||||
|
int GetVoiceCount();
|
||||||
|
void SetOption(int opt, int set);
|
||||||
|
private:
|
||||||
|
void *handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* WILDMIDI_LIB_H */
|
||||||
|
|
86
src/wildmidi/wm_error.cpp
Normal file
86
src/wildmidi/wm_error.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
wm_error.c
|
||||||
|
error reporting
|
||||||
|
|
||||||
|
Copyright (C) Chris Ison 2001-2011
|
||||||
|
Copyright (C) Bret Curtis 2013-2014
|
||||||
|
|
||||||
|
This file is part of WildMIDI.
|
||||||
|
|
||||||
|
WildMIDI is free software: you can redistribute and/or modify the player
|
||||||
|
under the terms of the GNU General Public License and you can redistribute
|
||||||
|
and/or modify the library under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3 of
|
||||||
|
the licenses, or(at your option) any later version.
|
||||||
|
|
||||||
|
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
|
||||||
|
the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with WildMIDI. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "wm_error.h"
|
||||||
|
#include "doomtype.h"
|
||||||
|
#include "v_text.h"
|
||||||
|
|
||||||
|
void _WM_ERROR_NEW(const char * wmfmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
fprintf(stderr, "\r");
|
||||||
|
va_start(args, wmfmt);
|
||||||
|
vfprintf(stderr, wmfmt, args);
|
||||||
|
va_end(args);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _WM_ERROR(const char * func, unsigned int lne, int wmerno,
|
||||||
|
const char * wmfor, int error) {
|
||||||
|
|
||||||
|
static const char *errors[WM_ERR_MAX+1] = {
|
||||||
|
"No error",
|
||||||
|
"Unable to obtain memory",
|
||||||
|
"Unable to stat",
|
||||||
|
"Unable to load",
|
||||||
|
"Unable to open",
|
||||||
|
"Unable to read",
|
||||||
|
"Invalid or Unsuported file format",
|
||||||
|
"File corrupt",
|
||||||
|
"Library not Initialized",
|
||||||
|
"Invalid argument",
|
||||||
|
"Library Already Initialized",
|
||||||
|
"Not a midi file",
|
||||||
|
"Refusing to load unusually long file",
|
||||||
|
|
||||||
|
"Invalid error code"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (wmerno < 0 || wmerno > WM_ERR_MAX)
|
||||||
|
wmerno = WM_ERR_MAX;
|
||||||
|
|
||||||
|
if (wmfor != NULL) {
|
||||||
|
if (error != 0) {
|
||||||
|
Printf(TEXTCOLOR_RED "libWildMidi(%s:%u): ERROR %s %s (%s)\n", func,
|
||||||
|
lne, errors[wmerno], wmfor, strerror(error));
|
||||||
|
} else {
|
||||||
|
Printf(TEXTCOLOR_RED "libWildMidi(%s:%u): ERROR %s %s\n", func, lne,
|
||||||
|
errors[wmerno], wmfor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (error != 0) {
|
||||||
|
Printf(TEXTCOLOR_RED "libWildMidi(%s:%u): ERROR %s (%s)\n", func, lne,
|
||||||
|
errors[wmerno], strerror(error));
|
||||||
|
} else {
|
||||||
|
Printf(TEXTCOLOR_RED "libWildMidi(%s:%u): ERROR %s\n", func, lne,
|
||||||
|
errors[wmerno]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
56
src/wildmidi/wm_error.h
Normal file
56
src/wildmidi/wm_error.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
wm_error.h
|
||||||
|
|
||||||
|
error reporting
|
||||||
|
|
||||||
|
Copyright (C) Chris Ison 2001-2011
|
||||||
|
Copyright (C) Bret Curtis 2013-2014
|
||||||
|
|
||||||
|
This file is part of WildMIDI.
|
||||||
|
|
||||||
|
WildMIDI is free software: you can redistribute and/or modify the player
|
||||||
|
under the terms of the GNU General Public License and you can redistribute
|
||||||
|
and/or modify the library under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation, either version 3 of
|
||||||
|
the licenses, or(at your option) any later version.
|
||||||
|
|
||||||
|
WildMIDI is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
|
||||||
|
the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and the
|
||||||
|
GNU Lesser General Public License along with WildMIDI. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __WM_ERROR_H
|
||||||
|
#define __WM_ERROR_H
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WM_ERR_NONE = 0,
|
||||||
|
WM_ERR_MEM,
|
||||||
|
WM_ERR_STAT,
|
||||||
|
WM_ERR_LOAD,
|
||||||
|
WM_ERR_OPEN,
|
||||||
|
WM_ERR_READ,
|
||||||
|
WM_ERR_INVALID,
|
||||||
|
WM_ERR_CORUPT,
|
||||||
|
WM_ERR_NOT_INIT,
|
||||||
|
WM_ERR_INVALID_ARG,
|
||||||
|
WM_ERR_ALR_INIT,
|
||||||
|
WM_ERR_NOT_MIDI,
|
||||||
|
WM_ERR_LONGFIL,
|
||||||
|
|
||||||
|
WM_ERR_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void _WM_ERROR_NEW(const char * wmfmt, ...)
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__attribute__((format(printf, 1, 2)))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
extern void _WM_ERROR(const char * func, unsigned int lne, int wmerno,
|
||||||
|
const char * wmfor, int error);
|
||||||
|
|
||||||
|
#endif /* __WM_ERROR_H */
|
|
@ -1726,3 +1726,36 @@ FString I_GetLongPathName(FString shortpath)
|
||||||
delete[] buff;
|
delete[] buff;
|
||||||
return longpath;
|
return longpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _MSC_VER == 1900 && defined(_USING_V110_SDK71_)
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// VS14Stat
|
||||||
|
//
|
||||||
|
// Work around an issue where stat doesn't work with v140_xp. This was
|
||||||
|
// supposedly fixed, but as of Update 1 continues to not function on XP.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
int VS14Stat(const char *path, struct _stat64i32 *buffer)
|
||||||
|
{
|
||||||
|
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||||
|
if(!GetFileAttributesEx(path, GetFileExInfoStandard, &data))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
buffer->st_ino = 0;
|
||||||
|
buffer->st_mode = ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR : S_IFREG)|
|
||||||
|
((data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD|S_IWRITE);
|
||||||
|
buffer->st_dev = buffer->st_rdev = 0;
|
||||||
|
buffer->st_nlink = 1;
|
||||||
|
buffer->st_uid = 0;
|
||||||
|
buffer->st_gid = 0;
|
||||||
|
buffer->st_size = data.nFileSizeLow;
|
||||||
|
buffer->st_atime = (*(QWORD*)&data.ftLastAccessTime) / 10000000 - 11644473600LL;
|
||||||
|
buffer->st_mtime = (*(QWORD*)&data.ftLastWriteTime) / 10000000 - 11644473600LL;
|
||||||
|
buffer->st_ctime = (*(QWORD*)&data.ftCreationTime) / 10000000 - 11644473600LL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -3105,6 +3105,7 @@ struct lemon *lemp;
|
||||||
FILE *in;
|
FILE *in;
|
||||||
char *tpltname;
|
char *tpltname;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
Boolean tpltnameinbuf;
|
||||||
|
|
||||||
cp = strrchr(lemp->filename,'.');
|
cp = strrchr(lemp->filename,'.');
|
||||||
if( cp ){
|
if( cp ){
|
||||||
|
@ -3114,10 +3115,13 @@ struct lemon *lemp;
|
||||||
}
|
}
|
||||||
if( access(buf,004)==0 ){
|
if( access(buf,004)==0 ){
|
||||||
tpltname = buf;
|
tpltname = buf;
|
||||||
|
tpltnameinbuf = LEMON_TRUE;
|
||||||
}else if( access(templatename,004)==0 ){
|
}else if( access(templatename,004)==0 ){
|
||||||
tpltname = templatename;
|
tpltname = templatename;
|
||||||
|
tpltnameinbuf = LEMON_TRUE;
|
||||||
}else{
|
}else{
|
||||||
tpltname = pathsearch(lemp->argv0,templatename,0);
|
tpltname = pathsearch(lemp->argv0,templatename,0);
|
||||||
|
tpltnameinbuf = LEMON_FALSE;
|
||||||
}
|
}
|
||||||
if( tpltname==0 ){
|
if( tpltname==0 ){
|
||||||
fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
|
fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
|
||||||
|
@ -3128,11 +3132,11 @@ struct lemon *lemp;
|
||||||
in = fopen(tpltname,"rb");
|
in = fopen(tpltname,"rb");
|
||||||
if( in==0 ){
|
if( in==0 ){
|
||||||
fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
|
fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
|
||||||
free(tpltname);
|
if (tpltnameinbuf == LEMON_FALSE) free(tpltname);
|
||||||
lemp->errorcnt++;
|
lemp->errorcnt++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
free(tpltname);
|
if (tpltnameinbuf == LEMON_FALSE) free(tpltname);
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -305,6 +305,7 @@ ACTOR Actor native //: Thinker
|
||||||
action native A_SetRipperLevel(int level);
|
action native A_SetRipperLevel(int level);
|
||||||
action native A_SetRipMin(int min);
|
action native A_SetRipMin(int min);
|
||||||
action native A_SetRipMax(int max);
|
action native A_SetRipMax(int max);
|
||||||
|
action native A_CheckProximity(state jump, class<Actor> classname, float distance, int count = 1, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||||
action native A_CheckBlock(state block, int flags = 0, int ptr = AAPTR_DEFAULT);
|
action native A_CheckBlock(state block, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||||
action native A_CheckSightOrRange(float distance, state label, bool two_dimension = false);
|
action native A_CheckSightOrRange(float distance, state label, bool two_dimension = false);
|
||||||
action native A_CheckRange(float distance, state label, bool two_dimension = false);
|
action native A_CheckRange(float distance, state label, bool two_dimension = false);
|
||||||
|
|
|
@ -129,6 +129,10 @@ const int WRF_NOFIRE = WRF_NOPRIMARY | WRF_NOSECONDARY;
|
||||||
const int WRF_ALLOWRELOAD = 16;
|
const int WRF_ALLOWRELOAD = 16;
|
||||||
const int WRF_ALLOWZOOM = 32;
|
const int WRF_ALLOWZOOM = 32;
|
||||||
const int WRF_DISABLESWITCH = 64;
|
const int WRF_DISABLESWITCH = 64;
|
||||||
|
const int WRF_ALLOWUSER1 = 128;
|
||||||
|
const int WRF_ALLOWUSER2 = 256;
|
||||||
|
const int WRF_ALLOWUSER3 = 512;
|
||||||
|
const int WRF_ALLOWUSER4 = 1024;
|
||||||
|
|
||||||
// Morph constants
|
// Morph constants
|
||||||
const int MRF_ADDSTAMINA = 1;
|
const int MRF_ADDSTAMINA = 1;
|
||||||
|
@ -484,6 +488,17 @@ enum
|
||||||
QF_WAVE = 1 << 5,
|
QF_WAVE = 1 << 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A_CheckProximity flags
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CPXF_ANCESTOR = 1,
|
||||||
|
CPXF_LESSOREQUAL = 1 << 1,
|
||||||
|
CPXF_NOZ = 1 << 2,
|
||||||
|
CPXF_COUNTDEAD = 1 << 3,
|
||||||
|
CPXF_DEADONLY = 1 << 4,
|
||||||
|
CPXF_EXACT = 1 << 5,
|
||||||
|
};
|
||||||
|
|
||||||
// Flags for A_CheckBlock
|
// Flags for A_CheckBlock
|
||||||
// These flags only affect the calling actor('s pointer), not the ones being searched.
|
// These flags only affect the calling actor('s pointer), not the ones being searched.
|
||||||
enum
|
enum
|
||||||
|
|
|
@ -56,4 +56,12 @@ gameinfo
|
||||||
statscreen_enteringpatch = "WIENTER"
|
statscreen_enteringpatch = "WIENTER"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DoomEdNums
|
||||||
|
{
|
||||||
|
4001 = "$Player5Start"
|
||||||
|
4002 = "$Player6Start"
|
||||||
|
4003 = "$Player7Start"
|
||||||
|
4004 = "$Player8Start"
|
||||||
|
}
|
||||||
|
|
||||||
include "mapinfo/common.txt"
|
include "mapinfo/common.txt"
|
||||||
|
|
|
@ -435,8 +435,12 @@ OptionMenu "CustomizeControls"
|
||||||
StaticText "Controls", 1
|
StaticText "Controls", 1
|
||||||
Control "Fire", "+attack"
|
Control "Fire", "+attack"
|
||||||
Control "Secondary Fire", "+altattack"
|
Control "Secondary Fire", "+altattack"
|
||||||
Control "Weapon Reload", "+reload"
|
Control "Weapon Reload", "+reload"
|
||||||
Control "Weapon Zoom", "+zoom"
|
Control "Weapon Zoom", "+zoom"
|
||||||
|
Control "Weapon State 1", "+user1"
|
||||||
|
Control "Weapon State 2", "+user2"
|
||||||
|
Control "Weapon State 3", "+user3"
|
||||||
|
Control "Weapon State 4", "+user4"
|
||||||
Control "Use / Open", "+use"
|
Control "Use / Open", "+use"
|
||||||
Control "Move forward", "+forward"
|
Control "Move forward", "+forward"
|
||||||
Control "Move backward", "+back"
|
Control "Move backward", "+back"
|
||||||
|
@ -1592,7 +1596,6 @@ OptionMenu AdvSoundOptions
|
||||||
StaticText "GUS Emulation", 1
|
StaticText "GUS Emulation", 1
|
||||||
TextField "GUS config file", "midi_config"
|
TextField "GUS config file", "midi_config"
|
||||||
Slider "MIDI voices", "midi_voices", 16, 256, 4, 0
|
Slider "MIDI voices", "midi_voices", 16, 256, 4, 0
|
||||||
Option "Emulate TiMidity", "midi_timiditylike", "OnOff"
|
|
||||||
Option "Read DMXGUS lumps", "midi_dmxgus", "OnOff"
|
Option "Read DMXGUS lumps", "midi_dmxgus", "OnOff"
|
||||||
Option "GUS memory size", "gus_memsize", "GusMemory"
|
Option "GUS memory size", "gus_memsize", "GusMemory"
|
||||||
StaticText " "
|
StaticText " "
|
||||||
|
@ -1608,6 +1611,10 @@ OptionMenu AdvSoundOptions
|
||||||
Option "Reverb", "timidity_reverb", "OnOff"
|
Option "Reverb", "timidity_reverb", "OnOff"
|
||||||
Option "Chorus", "timidity_chorus", "OnOff"
|
Option "Chorus", "timidity_chorus", "OnOff"
|
||||||
Slider "Relative volume", "timidity_mastervolume", 0, 4, 0.2, 1
|
Slider "Relative volume", "timidity_mastervolume", 0, 4, 0.2, 1
|
||||||
|
StaticText " "
|
||||||
|
StaticText "WildMidi", 1
|
||||||
|
TextField "WildMidi config file", "wildmidi_config"
|
||||||
|
Option "Reverb", "wildmidi_reverb", "OnOff"
|
||||||
}
|
}
|
||||||
|
|
||||||
/*=======================================
|
/*=======================================
|
||||||
|
|
72
zdoom.vcproj
72
zdoom.vcproj
|
@ -106,6 +106,7 @@
|
||||||
MapExports="true"
|
MapExports="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
StackReserveSize="0"
|
StackReserveSize="0"
|
||||||
|
LargeAddressAware="2"
|
||||||
TerminalServerAware="2"
|
TerminalServerAware="2"
|
||||||
OptimizeReferences="2"
|
OptimizeReferences="2"
|
||||||
EnableCOMDATFolding="2"
|
EnableCOMDATFolding="2"
|
||||||
|
@ -223,6 +224,7 @@
|
||||||
MapExports="true"
|
MapExports="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
StackReserveSize="0"
|
StackReserveSize="0"
|
||||||
|
LargeAddressAware="2"
|
||||||
TerminalServerAware="2"
|
TerminalServerAware="2"
|
||||||
OptimizeReferences="2"
|
OptimizeReferences="2"
|
||||||
EnableCOMDATFolding="2"
|
EnableCOMDATFolding="2"
|
||||||
|
@ -332,6 +334,7 @@
|
||||||
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
StackReserveSize="0"
|
StackReserveSize="0"
|
||||||
|
LargeAddressAware="2"
|
||||||
TerminalServerAware="2"
|
TerminalServerAware="2"
|
||||||
SetChecksum="false"
|
SetChecksum="false"
|
||||||
TargetMachine="0"
|
TargetMachine="0"
|
||||||
|
@ -440,6 +443,7 @@
|
||||||
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
ProgramDatabaseFile=".\Debug/zdoomd.pdb"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
StackReserveSize="0"
|
StackReserveSize="0"
|
||||||
|
LargeAddressAware="2"
|
||||||
TerminalServerAware="2"
|
TerminalServerAware="2"
|
||||||
SetChecksum="false"
|
SetChecksum="false"
|
||||||
TargetMachine="17"
|
TargetMachine="17"
|
||||||
|
@ -938,6 +942,10 @@
|
||||||
RelativePath=".\src\parsecontext.cpp"
|
RelativePath=".\src\parsecontext.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\pathexpander.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\po_man.cpp"
|
RelativePath=".\src\po_man.cpp"
|
||||||
>
|
>
|
||||||
|
@ -1475,6 +1483,10 @@
|
||||||
RelativePath=".\src\parsecontext.h"
|
RelativePath=".\src\parsecontext.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\pathexpander.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\po_man.h"
|
RelativePath=".\src\po_man.h"
|
||||||
>
|
>
|
||||||
|
@ -2589,6 +2601,10 @@
|
||||||
RelativePath=".\src\sound\music_timidity_mididevice.cpp"
|
RelativePath=".\src\sound\music_timidity_mididevice.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\sound\music_wildmidi_mididevice.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\sound\music_win_mididevice.cpp"
|
RelativePath=".\src\sound\music_win_mididevice.cpp"
|
||||||
>
|
>
|
||||||
|
@ -2785,6 +2801,62 @@
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="WildMidi"
|
||||||
|
>
|
||||||
|
<Filter
|
||||||
|
Name="Headers"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\common.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\file_io.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\gus_pat.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\reverb.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\wildmidi_lib.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\wm_error.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Source"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\file_io.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\gus_pat.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\reverb.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\wildmidi_lib.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\wildmidi\wm_error.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="SDL Files"
|
Name="SDL Files"
|
||||||
|
|
Loading…
Reference in a new issue