mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 into zsilencer-master
Conflicts: projects/openrct2.vcxproj.filters
This commit is contained in:
commit
f78b7a4c74
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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
|
||||
|
|
297
src/audio.c
297
src/audio.c
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
79
src/audio.h
79
src/audio.h
|
@ -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
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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++;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
36
src/peep.c
36
src/peep.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
49
src/ride.c
49
src/ride.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
16
src/ride.h
16
src/ride.h
|
@ -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
|
||||
|
|
434
src/vehicle.c
434
src/vehicle.c
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue