Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 into zsilencer-master

Conflicts:
	projects/openrct2.vcxproj.filters
This commit is contained in:
IntelOrca 2014-09-19 19:58:09 +01:00
commit f78b7a4c74
37 changed files with 3886 additions and 102 deletions

View File

@ -24,11 +24,14 @@ set (ORCT2_RESOURCE_DIR ${CMAKE_INSTALL_PREFIX}/share/${PROJECT}/)
project(${PROJECT})
add_definitions(-DORCT2_RESOURCE_DIR="${ORCT2_RESOURCE_DIR}")
add_definitions(-DHAVE_CONFIG_H)
# include lodepng header
include_directories("lodepng/")
# include speex header
include_directories("libspeex/")
# add source files
file(GLOB_RECURSE ORCT2_SOURCES "src/*.c" "lodepng/*.c")
file(GLOB_RECURSE ORCT2_SOURCES "src/*.c" "src/*.cpp" "libspeex/*.c" "lodepng/*.c")
if (UNIX)
# force 32bit build for now and set necessary flags to compile code as is

239
libspeex/arch.h Normal file
View File

@ -0,0 +1,239 @@
/* Copyright (C) 2003 Jean-Marc Valin */
/**
@file arch.h
@brief Various architecture definitions Speex
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``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 FOUNDATION OR
CONTRIBUTORS 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.
*/
#ifndef ARCH_H
#define ARCH_H
#ifndef SPEEX_VERSION
#define SPEEX_MAJOR_VERSION 1 /**< Major Speex version. */
#define SPEEX_MINOR_VERSION 1 /**< Minor Speex version. */
#define SPEEX_MICRO_VERSION 15 /**< Micro Speex version. */
#define SPEEX_EXTRA_VERSION "" /**< Extra Speex version. */
#define SPEEX_VERSION "speex-1.2beta3" /**< Speex version string. */
#endif
/* A couple test to catch stupid option combinations */
#ifdef FIXED_POINT
#ifdef FLOATING_POINT
#error You cannot compile as floating point and fixed point at the same time
#endif
#ifdef _USE_SSE
#error SSE is only for floating-point
#endif
#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
#error Make up your mind. What CPU do you have?
#endif
#ifdef VORBIS_PSYCHO
#error Vorbis-psy model currently not implemented in fixed-point
#endif
#else
#ifndef FLOATING_POINT
#error You now need to define either FIXED_POINT or FLOATING_POINT
#endif
#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
#endif
#ifdef FIXED_POINT_DEBUG
#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
#endif
#endif
#ifndef OUTSIDE_SPEEX
#include "speex/speex_types.h"
#endif
#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */
#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */
#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */
#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */
#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */
#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 32-bit value. */
#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */
#ifdef FIXED_POINT
typedef spx_int16_t spx_word16_t;
typedef spx_int32_t spx_word32_t;
typedef spx_word32_t spx_mem_t;
typedef spx_word16_t spx_coef_t;
typedef spx_word16_t spx_lsp_t;
typedef spx_word32_t spx_sig_t;
#define Q15ONE 32767
#define LPC_SCALING 8192
#define SIG_SCALING 16384
#define LSP_SCALING 8192.
#define GAMMA_SCALING 32768.
#define GAIN_SCALING 64
#define GAIN_SCALING_1 0.015625
#define LPC_SHIFT 13
#define LSP_SHIFT 13
#define SIG_SHIFT 14
#define GAIN_SHIFT 6
#define VERY_SMALL 0
#define VERY_LARGE32 ((spx_word32_t)2147483647)
#define VERY_LARGE16 ((spx_word16_t)32767)
#define Q15_ONE ((spx_word16_t)32767)
#ifdef FIXED_DEBUG
#include "fixed_debug.h"
#else
#include "fixed_generic.h"
#ifdef ARM5E_ASM
#include "fixed_arm5e.h"
#elif defined (ARM4_ASM)
#include "fixed_arm4.h"
#elif defined (BFIN_ASM)
#include "fixed_bfin.h"
#endif
#endif
#else
typedef float spx_mem_t;
typedef float spx_coef_t;
typedef float spx_lsp_t;
typedef float spx_sig_t;
typedef float spx_word16_t;
typedef float spx_word32_t;
#define Q15ONE 1.0f
#define LPC_SCALING 1.f
#define SIG_SCALING 1.f
#define LSP_SCALING 1.f
#define GAMMA_SCALING 1.f
#define GAIN_SCALING 1.f
#define GAIN_SCALING_1 1.f
#define VERY_SMALL 1e-15f
#define VERY_LARGE32 1e15f
#define VERY_LARGE16 1e15f
#define Q15_ONE ((spx_word16_t)1.f)
#define QCONST16(x,bits) (x)
#define QCONST32(x,bits) (x)
#define NEG16(x) (-(x))
#define NEG32(x) (-(x))
#define EXTRACT16(x) (x)
#define EXTEND32(x) (x)
#define SHR16(a,shift) (a)
#define SHL16(a,shift) (a)
#define SHR32(a,shift) (a)
#define SHL32(a,shift) (a)
#define PSHR16(a,shift) (a)
#define PSHR32(a,shift) (a)
#define VSHR32(a,shift) (a)
#define SATURATE16(x,a) (x)
#define SATURATE32(x,a) (x)
#define PSHR(a,shift) (a)
#define SHR(a,shift) (a)
#define SHL(a,shift) (a)
#define SATURATE(x,a) (x)
#define ADD16(a,b) ((a)+(b))
#define SUB16(a,b) ((a)-(b))
#define ADD32(a,b) ((a)+(b))
#define SUB32(a,b) ((a)-(b))
#define MULT16_16_16(a,b) ((a)*(b))
#define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b))
#define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b))
#define MULT16_32_Q11(a,b) ((a)*(b))
#define MULT16_32_Q13(a,b) ((a)*(b))
#define MULT16_32_Q14(a,b) ((a)*(b))
#define MULT16_32_Q15(a,b) ((a)*(b))
#define MULT16_32_P15(a,b) ((a)*(b))
#define MAC16_32_Q11(c,a,b) ((c)+(a)*(b))
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
#define MAC16_16_Q11(c,a,b) ((c)+(a)*(b))
#define MAC16_16_Q13(c,a,b) ((c)+(a)*(b))
#define MAC16_16_P13(c,a,b) ((c)+(a)*(b))
#define MULT16_16_Q11_32(a,b) ((a)*(b))
#define MULT16_16_Q13(a,b) ((a)*(b))
#define MULT16_16_Q14(a,b) ((a)*(b))
#define MULT16_16_Q15(a,b) ((a)*(b))
#define MULT16_16_P15(a,b) ((a)*(b))
#define MULT16_16_P13(a,b) ((a)*(b))
#define MULT16_16_P14(a,b) ((a)*(b))
#define DIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b))
#define PDIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b))
#define DIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b))
#define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b))
#endif
#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
/* 2 on TI C5x DSP */
#define BYTES_PER_CHAR 2
#define BITS_PER_CHAR 16
#define LOG2_BITS_PER_CHAR 4
#else
#define BYTES_PER_CHAR 1
#define BITS_PER_CHAR 8
#define LOG2_BITS_PER_CHAR 3
#endif
#ifdef FIXED_DEBUG
extern long long spx_mips;
#endif
#endif

20
libspeex/config.h Normal file
View File

@ -0,0 +1,20 @@
// Microsoft version of 'inline'
#define inline __inline
// Visual Studio support alloca(), but it always align variables to 16-bit
// boundary, while SSE need 128-bit alignment. So we disable alloca() when
// SSE is enabled.
#ifndef _USE_SSE
# define USE_ALLOCA
#endif
/* Default to floating point */
#ifndef FIXED_POINT
# define FLOATING_POINT
# define USE_SMALLFT
#else
# define USE_KISS_FFT
#endif
/* We don't support visibility on Win32 */
#define EXPORT

169
libspeex/os_support.h Normal file
View File

@ -0,0 +1,169 @@
/* Copyright (C) 2007 Jean-Marc Valin
File: os_support.h
This is the (tiny) OS abstraction layer. Aside from math.h, this is the
only place where system headers are allowed.
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.
*/
#ifndef OS_SUPPORT_H
#define OS_SUPPORT_H
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef OS_SUPPORT_CUSTOM
#include "os_support_custom.h"
#endif
/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free
NOTE: speex_alloc needs to CLEAR THE MEMORY */
#ifndef OVERRIDE_SPEEX_ALLOC
static inline void *speex_alloc (int size)
{
/* WARNING: this is not equivalent to malloc(). If you want to use malloc()
or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise
you will experience strange bugs */
return calloc(size,1);
}
#endif
/** Same as speex_alloc, except that the area is only needed inside a Speex call (might cause problem with wideband though) */
#ifndef OVERRIDE_SPEEX_ALLOC_SCRATCH
static inline void *speex_alloc_scratch (int size)
{
/* Scratch space doesn't need to be cleared */
return calloc(size,1);
}
#endif
/** Speex wrapper for realloc. To do your own dynamic allocation, all you need to do is replace this function, speex_alloc and speex_free */
#ifndef OVERRIDE_SPEEX_REALLOC
static inline void *speex_realloc (void *ptr, int size)
{
return realloc(ptr, size);
}
#endif
/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_alloc */
#ifndef OVERRIDE_SPEEX_FREE
static inline void speex_free (void *ptr)
{
free(ptr);
}
#endif
/** Same as speex_free, except that the area is only needed inside a Speex call (might cause problem with wideband though) */
#ifndef OVERRIDE_SPEEX_FREE_SCRATCH
static inline void speex_free_scratch (void *ptr)
{
free(ptr);
}
#endif
/** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking */
#ifndef OVERRIDE_SPEEX_COPY
#define SPEEX_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#endif
/** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term
provides compile-time type checking */
#ifndef OVERRIDE_SPEEX_MOVE
#define SPEEX_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#endif
/** Set n bytes of memory to value of c, starting at address s */
#ifndef OVERRIDE_SPEEX_MEMSET
#define SPEEX_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst))))
#endif
#ifndef OVERRIDE_SPEEX_FATAL
static inline void _speex_fatal(const char *str, const char *file, int line)
{
fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
exit(1);
}
#endif
#ifndef OVERRIDE_SPEEX_WARNING
static inline void speex_warning(const char *str)
{
#ifndef DISABLE_WARNINGS
fprintf (stderr, "warning: %s\n", str);
#endif
}
#endif
#ifndef OVERRIDE_SPEEX_WARNING_INT
static inline void speex_warning_int(const char *str, int val)
{
#ifndef DISABLE_WARNINGS
fprintf (stderr, "warning: %s %d\n", str, val);
#endif
}
#endif
#ifndef OVERRIDE_SPEEX_NOTIFY
static inline void speex_notify(const char *str)
{
#ifndef DISABLE_NOTIFICATIONS
fprintf (stderr, "notification: %s\n", str);
#endif
}
#endif
#ifndef OVERRIDE_SPEEX_PUTC
/** Speex wrapper for putc */
static inline void _speex_putc(int ch, void *file)
{
FILE *f = (FILE *)file;
fprintf(f, "%c", ch);
}
#endif
#define speex_fatal(str) _speex_fatal(str, __FILE__, __LINE__);
#define speex_assert(cond) {if (!(cond)) {speex_fatal("assertion failed: " #cond);}}
#ifndef RELEASE
static inline void print_vec(float *vec, int len, char *name)
{
int i;
printf ("%s ", name);
for (i=0;i<len;i++)
printf (" %f", vec[i]);
printf ("\n");
}
#endif
#endif

1131
libspeex/resample.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,340 @@
/* Copyright (C) 2007 Jean-Marc Valin
File: speex_resampler.h
Resampling code
The design goals of this code are:
- Very fast algorithm
- Low memory requirement
- Good *perceptual* quality (and not best SNR)
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.
*/
#ifndef SPEEX_RESAMPLER_H
#define SPEEX_RESAMPLER_H
#ifdef OUTSIDE_SPEEX
/********* WARNING: MENTAL SANITY ENDS HERE *************/
/* If the resampler is defined outside of Speex, we change the symbol names so that
there won't be any clash if linking with Speex later on. */
/* #define RANDOM_PREFIX your software name here */
#ifndef RANDOM_PREFIX
#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes"
#endif
#define CAT_PREFIX2(a,b) a ## b
#define CAT_PREFIX(a,b) CAT_PREFIX2(a, b)
#define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init)
#define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac)
#define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy)
#define speex_resampler_process_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_float)
#define speex_resampler_process_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_int)
#define speex_resampler_process_interleaved_float CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_float)
#define speex_resampler_process_interleaved_int CAT_PREFIX(RANDOM_PREFIX,_resampler_process_interleaved_int)
#define speex_resampler_set_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate)
#define speex_resampler_get_rate CAT_PREFIX(RANDOM_PREFIX,_resampler_get_rate)
#define speex_resampler_set_rate_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_set_rate_frac)
#define speex_resampler_get_ratio CAT_PREFIX(RANDOM_PREFIX,_resampler_get_ratio)
#define speex_resampler_set_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_set_quality)
#define speex_resampler_get_quality CAT_PREFIX(RANDOM_PREFIX,_resampler_get_quality)
#define speex_resampler_set_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_input_stride)
#define speex_resampler_get_input_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_stride)
#define speex_resampler_set_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_set_output_stride)
#define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride)
#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency)
#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency)
#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
#define spx_int16_t short
#define spx_int32_t int
#define spx_uint16_t unsigned short
#define spx_uint32_t unsigned int
#else /* OUTSIDE_SPEEX */
#include "speex/speex_types.h"
#endif /* OUTSIDE_SPEEX */
#ifdef __cplusplus
extern "C" {
#endif
#define SPEEX_RESAMPLER_QUALITY_MAX 10
#define SPEEX_RESAMPLER_QUALITY_MIN 0
#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4
#define SPEEX_RESAMPLER_QUALITY_VOIP 3
#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
enum {
RESAMPLER_ERR_SUCCESS = 0,
RESAMPLER_ERR_ALLOC_FAILED = 1,
RESAMPLER_ERR_BAD_STATE = 2,
RESAMPLER_ERR_INVALID_ARG = 3,
RESAMPLER_ERR_PTR_OVERLAP = 4,
RESAMPLER_ERR_MAX_ERROR
};
struct SpeexResamplerState_;
typedef struct SpeexResamplerState_ SpeexResamplerState;
/** Create a new resampler with integer input and output rates.
* @param nb_channels Number of channels to be processed
* @param in_rate Input sampling rate (integer number of Hz).
* @param out_rate Output sampling rate (integer number of Hz).
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
* and 10 has very high quality.
* @return Newly created resampler state
* @retval NULL Error: not enough memory
*/
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
spx_uint32_t in_rate,
spx_uint32_t out_rate,
int quality,
int *err);
/** Create a new resampler with fractional input/output rates. The sampling
* rate ratio is an arbitrary rational number with both the numerator and
* denominator being 32-bit integers.
* @param nb_channels Number of channels to be processed
* @param ratio_num Numerator of the sampling rate ratio
* @param ratio_den Denominator of the sampling rate ratio
* @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
* @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
* and 10 has very high quality.
* @return Newly created resampler state
* @retval NULL Error: not enough memory
*/
SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
spx_uint32_t ratio_num,
spx_uint32_t ratio_den,
spx_uint32_t in_rate,
spx_uint32_t out_rate,
int quality,
int *err);
/** Destroy a resampler state.
* @param st Resampler state
*/
void speex_resampler_destroy(SpeexResamplerState *st);
/** Resample a float array. The input and output buffers must *not* overlap.
* @param st Resampler state
* @param channel_index Index of the channel to process for the multi-channel
* base (0 otherwise)
* @param in Input buffer
* @param in_len Number of input samples in the input buffer. Returns the
* number of samples processed
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written
*/
int speex_resampler_process_float(SpeexResamplerState *st,
spx_uint32_t channel_index,
const float *in,
spx_uint32_t *in_len,
float *out,
spx_uint32_t *out_len);
/** Resample an int array. The input and output buffers must *not* overlap.
* @param st Resampler state
* @param channel_index Index of the channel to process for the multi-channel
* base (0 otherwise)
* @param in Input buffer
* @param in_len Number of input samples in the input buffer. Returns the number
* of samples processed
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written
*/
int speex_resampler_process_int(SpeexResamplerState *st,
spx_uint32_t channel_index,
const spx_int16_t *in,
spx_uint32_t *in_len,
spx_int16_t *out,
spx_uint32_t *out_len);
/** Resample an interleaved float array. The input and output buffers must *not* overlap.
* @param st Resampler state
* @param in Input buffer
* @param in_len Number of input samples in the input buffer. Returns the number
* of samples processed. This is all per-channel.
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written.
* This is all per-channel.
*/
int speex_resampler_process_interleaved_float(SpeexResamplerState *st,
const float *in,
spx_uint32_t *in_len,
float *out,
spx_uint32_t *out_len);
/** Resample an interleaved int array. The input and output buffers must *not* overlap.
* @param st Resampler state
* @param in Input buffer
* @param in_len Number of input samples in the input buffer. Returns the number
* of samples processed. This is all per-channel.
* @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written.
* This is all per-channel.
*/
int speex_resampler_process_interleaved_int(SpeexResamplerState *st,
const spx_int16_t *in,
spx_uint32_t *in_len,
spx_int16_t *out,
spx_uint32_t *out_len);
/** Set (change) the input/output sampling rates (integer value).
* @param st Resampler state
* @param in_rate Input sampling rate (integer number of Hz).
* @param out_rate Output sampling rate (integer number of Hz).
*/
int speex_resampler_set_rate(SpeexResamplerState *st,
spx_uint32_t in_rate,
spx_uint32_t out_rate);
/** Get the current input/output sampling rates (integer value).
* @param st Resampler state
* @param in_rate Input sampling rate (integer number of Hz) copied.
* @param out_rate Output sampling rate (integer number of Hz) copied.
*/
void speex_resampler_get_rate(SpeexResamplerState *st,
spx_uint32_t *in_rate,
spx_uint32_t *out_rate);
/** Set (change) the input/output sampling rates and resampling ratio
* (fractional values in Hz supported).
* @param st Resampler state
* @param ratio_num Numerator of the sampling rate ratio
* @param ratio_den Denominator of the sampling rate ratio
* @param in_rate Input sampling rate rounded to the nearest integer (in Hz).
* @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
*/
int speex_resampler_set_rate_frac(SpeexResamplerState *st,
spx_uint32_t ratio_num,
spx_uint32_t ratio_den,
spx_uint32_t in_rate,
spx_uint32_t out_rate);
/** Get the current resampling ratio. This will be reduced to the least
* common denominator.
* @param st Resampler state
* @param ratio_num Numerator of the sampling rate ratio copied
* @param ratio_den Denominator of the sampling rate ratio copied
*/
void speex_resampler_get_ratio(SpeexResamplerState *st,
spx_uint32_t *ratio_num,
spx_uint32_t *ratio_den);
/** Set (change) the conversion quality.
* @param st Resampler state
* @param quality Resampling quality between 0 and 10, where 0 has poor
* quality and 10 has very high quality.
*/
int speex_resampler_set_quality(SpeexResamplerState *st,
int quality);
/** Get the conversion quality.
* @param st Resampler state
* @param quality Resampling quality between 0 and 10, where 0 has poor
* quality and 10 has very high quality.
*/
void speex_resampler_get_quality(SpeexResamplerState *st,
int *quality);
/** Set (change) the input stride.
* @param st Resampler state
* @param stride Input stride
*/
void speex_resampler_set_input_stride(SpeexResamplerState *st,
spx_uint32_t stride);
/** Get the input stride.
* @param st Resampler state
* @param stride Input stride copied
*/
void speex_resampler_get_input_stride(SpeexResamplerState *st,
spx_uint32_t *stride);
/** Set (change) the output stride.
* @param st Resampler state
* @param stride Output stride
*/
void speex_resampler_set_output_stride(SpeexResamplerState *st,
spx_uint32_t stride);
/** Get the output stride.
* @param st Resampler state copied
* @param stride Output stride
*/
void speex_resampler_get_output_stride(SpeexResamplerState *st,
spx_uint32_t *stride);
/** Get the latency in input samples introduced by the resampler.
* @param st Resampler state
*/
int speex_resampler_get_input_latency(SpeexResamplerState *st);
/** Get the latency in output samples introduced by the resampler.
* @param st Resampler state
*/
int speex_resampler_get_output_latency(SpeexResamplerState *st);
/** Make sure that the first samples to go out of the resamplers don't have
* leading zeros. This is only useful before starting to use a newly created
* resampler. It is recommended to use that when resampling an audio file, as
* it will generate a file with the same length. For real-time processing,
* it is probably easier not to use this call (so that the output duration
* is the same for the first frame).
* @param st Resampler state
*/
int speex_resampler_skip_zeros(SpeexResamplerState *st);
/** Reset a resampler so a new (unrelated) stream can be processed.
* @param st Resampler state
*/
int speex_resampler_reset_mem(SpeexResamplerState *st);
/** Returns the English meaning for an error code
* @param err Error code
* @return English string
*/
const char *speex_resampler_strerror(int err);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,126 @@
/* speex_types.h taken from libogg */
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: #ifdef jail to whip a few platforms into the UNIX ideal.
last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $
********************************************************************/
/**
@file speex_types.h
@brief Speex types
*/
#ifndef _SPEEX_TYPES_H
#define _SPEEX_TYPES_H
#if defined(_WIN32)
# if defined(__CYGWIN__)
# include <_G_config.h>
typedef _G_int32_t spx_int32_t;
typedef _G_uint32_t spx_uint32_t;
typedef _G_int16_t spx_int16_t;
typedef _G_uint16_t spx_uint16_t;
# elif defined(__MINGW32__)
typedef short spx_int16_t;
typedef unsigned short spx_uint16_t;
typedef int spx_int32_t;
typedef unsigned int spx_uint32_t;
# elif defined(__MWERKS__)
typedef int spx_int32_t;
typedef unsigned int spx_uint32_t;
typedef short spx_int16_t;
typedef unsigned short spx_uint16_t;
# else
/* MSVC/Borland */
typedef __int32 spx_int32_t;
typedef unsigned __int32 spx_uint32_t;
typedef __int16 spx_int16_t;
typedef unsigned __int16 spx_uint16_t;
# endif
#elif defined(__MACOS__)
# include <sys/types.h>
typedef SInt16 spx_int16_t;
typedef UInt16 spx_uint16_t;
typedef SInt32 spx_int32_t;
typedef UInt32 spx_uint32_t;
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
# include <sys/types.h>
typedef int16_t spx_int16_t;
typedef u_int16_t spx_uint16_t;
typedef int32_t spx_int32_t;
typedef u_int32_t spx_uint32_t;
#elif defined(__BEOS__)
/* Be */
# include <inttypes.h>
typedef int16_t spx_int16_t;
typedef u_int16_t spx_uint16_t;
typedef int32_t spx_int32_t;
typedef u_int32_t spx_uint32_t;
#elif defined (__EMX__)
/* OS/2 GCC */
typedef short spx_int16_t;
typedef unsigned short spx_uint16_t;
typedef int spx_int32_t;
typedef unsigned int spx_uint32_t;
#elif defined (DJGPP)
/* DJGPP */
typedef short spx_int16_t;
typedef int spx_int32_t;
typedef unsigned int spx_uint32_t;
#elif defined(R5900)
/* PS2 EE */
typedef int spx_int32_t;
typedef unsigned spx_uint32_t;
typedef short spx_int16_t;
#elif defined(__SYMBIAN32__)
/* Symbian GCC */
typedef signed short spx_int16_t;
typedef unsigned short spx_uint16_t;
typedef signed int spx_int32_t;
typedef unsigned int spx_uint32_t;
#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
typedef short spx_int16_t;
typedef unsigned short spx_uint16_t;
typedef long spx_int32_t;
typedef unsigned long spx_uint32_t;
#elif defined(CONFIG_TI_C6X)
typedef short spx_int16_t;
typedef unsigned short spx_uint16_t;
typedef int spx_int32_t;
typedef unsigned int spx_uint32_t;
#else
# include <speex/speex_config_types.h>
#endif
#endif /* _SPEEX_TYPES_H */

115
libspeex/stack_alloc.h Normal file
View File

@ -0,0 +1,115 @@
/* Copyright (C) 2002 Jean-Marc Valin */
/**
@file stack_alloc.h
@brief Temporary memory allocation on stack
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``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 FOUNDATION OR
CONTRIBUTORS 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.
*/
#ifndef STACK_ALLOC_H
#define STACK_ALLOC_H
#ifdef USE_ALLOCA
# ifdef WIN32
# include <malloc.h>
# else
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
# include <stdlib.h>
# endif
# endif
#endif
/**
* @def ALIGN(stack, size)
*
* Aligns the stack to a 'size' boundary
*
* @param stack Stack
* @param size New size boundary
*/
/**
* @def PUSH(stack, size, type)
*
* Allocates 'size' elements of type 'type' on the stack
*
* @param stack Stack
* @param size Number of elements
* @param type Type of element
*/
/**
* @def VARDECL(var)
*
* Declare variable on stack
*
* @param var Variable to declare
*/
/**
* @def ALLOC(var, size, type)
*
* Allocate 'size' elements of 'type' on stack
*
* @param var Name of variable to allocate
* @param size Number of elements
* @param type Type of element
*/
#ifdef ENABLE_VALGRIND
#include <valgrind/memcheck.h>
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
#define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
#else
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type))))
#endif
#if defined(VAR_ARRAYS)
#define VARDECL(var)
#define ALLOC(var, size, type) type var[size]
#elif defined(USE_ALLOCA)
#define VARDECL(var) var
#define ALLOC(var, size, type) var = _alloca(sizeof(type)*(size))
#else
#define VARDECL(var) var
#define ALLOC(var, size, type) var = PUSH(stack, size, type)
#endif
#endif

View File

@ -28,11 +28,13 @@
<ClInclude Include="..\src\game.h" />
<ClInclude Include="..\src\gfx.h" />
<ClInclude Include="..\src\graph.h" />
<ClInclude Include="..\src\hook.h" />
<ClInclude Include="..\src\input.h" />
<ClInclude Include="..\src\intro.h" />
<ClInclude Include="..\src\language.h" />
<ClInclude Include="..\src\map.h" />
<ClInclude Include="..\src\marketing.h" />
<ClInclude Include="..\src\mixer.h" />
<ClInclude Include="..\src\news_item.h" />
<ClInclude Include="..\src\object.h" />
<ClInclude Include="..\src\osinterface.h" />
@ -65,6 +67,7 @@
<ClInclude Include="..\src\staff.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\libspeex\resample.c" />
<ClCompile Include="..\lodepng\lodepng.c" />
<ClCompile Include="..\src\audio.c" />
<ClCompile Include="..\src\award.c" />
@ -77,11 +80,13 @@
<ClCompile Include="..\src\game.c" />
<ClCompile Include="..\src\gfx.c" />
<ClCompile Include="..\src\graph.c" />
<ClCompile Include="..\src\hook.c" />
<ClCompile Include="..\src\input.c" />
<ClCompile Include="..\src\intro.c" />
<ClCompile Include="..\src\language.c" />
<ClCompile Include="..\src\map.c" />
<ClCompile Include="..\src\marketing.c" />
<ClCompile Include="..\src\mixer.cpp" />
<ClCompile Include="..\src\news_item.c" />
<ClCompile Include="..\src\object.c" />
<ClCompile Include="..\src\object_list.c" />
@ -191,7 +196,7 @@
<IntDir>$(SolutionDir)..\obj\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(SolutionDir)..\lodepng;$(SolutionDir)..\sdl\include;$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)..\lodepng;$(SolutionDir)..\sdl\include;$(SolutionDir)..\libspeex;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)..\sdl\lib\x86;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)..\build\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(Configuration)\</IntDir>
@ -202,7 +207,7 @@
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<StructMemberAlignment>1Byte</StructMemberAlignment>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -223,7 +228,7 @@
<OmitFramePointers>
</OmitFramePointers>
<BufferSecurityCheck>false</BufferSecurityCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -162,12 +162,18 @@
<ClInclude Include="..\src\input.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\scenery.h">
<ClInclude Include="..\src\mixer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\window_scenery.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\scenery.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\hook.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\game.c">
@ -386,9 +392,6 @@
<ClCompile Include="..\src\staff.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\window_scenery.c">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\src\input.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -398,6 +401,18 @@
<ClCompile Include="..\src\window_credits.c">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\libspeex\resample.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\mixer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\window_scenery.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\hook.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\openrct2.exe">

View File

@ -41,6 +41,8 @@
#define RCT2_CALLPROC_4(address, a1, a2, a3, a4, v1, v2, v3, v4) RCT2_CALLFUNC_4(address, void, a1, a2, a3, a4, v1, v2, v3, v4)
#define RCT2_CALLPROC_5(address, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) RCT2_CALLFUNC_5(address, void, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5)
#define RCT2_ADDRESS_EASTEREGG_NAMES 0x00988C20
#define RCT2_ADDRESS_RIDE_PROPERTIES 0x00997C9D
#define RCT2_ADDRESS_LAND_TOOL_SIZE 0x009A9800
#define RCT2_ADDRESS_SAVE_PROMPT_MODE 0x009A9802

View File

@ -22,6 +22,8 @@
#include "audio.h"
#include "addresses.h"
#include "config.h"
#include "map.h"
#include "osinterface.h"
#include "rct2.h"
#include "sprite.h"
#include "viewport.h"
@ -215,14 +217,14 @@ int dsound_create_primary_buffer(int a, int device, int channels, int samples, i
}
dsdevice = &RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, rct_dsdevice*)[device];
}
memset(&RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info), 0, sizeof(rct_audio_info));
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).var_0 = 1;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).channels = channels;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).samples = samples;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).var_8 = samples * RCT2_GLOBAL(0x01425B4C, uint16);
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).bytes = bits * channels / 8;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).bits = bits;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).var_E = 0;
memset(&RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, WAVEFORMATEX), 0, sizeof(WAVEFORMATEX));
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, WAVEFORMATEX).wFormatTag = 1;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, WAVEFORMATEX).nChannels = channels;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, WAVEFORMATEX).nSamplesPerSec = samples;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, WAVEFORMATEX).nAvgBytesPerSec = samples * RCT2_GLOBAL(0x01425B4C, uint16);
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, WAVEFORMATEX).nBlockAlign = bits * channels / 8;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, WAVEFORMATEX).wBitsPerSample = bits;
RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, WAVEFORMATEX).cbSize = 0;
DSBUFFERDESC bufferdesc;
memset(&bufferdesc, 0, sizeof(bufferdesc));
bufferdesc.dwSize = sizeof(bufferdesc);
@ -466,8 +468,8 @@ int sub_4015E7(int channel)
} else {
sound_channel->var_168 = 1;
sound_channel->var_15C = read;
rct_audio_info* audio_info = sound_channel->hmem;
uint16 v = ((audio_info->var_E != 8) - 1) & 0x80;
LPWAVEFORMATEX waveformat = sound_channel->hmem;
uint16 v = ((waveformat->nBlockAlign != 8) - 1) & 0x80;
memset(&buf1[read], v, buf1size - r);
}
}
@ -479,11 +481,26 @@ int sub_4015E7(int channel)
return result;
}
/**
*
* rct2: 0x00401AF3
*/
void sub_401AF3(int channel, const char* filename, int a3, int a4)
{
rct_sound_channel* sound_channel = &RCT2_ADDRESS(RCT2_ADDRESS_SOUND_CHANNEL_LIST, rct_sound_channel)[channel];
sound_channel->var_4 = 1;
memcpy(sound_channel->filename, filename, sizeof(sound_channel->filename));
sound_channel->var_10C = 0;
sound_channel->var_110 = a4;
sound_channel->var_114 = a3;
sound_channel->var_164 = 1;
}
/**
*
* rct2: 0x004016FF
*/
int sound_channel_load_file(int channel, char* filename, int offset)
int sound_channel_load_file(int channel, const char* filename, int offset)
{
rct_sound_channel* sound_channel = &RCT2_ADDRESS(0x014262E0, rct_sound_channel)[channel];
sound_channel->hmem;
@ -524,18 +541,18 @@ int sound_channel_load_file(int channel, char* filename, int offset)
*
* rct2: 0x00405222
*/
MMRESULT mmio_open(char* filename, HMMIO* hmmio, HGLOBAL* hmem, LPMMCKINFO mmckinfo)
MMRESULT mmio_open(const char* filename, HMMIO* hmmio, HGLOBAL* hmem, LPMMCKINFO mmckinfo)
{
HGLOBAL* hmemold;
HGLOBAL hmemold2;
HMMIO hmmio1;
MMRESULT result;
MMCKINFO mmckinfo1;
rct_audio_info audio_info;
WAVEFORMATEX waveformat;
hmemold = hmem;
*hmem = 0;
hmmio1 = mmioOpenA(filename, 0, MMIO_ALLOCBUF);
hmmio1 = mmioOpenA((char*)filename, 0, MMIO_ALLOCBUF);
if (hmmio1) {
result = mmioDescend(hmmio1, mmckinfo, 0, 0);
if (result != MMSYSERR_NOERROR) {
@ -555,20 +572,20 @@ MMRESULT mmio_open(char* filename, HMMIO* hmmio, HGLOBAL* hmem, LPMMCKINFO mmcki
result = 57601;
goto label20;
}
if (mmioRead(hmmio1, (HPSTR)&audio_info, 16) == 16) {
if (audio_info.var_0 == 1) {
if (mmioRead(hmmio1, (HPSTR)&waveformat, 16) == 16) {
if (waveformat.wFormatTag == 1) {
//strcpy(audio_info.var_0, "\x01");
hmem = 0;
label11:
hmemold2 = GlobalAlloc(0, (uint16)hmem + 18);
hmemold2 = GlobalAlloc(0, hmem + 18);
*hmemold = hmemold2;
if (!hmemold2) {
result = 57344;
goto label20;
}
memcpy(hmemold2, &audio_info, 16);
*((uint16*)*hmemold + 8) = (uint16)hmem;
if (!(uint16)hmem || mmioRead(hmmio1, (char*)*hmemold + 18, (uint16)hmem) == (uint16)hmem) {
memcpy(hmemold2, &waveformat, 16);
*((uint16*)*hmemold + 8) = hmem;
if (!hmem || mmioRead(hmmio1, (char*)*hmemold + 18, hmem) == hmem) {
result = mmioAscend(hmmio1, &mmckinfo1, 0);
if (!result) {
goto label24;
@ -1134,17 +1151,68 @@ int sound_prepare(int sound_id, rct_sound *sound, int channels, int software)
/**
*
* rct2: 0x006BB76E
*
* @param sound_id (eax)
* @param ebx (ebx)
* @param x (cx)
* @param y (dx)
* @param z (bp)
*/
int sound_play_panned(int sound_id, int x)
int sound_play_panned(int sound_id, int ebx, sint16 x, sint16 y, sint16 z)
{
//RCT2_CALLPROC_X(0x006BB76E, sound_id, x, 0, 0, 0, 0, 0);
// this function is not complete, need to add in volume adjust
int result = 0;
if (RCT2_GLOBAL(0x009AF59D, uint8) & 1) {
RCT2_GLOBAL(0x00F438AD, uint8) = 0;
int volume = 0;
if (x == 0x8001) {
// stuff to adjust volume
if (ebx == 0x8001) {
sint16 x2 = x & 0xFFE0; // round by 32
sint16 y2 = y & 0xFFE0;
if (x2 < 0x1FFF && y2 < 0x1FFF) {
rct_map_element* mapelement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[((y2 * 256 + x2) & 0xFFFF) / 8];
while (mapelement->type & MAP_ELEMENT_TYPE_MASK) {
mapelement++;
}
if ((mapelement->base_height * 8) - 5 > z) {
RCT2_GLOBAL(0x00F438AD, uint8) = 10;
}
}
sint16 v11;
sint16 v12;
switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) {
case MAP_ELEMENT_DIRECTION_WEST:
v11 = y - x;
v12 = ((y + x) / 2) - z;
break;
case MAP_ELEMENT_DIRECTION_NORTH:
v11 = -x - y;
v12 = ((y - x) / 2) - z;
break;
case MAP_ELEMENT_DIRECTION_EAST:
v11 = x - y;
v12 = ((-y - x) / 2) - z;
break;
case MAP_ELEMENT_DIRECTION_SOUTH:
v11 = y + x;
v12 = ((x - y) / 2) - z;
break;
}
rct_window* window = RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*);
while (1) {
window--;
if (window < RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window)) {
break;
}
rct_viewport* viewport = window->viewport;
if (viewport && viewport->flags & VIEWPORT_FLAG_SOUND_ON) {
sint16 v15 = v12 - viewport->view_y;
sint16 v16 = v11 - viewport->view_x;
ebx = viewport->x + (v16 >> viewport->zoom);
volume = RCT2_ADDRESS(0x0099282C, int)[sound_id] + ((-1024 * viewport->zoom - 1) << RCT2_GLOBAL(0x00F438AD, uint8)) + 1;
if (v15 < 0 || v15 >= viewport->view_height || v16 < 0 || v16 >= viewport->view_width || volume < -10000) {
return sound_id;
}
}
}
}
int i = 0;
rct_other_sound* other_sound = &RCT2_ADDRESS(0x009AF484, rct_other_sound)[i];
@ -1157,10 +1225,10 @@ int sound_play_panned(int sound_id, int x)
}
other_sound->id = sound_id;
int pan;
if (x == 0x8000) {
if (ebx == 0x8000) {
pan = 0;
} else {
int x2 = x << 16;
int x2 = ebx << 16;
uint16 screenwidth = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16);
if (screenwidth < 64) {
screenwidth = 64;
@ -1198,7 +1266,7 @@ int sub_401B63(int channel)
*
* rct2: 0x0040194E
*/
int sound_channel_load_file2(int channel, char* filename, int offset)
int sound_channel_load_file2(int channel, const char* filename, int offset)
{
if (!RCT2_GLOBAL(0x009E1AA4, int)) {
return 0;
@ -1539,12 +1607,12 @@ void stop_vehicle_sounds()
for (int i = 0; i < 7; i++) {
rct_vehicle_sound* vehicle_sound = &RCT2_ADDRESS(RCT2_ADDRESS_VEHICLE_SOUND_LIST, rct_vehicle_sound)[i];
if (vehicle_sound->id != 0xFFFF) {
if (vehicle_sound->var_18 != 0xFFFF) {
if (vehicle_sound->sound1_id != 0xFFFF) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_stop(&vehicle_sound->sound1);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
if (vehicle_sound->var_34 != 0xFFFF) {
if (vehicle_sound->sound2_id != 0xFFFF) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_stop(&vehicle_sound->sound2);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
@ -1640,4 +1708,171 @@ void unpause_sounds()
{
RCT2_GLOBAL(0x009AF59C, uint8)--;
g_sounds_disabled = 0;
}
}
/**
* Play/update ride music based on structs updated somewhere else
* rct2: 0x006BC6D8
*/
void sub_6BC6D8()
{
int edi;
int ebx;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)) {
if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0))) {
if (!RCT2_GLOBAL(0x009AF59C, uint8) && RCT2_GLOBAL(0x009AF59D, uint8) & 1 && RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)) {
while (1) {
int v8 = 0;
int v9 = 1;
rct_music_info* music_info = &RCT2_GLOBAL(0x009AF430, rct_music_info);
while (music_info < RCT2_GLOBAL(0x009AF42C, rct_music_info*)) {
if (music_info->id != (uint8)-1) {
rct_music_info3* music_info3 = &RCT2_GLOBAL(0x009AF1C8, rct_music_info3*)[music_info->var_1] + 8;
if (RCT2_ADDRESS(0x009AA0B1, uint8*)[music_info3->var_0]) {
v8++;
if (v9 >= music_info->volume) {
v9 = music_info->volume;
edi = (int)music_info;
}
}
}
music_info++;
}
if (v8 <= 1) {
break;
}
edi = -1;
}
while (1) {
int v8 = 0;
int v9 = 1;
rct_music_info* music_info = &RCT2_GLOBAL(0x009AF430, rct_music_info);
while (music_info < RCT2_GLOBAL(0x009AF42C, rct_music_info*)) {
if (music_info->id != (uint8)-1) {
v8++;
if (v9 >= music_info->volume) {
v9 = music_info->volume;
edi = (int)music_info;
}
}
music_info++;
}
if (v8 <= 2) {
break;
}
edi = -1;
}
rct_music_info2* music_info2 = &RCT2_GLOBAL(0x009AF46C, rct_music_info2);
int channel = 0;
do {
if (music_info2->id != (uint8)-1) {
rct_music_info* music_info = &RCT2_GLOBAL(0x009AF430, rct_music_info);
while (music_info < RCT2_GLOBAL(0x009AF42C, rct_music_info*)) {
if (music_info->id == music_info2->id && music_info->var_1 == music_info2->var_1) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
int v16 = sub_401B63(channel);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
if (v16) {
goto label32;
}
break;
}
music_info++;
}
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_channel_stop(channel);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
music_info2->id = -1;
}
label32:
music_info2++;
channel++;
} while(channel < 2);
for (rct_music_info* music_info = &RCT2_GLOBAL(0x009AF430, rct_music_info); music_info < RCT2_GLOBAL(0x009AF42C, rct_music_info*); music_info++) {
if (music_info->id != (uint8)-1) {
rct_music_info2* music_info2 = &RCT2_GLOBAL(0x009AF46C, rct_music_info2);
int channel = 0;
while (music_info->id != music_info2->id || music_info->var_1 != music_info2->var_1) {
if (music_info2->id == (uint8)-1) {
ebx = channel;
}
music_info2++;
channel++;
if (channel >= 2) {
rct_music_info3* music_info3 = &RCT2_GLOBAL(0x009AF1C8, rct_music_info3*)[music_info->var_1];
const char* filename = get_file_path(music_info3->pathid);
RCT2_GLOBAL(0x014241BC, uint32) = 3;
HANDLE hfile = osinterface_file_open(filename);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
if (hfile != INVALID_HANDLE_VALUE) {
RCT2_GLOBAL(0x014241BC, uint32) = 3;
osinterface_file_read(hfile, &RCT2_GLOBAL(0x009AF47E, uint32), 4);
RCT2_GLOBAL(0x014241BC, uint32) = 3;
osinterface_file_close(hfile);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
if (hfile == INVALID_HANDLE_VALUE || RCT2_GLOBAL(0x009AF47E, uint32) != 0x78787878) {
int offset = music_info->offset - 10000;
if (offset < 0) {
offset = 0;
}
RCT2_GLOBAL(0x014241BC, uint32) = 1;
int musicloaded = sound_channel_load_file2(ebx, filename, offset & 0xFFFFFFF0);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
if (musicloaded) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
int musicplayed = sound_channel_play(ebx, 0, music_info->volume, music_info->pan, music_info->freq);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
if (musicplayed) {
rct_music_info3* music_info3 = &RCT2_GLOBAL(0x009AF1C8, rct_music_info3*)[music_info->var_1];
if (music_info3->var_9) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sub_401AF3(ebx, get_file_path(music_info3->pathid), 1, 0);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
rct_music_info2* music_info2 = &RCT2_ADDRESS(0x009AF46C, rct_music_info2)[ebx];
music_info2->volume = music_info->volume;
music_info2->pan = music_info->pan;
music_info2->freq = music_info->freq;
music_info2->id = music_info->id;
music_info2->var_1 = music_info->var_1;
}
} else {
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0;
}
}
return;
}
}
if (music_info->volume != music_info2->volume) {
music_info2->volume = music_info->volume;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_channel_set_volume(channel, music_info->volume);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
if (music_info->pan != music_info2->pan) {
music_info2->pan = music_info->pan;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_channel_set_pan(channel, music_info->pan);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
if (music_info->freq != music_info2->freq) {
music_info2->freq = music_info->freq;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_channel_set_frequency(channel, music_info->freq);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
}
}
}
}
}
}

View File

@ -59,20 +59,11 @@ typedef struct rct_sound {
struct rct_sound* next;
} rct_sound;
typedef struct {
uint16 var_0;
uint16 channels;
uint32 samples;
uint32 var_8;
uint16 bytes;
uint16 bits;
uint16 var_E;
} rct_audio_info;
typedef struct {
uint32 var_0;
uint32 var_4;
char filename[0x108]; // 0x8
char filename[MAX_PATH]; // 0x8
uint32 var_10C;
uint32 var_110;
uint32 var_114;
uint32 var_118;
@ -100,15 +91,15 @@ typedef struct {
uint16 id;
uint16 var_2;
rct_sound sound1; // 0x04
uint16 var_18;
uint16 var_1A;
uint16 var_1C;
uint16 var_1D;
uint16 sound1_id; // 0x18
sint16 sound1_volume; // 0x1A
sint16 sound1_pan; // 0x1C
uint16 sound1_freq;
rct_sound sound2; // 0x20
uint16 var_34;
uint16 pad_36;
uint16 var_38;
uint16 var_3A;
uint16 sound2_id; // 0x34
sint16 sound2_volume; // 0x36
sint16 sound2_pan; // 0x38
uint16 sound2_freq; // 0x3A
} rct_vehicle_sound;
typedef struct {
@ -118,30 +109,55 @@ typedef struct {
typedef struct {
uint16 id;
uint8 var_2;
uint8 var_3;
uint8 var_4;
uint16 var_5;
uint8 var_7;
uint16 var_8;
uint16 next; // 0xA
sint16 pan; // 0x2
sint16 var_4;
uint16 frequency; // 0x6
sint16 var_8;
uint16 next; // 0xA
} rct_sound_unknown;
typedef struct {
uint8 id;
uint8 var_1;
sint32 offset; //0x2
sint16 volume; //0x6
sint16 pan; //0x8
uint16 freq; //0xA
} rct_music_info;
typedef struct {
uint8 id;
uint8 var_1;
uint16 volume; //0x2
uint16 pan; //0x4
uint16 freq; //0x6
} rct_music_info2;
typedef struct {
uint8 var_0;
uint8 pad_1[0x7];
uint8 pathid; //0x8
uint8 var_9;
} rct_music_info3;
int get_dsound_devices();
int dsound_create_primary_buffer(int a, int device, int channels, int samples, int bits);
void audio_timefunc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2, int channel);
int audio_release();
MMRESULT mmio_read(HMMIO hmmio, uint32 size, char* buffer, LPMMCKINFO mmckinfo, int* read);
MMRESULT mmio_seek(HMMIO* hmmio, LPMMCKINFO mmckinfo1, LPMMCKINFO mmckinfo2, int offset);
MMRESULT mmio_open(char* filename, HMMIO* hmmio, HGLOBAL* hmem, LPMMCKINFO mmckinfo);
MMRESULT mmio_open(const char* filename, HMMIO* hmmio, HGLOBAL* hmem, LPMMCKINFO mmckinfo);
int sub_40153B(int channel);
int sub_4015E7(int channel);
void sub_401AF3(int channel, const char* filename, int a3, int a4);
int sub_401B63(int channel);
void sub_6BC6D8();
int audio_remove_timer();
void audio_close();
LPVOID map_file(LPCSTR lpFileName, DWORD dwCreationDisposition, DWORD dwNumberOfBytesToMap);
int unmap_sound_info();
int sound_prepare(int sound_id, rct_sound *sound, int channels, int software);
int sound_play_panned(int sound_id, int x);
int sound_play_panned(int sound_id, int ebx, sint16 x, sint16 y, sint16 z);
int sound_play(rct_sound* sound, int looping, int volume, int pan, int frequency);
int sound_is_playing(rct_sound* sound);
int sound_set_frequency(rct_sound* sound, int frequency);
@ -151,8 +167,8 @@ int sound_channel_play(int channel, int a2, int volume, int pan, int frequency);
int sound_channel_set_frequency(int channel, int frequency);
int sound_channel_set_pan(int channel, int pan);
int sound_channel_set_volume(int channel, int volume);
int sound_channel_load_file2(int channel, char* filename, int offset);
int sound_channel_load_file(int channel, char* filename, int offset);
int sound_channel_load_file2(int channel, const char* filename, int offset);
int sound_channel_load_file(int channel, const char* filename, int offset);
void sound_channel_free(HMMIO* hmmio, HGLOBAL* hmem);
int sound_stop(rct_sound *sound);
int sound_stop_all();
@ -239,7 +255,8 @@ typedef enum {
SOUND_TRAM = 59,
SOUND_DOOR_OPEN = 60,
SOUND_DOOR_CLOSE = 61,
SOUND_62 = 62
SOUND_62 = 62,
SOUND_MAXID
} RCT2_SOUND;
#endif

View File

@ -133,7 +133,7 @@ typedef struct general_configuration {
uint16 language;
} general_configuration_t;
static const struct { char *key; int value; } _currencyLookupTable[] = {
static const struct { const char *key; int value; } _currencyLookupTable[] = {
{ "GBP", CURRENCY_POUNDS },
{ "USD", CURRENCY_DOLLARS },
{ "FRF", CURRENCY_FRANC },

View File

@ -383,7 +383,7 @@ void game_logic_update()
RCT2_CALLPROC_EBPSAFE(0x006B5A2A);
RCT2_CALLPROC_EBPSAFE(0x006B6456); // update ride measurements
RCT2_CALLPROC_EBPSAFE(0x0068AFAD);
RCT2_CALLPROC_EBPSAFE(0x006BBC6B); // vehicle and scream sounds
vehicle_sounds_update();//RCT2_CALLPROC_EBPSAFE(0x006BBC6B); // vehicle and scream sounds
peep_update_crowd_noise();
climate_update_sound();
news_item_update_current();

201
src/hook.c Normal file
View File

@ -0,0 +1,201 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <windows.h>
#include "hook.h"
void* g_hooktableaddress = 0;
int g_hooktableoffset = 0;
int g_maxhooks = 1000;
void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned)
{
int i = 0;
char data[100];
int registerssaved = 7;
int n = registersreturned;
for (; n; registerssaved--) {
n &= n - 1;
}
int numrargs = 0;
for (int j = 0; ; j++) {
if (registerargs[j] != END) {
numrargs++;
} else {
break;
}
}
int rargssize = numrargs * 4;
data[i++] = 0x50; // push eax
// move stack down for possible existing arguments
for (int j = 0; j < stacksize; j++) {
data[i++] = 0x8B; // mov eax, [esp+x]
data[i++] = 0x44;
data[i++] = 0xE4;
data[i++] = (signed char)((4 * (stacksize - j)) + 4);
data[i++] = 0x89; // mov [esp+x], eax
data[i++] = 0x44;
data[i++] = 0xE4;
data[i++] = (signed char)((4 * (stacksize - j)) - ((registerssaved + stacksize) * 4));
}
if (numrargs > 0) {
// push the registers to be on the stack to access as arguments
data[i++] = 0x83; // add esp, x
data[i++] = 0xC4;
data[i++] = -((registerssaved + stacksize) * 4) + 4;
for (signed int j = numrargs - 1; j >= 0; j--) {
switch (registerargs[j]) {
case EAX: data[i++] = 0x50; break;
case EBX: data[i++] = 0x53; break;
case ECX: data[i++] = 0x51; break;
case EDX: data[i++] = 0x52; break;
case ESI: data[i++] = 0x56; break;
case EDI: data[i++] = 0x57; break;
case EBP: data[i++] = 0x55; break;
}
}
data[i++] = 0x83; // add esp, x
data[i++] = 0xC4;
data[i++] = rargssize + ((registerssaved + stacksize) * 4) - 4;
}
data[i++] = 0xE8; // call
data[i++] = 0x00;
data[i++] = 0x00;
data[i++] = 0x00;
data[i++] = 0x00;
int sizec = i;
data[i++] = 0x8B; // push eax, [esp] - puts eip in eax
data[i++] = 0x04;
data[i++] = 0xE4;
data[i++] = 0x83; // add eax, x
data[i++] = 0xC0;
int sizeoffset = i;
data[i++] = 0; // set to returnlocation offset later
data[i++] = 0x89; // mov [esp-20h], eax - put return address on stack
data[i++] = 0x44;
data[i++] = 0xE4;
data[i++] = (signed char)(-(registerssaved * 4) - rargssize - (stacksize * 4)) + 4;
data[i++] = 0x83; // add esp, x
data[i++] = 0xC4;
data[i++] = 4;
data[i++] = 0x58; // pop eax
if (!(registersreturned & EAX)) {
data[i++] = 0x50; // push eax
}
if (!(registersreturned & EBX)) {
data[i++] = 0x53; // push ebx
}
if (!(registersreturned & ECX)) {
data[i++] = 0x51; // push ecx
}
if (!(registersreturned & EDX)) {
data[i++] = 0x52; // push edx
}
if (!(registersreturned & EBP)) {
data[i++] = 0x55; // push ebp
}
if (!(registersreturned & ESI)) {
data[i++] = 0x56; // push esi
}
if (!(registersreturned & EDI)) {
data[i++] = 0x57; // push edi
}
data[i++] = 0x83; // sub esp, x
data[i++] = 0xEC;
data[i++] = 4 + (stacksize * 4) + rargssize;
data[i++] = 0xEA; // jmp
*((int *)&data[i]) = newaddress; i += 4;
data[i++] = 0x23;
data[i++] = 0x00;
data[sizeoffset] = i - sizec;
// returnlocation:
data[i++] = 0x83; // sub esp, x
data[i++] = 0xEC;
data[i++] = (signed char)(stacksize * -4) - rargssize;
if (!(registersreturned & EDI)) {
data[i++] = 0x5F; // pop edi
}
if (!(registersreturned & ESI)) {
data[i++] = 0x5E; // pop esi
}
if (!(registersreturned & EBP)) {
data[i++] = 0x5D; // pop ebp
}
if (!(registersreturned & EDX)) {
data[i++] = 0x5A; // pop edx
}
if (!(registersreturned & ECX)) {
data[i++] = 0x59; // pop ecx
}
if (!(registersreturned & EBX)) {
data[i++] = 0x5B; // pop ebx
}
if (!(registersreturned & EAX)) {
data[i++] = 0x58; // pop eax
}
data[i++] = 0xC3; // retn
WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0);
}
void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned)
{
if (!g_hooktableaddress) {
g_hooktableaddress = VirtualAllocEx(GetCurrentProcess(), NULL, g_maxhooks * 100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
}
if (g_hooktableoffset > g_maxhooks) {
return;
}
unsigned int hookaddress = (unsigned int)g_hooktableaddress + (g_hooktableoffset * 100);
char data[9];
int i = 0;
data[i++] = 0xEA; // jmp
*((int *)&data[i]) = hookaddress; i += 4;
data[i++] = 0x23;
data[i++] = 0x00;
data[i++] = 0xC3; // retn
WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0);
hookfunc(hookaddress, newaddress, stacksize, registerargs, registersreturned);
g_hooktableoffset++;
}

37
src/hook.h Normal file
View File

@ -0,0 +1,37 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#ifndef _HOOK_H_
#define _HOOK_H_
enum REGISTER_ARGS {
EAX = 1 << 0,
EBX = 1 << 1,
ECX = 1 << 2,
EDX = 1 << 3,
ESI = 1 << 4,
EDI = 1 << 5,
EBP = 1 << 6,
END = 0
};
void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned);
#endif

View File

@ -536,7 +536,7 @@ static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex)
if (widget_is_disabled(w, widgetIndex))
break;
sound_play_panned(SOUND_CLICK_1, w->x + (widget->left + widget->right) / 2);
sound_play_panned(SOUND_CLICK_1, w->x + (widget->left + widget->right) / 2, 0, 0, 0);
// Set new cursor down widget
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass;
@ -649,7 +649,7 @@ void input_state_widget_pressed( int x, int y, int state, int widgetIndex, rct_w
break;
int mid_point_x = (widget->left + widget->right) / 2 + w->x;
sound_play_panned(5, mid_point_x);
sound_play_panned(5, mid_point_x, 0, 0, 0);
if (cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex)
break;

440
src/mixer.cpp Normal file
View File

@ -0,0 +1,440 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <math.h>
#include <SDL.h>
#include <string.h>
extern "C" {
#include "audio.h"
#include "config.h"
}
#include "mixer.h"
Mixer gMixer;
Sample::Sample()
{
data = 0;
length = 0;
issdlwav = false;
}
Sample::~Sample()
{
Unload();
}
bool Sample::Load(const char* filename)
{
Unload();
SDL_RWops* rw = SDL_RWFromFile(filename, "rb");
if (!rw) {
SDL_RWclose(rw);
return false;
}
SDL_AudioSpec audiospec;
memset(&audiospec, 0, sizeof(audiospec));
SDL_AudioSpec* spec = SDL_LoadWAV_RW(rw, false, &audiospec, &data, (Uint32*)&length);
if (spec != NULL) {
format.freq = spec->freq;
format.format = spec->format;
format.channels = spec->channels;
issdlwav = true;
} else {
return false;
}
return true;
}
bool Sample::LoadCSS1(const char* filename, unsigned int offset)
{
Unload();
SDL_RWops* rw = SDL_RWFromFile(filename, "rb");
if (!rw) {
return false;
}
Uint32 numsounds;
SDL_RWread(rw, &numsounds, sizeof(numsounds), 1);
if (offset > numsounds) {
SDL_RWclose(rw);
return false;
}
SDL_RWseek(rw, offset * 4, RW_SEEK_CUR);
Uint32 soundoffset;
SDL_RWread(rw, &soundoffset, sizeof(soundoffset), 1);
SDL_RWseek(rw, soundoffset, RW_SEEK_SET);
Uint32 soundsize;
SDL_RWread(rw, &soundsize, sizeof(soundsize), 1);
length = soundsize;
WAVEFORMATEX waveformat;
SDL_RWread(rw, &waveformat, sizeof(waveformat), 1);
format.freq = waveformat.nSamplesPerSec;
format.format = AUDIO_S16LSB;
format.channels = waveformat.nChannels;
data = new uint8[length];
SDL_RWread(rw, data, length, 1);
SDL_RWclose(rw);
return true;
}
void Sample::Unload()
{
if (data) {
if (issdlwav) {
SDL_FreeWAV(data);
} else {
delete[] data;
}
data = 0;
}
issdlwav = false;
length = 0;
}
bool Sample::Convert(AudioFormat format)
{
if(Sample::format.format != format.format || Sample::format.channels != format.channels || Sample::format.freq != format.freq){
SDL_AudioCVT cvt;
if (SDL_BuildAudioCVT(&cvt, Sample::format.format, Sample::format.channels, Sample::format.freq, format.format, format.channels, format.freq) < 0) {
return false;
}
cvt.len = length;
cvt.buf = (Uint8*)new uint8[cvt.len * cvt.len_mult];
memcpy(cvt.buf, data, length);
if (SDL_ConvertAudio(&cvt) < 0) {
delete[] cvt.buf;
return false;
}
Unload();
data = cvt.buf;
length = cvt.len_cvt;
Sample::format = format;
}
return true;
}
const uint8* Sample::Data()
{
return data;
}
unsigned long Sample::Length()
{
return length;
}
Stream::Stream()
{
sourcetype = SOURCE_NONE;
}
unsigned long Stream::GetSome(unsigned long offset, const uint8** data, unsigned long length)
{
unsigned long size = length;
switch(sourcetype) {
case SOURCE_SAMPLE:
if (offset >= sample->Length()) {
return 0;
}
if (offset + length > sample->Length()) {
size = sample->Length() - offset;
}
*data = &sample->Data()[offset];
return size;
break;
}
return 0;
}
unsigned long Stream::Length()
{
switch(sourcetype) {
case SOURCE_SAMPLE:
return sample->Length();
break;
}
return 0;
}
void Stream::SetSource_Sample(Sample& sample)
{
sourcetype = SOURCE_SAMPLE;
Stream::sample = &sample;
}
const AudioFormat* Stream::Format()
{
switch(sourcetype) {
case SOURCE_SAMPLE:
return &sample->format;
break;
}
return 0;
}
Channel::Channel()
{
rate = 1;
resampler = 0;
SetVolume(SDL_MIX_MAXVOLUME);
}
Channel::~Channel()
{
if (resampler) {
speex_resampler_destroy(resampler);
resampler = 0;
}
}
void Channel::Play(Stream& stream, int loop = MIXER_LOOP_NONE)
{
Channel::stream = &stream;
Channel::loop = loop;
offset = 0;
}
void Channel::SetRate(double rate)
{
Channel::rate = rate;
if (Channel::rate < 0.001) {
Channel::rate = 0.001;
}
}
void Channel::SetVolume(int volume)
{
Channel::volume = volume;
if (volume > SDL_MIX_MAXVOLUME) {
Channel::volume = SDL_MIX_MAXVOLUME;
}
if (volume < 0) {
Channel::volume = 0;
}
}
void Channel::SetPan(float pan)
{
Channel::pan = pan;
if (pan > 1) {
Channel::pan = 1;
}
if (pan < 0) {
Channel::pan = 0;
}
volume_l = (float)sin((1.0 - Channel::pan) * M_PI / 2.0);
volume_r = (float)sin(Channel::pan * M_PI / 2.0);
}
void Mixer::Init(const char* device)
{
Close();
SDL_AudioSpec want, have;
SDL_zero(want);
want.freq = 44100;
want.format = AUDIO_S16SYS;
want.channels = 2;
want.samples = 1024;
want.callback = Callback;
want.userdata = this;
deviceid = SDL_OpenAudioDevice(device, 0, &want, &have, 0);
format.format = have.format;
format.channels = have.channels;
format.freq = have.freq;
const char* filename = get_file_path(PATH_ID_CSS1);
for (int i = 0; i < SOUND_MAXID; i++) {
css1samples[i].LoadCSS1(filename, i);
css1samples[i].Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional
css1streams[i].SetSource_Sample(css1samples[i]);
}
effectbuffer = new uint8[(have.samples * format.BytesPerSample() * format.channels) + 200];
SDL_PauseAudioDevice(deviceid, 0);
}
void Mixer::Close()
{
SDL_CloseAudioDevice(deviceid);
delete[] effectbuffer;
}
void SDLCALL Mixer::Callback(void* arg, uint8* stream, int length)
{
Mixer* mixer = (Mixer*)arg;
memset(stream, 0, length);
for (int i = 0; i < 10; i++) {
mixer->MixChannel(mixer->channels[i], stream, length);
}
}
void Mixer::MixChannel(Channel& channel, uint8* data, int length)
{
if (channel.stream) {
if (!channel.resampler) {
channel.resampler = speex_resampler_init(format.channels, format.freq, format.freq, 0, 0);
}
AudioFormat channelformat = *channel.stream->Format();
int loaded = 0;
SDL_AudioCVT cvt;
cvt.len_ratio = 1;
do {
int samplesize = format.channels * format.BytesPerSample();
int samples = length / samplesize;
int samplesloaded = loaded / samplesize;
int samplestoread = (int)ceil((samples - samplesloaded) * channel.rate);
int lengthloaded = 0;
if (channel.offset < channel.stream->Length()) {
bool mustconvert = false;
if (MustConvert(*channel.stream)) {
if (SDL_BuildAudioCVT(&cvt, channelformat.format, channelformat.channels, channelformat.freq, Mixer::format.format, Mixer::format.channels, Mixer::format.freq) == -1) {
break;
}
mustconvert = true;
}
const uint8* datastream = 0;
int readfromstream = (channel.stream->GetSome(channel.offset, &datastream, (int)(((samplestoread) * samplesize) / cvt.len_ratio)) / channelformat.BytesPerSample()) * channelformat.BytesPerSample();
if (readfromstream == 0) {
break;
}
int volume = channel.volume;
uint8* dataconverted = 0;
const uint8* tomix = 0;
if (mustconvert) {
if (Convert(cvt, datastream, readfromstream, &dataconverted)) {
tomix = dataconverted;
lengthloaded = (cvt.len_cvt / samplesize) * samplesize;
} else {
break;
}
} else {
tomix = datastream;
lengthloaded = readfromstream;
}
bool effectbufferloaded = false;
if (channel.rate != 1 && format.format == AUDIO_S16SYS) {
int in_len = (int)(ceil((double)lengthloaded / samplesize));
int out_len = samples + 20; // needs some extra, otherwise resampler sometimes doesn't process all the input samples
speex_resampler_set_rate(channel.resampler, format.freq, (int)(format.freq * (1 / channel.rate)));
speex_resampler_process_interleaved_int(channel.resampler, (const spx_int16_t*)tomix, (spx_uint32_t*)&in_len, (spx_int16_t*)effectbuffer, (spx_uint32_t*)&out_len);
effectbufferloaded = true;
tomix = effectbuffer;
lengthloaded = (out_len * samplesize);
}
if (channel.pan != 0.5f && format.channels == 2) {
if (!effectbufferloaded) {
memcpy(effectbuffer, tomix, lengthloaded);
effectbufferloaded = true;
tomix = effectbuffer;
}
switch (format.format) {
case AUDIO_S16SYS:
EffectPanS16(channel, (sint16*)effectbuffer, lengthloaded / samplesize);
break;
case AUDIO_U8:
EffectPanU8(channel, (uint8*)effectbuffer, lengthloaded / samplesize);
break;
}
}
int mixlength = lengthloaded;
if (loaded + mixlength > length) {
mixlength = length - loaded;
}
SDL_MixAudioFormat(&data[loaded], tomix, format.format, mixlength, volume);
if (dataconverted) {
delete[] dataconverted;
}
channel.offset += readfromstream;
}
loaded += lengthloaded;
if (channel.loop != 0 && channel.offset >= channel.stream->Length()) {
if (channel.loop != -1) {
channel.loop--;
}
channel.offset = 0;
}
} while(loaded < length && channel.loop != 0);
}
}
void Mixer::EffectPanS16(Channel& channel, sint16* data, int length)
{
float left = channel.volume_l;
float right = channel.volume_r;
for (int i = 0; i < length * 2; i += 2) {
data[i] = (sint16)(data[i] * left);
data[i + 1] = (sint16)(data[i + 1] * right);
}
}
void Mixer::EffectPanU8(Channel& channel, uint8* data, int length)
{
float left = channel.volume_l;
float right = channel.volume_r;
for (int i = 0; i < length * 2; i += 2) {
data[i] = (uint8)(data[i] * left);
data[i + 1] = (uint8)(data[i + 1] * right);
}
}
bool Mixer::MustConvert(Stream& stream)
{
const AudioFormat* streamformat = stream.Format();
if (!streamformat) {
return false;
}
if (streamformat->format != format.format || streamformat->channels != format.channels || streamformat->freq != format.freq) {
return true;
}
return false;
}
bool Mixer::Convert(SDL_AudioCVT& cvt, const uint8* data, unsigned long length, uint8** dataout)
{
if (length == 0 || cvt.len_mult == 0) {
return false;
}
cvt.len = length;
cvt.buf = (Uint8*)new uint8[cvt.len * cvt.len_mult];
memcpy(cvt.buf, data, length);
if (SDL_ConvertAudio(&cvt) < 0) {
delete[] cvt.buf;
return false;
}
*dataout = cvt.buf;
return true;
}
void Mixer_Init(const char* device)
{
gMixer.Init(device);
}

136
src/mixer.h Normal file
View File

@ -0,0 +1,136 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#ifndef _MIXER_H_
#define _MIXER_H_
#include "rct2.h"
#define MIXER_LOOP_NONE 0
#define MIXER_LOOP_INFINITE -1
#ifdef __cplusplus
extern "C" {
#include <speex/speex_resampler.h>
}
struct AudioFormat {
int BytesPerSample() const { return (SDL_AUDIO_BITSIZE(format)) / 8; };
int freq;
SDL_AudioFormat format;
int channels;
};
class Sample
{
public:
Sample();
~Sample();
bool Load(const char* filename);
bool LoadCSS1(const char* filename, unsigned int offset);
void Unload();
bool Convert(AudioFormat format);
const uint8* Data();
unsigned long Length();
friend class Stream;
private:
AudioFormat format;
uint8* data;
unsigned long length;
bool issdlwav;
};
class Stream
{
public:
Stream();
unsigned long GetSome(unsigned long offset, const uint8** data, unsigned long length);
unsigned long Length();
void SetSource_Sample(Sample& sample);
const AudioFormat* Format();
friend class Mixer;
private:
enum {
SOURCE_NONE = 0,
SOURCE_SAMPLE
} sourcetype;
Sample* sample;
};
class Channel
{
public:
Channel();
~Channel();
void Play(Stream& stream, int loop);
void SetRate(double rate);
void SetVolume(int volume);
void SetPan(float pan);
friend class Mixer;
private:
int loop;
unsigned long offset;
double rate;
int volume;
float volume_l, volume_r;
float pan;
SpeexResamplerState* resampler;
Stream* stream;
};
class Mixer
{
public:
void Init(const char* device);
void Close();
private:
static void SDLCALL Callback(void* arg, uint8* data, int length);
void MixChannel(Channel& channel, uint8* buffer, int length);
void EffectPanS16(Channel& channel, sint16* data, int length);
void EffectPanU8(Channel& channel, uint8* data, int length);
bool MustConvert(Stream& stream);
bool Convert(SDL_AudioCVT& cvt, const uint8* data, unsigned long length, uint8** dataout);
SDL_AudioDeviceID deviceid;
AudioFormat format;
uint8* effectbuffer;
Sample css1samples[SOUND_MAXID];
Stream css1streams[SOUND_MAXID];
Channel channels[10];
};
extern "C"
{
#endif
void Mixer_Init(const char* device);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -97,7 +97,7 @@ void news_item_update_current()
newsItems[0].ticks++;
if (newsItems[0].ticks == 1 && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)) {
// Play sound
sound_play_panned(SOUND_NEWS_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2);
sound_play_panned(SOUND_NEWS_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2, 0, 0, 0);
}
// Removal of current news item

View File

@ -654,7 +654,7 @@ int osinterface_file_close(HANDLE handle)
*
* rct2: 0x00408060
*/
HANDLE osinterface_file_open(char* filename)
HANDLE osinterface_file_open(const char* filename)
{
return CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, 0);
}
@ -663,7 +663,7 @@ HANDLE osinterface_file_open(char* filename)
*
* rct2: 0x0040807D
*/
HANDLE osinterface_file_create(char* filename)
HANDLE osinterface_file_create(const char* filename)
{
return CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
}
@ -672,7 +672,7 @@ HANDLE osinterface_file_create(char* filename)
*
* rct2: 0x00408099
*/
int osinterface_file_move(char* srcfilename, char* dstfilename)
int osinterface_file_move(const char* srcfilename, const char* dstfilename)
{
return (MoveFileA(srcfilename, dstfilename) != 0) - 1;
}
@ -681,7 +681,7 @@ int osinterface_file_move(char* srcfilename, char* dstfilename)
*
* rct2: 0x004080AF
*/
int osinterface_file_delete(char* filename)
int osinterface_file_delete(const char* filename)
{
return (DeleteFileA(filename) != 0) - 1;
}

View File

@ -21,6 +21,7 @@
#ifndef _SDL_INTERFACE_H_
#define _SDL_INTERFACE_H_
#include <windows.h>
#include "rct2.h"
enum {
@ -74,7 +75,7 @@ typedef struct {
char path[260];
uint32 var_20C;
uint8 pad_210[0x100];
char addon[15][0x80];
char addon[16][0x80];
uint32 addons; //0xB10
} rct2_install_info;
@ -96,6 +97,10 @@ void osinterface_progressbar_setpos(int pos);
void osinterface_set_cursor(char cursor);
HANDLE osinterface_file_open(const char* filename);
int osinterface_file_read(HANDLE handle, void* data, int size);
int osinterface_file_close(HANDLE handle);
int osinterface_open_common_file_dialog(int type, char *title, char *filename, char *filterPattern, char *filterName);
void osinterface_show_messagebox(char* message);
char* osinterface_open_directory_browser(char *title);

View File

@ -394,7 +394,7 @@ void peep_applause()
}
// Play applause noise
sound_play_panned(SOUND_APPLAUSE, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2);
sound_play_panned(SOUND_APPLAUSE, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2, 0, 0, 0);
}
/**
@ -682,3 +682,37 @@ int get_peep_face_sprite_small(rct_peep *peep){
int get_peep_face_sprite_large(rct_peep *peep){
return face_sprite_large[get_face_sprite_offset(peep)];
}
/**
*
* rct2: 0x0069A5A0
* tests if a peep's name matches a cheat code, normally returns using a register flag
* @param index (eax)
* @param ride (esi)
*/
int peep_check_cheatcode(int index, rct_peep *peep)
{
char* str = RCT2_ADDRESS(RCT2_ADDRESS_EASTEREGG_NAMES, char*)[index];
char* dst = (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER;
format_string(dst, peep->name_string_idx, &peep->id);
// strtoupper:
int i = 0;
while(dst[i]) {
if (dst[i] >= 0x61 && dst[i] <= 0x7A) {
dst[i] -= 0x20;
}
i++;
}
// check for match, characters are -1 to obfuscate the cheat codes
i = 0;
while(str[i] + 1) {
if (str[i] + 1 != dst[i]) {
return 0;
}
i++;
}
return 1;
}

View File

@ -456,6 +456,7 @@ void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argum
void get_arguments_from_thought(rct_peep_thought thought, uint32* argument_1, uint32* argument_2);
int get_peep_face_sprite_small(rct_peep *peep);
int get_peep_face_sprite_large(rct_peep *peep);
int peep_check_cheatcode(int index, rct_peep *peep);
#endif

View File

@ -39,6 +39,7 @@
#include "intro.h"
#include "language.h"
#include "map.h"
#include "mixer.h"
#include "news_item.h"
#include "object.h"
#include "osinterface.h"
@ -88,6 +89,7 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta
config_init();
language_open(gGeneral_config.language);
rct2_init();
Mixer_Init(NULL);
rct2_loop();
osinterface_free();
exit(0);

View File

@ -25,6 +25,7 @@
#include "news_item.h"
#include "sprite.h"
#include "ride.h"
#include "scenario.h"
#include "sprite.h"
#include "peep.h"
#include "window.h"
@ -474,3 +475,51 @@ int ride_try_construct(rct_map_element *trackMapElement)
RCT2_CALLPROC_X(0x006CC056, 0, 0, 0, (int)trackMapElement, 0, 0, 0);
return 1;
}
/**
*
* rct2: 0x006AC988
* set the speed of the gokart type vehicle at the start to a random value or alter if peep name is a cheat code
* @param ride (esi)
*/
void ride_init_vehicle_speed(rct_ride *ride)
{
int ecx = -1;
while (1) {
ecx++;
if (ecx >= ride->var_0C8) {
break;
}
rct_vehicle *vehicle = &g_sprite_list[ride->train_car_map[ecx]].vehicle;
vehicle->var_48 &= (1 << 6);
uint8 r = scenario_rand();
r = 0xC;
r &= 0xF;
r -= 8;
int testaddr = (vehicle->var_31 * 0x65);
testaddr += (int)RCT2_ADDRESS(0x009ACFA4, rct_ride_type*)[vehicle->var_D6];
uint8 test = ((uint8*)testaddr)[0x76];
r += test;
vehicle->speed = r;
if (vehicle->var_B3) {
rct_peep *peep = &g_sprite_list[vehicle->peep].peep;
if (peep_check_cheatcode(0, peep)) { // MICHAEL SCHUMACHER
vehicle->speed += 35;
}
if (peep_check_cheatcode(1, peep)) { // JACQUES VILLENEUVE
vehicle->speed += 25;
}
if (peep_check_cheatcode(2, peep)) { // DAMON HILL
vehicle->speed += 55;
}
if (peep_check_cheatcode(4, peep)) { // CHRIS SAWYER
vehicle->speed += 14;
}
if (peep_check_cheatcode(3, peep)) { // MR BEAN
vehicle->speed = 9;
}
}
}
}

View File

@ -81,7 +81,9 @@ typedef struct {
uint16 overall_view; // 0x050 00XX = X, XX00 = Y (* 32 + 16)
uint16 station_starts[4]; // 0x052
uint8 station_heights[4]; // 0x05A
uint8 pad_05E[0xC];
uint8 pad_05E[4];
uint8 var_62[4];
uint8 pad_66[4];
uint16 entrances[4]; // 0x06A
uint16 exits[4]; // 0x072
uint8 pad_07A[0x0C];
@ -90,11 +92,12 @@ typedef struct {
// Not sure if these should be uint or sint.
uint8 var_0C7;
uint8 var_0C8;
uint8 var_0C8; // Number of train cars?
uint8 var_0C9;
uint8 pad_0CA[0x1A];
uint8 pad_0CA[0x06];
uint8 var_0D0;
uint8 pad_0D1[0x13];
sint32 var_0E4;
sint32 var_0E8;
sint32 var_0EC;
@ -147,7 +150,9 @@ typedef struct {
sint32 profit; // 0x1B4
uint8 queue_time[4]; // 0x1B8
uint8 var_1BC;
uint8 pad_1BD[0x10];
uint8 pad_1BD[0xD];
uint16 var_1CA;
uint8 var_1CC;
uint8 var_1CD;
uint16 guests_favourite; // 0x1CE
uint32 lifecycle_flags; // 0x1D0
@ -389,5 +394,6 @@ rct_map_element *sub_6CAF80(int rideIndex, int *outX, int *outY);
rct_map_element *ride_find_track_gap(rct_map_element *startTrackElement, int *outX, int *outY);
void ride_construct_new(int list_item);
int ride_try_construct(rct_map_element *trackMapElement);
void ride_init_vehicle_speed(rct_ride *ride);
#endif

View File

@ -19,11 +19,445 @@
*****************************************************************************/
#include "addresses.h"
#include "audio.h"
#include "ride.h"
#include "sprite.h"
#include "vehicle.h"
#include "viewport.h"
static void vehicle_update(rct_vehicle *vehicle);
/**
*
* rct2: 0x006BB9FF
*/
void sub_6BB9FF(rct_vehicle* vehicle)
{
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) && (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 4) || RCT2_GLOBAL(0x0141F570, uint8) == 6)) {
if (vehicle->var_BB != (uint8)-1 || vehicle->var_BD != (uint8)-1) {
if (vehicle->var_16.width != 0x8000) {
RCT2_GLOBAL(0x009AF5A0, rct_widthheight) = vehicle->var_16;
RCT2_GLOBAL(0x009AF5A4, rct_widthheight) = vehicle->view;
sint16 v4 = RCT2_GLOBAL(0x00F438A4, rct_viewport*)->view_x;
sint16 v5 = RCT2_GLOBAL(0x00F438A4, rct_viewport*)->view_y;
sint16 v6 = RCT2_GLOBAL(0x00F438A4, rct_viewport*)->view_width / 4;
sint16 v7 = RCT2_GLOBAL(0x00F438A4, rct_viewport*)->view_height / 4;
if (!RCT2_GLOBAL(0x00F438A8, rct_window*)->classification) {
v4 -= v6;
v5 -= v7;
}
if (v4 < RCT2_GLOBAL(0x009AF5A4, rct_widthheight).width && v5 < RCT2_GLOBAL(0x009AF5A4, rct_widthheight).height) {
sint16 t8 = RCT2_GLOBAL(0x00F438A4, rct_viewport*)->view_width + v4;
sint16 t9 = RCT2_GLOBAL(0x00F438A4, rct_viewport*)->view_height + v5;
if (!RCT2_GLOBAL(0x00F438A8, rct_window*)->classification) {
t8 += v6 + v6;
t9 += v7 + v7;
}
if (t8 >= RCT2_GLOBAL(0x009AF5A0, rct_widthheight).width && t9 >= RCT2_GLOBAL(0x009AF5A0, rct_widthheight).height) {
uint16 v9 = sub_6BC2F3(vehicle);
rct_sound_unknown* i;
for (i = RCT2_ADDRESS(0x00F438B4, rct_sound_unknown); i < RCT2_GLOBAL(0x00F438B0, rct_sound_unknown*) && v9 <= i->next; i++);
if (i < RCT2_ADDRESS(0x00F43908, rct_sound_unknown)) { // 0x00F43908 is end of rct_sound_unknown list, which has 7 elements, not to be confused with variable at 0x00F43908
if (RCT2_GLOBAL(0x00F438B0, rct_sound_unknown*) < RCT2_ADDRESS(0x00F43908, rct_sound_unknown)) {
RCT2_GLOBAL(0x00F438B0, rct_sound_unknown*)++;
}
rct_sound_unknown* j = RCT2_GLOBAL(0x00F438B0, rct_sound_unknown*) - 1;
while (j >= i) {
j--;
*(j + 1) = *j;
}
i->next = v9;
rct_widthheight v12;
v12.height = vehicle->var_16.height;
v12.width = ((uint16)RCT2_GLOBAL(0x009AF5A0, rct_widthheight).width / 2) + ((uint16)RCT2_GLOBAL(0x009AF5A4, rct_widthheight).width / 2) - RCT2_GLOBAL(0x00F438A4, rct_viewport*)->view_x;
v12.width >>= RCT2_GLOBAL(0x00F438A4, rct_viewport*)->zoom;
v12.width += RCT2_GLOBAL(0x00F438A4, rct_viewport*)->x;
uint16 v14 = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16);
if (v14 < 64) {
v14 = 64;
}
rct_widthheight v15;
i->pan = (((((uint32)v12.width << 16) / v14) - 0x8000) >> 4);
v15.width = 0;
v15.height = (RCT2_GLOBAL(0x009AF5A0, rct_widthheight).height / 2) + (RCT2_GLOBAL(0x009AF5A4, rct_widthheight).height / 2) - RCT2_GLOBAL(0x00F438A4, rct_viewport*)->view_y;
v15.height >>= RCT2_GLOBAL(0x00F438A4, rct_viewport*)->zoom;
v15.height += RCT2_GLOBAL(0x00F438A4, rct_viewport*)->y;
uint16 v18 = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16);
if (v18 < 64) {
v18 = 64;
}
i->var_4 = (sint16)(((v15.both / v18) - 0x8000) >> 4);
sint32 v19 = vehicle->var_28;
int testaddr = (vehicle->var_31 * 0x65);
testaddr += (int)RCT2_ADDRESS(0x009ACFA4, rct_ride_type*)[vehicle->var_D6];
uint8 test = ((uint8*)testaddr)[0x74];
if (test & 1) {
v19 *= 2;
}
if (v19 < 0) {
v19 = -v19;
}
v19 >>= 5;
v19 *= 0x1588;
v19 >>= 14;
v19 += 0x2B11;
v19 += 16 * vehicle->var_BF;
i->frequency = (uint16)v19;
i->id = vehicle->sprite_index;
i->var_8 = 0;
if (vehicle->x != 0x8000) {
uint16 v22 = (vehicle->y & 0xFFE0) << 8;
v22 |= (vehicle->x & 0xFFE0 | v22) & 0xFFFF;
rct_map_element* map_element;
for (map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[v22 >> 3]; map_element->type & MAP_ELEMENT_TYPE_MASK; map_element++);
if (map_element->base_height * 8 > vehicle->z) {
i->var_8 = 0x30;
}
}
}
}
}
}
}
}
}
/**
*
* rct2: 0x006BC2F3
*/
int sub_6BC2F3(rct_vehicle* vehicle)
{
int result = 0;
rct_vehicle* vehicle_temp = vehicle;
do {
result += vehicle_temp->var_46;
} while (vehicle_temp->next_vehicle_on_train != (uint16)-1 && (vehicle_temp = GET_VEHICLE(vehicle_temp->next_vehicle_on_train)));
sint32 v4 = vehicle->var_28;
if (v4 < 0) {
v4 = -v4;
}
result += ((uint16)v4) >> 13;
rct_vehicle_sound* vehicle_sound = RCT2_ADDRESS(RCT2_ADDRESS_VEHICLE_SOUND_LIST, rct_vehicle_sound);
while (vehicle_sound->id != vehicle->sprite_index) {
vehicle_sound++;
if (vehicle_sound >= RCT2_GLOBAL(0x009AF42C, rct_vehicle_sound*)) {
return result;
}
}
return result + 300;
}
/**
*
* rct2: 0x006BBC6B
*/
void vehicle_sounds_update()
{
uint16 result;
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1 && !RCT2_GLOBAL(0x009AF59C, uint8) && RCT2_GLOBAL(0x009AF59D, uint8) & 1) {
RCT2_GLOBAL(0x00F438A4, rct_viewport*) = (rct_viewport*)-1;
rct_window* window = RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*);
rct_viewport* viewport = (rct_viewport*)-1;
for (window = RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); window >= RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window); window--) {
viewport = window->viewport;
if (viewport && viewport->flags & VIEWPORT_FLAG_SOUND_ON) {
break;
}
}
RCT2_GLOBAL(0x00F438A4, rct_viewport*) = viewport;
if (viewport != (rct_viewport*)-1) {
if (window) {
RCT2_GLOBAL(0x00F438A8, rct_window*) = window;
RCT2_GLOBAL(0x00F438AC, uint8) = 0;
if (viewport->zoom) {
RCT2_GLOBAL(0x00F438AC, uint8) = 35;
if (viewport->zoom != 1) {
RCT2_GLOBAL(0x00F438AC, uint8) = 70;
}
}
}
//label12:
RCT2_GLOBAL(0x00F438B0, rct_sound_unknown**) = &RCT2_GLOBAL(0x00F438B4, rct_sound_unknown*);
for (uint16 i = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_VEHICLE, uint16); i != SPRITE_INDEX_NULL; i = g_sprite_list[i].vehicle.next) {
sub_6BB9FF(&g_sprite_list[i].vehicle);
}
RCT2_ADDRESS_VEHICLE_SOUND_LIST;
for (rct_vehicle_sound* vehicle_sound = &RCT2_GLOBAL(RCT2_ADDRESS_VEHICLE_SOUND_LIST, rct_vehicle_sound); vehicle_sound != &RCT2_GLOBAL(0x009AF42C, rct_vehicle_sound); vehicle_sound++) {
if (vehicle_sound->id != (uint16)-1) {
for (rct_sound_unknown* sound_unknown = &RCT2_GLOBAL(0x00F438B4, rct_sound_unknown); sound_unknown != RCT2_GLOBAL(0x00F438B0, rct_sound_unknown*); sound_unknown++) {
if (vehicle_sound->id == sound_unknown->id) {
goto label26;
}
}
if (vehicle_sound->sound1_id != (uint16)-1) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_stop(&vehicle_sound->sound1);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
if (vehicle_sound->sound2_id != (uint16)-1) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_stop(&vehicle_sound->sound2);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
vehicle_sound->id = (uint16)-1;
}
label26:
1;
}
for (rct_sound_unknown* sound_unknown = &RCT2_GLOBAL(0x00F438B4, rct_sound_unknown); sound_unknown != RCT2_GLOBAL(0x00F438B0, rct_sound_unknown*); sound_unknown++) {
label28:
result = (uint16)-1;
sint16 v = sound_unknown->var_4;
if (v < 0) {
v = -v;
}
if (v > 0xFFF) {
v = 0xFFF;
}
v -= 0x800;
if (v > 0) {
v -= 0x400;
v = -v;
v = (uint16)v / 4;
result = MAKEWORD(LOBYTE(v), HIBYTE(result));
if (HIBYTE(v) != 0) {
result = MAKEWORD(0xFF, HIBYTE(result));
if (HIBYTE(v) < 0) {
result = MAKEWORD(0, HIBYTE(result));
}
}
}
sint16 w = sound_unknown->pan;
if (w < 0) {
w = -w;
}
if (w > 0xFFF) {
w = 0xFFF;
}
w -= 0x800;
if (w > 0) {
w -= 0x400;
w = -w;
w = (uint16)w / 4;
result = MAKEWORD(LOBYTE(result), LOBYTE(w));
if (HIBYTE(w) != 0) {
result = MAKEWORD(LOBYTE(result), 0xFF);
if (HIBYTE(w) < 0) {
result = MAKEWORD(LOBYTE(result), 0);
}
}
}
if (LOBYTE(result) >= HIBYTE(result)) {
result = MAKEWORD(HIBYTE(result), HIBYTE(result));
}
if (LOBYTE(result) < RCT2_GLOBAL(0x00F438AC, uint8)) {
result = MAKEWORD(0, HIBYTE(result));
} else {
result = MAKEWORD(LOBYTE(result) - RCT2_GLOBAL(0x00F438AC, uint8), HIBYTE(result));
}
rct_vehicle_sound* vehicle_sound = &RCT2_GLOBAL(RCT2_ADDRESS_VEHICLE_SOUND_LIST, rct_vehicle_sound);
while (sound_unknown->id != vehicle_sound->id) {
vehicle_sound++;
if (vehicle_sound >= &RCT2_GLOBAL(0x009AF42C, rct_vehicle_sound)) {
vehicle_sound = &RCT2_GLOBAL(RCT2_ADDRESS_VEHICLE_SOUND_LIST, rct_vehicle_sound);
int i = 0;
while (vehicle_sound->id != (uint16)-1) {
vehicle_sound++;
i++;
if (i >= RCT2_GLOBAL(0x009AAC75, sint8)) {
sound_unknown = (rct_sound_unknown*)((int)sound_unknown + sound_unknown->next);
goto label28;
}
}
vehicle_sound->id = sound_unknown->id;
vehicle_sound->sound1_id = (uint16)-1;
vehicle_sound->sound2_id = (uint16)-1;
vehicle_sound->var_2 = 0x30;
break;
}
}
uint8 v21 = LOBYTE(sound_unknown->var_8);
uint8 v22 = LOBYTE(vehicle_sound->var_2);
if (v22 != v21) {
if (v22 < v21) {
v22 += 4;
} else {
v22 -= 4;
}
}
vehicle_sound->var_2 = v22;
if (LOBYTE(result) < v22) {
result = MAKEWORD(0, HIBYTE(result));
} else {
result = MAKEWORD(LOBYTE(result) - v22, HIBYTE(result));
}
// do sound1 stuff, track noise
RCT2_ADDRESS_SPRITE_LIST;
rct_sprite* sprite = &g_sprite_list[sound_unknown->id];
sint16 volume = sprite->vehicle.var_BC;
volume *= LOBYTE(result);
volume = (uint16)volume / 8;
volume -= 0x1FFF;
if (volume < -10000) {
volume = -10000;
}
if (sprite->vehicle.var_BB == (uint8)-1) {
if (vehicle_sound->sound1_id != (uint16)-1) {
vehicle_sound->sound1_id = -1;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_stop(&vehicle_sound->sound1);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
} else {
if (vehicle_sound->sound1_id == (uint16)-1) {
goto label69;
}
if (sprite->vehicle.var_BB != vehicle_sound->sound1_id) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_stop(&vehicle_sound->sound1);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
label69:
vehicle_sound->sound1_id = sprite->vehicle.var_BB;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_prepare(sprite->vehicle.var_BB, &vehicle_sound->sound1, 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32));
RCT2_GLOBAL(0x014241BC, uint32) = 0;
vehicle_sound->sound1_pan = sound_unknown->pan;
vehicle_sound->sound1_volume = volume;
vehicle_sound->sound1_freq = sound_unknown->frequency;
uint16 frequency = sound_unknown->frequency;
if (RCT2_ADDRESS(0x009AF51F, uint8)[2 * sprite->vehicle.var_BB] & 2) {
frequency = (frequency / 2) + 4000;
}
uint8 looping = RCT2_ADDRESS(0x009AF51E, uint8)[2 * sprite->vehicle.var_BB];
int pan = sound_unknown->pan;
if (!RCT2_GLOBAL(0x009AAC6D, uint8)) {
pan = 0;
}
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_play(&vehicle_sound->sound1, looping, volume, pan, frequency);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
goto label87;
}
if (volume != vehicle_sound->sound1_volume) {
vehicle_sound->sound1_volume = volume;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_set_volume(&vehicle_sound->sound1, volume);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
if (sound_unknown->pan != vehicle_sound->sound1_pan) {
vehicle_sound->sound1_pan = sound_unknown->pan;
if (RCT2_GLOBAL(0x009AAC6D, uint8)) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_set_pan(&vehicle_sound->sound1, sound_unknown->pan);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
}
if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3) && sound_unknown->frequency != vehicle_sound->sound1_freq) {
vehicle_sound->sound1_freq = sound_unknown->frequency;
uint16 frequency = sound_unknown->frequency;
if (RCT2_GLOBAL(0x009AF51F, uint8*)[2 * sprite->vehicle.var_BB] & 2) {
frequency = (frequency / 2) + 4000;
}
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_set_frequency(&vehicle_sound->sound1, frequency);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
}
label87: // do sound2 stuff, screams
sprite = &g_sprite_list[sound_unknown->id];
volume = sprite->vehicle.var_BE;
volume *= LOBYTE(result);
volume = (uint16)volume / 8;
volume -= 0x1FFF;
if (volume < -10000) {
volume = -10000;
}
if (sprite->vehicle.var_BD == (uint8)-1) {
if (vehicle_sound->sound2_id != (uint16)-1) {
vehicle_sound->sound2_id = -1;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_stop(&vehicle_sound->sound2);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
} else {
if (vehicle_sound->sound2_id == (uint16)-1) {
goto label93;
}
if (sprite->vehicle.var_BD != vehicle_sound->sound2_id) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_stop(&vehicle_sound->sound2);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
label93:
vehicle_sound->sound2_id = sprite->vehicle.var_BD;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_prepare(sprite->vehicle.var_BD, &vehicle_sound->sound2, 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32));
RCT2_GLOBAL(0x014241BC, uint32) = 0;
vehicle_sound->sound2_pan = sound_unknown->pan;
vehicle_sound->sound2_volume = volume;
vehicle_sound->sound2_freq = sound_unknown->frequency;
uint16 frequency = sound_unknown->frequency;
if (RCT2_ADDRESS(0x009AF51F, uint8)[2 * sprite->vehicle.var_BD] & 1) {
frequency = 12649;
}
frequency = (frequency * 2) - 3248;
if (frequency > 25700) {
frequency = 25700;
}
uint8 looping = RCT2_ADDRESS(0x009AF51E, uint8)[2 * sprite->vehicle.var_BD];
int pan = sound_unknown->pan;
if (!RCT2_GLOBAL(0x009AAC6D, uint8)) {
pan = 0;
}
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_play(&vehicle_sound->sound2, looping, volume, pan, frequency);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
goto label114;
}
if (volume != vehicle_sound->sound2_volume) {
vehicle_sound->sound2_volume = volume;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_set_volume(&vehicle_sound->sound2, volume);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
if (sound_unknown->pan != vehicle_sound->sound2_pan) {
vehicle_sound->sound2_pan = sound_unknown->pan;
if (RCT2_GLOBAL(0x009AAC6D, uint8)) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_set_pan(&vehicle_sound->sound2, sound_unknown->pan);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
}
if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3) && sound_unknown->frequency != vehicle_sound->sound2_freq) {
vehicle_sound->sound2_freq = sound_unknown->frequency;
if (!(RCT2_ADDRESS(0x009AF51F, uint8)[2 * sprite->vehicle.var_BD] & 1)) {
uint16 frequency = (sound_unknown->frequency * 2) - 3248;
if (frequency > 25700) {
frequency = 25700;
}
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_set_frequency(&vehicle_sound->sound2, frequency);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
}
}
label114:
1;
}
}
}
}
/**
*
* rct2: 0x006D4204

View File

@ -25,10 +25,10 @@
typedef union {
struct {
uint16 width;
uint16 height;
sint16 width;
sint16 height;
};
uint32 both;
sint32 both;
} rct_widthheight;
typedef struct {
@ -48,28 +48,46 @@ typedef struct {
rct_widthheight view; // 0x1A
uint16 var_1E;
uint8 pad_20[0x08];
uint32 var_28;
sint32 var_28;
uint8 pad_2C[0x04];
uint8 ride; // 0x30
uint8 var_31;
uint8 pad_32[0x0C];
uint8 pad_32[0x02];
uint16 var_34;
uint8 pad_36[0x08];
uint16 next_vehicle_on_train; // 0x3E
uint8 pad_40[0x08];
uint32 var_40;
uint16 var_44;
uint16 var_46;
uint16 var_48;
uint8 pad_4A[0x06];
uint8 var_50;
uint8 var_51;
uint8 pad_52[0x2E];
uint16 peep; // 0x52
uint8 pad_54[0x2C];
uint16 var_80;
uint8 pad_82[0x31];
uint8 var_B3;
uint8 pad_B4[0x07];
uint8 var_BB;
uint8 var_BC;
uint8 var_BD;
uint8 pad_BE[0x0E];
uint8 var_BE;
sint8 var_BF;
uint8 pad_C0[0x02];
uint8 speed; // 0xC2
uint8 pad_C3[0x09];
uint8 var_CC;
uint8 pad_CD[0x09];
uint8 var_CD;
uint8 var_CE;
uint8 pad_CF[0x07];
uint8 var_D6;
} rct_vehicle;
void vehicle_update_all();
int sub_6BC2F3(rct_vehicle* vehicle);
void sub_6BB9FF(rct_vehicle* vehicle);
void vehicle_sounds_update();
/** Helper macro until rides are stored in this module. */
#define GET_VEHICLE(sprite_index) &(g_sprite_list[sprite_index].vehicle)

View File

@ -383,7 +383,7 @@ rct_window *window_create(int x, int y, int width, int height, uint32 *event_han
// Play sounds and flash the window
if (!(flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT))){
w->flags |= WF_WHITE_BORDER_MASK;
sound_play_panned(SOUND_WINDOW_OPEN, x + (width / 2));
sound_play_panned(SOUND_WINDOW_OPEN, x + (width / 2), 0, 0, 0);
}
w->number = 0;

View File

@ -730,7 +730,7 @@ static void window_footpath_place_path_at_point(int x, int y)
// bp = 0x009DEA62
// dx = 0x009DEA60
// cx = 0x009DEA5E
sound_play_panned(SOUND_PLACE_ITEM, 0x8001);
sound_play_panned(SOUND_PLACE_ITEM, 0x8001, RCT2_GLOBAL(0x009DEA5E, uint16), RCT2_GLOBAL(0x009DEA60, uint16), RCT2_GLOBAL(0x009DEA62, uint16));
}
}

View File

@ -658,7 +658,7 @@ static void window_new_ride_scrollmousedown()
RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_RIDE_LIST_HIGHLIGHTED_ITEM, ride_list_item)[_window_new_ride_current_tab] = item;
w->new_ride.selected_ride_id = *((sint16*)&item);
sound_play_panned(SOUND_CLICK_1, w->x + (w->width / 2));
sound_play_panned(SOUND_CLICK_1, w->x + (w->width / 2), 0, 0, 0);
w->new_ride.selected_ride_countdown = 8;
window_invalidate(w);
}

View File

@ -150,7 +150,7 @@ static void window_news_update(rct_window *w)
return;
window_invalidate(w);
sound_play_panned(SOUND_CLICK_2, w->x + (w->width / 2));
sound_play_panned(SOUND_CLICK_2, w->x + (w->width / 2), 0, 0, 0);
newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
j = w->news.var_480;
@ -255,7 +255,7 @@ static void window_news_scrollmousedown()
w->news.var_482 = buttonIndex;
w->news.var_484 = 4;
window_invalidate(w);
sound_play_panned(SOUND_CLICK_1, w->x + (w->width / 2));
sound_play_panned(SOUND_CLICK_1, w->x + (w->width / 2), 0, 0, 0);
}
}

View File

@ -33,6 +33,7 @@
#include "config.h"
#include "gfx.h"
#include "language.h"
#include "mixer.h"
#include "osinterface.h"
#include "sprites.h"
#include "string_ids.h"
@ -503,6 +504,9 @@ static void window_options_dropdown()
switch (widgetIndex) {
case WIDX_SOUND_DROPDOWN:
audio_init2(dropdownIndex);
if (dropdownIndex < gAudioDeviceCount) {
Mixer_Init(gAudioDevices[dropdownIndex].name);
}
/*#ifdef _MSC_VER
__asm movzx ax, dropdownIndex
#else

View File

@ -774,7 +774,7 @@ void window_scenery_scrollmousedown() {
window_scenery_selected_scenery_by_tab[tabIndex] = sceneryId;
window_scenery_is_repaint_scenery_tool_on &= 0xFE;
sound_play_panned(4, (w->width >> 1) + w->x);
sound_play_panned(4, (w->width >> 1) + w->x, 0, 0, 0);
w->scenery.hover_counter = -16;
RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000;
window_invalidate(w);

View File

@ -244,7 +244,7 @@ static void window_scenarioselect_scrollmousedown()
if (y >= 0)
continue;
sound_play_panned(SOUND_CLICK_1, w->width / 2 + w->x);
sound_play_panned(SOUND_CLICK_1, w->width / 2 + w->x, 0, 0, 0);
scenario_load_and_play(scenario);
break;
}