mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
Merge branch 'master' of https://github.com/mamedev/mame.git
This commit is contained in:
commit
c4d91605fc
32
3rdparty/bgfx/3rdparty/iqa/LICENSE
vendored
Normal file
32
3rdparty/bgfx/3rdparty/iqa/LICENSE
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
36
3rdparty/bgfx/3rdparty/iqa/README.txt
vendored
Normal file
36
3rdparty/bgfx/3rdparty/iqa/README.txt
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
Doxygen documentation can be found at: http://tdistler.com/iqa
|
||||
|
||||
BUILD:
|
||||
|
||||
All build artifacts end up in build/<configuration>, where <configuration> is
|
||||
'debug' or 'release'.
|
||||
|
||||
Windows:
|
||||
- Open iqa.sln, select 'Debug' or 'Release', and build. The output is a
|
||||
static library 'iqa.lib'.
|
||||
- To run the tests under the debugger, first right-click the 'test' project,
|
||||
select Properties -> Configuration Properties -> Debugging and set
|
||||
'Working Directory' to '$(OutDir)'. Then start the application.
|
||||
|
||||
Linux:
|
||||
- Change directories into the root of the IQA branch you want to build.
|
||||
- Type `make` for a debug build, or `make RELEASE=1` for a release build.
|
||||
The output is a static library 'libiqa.a'.
|
||||
- Type `make test` (or `make test RELEASE=1`) to build the unit tests.
|
||||
- Type `make clean` (or `make clean RELEASE=1`) to delete all build
|
||||
artifacts.
|
||||
- To run the tests, `cd` to the build/<configuration> directory and type
|
||||
`./test`.
|
||||
|
||||
|
||||
USE:
|
||||
|
||||
- Include 'iqa.h' in your source file.
|
||||
- Call iqa_* methods.
|
||||
- Link against the IQA library.
|
||||
|
||||
|
||||
HELP & SUPPORT:
|
||||
|
||||
Further help can be found at: https://sourceforge.net/projects/iqa/support
|
||||
|
111
3rdparty/bgfx/3rdparty/iqa/include/convolve.h
vendored
Normal file
111
3rdparty/bgfx/3rdparty/iqa/include/convolve.h
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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 _CONVOLVE_H_
|
||||
#define _CONVOLVE_H_
|
||||
|
||||
typedef float (*_iqa_get_pixel)(const float *img, int w, int h, int x, int y, float bnd_const);
|
||||
|
||||
/** Out-of-bounds array values are a mirrored reflection of the border values*/
|
||||
float KBND_SYMMETRIC(const float *img, int w, int h, int x, int y, float bnd_const);
|
||||
/** Out-of-bounds array values are set to the nearest border value */
|
||||
float KBND_REPLICATE(const float *img, int w, int h, int x, int y, float bnd_const);
|
||||
/** Out-of-bounds array values are set to 'bnd_const' */
|
||||
float KBND_CONSTANT(const float *img, int w, int h, int x, int y, float bnd_const);
|
||||
|
||||
|
||||
/** Defines a convolution kernel */
|
||||
struct _kernel {
|
||||
float *kernel; /**< Pointer to the kernel values */
|
||||
int w; /**< The kernel width */
|
||||
int h; /**< The kernel height */
|
||||
int normalized; /**< 1 if the kernel values add up to 1. 0 otherwise */
|
||||
_iqa_get_pixel bnd_opt; /**< Defines how out-of-bounds image values are handled */
|
||||
float bnd_const; /**< If 'bnd_opt' is KBND_CONSTANT, this specifies the out-of-bounds value */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Applies the specified kernel to the image.
|
||||
* The kernel will be applied to all areas where it fits completely within
|
||||
* the image. The resulting image will be smaller by half the kernel width
|
||||
* and height (w - kw/2 and h - kh/2).
|
||||
*
|
||||
* @param img Image to modify
|
||||
* @param w Image width
|
||||
* @param h Image height
|
||||
* @param k The kernel to apply
|
||||
* @param result Buffer to hold the resulting image ((w-kw)*(h-kh), where kw
|
||||
* and kh are the kernel width and height). If 0, the result
|
||||
* will be written to the original image buffer.
|
||||
* @param rw Optional. The width of the resulting image will be stored here.
|
||||
* @param rh Optional. The height of the resulting image will be stored here.
|
||||
*/
|
||||
void _iqa_convolve(float *img, int w, int h, const struct _kernel *k, float *result, int *rw, int *rh);
|
||||
|
||||
/**
|
||||
* The same as _iqa_convolve() except the kernel is applied to the entire image.
|
||||
* In other words, the kernel is applied to all areas where the top-left corner
|
||||
* of the kernel is in the image. Out-of-bound pixel value (off the right and
|
||||
* bottom edges) are chosen based on the 'bnd_opt' and 'bnd_const' members of
|
||||
* the kernel structure. The resulting array is the same size as the input
|
||||
* image.
|
||||
*
|
||||
* @param img Image to modify
|
||||
* @param w Image width
|
||||
* @param h Image height
|
||||
* @param k The kernel to apply
|
||||
* @param result Buffer to hold the resulting image ((w-kw)*(h-kh), where kw
|
||||
* and kh are the kernel width and height). If 0, the result
|
||||
* will be written to the original image buffer.
|
||||
* @return 0 if successful. Non-zero otherwise.
|
||||
*/
|
||||
int _iqa_img_filter(float *img, int w, int h, const struct _kernel *k, float *result);
|
||||
|
||||
/**
|
||||
* Returns the filtered version of the specified pixel. If no kernel is given,
|
||||
* the raw pixel value is returned.
|
||||
*
|
||||
* @param img Source image
|
||||
* @param w Image width
|
||||
* @param h Image height
|
||||
* @param x The x location of the pixel to filter
|
||||
* @param y The y location of the pixel to filter
|
||||
* @param k Optional. The convolution kernel to apply to the pixel.
|
||||
* @param kscale The scale of the kernel (for normalization). 1 for normalized
|
||||
* kernels. Required if 'k' is not null.
|
||||
* @return The filtered pixel value.
|
||||
*/
|
||||
float _iqa_filter_pixel(const float *img, int w, int h, int x, int y, const struct _kernel *k, const float kscale);
|
||||
|
||||
|
||||
#endif /*_CONVOLVE_H_*/
|
55
3rdparty/bgfx/3rdparty/iqa/include/decimate.h
vendored
Normal file
55
3rdparty/bgfx/3rdparty/iqa/include/decimate.h
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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 _DECIMATE_H_
|
||||
#define _DECIMATE_H_
|
||||
|
||||
#include "convolve.h"
|
||||
|
||||
/**
|
||||
* @brief Downsamples (decimates) an image.
|
||||
*
|
||||
* @param img Image to modify
|
||||
* @param w Image width
|
||||
* @param h Image height
|
||||
* @param factor Decimation factor
|
||||
* @param k The kernel to apply (e.g. low-pass filter). Can be 0.
|
||||
* @param result Buffer to hold the resulting image (w/factor*h/factor). If 0,
|
||||
* the result will be written to the original image buffer.
|
||||
* @param rw Optional. The width of the resulting image will be stored here.
|
||||
* @param rh Optional. The height of the resulting image will be stored here.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int _iqa_decimate(float *img, int w, int h, int factor, const struct _kernel *k, float *result, int *rw, int *rh);
|
||||
|
||||
#endif /*_DECIMATE_H_*/
|
134
3rdparty/bgfx/3rdparty/iqa/include/iqa.h
vendored
Normal file
134
3rdparty/bgfx/3rdparty/iqa/include/iqa.h
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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 _IQA_H_
|
||||
#define _IQA_H_
|
||||
|
||||
#include "iqa_os.h"
|
||||
|
||||
/**
|
||||
* Allows fine-grain control of the SSIM algorithm.
|
||||
*/
|
||||
struct iqa_ssim_args {
|
||||
float alpha; /**< luminance exponent */
|
||||
float beta; /**< contrast exponent */
|
||||
float gamma; /**< structure exponent */
|
||||
int L; /**< dynamic range (2^8 - 1)*/
|
||||
float K1; /**< stabilization constant 1 */
|
||||
float K2; /**< stabilization constant 2 */
|
||||
int f; /**< scale factor. 0=default scaling, 1=no scaling */
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows fine-grain control of the MS-SSIM algorithm.
|
||||
*/
|
||||
struct iqa_ms_ssim_args {
|
||||
int wang; /**< 1=original algorithm by Wang, et al. 0=MS-SSIM* by Rouse/Hemami (default). */
|
||||
int gaussian; /**< 1=11x11 Gaussian window (default). 0=8x8 linear window. */
|
||||
int scales; /**< Number of scaled images to use. Default is 5. */
|
||||
const float *alphas; /**< Pointer to array of alpha values for each scale. Required if 'scales' isn't 5. */
|
||||
const float *betas; /**< Pointer to array of beta values for each scale. Required if 'scales' isn't 5. */
|
||||
const float *gammas; /**< Pointer to array of gamma values for each scale. Required if 'scales' isn't 5. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the Mean Squared Error between 2 equal-sized 8-bit images.
|
||||
* @note The images must have the same width, height, and stride.
|
||||
* @param ref Original reference image
|
||||
* @param cmp Distorted image
|
||||
* @param w Width of the images
|
||||
* @param h Height of the images
|
||||
* @param stride The length (in bytes) of each horizontal line in the image.
|
||||
* This may be different from the image width.
|
||||
* @return The MSE.
|
||||
*/
|
||||
float iqa_mse(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride);
|
||||
|
||||
/**
|
||||
* Calculates the Peak Signal-to-Noise-Ratio between 2 equal-sized 8-bit
|
||||
* images.
|
||||
* @note The images must have the same width, height, and stride.
|
||||
* @param ref Original reference image
|
||||
* @param cmp Distorted image
|
||||
* @param w Width of the images
|
||||
* @param h Height of the images
|
||||
* @param stride The length (in bytes) of each horizontal line in the image.
|
||||
* This may be different from the image width.
|
||||
* @return The PSNR.
|
||||
*/
|
||||
float iqa_psnr(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride);
|
||||
|
||||
/**
|
||||
* Calculates the Structural SIMilarity between 2 equal-sized 8-bit images.
|
||||
*
|
||||
* See https://ece.uwaterloo.ca/~z70wang/publications/ssim.html
|
||||
* @note The images must have the same width, height, and stride.
|
||||
* @param ref Original reference image
|
||||
* @param cmp Distorted image
|
||||
* @param w Width of the images
|
||||
* @param h Height of the images
|
||||
* @param stride The length (in bytes) of each horizontal line in the image.
|
||||
* This may be different from the image width.
|
||||
* @param gaussian 0 = 8x8 square window, 1 = 11x11 circular-symmetric Gaussian
|
||||
* weighting.
|
||||
* @param args Optional SSIM arguments for fine control of the algorithm. 0 for
|
||||
* defaults. Defaults are a=b=g=1.0, L=255, K1=0.01, K2=0.03
|
||||
* @return The mean SSIM over the entire image (MSSIM), or INFINITY if error.
|
||||
*/
|
||||
float iqa_ssim(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride,
|
||||
int gaussian, const struct iqa_ssim_args *args);
|
||||
|
||||
/**
|
||||
* Calculates the Multi-Scale Structural SIMilarity between 2 equal-sized 8-bit
|
||||
* images. The default algorithm is MS-SSIM* proposed by Rouse/Hemami 2008.
|
||||
*
|
||||
* See https://ece.uwaterloo.ca/~z70wang/publications/msssim.pdf and
|
||||
* http://foulard.ece.cornell.edu/publications/dmr_hvei2008_paper.pdf
|
||||
*
|
||||
* @note 1. The images must have the same width, height, and stride.
|
||||
* @note 2. The minimum image width or height is 2^(scales-1) * filter, where 'filter' is 11
|
||||
* if a Gaussian window is being used, or 9 otherwise.
|
||||
* @param ref Original reference image
|
||||
* @param cmp Distorted image
|
||||
* @param w Width of the images.
|
||||
* @param h Height of the images.
|
||||
* @param stride The length (in bytes) of each horizontal line in the image.
|
||||
* This may be different from the image width.
|
||||
* @param args Optional MS-SSIM arguments for fine control of the algorithm. 0
|
||||
* for defaults. Defaults are wang=0, scales=5, gaussian=1.
|
||||
* @return The mean MS-SSIM over the entire image, or INFINITY if error.
|
||||
*/
|
||||
float iqa_ms_ssim(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride,
|
||||
const struct iqa_ms_ssim_args *args);
|
||||
|
||||
#endif /*_IQA_H_*/
|
68
3rdparty/bgfx/3rdparty/iqa/include/iqa_os.h
vendored
Normal file
68
3rdparty/bgfx/3rdparty/iqa/include/iqa_os.h
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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 _OS_H_
|
||||
#define _OS_H_
|
||||
|
||||
/* Microsoft tends to implement features early, but they have a high legacy
|
||||
* cost because they won't break existing implementations. As such, certain
|
||||
* features we take for granted on other platforms (like C99) aren't fully
|
||||
* implemented. This file is meant to rectify that.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <math.h>
|
||||
|
||||
#define IQA_INLINE __inline
|
||||
|
||||
#ifndef INFINITY
|
||||
#define INFINITY (float)HUGE_VAL /**< Defined in C99 (Windows is C89) */
|
||||
#endif /*INFINITY*/
|
||||
|
||||
#ifndef NAN
|
||||
static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
|
||||
#define NAN (*(const float *) __nan) /**< Defined in C99 (Windows is C99) */
|
||||
#endif
|
||||
|
||||
#define IQA_EXPORT __declspec(dllexport)
|
||||
|
||||
#else /* !Windows */
|
||||
|
||||
#define IQA_INLINE inline
|
||||
#define IQA_EXPORT
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _OS_H_ */
|
64
3rdparty/bgfx/3rdparty/iqa/include/math_utils.h
vendored
Normal file
64
3rdparty/bgfx/3rdparty/iqa/include/math_utils.h
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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 _MATH_UTILS_H_
|
||||
#define _MATH_UTILS_H_
|
||||
|
||||
#include "iqa_os.h"
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* Rounds a float to the nearest integer.
|
||||
*/
|
||||
IQA_EXPORT IQA_INLINE int _round(float a);
|
||||
|
||||
IQA_EXPORT IQA_INLINE int _max(int x, int y);
|
||||
|
||||
IQA_EXPORT IQA_INLINE int _min(int x, int y);
|
||||
|
||||
|
||||
/**
|
||||
* Compares 2 floats to the specified digit of precision.
|
||||
* @return 0 if equal, 1 otherwise.
|
||||
*/
|
||||
IQA_EXPORT IQA_INLINE int _cmp_float(float a, float b, int digits);
|
||||
|
||||
|
||||
/**
|
||||
* Compares 2 matrices with the specified precision. 'b' is assumed to be the
|
||||
* same size as 'a' or smaller.
|
||||
* @return 0 if equal, 1 otherwise
|
||||
*/
|
||||
IQA_EXPORT IQA_INLINE int _matrix_cmp(const float *a, const float *b, int w, int h, int digits);
|
||||
|
||||
#endif /*_MATH_UTILS_H_*/
|
117
3rdparty/bgfx/3rdparty/iqa/include/ssim.h
vendored
Normal file
117
3rdparty/bgfx/3rdparty/iqa/include/ssim.h
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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 _SSIM_H_
|
||||
#define _SSIM_H_
|
||||
|
||||
#include "convolve.h"
|
||||
|
||||
/*
|
||||
* Circular-symmetric Gaussian weighting.
|
||||
* h(x,y) = hg(x,y)/SUM(SUM(hg)) , for normalization to 1.0
|
||||
* hg(x,y) = e^( -0.5*( (x^2+y^2)/sigma^2 ) ) , where sigma was 1.5
|
||||
*/
|
||||
#define GAUSSIAN_LEN 11
|
||||
static const float g_gaussian_window[GAUSSIAN_LEN][GAUSSIAN_LEN] = {
|
||||
{0.000001f, 0.000008f, 0.000037f, 0.000112f, 0.000219f, 0.000274f, 0.000219f, 0.000112f, 0.000037f, 0.000008f, 0.000001f},
|
||||
{0.000008f, 0.000058f, 0.000274f, 0.000831f, 0.001619f, 0.002021f, 0.001619f, 0.000831f, 0.000274f, 0.000058f, 0.000008f},
|
||||
{0.000037f, 0.000274f, 0.001296f, 0.003937f, 0.007668f, 0.009577f, 0.007668f, 0.003937f, 0.001296f, 0.000274f, 0.000037f},
|
||||
{0.000112f, 0.000831f, 0.003937f, 0.011960f, 0.023294f, 0.029091f, 0.023294f, 0.011960f, 0.003937f, 0.000831f, 0.000112f},
|
||||
{0.000219f, 0.001619f, 0.007668f, 0.023294f, 0.045371f, 0.056662f, 0.045371f, 0.023294f, 0.007668f, 0.001619f, 0.000219f},
|
||||
{0.000274f, 0.002021f, 0.009577f, 0.029091f, 0.056662f, 0.070762f, 0.056662f, 0.029091f, 0.009577f, 0.002021f, 0.000274f},
|
||||
{0.000219f, 0.001619f, 0.007668f, 0.023294f, 0.045371f, 0.056662f, 0.045371f, 0.023294f, 0.007668f, 0.001619f, 0.000219f},
|
||||
{0.000112f, 0.000831f, 0.003937f, 0.011960f, 0.023294f, 0.029091f, 0.023294f, 0.011960f, 0.003937f, 0.000831f, 0.000112f},
|
||||
{0.000037f, 0.000274f, 0.001296f, 0.003937f, 0.007668f, 0.009577f, 0.007668f, 0.003937f, 0.001296f, 0.000274f, 0.000037f},
|
||||
{0.000008f, 0.000058f, 0.000274f, 0.000831f, 0.001619f, 0.002021f, 0.001619f, 0.000831f, 0.000274f, 0.000058f, 0.000008f},
|
||||
{0.000001f, 0.000008f, 0.000037f, 0.000112f, 0.000219f, 0.000274f, 0.000219f, 0.000112f, 0.000037f, 0.000008f, 0.000001f},
|
||||
};
|
||||
|
||||
/*
|
||||
* Equal weight square window.
|
||||
* Each pixel is equally weighted (1/64) so that SUM(x) = 1.0
|
||||
*/
|
||||
#define SQUARE_LEN 8
|
||||
static const float g_square_window[SQUARE_LEN][SQUARE_LEN] = {
|
||||
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
|
||||
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
|
||||
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
|
||||
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
|
||||
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
|
||||
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
|
||||
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
|
||||
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
|
||||
};
|
||||
|
||||
/* Holds intermediate SSIM values for map-reduce operation. */
|
||||
struct _ssim_int {
|
||||
double l;
|
||||
double c;
|
||||
double s;
|
||||
};
|
||||
|
||||
/* Defines the pointers to the map-reduce functions. */
|
||||
typedef int (*_map)(const struct _ssim_int *, void *);
|
||||
typedef float (*_reduce)(int, int, void *);
|
||||
|
||||
/* Arguments for map-reduce. The 'context' is user-defined. */
|
||||
struct _map_reduce {
|
||||
_map map;
|
||||
_reduce reduce;
|
||||
void *context;
|
||||
};
|
||||
|
||||
/**
|
||||
* Private method that calculates the SSIM value on a pre-processed image.
|
||||
*
|
||||
* The input images must have stride==width. This method does not scale.
|
||||
*
|
||||
* @note Image buffers are modified.
|
||||
*
|
||||
* Map-reduce is used for doing the final SSIM calculation. The map function is
|
||||
* called for every pixel, and the reduce is called at the end. The context is
|
||||
* caller-defined and *not* modified by this method.
|
||||
*
|
||||
* @param ref Original reference image
|
||||
* @param cmp Distorted image
|
||||
* @param w Width of the images
|
||||
* @param h Height of the images
|
||||
* @param k The kernel used as the window function
|
||||
* @param mr Optional map-reduce functions to use to calculate SSIM. Required
|
||||
* if 'args' is not null. Ignored if 'args' is null.
|
||||
* @param args Optional SSIM arguments for fine control of the algorithm. 0 for defaults.
|
||||
* Defaults are a=b=g=1.0, L=255, K1=0.01, K2=0.03
|
||||
* @return The mean SSIM over the entire image (MSSIM), or INFINITY if error.
|
||||
*/
|
||||
float _iqa_ssim(float *ref, float *cmp, int w, int h, const struct _kernel *k, const struct _map_reduce *mr, const struct iqa_ssim_args *args);
|
||||
|
||||
#endif /* _SSIM_H_ */
|
195
3rdparty/bgfx/3rdparty/iqa/source/convolve.c
vendored
Normal file
195
3rdparty/bgfx/3rdparty/iqa/source/convolve.c
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
#include "convolve.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
float KBND_SYMMETRIC(const float *img, int w, int h, int x, int y, float bnd_const)
|
||||
{
|
||||
(void)bnd_const;
|
||||
if (x<0) x=-1-x;
|
||||
else if (x>=w) x=(w-(x-w))-1;
|
||||
if (y<0) y=-1-y;
|
||||
else if (y>=h) y=(h-(y-h))-1;
|
||||
return img[y*w + x];
|
||||
}
|
||||
|
||||
float KBND_REPLICATE(const float *img, int w, int h, int x, int y, float bnd_const)
|
||||
{
|
||||
(void)bnd_const;
|
||||
if (x<0) x=0;
|
||||
if (x>=w) x=w-1;
|
||||
if (y<0) y=0;
|
||||
if (y>=h) y=h-1;
|
||||
return img[y*w + x];
|
||||
}
|
||||
|
||||
float KBND_CONSTANT(const float *img, int w, int h, int x, int y, float bnd_const)
|
||||
{
|
||||
if (x<0) x=0;
|
||||
if (y<0) y=0;
|
||||
if (x>=w || y>=h)
|
||||
return bnd_const;
|
||||
return img[y*w + x];
|
||||
}
|
||||
|
||||
static float _calc_scale(const struct _kernel *k)
|
||||
{
|
||||
int ii,k_len;
|
||||
double sum=0.0;
|
||||
|
||||
if (k->normalized)
|
||||
return 1.0f;
|
||||
else {
|
||||
k_len = k->w * k->h;
|
||||
for (ii=0; ii<k_len; ++ii)
|
||||
sum += k->kernel[ii];
|
||||
if (sum != 0.0)
|
||||
return (float)(1.0 / sum);
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void _iqa_convolve(float *img, int w, int h, const struct _kernel *k, float *result, int *rw, int *rh)
|
||||
{
|
||||
int x,y,kx,ky,u,v;
|
||||
int uc = k->w/2;
|
||||
int vc = k->h/2;
|
||||
int kw_even = (k->w&1)?0:1;
|
||||
int kh_even = (k->h&1)?0:1;
|
||||
int dst_w = w - k->w + 1;
|
||||
int dst_h = h - k->h + 1;
|
||||
int img_offset,k_offset;
|
||||
double sum;
|
||||
float scale, *dst=result;
|
||||
|
||||
if (!dst)
|
||||
dst = img; /* Convolve in-place */
|
||||
|
||||
/* Kernel is applied to all positions where the kernel is fully contained
|
||||
* in the image */
|
||||
scale = _calc_scale(k);
|
||||
for (y=0; y < dst_h; ++y) {
|
||||
for (x=0; x < dst_w; ++x) {
|
||||
sum = 0.0;
|
||||
k_offset = 0;
|
||||
ky = y+vc;
|
||||
kx = x+uc;
|
||||
for (v=-vc; v <= vc-kh_even; ++v) {
|
||||
img_offset = (ky+v)*w + kx;
|
||||
for (u=-uc; u <= uc-kw_even; ++u, ++k_offset) {
|
||||
sum += img[img_offset+u] * k->kernel[k_offset];
|
||||
}
|
||||
}
|
||||
dst[y*dst_w + x] = (float)(sum * scale);
|
||||
}
|
||||
}
|
||||
|
||||
if (rw) *rw = dst_w;
|
||||
if (rh) *rh = dst_h;
|
||||
}
|
||||
|
||||
int _iqa_img_filter(float *img, int w, int h, const struct _kernel *k, float *result)
|
||||
{
|
||||
int x,y;
|
||||
int img_offset;
|
||||
float scale, *dst=result;
|
||||
|
||||
if (!k || !k->bnd_opt)
|
||||
return 1;
|
||||
|
||||
if (!dst) {
|
||||
dst = (float*)malloc(w*h*sizeof(float));
|
||||
if (!dst)
|
||||
return 2;
|
||||
}
|
||||
|
||||
scale = _calc_scale(k);
|
||||
|
||||
/* Kernel is applied to all positions where top-left corner is in the image */
|
||||
for (y=0; y < h; ++y) {
|
||||
for (x=0; x < w; ++x) {
|
||||
dst[y*w + x] = _iqa_filter_pixel(img, w, h, x, y, k, scale);
|
||||
}
|
||||
}
|
||||
|
||||
/* If no result buffer given, copy results to image buffer */
|
||||
if (!result) {
|
||||
for (y=0; y<h; ++y) {
|
||||
img_offset = y*w;
|
||||
for (x=0; x<w; ++x, ++img_offset) {
|
||||
img[img_offset] = dst[img_offset];
|
||||
}
|
||||
}
|
||||
free(dst);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
float _iqa_filter_pixel(const float *img, int w, int h, int x, int y, const struct _kernel *k, const float kscale)
|
||||
{
|
||||
int u,v,uc,vc;
|
||||
int kw_even,kh_even;
|
||||
int x_edge_left,x_edge_right,y_edge_top,y_edge_bottom;
|
||||
int edge,img_offset,k_offset;
|
||||
double sum;
|
||||
|
||||
if (!k)
|
||||
return img[y*w + x];
|
||||
|
||||
uc = k->w/2;
|
||||
vc = k->h/2;
|
||||
kw_even = (k->w&1)?0:1;
|
||||
kh_even = (k->h&1)?0:1;
|
||||
x_edge_left = uc;
|
||||
x_edge_right = w-uc;
|
||||
y_edge_top = vc;
|
||||
y_edge_bottom = h-vc;
|
||||
|
||||
edge = 0;
|
||||
if (x < x_edge_left || y < y_edge_top || x >= x_edge_right || y >= y_edge_bottom)
|
||||
edge = 1;
|
||||
|
||||
sum = 0.0;
|
||||
k_offset = 0;
|
||||
for (v=-vc; v <= vc-kh_even; ++v) {
|
||||
img_offset = (y+v)*w + x;
|
||||
for (u=-uc; u <= uc-kw_even; ++u, ++k_offset) {
|
||||
if (!edge)
|
||||
sum += img[img_offset+u] * k->kernel[k_offset];
|
||||
else
|
||||
sum += k->bnd_opt(img, w, h, x+u, y+v, k->bnd_const) * k->kernel[k_offset];
|
||||
}
|
||||
}
|
||||
return (float)(sum * kscale);
|
||||
}
|
59
3rdparty/bgfx/3rdparty/iqa/source/decimate.c
vendored
Normal file
59
3rdparty/bgfx/3rdparty/iqa/source/decimate.c
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
#include "decimate.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
int _iqa_decimate(float *img, int w, int h, int factor, const struct _kernel *k, float *result, int *rw, int *rh)
|
||||
{
|
||||
int x,y;
|
||||
int sw = w/factor + (w&1);
|
||||
int sh = h/factor + (h&1);
|
||||
int dst_offset;
|
||||
float *dst=img;
|
||||
|
||||
if (result)
|
||||
dst = result;
|
||||
|
||||
/* Downsample */
|
||||
for (y=0; y<sh; ++y) {
|
||||
dst_offset = y*sw;
|
||||
for (x=0; x<sw; ++x,++dst_offset) {
|
||||
dst[dst_offset] = _iqa_filter_pixel(img, w, h, x*factor, y*factor, k, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (rw) *rw = sw;
|
||||
if (rh) *rh = sh;
|
||||
return 0;
|
||||
}
|
82
3rdparty/bgfx/3rdparty/iqa/source/math_utils.c
vendored
Normal file
82
3rdparty/bgfx/3rdparty/iqa/source/math_utils.c
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
#include "math_utils.h"
|
||||
#include <math.h>
|
||||
|
||||
int _round(float a)
|
||||
{
|
||||
int sign_a = a > 0.0f ? 1 : -1;
|
||||
return a-(int)a >= 0.5 ? (int)a + sign_a : (int)a;
|
||||
}
|
||||
|
||||
int _max(int x, int y)
|
||||
{
|
||||
return x >= y ? x : y;
|
||||
}
|
||||
|
||||
int _min(int x, int y)
|
||||
{
|
||||
return x <= y ? x : y;
|
||||
}
|
||||
|
||||
int _cmp_float(float a, float b, int digits)
|
||||
{
|
||||
/* Round */
|
||||
int sign_a = a > 0.0f ? 1 : -1;
|
||||
int sign_b = b > 0.0f ? 1 : -1;
|
||||
double scale = pow(10.0, (double)digits);
|
||||
double ax = a * scale;
|
||||
double bx = b * scale;
|
||||
int ai = ax-(int)ax >= 0.5 ? (int)ax + sign_a : (int)ax;
|
||||
int bi = bx-(int)bx >= 0.5 ? (int)bx + sign_b : (int)bx;
|
||||
|
||||
/* Compare */
|
||||
return ai == bi ? 0 : 1;
|
||||
}
|
||||
|
||||
int _matrix_cmp(const float *a, const float *b, int w, int h, int digits)
|
||||
{
|
||||
int offset;
|
||||
int result=0;
|
||||
int len=w*h;
|
||||
for (offset=0; offset<len; ++offset) {
|
||||
if (_cmp_float(a[offset], b[offset], digits)) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
277
3rdparty/bgfx/3rdparty/iqa/source/ms_ssim.c
vendored
Normal file
277
3rdparty/bgfx/3rdparty/iqa/source/ms_ssim.c
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
#include "iqa.h"
|
||||
#include "ssim.h"
|
||||
#include "decimate.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Default number of scales */
|
||||
#define SCALES 5
|
||||
|
||||
/* Low-pass filter for down-sampling (9/7 biorthogonal wavelet filter) */
|
||||
#define LPF_LEN 9
|
||||
static const float g_lpf[LPF_LEN][LPF_LEN] = {
|
||||
{ 0.000714f,-0.000450f,-0.002090f, 0.007132f, 0.016114f, 0.007132f,-0.002090f,-0.000450f, 0.000714f},
|
||||
{-0.000450f, 0.000283f, 0.001316f,-0.004490f,-0.010146f,-0.004490f, 0.001316f, 0.000283f,-0.000450f},
|
||||
{-0.002090f, 0.001316f, 0.006115f,-0.020867f,-0.047149f,-0.020867f, 0.006115f, 0.001316f,-0.002090f},
|
||||
{ 0.007132f,-0.004490f,-0.020867f, 0.071207f, 0.160885f, 0.071207f,-0.020867f,-0.004490f, 0.007132f},
|
||||
{ 0.016114f,-0.010146f,-0.047149f, 0.160885f, 0.363505f, 0.160885f,-0.047149f,-0.010146f, 0.016114f},
|
||||
{ 0.007132f,-0.004490f,-0.020867f, 0.071207f, 0.160885f, 0.071207f,-0.020867f,-0.004490f, 0.007132f},
|
||||
{-0.002090f, 0.001316f, 0.006115f,-0.020867f,-0.047149f,-0.020867f, 0.006115f, 0.001316f,-0.002090f},
|
||||
{-0.000450f, 0.000283f, 0.001316f,-0.004490f,-0.010146f,-0.004490f, 0.001316f, 0.000283f,-0.000450f},
|
||||
{ 0.000714f,-0.000450f,-0.002090f, 0.007132f, 0.016114f, 0.007132f,-0.002090f,-0.000450f, 0.000714f},
|
||||
};
|
||||
|
||||
/* Alpha, beta, and gamma values for each scale */
|
||||
static float g_alphas[] = { 0.0000f, 0.0000f, 0.0000f, 0.0000f, 0.1333f };
|
||||
static float g_betas[] = { 0.0448f, 0.2856f, 0.3001f, 0.2363f, 0.1333f };
|
||||
static float g_gammas[] = { 0.0448f, 0.2856f, 0.3001f, 0.2363f, 0.1333f };
|
||||
|
||||
|
||||
struct _context {
|
||||
double l; /* Luminance */
|
||||
double c; /* Contrast */
|
||||
double s; /* Structure */
|
||||
float alpha;
|
||||
float beta;
|
||||
float gamma;
|
||||
};
|
||||
|
||||
/* Called for each pixel */
|
||||
int _ms_ssim_map(const struct _ssim_int *si, void *ctx)
|
||||
{
|
||||
struct _context *ms_ctx = (struct _context*)ctx;
|
||||
ms_ctx->l += si->l;
|
||||
ms_ctx->c += si->c;
|
||||
ms_ctx->s += si->s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called to calculate the final result */
|
||||
float _ms_ssim_reduce(int w, int h, void *ctx)
|
||||
{
|
||||
double size = (double)(w*h);
|
||||
struct _context *ms_ctx = (struct _context*)ctx;
|
||||
ms_ctx->l = pow(ms_ctx->l / size, (double)ms_ctx->alpha);
|
||||
ms_ctx->c = pow(ms_ctx->c / size, (double)ms_ctx->beta);
|
||||
ms_ctx->s = pow(fabs(ms_ctx->s / size), (double)ms_ctx->gamma);
|
||||
return (float)(ms_ctx->l * ms_ctx->c * ms_ctx->s);
|
||||
}
|
||||
|
||||
/* Releases the scaled buffers */
|
||||
void _free_buffers(float **buf, int scales)
|
||||
{
|
||||
int idx;
|
||||
for (idx=0; idx<scales; ++idx)
|
||||
free(buf[idx]);
|
||||
}
|
||||
|
||||
/* Allocates the scaled buffers. If error, all buffers are free'd */
|
||||
int _alloc_buffers(float **buf, int w, int h, int scales)
|
||||
{
|
||||
int idx;
|
||||
int cur_w = w;
|
||||
int cur_h = h;
|
||||
for (idx=0; idx<scales; ++idx) {
|
||||
buf[idx] = (float*)malloc(cur_w*cur_h*sizeof(float));
|
||||
if (!buf[idx]) {
|
||||
_free_buffers(buf, idx);
|
||||
return 1;
|
||||
}
|
||||
cur_w = cur_w/2 + (cur_w&1);
|
||||
cur_h = cur_h/2 + (cur_h&1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* MS_SSIM(X,Y) = Lm(x,y)^aM * MULT[j=1->M]( Cj(x,y)^bj * Sj(x,y)^gj )
|
||||
* where,
|
||||
* L = mean
|
||||
* C = variance
|
||||
* S = cross-correlation
|
||||
*
|
||||
* b1=g1=0.0448, b2=g2=0.2856, b3=g3=0.3001, b4=g4=0.2363, a5=b5=g5=0.1333
|
||||
*/
|
||||
float iqa_ms_ssim(const unsigned char *ref, const unsigned char *cmp, int w, int h,
|
||||
int stride, const struct iqa_ms_ssim_args *args)
|
||||
{
|
||||
int wang=0;
|
||||
int scales=SCALES;
|
||||
int gauss=1;
|
||||
const float *alphas=g_alphas, *betas=g_betas, *gammas=g_gammas;
|
||||
int idx,x,y,cur_w,cur_h;
|
||||
int offset,src_offset;
|
||||
float **ref_imgs, **cmp_imgs; /* Array of pointers to scaled images */
|
||||
float msssim;
|
||||
struct _kernel lpf, window;
|
||||
struct iqa_ssim_args s_args;
|
||||
struct _map_reduce mr;
|
||||
struct _context ms_ctx;
|
||||
|
||||
if (args) {
|
||||
wang = args->wang;
|
||||
gauss = args->gaussian;
|
||||
scales = args->scales;
|
||||
if (args->alphas)
|
||||
alphas = args->alphas;
|
||||
if (args->betas)
|
||||
betas = args->betas;
|
||||
if (args->gammas)
|
||||
gammas = args->gammas;
|
||||
}
|
||||
|
||||
/* Make sure we won't scale below 1x1 */
|
||||
cur_w = w;
|
||||
cur_h = h;
|
||||
for (idx=0; idx<scales; ++idx) {
|
||||
if ( gauss ? cur_w<GAUSSIAN_LEN || cur_h<GAUSSIAN_LEN : cur_w<LPF_LEN || cur_h<LPF_LEN )
|
||||
return INFINITY;
|
||||
cur_w /= 2;
|
||||
cur_h /= 2;
|
||||
}
|
||||
|
||||
window.kernel = (float*)g_square_window;
|
||||
window.w = window.h = SQUARE_LEN;
|
||||
window.normalized = 1;
|
||||
window.bnd_opt = KBND_SYMMETRIC;
|
||||
if (gauss) {
|
||||
window.kernel = (float*)g_gaussian_window;
|
||||
window.w = window.h = GAUSSIAN_LEN;
|
||||
}
|
||||
|
||||
mr.map = _ms_ssim_map;
|
||||
mr.reduce = _ms_ssim_reduce;
|
||||
|
||||
/* Allocate the scaled image buffers */
|
||||
ref_imgs = (float**)malloc(scales*sizeof(float*));
|
||||
cmp_imgs = (float**)malloc(scales*sizeof(float*));
|
||||
if (!ref_imgs || !cmp_imgs) {
|
||||
if (ref_imgs) free(ref_imgs);
|
||||
if (cmp_imgs) free(cmp_imgs);
|
||||
return INFINITY;
|
||||
}
|
||||
if (_alloc_buffers(ref_imgs, w, h, scales)) {
|
||||
free(ref_imgs);
|
||||
free(cmp_imgs);
|
||||
return INFINITY;
|
||||
}
|
||||
if (_alloc_buffers(cmp_imgs, w, h, scales)) {
|
||||
_free_buffers(ref_imgs, scales);
|
||||
free(ref_imgs);
|
||||
free(cmp_imgs);
|
||||
return INFINITY;
|
||||
}
|
||||
|
||||
/* Copy original images into first scale buffer, forcing stride = width. */
|
||||
for (y=0; y<h; ++y) {
|
||||
src_offset = y*stride;
|
||||
offset = y*w;
|
||||
for (x=0; x<w; ++x, ++offset, ++src_offset) {
|
||||
ref_imgs[0][offset] = (float)ref[src_offset];
|
||||
cmp_imgs[0][offset] = (float)cmp[src_offset];
|
||||
}
|
||||
}
|
||||
|
||||
/* Create scaled versions of the images */
|
||||
cur_w=w;
|
||||
cur_h=h;
|
||||
lpf.kernel = (float*)g_lpf;
|
||||
lpf.w = lpf.h = LPF_LEN;
|
||||
lpf.normalized = 1;
|
||||
lpf.bnd_opt = KBND_SYMMETRIC;
|
||||
for (idx=1; idx<scales; ++idx) {
|
||||
if (_iqa_decimate(ref_imgs[idx-1], cur_w, cur_h, 2, &lpf, ref_imgs[idx], 0, 0) ||
|
||||
_iqa_decimate(cmp_imgs[idx-1], cur_w, cur_h, 2, &lpf, cmp_imgs[idx], &cur_w, &cur_h))
|
||||
{
|
||||
_free_buffers(ref_imgs, scales);
|
||||
_free_buffers(cmp_imgs, scales);
|
||||
free(ref_imgs);
|
||||
free(cmp_imgs);
|
||||
return INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
cur_w=w;
|
||||
cur_h=h;
|
||||
msssim = 1.0;
|
||||
for (idx=0; idx<scales; ++idx) {
|
||||
|
||||
ms_ctx.l = 0;
|
||||
ms_ctx.c = 0;
|
||||
ms_ctx.s = 0;
|
||||
ms_ctx.alpha = alphas[idx];
|
||||
ms_ctx.beta = betas[idx];
|
||||
ms_ctx.gamma = gammas[idx];
|
||||
|
||||
if (!wang) {
|
||||
/* MS-SSIM* (Rouse/Hemami) */
|
||||
s_args.alpha = 1.0f;
|
||||
s_args.beta = 1.0f;
|
||||
s_args.gamma = 1.0f;
|
||||
s_args.K1 = 0.0f; /* Force stabilization constants to 0 */
|
||||
s_args.K2 = 0.0f;
|
||||
s_args.L = 255;
|
||||
s_args.f = 1; /* Don't resize */
|
||||
mr.context = &ms_ctx;
|
||||
msssim *= _iqa_ssim(ref_imgs[idx], cmp_imgs[idx], cur_w, cur_h, &window, &mr, &s_args);
|
||||
}
|
||||
else {
|
||||
/* MS-SSIM (Wang) */
|
||||
s_args.alpha = 1.0f;
|
||||
s_args.beta = 1.0f;
|
||||
s_args.gamma = 1.0f;
|
||||
s_args.K1 = 0.01f;
|
||||
s_args.K2 = 0.03f;
|
||||
s_args.L = 255;
|
||||
s_args.f = 1; /* Don't resize */
|
||||
mr.context = &ms_ctx;
|
||||
msssim *= _iqa_ssim(ref_imgs[idx], cmp_imgs[idx], cur_w, cur_h, &window, &mr, &s_args);
|
||||
}
|
||||
|
||||
if (msssim == INFINITY)
|
||||
break;
|
||||
cur_w = cur_w/2 + (cur_w&1);
|
||||
cur_h = cur_h/2 + (cur_h&1);
|
||||
}
|
||||
|
||||
_free_buffers(ref_imgs, scales);
|
||||
_free_buffers(cmp_imgs, scales);
|
||||
free(ref_imgs);
|
||||
free(cmp_imgs);
|
||||
|
||||
return msssim;
|
||||
}
|
50
3rdparty/bgfx/3rdparty/iqa/source/mse.c
vendored
Normal file
50
3rdparty/bgfx/3rdparty/iqa/source/mse.c
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
#include "iqa.h"
|
||||
|
||||
/* MSE(a,b) = 1/N * SUM((a-b)^2) */
|
||||
float iqa_mse(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride)
|
||||
{
|
||||
int error, offset;
|
||||
unsigned long long sum=0;
|
||||
int ww,hh;
|
||||
for (hh=0; hh<h; ++hh) {
|
||||
offset = hh*stride;
|
||||
for (ww=0; ww<w; ++ww, ++offset) {
|
||||
error = ref[offset] - cmp[offset];
|
||||
sum += error * error;
|
||||
}
|
||||
}
|
||||
return (float)( (double)sum / (double)(w*h) );
|
||||
}
|
42
3rdparty/bgfx/3rdparty/iqa/source/psnr.c
vendored
Normal file
42
3rdparty/bgfx/3rdparty/iqa/source/psnr.c
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
#include "iqa.h"
|
||||
#include <math.h>
|
||||
|
||||
/* PSNR(a,b) = 10*log10(L^2 / MSE(a,b)), where L=2^b - 1 (8bit = 255) */
|
||||
float iqa_psnr(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride)
|
||||
{
|
||||
const int L_sqd = 255 * 255;
|
||||
return (float)( 10.0 * log10( L_sqd / iqa_mse(ref,cmp,w,h,stride) ) );
|
||||
}
|
322
3rdparty/bgfx/3rdparty/iqa/source/ssim.c
vendored
Normal file
322
3rdparty/bgfx/3rdparty/iqa/source/ssim.c
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* The BSD License
|
||||
*
|
||||
* 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 tdistler.com 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
#include "iqa.h"
|
||||
#include "convolve.h"
|
||||
#include "decimate.h"
|
||||
#include "math_utils.h"
|
||||
#include "ssim.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/* Forward declarations. */
|
||||
IQA_INLINE static double _calc_luminance(float, float, float, float);
|
||||
IQA_INLINE static double _calc_contrast(double, float, float, float, float);
|
||||
IQA_INLINE static double _calc_structure(float, double, float, float, float, float);
|
||||
static int _ssim_map(const struct _ssim_int *, void *);
|
||||
static float _ssim_reduce(int, int, void *);
|
||||
|
||||
/*
|
||||
* SSIM(x,y)=(2*ux*uy + C1)*(2sxy + C2) / (ux^2 + uy^2 + C1)*(sx^2 + sy^2 + C2)
|
||||
* where,
|
||||
* ux = SUM(w*x)
|
||||
* sx = (SUM(w*(x-ux)^2)^0.5
|
||||
* sxy = SUM(w*(x-ux)*(y-uy))
|
||||
*
|
||||
* Returns mean SSIM. MSSIM(X,Y) = 1/M * SUM(SSIM(x,y))
|
||||
*/
|
||||
float iqa_ssim(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride,
|
||||
int gaussian, const struct iqa_ssim_args *args)
|
||||
{
|
||||
int scale;
|
||||
int x,y,src_offset,offset;
|
||||
float *ref_f,*cmp_f;
|
||||
struct _kernel low_pass;
|
||||
struct _kernel window;
|
||||
float result;
|
||||
double ssim_sum=0.0;
|
||||
struct _map_reduce mr;
|
||||
|
||||
/* Initialize algorithm parameters */
|
||||
scale = _max( 1, _round( (float)_min(w,h) / 256.0f ) );
|
||||
if (args) {
|
||||
if(args->f)
|
||||
scale = args->f;
|
||||
mr.map = _ssim_map;
|
||||
mr.reduce = _ssim_reduce;
|
||||
mr.context = (void*)&ssim_sum;
|
||||
}
|
||||
window.kernel = (float*)g_square_window;
|
||||
window.w = window.h = SQUARE_LEN;
|
||||
window.normalized = 1;
|
||||
window.bnd_opt = KBND_SYMMETRIC;
|
||||
if (gaussian) {
|
||||
window.kernel = (float*)g_gaussian_window;
|
||||
window.w = window.h = GAUSSIAN_LEN;
|
||||
}
|
||||
|
||||
/* Convert image values to floats. Forcing stride = width. */
|
||||
ref_f = (float*)malloc(w*h*sizeof(float));
|
||||
cmp_f = (float*)malloc(w*h*sizeof(float));
|
||||
if (!ref_f || !cmp_f) {
|
||||
if (ref_f) free(ref_f);
|
||||
if (cmp_f) free(cmp_f);
|
||||
return INFINITY;
|
||||
}
|
||||
for (y=0; y<h; ++y) {
|
||||
src_offset = y*stride;
|
||||
offset = y*w;
|
||||
for (x=0; x<w; ++x, ++offset, ++src_offset) {
|
||||
ref_f[offset] = (float)ref[src_offset];
|
||||
cmp_f[offset] = (float)cmp[src_offset];
|
||||
}
|
||||
}
|
||||
|
||||
/* Scale the images down if required */
|
||||
if (scale > 1) {
|
||||
/* Generate simple low-pass filter */
|
||||
low_pass.kernel = (float*)malloc(scale*scale*sizeof(float));
|
||||
if (!low_pass.kernel) {
|
||||
free(ref_f);
|
||||
free(cmp_f);
|
||||
return INFINITY;
|
||||
}
|
||||
low_pass.w = low_pass.h = scale;
|
||||
low_pass.normalized = 0;
|
||||
low_pass.bnd_opt = KBND_SYMMETRIC;
|
||||
for (offset=0; offset<scale*scale; ++offset)
|
||||
low_pass.kernel[offset] = 1.0f/(scale*scale);
|
||||
|
||||
/* Resample */
|
||||
if (_iqa_decimate(ref_f, w, h, scale, &low_pass, 0, 0, 0) ||
|
||||
_iqa_decimate(cmp_f, w, h, scale, &low_pass, 0, &w, &h)) { /* Update w/h */
|
||||
free(ref_f);
|
||||
free(cmp_f);
|
||||
free(low_pass.kernel);
|
||||
return INFINITY;
|
||||
}
|
||||
free(low_pass.kernel);
|
||||
}
|
||||
|
||||
result = _iqa_ssim(ref_f, cmp_f, w, h, &window, &mr, args);
|
||||
|
||||
free(ref_f);
|
||||
free(cmp_f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* _iqa_ssim */
|
||||
float _iqa_ssim(float *ref, float *cmp, int w, int h, const struct _kernel *k, const struct _map_reduce *mr, const struct iqa_ssim_args *args)
|
||||
{
|
||||
float alpha=1.0f, beta=1.0f, gamma=1.0f;
|
||||
int L=255;
|
||||
float K1=0.01f, K2=0.03f;
|
||||
float C1,C2,C3;
|
||||
int x,y,offset;
|
||||
float *ref_mu,*cmp_mu,*ref_sigma_sqd,*cmp_sigma_sqd,*sigma_both;
|
||||
double ssim_sum, numerator, denominator;
|
||||
double luminance_comp, contrast_comp, structure_comp, sigma_root;
|
||||
struct _ssim_int sint;
|
||||
|
||||
/* Initialize algorithm parameters */
|
||||
if (args) {
|
||||
if (!mr)
|
||||
return INFINITY;
|
||||
alpha = args->alpha;
|
||||
beta = args->beta;
|
||||
gamma = args->gamma;
|
||||
L = args->L;
|
||||
K1 = args->K1;
|
||||
K2 = args->K2;
|
||||
}
|
||||
C1 = (K1*L)*(K1*L);
|
||||
C2 = (K2*L)*(K2*L);
|
||||
C3 = C2 / 2.0f;
|
||||
|
||||
ref_mu = (float*)malloc(w*h*sizeof(float));
|
||||
cmp_mu = (float*)malloc(w*h*sizeof(float));
|
||||
ref_sigma_sqd = (float*)malloc(w*h*sizeof(float));
|
||||
cmp_sigma_sqd = (float*)malloc(w*h*sizeof(float));
|
||||
sigma_both = (float*)malloc(w*h*sizeof(float));
|
||||
if (!ref_mu || !cmp_mu || !ref_sigma_sqd || !cmp_sigma_sqd || !sigma_both) {
|
||||
if (ref_mu) free(ref_mu);
|
||||
if (cmp_mu) free(cmp_mu);
|
||||
if (ref_sigma_sqd) free(ref_sigma_sqd);
|
||||
if (cmp_sigma_sqd) free(cmp_sigma_sqd);
|
||||
if (sigma_both) free(sigma_both);
|
||||
return INFINITY;
|
||||
}
|
||||
|
||||
/* Calculate mean */
|
||||
_iqa_convolve(ref, w, h, k, ref_mu, 0, 0);
|
||||
_iqa_convolve(cmp, w, h, k, cmp_mu, 0, 0);
|
||||
|
||||
for (y=0; y<h; ++y) {
|
||||
offset = y*w;
|
||||
for (x=0; x<w; ++x, ++offset) {
|
||||
ref_sigma_sqd[offset] = ref[offset] * ref[offset];
|
||||
cmp_sigma_sqd[offset] = cmp[offset] * cmp[offset];
|
||||
sigma_both[offset] = ref[offset] * cmp[offset];
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate sigma */
|
||||
_iqa_convolve(ref_sigma_sqd, w, h, k, 0, 0, 0);
|
||||
_iqa_convolve(cmp_sigma_sqd, w, h, k, 0, 0, 0);
|
||||
_iqa_convolve(sigma_both, w, h, k, 0, &w, &h); /* Update the width and height */
|
||||
|
||||
/* The convolution results are smaller by the kernel width and height */
|
||||
for (y=0; y<h; ++y) {
|
||||
offset = y*w;
|
||||
for (x=0; x<w; ++x, ++offset) {
|
||||
ref_sigma_sqd[offset] -= ref_mu[offset] * ref_mu[offset];
|
||||
cmp_sigma_sqd[offset] -= cmp_mu[offset] * cmp_mu[offset];
|
||||
sigma_both[offset] -= ref_mu[offset] * cmp_mu[offset];
|
||||
}
|
||||
}
|
||||
|
||||
ssim_sum = 0.0;
|
||||
for (y=0; y<h; ++y) {
|
||||
offset = y*w;
|
||||
for (x=0; x<w; ++x, ++offset) {
|
||||
|
||||
if (!args) {
|
||||
/* The default case */
|
||||
numerator = (2.0 * ref_mu[offset] * cmp_mu[offset] + C1) * (2.0 * sigma_both[offset] + C2);
|
||||
denominator = (ref_mu[offset]*ref_mu[offset] + cmp_mu[offset]*cmp_mu[offset] + C1) *
|
||||
(ref_sigma_sqd[offset] + cmp_sigma_sqd[offset] + C2);
|
||||
ssim_sum += numerator / denominator;
|
||||
}
|
||||
else {
|
||||
/* User tweaked alpha, beta, or gamma */
|
||||
|
||||
/* passing a negative number to sqrt() cause a domain error */
|
||||
if (ref_sigma_sqd[offset] < 0.0f)
|
||||
ref_sigma_sqd[offset] = 0.0f;
|
||||
if (cmp_sigma_sqd[offset] < 0.0f)
|
||||
cmp_sigma_sqd[offset] = 0.0f;
|
||||
sigma_root = sqrt(ref_sigma_sqd[offset] * cmp_sigma_sqd[offset]);
|
||||
|
||||
luminance_comp = _calc_luminance(ref_mu[offset], cmp_mu[offset], C1, alpha);
|
||||
contrast_comp = _calc_contrast(sigma_root, ref_sigma_sqd[offset], cmp_sigma_sqd[offset], C2, beta);
|
||||
structure_comp = _calc_structure(sigma_both[offset], sigma_root, ref_sigma_sqd[offset], cmp_sigma_sqd[offset], C3, gamma);
|
||||
|
||||
sint.l = luminance_comp;
|
||||
sint.c = contrast_comp;
|
||||
sint.s = structure_comp;
|
||||
|
||||
if (mr->map(&sint, mr->context))
|
||||
return INFINITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(ref_mu);
|
||||
free(cmp_mu);
|
||||
free(ref_sigma_sqd);
|
||||
free(cmp_sigma_sqd);
|
||||
free(sigma_both);
|
||||
|
||||
if (!args)
|
||||
return (float)(ssim_sum / (double)(w*h));
|
||||
return mr->reduce(w, h, mr->context);
|
||||
}
|
||||
|
||||
|
||||
/* _ssim_map */
|
||||
int _ssim_map(const struct _ssim_int *si, void *ctx)
|
||||
{
|
||||
double *ssim_sum = (double*)ctx;
|
||||
*ssim_sum += si->l * si->c * si->s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* _ssim_reduce */
|
||||
float _ssim_reduce(int w, int h, void *ctx)
|
||||
{
|
||||
double *ssim_sum = (double*)ctx;
|
||||
return (float)(*ssim_sum / (double)(w*h));
|
||||
}
|
||||
|
||||
|
||||
/* _calc_luminance */
|
||||
IQA_INLINE static double _calc_luminance(float mu1, float mu2, float C1, float alpha)
|
||||
{
|
||||
double result;
|
||||
float sign;
|
||||
/* For MS-SSIM* */
|
||||
if (C1 == 0 && mu1*mu1 == 0 && mu2*mu2 == 0)
|
||||
return 1.0;
|
||||
result = (2.0 * mu1 * mu2 + C1) / (mu1*mu1 + mu2*mu2 + C1);
|
||||
if (alpha == 1.0f)
|
||||
return result;
|
||||
sign = result < 0.0 ? -1.0f : 1.0f;
|
||||
return sign * pow(fabs(result),(double)alpha);
|
||||
}
|
||||
|
||||
/* _calc_contrast */
|
||||
IQA_INLINE static double _calc_contrast(double sigma_comb_12, float sigma1_sqd, float sigma2_sqd, float C2, float beta)
|
||||
{
|
||||
double result;
|
||||
float sign;
|
||||
/* For MS-SSIM* */
|
||||
if (C2 == 0 && sigma1_sqd + sigma2_sqd == 0)
|
||||
return 1.0;
|
||||
result = (2.0 * sigma_comb_12 + C2) / (sigma1_sqd + sigma2_sqd + C2);
|
||||
if (beta == 1.0f)
|
||||
return result;
|
||||
sign = result < 0.0 ? -1.0f : 1.0f;
|
||||
return sign * pow(fabs(result),(double)beta);
|
||||
}
|
||||
|
||||
/* _calc_structure */
|
||||
IQA_INLINE static double _calc_structure(float sigma_12, double sigma_comb_12, float sigma1, float sigma2, float C3, float gamma)
|
||||
{
|
||||
double result;
|
||||
float sign;
|
||||
/* For MS-SSIM* */
|
||||
if (C3 == 0 && sigma_comb_12 == 0) {
|
||||
if (sigma1 == 0 && sigma2 == 0)
|
||||
return 1.0;
|
||||
else if (sigma1 == 0 || sigma2 == 0)
|
||||
return 0.0;
|
||||
}
|
||||
result = (sigma_12 + C3) / (sigma_comb_12 + C3);
|
||||
if (gamma == 1.0f)
|
||||
return result;
|
||||
sign = result < 0.0 ? -1.0f : 1.0f;
|
||||
return sign * pow(fabs(result),(double)gamma);
|
||||
}
|
10
3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.cpp
vendored
10
3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.cpp
vendored
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.48 WIP
|
||||
// dear imgui, v1.49 WIP
|
||||
// (main code and documentation)
|
||||
|
||||
// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
|
||||
@ -2341,9 +2341,9 @@ static void AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDr
|
||||
|
||||
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = 2 bytes = 64K vertices)
|
||||
// If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly.
|
||||
IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
||||
IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= ((unsigned long long int)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above.
|
||||
|
||||
IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
||||
IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= ((int64_t)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above.
|
||||
|
||||
out_render_list.push_back(draw_list);
|
||||
GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size;
|
||||
GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size;
|
||||
@ -7101,9 +7101,9 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* ob
|
||||
|
||||
static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
|
||||
static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; }
|
||||
static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; }
|
||||
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
|
||||
#ifdef __APPLE__ // FIXME: Move setting to IO structure
|
||||
static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; }
|
||||
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
|
||||
#else
|
||||
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
|
||||
|
9
3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.h
vendored
9
3rdparty/bgfx/3rdparty/ocornut-imgui/imgui.h
vendored
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.48 WIP
|
||||
// dear imgui, v1.49 WIP
|
||||
// (headers)
|
||||
|
||||
// See imgui.cpp file for documentation.
|
||||
@ -16,7 +16,7 @@
|
||||
#include <stddef.h> // ptrdiff_t, NULL
|
||||
#include <string.h> // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp
|
||||
|
||||
#define IMGUI_VERSION "1.48 WIP"
|
||||
#define IMGUI_VERSION "1.49 WIP"
|
||||
|
||||
// Define attributes of all API symbols declarations, e.g. for DLL under Windows.
|
||||
#ifndef IMGUI_API
|
||||
@ -315,7 +315,7 @@ namespace ImGui
|
||||
IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose
|
||||
IMGUI_API void TreePush(const void* ptr_id = NULL); // "
|
||||
IMGUI_API void TreePop();
|
||||
IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node to be opened.
|
||||
IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened.
|
||||
|
||||
// Widgets: Selectable / Lists
|
||||
IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
|
||||
@ -892,6 +892,7 @@ struct ImGuiTextFilter
|
||||
int CountGrep;
|
||||
|
||||
ImGuiTextFilter(const char* default_filter = "");
|
||||
~ImGuiTextFilter() {}
|
||||
void Clear() { InputBuf[0] = 0; Build(); }
|
||||
bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build
|
||||
bool PassFilter(const char* text, const char* text_end = NULL) const;
|
||||
@ -1155,7 +1156,7 @@ struct ImDrawList
|
||||
// Stateful path API, add points then finish with PathFill() or PathStroke()
|
||||
inline void PathClear() { _Path.resize(0); }
|
||||
inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); }
|
||||
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || _Path[_Path.Size-1].x != pos.x || _Path[_Path.Size-1].y != pos.y) _Path.push_back(pos); }
|
||||
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); }
|
||||
inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); }
|
||||
inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); }
|
||||
IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.48 WIP
|
||||
// dear imgui, v1.49 WIP
|
||||
// (demo code)
|
||||
|
||||
// Don't remove this file from your project! It is useful reference code that you can execute.
|
||||
@ -2295,12 +2295,12 @@ static void ShowExampleAppPropertyEditor(bool* p_opened)
|
||||
{
|
||||
ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
|
||||
ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
|
||||
bool opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
|
||||
bool is_opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
|
||||
ImGui::NextColumn();
|
||||
ImGui::AlignFirstTextHeightToWidgets();
|
||||
ImGui::Text("my sailor is rich");
|
||||
ImGui::NextColumn();
|
||||
if (opened)
|
||||
if (is_opened)
|
||||
{
|
||||
static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
|
||||
for (int i = 0; i < 8; i++)
|
||||
|
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.48 WIP
|
||||
// dear imgui, v1.49 WIP
|
||||
// (drawing and font code)
|
||||
|
||||
// Contains implementation for
|
||||
|
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.48 WIP
|
||||
// dear imgui, v1.49 WIP
|
||||
// (internals)
|
||||
|
||||
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
|
||||
|
1416
3rdparty/bgfx/3rdparty/openvr/openvr_capi.h
vendored
Normal file
1416
3rdparty/bgfx/3rdparty/openvr/openvr_capi.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@
|
||||
#include <string.h> // memcpy
|
||||
|
||||
#ifndef ENTRY_CONFIG_USE_NOOP
|
||||
# define ENTRY_CONFIG_USE_NOOP (BX_PLATFORM_QNX || BX_PLATFORM_XBOXONE)
|
||||
# define ENTRY_CONFIG_USE_NOOP (BX_PLATFORM_QNX)
|
||||
#endif // ENTRY_CONFIG_USE_NOOP
|
||||
|
||||
#ifndef ENTRY_CONFIG_USE_SDL
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "entry_p.h"
|
||||
|
||||
#if BX_PLATFORM_WINRT
|
||||
#if BX_PLATFORM_WINRT || BX_PLATFORM_XBOXONE
|
||||
|
||||
#include <bgfx/bgfxplatform.h>
|
||||
#include <bx/thread.h>
|
||||
@ -17,7 +17,9 @@ using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::Input;
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::Foundation;
|
||||
#if BX_PLATFORM_WINRT
|
||||
using namespace Windows::Graphics::Display;
|
||||
#endif // BX_PLATFORM_WINRT
|
||||
using namespace Platform;
|
||||
|
||||
static char* g_emptyArgs[] = { "" };
|
||||
@ -36,13 +38,23 @@ public:
|
||||
// IFrameworkView Methods.
|
||||
virtual void Initialize(CoreApplicationView^ applicationView)
|
||||
{
|
||||
applicationView->Activated += ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
|
||||
applicationView->Activated += ref new
|
||||
TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
|
||||
|
||||
CoreApplication::Suspending += ref new
|
||||
EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
|
||||
|
||||
CoreApplication::Resuming += ref new
|
||||
EventHandler<Platform::Object^>(this, &App::OnResuming);
|
||||
}
|
||||
|
||||
virtual void SetWindow(CoreWindow^ window)
|
||||
{
|
||||
window->VisibilityChanged += ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
|
||||
window->Closed += ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
|
||||
window->VisibilityChanged += ref new
|
||||
TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
|
||||
|
||||
window->Closed += ref new
|
||||
TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
|
||||
|
||||
bgfx::winrtSetWindow(reinterpret_cast<IUnknown*>(window) );
|
||||
}
|
||||
@ -58,13 +70,15 @@ public:
|
||||
|
||||
CoreWindow^ window = CoreWindow::GetForCurrentThread();
|
||||
auto bounds = window->Bounds;
|
||||
auto dpi = DisplayInformation::GetForCurrentView()->LogicalDpi;
|
||||
|
||||
#if BX_PLATFORM_WINRT
|
||||
auto dpi = DisplayInformation::GetForCurrentView()->LogicalDpi;
|
||||
static const float dipsPerInch = 96.0f;
|
||||
g_eventQueue.postSizeEvent(g_defaultWindow
|
||||
, lround(floorf(bounds.Width * dpi / dipsPerInch + 0.5f) )
|
||||
, lround(floorf(bounds.Height * dpi / dipsPerInch + 0.5f) )
|
||||
, lround(bx::ffloor(bounds.Width * dpi / dipsPerInch + 0.5f) )
|
||||
, lround(bx::ffloor(bounds.Height * dpi / dipsPerInch + 0.5f) )
|
||||
);
|
||||
#endif // BX_PLATFORM_WINRT
|
||||
|
||||
while (!m_windowClosed)
|
||||
{
|
||||
@ -101,6 +115,16 @@ private:
|
||||
m_windowVisible = args->Visible;
|
||||
}
|
||||
|
||||
void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
|
||||
{
|
||||
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
|
||||
BX_UNUSED(deferral);
|
||||
}
|
||||
|
||||
void OnResuming(Platform::Object^ sender, Platform::Object^ args)
|
||||
{
|
||||
}
|
||||
|
||||
void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
|
||||
{
|
||||
m_windowClosed = true;
|
||||
@ -189,4 +213,4 @@ int main(Array<String^>^)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // BX_PLATFORM_WINRT
|
||||
#endif // BX_PLATFORM_WINRT || BX_PLATFORM_XBOXONE
|
||||
|
3
3rdparty/bgfx/scripts/texturec.lua
vendored
3
3rdparty/bgfx/scripts/texturec.lua
vendored
@ -13,6 +13,7 @@ project "texturec"
|
||||
path.join(BGFX_DIR, "src"),
|
||||
path.join(BGFX_DIR, "3rdparty"),
|
||||
path.join(BGFX_DIR, "3rdparty/nvtt"),
|
||||
path.join(BGFX_DIR, "3rdparty/iqa/include"),
|
||||
}
|
||||
|
||||
files {
|
||||
@ -31,6 +32,8 @@ project "texturec"
|
||||
path.join(BGFX_DIR, "3rdparty/pvrtc/**.h"),
|
||||
path.join(BGFX_DIR, "3rdparty/tinyexr/**.cc"),
|
||||
path.join(BGFX_DIR, "3rdparty/tinyexr/**.h"),
|
||||
path.join(BGFX_DIR, "3rdparty/iqa/include/**.h"),
|
||||
path.join(BGFX_DIR, "3rdparty/iqa/source/**.c"),
|
||||
path.join(BGFX_DIR, "tools/texturec/**.cpp"),
|
||||
path.join(BGFX_DIR, "tools/texturec/**.h"),
|
||||
}
|
||||
|
4
3rdparty/bgfx/src/glcontext_egl.h
vendored
4
3rdparty/bgfx/src/glcontext_egl.h
vendored
@ -10,6 +10,10 @@
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#if defined(Success)
|
||||
// X11 defines Success
|
||||
# undef Success
|
||||
#endif // defined(Success)
|
||||
|
||||
namespace bgfx { namespace gl
|
||||
{
|
||||
|
95
3rdparty/bgfx/src/hmd_openvr.cpp
vendored
Normal file
95
3rdparty/bgfx/src/hmd_openvr.cpp
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2011-2016 Branimir Karadzic. All rights reserved.
|
||||
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
|
||||
*/
|
||||
|
||||
#include "hmd_openvr.h"
|
||||
|
||||
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-variable")
|
||||
#include <openvr/openvr_capi.h>
|
||||
|
||||
namespace bgfx
|
||||
{
|
||||
#if BX_PLATFORM_WINDOWS
|
||||
# define VR_CALLTYPE __cdecl
|
||||
#else
|
||||
# define VR_CALLTYPE
|
||||
#endif
|
||||
|
||||
typedef uint32_t (VR_CALLTYPE *PFN_VR_INITINTERNAL)(EVRInitError* peError, EVRApplicationType eType);
|
||||
typedef void (VR_CALLTYPE *PFN_VR_SHUTDOWNINTERNAL)();
|
||||
typedef bool (VR_CALLTYPE *PFN_VR_ISHMDPRESENT)();
|
||||
typedef void* (VR_CALLTYPE *PFN_VR_GETGENERICINTERFACE)(const char* pchInterfaceVersion, EVRInitError* peError);
|
||||
typedef bool (VR_CALLTYPE *PFN_VR_ISRUNTIMEINSTALLED)();
|
||||
typedef bool (VR_CALLTYPE *PFN_VR_ISINTERFACEVERSIONVALID)(const char *pchInterfaceVersion);
|
||||
typedef uint32_t (VR_CALLTYPE *PFN_VR_GETINITTOKEN)();
|
||||
typedef const char* (VR_CALLTYPE *PFN_VR_GETVRINITERRORASSYMBOL)(EVRInitError error);
|
||||
typedef const char* (VR_CALLTYPE *PFN_VR_GETVRINITERRORASENGLISHDESCRIPTION)(EVRInitError error);
|
||||
|
||||
PFN_VR_INITINTERNAL VR_InitInternal;
|
||||
PFN_VR_SHUTDOWNINTERNAL VR_ShutdownInternal;
|
||||
PFN_VR_ISHMDPRESENT VR_IsHmdPresent;
|
||||
PFN_VR_GETGENERICINTERFACE VR_GetGenericInterface;
|
||||
PFN_VR_ISRUNTIMEINSTALLED VR_IsRuntimeInstalled;
|
||||
PFN_VR_ISINTERFACEVERSIONVALID VR_IsInterfaceVersionValid;
|
||||
PFN_VR_GETINITTOKEN VR_GetInitToken;
|
||||
PFN_VR_GETVRINITERRORASSYMBOL VR_GetVRInitErrorAsSymbol;
|
||||
PFN_VR_GETVRINITERRORASENGLISHDESCRIPTION VR_GetVRInitErrorAsEnglishDescription;
|
||||
|
||||
void* loadOpenVR()
|
||||
{
|
||||
void* openvrdll = bx::dlopen(
|
||||
#if BX_PLATFORM_LINUX
|
||||
"libopenvr_api.so"
|
||||
#elif BX_PLATFORM_OSX
|
||||
"libopenvr_api.dylib"
|
||||
#else
|
||||
"openvr_api.dll"
|
||||
#endif // BX_PLATFORM_*
|
||||
);
|
||||
if (NULL != openvrdll)
|
||||
{
|
||||
VR_InitInternal = (PFN_VR_INITINTERNAL )bx::dlsym(openvrdll, "VR_InitInternal");
|
||||
VR_ShutdownInternal = (PFN_VR_SHUTDOWNINTERNAL )bx::dlsym(openvrdll, "VR_ShutdownInternal");
|
||||
VR_IsHmdPresent = (PFN_VR_ISHMDPRESENT )bx::dlsym(openvrdll, "VR_IsHmdPresent");
|
||||
VR_GetGenericInterface = (PFN_VR_GETGENERICINTERFACE )bx::dlsym(openvrdll, "VR_GetGenericInterface");
|
||||
VR_IsRuntimeInstalled = (PFN_VR_ISRUNTIMEINSTALLED )bx::dlsym(openvrdll, "VR_IsRuntimeInstalled");
|
||||
VR_IsInterfaceVersionValid = (PFN_VR_ISINTERFACEVERSIONVALID)bx::dlsym(openvrdll, "VR_IsInterfaceVersionValid");
|
||||
VR_GetInitToken = (PFN_VR_GETINITTOKEN )bx::dlsym(openvrdll, "VR_GetInitToken");
|
||||
VR_GetVRInitErrorAsSymbol = (PFN_VR_GETVRINITERRORASSYMBOL )bx::dlsym(openvrdll, "VR_GetVRInitErrorAsSymbol");
|
||||
VR_GetVRInitErrorAsEnglishDescription = (PFN_VR_GETVRINITERRORASENGLISHDESCRIPTION)bx::dlsym(openvrdll, "VR_GetVRInitErrorAsEnglishDescription");
|
||||
|
||||
if (NULL == VR_InitInternal
|
||||
&& NULL == VR_ShutdownInternal
|
||||
&& NULL == VR_IsHmdPresent
|
||||
&& NULL == VR_GetGenericInterface
|
||||
&& NULL == VR_IsRuntimeInstalled
|
||||
&& NULL == VR_IsInterfaceVersionValid
|
||||
&& NULL == VR_GetInitToken
|
||||
&& NULL == VR_GetVRInitErrorAsSymbol
|
||||
&& NULL == VR_GetVRInitErrorAsEnglishDescription)
|
||||
{
|
||||
bx::dlclose(openvrdll);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVRInitError err;
|
||||
uint32_t token = VR_InitInternal(&err, EVRApplicationType_VRApplication_Scene);
|
||||
BX_UNUSED(token);
|
||||
|
||||
BX_TRACE("OpenVR: HMD is %spresent, Runtime is %sinstalled."
|
||||
, VR_IsHmdPresent() ? "" : "not "
|
||||
, VR_IsRuntimeInstalled() ? "" : "not "
|
||||
);
|
||||
}
|
||||
|
||||
return openvrdll;
|
||||
}
|
||||
|
||||
void unloadOpenVR(void* _openvrdll)
|
||||
{
|
||||
VR_ShutdownInternal();
|
||||
bx::dlclose(_openvrdll);
|
||||
}
|
||||
|
||||
} // namespace bgfx
|
18
3rdparty/bgfx/src/hmd_openvr.h
vendored
Normal file
18
3rdparty/bgfx/src/hmd_openvr.h
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2011-2016 Branimir Karadzic. All rights reserved.
|
||||
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
|
||||
*/
|
||||
|
||||
#ifndef BGFX_OPENVR_H_HEADER_GUARD
|
||||
#define BGFX_OPENVR_H_HEADER_GUARD
|
||||
|
||||
#include "bgfx_p.h"
|
||||
|
||||
namespace bgfx
|
||||
{
|
||||
void* loadOpenVR();
|
||||
void unloadOpenVR(void*);
|
||||
|
||||
} // namespace bgfx
|
||||
|
||||
#endif // BGFX_OPENVR_H_HEADER_GUARD
|
3
3rdparty/bgfx/src/hmd_ovr.cpp
vendored
3
3rdparty/bgfx/src/hmd_ovr.cpp
vendored
@ -17,6 +17,8 @@ namespace bgfx
|
||||
|
||||
#if BGFX_CONFIG_DEBUG
|
||||
# define OVR_CHECK(_call) _OVR_CHECK(_call)
|
||||
#else
|
||||
# define OVR_CHECK(_call) _call
|
||||
#endif // BGFX_CONFIG_DEBUG
|
||||
|
||||
OVR::OVR()
|
||||
@ -152,6 +154,7 @@ namespace bgfx
|
||||
|
||||
for (uint32_t ii = 0; ii < 2; ++ii)
|
||||
{
|
||||
m_eyeBuffers[ii]->postRender(m_hmd);
|
||||
result = ovr_CommitTextureSwapChain(m_hmd, m_eyeBuffers[ii]->m_textureSwapChain);
|
||||
if (!OVR_SUCCESS(result) )
|
||||
{
|
||||
|
4
3rdparty/bgfx/src/hmd_ovr.h
vendored
4
3rdparty/bgfx/src/hmd_ovr.h
vendored
@ -31,10 +31,10 @@ namespace bgfx
|
||||
struct OVRBufferI
|
||||
{
|
||||
virtual ~OVRBufferI() {};
|
||||
virtual void create(const ovrSession& _session, int _eyeIdx) = 0;
|
||||
virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) = 0;
|
||||
virtual void destroy(const ovrSession& _session) = 0;
|
||||
virtual void render(const ovrSession& _session) = 0;
|
||||
|
||||
virtual void postRender(const ovrSession& _session) = 0;
|
||||
ovrSizei m_eyeTextureSize;
|
||||
ovrTextureSwapChain m_textureSwapChain;
|
||||
};
|
||||
|
368
3rdparty/bgfx/src/renderer_d3d11.cpp
vendored
368
3rdparty/bgfx/src/renderer_d3d11.cpp
vendored
@ -1076,13 +1076,9 @@ BX_PRAGMA_DIAGNOSTIC_POP();
|
||||
DX_RELEASE(device, 2);
|
||||
}
|
||||
|
||||
memset(&m_adapterDesc, 0, sizeof(m_adapterDesc) );
|
||||
hr = adapter->GetDesc(&m_adapterDesc);
|
||||
if (FAILED(hr) )
|
||||
{
|
||||
BX_TRACE("Unable to create Direct3D11 device.");
|
||||
DX_RELEASE(adapter, 2);
|
||||
goto error;
|
||||
}
|
||||
BX_WARN(SUCCEEDED(hr), "Adapter GetDesc failed 0x%08x.", hr);
|
||||
|
||||
g_caps.vendorId = 0 == m_adapterDesc.VendorId
|
||||
? BGFX_PCI_ID_SOFTWARE_RASTERIZER
|
||||
@ -1354,140 +1350,168 @@ BX_PRAGMA_DIAGNOSTIC_POP();
|
||||
|
||||
if (DXGI_FORMAT_UNKNOWN != fmt)
|
||||
{
|
||||
struct D3D11_FEATURE_DATA_FORMAT_SUPPORT
|
||||
if (BX_ENABLED(BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) )
|
||||
{
|
||||
DXGI_FORMAT InFormat;
|
||||
UINT OutFormatSupport;
|
||||
};
|
||||
struct D3D11_FEATURE_DATA_FORMAT_SUPPORT
|
||||
{
|
||||
DXGI_FORMAT InFormat;
|
||||
UINT OutFormatSupport;
|
||||
};
|
||||
|
||||
D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
|
||||
data.InFormat = fmt;
|
||||
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
|
||||
if (SUCCEEDED(hr) )
|
||||
{
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE2D
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE3D
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_2D
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE3D
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_3D
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_CUBE
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_BUFFER
|
||||
| D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER
|
||||
| D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_VERTEX
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_SHADER_LOAD
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_IMAGE
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_RENDER_TARGET
|
||||
| D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_MSAA
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
BX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) );
|
||||
}
|
||||
|
||||
if (0 != (support & BGFX_CAPS_FORMAT_TEXTURE_IMAGE) )
|
||||
{
|
||||
// clear image flag for additional testing
|
||||
support &= ~BGFX_CAPS_FORMAT_TEXTURE_IMAGE;
|
||||
|
||||
data.InFormat = s_textureFormat[ii].m_fmt;
|
||||
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &data, sizeof(data) );
|
||||
D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
|
||||
data.InFormat = fmt;
|
||||
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
|
||||
if (SUCCEEDED(hr) )
|
||||
{
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD
|
||||
| D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE2D
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE3D
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_2D
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE3D
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_3D
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_CUBE
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_BUFFER
|
||||
| D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER
|
||||
| D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_VERTEX
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_SHADER_LOAD
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_IMAGE
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_RENDER_TARGET
|
||||
| D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_MSAA
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
BX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) );
|
||||
}
|
||||
|
||||
if (0 != (support & BGFX_CAPS_FORMAT_TEXTURE_IMAGE) )
|
||||
{
|
||||
// clear image flag for additional testing
|
||||
support &= ~BGFX_CAPS_FORMAT_TEXTURE_IMAGE;
|
||||
|
||||
data.InFormat = s_textureFormat[ii].m_fmt;
|
||||
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &data, sizeof(data) );
|
||||
if (SUCCEEDED(hr) )
|
||||
{
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD
|
||||
| D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_IMAGE
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
support |= 0
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_2D
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_3D
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_CUBE
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_IMAGE
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_VERTEX
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_IMAGE
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_MSAA
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (DXGI_FORMAT_UNKNOWN != fmtSrgb)
|
||||
{
|
||||
struct D3D11_FEATURE_DATA_FORMAT_SUPPORT
|
||||
if (BX_ENABLED(BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) )
|
||||
{
|
||||
DXGI_FORMAT InFormat;
|
||||
UINT OutFormatSupport;
|
||||
};
|
||||
struct D3D11_FEATURE_DATA_FORMAT_SUPPORT
|
||||
{
|
||||
DXGI_FORMAT InFormat;
|
||||
UINT OutFormatSupport;
|
||||
};
|
||||
|
||||
D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
|
||||
data.InFormat = fmtSrgb;
|
||||
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
|
||||
if (SUCCEEDED(hr) )
|
||||
{
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE2D
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
|
||||
data.InFormat = fmtSrgb;
|
||||
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
|
||||
if (SUCCEEDED(hr) )
|
||||
{
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE2D
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE3D
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURE3D
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
support |= 0 != (data.OutFormatSupport & (0
|
||||
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
|
||||
) )
|
||||
? BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB
|
||||
: BGFX_CAPS_FORMAT_TEXTURE_NONE
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
BX_TRACE("CheckFeatureSupport failed with %x for sRGB format %s.", hr, getName(TextureFormat::Enum(ii) ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BX_TRACE("CheckFeatureSupport failed with %x for sRGB format %s.", hr, getName(TextureFormat::Enum(ii) ) );
|
||||
support |= 0
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB
|
||||
| BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2132,7 +2156,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
|
||||
ovrPostReset();
|
||||
|
||||
// If OVR doesn't create separate depth stencil view, create default one.
|
||||
if (NULL == m_backBufferDepthStencil)
|
||||
if (!m_ovr.isEnabled() && NULL == m_backBufferDepthStencil)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC dsd;
|
||||
dsd.Width = getBufferWidth();
|
||||
@ -3096,13 +3120,15 @@ BX_PRAGMA_DIAGNOSTIC_POP();
|
||||
{
|
||||
if (m_ovr.postReset() )
|
||||
{
|
||||
const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT);
|
||||
|
||||
for (uint32_t ii = 0; ii < 2; ++ii)
|
||||
{
|
||||
// eye buffers need to be initialized only once during application lifetime
|
||||
if (NULL == m_ovr.m_eyeBuffers[ii])
|
||||
{
|
||||
m_ovr.m_eyeBuffers[ii] = &m_ovrBuffers[ii];
|
||||
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii);
|
||||
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii, msaaSamples);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3566,10 +3592,13 @@ BX_PRAGMA_DIAGNOSTIC_POP();
|
||||
}
|
||||
|
||||
#if BGFX_CONFIG_USE_OVR
|
||||
void OVRBufferD3D11::create(const ovrSession& _session, int _eyeIdx)
|
||||
void OVRBufferD3D11::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples)
|
||||
{
|
||||
ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session);
|
||||
m_eyeTextureSize = ovr_GetFovTextureSize(_session, (ovrEyeType)_eyeIdx, hmdDesc.DefaultEyeFov[_eyeIdx], 1.0f);
|
||||
m_msaaTexture = NULL;
|
||||
m_msaaRtv = NULL;
|
||||
m_msaaSv = NULL;
|
||||
|
||||
ovrTextureSwapChainDesc desc = {};
|
||||
desc.Type = ovrTexture_2D;
|
||||
@ -3617,7 +3646,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
|
||||
dbDesc.MipLevels = 1;
|
||||
dbDesc.ArraySize = 1;
|
||||
dbDesc.Format = DXGI_FORMAT_D32_FLOAT;
|
||||
dbDesc.SampleDesc.Count = 1;
|
||||
dbDesc.SampleDesc.Count = _msaaSamples;
|
||||
dbDesc.SampleDesc.Quality = 0;
|
||||
dbDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
dbDesc.CPUAccessFlags = 0;
|
||||
@ -3627,29 +3656,74 @@ BX_PRAGMA_DIAGNOSTIC_POP();
|
||||
DX_CHECK(device->CreateTexture2D(&dbDesc, NULL, &tex) );
|
||||
DX_CHECK(device->CreateDepthStencilView(tex, NULL, &m_depthBuffer) );
|
||||
DX_RELEASE(tex, 0);
|
||||
|
||||
// create MSAA render target
|
||||
if (_msaaSamples > 1)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC dsDesc;
|
||||
dsDesc.Width = m_eyeTextureSize.w;
|
||||
dsDesc.Height = m_eyeTextureSize.h;
|
||||
dsDesc.MipLevels = 1;
|
||||
dsDesc.ArraySize = 1;
|
||||
dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
dsDesc.SampleDesc.Count = _msaaSamples;
|
||||
dsDesc.SampleDesc.Quality = 0;
|
||||
dsDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
dsDesc.CPUAccessFlags = 0;
|
||||
dsDesc.MiscFlags = 0;
|
||||
dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||
|
||||
ID3D11Device* device = s_renderD3D11->m_device;
|
||||
DX_CHECK(device->CreateTexture2D(&dsDesc, NULL, &m_msaaTexture));
|
||||
DX_CHECK(device->CreateShaderResourceView(m_msaaTexture, NULL, &m_msaaSv));
|
||||
DX_CHECK(device->CreateRenderTargetView(m_msaaTexture, NULL, &m_msaaRtv));
|
||||
}
|
||||
}
|
||||
|
||||
void OVRBufferD3D11::render(const ovrSession& _session)
|
||||
{
|
||||
// Clear and set up rendertarget
|
||||
int texIndex = 0;
|
||||
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &texIndex);
|
||||
|
||||
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
|
||||
|
||||
float black[] = { 0.0f, 0.0f, 0.0f, 0.0f }; // Important that alpha=0, if want pixels to be transparent, for manual layers
|
||||
deviceCtx->OMSetRenderTargets(1, &m_eyeRtv[texIndex], m_depthBuffer);
|
||||
deviceCtx->ClearRenderTargetView(m_eyeRtv[texIndex], black);
|
||||
deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
|
||||
|
||||
D3D11_VIEWPORT D3Dvp;
|
||||
D3Dvp.TopLeftX = 0;
|
||||
D3Dvp.TopLeftY = 0;
|
||||
D3Dvp.Width = (FLOAT)m_eyeTextureSize.w;
|
||||
D3Dvp.Height = (FLOAT)m_eyeTextureSize.h;
|
||||
D3Dvp.MinDepth = 0;
|
||||
D3Dvp.MaxDepth = 1;
|
||||
deviceCtx->RSSetViewports(1, &D3Dvp);
|
||||
// render to MSAA target
|
||||
if (NULL != m_msaaTexture)
|
||||
{
|
||||
deviceCtx->OMSetRenderTargets(1, &m_msaaRtv, m_depthBuffer);
|
||||
deviceCtx->ClearRenderTargetView(m_msaaRtv, black);
|
||||
deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
|
||||
}
|
||||
else // MSAA disabled? render directly to eye buffer
|
||||
{
|
||||
int texIndex = 0;
|
||||
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &texIndex);
|
||||
|
||||
deviceCtx->OMSetRenderTargets(1, &m_eyeRtv[texIndex], m_depthBuffer);
|
||||
deviceCtx->ClearRenderTargetView(m_eyeRtv[texIndex], black);
|
||||
deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
|
||||
|
||||
D3D11_VIEWPORT D3Dvp;
|
||||
D3Dvp.TopLeftX = 0;
|
||||
D3Dvp.TopLeftY = 0;
|
||||
D3Dvp.Width = (FLOAT)m_eyeTextureSize.w;
|
||||
D3Dvp.Height = (FLOAT)m_eyeTextureSize.h;
|
||||
D3Dvp.MinDepth = 0;
|
||||
D3Dvp.MaxDepth = 1;
|
||||
deviceCtx->RSSetViewports(1, &D3Dvp);
|
||||
}
|
||||
}
|
||||
|
||||
void OVRBufferD3D11::postRender(const ovrSession& _session)
|
||||
{
|
||||
if (NULL != m_msaaTexture)
|
||||
{
|
||||
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
|
||||
int destIndex = 0;
|
||||
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &destIndex);
|
||||
ID3D11Resource* dstTex = NULL;
|
||||
ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain, destIndex, IID_PPV_ARGS(&dstTex));
|
||||
deviceCtx->ResolveSubresource(dstTex, 0, m_msaaTexture, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
dstTex->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void OVRBufferD3D11::destroy(const ovrSession& _session)
|
||||
@ -3661,6 +3735,24 @@ BX_PRAGMA_DIAGNOSTIC_POP();
|
||||
|
||||
ovr_DestroyTextureSwapChain(_session, m_textureSwapChain);
|
||||
m_depthBuffer->Release();
|
||||
|
||||
if (NULL != m_msaaTexture)
|
||||
{
|
||||
m_msaaTexture->Release();
|
||||
m_msaaTexture = NULL;
|
||||
}
|
||||
|
||||
if (NULL != m_msaaSv)
|
||||
{
|
||||
m_msaaSv->Release();
|
||||
m_msaaSv = NULL;
|
||||
}
|
||||
|
||||
if (NULL != m_msaaRtv)
|
||||
{
|
||||
m_msaaRtv->Release();
|
||||
m_msaaRtv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void OVRMirrorD3D11::create(const ovrSession& _session, int _width, int _height)
|
||||
|
7
3rdparty/bgfx/src/renderer_d3d11.h
vendored
7
3rdparty/bgfx/src/renderer_d3d11.h
vendored
@ -33,6 +33,7 @@ BX_PRAGMA_DIAGNOSTIC_POP()
|
||||
#include "renderer_d3d.h"
|
||||
#include "shader_dxbc.h"
|
||||
#include "hmd_ovr.h"
|
||||
#include "hmd_openvr.h"
|
||||
#include "debug_renderdoc.h"
|
||||
|
||||
#ifndef D3DCOLOR_ARGB
|
||||
@ -62,12 +63,16 @@ namespace bgfx { namespace d3d11
|
||||
#if BGFX_CONFIG_USE_OVR
|
||||
struct OVRBufferD3D11 : public OVRBufferI
|
||||
{
|
||||
virtual void create(const ovrSession& _session, int _eyeIdx) BX_OVERRIDE;
|
||||
virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) BX_OVERRIDE;
|
||||
virtual void destroy(const ovrSession& _session) BX_OVERRIDE;
|
||||
virtual void render(const ovrSession& _session) BX_OVERRIDE;
|
||||
virtual void postRender(const ovrSession& _session) BX_OVERRIDE;
|
||||
|
||||
ID3D11RenderTargetView* m_eyeRtv[4];
|
||||
ID3D11DepthStencilView* m_depthBuffer;
|
||||
ID3D11Texture2D* m_msaaTexture;
|
||||
ID3D11ShaderResourceView* m_msaaSv;
|
||||
ID3D11RenderTargetView* m_msaaRtv;
|
||||
};
|
||||
|
||||
struct OVRMirrorD3D11 : public OVRMirrorI
|
||||
|
104
3rdparty/bgfx/src/renderer_gl.cpp
vendored
104
3rdparty/bgfx/src/renderer_gl.cpp
vendored
@ -2864,13 +2864,15 @@ namespace bgfx { namespace gl
|
||||
{
|
||||
if (m_ovr.postReset() )
|
||||
{
|
||||
const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT);
|
||||
|
||||
for (uint32_t ii = 0; ii < 2; ++ii)
|
||||
{
|
||||
// eye buffers need to be initialized only once during application lifetime
|
||||
if (NULL == m_ovr.m_eyeBuffers[ii])
|
||||
{
|
||||
m_ovr.m_eyeBuffers[ii] = &m_ovrBuffers[ii];
|
||||
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii);
|
||||
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii, msaaSamples);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3332,8 +3334,15 @@ namespace bgfx { namespace gl
|
||||
}
|
||||
|
||||
#if BGFX_CONFIG_USE_OVR
|
||||
void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx)
|
||||
void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples)
|
||||
{
|
||||
m_eyeFbo = 0;
|
||||
m_eyeTexId = 0;
|
||||
m_depthBuffer = 0;
|
||||
m_msaaEyeFbo = 0;
|
||||
m_msaaEyeTexId = 0;
|
||||
m_msaaDepthBuffer = 0;
|
||||
|
||||
ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session);
|
||||
m_eyeTextureSize = ovr_GetFovTextureSize(_session, ovrEyeType(_eyeIdx), hmdDesc.DefaultEyeFov[_eyeIdx], 1.0f);
|
||||
|
||||
@ -3375,6 +3384,35 @@ namespace bgfx { namespace gl
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
|
||||
|
||||
GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_eyeTextureSize.w, m_eyeTextureSize.h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL) );
|
||||
|
||||
// create MSAA buffers
|
||||
if (_msaaSamples > 1)
|
||||
{
|
||||
GL_CHECK(glGenFramebuffers(1, &m_msaaEyeFbo) );
|
||||
|
||||
// create color MSAA texture
|
||||
GL_CHECK(glGenTextures(1, &m_msaaEyeTexId) );
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId) );
|
||||
|
||||
GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_RGBA, m_eyeTextureSize.w, m_eyeTextureSize.h, false) );
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) );
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) );
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) );
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) );
|
||||
|
||||
// create MSAA depth buffer
|
||||
GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer) );
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer) );
|
||||
|
||||
GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_DEPTH_COMPONENT, m_eyeTextureSize.w, m_eyeTextureSize.h, false) );
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) );
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) );
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) );
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
|
||||
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) );
|
||||
}
|
||||
}
|
||||
|
||||
void OVRBufferGL::render(const ovrSession& _session)
|
||||
@ -3384,20 +3422,74 @@ namespace bgfx { namespace gl
|
||||
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &curIndex);
|
||||
ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, curIndex, &m_eyeTexId);
|
||||
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo) );
|
||||
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) );
|
||||
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0) );
|
||||
|
||||
if (0 != m_msaaEyeFbo)
|
||||
{
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaEyeFbo) );
|
||||
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId, 0) );
|
||||
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer, 0) );
|
||||
}
|
||||
else // MSAA disabled? render directly to eye buffer
|
||||
{
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo) );
|
||||
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) );
|
||||
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0) );
|
||||
}
|
||||
GL_CHECK(glViewport(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h) );
|
||||
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) );
|
||||
}
|
||||
|
||||
void OVRBufferGL::postRender(const ovrSession& /*_sesion*/)
|
||||
{
|
||||
if (0 != m_msaaEyeFbo && 0 != m_eyeTexId)
|
||||
{
|
||||
// blit the contents of MSAA FBO to the regular eye buffer "connected" to the HMD
|
||||
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo));
|
||||
GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId, 0) );
|
||||
GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
|
||||
|
||||
BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_READ_FRAMEBUFFER)
|
||||
, "glCheckFramebufferStatus failed 0x%08x"
|
||||
, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) );
|
||||
|
||||
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_eyeFbo));
|
||||
GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) );
|
||||
GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
|
||||
|
||||
BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
|
||||
, "glCheckFramebufferStatus failed 0x%08x"
|
||||
, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) );
|
||||
|
||||
GL_CHECK(glBlitFramebuffer(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h,
|
||||
0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h, GL_COLOR_BUFFER_BIT, GL_NEAREST) );
|
||||
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
|
||||
}
|
||||
}
|
||||
|
||||
void OVRBufferGL::destroy(const ovrSession& _session)
|
||||
{
|
||||
GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo) );
|
||||
GL_CHECK(glDeleteTextures(1, &m_depthBuffer) );
|
||||
|
||||
ovr_DestroyTextureSwapChain(_session, m_textureSwapChain);
|
||||
|
||||
if (0 != m_msaaEyeFbo)
|
||||
{
|
||||
GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo) );
|
||||
m_msaaEyeFbo = 0;
|
||||
}
|
||||
|
||||
if (0 != m_msaaEyeTexId)
|
||||
{
|
||||
GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId));
|
||||
m_msaaEyeTexId = 0;
|
||||
}
|
||||
|
||||
if (0 != m_msaaDepthBuffer)
|
||||
{
|
||||
GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer));
|
||||
m_msaaDepthBuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OVRMirrorGL::create(const ovrSession& _session, int _width, int _height)
|
||||
|
15
3rdparty/bgfx/src/renderer_gl.h
vendored
15
3rdparty/bgfx/src/renderer_gl.h
vendored
@ -108,6 +108,7 @@ typedef uint64_t GLuint64;
|
||||
|
||||
#include "renderer.h"
|
||||
#include "hmd_ovr.h"
|
||||
#include "hmd_openvr.h"
|
||||
#include "debug_renderdoc.h"
|
||||
|
||||
#ifndef GL_LUMINANCE
|
||||
@ -904,13 +905,17 @@ namespace bgfx { namespace gl
|
||||
#if BGFX_CONFIG_USE_OVR
|
||||
struct OVRBufferGL : public OVRBufferI
|
||||
{
|
||||
virtual void create(const ovrSession& _session, int _eyeIdx) BX_OVERRIDE;
|
||||
virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) BX_OVERRIDE;
|
||||
virtual void destroy(const ovrSession& _session) BX_OVERRIDE;
|
||||
virtual void render(const ovrSession& _session) BX_OVERRIDE;
|
||||
virtual void postRender(const ovrSession& _sesion) BX_OVERRIDE;
|
||||
|
||||
GLuint m_eyeFbo;
|
||||
GLuint m_eyeTexId;
|
||||
GLuint m_depthBuffer;
|
||||
GLuint m_msaaEyeFbo;
|
||||
GLuint m_msaaEyeTexId;
|
||||
GLuint m_msaaDepthBuffer;
|
||||
};
|
||||
|
||||
struct OVRMirrorGL : public OVRMirrorI
|
||||
@ -1284,8 +1289,8 @@ namespace bgfx { namespace gl
|
||||
|
||||
void create(const ShaderGL& _vsh, const ShaderGL& _fsh);
|
||||
void destroy();
|
||||
void init();
|
||||
void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const;
|
||||
void init();
|
||||
void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const;
|
||||
void bindInstanceData(uint32_t _stride, uint32_t _baseVertex = 0) const;
|
||||
|
||||
void add(uint32_t _hash)
|
||||
@ -1299,8 +1304,8 @@ namespace bgfx { namespace gl
|
||||
GLint m_attributes[Attrib::Count]; // sparse
|
||||
GLint m_instanceData[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT+1];
|
||||
|
||||
GLint m_sampler[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
|
||||
uint8_t m_numSamplers;
|
||||
GLint m_sampler[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
|
||||
uint8_t m_numSamplers;
|
||||
|
||||
UniformBuffer* m_constantBuffer;
|
||||
PredefinedUniform m_predefined[PredefinedUniform::Count];
|
||||
|
@ -34,7 +34,7 @@ function cheatfind.startplugin()
|
||||
if device:shortname() == "ram" then
|
||||
ram[tag] = {}
|
||||
ram[tag].dev = device
|
||||
ram[tag].size = emu.item(device.items["0/m_size"]:read(0))
|
||||
ram[tag].size = emu.item(device.items["0/m_size"]):read(0)
|
||||
end
|
||||
end
|
||||
return ram
|
||||
@ -42,10 +42,10 @@ function cheatfind.startplugin()
|
||||
|
||||
-- save data block
|
||||
function cheat.save(space, start, size)
|
||||
local data = { block = "", dev = space, start = start, size = size, space = space }
|
||||
local data = { block = "", start = start, size = size, space = space }
|
||||
if space.shortname then
|
||||
if space:shortname() == "ram" then
|
||||
data.block = emu.item(device.items["0/m_pointer"]):read_block(start, size)
|
||||
data.block = emu.item(space.items["0/m_pointer"]):read_block(start, size)
|
||||
if not data.block then
|
||||
return nil
|
||||
end
|
||||
@ -61,8 +61,45 @@ function cheatfind.startplugin()
|
||||
end
|
||||
|
||||
-- compare two data blocks
|
||||
function cheat.comp(olddata, newdata, oper, val)
|
||||
function cheat.comp(olddata, newdata, oper, val, signed, width, endian)
|
||||
local ret = {}
|
||||
local format = ""
|
||||
local size = olddata.size
|
||||
|
||||
if endian == 1 then
|
||||
format = format .. ">"
|
||||
else
|
||||
format = format .. "<"
|
||||
end
|
||||
if width == 16 then
|
||||
size = size & 0xfffe
|
||||
if signed == "signed" then
|
||||
format = format .. "h"
|
||||
else
|
||||
format = format .. "H"
|
||||
end
|
||||
elseif width == 32 then
|
||||
size = size & 0xfffc
|
||||
if signed == "signed" then
|
||||
format = format .. "l"
|
||||
else
|
||||
format = format .. "L"
|
||||
end
|
||||
elseif width == 64 then
|
||||
size = size & 0xfff8
|
||||
if signed == "signed" then
|
||||
format = format .. "j"
|
||||
else
|
||||
format = format .. "J"
|
||||
end
|
||||
else
|
||||
if signed == "signed" then
|
||||
format = format .. "b"
|
||||
else
|
||||
format = format .. "B"
|
||||
end
|
||||
end
|
||||
|
||||
if olddata.start ~= newdata.start or olddata.size ~= newdata.size then
|
||||
return {}
|
||||
end
|
||||
@ -70,37 +107,37 @@ function cheatfind.startplugin()
|
||||
val = 0
|
||||
end
|
||||
if oper == "+" or oper == "inc" or oper == "<" or oper == "lt" then
|
||||
for i = 1, olddata.size do
|
||||
local old = string.unpack("B", olddata.block, i)
|
||||
local new = string.unpack("B", newdata.block, i)
|
||||
for i = 1, size do
|
||||
local old = string.unpack(format, olddata.block, i)
|
||||
local new = string.unpack(format, newdata.block, i)
|
||||
if old < new then
|
||||
if (val > 0 and (old + val) == new) or val == 0 then
|
||||
ret[#ret + 1] = { addr = olddata.start + i,
|
||||
oldval = old,
|
||||
newval = new}
|
||||
ret[#ret + 1] = { addr = olddata.start + i - 1,
|
||||
oldval = old,
|
||||
newval = new}
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif oper == "-" or oper == "dec" or oper == ">" or oper == "gt" then
|
||||
for i = 1, olddata.size do
|
||||
local old = string.unpack("B", olddata.block, i)
|
||||
local new = string.unpack("B", newdata.block, i)
|
||||
for i = 1, size do
|
||||
local old = string.unpack(format, olddata.block, i)
|
||||
local new = string.unpack(format, newdata.block, i)
|
||||
if old > new then
|
||||
if (val > 0 and (old - val) == new) or val == 0 then
|
||||
ret[#ret + 1] = { addr = olddata.start + i,
|
||||
oldval = old,
|
||||
newval = new}
|
||||
ret[#ret + 1] = { addr = olddata.start + i - 1,
|
||||
oldval = old,
|
||||
newval = new}
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif oper == "=" or oper == "eq" then
|
||||
for i = 1, olddata.size do
|
||||
local old = string.unpack("B", olddata.block, i)
|
||||
local new = string.unpack("B", newdata.block, i)
|
||||
for i = 1, size do
|
||||
local old = string.unpack(format, olddata.block, i)
|
||||
local new = string.unpack(format, newdata.block, i)
|
||||
if old == new then
|
||||
ret[#ret + 1] = { addr = olddata.start + i,
|
||||
oldval = old,
|
||||
newval = new}
|
||||
ret[#ret + 1] = { addr = olddata.start + i - 1,
|
||||
oldval = old,
|
||||
newval = new}
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -108,15 +145,18 @@ function cheatfind.startplugin()
|
||||
end
|
||||
|
||||
-- compare a data block to the current state
|
||||
function cheat.compcur(olddata, oper, val)
|
||||
local newdata = cheat.save(olddata.dev, olddata.start, olddata.size, olddata.space)
|
||||
return cheat.comp(olddata, newdata, oper, val)
|
||||
function cheat.compcur(olddata, oper, val, signed, width, endian)
|
||||
local newdata = cheat.save(olddata.space, olddata.start, olddata.size, olddata.space)
|
||||
return cheat.comp(olddata, newdata, oper, val, signed, width, endian)
|
||||
end
|
||||
|
||||
|
||||
_G.cf = cheat
|
||||
|
||||
|
||||
local devtable = {}
|
||||
local devsel = 1
|
||||
local bitwidth = 3
|
||||
local signed = 0
|
||||
local endian = 0
|
||||
local optable = { "<", ">", "=" }
|
||||
local opsel = 1
|
||||
local value = 0
|
||||
@ -125,11 +165,16 @@ function cheatfind.startplugin()
|
||||
local matches = {}
|
||||
local matchsel = 1
|
||||
local menu_blocks = {}
|
||||
local midx = { region = 1, init = 2, save = 3, op = 5, val = 6, lop = 7, rop = 8, comp = 9, match = 11 }
|
||||
local midx = { region = 1, init = 2, save = 3, width = 5, signed = 6, endian = 7, op = 8, val = 9,
|
||||
lop = 10, rop = 11, comp = 12, match = 14 }
|
||||
|
||||
local function start()
|
||||
devtable = {}
|
||||
devsel = 1
|
||||
devsel = 1
|
||||
bitwidth = 3
|
||||
signed = 0
|
||||
endian = 0
|
||||
opsel = 1
|
||||
value = 0
|
||||
leftop = 1
|
||||
@ -154,7 +199,7 @@ function cheatfind.startplugin()
|
||||
end
|
||||
table = cheat.getram()
|
||||
for tag, ram in pairs(table) do
|
||||
devtable[#devtable + 1] = { tag = tag, space = ram.dev, ram = { offset = 0, size = ram.size } }
|
||||
devtable[#devtable + 1] = { tag = tag, space = ram.dev, ram = {{ offset = 0, size = ram.size }} }
|
||||
end
|
||||
end
|
||||
|
||||
@ -162,55 +207,56 @@ function cheatfind.startplugin()
|
||||
|
||||
local function menu_populate()
|
||||
local menu = {}
|
||||
|
||||
local function menu_lim(val, min, max, menuitem)
|
||||
if val == min then
|
||||
menuitem[3] = "r"
|
||||
elseif val == max then
|
||||
menuitem[3] = "l"
|
||||
else
|
||||
menuitem[3] = "lr"
|
||||
end
|
||||
end
|
||||
|
||||
menu[midx.region] = { "CPU or RAM", devtable[devsel].tag, "" }
|
||||
if #devtable == 1 then
|
||||
menu[midx.region][3] = 0
|
||||
elseif devsel == 1 then
|
||||
menu[midx.region][3] = "r"
|
||||
elseif devsel == #devtable then
|
||||
menu[midx.region][3] = "l"
|
||||
else
|
||||
menu[midx.region][3] = "lr"
|
||||
menu_lim(devsel, 1, #devtable, menu[midx.region])
|
||||
end
|
||||
menu[midx.init] = { "Init", "", 0 }
|
||||
if next(menu_blocks) then
|
||||
menu[midx.save] = { "Save current", "", 0 }
|
||||
menu[midx.save + 1] = { "---", "", "off" }
|
||||
menu[midx.op] = { "Operator", optable[opsel], "" }
|
||||
if opsel == 1 then
|
||||
menu[midx.op][3] = "r"
|
||||
elseif opsel == #optable then
|
||||
menu[midx.op][3] = "l"
|
||||
else
|
||||
menu[midx.op][3] = "lr"
|
||||
menu[midx.width] = { "Bit Width", 1 << bitwidth , 0 }
|
||||
menu_lim(bitwidth, 3, 6, menu[midx.width])
|
||||
menu[midx.signed] = { "Signed", "false", 0 }
|
||||
menu_lim(signed, 0, 1, menu[midx.signed])
|
||||
if signed == 1 then
|
||||
menu[midx.signed][2] = "true"
|
||||
end
|
||||
menu[midx.endian] = { "Endian", "little", 0 }
|
||||
menu_lim(endian, 0, 1, menu[midx.endian])
|
||||
if endian == 1 then
|
||||
menu[midx.endian][2] = "big"
|
||||
end
|
||||
menu[midx.op] = { "Operator", optable[opsel], "" }
|
||||
menu_lim(opsel, 1, #optable, menu[midx.op])
|
||||
menu[midx.val] = { "Value", value, "" }
|
||||
menu_lim(value, 0, 100, menu[midx.val]) -- max value?
|
||||
if value == 0 then
|
||||
menu[midx.val][2] = "Any"
|
||||
menu[midx.val][3] = "r"
|
||||
elseif value == 100 then --?
|
||||
menu[midx.val][3] = "l"
|
||||
else
|
||||
menu[midx.val][3] = "lr"
|
||||
end
|
||||
menu[midx.lop] = { "Left operand", leftop, "" }
|
||||
if #menu_blocks == 1 then
|
||||
menu[midx.lop][3] = 0
|
||||
elseif leftop == 1 then
|
||||
menu[midx.lop][3] = "r"
|
||||
elseif leftop == #menu_blocks then
|
||||
menu[midx.lop][3] = "l"
|
||||
else
|
||||
menu[midx.lop][3] = "lr"
|
||||
menu_lim(leftop, 1, #menu_blocks, menu[midx.lop])
|
||||
end
|
||||
menu[midx.rop] = { "Right operand", leftop, "" }
|
||||
menu[midx.rop] = { "Right operand", rightop, "" }
|
||||
menu_lim(rightop, 0, #menu_blocks, menu[midx.rop])
|
||||
if rightop == 0 then
|
||||
menu[midx.rop][2] = "Current"
|
||||
menu[midx.rop][3] = "r"
|
||||
elseif rightop == #menu_blocks then
|
||||
menu[midx.rop][3] = "l"
|
||||
else
|
||||
menu[midx.rop][3] = "lr"
|
||||
end
|
||||
menu[midx.comp] = { "Compare", "", 0 }
|
||||
if next(matches) then
|
||||
@ -218,18 +264,25 @@ function cheatfind.startplugin()
|
||||
menu[midx.match] = { "Match block", matchsel, "" }
|
||||
if #matches == 1 then
|
||||
menu[midx.match][3] = 0
|
||||
elseif matchsel == 1 then
|
||||
menu[midx.match][3] = "r"
|
||||
elseif matchsel == #matches then
|
||||
menu[midx.match][3] = "l"
|
||||
else
|
||||
menu[midx.match][3] = "lr"
|
||||
menu_lim(matchsel, 1, #matches, menu[midx.match])
|
||||
end
|
||||
for num2, match in ipairs(matches[matchsel]) do
|
||||
if #menu > 50 then
|
||||
break
|
||||
end
|
||||
menu[#menu + 1] = { string.format("%08x %02x %02x", match.addr, match.oldval, match.newval), "", 0 }
|
||||
local numform = ""
|
||||
if bitwidth == 4 then
|
||||
numform = " %04x"
|
||||
elseif bitwidth == 5 then
|
||||
numform = " %08x"
|
||||
elseif bitwidth == 6 then
|
||||
numform = " %016x"
|
||||
else
|
||||
numform = " %02x"
|
||||
end
|
||||
menu[#menu + 1] = { string.format("%08x" .. numform .. numform, match.addr, match.oldval,
|
||||
match.newval), "", 0 }
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -237,17 +290,30 @@ function cheatfind.startplugin()
|
||||
end
|
||||
|
||||
local function menu_callback(index, event)
|
||||
local ret = false
|
||||
|
||||
local function incdec(val, min, max)
|
||||
if event == "left" and val ~= min then
|
||||
val = val - 1
|
||||
ret = true
|
||||
elseif event == "right" and val ~= max then
|
||||
val = val + 1
|
||||
ret = true
|
||||
end
|
||||
return val
|
||||
end
|
||||
|
||||
if index == midx.region then
|
||||
if event == "left" then
|
||||
if devsel ~= 1 then
|
||||
devsel = devsel - 1
|
||||
return true
|
||||
end
|
||||
elseif event == "right" then
|
||||
if devsel ~= #devtable then
|
||||
devsel = devsel + 1
|
||||
return true
|
||||
devsel = incdec(devsel, 1, #devtable)
|
||||
elseif index == midx.init then
|
||||
if event == "select" then
|
||||
menu_blocks = {{}}
|
||||
matches = {}
|
||||
for num, region in ipairs(devtable[devsel].ram) do
|
||||
menu_blocks[1][num] = cheat.save(devtable[devsel].space, region.offset, region.size)
|
||||
end
|
||||
manager:machine():popmessage("Data cleared and current state saved")
|
||||
ret = true
|
||||
end
|
||||
elseif index == midx.init then
|
||||
if event == "select" then
|
||||
@ -257,16 +323,23 @@ function cheatfind.startplugin()
|
||||
menu_blocks[1][num] = cheat.save(devtable[devsel].space, region.offset, region.size)
|
||||
end
|
||||
manager:machine():popmessage("Data cleared and current state saved")
|
||||
return true
|
||||
ret = true
|
||||
end
|
||||
elseif index == midx.save then
|
||||
if event == "select" then
|
||||
menu_blocks[#menu_blocks + 1] = {}
|
||||
for num, region in ipairs(devtable[devsel].ram) do
|
||||
menu_blocks[#menu_blocks][num] = cheat.save(devtable[devsel].space, region.offset, region.size)
|
||||
end
|
||||
manager:machine():popmessage("Current state saved")
|
||||
return false
|
||||
end
|
||||
ret = true
|
||||
end
|
||||
elseif index == midx.width then
|
||||
bitwidth = incdec(bitwidth, 3, 6)
|
||||
elseif index == midx.signed then
|
||||
signed = incdec(signed, 0, 1)
|
||||
elseif index == midx.endian then
|
||||
endian = incdec(endian, 0, 1)
|
||||
elseif index == midx.op then
|
||||
if event == "up" or event == "down" or event == "comment" then
|
||||
if optable[opsel] == "<" then
|
||||
@ -276,84 +349,37 @@ function cheatfind.startplugin()
|
||||
elseif optable[opsel] == "=" then
|
||||
manager:machine():popmessage("Left equal to right, value is ignored")
|
||||
end
|
||||
elseif event == "left" then
|
||||
if opsel ~= 1 then
|
||||
opsel = opsel - 1
|
||||
return true
|
||||
end
|
||||
elseif event == "right" then
|
||||
if opsel ~= #optable then
|
||||
opsel = opsel + 1
|
||||
return true
|
||||
end
|
||||
else
|
||||
opsel = incdec(opsel, 1, #optable)
|
||||
end
|
||||
elseif index == midx.val then
|
||||
if event == "left" then
|
||||
if value ~= 0 then
|
||||
value = value - 1
|
||||
return true
|
||||
end
|
||||
elseif event == "right" then
|
||||
if value ~= 100 then
|
||||
value = value + 1
|
||||
return true
|
||||
end
|
||||
end
|
||||
value = incdec(value, 0, 100)
|
||||
elseif index == midx.lop then
|
||||
if event == "left" then
|
||||
if leftop ~= 1 then
|
||||
leftop = leftop - 1
|
||||
return true
|
||||
end
|
||||
elseif event == "right" then
|
||||
if leftop ~= #menu_blocks then
|
||||
leftop = leftop + 1
|
||||
return true
|
||||
end
|
||||
end
|
||||
leftop = incdec(leftop, 1, #menu_blocks)
|
||||
elseif index == midx.rop then
|
||||
if event == "left" then
|
||||
if rightop ~= 0 then
|
||||
rightop = rightop - 1
|
||||
return true
|
||||
end
|
||||
elseif event == "right" then
|
||||
if rightop ~= #menu_blocks then
|
||||
rightop = rightop + 1
|
||||
return true
|
||||
end
|
||||
end
|
||||
rightop = incdec(rightop, 0, #menu_blocks)
|
||||
elseif index == midx.comp then
|
||||
if event == "select" then
|
||||
matches = {}
|
||||
for num = 1, #menu_blocks[1] do
|
||||
if rightop == 0 then
|
||||
matches[#matches + 1] = cheat.compcur(menu_blocks[leftop][num], optable[opsel], value)
|
||||
matches[#matches + 1] = cheat.compcur(menu_blocks[leftop][num], optable[opsel], value,
|
||||
signed, 1 << bitwidth, endian)
|
||||
else
|
||||
matches[#matches + 1] = cheat.comp(menu_blocks[leftop][num], menu_blocks[rightop][num],
|
||||
optable[opsel], value)
|
||||
optable[opsel], value, signed, 1 << bitwidth, endian)
|
||||
end
|
||||
end
|
||||
return true
|
||||
ret = true
|
||||
end
|
||||
elseif index == midx.match then
|
||||
if event == "left" then
|
||||
if matchsel ~= 1 then
|
||||
matchsel = matchsel - 1
|
||||
return true
|
||||
end
|
||||
elseif event == "right" then
|
||||
if matchsel ~= #matches then
|
||||
matchsel = matchsel + 1
|
||||
return true
|
||||
end
|
||||
end
|
||||
matchsel = incdec(matchsel, 0, #matches)
|
||||
elseif index > midx.match then
|
||||
if event == "select" then
|
||||
-- write out a script?
|
||||
end
|
||||
end
|
||||
return false
|
||||
return ret
|
||||
end
|
||||
emu.register_menu(menu_callback, menu_populate, "Cheat Finder")
|
||||
end
|
||||
|
@ -801,6 +801,7 @@ end
|
||||
MAME_DIR .. "3rdparty/bgfx/src/glcontext_wgl.cpp",
|
||||
MAME_DIR .. "3rdparty/bgfx/src/image.cpp",
|
||||
MAME_DIR .. "3rdparty/bgfx/src/hmd_ovr.cpp",
|
||||
MAME_DIR .. "3rdparty/bgfx/src/hmd_openvr.cpp",
|
||||
MAME_DIR .. "3rdparty/bgfx/src/renderer_d3d12.cpp",
|
||||
MAME_DIR .. "3rdparty/bgfx/src/renderer_d3d11.cpp",
|
||||
MAME_DIR .. "3rdparty/bgfx/src/renderer_d3d9.cpp",
|
||||
|
@ -703,6 +703,23 @@ if (BUSES["INTV"]~=null) then
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/bus/intv/slot.h,BUSES["INTV_CTRL"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (BUSES["INTV_CTRL"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/bus/intv_ctrl/ctrl.cpp",
|
||||
MAME_DIR .. "src/devices/bus/intv_ctrl/ctrl.h",
|
||||
MAME_DIR .. "src/devices/bus/intv_ctrl/handctrl.cpp",
|
||||
MAME_DIR .. "src/devices/bus/intv_ctrl/handctrl.h",
|
||||
MAME_DIR .. "src/devices/bus/intv_ctrl/ecs_ctrl.cpp",
|
||||
MAME_DIR .. "src/devices/bus/intv_ctrl/ecs_ctrl.h",
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/bus/isa/isa.h,BUSES["ISA"] = true
|
||||
|
@ -158,7 +158,6 @@ files {
|
||||
MAME_DIR .. "src/emu/mame.h",
|
||||
MAME_DIR .. "src/emu/machine.cpp",
|
||||
MAME_DIR .. "src/emu/machine.h",
|
||||
MAME_DIR .. "src/emu/machine.ipp",
|
||||
MAME_DIR .. "src/emu/mconfig.cpp",
|
||||
MAME_DIR .. "src/emu/mconfig.h",
|
||||
MAME_DIR .. "src/emu/memarray.cpp",
|
||||
|
@ -91,6 +91,18 @@ function osdmodulesbuild()
|
||||
MAME_DIR .. "src/osd/modules/output/none.cpp",
|
||||
MAME_DIR .. "src/osd/modules/output/console.cpp",
|
||||
MAME_DIR .. "src/osd/modules/output/network.cpp",
|
||||
MAME_DIR .. "src/osd/modules/ipc/tcp_connection.cpp",
|
||||
MAME_DIR .. "src/osd/modules/ipc/tcp_connection.h",
|
||||
MAME_DIR .. "src/osd/modules/ipc/tcp_server.cpp",
|
||||
MAME_DIR .. "src/osd/modules/ipc/tcp_server.h",
|
||||
MAME_DIR .. "src/osd/modules/ipc/raw_tcp_connection.cpp",
|
||||
MAME_DIR .. "src/osd/modules/ipc/raw_tcp_connection.h",
|
||||
MAME_DIR .. "src/osd/modules/ipc/raw_tcp_server.cpp",
|
||||
MAME_DIR .. "src/osd/modules/ipc/raw_tcp_server.h",
|
||||
MAME_DIR .. "src/osd/modules/ipc/rtc_tcp_connection.cpp",
|
||||
MAME_DIR .. "src/osd/modules/ipc/rtc_tcp_connection.h",
|
||||
MAME_DIR .. "src/osd/modules/ipc/rtc_tcp_server.cpp",
|
||||
MAME_DIR .. "src/osd/modules/ipc/rtc_tcp_server.h",
|
||||
}
|
||||
includedirs {
|
||||
ext_includedir("uv"),
|
||||
|
@ -601,6 +601,7 @@ BUSES["CENTRONICS"] = true
|
||||
--BUSES["EP64"] = true
|
||||
--BUSES["EPSON_SIO"] = true
|
||||
--BUSES["GAMEBOY"] = true
|
||||
BUSES["GAMEGEAR"] = true
|
||||
--BUSES["GBA"] = true
|
||||
BUSES["GENERIC"] = true
|
||||
--BUSES["IEEE488"] = true
|
||||
@ -632,7 +633,7 @@ BUSES["RS232"] = true
|
||||
--BUSES["SATURN"] = true
|
||||
BUSES["SCSI"] = true
|
||||
--BUSES["SCV"] = true
|
||||
--BUSES["SEGA8"] = true
|
||||
BUSES["SEGA8"] = true
|
||||
BUSES["SMS_CTRL"] = true
|
||||
BUSES["SMS_EXP"] = true
|
||||
--BUSES["SNES"] = true
|
||||
|
@ -618,6 +618,7 @@ BUSES["GENERIC"] = true
|
||||
BUSES["IEEE488"] = true
|
||||
BUSES["IMI7000"] = true
|
||||
BUSES["INTV"] = true
|
||||
BUSES["INTV_CTRL"] = true
|
||||
BUSES["IQ151"] = true
|
||||
BUSES["ISA"] = true
|
||||
BUSES["ISBX"] = true
|
||||
|
@ -5,7 +5,7 @@
|
||||
pcxporter.cpp
|
||||
|
||||
Implementation of the Applied Engineering PC Transporter card
|
||||
Preliminary version by R. Belmont
|
||||
Preliminary version by R. Belmont, additional reverse-engineering by Peter Ferrie
|
||||
|
||||
The PC Transporter is basically a PC-XT on an Apple II card.
|
||||
Features include:
|
||||
@ -37,18 +37,42 @@
|
||||
plus used for general storage by the system.
|
||||
RAM from 0xB0000-0xBFFFF is the CGA framebuffer as usual.
|
||||
|
||||
C800-CBFF?: RAM, used as scratchpad space by the software
|
||||
CF00: PC memory pointer (bits 0-7)
|
||||
CF01: PC memory pointer (bits 8-15)
|
||||
CF02: PC memory pointer (bits 16-23)
|
||||
CF03: read/write PC memory at the pointer and increment the pointer
|
||||
CF04: read/write PC memory at the pointer and *don't* increment the pointer
|
||||
CF2C: CGA 6845 register select (port 3D0/3D2/3D4/3D6)
|
||||
CF2D: CGA 6845 data read/write (port 3D1/3D3/3D5/3D7)
|
||||
CF2E: CGA mode select (port 3D8)
|
||||
CF2F: CGA color select (port 3D9)
|
||||
|
||||
TODO:
|
||||
- A2 probably also can access the V30's I/O space: where's that at? CF0E/CF0F
|
||||
are suspects...
|
||||
- What's going on at CF0E/CF0F?
|
||||
- How is the V30 started/stopped?
|
||||
- There's likely A2 ROM at CnXX and C800-CBFF to support the "Slinky" memory
|
||||
expansion card emulation function inside one of the custom ASICs. Need to
|
||||
dump this...
|
||||
|
||||
The final stages before the software settles into its loop are:
|
||||
|
||||
20 to C800 at cf30
|
||||
00 to C800 at cf31
|
||||
12 to C800 at cf2b
|
||||
21 to C800 at cf25
|
||||
33 to C800 at cf24
|
||||
80 to C800 at cf31
|
||||
20 to C800 at cf30
|
||||
loop:
|
||||
Read $C800 at cf36
|
||||
Read $C800 at cf31
|
||||
Read $C800 at cf31
|
||||
Read $C800 at cf36
|
||||
Read $C800 at cf31
|
||||
Read $C800 at cf31
|
||||
80 to C800 at cf31
|
||||
loop end: (return to loop)
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
@ -176,7 +200,7 @@ UINT8 a2bus_pcxporter_device::read_c800(address_space &space, UINT16 offset)
|
||||
|
||||
if (offset < 0x400)
|
||||
{
|
||||
return 0xff;
|
||||
return m_c800_ram[offset];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -195,12 +219,20 @@ UINT8 a2bus_pcxporter_device::read_c800(address_space &space, UINT16 offset)
|
||||
|
||||
case 0x703: // read with increment
|
||||
rv = m_ram[m_offset];
|
||||
m_offset++;
|
||||
// don't increment if the debugger's reading
|
||||
if (!space.debugger_access())
|
||||
{
|
||||
m_offset++;
|
||||
}
|
||||
return rv;
|
||||
|
||||
case 0x704: // read w/o increment
|
||||
rv = m_ram[m_offset];
|
||||
return rv;
|
||||
return rv;
|
||||
|
||||
default:
|
||||
printf("Read $C800 at %x\n", offset + 0xc800);
|
||||
break;
|
||||
}
|
||||
|
||||
return m_regs[offset];
|
||||
@ -214,6 +246,7 @@ void a2bus_pcxporter_device::write_c800(address_space &space, UINT16 offset, UIN
|
||||
{
|
||||
if (offset < 0x400)
|
||||
{
|
||||
m_c800_ram[offset] = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -245,6 +278,11 @@ void a2bus_pcxporter_device::write_c800(address_space &space, UINT16 offset, UIN
|
||||
case 0x704: // write w/o increment
|
||||
m_ram[m_offset] = data;
|
||||
break;
|
||||
|
||||
case 0x72c: // CGA 6845 register select
|
||||
case 0x72d: // CGA 6845 data read/write
|
||||
case 0x72e: // CGA mode select
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%02x to C800 at %x\n", data, offset + 0xc800);
|
||||
|
@ -44,6 +44,7 @@ protected:
|
||||
|
||||
private:
|
||||
UINT8 m_ram[768*1024];
|
||||
UINT8 m_c800_ram[0x400];
|
||||
UINT8 m_regs[0x400];
|
||||
UINT32 m_offset;
|
||||
};
|
||||
|
@ -31,15 +31,6 @@ intv_ecs_device::intv_ecs_device(const machine_config &mconfig, const char *tag,
|
||||
: intv_rom_device(mconfig, INTV_ROM_ECS, "Intellivision ECS Expansion", tag, owner, clock, "intv_ecs", __FILE__),
|
||||
m_snd(*this, "ay8914"),
|
||||
m_subslot(*this, "subslot"),
|
||||
m_keybd(*this, "ROW"),
|
||||
m_synth(*this, "SYNTH"),
|
||||
m_cntrlsel(*this, "CNTRLSEL"),
|
||||
m_options(*this, "OPTIONS"),
|
||||
m_keypad(*this, "KEYPAD"),
|
||||
m_disc(*this, "DISC"),
|
||||
m_discx(*this, "DISCX"),
|
||||
m_discy(*this, "DISCY"),
|
||||
m_psg_porta(0),
|
||||
m_voice_enabled(false),
|
||||
m_ramd0_enabled(false),
|
||||
m_ram88_enabled(false)
|
||||
@ -65,7 +56,6 @@ void intv_ecs_device::device_start()
|
||||
}
|
||||
|
||||
save_item(NAME(m_bank_base));
|
||||
save_item(NAME(m_psg_porta));
|
||||
}
|
||||
|
||||
void intv_ecs_device::device_reset()
|
||||
@ -102,135 +92,17 @@ void intv_ecs_device::late_subslot_setup()
|
||||
// MACHINE_CONFIG_FRAGMENT( sub_slot )
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT8 intv_ecs_device::intv_control_r(int hand)
|
||||
{
|
||||
static const UINT8 keypad_table[] =
|
||||
{
|
||||
0xFF, 0x3F, 0x9F, 0x5F, 0xD7, 0xB7, 0x77, 0xDB,
|
||||
0xBB, 0x7B, 0xDD, 0xBD, 0x7D, 0xDE, 0xBE, 0x7E
|
||||
};
|
||||
|
||||
static const UINT8 disc_table[] =
|
||||
{
|
||||
0xF3, 0xE3, 0xE7, 0xF7, 0xF6, 0xE6, 0xEE, 0xFE,
|
||||
0xFC, 0xEC, 0xED, 0xFD, 0xF9, 0xE9, 0xEB, 0xFB
|
||||
};
|
||||
|
||||
static const UINT8 discyx_table[5][5] =
|
||||
{
|
||||
{ 0xE3, 0xF3, 0xFB, 0xEB, 0xE9 },
|
||||
{ 0xE7, 0xE3, 0xFB, 0xE9, 0xF9 },
|
||||
{ 0xF7, 0xF7, 0xFF, 0xFD, 0xFD },
|
||||
{ 0xF6, 0xE6, 0xFE, 0xEC, 0xED },
|
||||
{ 0xE6, 0xEE, 0xFE, 0xFC, 0xEC }
|
||||
};
|
||||
|
||||
int x, y;
|
||||
UINT8 val = 0xff;
|
||||
|
||||
/* keypad */
|
||||
x = m_keypad[hand]->read();
|
||||
for (y = 0; y < 16; y++)
|
||||
{
|
||||
if (x & (1 << y))
|
||||
{
|
||||
val &= keypad_table[y];
|
||||
}
|
||||
}
|
||||
|
||||
y = (m_options->read() >> ((hand + 2) * 2)) & 3;
|
||||
switch (y)
|
||||
{
|
||||
case 0: /* disc == digital 8-way */
|
||||
case 1: /* disc == digital 16-way */
|
||||
default:
|
||||
|
||||
x = m_disc[hand]->read();
|
||||
if (!!x && (!y || !(x & 0x7777)))
|
||||
{
|
||||
// merge cardinals to form true diagonals
|
||||
y = ((x >> 2) & (x << 2)) | ((x >> (16 - 2)) & (x >> 2));
|
||||
x = y | (x & ~((y << 2) | (y >> 2) | (y << (16 - 2))));
|
||||
}
|
||||
|
||||
// only one disc direction is allowed
|
||||
x &= -x;
|
||||
|
||||
for (y = 0; y < 16; y++)
|
||||
{
|
||||
if (x & (1 << y))
|
||||
{
|
||||
val &= disc_table[y];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* disc == _fake_ analog */
|
||||
|
||||
x = m_discx[hand]->read();
|
||||
y = m_discy[hand]->read();
|
||||
val &= discyx_table[y / 32][x / 32];
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
READ8_MEMBER( intv_ecs_device::ay_porta_r )
|
||||
{
|
||||
if (m_cntrlsel->read() == 0)
|
||||
return intv_control_r(0);
|
||||
else
|
||||
return 0xff; // not sure what to return here, maybe it should be last output?
|
||||
}
|
||||
|
||||
READ8_MEMBER( intv_ecs_device::ay_portb_r )
|
||||
{
|
||||
switch (m_cntrlsel->read())
|
||||
{
|
||||
case 0x00: // hand controller
|
||||
return intv_control_r(1);
|
||||
|
||||
case 0x01: // synthesizer keyboard
|
||||
{
|
||||
UINT8 val = 0xff;
|
||||
// return correct result if more than one bit of 0xFE is set
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (BIT(m_psg_porta, i))
|
||||
val &= m_synth[i]->read();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
case 0x02: // ecs keyboard
|
||||
{
|
||||
UINT8 val = 0xff;
|
||||
// return correct result if more than one bit of 0xFE is set
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (BIT(m_psg_porta, i))
|
||||
val &= m_keybd[i]->read();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
default:
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( intv_ecs_device::ay_porta_w )
|
||||
{
|
||||
m_psg_porta = (~data) & 0xff;
|
||||
}
|
||||
|
||||
static MACHINE_CONFIG_FRAGMENT( sub_slot )
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono_ecs")
|
||||
|
||||
MCFG_SOUND_ADD("ay8914", AY8914, XTAL_3_579545MHz/2)
|
||||
MCFG_AY8910_PORT_A_READ_CB(READ8(intv_ecs_device, ay_porta_r))
|
||||
MCFG_AY8910_PORT_B_READ_CB(READ8(intv_ecs_device, ay_portb_r))
|
||||
MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(intv_ecs_device, ay_porta_w))
|
||||
MCFG_AY8910_PORT_A_READ_CB(DEVREAD8("ctrl_port", intvecs_control_port_device, portA_r))
|
||||
MCFG_AY8910_PORT_B_READ_CB(DEVREAD8("ctrl_port", intvecs_control_port_device, portB_r))
|
||||
MCFG_AY8910_PORT_A_WRITE_CB(DEVWRITE8("ctrl_port", intvecs_control_port_device, portA_w))
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono_ecs", 0.33)
|
||||
|
||||
MCFG_INTVECS_CONTROL_PORT_ADD("ctrl_port", intvecs_control_port_devices, "keybd")
|
||||
MCFG_INTV_CARTRIDGE_ADD("subslot", intv_cart, nullptr)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
@ -254,294 +126,6 @@ const rom_entry *intv_ecs_device::device_rom_region() const
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( intv_ecs_kbd )
|
||||
/*
|
||||
ECS matrix scanned by setting 0xFE bits to output and reading 0xFF
|
||||
ECS Keyboard Layout:
|
||||
FF\FE Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
|
||||
Bit 0 NC RTN 0 ESC P ; . (left)
|
||||
Bit 1 L O 8 9 I K M ,
|
||||
Bit 2 J U 6 7 Y H B N
|
||||
Bit 3 G T 4 5 R F C V
|
||||
Bit 4 D E 2 3 W S Z X
|
||||
Bit 5 A CTL (right) 1 Q (up) (down) (space)
|
||||
Bit 6 SHIFT NC NC NC NC NC NC NC
|
||||
|
||||
Shifted keys that differ from pc:
|
||||
Key : 1 2 5 6 7 (left) (right) (up) (down)
|
||||
Shift + key: = " + - / % ' ^ ?
|
||||
*/
|
||||
|
||||
PORT_START("ROW.0")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RTN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CHAR('%') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
|
||||
PORT_START("ROW.1")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
|
||||
PORT_START("ROW.2")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('-') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
|
||||
PORT_START("ROW.3")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
|
||||
PORT_START("ROW.4")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
|
||||
PORT_START("ROW.5")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTL") PORT_CODE(KEYCODE_RCONTROL) PORT_CODE(KEYCODE_LCONTROL) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CHAR('\'') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('=') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CHAR('^') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CHAR('?') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
|
||||
PORT_START("ROW.6")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_RSHIFT) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x02)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START( intv_ecs_synth )
|
||||
/*
|
||||
ECS Synthesizer Layout:
|
||||
FF\FE Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
|
||||
Bit 0 G2 Gb2 F2 E2 Eb2 D2 Db2 C2
|
||||
Bit 1 Eb3 D3 Db3 C3 B2 Bb2 A2 Ab2
|
||||
Bit 2 B3 Bb3 A3 Ab3 G3 Gb3 F3 E3
|
||||
Bit 3 G4 Gb4 F4 E4 Eb4 D4 Db4 C4
|
||||
Bit 4 Eb5 D5 Db5 C5 B4 Bb4 A4 Ab4
|
||||
Bit 5 B5 Bb5 A5 Ab5 G5 Gb5 F5 E5
|
||||
Bit 6 C6 NC NC NC NC NC NC NC
|
||||
*/
|
||||
PORT_START("SYNTH.0")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
|
||||
PORT_START("SYNTH.1")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
|
||||
PORT_START("SYNTH.2")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
|
||||
PORT_START("SYNTH.3")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
|
||||
PORT_START("SYNTH.4")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
|
||||
PORT_START("SYNTH.5")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
|
||||
PORT_START("SYNTH.6")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C6") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x01)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START( intv_ecs_pads )
|
||||
// First ECS Hand Controller
|
||||
PORT_START("KEYPAD.0")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 1") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 6") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 7") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 8") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 9") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 Clear") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 0") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P3 Enter") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P3 Upper") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P3 Lower-Left") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P3 Lower-Right") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
|
||||
PORT_START("DISC.0")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("P3 Up") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,NOTEQUALS,0x20)
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Up-Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Right-Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("P3 Right") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,NOTEQUALS,0x20)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Right-Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Down-Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("P3 Down") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,NOTEQUALS,0x20)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Down-Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Left-Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("P3 Left") PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,NOTEQUALS,0x20)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Left-Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Up-Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x10)
|
||||
|
||||
PORT_START("DISCX.0")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("P3 X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x20)
|
||||
|
||||
PORT_START("DISCY.0")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("P3 Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_PLAYER(3) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0x30,EQUALS,0x20)
|
||||
|
||||
// Second ECS Hand Controller
|
||||
PORT_START("KEYPAD.1")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 1") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 2") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 3") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 4") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 5") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 6") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 7") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 8") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 9") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 Clear") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 0") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("P4 Enter") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P4 Upper") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P4 Lower-Left") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P4 Lower-Right") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
|
||||
PORT_START("DISC.1")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("P4 Up") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,NOTEQUALS,0x80)
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Up-Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Right-Up-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("P4 Right") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,NOTEQUALS,0x80)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Right-Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Down-Down-Right") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("P4 Down") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,NOTEQUALS,0x80)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Down-Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Left-Down-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("P4 Left") PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,NOTEQUALS,0x80)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Left-Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Up-Up-Left") PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x40)
|
||||
|
||||
PORT_START("DISCX.1")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("P4 X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_D) PORT_CODE_INC(KEYCODE_G) PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x80)
|
||||
|
||||
PORT_START("DISCY.1")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("P4 Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_R) PORT_CODE_INC(KEYCODE_F) PORT_PLAYER(4) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00) PORT_CONDITION("OPTIONS",0xC0,EQUALS,0x80)
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START( intv_ecs )
|
||||
PORT_INCLUDE( intv_ecs_pads )
|
||||
PORT_INCLUDE( intv_ecs_synth )
|
||||
PORT_INCLUDE( intv_ecs_kbd )
|
||||
|
||||
PORT_START("OPTIONS")
|
||||
PORT_CONFNAME( 0x30, 0x00, "ECS P3 Disc" ) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_CONFSETTING( 0x00, "Digital 8-way" )
|
||||
PORT_CONFSETTING( 0x10, "Digital 16-way" )
|
||||
PORT_CONFSETTING( 0x20, "Analog" )
|
||||
PORT_CONFNAME( 0xC0, 0x00, "ECS P4 Disc" ) PORT_CONDITION("CNTRLSEL",0x0f,EQUALS,0x00)
|
||||
PORT_CONFSETTING( 0x00, "Digital 8-way" )
|
||||
PORT_CONFSETTING( 0x40, "Digital 16-way" )
|
||||
PORT_CONFSETTING( 0x80, "Analog" )
|
||||
|
||||
PORT_START("CNTRLSEL")
|
||||
PORT_CONFNAME( 0x0F, 0x02, "ECS Controller")
|
||||
PORT_CONFSETTING( 0x00, "Gamepads" )
|
||||
PORT_CONFSETTING( 0x01, "Piano" )
|
||||
PORT_CONFSETTING( 0x02, "Keyboard" )
|
||||
INPUT_PORTS_END
|
||||
|
||||
ioport_constructor intv_ecs_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( intv_ecs );
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
Paged ROM handling
|
||||
-------------------------------------------------*/
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "slot.h"
|
||||
#include "rom.h"
|
||||
#include "sound/ay8910.h"
|
||||
|
||||
#include "bus/intv_ctrl/ecs_ctrl.h"
|
||||
|
||||
|
||||
// ======================> intv_ecs_device
|
||||
@ -21,7 +21,6 @@ public:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual machine_config_constructor device_mconfig_additions() const override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual const rom_entry *device_rom_region() const override;
|
||||
|
||||
// reading and writing
|
||||
@ -38,9 +37,6 @@ public:
|
||||
// AY8914
|
||||
virtual DECLARE_READ16_MEMBER(read_ay) override;
|
||||
virtual DECLARE_WRITE16_MEMBER(write_ay) override;
|
||||
DECLARE_READ8_MEMBER(ay_porta_r);
|
||||
DECLARE_READ8_MEMBER(ay_portb_r);
|
||||
DECLARE_WRITE8_MEMBER(ay_porta_w);
|
||||
|
||||
// passthru accesses
|
||||
virtual DECLARE_READ16_MEMBER(read_rom04) override { return m_subslot->read_rom04(space, offset, mem_mask); }
|
||||
@ -117,30 +113,16 @@ public:
|
||||
|
||||
virtual void late_subslot_setup() override;
|
||||
|
||||
UINT8 intv_control_r(int hand);
|
||||
|
||||
private:
|
||||
|
||||
required_device<ay8914_device> m_snd;
|
||||
required_device<intv_cart_slot_device> m_subslot;
|
||||
required_ioport_array<7> m_keybd;
|
||||
required_ioport_array<7> m_synth;
|
||||
required_ioport m_cntrlsel;
|
||||
required_ioport m_options;
|
||||
required_ioport_array<2> m_keypad;
|
||||
required_ioport_array<2> m_disc;
|
||||
required_ioport_array<2> m_discx;
|
||||
required_ioport_array<2> m_discy;
|
||||
|
||||
int m_bank_base[0x10];
|
||||
UINT8 m_psg_porta;
|
||||
bool m_voice_enabled, m_ramd0_enabled, m_ram88_enabled;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type INTV_ROM_ECS;
|
||||
|
||||
|
95
src/devices/bus/intv_ctrl/ctrl.cpp
Normal file
95
src/devices/bus/intv_ctrl/ctrl.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Fabio Priuli
|
||||
/**********************************************************************
|
||||
|
||||
Mattel Intellivision controller port emulation
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "ctrl.h"
|
||||
// slot devices
|
||||
#include "handctrl.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
const device_type INTV_CONTROL_PORT = &device_creator<intv_control_port_device>;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CARD INTERFACE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_intv_control_port_interface - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_intv_control_port_interface::device_intv_control_port_interface(const machine_config &mconfig, device_t &device)
|
||||
: device_slot_card_interface(mconfig,device)
|
||||
{
|
||||
m_port = dynamic_cast<intv_control_port_device *>(device.owner());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ~device_intv_control_port_interface - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_intv_control_port_interface::~device_intv_control_port_interface()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// intv_control_port_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
intv_control_port_device::intv_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, INTV_CONTROL_PORT, "Mattel Intellivision control port", tag, owner, clock, "intv_control_port", __FILE__),
|
||||
device_slot_interface(mconfig, *this), m_device(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// intv_control_port_device - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
intv_control_port_device::~intv_control_port_device()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void intv_control_port_device::device_start()
|
||||
{
|
||||
m_device = dynamic_cast<device_intv_control_port_interface *>(get_card_device());
|
||||
}
|
||||
|
||||
|
||||
UINT8 intv_control_port_device::read_ctrl()
|
||||
{
|
||||
UINT8 data = 0;
|
||||
if (m_device)
|
||||
data |= m_device->read_ctrl();
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// SLOT_INTERFACE( intv_control_port_devices )
|
||||
//-------------------------------------------------
|
||||
|
||||
SLOT_INTERFACE_START( intv_control_port_devices )
|
||||
SLOT_INTERFACE("handctrl", INTV_HANDCTRL)
|
||||
SLOT_INTERFACE_END
|
||||
|
76
src/devices/bus/intv_ctrl/ctrl.h
Normal file
76
src/devices/bus/intv_ctrl/ctrl.h
Normal file
@ -0,0 +1,76 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Fabio Priuli
|
||||
/**********************************************************************
|
||||
|
||||
Mattel Intellivision controller port emulation
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __INTV_CONTROL_PORT__
|
||||
#define __INTV_CONTROL_PORT__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
class intv_control_port_device;
|
||||
|
||||
// ======================> device_intv_control_port_interface
|
||||
|
||||
class device_intv_control_port_interface : public device_slot_card_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
device_intv_control_port_interface(const machine_config &mconfig, device_t &device);
|
||||
virtual ~device_intv_control_port_interface();
|
||||
|
||||
virtual UINT8 read_ctrl() { return 0; };
|
||||
|
||||
protected:
|
||||
intv_control_port_device *m_port;
|
||||
};
|
||||
|
||||
// ======================> intv_control_port_device
|
||||
|
||||
class intv_control_port_device : public device_t,
|
||||
public device_slot_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
intv_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
virtual ~intv_control_port_device();
|
||||
|
||||
DECLARE_READ8_MEMBER( ctrl_r ) { return read_ctrl(); }
|
||||
UINT8 read_ctrl();
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
||||
device_intv_control_port_interface *m_device;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type INTV_CONTROL_PORT;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_INTV_CONTROL_PORT_ADD(_tag, _slot_intf, _def_slot) \
|
||||
MCFG_DEVICE_ADD(_tag, INTV_CONTROL_PORT, 0) \
|
||||
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
|
||||
|
||||
|
||||
|
||||
SLOT_INTERFACE_EXTERN( intv_control_port_devices );
|
||||
|
||||
|
||||
#endif
|
448
src/devices/bus/intv_ctrl/ecs_ctrl.cpp
Normal file
448
src/devices/bus/intv_ctrl/ecs_ctrl.cpp
Normal file
@ -0,0 +1,448 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Fabio Priuli
|
||||
/**********************************************************************
|
||||
|
||||
Mattel Intellivision ECS hack for controller port emulation
|
||||
|
||||
FIXME: This device is the best I could come up with to emulate
|
||||
the fact that Keyboard and Synth controllers for the ECS should be
|
||||
plugged in both ECS control ports, while the 3rd and 4th additional
|
||||
hand controller should only be plugged in a single port.
|
||||
Since the core currently does not allow a single device mounted
|
||||
in more than a slot, this has been worked around with this device
|
||||
which supports as options
|
||||
- ECS keyboard
|
||||
- ECS synth
|
||||
- a pair of Intellivision controller
|
||||
|
||||
All the code for both the controller port and the slot devices has
|
||||
been included in this single source file to make easier to clean
|
||||
them up once we extend the core to support this kind of setup
|
||||
(necessary for Atari 2600 Compumate as well)
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "ecs_ctrl.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
const device_type INTVECS_CONTROL_PORT = &device_creator<intvecs_control_port_device>;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CARD INTERFACE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_intvecs_control_port_interface - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_intvecs_control_port_interface::device_intvecs_control_port_interface(const machine_config &mconfig, device_t &device)
|
||||
: device_slot_card_interface(mconfig,device)
|
||||
{
|
||||
m_port = dynamic_cast<intvecs_control_port_device *>(device.owner());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ~device_intvecs_control_port_interface - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_intvecs_control_port_interface::~device_intvecs_control_port_interface()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// intvecs_control_port_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
intvecs_control_port_device::intvecs_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, INTVECS_CONTROL_PORT, "Mattel Intellivision ECS control port (HACK)", tag, owner, clock, "intvecs_control_port", __FILE__),
|
||||
device_slot_interface(mconfig, *this), m_device(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// intvecs_control_port_device - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
intvecs_control_port_device::~intvecs_control_port_device()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void intvecs_control_port_device::device_start()
|
||||
{
|
||||
m_device = dynamic_cast<device_intvecs_control_port_interface *>(get_card_device());
|
||||
}
|
||||
|
||||
|
||||
UINT8 intvecs_control_port_device::read_portA()
|
||||
{
|
||||
UINT8 data = 0;
|
||||
if (m_device)
|
||||
data |= m_device->read_portA();
|
||||
return data;
|
||||
}
|
||||
|
||||
UINT8 intvecs_control_port_device::read_portB()
|
||||
{
|
||||
UINT8 data = 0;
|
||||
if (m_device)
|
||||
data |= m_device->read_portB();
|
||||
return data;
|
||||
}
|
||||
|
||||
void intvecs_control_port_device::write_portA(UINT8 data)
|
||||
{
|
||||
if (m_device)
|
||||
m_device->write_portA(data);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// SLOT_INTERFACE( intvecs_control_port_devices )
|
||||
//-------------------------------------------------
|
||||
|
||||
SLOT_INTERFACE_START( intvecs_control_port_devices )
|
||||
SLOT_INTERFACE("ctrls", ECS_CTRLS)
|
||||
SLOT_INTERFACE("keybd", ECS_KEYBD)
|
||||
SLOT_INTERFACE("synth", ECS_SYNTH)
|
||||
SLOT_INTERFACE_END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// ACTUAL SLOT DEVICES - included here until core issues are solved...
|
||||
//**************************************************************************
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ECS_CTRLS - A pair of hand controllers
|
||||
//-------------------------------------------------
|
||||
|
||||
const device_type ECS_CTRLS = &device_creator<intvecs_ctrls_device>;
|
||||
|
||||
static SLOT_INTERFACE_START( intvecs_controller )
|
||||
SLOT_INTERFACE("handctrl", INTV_HANDCTRL)
|
||||
SLOT_INTERFACE_END
|
||||
|
||||
static MACHINE_CONFIG_FRAGMENT( intvecs_ctrls )
|
||||
MCFG_INTV_CONTROL_PORT_ADD("port1", intvecs_controller, "handctrl")
|
||||
MCFG_INTV_CONTROL_PORT_ADD("port2", intvecs_controller, "handctrl")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
machine_config_constructor intvecs_ctrls_device::device_mconfig_additions() const
|
||||
{
|
||||
return MACHINE_CONFIG_NAME( intvecs_ctrls );
|
||||
}
|
||||
|
||||
intvecs_ctrls_device::intvecs_ctrls_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, ECS_CTRLS, "Mattel Intellivision ECS Hand Controller x2 (HACK)", tag, owner, clock, "intvecs_ctrls", __FILE__),
|
||||
device_intvecs_control_port_interface(mconfig, *this),
|
||||
m_hand1(*this, "port1"),
|
||||
m_hand2(*this, "port2")
|
||||
{
|
||||
}
|
||||
|
||||
void intvecs_ctrls_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
void intvecs_ctrls_device::device_reset()
|
||||
{
|
||||
}
|
||||
|
||||
UINT8 intvecs_ctrls_device::read_portA()
|
||||
{
|
||||
return m_hand1->read_ctrl();
|
||||
}
|
||||
|
||||
UINT8 intvecs_ctrls_device::read_portB()
|
||||
{
|
||||
return m_hand2->read_ctrl();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// ECS_KEYBD - Keyboard
|
||||
//-------------------------------------------------
|
||||
|
||||
const device_type ECS_KEYBD = &device_creator<intvecs_keybd_device>;
|
||||
|
||||
static INPUT_PORTS_START( intvecs_keybd )
|
||||
/*
|
||||
ECS matrix scanned by setting 0xFE bits to output and reading 0xFF
|
||||
ECS Keyboard Layout:
|
||||
FF\FE Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
|
||||
Bit 0 NC RTN 0 ESC P ; . (left)
|
||||
Bit 1 L O 8 9 I K M ,
|
||||
Bit 2 J U 6 7 Y H B N
|
||||
Bit 3 G T 4 5 R F C V
|
||||
Bit 4 D E 2 3 W S Z X
|
||||
Bit 5 A CTL (right) 1 Q (up) (down) (space)
|
||||
Bit 6 SHIFT NC NC NC NC NC NC NC
|
||||
|
||||
Shifted keys that differ from pc:
|
||||
Key : 1 2 5 6 7 (left) (right) (up) (down)
|
||||
Shift + key: = " + - / % ' ^ ?
|
||||
*/
|
||||
|
||||
PORT_START("ROW.0")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RTN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P')
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CHAR('%')
|
||||
|
||||
PORT_START("ROW.1")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L')
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('O')
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I')
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('K')
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('M')
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
|
||||
|
||||
PORT_START("ROW.2")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('J')
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('U')
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('-')
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/')
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('H')
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('B')
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('N')
|
||||
|
||||
PORT_START("ROW.3")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('G')
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('T')
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('R')
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('F')
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('C')
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('V')
|
||||
|
||||
PORT_START("ROW.4")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D')
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('E')
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('W')
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S')
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('X')
|
||||
|
||||
PORT_START("ROW.5")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A')
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTL") PORT_CODE(KEYCODE_RCONTROL) PORT_CODE(KEYCODE_LCONTROL)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CHAR('\'')
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('=')
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CHAR('^')
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CHAR('?')
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
|
||||
|
||||
PORT_START("ROW.6")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_RSHIFT) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
INPUT_PORTS_END
|
||||
|
||||
ioport_constructor intvecs_keybd_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( intvecs_keybd );
|
||||
}
|
||||
|
||||
intvecs_keybd_device::intvecs_keybd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, ECS_KEYBD, "Mattel Intellivision ECS Keyboard", tag, owner, clock, "intvecs_keybd", __FILE__),
|
||||
device_intvecs_control_port_interface(mconfig, *this),
|
||||
m_keybd(*this, "ROW")
|
||||
{
|
||||
}
|
||||
|
||||
void intvecs_keybd_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_psg_portA));
|
||||
}
|
||||
|
||||
void intvecs_keybd_device::device_reset()
|
||||
{
|
||||
m_psg_portA = 0;
|
||||
}
|
||||
|
||||
UINT8 intvecs_keybd_device::read_portB()
|
||||
{
|
||||
UINT8 val = 0xff;
|
||||
// return correct result if more than one bit of 0xFE is set
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (BIT(m_psg_portA, i))
|
||||
val &= m_keybd[i]->read();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void intvecs_keybd_device::write_portA(UINT8 data)
|
||||
{
|
||||
m_psg_portA = (~data) & 0xff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ECS_SYNTH - Synth
|
||||
//-------------------------------------------------
|
||||
|
||||
const device_type ECS_SYNTH = &device_creator<intvecs_synth_device>;
|
||||
|
||||
|
||||
static INPUT_PORTS_START( intvecs_synth )
|
||||
/*
|
||||
ECS Synthesizer Layout:
|
||||
FF\FE Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
|
||||
Bit 0 G2 Gb2 F2 E2 Eb2 D2 Db2 C2
|
||||
Bit 1 Eb3 D3 Db3 C3 B2 Bb2 A2 Ab2
|
||||
Bit 2 B3 Bb3 A3 Ab3 G3 Gb3 F3 E3
|
||||
Bit 3 G4 Gb4 F4 E4 Eb4 D4 Db4 C4
|
||||
Bit 4 Eb5 D5 Db5 C5 B4 Bb4 A4 Ab4
|
||||
Bit 5 B5 Bb5 A5 Ab5 G5 Gb5 F5 E5
|
||||
Bit 6 C6 NC NC NC NC NC NC NC
|
||||
*/
|
||||
PORT_START("SYNTH.0")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G2")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb2")
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2")
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E2")
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb2")
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D2")
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db2")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C2")
|
||||
|
||||
PORT_START("SYNTH.1")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb3")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D3")
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db3")
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C3")
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B2")
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb2")
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A2")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab2")
|
||||
|
||||
PORT_START("SYNTH.2")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B3")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb3")
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A3")
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab3")
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G3")
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb3")
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E3")
|
||||
|
||||
PORT_START("SYNTH.3")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G4")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb4")
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4")
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E4")
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb4")
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D4")
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db4")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C4")
|
||||
|
||||
PORT_START("SYNTH.4")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Eb5")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D5")
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Db5")
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C5")
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B4")
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb4")
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A4")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab4")
|
||||
|
||||
PORT_START("SYNTH.5")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B5")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Bb5")
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A5")
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ab5")
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G5")
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gb5")
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E5")
|
||||
|
||||
PORT_START("SYNTH.6")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C6")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
ioport_constructor intvecs_synth_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( intvecs_synth );
|
||||
}
|
||||
|
||||
|
||||
intvecs_synth_device::intvecs_synth_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, ECS_SYNTH, "Mattel Intellivision ECS Synthetizer", tag, owner, clock, "intvecs_synth", __FILE__),
|
||||
device_intvecs_control_port_interface(mconfig, *this),
|
||||
m_synth(*this, "SYNTH")
|
||||
{
|
||||
}
|
||||
|
||||
void intvecs_synth_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_psg_portA));
|
||||
}
|
||||
|
||||
void intvecs_synth_device::device_reset()
|
||||
{
|
||||
m_psg_portA = 0;
|
||||
}
|
||||
|
||||
UINT8 intvecs_synth_device::read_portB()
|
||||
{
|
||||
UINT8 val = 0xff;
|
||||
// return correct result if more than one bit of 0xFE is set
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (BIT(m_psg_portA, i))
|
||||
val &= m_synth[i]->read();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void intvecs_synth_device::write_portA(UINT8 data)
|
||||
{
|
||||
m_psg_portA = (~data) & 0xff;
|
||||
}
|
||||
|
171
src/devices/bus/intv_ctrl/ecs_ctrl.h
Normal file
171
src/devices/bus/intv_ctrl/ecs_ctrl.h
Normal file
@ -0,0 +1,171 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Fabio Priuli
|
||||
/**********************************************************************
|
||||
|
||||
Mattel Intellivision ECS hack for controller port emulation
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __INTVECS_CONTROL_PORT__
|
||||
#define __INTVECS_CONTROL_PORT__
|
||||
|
||||
#include "emu.h"
|
||||
#include "bus/intv_ctrl/ctrl.h"
|
||||
#include "bus/intv_ctrl/handctrl.h"
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
class intvecs_control_port_device;
|
||||
|
||||
// ======================> device_intvecs_control_port_interface
|
||||
|
||||
class device_intvecs_control_port_interface : public device_slot_card_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
device_intvecs_control_port_interface(const machine_config &mconfig, device_t &device);
|
||||
virtual ~device_intvecs_control_port_interface();
|
||||
|
||||
virtual UINT8 read_portA() { return 0xff; };
|
||||
virtual UINT8 read_portB() { return 0xff; };
|
||||
virtual void write_portA(UINT8 data) { };
|
||||
|
||||
protected:
|
||||
intvecs_control_port_device *m_port;
|
||||
};
|
||||
|
||||
// ======================> intvecs_control_port_device
|
||||
|
||||
class intvecs_control_port_device : public device_t,
|
||||
public device_slot_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
intvecs_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
virtual ~intvecs_control_port_device();
|
||||
|
||||
DECLARE_READ8_MEMBER( portA_r ) { return read_portA(); }
|
||||
DECLARE_READ8_MEMBER( portB_r ) { return read_portB(); }
|
||||
DECLARE_WRITE8_MEMBER( portA_w ) { return write_portA(data); }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
UINT8 read_portA();
|
||||
UINT8 read_portB();
|
||||
void write_portA(UINT8 data);
|
||||
|
||||
device_intvecs_control_port_interface *m_device;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type INTVECS_CONTROL_PORT;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_INTVECS_CONTROL_PORT_ADD(_tag, _slot_intf, _def_slot) \
|
||||
MCFG_DEVICE_ADD(_tag, INTVECS_CONTROL_PORT, 0) \
|
||||
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
|
||||
|
||||
|
||||
|
||||
SLOT_INTERFACE_EXTERN( intvecs_control_port_devices );
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// ACTUAL SLOT DEVICES - included here until core issues are solved...
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> intvecs_ctrls_device
|
||||
|
||||
class intvecs_ctrls_device : public device_t,
|
||||
public device_intvecs_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
intvecs_ctrls_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual machine_config_constructor device_mconfig_additions() const override;
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual UINT8 read_portA() override;
|
||||
virtual UINT8 read_portB() override;
|
||||
|
||||
private:
|
||||
required_device<intv_control_port_device> m_hand1;
|
||||
required_device<intv_control_port_device> m_hand2;
|
||||
};
|
||||
|
||||
// ======================> intvecs_keybd_device
|
||||
|
||||
class intvecs_keybd_device : public device_t,
|
||||
public device_intvecs_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
intvecs_keybd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual UINT8 read_portB() override;
|
||||
virtual void write_portA(UINT8 data) override;
|
||||
|
||||
private:
|
||||
UINT8 m_psg_portA;
|
||||
required_ioport_array<7> m_keybd;
|
||||
};
|
||||
|
||||
// ======================> intvecs_synth_device
|
||||
|
||||
class intvecs_synth_device : public device_t,
|
||||
public device_intvecs_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
intvecs_synth_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual UINT8 read_portB() override;
|
||||
virtual void write_portA(UINT8 data) override;
|
||||
|
||||
private:
|
||||
UINT8 m_psg_portA;
|
||||
required_ioport_array<7> m_synth;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type ECS_CTRLS;
|
||||
extern const device_type ECS_KEYBD;
|
||||
extern const device_type ECS_SYNTH;
|
||||
|
||||
|
||||
|
||||
#endif
|
179
src/devices/bus/intv_ctrl/handctrl.cpp
Normal file
179
src/devices/bus/intv_ctrl/handctrl.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Fabio Priuli
|
||||
/**********************************************************************
|
||||
|
||||
Mattel Intellivision Hand Controllers
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "handctrl.h"
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
const device_type INTV_HANDCTRL = &device_creator<intv_handctrl_device>;
|
||||
|
||||
|
||||
static INPUT_PORTS_START( intv_handctrl )
|
||||
PORT_START("KEYPAD")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("1") PORT_CODE(KEYCODE_1_PAD)
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("2") PORT_CODE(KEYCODE_2_PAD)
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("3") PORT_CODE(KEYCODE_3_PAD)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("4") PORT_CODE(KEYCODE_4_PAD)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("5") PORT_CODE(KEYCODE_5_PAD)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("6") PORT_CODE(KEYCODE_6_PAD)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("7") PORT_CODE(KEYCODE_7_PAD)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("8") PORT_CODE(KEYCODE_8_PAD)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("9") PORT_CODE(KEYCODE_9_PAD)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Clear") PORT_CODE(KEYCODE_DEL_PAD)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("0") PORT_CODE(KEYCODE_0_PAD)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER_PAD)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Upper") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Lower-Left") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Lower-Right") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
|
||||
PORT_START("DISC_DG")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("Up") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Right") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("Down") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Left") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Up-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
|
||||
PORT_START("DISC_AN_X")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_LEFT) PORT_CODE_INC(KEYCODE_RIGHT) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
|
||||
|
||||
PORT_START("DISC_AN_Y")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_UP) PORT_CODE_INC(KEYCODE_DOWN) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
|
||||
|
||||
|
||||
PORT_START("OPTIONS")
|
||||
PORT_CONFNAME( 0x01, 0x01, "Controller Disc Emulation" )
|
||||
PORT_CONFSETTING( 0x00, "Digital" )
|
||||
PORT_CONFSETTING( 0x01, "Analog" )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// input_ports - device-specific input ports
|
||||
//-------------------------------------------------
|
||||
|
||||
ioport_constructor intv_handctrl_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( intv_handctrl );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// intv_handctrl_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
intv_handctrl_device::intv_handctrl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, INTV_HANDCTRL, "Mattel Intellivision Hand Controller", tag, owner, clock, "intv_hand", __FILE__),
|
||||
device_intv_control_port_interface(mconfig, *this),
|
||||
m_cfg(*this, "OPTIONS"),
|
||||
m_keypad(*this, "KEYPAD"),
|
||||
m_disc_dig(*this, "DISC_DG"),
|
||||
m_disc_anx(*this, "DISC_AN_X"),
|
||||
m_disc_any(*this, "DISC_AN_Y")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void intv_handctrl_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void intv_handctrl_device::device_reset()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read_ctrl
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT8 intv_handctrl_device::read_ctrl()
|
||||
{
|
||||
static const UINT8 keypad_table[] =
|
||||
{
|
||||
0xff, 0x3f, 0x9f, 0x5f, 0xd7, 0xb7, 0x77, 0xdb,
|
||||
0xbb, 0x7b, 0xdd, 0xbd, 0x7d, 0xde, 0xbe, 0x7e
|
||||
};
|
||||
|
||||
static const UINT8 disc_table[] =
|
||||
{
|
||||
0xf3, 0xe3, 0xe7, 0xf7, 0xf6, 0xe6, 0xee, 0xfe,
|
||||
0xfc, 0xec, 0xed, 0xfd, 0xf9, 0xe9, 0xeb, 0xfb
|
||||
};
|
||||
|
||||
static const UINT8 discyx_table[5][5] =
|
||||
{
|
||||
{ 0xe3, 0xf3, 0xfb, 0xeb, 0xe9 },
|
||||
{ 0xe7, 0xe3, 0xfb, 0xe9, 0xf9 },
|
||||
{ 0xf7, 0xf7, 0xff, 0xfd, 0xfd },
|
||||
{ 0xf6, 0xe6, 0xfe, 0xec, 0xed },
|
||||
{ 0xe6, 0xee, 0xfe, 0xfc, 0xec }
|
||||
};
|
||||
|
||||
int x, y;
|
||||
UINT8 res = 0xff;
|
||||
|
||||
/* keypad */
|
||||
x = m_keypad->read();
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (BIT(x, i))
|
||||
res &= keypad_table[i];
|
||||
}
|
||||
|
||||
switch (m_cfg->read() & 1)
|
||||
{
|
||||
/* disc == digital */
|
||||
case 0:
|
||||
default:
|
||||
x = m_disc_dig->read();
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (BIT(x, i))
|
||||
res &= disc_table[i];
|
||||
}
|
||||
break;
|
||||
|
||||
/* disc == _fake_ analog */
|
||||
case 1:
|
||||
x = m_disc_anx->read();
|
||||
y = m_disc_any->read();
|
||||
res &= discyx_table[y / 32][x / 32];
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
55
src/devices/bus/intv_ctrl/handctrl.h
Normal file
55
src/devices/bus/intv_ctrl/handctrl.h
Normal file
@ -0,0 +1,55 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Fabio Priuli
|
||||
/**********************************************************************
|
||||
|
||||
Mattel Intellivision Hand Controller
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __INTV_HANDCTRL__
|
||||
#define __INTV_HANDCTRL__
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "ctrl.h"
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> intv_handctrl_device
|
||||
|
||||
class intv_handctrl_device : public device_t,
|
||||
public device_intv_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
intv_handctrl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_intv_control_port_interface overrides
|
||||
virtual UINT8 read_ctrl() override;
|
||||
|
||||
private:
|
||||
required_ioport m_cfg;
|
||||
required_ioport m_keypad;
|
||||
required_ioport m_disc_dig;
|
||||
required_ioport m_disc_anx;
|
||||
required_ioport m_disc_any;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type INTV_HANDCTRL;
|
||||
|
||||
|
||||
#endif
|
@ -36,7 +36,7 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
// device_snes_control_port_interface overrides
|
||||
virtual UINT8 read_pin4() override;
|
||||
virtual void write_strobe(UINT8 data) override;
|
||||
virtual void port_poll() override;
|
||||
|
@ -36,7 +36,7 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
// device_snes_control_port_interface overrides
|
||||
virtual UINT8 read_pin4() override;
|
||||
virtual void write_strobe(UINT8 data) override;
|
||||
virtual void port_poll() override;
|
||||
|
@ -37,7 +37,7 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
// device_snes_control_port_interface overrides
|
||||
virtual UINT8 read_pin4() override;
|
||||
virtual UINT8 read_pin5() override;
|
||||
virtual void write_strobe(UINT8 data) override;
|
||||
|
@ -36,7 +36,7 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
// device_snes_control_port_interface overrides
|
||||
virtual UINT8 read_pin4() override;
|
||||
virtual void write_strobe(UINT8 data) override;
|
||||
virtual void port_poll() override;
|
||||
|
@ -36,7 +36,7 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
// device_snes_control_port_interface overrides
|
||||
virtual UINT8 read_pin4() override;
|
||||
virtual void write_strobe(UINT8 data) override;
|
||||
virtual void port_poll() override;
|
||||
|
@ -36,7 +36,7 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
// device_snes_control_port_interface overrides
|
||||
virtual UINT8 read_pin4() override;
|
||||
virtual void write_strobe(UINT8 data) override;
|
||||
virtual void port_poll() override;
|
||||
|
@ -300,9 +300,8 @@ void netlist_mame_device_t::device_start()
|
||||
|
||||
//printf("clock is %d\n", clock());
|
||||
|
||||
m_netlist = global_alloc(netlist_mame_t(*this));
|
||||
m_netlist = global_alloc(netlist_mame_t(*this, "netlist"));
|
||||
m_setup = global_alloc(netlist::setup_t(m_netlist));
|
||||
netlist().init_object(*m_netlist, "netlist");
|
||||
m_setup->init();
|
||||
|
||||
// register additional devices
|
||||
@ -325,9 +324,9 @@ void netlist_mame_device_t::device_start()
|
||||
m_setup->start_devices();
|
||||
m_setup->resolve_inputs();
|
||||
|
||||
netlist().save(NAME(m_rem));
|
||||
netlist().save(NAME(m_div));
|
||||
netlist().save(NAME(m_old));
|
||||
netlist().save_item(m_rem, this, "m_rem");
|
||||
netlist().save_item(m_div, this, "m_div");
|
||||
netlist().save_item(m_old, this, "m_old");
|
||||
|
||||
save_state();
|
||||
|
||||
@ -348,7 +347,7 @@ void netlist_mame_device_t::device_reset()
|
||||
LOG_DEV_CALLS(("device_reset\n"));
|
||||
m_old = netlist::netlist_time::zero;
|
||||
m_rem = netlist::netlist_time::zero;
|
||||
netlist().do_reset();
|
||||
netlist().reset();
|
||||
}
|
||||
|
||||
void netlist_mame_device_t::device_stop()
|
||||
|
@ -85,8 +85,8 @@ class netlist_mame_t : public netlist::netlist_t
|
||||
{
|
||||
public:
|
||||
|
||||
netlist_mame_t(netlist_mame_device_t &parent)
|
||||
: netlist::netlist_t(),
|
||||
netlist_mame_t(netlist_mame_device_t &parent, const pstring &aname)
|
||||
: netlist::netlist_t(aname),
|
||||
m_parent(parent)
|
||||
{}
|
||||
virtual ~netlist_mame_t() { };
|
||||
|
@ -106,9 +106,6 @@ typedef device_t * (*machine_config_constructor)(machine_config &config, device_
|
||||
#include "sound.h"
|
||||
#include "speaker.h"
|
||||
|
||||
// user interface
|
||||
#include "ui/ui.h"
|
||||
|
||||
// generic helpers
|
||||
#include "devcb.h"
|
||||
#include "dispatch.h"
|
||||
@ -118,6 +115,5 @@ typedef device_t * (*machine_config_constructor)(machine_config &config, device_
|
||||
|
||||
// member templates that don't like incomplete types
|
||||
#include "device.ipp"
|
||||
#include "machine.ipp"
|
||||
|
||||
#endif /* __EMU_H__ */
|
||||
|
@ -1202,6 +1202,24 @@ void running_machine::nvram_save()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// OUTPUT
|
||||
//**************************************************************************
|
||||
|
||||
void running_machine::popup_clear() const
|
||||
{
|
||||
ui().popup_time(0, " ");
|
||||
}
|
||||
|
||||
void running_machine::popup_message(util::format_argument_pack<std::ostream> const &args) const
|
||||
{
|
||||
std::string const temp(string_format(args));
|
||||
ui().popup_time(temp.length() / 40 + 2, "%s", temp);
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CALLBACK ITEMS
|
||||
//**************************************************************************
|
||||
|
@ -17,6 +17,7 @@
|
||||
#ifndef __MACHINE_H__
|
||||
#define __MACHINE_H__
|
||||
|
||||
#include "strformat.h"
|
||||
#include "vecstream.h"
|
||||
|
||||
#include <time.h>
|
||||
@ -274,6 +275,8 @@ private:
|
||||
std::string nvram_filename(device_t &device) const;
|
||||
void nvram_load();
|
||||
void nvram_save();
|
||||
void popup_clear() const;
|
||||
void popup_message(util::format_argument_pack<std::ostream> const &args) const;
|
||||
|
||||
// internal callbacks
|
||||
static void logfile_callback(const running_machine &machine, const char *buffer);
|
||||
@ -382,4 +385,54 @@ private:
|
||||
mutable util::ovectorstream m_string_buffer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// MEMBER TEMPLATES
|
||||
//**************************************************************************
|
||||
|
||||
/*-------------------------------------------------
|
||||
popmessage - pop up a user-visible message
|
||||
-------------------------------------------------*/
|
||||
|
||||
template <typename Format, typename... Params>
|
||||
inline void running_machine::popmessage(Format &&fmt, Params &&... args) const
|
||||
{
|
||||
// if the format is NULL, it is a signal to clear the popmessage
|
||||
// otherwise, generate the buffer and call the UI to display the message
|
||||
if (is_null<Format>::value(fmt))
|
||||
popup_clear();
|
||||
else
|
||||
popup_message(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
logerror - log to the debugger and any other
|
||||
OSD-defined output streams
|
||||
-------------------------------------------------*/
|
||||
|
||||
template <typename Format, typename... Params>
|
||||
inline void running_machine::logerror(Format &&fmt, Params &&... args) const
|
||||
{
|
||||
// process only if there is a target
|
||||
if (!m_logerror_list.empty())
|
||||
{
|
||||
g_profiler.start(PROFILER_LOGERROR);
|
||||
|
||||
// dump to the buffer
|
||||
m_string_buffer.clear();
|
||||
m_string_buffer.seekp(0);
|
||||
util::stream_format(m_string_buffer, std::forward<Format>(fmt), std::forward<Params>(args)...);
|
||||
m_string_buffer.put('\0');
|
||||
|
||||
// log to all callbacks
|
||||
char const *const str(&m_string_buffer.vec()[0]);
|
||||
for (auto &cb : m_logerror_list)
|
||||
(cb->m_func)(*this, str);
|
||||
|
||||
g_profiler.stop();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __MACHINE_H__ */
|
||||
|
@ -1,77 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Aaron Giles
|
||||
/***************************************************************************
|
||||
|
||||
machine.ipp
|
||||
|
||||
Controls execution of the core MAME system.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __EMU_H__
|
||||
#error Dont include this file directly; include emu.h instead.
|
||||
#endif
|
||||
|
||||
#ifndef __MACHINE_IPP__
|
||||
#define __MACHINE_IPP__
|
||||
|
||||
#include "strformat.h"
|
||||
|
||||
//**************************************************************************
|
||||
// MEMBER TEMPLATES
|
||||
//**************************************************************************
|
||||
|
||||
/*-------------------------------------------------
|
||||
popmessage - pop up a user-visible message
|
||||
-------------------------------------------------*/
|
||||
|
||||
template <typename Format, typename... Params>
|
||||
inline void running_machine::popmessage(Format &&fmt, Params &&... args) const
|
||||
{
|
||||
if (is_null<Format>::value(fmt))
|
||||
{
|
||||
// if the format is NULL, it is a signal to clear the popmessage
|
||||
ui().popup_time(0, " ");
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, generate the buffer and call the UI to display the message
|
||||
std::string const temp(string_format(std::forward<Format>(fmt), std::forward<Params>(args)...));
|
||||
|
||||
// pop it in the UI
|
||||
ui().popup_time(temp.length() / 40 + 2, "%s", temp.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
logerror - log to the debugger and any other
|
||||
OSD-defined output streams
|
||||
-------------------------------------------------*/
|
||||
|
||||
template <typename Format, typename... Params>
|
||||
inline void running_machine::logerror(Format &&fmt, Params &&... args) const
|
||||
{
|
||||
// process only if there is a target
|
||||
if (!m_logerror_list.empty())
|
||||
{
|
||||
g_profiler.start(PROFILER_LOGERROR);
|
||||
|
||||
// dump to the buffer
|
||||
m_string_buffer.clear();
|
||||
m_string_buffer.seekp(0);
|
||||
util::stream_format(m_string_buffer, std::forward<Format>(fmt), std::forward<Params>(args)...);
|
||||
m_string_buffer.put('\0');
|
||||
|
||||
// log to all callbacks
|
||||
char const *const str(&m_string_buffer.vec()[0]);
|
||||
for (auto &cb : m_logerror_list)
|
||||
(cb->m_func)(*this, str);
|
||||
|
||||
g_profiler.stop();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __MACHINE_IPP__
|
@ -51,8 +51,9 @@
|
||||
#include <math.h>
|
||||
#include <mutex>
|
||||
|
||||
#include "emucore.h"
|
||||
#include "bitmap.h"
|
||||
#include "emu.h"
|
||||
//#include "bitmap.h"
|
||||
//#include "screen.h"
|
||||
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
|
@ -57,7 +57,8 @@ enum ui_menu_reset_options
|
||||
enum class ui_menu_item_type
|
||||
{
|
||||
UI_MENU_ITEM_TYPE_UNKNOWN,
|
||||
UI_MENU_ITEM_TYPE_SLIDER
|
||||
UI_MENU_ITEM_TYPE_SLIDER,
|
||||
UI_MENU_ITEM_TYPE_SEPARATOR
|
||||
};
|
||||
|
||||
|
||||
|
@ -140,32 +140,47 @@ void ui_menu_sliders::populate()
|
||||
std::string tempstring;
|
||||
|
||||
/* add UI sliders */
|
||||
std::vector<slider_state *> ui_sliders = machine().ui().get_slider_list();
|
||||
for (slider_state* slider : ui_sliders)
|
||||
std::vector<ui_menu_item> ui_sliders = machine().ui().get_slider_list();
|
||||
for (ui_menu_item item : ui_sliders)
|
||||
{
|
||||
INT32 curval = (*slider->update)(machine(), slider->arg, slider->id, &tempstring, SLIDER_NOCHANGE);
|
||||
UINT32 flags = 0;
|
||||
if (curval > slider->minval)
|
||||
flags |= MENU_FLAG_LEFT_ARROW;
|
||||
if (curval < slider->maxval)
|
||||
flags |= MENU_FLAG_RIGHT_ARROW;
|
||||
item_append(slider->description, tempstring.c_str(), flags, (void *)slider, ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER);
|
||||
if (item.type == ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER)
|
||||
{
|
||||
slider_state* slider = reinterpret_cast<slider_state *>(item.ref);
|
||||
INT32 curval = (*slider->update)(machine(), slider->arg, slider->id, &tempstring, SLIDER_NOCHANGE);
|
||||
UINT32 flags = 0;
|
||||
if (curval > slider->minval)
|
||||
flags |= MENU_FLAG_LEFT_ARROW;
|
||||
if (curval < slider->maxval)
|
||||
flags |= MENU_FLAG_RIGHT_ARROW;
|
||||
item_append(slider->description, tempstring.c_str(), flags, (void *)slider, ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
item_append(item);
|
||||
}
|
||||
}
|
||||
|
||||
item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr);
|
||||
|
||||
/* add OSD options */
|
||||
std::vector<slider_state *> osd_sliders = machine().osd().get_slider_list();
|
||||
for (slider_state* slider : osd_sliders)
|
||||
std::vector<ui_menu_item> osd_sliders = machine().osd().get_slider_list();
|
||||
for (ui_menu_item item : osd_sliders)
|
||||
{
|
||||
|
||||
INT32 curval = (*slider->update)(machine(), slider->arg, slider->id, &tempstring, SLIDER_NOCHANGE);
|
||||
UINT32 flags = 0;
|
||||
if (curval > slider->minval)
|
||||
flags |= MENU_FLAG_LEFT_ARROW;
|
||||
if (curval < slider->maxval)
|
||||
flags |= MENU_FLAG_RIGHT_ARROW;
|
||||
item_append(slider->description, tempstring.c_str(), flags, (void *)slider, ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER);
|
||||
if (item.type == ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER)
|
||||
{
|
||||
slider_state* slider = reinterpret_cast<slider_state *>(item.ref);
|
||||
INT32 curval = (*slider->update)(machine(), slider->arg, slider->id, &tempstring, SLIDER_NOCHANGE);
|
||||
UINT32 flags = 0;
|
||||
if (curval > slider->minval)
|
||||
flags |= MENU_FLAG_LEFT_ARROW;
|
||||
if (curval < slider->maxval)
|
||||
flags |= MENU_FLAG_RIGHT_ARROW;
|
||||
item_append(slider->description, tempstring.c_str(), flags, (void *)slider, ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
item_append(item);
|
||||
}
|
||||
}
|
||||
|
||||
custombottom = 2.0f * machine().ui().get_line_height() + 2.0f * UI_BOX_TB_BORDER;
|
||||
|
@ -118,7 +118,7 @@ std::string ui_manager::messagebox_poptext;
|
||||
rgb_t ui_manager::messagebox_backcolor;
|
||||
|
||||
// slider info
|
||||
std::vector<slider_state *> ui_manager::slider_list;
|
||||
std::vector<ui_menu_item> ui_manager::slider_list;
|
||||
slider_state *ui_manager::slider_current;
|
||||
|
||||
|
||||
@ -340,7 +340,7 @@ void ui_manager::initialize(running_machine &machine)
|
||||
slider_list = slider_init(machine);
|
||||
if (slider_list.size() > 0)
|
||||
{
|
||||
slider_current = slider_list[0];
|
||||
slider_current = reinterpret_cast<slider_state *>(slider_list[0].ref);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1873,7 +1873,7 @@ UINT32 ui_manager::handler_confirm_quit(running_machine &machine, render_contain
|
||||
// ui_get_slider_list - get the list of sliders
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<slider_state *>& ui_manager::get_slider_list(void)
|
||||
std::vector<ui_menu_item>& ui_manager::get_slider_list(void)
|
||||
{
|
||||
return slider_list;
|
||||
}
|
||||
@ -1906,7 +1906,7 @@ static slider_state *slider_alloc(running_machine &machine, const char *title, I
|
||||
// controls
|
||||
//----------------------------------------------------------
|
||||
|
||||
std::vector<slider_state *> ui_manager::slider_init(running_machine &machine)
|
||||
std::vector<ui_menu_item> ui_manager::slider_init(running_machine &machine)
|
||||
{
|
||||
std::vector<slider_state *> sliders;
|
||||
|
||||
@ -2040,7 +2040,19 @@ std::vector<slider_state *> ui_manager::slider_init(running_machine &machine)
|
||||
}
|
||||
#endif
|
||||
|
||||
return sliders;
|
||||
std::vector<ui_menu_item> items;
|
||||
for (slider_state *slider : sliders)
|
||||
{
|
||||
ui_menu_item item;
|
||||
item.text = slider->description;
|
||||
item.subtext = "";
|
||||
item.flags = 0;
|
||||
item.ref = slider;
|
||||
item.type = ui_menu_item_type::UI_MENU_ITEM_TYPE_SLIDER;
|
||||
items.push_back(item);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "render.h"
|
||||
#include "moptions.h"
|
||||
|
||||
class ui_menu_item;
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
@ -130,7 +132,7 @@ public:
|
||||
|
||||
// methods
|
||||
void initialize(running_machine &machine);
|
||||
std::vector<slider_state *> slider_init(running_machine &machine);
|
||||
std::vector<ui_menu_item> slider_init(running_machine &machine);
|
||||
UINT32 set_handler(ui_callback callback, UINT32 param);
|
||||
void display_startup_screens(bool first_time);
|
||||
void set_startup_text(const char *text, bool force);
|
||||
@ -169,7 +171,7 @@ public:
|
||||
std::string &game_info_astring(std::string &str);
|
||||
|
||||
// slider controls
|
||||
std::vector<slider_state *>& get_slider_list(void);
|
||||
std::vector<ui_menu_item>& get_slider_list(void);
|
||||
|
||||
// other
|
||||
void process_natural_keyboard();
|
||||
@ -212,7 +214,7 @@ private:
|
||||
static std::string messagebox_poptext;
|
||||
static rgb_t messagebox_backcolor;
|
||||
|
||||
static std::vector<slider_state *> slider_list;
|
||||
static std::vector<ui_menu_item> slider_list;
|
||||
static slider_state *slider_current;
|
||||
|
||||
// text generators
|
||||
|
@ -479,10 +479,10 @@ public:
|
||||
const pstring &def_param)
|
||||
: base_factory_t(name, classname, def_param), m_setup(setup) { }
|
||||
|
||||
class dummy : public device_t
|
||||
class wrapper : public device_t
|
||||
{
|
||||
public:
|
||||
dummy(const pstring &dev_name) : device_t(), m_dev_name(dev_name) { }
|
||||
wrapper(const pstring &dev_name) : device_t(), m_dev_name(dev_name) { }
|
||||
protected:
|
||||
virtual void init(netlist_t &anetlist, const pstring &aname) override
|
||||
{
|
||||
@ -499,7 +499,7 @@ public:
|
||||
|
||||
ATTR_COLD device_t *Create() override
|
||||
{
|
||||
device_t *r = palloc(dummy(this->name()));
|
||||
device_t *r = palloc(wrapper(this->name()));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -74,13 +74,12 @@ logic_family_desc_t *family_CD4XXX = palloc(logic_family_cd4xxx_t);
|
||||
|
||||
queue_t::queue_t(netlist_t &nl)
|
||||
: timed_queue<net_t *, netlist_time>(512)
|
||||
, object_t(QUEUE, GENERIC)
|
||||
, object_t(nl, "QUEUE", QUEUE, GENERIC)
|
||||
, pstate_callback_t()
|
||||
, m_qsize(0)
|
||||
, m_times(512)
|
||||
, m_names(512)
|
||||
{
|
||||
this->init_object(nl, "QUEUE");
|
||||
}
|
||||
|
||||
void queue_t::register_state(pstate_manager_t &manager, const pstring &module)
|
||||
@ -128,13 +127,33 @@ void queue_t::on_post_load()
|
||||
ATTR_COLD object_t::object_t(const type_t atype, const family_t afamily)
|
||||
: m_objtype(atype)
|
||||
, m_family(afamily)
|
||||
, m_netlist(NULL)
|
||||
, m_netlist(nullptr)
|
||||
{}
|
||||
|
||||
ATTR_COLD object_t::object_t(netlist_t &nl, const type_t atype, const family_t afamily)
|
||||
: m_objtype(atype)
|
||||
, m_family(afamily)
|
||||
, m_netlist(&nl)
|
||||
{}
|
||||
|
||||
ATTR_COLD object_t::object_t(netlist_t &nl, const pstring &aname, const type_t atype, const family_t afamily)
|
||||
: m_name(aname)
|
||||
, m_objtype(atype)
|
||||
, m_family(afamily)
|
||||
, m_netlist(&nl)
|
||||
{
|
||||
}
|
||||
|
||||
ATTR_COLD object_t::~object_t()
|
||||
{
|
||||
}
|
||||
|
||||
ATTR_COLD void object_t::init_object(const pstring &aname)
|
||||
{
|
||||
m_name = aname;
|
||||
save_register();
|
||||
}
|
||||
|
||||
ATTR_COLD void object_t::init_object(netlist_t &nl, const pstring &aname)
|
||||
{
|
||||
m_netlist = &nl;
|
||||
@ -171,8 +190,8 @@ ATTR_COLD void device_object_t::init_object(core_device_t &dev,
|
||||
// netlist_t
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
netlist_t::netlist_t()
|
||||
: object_t(NETLIST, GENERIC), pstate_manager_t(),
|
||||
netlist_t::netlist_t(const pstring &aname)
|
||||
: pstate_manager_t(),
|
||||
m_stop(netlist_time::zero),
|
||||
m_time(netlist_time::zero),
|
||||
m_use_deactivate(0),
|
||||
@ -181,9 +200,12 @@ netlist_t::netlist_t()
|
||||
m_solver(NULL),
|
||||
m_gnd(NULL),
|
||||
m_params(NULL),
|
||||
m_name(aname),
|
||||
m_setup(NULL),
|
||||
m_log(this)
|
||||
{
|
||||
save_item(static_cast<pstate_callback_t &>(m_queue), this, "m_queue");
|
||||
save_item(m_time, this, "m_time");
|
||||
}
|
||||
|
||||
netlist_t::~netlist_t()
|
||||
@ -202,13 +224,6 @@ netlist_t::~netlist_t()
|
||||
pstring::resetmem();
|
||||
}
|
||||
|
||||
ATTR_COLD void netlist_t::save_register()
|
||||
{
|
||||
save(static_cast<pstate_callback_t &>(m_queue), "m_queue");
|
||||
save(NLNAME(m_time));
|
||||
object_t::save_register();
|
||||
}
|
||||
|
||||
ATTR_HOT nl_double netlist_t::gmin() const
|
||||
{
|
||||
return solver()->gmin();
|
||||
@ -925,6 +940,19 @@ ATTR_COLD analog_output_t::analog_output_t()
|
||||
net().m_cur_Analog = NL_FCONST(0.99);
|
||||
}
|
||||
|
||||
ATTR_COLD analog_output_t::analog_output_t(core_device_t &dev, const pstring &aname)
|
||||
: analog_t(OUTPUT), m_proxied_net(NULL)
|
||||
{
|
||||
this->set_net(m_my_net);
|
||||
set_state(STATE_OUT);
|
||||
|
||||
net().m_cur_Analog = NL_FCONST(0.99);
|
||||
|
||||
analog_t::init_object(dev, aname);
|
||||
net().init_object(dev.netlist(), aname + ".net");
|
||||
net().register_railterminal(*this);
|
||||
}
|
||||
|
||||
ATTR_COLD void analog_output_t::init_object(core_device_t &dev, const pstring &aname)
|
||||
{
|
||||
analog_t::init_object(dev, aname);
|
||||
|
@ -367,7 +367,7 @@ namespace netlist
|
||||
// object_t
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class object_t
|
||||
class object_t : public pstate_interface_t<object_t>
|
||||
{
|
||||
P_PREVENT_COPYING(object_t)
|
||||
public:
|
||||
@ -378,8 +378,7 @@ namespace netlist
|
||||
PARAM = 3,
|
||||
NET = 4,
|
||||
DEVICE = 5,
|
||||
NETLIST = 6,
|
||||
QUEUE = 7
|
||||
QUEUE = 6
|
||||
};
|
||||
enum family_t {
|
||||
// Terminal families
|
||||
@ -405,15 +404,18 @@ namespace netlist
|
||||
};
|
||||
|
||||
ATTR_COLD object_t(const type_t atype, const family_t afamily);
|
||||
ATTR_COLD object_t(netlist_t &nl, const type_t atype, const family_t afamily);
|
||||
ATTR_COLD object_t(netlist_t &nl, const pstring &aname, const type_t atype, const family_t afamily);
|
||||
|
||||
virtual ~object_t();
|
||||
|
||||
ATTR_COLD void init_object(const pstring &aname);
|
||||
ATTR_COLD void init_object(netlist_t &nl, const pstring &aname);
|
||||
ATTR_COLD bool isInitialized() { return (m_netlist != NULL); }
|
||||
|
||||
ATTR_COLD const pstring &name() const;
|
||||
|
||||
PSTATE_INTERFACE_DECL()
|
||||
ATTR_COLD inline pstate_manager_t *state_manager();
|
||||
|
||||
ATTR_HOT type_t type() const { return m_objtype; }
|
||||
ATTR_HOT family_t family() const { return m_family; }
|
||||
@ -904,6 +906,7 @@ namespace netlist
|
||||
P_PREVENT_COPYING(analog_output_t)
|
||||
public:
|
||||
|
||||
ATTR_COLD analog_output_t(core_device_t &dev, const pstring &aname);
|
||||
ATTR_COLD analog_output_t();
|
||||
|
||||
ATTR_COLD void init_object(core_device_t &dev, const pstring &aname);
|
||||
@ -1183,14 +1186,16 @@ namespace netlist
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class netlist_t : public object_t, public pstate_manager_t, public plog_dispatch_intf
|
||||
class netlist_t : public pstate_manager_t, public plog_dispatch_intf
|
||||
{
|
||||
P_PREVENT_COPYING(netlist_t)
|
||||
public:
|
||||
|
||||
netlist_t();
|
||||
netlist_t(const pstring &aname);
|
||||
virtual ~netlist_t();
|
||||
|
||||
pstring name() const { return m_name; }
|
||||
|
||||
ATTR_COLD void start();
|
||||
ATTR_COLD void stop();
|
||||
|
||||
@ -1265,15 +1270,13 @@ namespace netlist
|
||||
pnamedlist_t<core_device_t *> m_started_devices;
|
||||
#endif
|
||||
|
||||
ATTR_COLD plog_base<NL_DEBUG> &log() { return m_log; }
|
||||
ATTR_COLD const plog_base<NL_DEBUG> &log() const { return m_log; }
|
||||
ATTR_COLD plog_base<NL_DEBUG> &log() { return m_log; }
|
||||
ATTR_COLD const plog_base<NL_DEBUG> &log() const { return m_log; }
|
||||
|
||||
virtual void reset();
|
||||
|
||||
protected:
|
||||
|
||||
/* from object */
|
||||
virtual void reset() override;
|
||||
virtual void save_register() override;
|
||||
|
||||
#if (NL_KEEP_STATISTICS)
|
||||
// performance
|
||||
int m_perf_out_processed;
|
||||
@ -1288,13 +1291,13 @@ namespace netlist
|
||||
bool m_use_deactivate;
|
||||
queue_t m_queue;
|
||||
|
||||
|
||||
devices::NETLIB_NAME(mainclock) * m_mainclock;
|
||||
devices::NETLIB_NAME(solver) * m_solver;
|
||||
devices::NETLIB_NAME(gnd) * m_gnd;
|
||||
|
||||
|
||||
devices::NETLIB_NAME(netlistparams) *m_params;
|
||||
|
||||
pstring m_name;
|
||||
setup_t *m_setup;
|
||||
plog_base<NL_DEBUG> m_log;
|
||||
};
|
||||
@ -1303,7 +1306,10 @@ namespace netlist
|
||||
// inline implementations
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
PSTATE_INTERFACE(object_t, m_netlist, name())
|
||||
ATTR_COLD inline pstate_manager_t *object_t::state_manager()
|
||||
{
|
||||
return m_netlist;
|
||||
}
|
||||
|
||||
template <class C, param_t::param_type_t T>
|
||||
ATTR_HOT inline void param_template_t<C, T>::setTo(const C ¶m)
|
||||
|
@ -197,8 +197,6 @@ pstring setup_t::objtype_as_astr(object_t &in) const
|
||||
return "PARAM";
|
||||
case terminal_t::DEVICE:
|
||||
return "DEVICE";
|
||||
case terminal_t::NETLIST:
|
||||
return "NETLIST";
|
||||
case terminal_t::QUEUE:
|
||||
return "QUEUE";
|
||||
}
|
||||
@ -283,9 +281,6 @@ void setup_t::register_object(device_t &dev, const pstring &name, object_t &obj)
|
||||
case terminal_t::DEVICE:
|
||||
log().fatal("Device registration not yet supported - {1}\n", name);
|
||||
break;
|
||||
case terminal_t::NETLIST:
|
||||
log().fatal("Netlist registration not yet supported - {1}\n", name);
|
||||
break;
|
||||
case terminal_t::QUEUE:
|
||||
log().fatal("QUEUE registration not yet supported - {1}\n", name);
|
||||
break;
|
||||
|
@ -15,19 +15,6 @@
|
||||
// state saving ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#define PSTATE_INTERFACE_DECL() \
|
||||
template<typename C> ATTR_COLD void save(C &state, const pstring &stname); \
|
||||
template<typename C, std::size_t N> ATTR_COLD void save(C (&state)[N], const pstring &stname); \
|
||||
template<typename C> ATTR_COLD void save(C *state, const pstring &stname, const int count);
|
||||
|
||||
#define PSTATE_INTERFACE(obj, manager, module) \
|
||||
template<typename C> ATTR_COLD void obj::save(C &state, const pstring &stname) \
|
||||
{ manager->save_item(state, this, module + "." + stname); } \
|
||||
template<typename C, std::size_t N> ATTR_COLD void obj::save(C (&state)[N], const pstring &stname) \
|
||||
{ manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(state[0]), N, &(state[0]), false); } \
|
||||
template<typename C> ATTR_COLD void obj::save(C *state, const pstring &stname, const int count) \
|
||||
{ manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(C), count, state, false); }
|
||||
|
||||
enum pstate_data_type_e {
|
||||
NOT_SUPPORTED,
|
||||
DT_CUSTOM,
|
||||
@ -148,6 +135,12 @@ public:
|
||||
save_state_ptr(stname, pstate_datatype<C>::type, owner, sizeof(C), count, state, false);
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
void save_item(std::vector<C> &v, const void *owner, const pstring &stname)
|
||||
{
|
||||
save_state(v.data(), owner, stname, v.size());
|
||||
}
|
||||
|
||||
ATTR_COLD void pre_save();
|
||||
ATTR_COLD void post_load();
|
||||
ATTR_COLD void remove_save_items(const void *owner);
|
||||
@ -164,5 +157,31 @@ private:
|
||||
|
||||
template<> ATTR_COLD void pstate_manager_t::save_item(pstate_callback_t &state, const void *owner, const pstring &stname);
|
||||
|
||||
template <typename T>
|
||||
class pstate_interface_t
|
||||
{
|
||||
public:
|
||||
pstate_interface_t() { }
|
||||
|
||||
template<typename C> void save(C &state, const pstring &stname)
|
||||
{
|
||||
pstate_manager_t *manager = static_cast<T*>(this)->state_manager();
|
||||
pstring module = static_cast<T*>(this)->name();
|
||||
manager->save_item(state, this, module + "." + stname);
|
||||
}
|
||||
template<typename C, std::size_t N> ATTR_COLD void save(C (&state)[N], const pstring &stname)
|
||||
{
|
||||
pstate_manager_t *manager = static_cast<T*>(this)->state_manager();
|
||||
pstring module = static_cast<T*>(this)->name();
|
||||
manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(state[0]), N, &(state[0]), false);
|
||||
}
|
||||
template<typename C> ATTR_COLD void save(C *state, const pstring &stname, const int count)
|
||||
{
|
||||
pstate_manager_t *manager = static_cast<T*>(this)->state_manager();
|
||||
pstring module = static_cast<T*>(this)->name();
|
||||
manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(C), count, state, false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* PSTATE_H_ */
|
||||
|
@ -145,8 +145,8 @@ class netlist_tool_t : public netlist::netlist_t
|
||||
{
|
||||
public:
|
||||
|
||||
netlist_tool_t()
|
||||
: netlist::netlist_t(), m_opts(NULL), m_setup(NULL)
|
||||
netlist_tool_t(const pstring &aname)
|
||||
: netlist::netlist_t(aname), m_opts(NULL), m_setup(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -159,7 +159,6 @@ public:
|
||||
void init()
|
||||
{
|
||||
m_setup = palloc(netlist::setup_t(this));
|
||||
this->init_object(*this, "netlist");
|
||||
m_setup->init();
|
||||
}
|
||||
|
||||
@ -281,7 +280,7 @@ pvector_t<input_t> *read_input(netlist::netlist_t *netlist, pstring fname)
|
||||
|
||||
static void run(tool_options_t &opts)
|
||||
{
|
||||
netlist_tool_t nt;
|
||||
netlist_tool_t nt("netlist");
|
||||
osd_ticks_t t = osd_ticks();
|
||||
|
||||
nt.m_opts = &opts;
|
||||
@ -326,7 +325,7 @@ static void run(tool_options_t &opts)
|
||||
|
||||
static void listdevices()
|
||||
{
|
||||
netlist_tool_t nt;
|
||||
netlist_tool_t nt("netlist");
|
||||
nt.init();
|
||||
const netlist::factory_list_t &list = nt.setup().factory();
|
||||
|
||||
|
@ -178,6 +178,9 @@ ATTR_COLD void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
|
||||
|
||||
if (net_proxy_output == NULL)
|
||||
{
|
||||
//net_proxy_output = palloc(analog_output_t(*this,
|
||||
// this->name() + "." + pfmt("m{1}")(m_inps.size())));
|
||||
|
||||
net_proxy_output = palloc(analog_output_t);
|
||||
net_proxy_output->init_object(*this, this->name() + "." + pfmt("m{1}")(m_inps.size()));
|
||||
m_inps.push_back(net_proxy_output);
|
||||
|
@ -48,10 +48,8 @@ public:
|
||||
, m_cd_pos(0)
|
||||
, m_header()
|
||||
, m_curr_is_dir(false)
|
||||
, m_curr_name()
|
||||
, m_buffer()
|
||||
{
|
||||
std::memset(&m_header, 0, sizeof(m_header));
|
||||
std::fill(m_buffer.begin(), m_buffer.end(), 0);
|
||||
}
|
||||
|
||||
@ -134,7 +132,7 @@ public:
|
||||
}
|
||||
|
||||
bool current_is_directory() const { return m_curr_is_dir; }
|
||||
const std::string ¤t_name() const { return m_curr_name; }
|
||||
const std::string ¤t_name() const { return m_header.file_name; }
|
||||
std::uint64_t current_uncompressed_length() const { return m_header.uncompressed_length; }
|
||||
std::uint32_t current_crc() const { return m_header.crc; }
|
||||
|
||||
@ -179,6 +177,7 @@ private:
|
||||
std::uint64_t uncompressed_length; // uncompressed size
|
||||
std::uint32_t start_disk_number; // disk number start
|
||||
std::uint64_t local_header_offset; // relative offset of local header
|
||||
std::string file_name; // file name
|
||||
};
|
||||
|
||||
// contains extracted end of central directory information
|
||||
@ -207,7 +206,6 @@ private:
|
||||
std::uint32_t m_cd_pos; // position in central directory
|
||||
file_header m_header; // current file header
|
||||
bool m_curr_is_dir; // current file is directory
|
||||
std::string m_curr_name; // current file name
|
||||
|
||||
std::array<std::uint8_t, DECOMPRESS_BUFSIZE> m_buffer; // buffer for decompression
|
||||
};
|
||||
@ -315,39 +313,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class zip64_ext_info_reader : private reader_base
|
||||
{
|
||||
public:
|
||||
zip64_ext_info_reader(extra_field_reader const &field) : reader_base(field.data()) { }
|
||||
|
||||
std::uint64_t uncompressed_size() const { return read_qword(0x00); }
|
||||
std::uint64_t compressed_size() const { return read_qword(0x08); }
|
||||
std::uint64_t header_offset() const { return read_qword(0x10); }
|
||||
std::uint32_t start_disk() const { return read_dword(0x18); }
|
||||
|
||||
std::size_t total_length() const { return minimum_length(); }
|
||||
static std::size_t minimum_length() { return 0x1c; }
|
||||
};
|
||||
|
||||
|
||||
class utf8_path_reader : private reader_base
|
||||
{
|
||||
public:
|
||||
utf8_path_reader(extra_field_reader const &field) : reader_base(field.data()), m_length(field.data_size()) { }
|
||||
|
||||
std::uint8_t version() const { return m_buffer[0]; }
|
||||
std::uint32_t name_crc32() const { return read_dword(0x01); }
|
||||
std::string unicode_name() const { return read_string(0x05, m_length - 0x05); }
|
||||
void unicode_name(std::string &result) const { return read_string(result, 0x05, m_length - 0x05); }
|
||||
|
||||
std::size_t total_length() const { return m_length; }
|
||||
static std::size_t minimum_length() { return 0x05; }
|
||||
|
||||
private:
|
||||
std::size_t m_length;
|
||||
};
|
||||
|
||||
|
||||
class local_file_header_reader : private reader_base
|
||||
{
|
||||
public:
|
||||
@ -479,6 +444,64 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class zip64_ext_info_reader : private reader_base
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
zip64_ext_info_reader(
|
||||
T const &header,
|
||||
extra_field_reader const &field)
|
||||
: reader_base(field.data())
|
||||
, m_uncompressed_size(header.uncompressed_size())
|
||||
, m_compressed_size(header.compressed_size())
|
||||
, m_header_offset(header.header_offset())
|
||||
, m_start_disk(header.start_disk())
|
||||
, m_offs_compressed_size(~m_uncompressed_size ? 0 : 8)
|
||||
, m_offs_header_offset(m_offs_compressed_size + (~m_compressed_size ? 0 : 8))
|
||||
, m_offs_start_disk(m_offs_header_offset + (~m_header_offset ? 0 : 8))
|
||||
, m_offs_end(m_offs_start_disk + (~m_start_disk ? 0 : 4))
|
||||
{
|
||||
}
|
||||
|
||||
std::uint64_t uncompressed_size() const { return ~m_uncompressed_size ? m_uncompressed_size : read_qword(0x00); }
|
||||
std::uint64_t compressed_size() const { return ~m_compressed_size ? m_compressed_size : read_qword(m_offs_compressed_size); }
|
||||
std::uint64_t header_offset() const { return ~m_header_offset ? m_header_offset : read_qword(m_offs_header_offset); }
|
||||
std::uint32_t start_disk() const { return ~m_start_disk ? m_start_disk : read_dword(m_offs_start_disk); }
|
||||
|
||||
std::size_t total_length() const { return minimum_length() + m_offs_end; }
|
||||
static std::size_t minimum_length() { return 0x00; }
|
||||
|
||||
private:
|
||||
std::uint32_t m_uncompressed_size;
|
||||
std::uint32_t m_compressed_size;
|
||||
std::uint32_t m_header_offset;
|
||||
std::uint16_t m_start_disk;
|
||||
|
||||
std::size_t m_offs_compressed_size;
|
||||
std::size_t m_offs_header_offset;
|
||||
std::size_t m_offs_start_disk;
|
||||
std::size_t m_offs_end;
|
||||
};
|
||||
|
||||
|
||||
class utf8_path_reader : private reader_base
|
||||
{
|
||||
public:
|
||||
utf8_path_reader(extra_field_reader const &field) : reader_base(field.data()), m_length(field.data_size()) { }
|
||||
|
||||
std::uint8_t version() const { return m_buffer[0]; }
|
||||
std::uint32_t name_crc32() const { return read_dword(0x01); }
|
||||
std::string unicode_name() const { return read_string(0x05, m_length - 0x05); }
|
||||
void unicode_name(std::string &result) const { return read_string(result, 0x05, m_length - 0x05); }
|
||||
|
||||
std::size_t total_length() const { return m_length; }
|
||||
static std::size_t minimum_length() { return 0x05; }
|
||||
|
||||
private:
|
||||
std::size_t m_length;
|
||||
};
|
||||
|
||||
|
||||
class general_flag_reader
|
||||
{
|
||||
public:
|
||||
@ -553,7 +576,6 @@ void zip_file_impl::close(ptr &&zip)
|
||||
int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname, bool partialpath)
|
||||
{
|
||||
// if we're at or past the end, we're done
|
||||
std::string filename;
|
||||
while ((m_cd_pos + central_dir_entry_reader::minimum_length()) <= m_ecd.cd_size)
|
||||
{
|
||||
// make sure we have enough data
|
||||
@ -577,7 +599,7 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi
|
||||
|
||||
// copy the filename
|
||||
bool is_utf8(general_flag_reader(m_header.bit_flag).utf8_encoding());
|
||||
reader.file_name(filename);
|
||||
reader.file_name(m_header.file_name);
|
||||
|
||||
// walk the extra data
|
||||
for (auto extra = reader.extra_field(); extra.length_sufficient(); extra = extra.next())
|
||||
@ -585,12 +607,13 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi
|
||||
// look for ZIP64 extended info
|
||||
if ((extra.header_id() == 0x0001) && (extra.data_size() >= zip64_ext_info_reader::minimum_length()))
|
||||
{
|
||||
zip64_ext_info_reader const ext64(extra);
|
||||
zip64_ext_info_reader const ext64(reader, extra);
|
||||
if (extra.data_size() >= ext64.total_length())
|
||||
{
|
||||
m_header.compressed_length = ext64.compressed_size();
|
||||
m_header.uncompressed_length = ext64.uncompressed_size();
|
||||
m_header.start_disk_number = ext64.start_disk();
|
||||
m_header.local_header_offset = ext64.header_offset();
|
||||
}
|
||||
}
|
||||
|
||||
@ -600,10 +623,12 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi
|
||||
utf8_path_reader const utf8path(extra);
|
||||
if (utf8path.version() == 1)
|
||||
{
|
||||
auto const crc(crc32_creator::simple(m_filename.empty() ? nullptr : &filename[0], filename.length() * sizeof(filename[0])));
|
||||
auto const addr(m_header.file_name.empty() ? nullptr : &m_header.file_name[0]);
|
||||
auto const length(m_header.file_name.empty() ? 0 : m_header.file_name.length() * sizeof(m_header.file_name[0]));
|
||||
auto const crc(crc32_creator::simple(addr, length));
|
||||
if (utf8path.name_crc32() == crc.m_raw)
|
||||
{
|
||||
utf8path.unicode_name(filename);
|
||||
utf8path.unicode_name(m_header.file_name);
|
||||
is_utf8 = true;
|
||||
}
|
||||
}
|
||||
@ -613,22 +638,21 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi
|
||||
// FIXME: if (!is_utf8) convert filename to UTF8 (assume CP437 or something)
|
||||
|
||||
// chop off trailing slash for directory entries
|
||||
bool const is_dir((filename.length() > 0) && (filename[filename.length() - 1] == '/'));
|
||||
if (is_dir) filename.resize(filename.length() - 1);
|
||||
bool const is_dir(!m_header.file_name.empty() && (m_header.file_name.back() == '/'));
|
||||
if (is_dir) m_header.file_name.resize(m_header.file_name.length() - 1);
|
||||
|
||||
// check to see if it matches query
|
||||
bool const crcmatch(search_crc == m_header.crc);
|
||||
auto const partialoffset(filename.length() - search_filename.length());
|
||||
bool const partialpossible((filename.length() > search_filename.length()) && (filename[partialoffset - 1] == '/'));
|
||||
auto const partialoffset(m_header.file_name.length() - search_filename.length());
|
||||
bool const partialpossible((m_header.file_name.length() > search_filename.length()) && (m_header.file_name[partialoffset - 1] == '/'));
|
||||
const bool namematch(
|
||||
!core_stricmp(search_filename.c_str(), filename.c_str()) ||
|
||||
(partialpath && partialpossible && !core_stricmp(search_filename.c_str(), filename.c_str() + partialoffset)));
|
||||
!core_stricmp(search_filename.c_str(), m_header.file_name.c_str()) ||
|
||||
(partialpath && partialpossible && !core_stricmp(search_filename.c_str(), m_header.file_name.c_str() + partialoffset)));
|
||||
|
||||
bool const found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch);
|
||||
if (found)
|
||||
{
|
||||
m_curr_is_dir = is_dir;
|
||||
m_curr_name = std::move(filename);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -966,7 +990,7 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
|
||||
std::uint32_t read_length;
|
||||
osd_file::error filerr;
|
||||
SRes lzerr;
|
||||
ELzmaStatus lzstatus;
|
||||
ELzmaStatus lzstatus(LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK);
|
||||
|
||||
// reset the stream
|
||||
ISzAlloc alloc_imp;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <forward_list>
|
||||
#include <new>
|
||||
|
||||
|
||||
@ -25,20 +26,6 @@ namespace util {
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* @struct zippath_returned_directory
|
||||
*
|
||||
* @brief A zippath returned directory.
|
||||
*/
|
||||
|
||||
struct zippath_returned_directory
|
||||
{
|
||||
/** @brief The next. */
|
||||
zippath_returned_directory *next;
|
||||
/** @brief The name. */
|
||||
std::string name;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class zippath_directory
|
||||
*
|
||||
@ -49,11 +36,13 @@ class zippath_directory
|
||||
{
|
||||
public:
|
||||
zippath_directory()
|
||||
: returned_parent(false),
|
||||
directory(nullptr),
|
||||
called_zip_first(false),
|
||||
zipfile(nullptr),
|
||||
returned_dirlist(nullptr) { }
|
||||
: returned_parent(false)
|
||||
, directory(nullptr)
|
||||
, called_zip_first(false)
|
||||
, zipfile(nullptr)
|
||||
, returned_dirlist()
|
||||
{
|
||||
}
|
||||
|
||||
/* common */
|
||||
/** @brief true to returned parent. */
|
||||
@ -73,7 +62,7 @@ public:
|
||||
/** @brief The zipprefix. */
|
||||
std::string zipprefix;
|
||||
/** @brief The returned dirlist. */
|
||||
zippath_returned_directory *returned_dirlist;
|
||||
std::forward_list<std::string> returned_dirlist;
|
||||
};
|
||||
|
||||
|
||||
@ -856,12 +845,7 @@ void zippath_closedir(zippath_directory *directory)
|
||||
if (directory->zipfile != nullptr)
|
||||
directory->zipfile.reset();
|
||||
|
||||
while (directory->returned_dirlist != nullptr)
|
||||
{
|
||||
zippath_returned_directory *dirlist = directory->returned_dirlist;
|
||||
directory->returned_dirlist = directory->returned_dirlist->next;
|
||||
delete dirlist;
|
||||
}
|
||||
directory->returned_dirlist.clear();
|
||||
|
||||
delete directory;
|
||||
}
|
||||
@ -887,24 +871,28 @@ void zippath_closedir(zippath_directory *directory)
|
||||
static const char *get_relative_path(zippath_directory const &directory)
|
||||
{
|
||||
auto len = directory.zipprefix.length();
|
||||
const char *prefix = directory.zipprefix.c_str();
|
||||
char const *prefix = directory.zipprefix.c_str();
|
||||
while (is_zip_file_separator(*prefix))
|
||||
{
|
||||
len--;
|
||||
prefix++;
|
||||
}
|
||||
|
||||
if ((len <= directory.zipfile->current_name().length()) &&
|
||||
!strncmp(prefix, directory.zipfile->current_name().c_str(), len))
|
||||
std::string const ¤t(directory.zipfile->current_name());
|
||||
char const *result = directory.zipfile->current_name().c_str() + len;
|
||||
if ((current.length() >= len) &&
|
||||
!strncmp(prefix, current.c_str(), len) &&
|
||||
(!*prefix || is_zip_file_separator(*result) || is_zip_file_separator(directory.zipprefix.back())))
|
||||
{
|
||||
const char *result = &directory.zipfile->current_name().c_str()[len];
|
||||
while (is_zip_file_separator(*result))
|
||||
result++;
|
||||
|
||||
return *result ? result : nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -925,11 +913,6 @@ static const char *get_relative_path(zippath_directory const &directory)
|
||||
const osd_directory_entry *zippath_readdir(zippath_directory *directory)
|
||||
{
|
||||
const osd_directory_entry *result = nullptr;
|
||||
int header;
|
||||
const char *relpath;
|
||||
const char *separator;
|
||||
const char *s;
|
||||
zippath_returned_directory *rdent;
|
||||
|
||||
if (!directory->returned_parent)
|
||||
{
|
||||
@ -947,10 +930,10 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory)
|
||||
{
|
||||
result = osd_readdir(directory->directory);
|
||||
}
|
||||
while((result != nullptr) && (!strcmp(result->name, ".") || !strcmp(result->name, "..")));
|
||||
while (result && (!strcmp(result->name, ".") || !strcmp(result->name, "..")));
|
||||
|
||||
/* special case - is this entry a ZIP file? if so we need to return it as a "directory" */
|
||||
if ((result != nullptr) && (is_zip_file(result->name) || is_7z_file(result->name)))
|
||||
if (result && (is_zip_file(result->name) || is_7z_file(result->name)))
|
||||
{
|
||||
/* copy; but change the entry type */
|
||||
directory->returned_entry = *result;
|
||||
@ -960,47 +943,46 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory)
|
||||
}
|
||||
else if (directory->zipfile)
|
||||
{
|
||||
char const *relpath;
|
||||
do
|
||||
{
|
||||
/* a zip file read */
|
||||
int header;
|
||||
do
|
||||
{
|
||||
if (!directory->called_zip_first)
|
||||
header = directory->zipfile->first_file();
|
||||
else
|
||||
header = directory->zipfile->next_file();
|
||||
header = directory->called_zip_first ? directory->zipfile->next_file() : directory->zipfile->first_file();
|
||||
directory->called_zip_first = true;
|
||||
relpath = nullptr;
|
||||
}
|
||||
while((header >= 0) && ((relpath = get_relative_path(*directory)) == nullptr));
|
||||
while ((header >= 0) && ((relpath = get_relative_path(*directory)) == nullptr));
|
||||
|
||||
if (relpath != nullptr)
|
||||
if (relpath)
|
||||
{
|
||||
/* we've found a ZIP entry; but this may be an entry deep within the target directory */
|
||||
for (s = relpath; *s && !is_zip_file_separator(*s); s++)
|
||||
;
|
||||
separator = *s ? s : nullptr;
|
||||
char const *separator = relpath;
|
||||
while (*separator && !is_zip_file_separator(*separator)) separator++;
|
||||
|
||||
if (separator != nullptr)
|
||||
if (*separator || directory->zipfile->current_is_directory())
|
||||
{
|
||||
/* a nested entry; loop through returned_dirlist to see if we've returned the parent directory */
|
||||
for (rdent = directory->returned_dirlist; rdent != nullptr; rdent = rdent->next)
|
||||
auto const len(separator - relpath);
|
||||
auto rdent = directory->returned_dirlist.begin();
|
||||
while (directory->returned_dirlist.end() != rdent)
|
||||
{
|
||||
if (!core_strnicmp(rdent->name.c_str(), relpath, separator - relpath))
|
||||
if ((rdent->length() == len) && !core_strnicmp(rdent->c_str(), relpath, len))
|
||||
break;
|
||||
else
|
||||
++rdent;
|
||||
}
|
||||
|
||||
if (rdent == nullptr)
|
||||
if (directory->returned_dirlist.end() == rdent)
|
||||
{
|
||||
/* we've found a new directory; add this to returned_dirlist */
|
||||
rdent = new zippath_returned_directory;
|
||||
rdent->next = directory->returned_dirlist;
|
||||
rdent->name.assign(relpath, separator - relpath);
|
||||
directory->returned_dirlist = rdent;
|
||||
directory->returned_dirlist.emplace_front(relpath, separator - relpath);
|
||||
|
||||
/* ...and return it */
|
||||
memset(&directory->returned_entry, 0, sizeof(directory->returned_entry));
|
||||
directory->returned_entry.name = rdent->name.c_str();
|
||||
directory->returned_entry.name = directory->returned_dirlist.front().c_str();
|
||||
directory->returned_entry.type = ENTTYPE_DIR;
|
||||
result = &directory->returned_entry;
|
||||
}
|
||||
@ -1016,7 +998,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory)
|
||||
}
|
||||
}
|
||||
}
|
||||
while((relpath != nullptr) && (result == nullptr));
|
||||
while (relpath && !result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -454,9 +454,9 @@ ROM_END
|
||||
ROM_START( feagv11 )
|
||||
ROM_REGION( 0x20000, "maincpu", 0 )
|
||||
ROM_LOAD32_BYTE("16", 0x00000, 0x08000, CRC(8375d61f) SHA1(e042f6f01480c59ee09a458cf34f135664479824) ) // 27c256
|
||||
ROM_LOAD32_BYTE("17", 0x00001, 0x08000, CRC(bfd14916) SHA1(115af6dfd29ddd8ad6d2ce390f8ecc4d60de6fce) ) // "
|
||||
ROM_LOAD32_BYTE("18", 0x00002, 0x08000, CRC(9341dcaf) SHA1(686bd4799e89ffaf11a813d4cf5a2aedd4c2d97a) ) // "
|
||||
ROM_LOAD32_BYTE("19", 0x00003, 0x08000, CRC(a70c5468) SHA1(7f6b4f46577d5cfdaa84d387c7ce35d941e5bbc7) ) // "
|
||||
ROM_LOAD32_BYTE("17", 0x00001, 0x08000, CRC(bfd14916) SHA1(115af6dfd29ddd8ad6d2ce390f8ecc4d60de6fce) ) // "
|
||||
ROM_END
|
||||
|
||||
#define rom_feagv10 rom_feagv11
|
||||
|
@ -4086,13 +4086,13 @@ ROM_START( racedrivpan )
|
||||
ROM_LOAD16_BYTE( "088-1016.bin", 0x0e0000, 0x010000, CRC(e83a9c99) SHA1(1d4093902133bb6da981f294e6947544c3564393) ) // == 136077-1016.200y
|
||||
ROM_LOAD16_BYTE( "088-1015.bin", 0x0e0001, 0x010000, CRC(725806f3) SHA1(0fa4601465dc94f27c71db789ad625bbcd254169) ) // == 136077-4015.210y
|
||||
|
||||
ROM_REGION( 0x60000, "mainpcb:user1", 0 ) /* 384k for object ROM */
|
||||
ROM_LOAD16_BYTE( "088-1017.bin", 0x00000, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
|
||||
ROM_LOAD16_BYTE( "088-1018.bin", 0x00001, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
|
||||
ROM_LOAD16_BYTE( "088-1019.bin", 0x20000, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1020.bin", 0x20001, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1021.bin", 0x40000, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
|
||||
ROM_LOAD16_BYTE( "088-1022.bin", 0x40001, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
|
||||
ROM_REGION16_BE( 0x60000, "mainpcb:user1", 0 ) /* 384k for object ROM */
|
||||
ROM_LOAD16_BYTE( "088-1018.bin", 0x00000, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
|
||||
ROM_LOAD16_BYTE( "088-1017.bin", 0x00001, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
|
||||
ROM_LOAD16_BYTE( "088-1020.bin", 0x20000, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1019.bin", 0x20001, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1022.bin", 0x40000, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
|
||||
ROM_LOAD16_BYTE( "088-1021.bin", 0x40001, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
|
||||
|
||||
/* ----------------------- */
|
||||
|
||||
@ -4142,13 +4142,13 @@ ROM_START( racedrivpan )
|
||||
ROM_LOAD16_BYTE( "088-2016.bin", 0x0e0000, 0x010000, CRC(6a42b7e2) SHA1(2e0ff4b7e391106a976cb872f6311f6d35dca5b0) )
|
||||
ROM_LOAD16_BYTE( "088-2015.bin", 0x0e0001, 0x010000, CRC(334e2a3b) SHA1(a19bfa7652845b9453c722091c773819ba248569) )
|
||||
|
||||
ROM_REGION( 0x60000, "leftpcb:user1", 0 ) /* 384k for object ROM */
|
||||
ROM_LOAD16_BYTE( "088-1017.bin", 0x00000, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
|
||||
ROM_LOAD16_BYTE( "088-1018.bin", 0x00001, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
|
||||
ROM_LOAD16_BYTE( "088-1019.bin", 0x20000, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1020.bin", 0x20001, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1021.bin", 0x40000, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
|
||||
ROM_LOAD16_BYTE( "088-1022.bin", 0x40001, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
|
||||
ROM_REGION16_BE( 0x60000, "leftpcb:user1", 0 ) /* 384k for object ROM */
|
||||
ROM_LOAD16_BYTE( "088-1018.bin", 0x00000, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
|
||||
ROM_LOAD16_BYTE( "088-1017.bin", 0x00001, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
|
||||
ROM_LOAD16_BYTE( "088-1020.bin", 0x20000, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1019.bin", 0x20001, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1022.bin", 0x40000, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
|
||||
ROM_LOAD16_BYTE( "088-1021.bin", 0x40001, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
|
||||
|
||||
ROM_REGION( 0x800, "leftpcb:200e", 0 ) // set to display left monitor, controls not calibrated with valid values (don't think they need to be)
|
||||
ROM_LOAD( "leftpcb_200e", 0x000000, 0x000800, CRC(a618d02e) SHA1(cc1068fe4f6ec9a26b6e8fdbe05f4364a64559c1) )
|
||||
@ -4174,13 +4174,13 @@ ROM_START( racedrivpan )
|
||||
ROM_LOAD16_BYTE( "088-2016.bin", 0x0e0000, 0x010000, CRC(6a42b7e2) SHA1(2e0ff4b7e391106a976cb872f6311f6d35dca5b0) )
|
||||
ROM_LOAD16_BYTE( "088-2015.bin", 0x0e0001, 0x010000, CRC(334e2a3b) SHA1(a19bfa7652845b9453c722091c773819ba248569) )
|
||||
|
||||
ROM_REGION( 0x60000, "rightpcb:user1", 0 ) /* 384k for object ROM */
|
||||
ROM_LOAD16_BYTE( "088-1017.bin", 0x00000, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
|
||||
ROM_LOAD16_BYTE( "088-1018.bin", 0x00001, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
|
||||
ROM_LOAD16_BYTE( "088-1019.bin", 0x20000, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1020.bin", 0x20001, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1021.bin", 0x40000, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
|
||||
ROM_LOAD16_BYTE( "088-1022.bin", 0x40001, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
|
||||
ROM_REGION16_BE( 0x60000, "rightpcb:user1", 0 ) /* 384k for object ROM */
|
||||
ROM_LOAD16_BYTE( "088-1018.bin", 0x00000, 0x10000, CRC(11a0a8f5) SHA1(d4ccc83fc99331d741bc9b8027ef20d72e3ad71a) )
|
||||
ROM_LOAD16_BYTE( "088-1017.bin", 0x00001, 0x10000, CRC(d92251e8) SHA1(deeeec54c4a61c3adf62f6b1b910135559090ee5) )
|
||||
ROM_LOAD16_BYTE( "088-1020.bin", 0x20000, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) ) // == 136091-0020.2r (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1019.bin", 0x20001, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) ) // == 136091-0019.2k (strtdriv)
|
||||
ROM_LOAD16_BYTE( "088-1022.bin", 0x40000, 0x10000, CRC(4f1e1c5d) SHA1(3e72813129cae9e9bf084bfb1b747aa46b92591e) )
|
||||
ROM_LOAD16_BYTE( "088-1021.bin", 0x40001, 0x10000, CRC(ce8e4886) SHA1(d29cd4761deb80ed179d0e503243739eebc0edb4) )
|
||||
|
||||
ROM_REGION( 0x800, "rightpcb:200e", 0 ) // set to display right monitor, controls not calibrated with valid values (don't think they need to be)
|
||||
ROM_LOAD( "rightpcb_200e", 0x000000, 0x000800, CRC(6f1b7094) SHA1(6194a5b99aebe43f02c8d267290207b32c5bdbbd) )
|
||||
@ -4463,13 +4463,13 @@ ROM_START( strtdriv )
|
||||
ROM_REGION( 0x10000 + 0x10000, "mainpcb:asic65:asic65cpu", 0 ) /* dummy region for ADSP 2105 */
|
||||
ROM_LOAD( "136091-0033.10j", 0x000000, 0x010000, CRC(57504ab6) SHA1(ec8361b7da964c07ca0da48a87537badc3986fe0) )
|
||||
|
||||
ROM_REGION( 0x60000, "mainpcb:user1", 0 ) /* 384k for object ROM */
|
||||
ROM_LOAD16_BYTE( "136091-0017.2lm", 0x00000, 0x10000, CRC(b0454074) SHA1(9530ea1ef215116da1f0843776fa7a6b4637049d) )
|
||||
ROM_LOAD16_BYTE( "136091-0018.2t", 0x00001, 0x10000, CRC(ef432aa8) SHA1(56bce13c111db7874c9b669d479f6ef47976ee14) )
|
||||
ROM_LOAD16_BYTE( "136091-0019.2k", 0x20000, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) )
|
||||
ROM_LOAD16_BYTE( "136091-0020.2r", 0x20001, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) )
|
||||
ROM_LOAD16_BYTE( "136091-0021.2j", 0x40000, 0x10000, CRC(14f2caae) SHA1(ff40dbced58dc910a2b5825b846a5e52933cb8fc) )
|
||||
ROM_LOAD16_BYTE( "136091-0022.2p", 0x40001, 0x10000, CRC(bc4dd071) SHA1(ca182451a0a18d343dce1be56090d51950d43906) )
|
||||
ROM_REGION16_BE( 0x60000, "mainpcb:user1", 0 ) /* 384k for object ROM */
|
||||
ROM_LOAD16_BYTE( "136091-0018.2t", 0x00000, 0x10000, CRC(ef432aa8) SHA1(56bce13c111db7874c9b669d479f6ef47976ee14) )
|
||||
ROM_LOAD16_BYTE( "136091-0017.2lm", 0x00001, 0x10000, CRC(b0454074) SHA1(9530ea1ef215116da1f0843776fa7a6b4637049d) )
|
||||
ROM_LOAD16_BYTE( "136091-0020.2r", 0x20000, 0x10000, CRC(311cef99) SHA1(9c466aabad7e80581e477253ec6f2fd245f9b9fd) )
|
||||
ROM_LOAD16_BYTE( "136091-0019.2k", 0x20001, 0x10000, CRC(5bb00676) SHA1(cad1cea8e43f9590fc71c00fab4eff0d447f9296) )
|
||||
ROM_LOAD16_BYTE( "136091-0022.2p", 0x40000, 0x10000, CRC(bc4dd071) SHA1(ca182451a0a18d343dce1be56090d51950d43906) )
|
||||
ROM_LOAD16_BYTE( "136091-0021.2j", 0x40001, 0x10000, CRC(14f2caae) SHA1(ff40dbced58dc910a2b5825b846a5e52933cb8fc) )
|
||||
|
||||
ROM_REGION16_BE( 0x50000, "mainpcb:user3", 0 ) /* 256k for DSK ROMs + 64k for RAM */
|
||||
ROM_LOAD16_BYTE( "136091-0026.30e", 0x000000, 0x020000, CRC(47705109) SHA1(fa40275b71b74be8591282d2fba4215b98fc29c9) )
|
||||
@ -4519,13 +4519,13 @@ ROM_START( hdrivair )
|
||||
ROM_REGION( 0x10000 + 0x10000, "mainpcb:asic65:asic65cpu", 0 ) /* dummy region for ADSP 2105 */
|
||||
ROM_LOAD( "sboot.bin", 0x000000, 0x010000, CRC(cde4d010) SHA1(853f4b813ff70fe74cd87e92131c46fca045610d) )
|
||||
|
||||
ROM_REGION( 0xc0000, "mainpcb:user1", 0 ) /* 768k for object ROM */
|
||||
ROM_LOAD16_BYTE( "obj0l.bin", 0x00000, 0x20000, CRC(1f835f2e) SHA1(9d3419f2c1aa65ddfe9ace4e70ca1212d634afbf) )
|
||||
ROM_LOAD16_BYTE( "obj0h.bin", 0x00001, 0x20000, CRC(c321ab55) SHA1(e095e40bb1ebda7c9ff04a5086c10ab41dec2f16) )
|
||||
ROM_LOAD16_BYTE( "obj1l.bin", 0x40000, 0x20000, CRC(3d65f264) SHA1(e9232f5bf439bf4e1cf99cc7e81b7f9550563f15) )
|
||||
ROM_LOAD16_BYTE( "obj1h.bin", 0x40001, 0x20000, CRC(2c06b708) SHA1(daa16f727f2f500172f88b69d6931aa0fa13641b) )
|
||||
ROM_LOAD16_BYTE( "obj2l.bin", 0x80000, 0x20000, CRC(b206cc7e) SHA1(17f05e906c41b804fe99dd6cd8acbade919a6a10) )
|
||||
ROM_LOAD16_BYTE( "obj2h.bin", 0x80001, 0x20000, CRC(a666e98c) SHA1(90e380ff87538c7d557cf005a4a5bcedc250eb72) )
|
||||
ROM_REGION16_BE( 0xc0000, "mainpcb:user1", 0 ) /* 768k for object ROM */
|
||||
ROM_LOAD16_BYTE( "obj0h.bin", 0x00000, 0x20000, CRC(c321ab55) SHA1(e095e40bb1ebda7c9ff04a5086c10ab41dec2f16) )
|
||||
ROM_LOAD16_BYTE( "obj0l.bin", 0x00001, 0x20000, CRC(1f835f2e) SHA1(9d3419f2c1aa65ddfe9ace4e70ca1212d634afbf) )
|
||||
ROM_LOAD16_BYTE( "obj1h.bin", 0x40000, 0x20000, CRC(2c06b708) SHA1(daa16f727f2f500172f88b69d6931aa0fa13641b) )
|
||||
ROM_LOAD16_BYTE( "obj1l.bin", 0x40001, 0x20000, CRC(3d65f264) SHA1(e9232f5bf439bf4e1cf99cc7e81b7f9550563f15) )
|
||||
ROM_LOAD16_BYTE( "obj2h.bin", 0x80000, 0x20000, CRC(a666e98c) SHA1(90e380ff87538c7d557cf005a4a5bcedc250eb72) )
|
||||
ROM_LOAD16_BYTE( "obj2l.bin", 0x80001, 0x20000, CRC(b206cc7e) SHA1(17f05e906c41b804fe99dd6cd8acbade919a6a10) )
|
||||
|
||||
ROM_REGION16_BE( 0x140000, "mainpcb:user3", 0 )/* 1MB for DSK ROMs + 256k for RAM */
|
||||
ROM_LOAD16_BYTE( "dsk2phi.bin", 0x00000, 0x80000, CRC(71c268e0) SHA1(c089248a7dfadf2eba3134fe40ebb777c115a886) )
|
||||
@ -4582,13 +4582,13 @@ ROM_START( hdrivairp )
|
||||
ROM_REGION( 0x10000 + 0x10000, "mainpcb:asic65:asic65cpu", 0 ) /* dummy region for ADSP 2105 */
|
||||
ROM_LOAD( "xboota.bin", 0x10000 + 0x00000, 0x10000, CRC(d9c49901) SHA1(9f90ae3a47eb1ef00c3ec3661f60402c2eae2108) )
|
||||
|
||||
ROM_REGION( 0xc0000, "mainpcb:user1", 0 ) /* 768k for object ROM */
|
||||
ROM_LOAD16_BYTE( "objects.0l", 0x00000, 0x20000, CRC(3c9e9078) SHA1(f1daf32117236401f3cb97f332708632003e55f8) )
|
||||
ROM_LOAD16_BYTE( "objects.0h", 0x00001, 0x20000, CRC(4480dbae) SHA1(6a455173c38e80093f58bdc322cffcf25e70b6ae) )
|
||||
ROM_LOAD16_BYTE( "objects.1l", 0x40000, 0x20000, CRC(700bd978) SHA1(5cd63d4eee00d90fe29fb9697b6a0ea6b86704ae) )
|
||||
ROM_LOAD16_BYTE( "objects.1h", 0x40001, 0x20000, CRC(f613adaf) SHA1(9b9456e144a48fb73c5e084b33345667eed4905e) )
|
||||
ROM_LOAD16_BYTE( "objects.2l", 0x80000, 0x20000, CRC(e3b512f0) SHA1(080c5a21cb76edcb55d1c2488e9d91cf29cb0665) )
|
||||
ROM_LOAD16_BYTE( "objects.2h", 0x80001, 0x20000, CRC(3f83742b) SHA1(4b6e0134a806bcc9bd56432737047f86d0a16424) )
|
||||
ROM_REGION16_BE( 0xc0000, "mainpcb:user1", 0 ) /* 768k for object ROM */
|
||||
ROM_LOAD16_BYTE( "objects.0h", 0x00000, 0x20000, CRC(4480dbae) SHA1(6a455173c38e80093f58bdc322cffcf25e70b6ae) )
|
||||
ROM_LOAD16_BYTE( "objects.0l", 0x00001, 0x20000, CRC(3c9e9078) SHA1(f1daf32117236401f3cb97f332708632003e55f8) )
|
||||
ROM_LOAD16_BYTE( "objects.1h", 0x40000, 0x20000, CRC(f613adaf) SHA1(9b9456e144a48fb73c5e084b33345667eed4905e) )
|
||||
ROM_LOAD16_BYTE( "objects.1l", 0x40001, 0x20000, CRC(700bd978) SHA1(5cd63d4eee00d90fe29fb9697b6a0ea6b86704ae) )
|
||||
ROM_LOAD16_BYTE( "objects.2h", 0x80000, 0x20000, CRC(3f83742b) SHA1(4b6e0134a806bcc9bd56432737047f86d0a16424) )
|
||||
ROM_LOAD16_BYTE( "objects.2l", 0x80001, 0x20000, CRC(e3b512f0) SHA1(080c5a21cb76edcb55d1c2488e9d91cf29cb0665) )
|
||||
|
||||
ROM_REGION16_BE( 0x140000, "mainpcb:user3", 0 )/* 1MB for DSK ROMs + 256k for RAM */
|
||||
ROM_LOAD16_BYTE( "dskpics.hi", 0x00000, 0x80000, CRC(eaa88101) SHA1(ed0ebf8a9a9514d810242b9b552126f6717f9e25) )
|
||||
|
@ -2073,9 +2073,9 @@ static MACHINE_CONFIG_START( cdkong, cdkong_state )
|
||||
MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_hmcs40_state, display_decay_tick, attotime::from_msec(1))
|
||||
|
||||
MCFG_SCREEN_SVG_ADD("screen", "svg")
|
||||
MCFG_SCREEN_REFRESH_RATE(10)
|
||||
MCFG_SCREEN_SIZE(538, 1001)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, 537, 0, 1000)
|
||||
MCFG_SCREEN_REFRESH_RATE(50)
|
||||
MCFG_SCREEN_SIZE(559, 998)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, 558, 0, 997)
|
||||
MCFG_DEFAULT_LAYOUT(layout_svg)
|
||||
|
||||
/* sound hardware */
|
||||
@ -3967,8 +3967,8 @@ ROM_START( cdkong )
|
||||
ROM_LOAD( "hd38820a45", 0x0000, 0x1000, CRC(196b8070) SHA1(da85d1eb4b048b77f3168630662ab94ec9baa262) )
|
||||
ROM_CONTINUE( 0x1e80, 0x0100 )
|
||||
|
||||
ROM_REGION( 714102, "svg", 0)
|
||||
ROM_LOAD( "cdkong.svg", 0, 714102, CRC(184bbe69) SHA1(98554341054246e5d76e0779620498e6cb723958) )
|
||||
ROM_REGION( 359199, "svg", 0)
|
||||
ROM_LOAD( "cdkong.svg", 0, 359199, CRC(ba159fd5) SHA1(3188e2ed3234f39ac9ee93a485a7e73314bc3457) ) // version 8 april 2016. by Rik, kevtris
|
||||
ROM_END
|
||||
|
||||
|
||||
|
@ -136,103 +136,6 @@ static GFXDECODE_START( intvkbd )
|
||||
GFXDECODE_ENTRY( "gfx1", 0x0000, intvkbd_charlayout, 0, 256 )
|
||||
GFXDECODE_END
|
||||
|
||||
static INPUT_PORTS_START( intv )
|
||||
|
||||
/* Left Player Controller */
|
||||
PORT_START("KEYPAD1")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/1") PORT_CODE(KEYCODE_1_PAD)
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/2") PORT_CODE(KEYCODE_2_PAD)
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/3") PORT_CODE(KEYCODE_3_PAD)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/4") PORT_CODE(KEYCODE_4_PAD)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/5") PORT_CODE(KEYCODE_5_PAD)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/6") PORT_CODE(KEYCODE_6_PAD)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/7") PORT_CODE(KEYCODE_7_PAD)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/8") PORT_CODE(KEYCODE_8_PAD)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/9") PORT_CODE(KEYCODE_9_PAD)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/Clear") PORT_CODE(KEYCODE_DEL_PAD)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/0") PORT_CODE(KEYCODE_0_PAD)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left/Enter") PORT_CODE(KEYCODE_ENTER_PAD)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Left/Upper") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Left/Lower-Left") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Left/Lower-Right") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
|
||||
PORT_START("DISC1")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("Left/Up") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Up-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Right-Up-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Left/Right") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Right-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Down-Down-Right") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("Left/Down") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Down-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Left-Down-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Left/Left") PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Left-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left/Up-Up-Left") PORT_CONDITION("OPTIONS",0x01,EQUALS,0x00)
|
||||
|
||||
PORT_START("DISCX1")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("Left/X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_LEFT) PORT_CODE_INC(KEYCODE_RIGHT) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
|
||||
|
||||
PORT_START("DISCY1")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("Left/Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_UP) PORT_CODE_INC(KEYCODE_DOWN) PORT_PLAYER(1) PORT_CONDITION("OPTIONS",0x01,EQUALS,0x01)
|
||||
|
||||
/* Right Player Controller */
|
||||
PORT_START("KEYPAD2")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/1")
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/2")
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/3")
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/4")
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/5")
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/6")
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/7")
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/8")
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/9")
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/Clear")
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/0")
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right/Enter")
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Right/Upper") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Right/Lower-Left") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Right/Lower-Right") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
|
||||
PORT_START("DISC2")
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("Right/Up") PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Up-Up-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Up-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Right-Up-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Right/Right") PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Right-Down-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Down-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Down-Down-Right") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("Right/Down") PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Down-Down-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Down-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Left-Down-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Right/Left") PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Left-Up-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Up-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right/Up-Up-Left") PORT_CONDITION("OPTIONS",0x02,EQUALS,0x00)
|
||||
|
||||
PORT_START("DISCX2")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_X ) PORT_NAME("Right/X") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_D) PORT_CODE_INC(KEYCODE_G) PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x02)
|
||||
|
||||
PORT_START("DISCY2")
|
||||
PORT_BIT( 0xff, 0x50, IPT_AD_STICK_Y ) PORT_NAME("Right/Y") PORT_MINMAX(0x00,0x9f) PORT_SENSITIVITY(100) PORT_KEYDELTA(0x50) PORT_CODE_DEC(KEYCODE_R) PORT_CODE_INC(KEYCODE_F) PORT_PLAYER(2) PORT_CONDITION("OPTIONS",0x02,EQUALS,0x02)
|
||||
|
||||
PORT_START("OPTIONS")
|
||||
PORT_CONFNAME( 0x01, 0x00, "Left Disc" )
|
||||
PORT_CONFSETTING( 0x00, "Digital" )
|
||||
PORT_CONFSETTING( 0x01, "Analog" )
|
||||
PORT_CONFNAME( 0x02, 0x00, "Right Disc" )
|
||||
PORT_CONFSETTING( 0x00, "Digital" )
|
||||
PORT_CONFSETTING( 0x02, "Analog" )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
/*
|
||||
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
|
||||
@ -370,11 +273,6 @@ static INPUT_PORTS_START( intvkbd )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD)
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD)
|
||||
|
||||
/* 2008-05 FP: I include here the controller inputs to make happy the read_handler.
|
||||
Please remove this (and re-tag accordingly the inputs above) if intv_right_control_r
|
||||
is supposed to scan the keyboard inputs when the Keyboard Component is connected */
|
||||
PORT_INCLUDE( intv )
|
||||
INPUT_PORTS_END
|
||||
|
||||
static ADDRESS_MAP_START( intv_mem, AS_PROGRAM, 16, intv_state )
|
||||
@ -551,7 +449,6 @@ INTERRUPT_GEN_MEMBER(intv_state::intv_interrupt2)
|
||||
timer_set(m_keyboard->cycles_to_attotime(100), TIMER_INTV_INTERRUPT2_COMPLETE);
|
||||
}
|
||||
|
||||
|
||||
static MACHINE_CONFIG_START( intv, intv_state )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD("maincpu", CP1610, XTAL_3_579545MHz/4) /* Colorburst/4 */
|
||||
@ -574,11 +471,14 @@ static MACHINE_CONFIG_START( intv, intv_state )
|
||||
MCFG_PALETTE_INDIRECT_ENTRIES(32)
|
||||
MCFG_PALETTE_INIT_OWNER(intv_state, intv)
|
||||
|
||||
MCFG_INTV_CONTROL_PORT_ADD("iopt_right_ctrl", intv_control_port_devices, "handctrl")
|
||||
MCFG_INTV_CONTROL_PORT_ADD("iopt_left_ctrl", intv_control_port_devices, "handctrl")
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD("ay8914", AY8914, XTAL_3_579545MHz/2)
|
||||
MCFG_AY8910_PORT_A_READ_CB(READ8(intv_state, intv_right_control_r))
|
||||
MCFG_AY8910_PORT_B_READ_CB(READ8(intv_state, intv_left_control_r))
|
||||
MCFG_AY8910_PORT_A_READ_CB(DEVREAD8("iopt_right_ctrl", intv_control_port_device, ctrl_r))
|
||||
MCFG_AY8910_PORT_B_READ_CB(DEVREAD8("iopt_left_ctrl", intv_control_port_device, ctrl_r))
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.33)
|
||||
|
||||
/* cartridge */
|
||||
@ -743,11 +643,11 @@ DRIVER_INIT_MEMBER(intv_state,intvkbd)
|
||||
***************************************************************************/
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
|
||||
CONS( 1979, intv, 0, 0, intv, intv, intv_state, intv, "Mattel", "Intellivision", MACHINE_SUPPORTS_SAVE )
|
||||
CONS( 1981, intvsrs, intv, 0, intv, intv, intv_state, intv, "Sears", "Super Video Arcade", MACHINE_SUPPORTS_SAVE )
|
||||
CONS( 1979, intv, 0, 0, intv, 0, intv_state, intv, "Mattel", "Intellivision", MACHINE_SUPPORTS_SAVE )
|
||||
CONS( 1981, intvsrs, intv, 0, intv, 0, intv_state, intv, "Sears", "Super Video Arcade", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1981, intvkbd, intv, 0, intvkbd, intvkbd, intv_state, intvkbd, "Mattel", "Intellivision Keyboard Component (Unreleased)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
|
||||
CONS( 1982, intv2, intv, 0, intv2, intv, intv_state, intv, "Mattel", "Intellivision II", MACHINE_SUPPORTS_SAVE )
|
||||
CONS( 1982, intv2, intv, 0, intv2, 0, intv_state, intv, "Mattel", "Intellivision II", MACHINE_SUPPORTS_SAVE )
|
||||
|
||||
// made up, user friendlier machines with pre-mounted passthu expansions
|
||||
COMP( 1982, intvoice, intv, 0, intvoice, intv, intv_state, intv, "Mattel", "Intellivision w/IntelliVoice expansion", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1983, intvecs, intv, 0, intvecs, intv, intv_state, intv, "Mattel", "Intellivision w/Entertainment Computer System + Intellivoice expansions", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1982, intvoice, intv, 0, intvoice, 0, intv_state, intv, "Mattel", "Intellivision w/IntelliVoice expansion", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1983, intvecs, intv, 0, intvecs, 0, intv_state, intv, "Mattel", "Intellivision w/Entertainment Computer System + Intellivoice expansions", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -7561,6 +7561,30 @@ ROM_START( kf2k3pcb ) /* Encrypted Set, JAMMA PCB */
|
||||
ROM_END
|
||||
|
||||
|
||||
|
||||
ROM_START( unkneo )
|
||||
ROM_REGION( 0x100000, "maincpu", 0 )
|
||||
ROM_LOAD16_BYTE( "EP1.bin", 0x000001, 0x080000, CRC(f353448c) SHA1(f0f966ca15d503e01b40e901765ff0888463b65d) )
|
||||
ROM_LOAD16_BYTE( "EP2.bin", 0x000000, 0x080000, CRC(f25c71ad) SHA1(803fb6cd6a7ada59678ad901ff9788b1e54ddd0c) )
|
||||
|
||||
NEO_SFIX_128K( "s1.s1", CRC(706477a7) SHA1(8cbee7f6832e7edd2dc792ca330420a6a984b879) ) // was a dead AXS512PC 512KB sram card, this data is handcrafted to make the set usable (hence BAD_DUMP)
|
||||
|
||||
NEOGEO_BIOS
|
||||
ROM_REGION( 0x20000, "audiobios", 0 )
|
||||
ROM_LOAD( "sm1.sm1", 0x00000, 0x20000, CRC(94416d67) SHA1(42f9d7ddd6c0931fd64226a60dc73602b2819dcf) )
|
||||
ROM_REGION( 0x30000, "audiocpu", ROMREGION_ERASE00 )
|
||||
/* not present */
|
||||
|
||||
ROM_REGION( 0x400000, "ymsnd", 0 )
|
||||
ROM_LOAD( "sram.v1", 0x000000, 0x200000, NO_DUMP ) // was a dead AXS2000PC 2MB sram card, battery dead, data lost.
|
||||
|
||||
NO_DELTAT_REGION
|
||||
|
||||
ROM_REGION( 0x2000000, "sprites", 0 )
|
||||
ROM_LOAD16_BYTE( "no3.bin", 0x000000, 0x1000000, CRC(81821826) SHA1(b7c1a53e32633383675206a16c68f6f2ff984865) )
|
||||
ROM_LOAD16_BYTE( "no4.bin", 0x000001, 0x1000000, CRC(3601d568) SHA1(800323e52f5d33b402f84d31850b42c688082d67) )
|
||||
ROM_END
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Bootleg sets
|
||||
@ -9902,6 +9926,8 @@ GAME( 1995, marukodq, neogeo, neogeo_noslot, neogeo, neogeo_state, neoge
|
||||
GAME( 1995, doubledr, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Technos Japan", "Double Dragon (Neo-Geo)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1995, gowcaizr, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Technos Japan", "Voltage Fighter - Gowcaizer / Choujin Gakuen Gowcaizer", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1996, sdodgeb, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Technos Japan", "Super Dodge Ball / Kunio no Nekketsu Toukyuu Densetsu", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 199?, unkneo, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Technos Japan?", "Unknown Neo-Geo Vs. Fighter (prototype)", MACHINE_SUPPORTS_SAVE ) // same ID code as Voltage Fighter Gowkaizer so probably by Technos
|
||||
|
||||
|
||||
/* Tecmo */
|
||||
GAME( 1996, tws96, neogeo, neogeo_noslot, neogeo, neogeo_state, neogeo, ROT0, "Tecmo", "Tecmo World Soccer '96", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -2150,21 +2150,22 @@ ROM_START( cluclu )
|
||||
PALETTE_2C04_0004
|
||||
ROM_END
|
||||
|
||||
ROM_START( excitebk ) /* EB4-4 A = Excite Bike, Palette 4, rev A */
|
||||
|
||||
ROM_START( excitebk ) /* EB4-3 = Excite Bike, Palette 3, revision 'E' */
|
||||
ROM_REGION( 0x10000,"maincpu", 0 ) /* 6502 memory */
|
||||
ROM_LOAD( "mds-eb4-4 a.6d", 0x8000, 0x2000, CRC(6aa87037) SHA1(f3313700955498800a3d59c523ba2a4e0cf443bc) )
|
||||
ROM_LOAD( "mds-eb4-4 a.6c", 0xa000, 0x2000, CRC(bdb317db) SHA1(a8b3e8deb1e625d764aaffe86a513bc7ede51a46) )
|
||||
ROM_LOAD( "mds-eb4-4 a.6b", 0xc000, 0x2000, CRC(d1afe2dd) SHA1(ef0f44d98464b7dab7c51be4379242f7a4e4fcdd) )
|
||||
ROM_LOAD( "mds-eb4-4 a.6a", 0xe000, 0x2000, CRC(46711d0e) SHA1(6ce2f395b3f407671a87c6e1133ab63a637022f2) )
|
||||
ROM_LOAD( "mds-eb4-3e.1d", 0x8000, 0x2000, CRC(f58a392e) SHA1(ca721e47e5dbe72d6f231d9b20b1ca33304c5370) )
|
||||
ROM_LOAD( "mds-eb4-3e.1c", 0xa000, 0x2000, CRC(6ae01102) SHA1(f3f49644f7e2887e14655e8934c7c75d4b92968e) )
|
||||
ROM_LOAD( "mds-eb4-3e.1b", 0xc000, 0x2000, CRC(fbc53465) SHA1(81c9ebac895dfbc5c451b4b32e5990aba3734714) )
|
||||
ROM_LOAD( "mds-eb4-3e.1a", 0xe000, 0x2000, CRC(e2902b4e) SHA1(f559517c735847e2ad622418b8fa525d9c9adac3) )
|
||||
|
||||
ROM_REGION( 0x4000,"gfx1", 0 ) /* PPU memory */
|
||||
ROM_LOAD( "mds-eb4-4 a.8b", 0x0000, 0x2000, CRC(62a76c52) SHA1(7ebd0dac976abe8636f4f75a3b2a473d7a54934d) )
|
||||
ROM_LOAD( "mds-eb4-4 a.8a", 0x2000, 0x2000, CRC(a9b49a05) SHA1(c14706e6a5524f81e79c101e32deef9f3d60de3f) )
|
||||
ROM_LOAD( "mds-eb4-3e.2b", 0x0000, 0x2000, CRC(80be1f50) SHA1(d8544b9a0a9d8719ab601fa9c68c4305385b14c7) )
|
||||
ROM_LOAD( "mds-eb4-3e.2a", 0x2000, 0x2000, CRC(001e8e0b) SHA1(c4c2a11ade7788bac9dd61ea8de319c4111d2592) )
|
||||
|
||||
PALETTE_2C04_0004
|
||||
PALETTE_2C04_0003
|
||||
ROM_END
|
||||
|
||||
ROM_START( excitebka ) /* EB4-3 = Excite Bike, Palette 3, unknown revision */
|
||||
ROM_START( excitebko ) /* EB4-3 = Excite Bike, Palette 3, unknown revision */
|
||||
ROM_REGION( 0x10000,"maincpu", 0 ) /* 6502 memory */
|
||||
ROM_LOAD( "mds-eb4-3.1d", 0x8000, 0x2000, CRC(7e54df1d) SHA1(38d878041976386e8608c73133040b18d0e4b9cd) ) /* Need to verify correct label */
|
||||
ROM_LOAD( "mds-eb4-3.1c", 0xa000, 0x2000, CRC(89baae91) SHA1(6aebf13c415e3246edf7daa847533b7e3ae0425f) ) /* Need to verify correct label */
|
||||
@ -2178,6 +2179,20 @@ ROM_START( excitebka ) /* EB4-3 = Excite Bike, Palette 3, unknown revision */
|
||||
PALETTE_2C04_0003
|
||||
ROM_END
|
||||
|
||||
ROM_START( excitebkj ) /* EB4-4 A = Excite Bike, Palette 4, rev A */
|
||||
ROM_REGION( 0x10000,"maincpu", 0 ) /* 6502 memory */
|
||||
ROM_LOAD( "mds-eb4-4 a.6d", 0x8000, 0x2000, CRC(6aa87037) SHA1(f3313700955498800a3d59c523ba2a4e0cf443bc) )
|
||||
ROM_LOAD( "mds-eb4-4 a.6c", 0xa000, 0x2000, CRC(bdb317db) SHA1(a8b3e8deb1e625d764aaffe86a513bc7ede51a46) )
|
||||
ROM_LOAD( "mds-eb4-4 a.6b", 0xc000, 0x2000, CRC(d1afe2dd) SHA1(ef0f44d98464b7dab7c51be4379242f7a4e4fcdd) )
|
||||
ROM_LOAD( "mds-eb4-4 a.6a", 0xe000, 0x2000, CRC(46711d0e) SHA1(6ce2f395b3f407671a87c6e1133ab63a637022f2) )
|
||||
|
||||
ROM_REGION( 0x4000,"gfx1", 0 ) /* PPU memory */
|
||||
ROM_LOAD( "mds-eb4-4 a.8b", 0x0000, 0x2000, CRC(62a76c52) SHA1(7ebd0dac976abe8636f4f75a3b2a473d7a54934d) )
|
||||
ROM_LOAD( "mds-eb4-4 a.8a", 0x2000, 0x2000, CRC(a9b49a05) SHA1(c14706e6a5524f81e79c101e32deef9f3d60de3f) )
|
||||
|
||||
PALETTE_2C04_0004
|
||||
ROM_END
|
||||
|
||||
ROM_START( jajamaru )
|
||||
ROM_REGION( 0x10000,"maincpu", 0 ) /* 6502 memory */
|
||||
ROM_LOAD( "10.bin", 0x8000, 0x2000, CRC(16af1704) SHA1(ebcf9ad06e302c51ee4432631a6b0fb85a9630ed) )
|
||||
@ -2787,8 +2802,9 @@ GAME( 1985, starlstr, 0, vsnes, starlstr, vsnes_state, vsnormal, ROT0,
|
||||
GAME( 1987, cstlevna, 0, vsnes, cstlevna, vsnes_state, vsvram, ROT0, "Konami", "Vs. Castlevania", 0 )
|
||||
GAME( 1984, cluclu, 0, vsnes, cluclu, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Clu Clu Land", 0 )
|
||||
GAME( 1990, drmario, 0, vsnes, drmario, vsnes_state, drmario, ROT0, "Nintendo", "Vs. Dr. Mario", 0 )
|
||||
GAME( 1984, excitebk, 0, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-4 A)", 0 )
|
||||
GAME( 1984, excitebka,excitebk, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 ?)", 0 )
|
||||
GAME( 1984, excitebk, 0, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 E)", 0 )
|
||||
GAME( 1984, excitebko,excitebk, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 ?)", 0 ) // older
|
||||
GAME( 1984, excitebkj,excitebk, vsnes, excitebk, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-4 A)", 0 ) // likely Japan
|
||||
GAME( 1986, goonies, 0, vsnes, goonies, vsnes_state, vskonami, ROT0, "Konami", "Vs. The Goonies (set E)", 0 )
|
||||
GAME( 1984, iceclimb, 0, vsnes, iceclmbj, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Ice Climber (set IC4-4 B-1)", 0 )
|
||||
GAME( 1984, iceclimba,iceclimb, vsnes, iceclimb, vsnes_state, vsnormal, ROT0, "Nintendo", "Vs. Ice Climber (set IC4-4 ?)", 0 )
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include "bus/intv/ecs.h"
|
||||
//#include "bus/intv/keycomp.h"
|
||||
|
||||
#include "bus/intv_ctrl/ctrl.h"
|
||||
#include "bus/intv_ctrl/handctrl.h"
|
||||
|
||||
#include "bus/generic/slot.h"
|
||||
#include "bus/generic/carts.h"
|
||||
|
||||
@ -43,7 +46,6 @@ public:
|
||||
m_iocart2(*this, "ioslot2"),
|
||||
m_region_maincpu(*this, "maincpu"),
|
||||
m_region_keyboard(*this, "keyboard"),
|
||||
m_io_options(*this, "OPTIONS"),
|
||||
m_io_test(*this, "TEST"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_palette(*this, "palette")
|
||||
@ -118,19 +120,13 @@ protected:
|
||||
optional_device<generic_slot_device> m_iocart2;
|
||||
required_memory_region m_region_maincpu;
|
||||
optional_memory_region m_region_keyboard;
|
||||
required_ioport m_io_options;
|
||||
optional_ioport m_io_test;
|
||||
|
||||
optional_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
ioport_port *m_keypad[4];
|
||||
ioport_port *m_disc[4];
|
||||
ioport_port *m_discx[4];
|
||||
ioport_port *m_discy[4];
|
||||
ioport_port *m_intv_keyboard[10];
|
||||
|
||||
UINT8 intv_control_r(int hand);
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
};
|
||||
|
||||
|
@ -326,28 +326,6 @@ void intv_state::machine_reset()
|
||||
|
||||
void intv_state::machine_start()
|
||||
{
|
||||
// TODO: split these for intvkbd & intvecs??
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
char str[8];
|
||||
sprintf(str, "KEYPAD%i", i + 1);
|
||||
m_keypad[i] = ioport(str);
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
char str[6];
|
||||
sprintf(str, "DISC%i", i + 1);
|
||||
m_disc[i] = ioport(str);
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
char str[7];
|
||||
sprintf(str, "DISCX%i", i + 1);
|
||||
m_discx[i] = ioport(str);
|
||||
sprintf(str, "DISCY%i", i + 1);
|
||||
m_discy[i] = ioport(str);
|
||||
}
|
||||
|
||||
save_item(NAME(m_bus_copy_mode));
|
||||
save_item(NAME(m_backtab_row));
|
||||
save_item(NAME(m_ram16));
|
||||
@ -459,74 +437,3 @@ INTERRUPT_GEN_MEMBER(intv_state::intv_interrupt)
|
||||
m_stic->screenrefresh();
|
||||
}
|
||||
|
||||
/* hand 0 == left, 1 == right, 2 == ECS hand controller 1, 3 == ECS hand controller 2 */
|
||||
UINT8 intv_state::intv_control_r(int hand)
|
||||
{
|
||||
static const UINT8 keypad_table[] =
|
||||
{
|
||||
0xFF, 0x3F, 0x9F, 0x5F, 0xD7, 0xB7, 0x77, 0xDB,
|
||||
0xBB, 0x7B, 0xDD, 0xBD, 0x7D, 0xDE, 0xBE, 0x7E
|
||||
};
|
||||
|
||||
static const UINT8 disc_table[] =
|
||||
{
|
||||
0xF3, 0xE3, 0xE7, 0xF7, 0xF6, 0xE6, 0xEE, 0xFE,
|
||||
0xFC, 0xEC, 0xED, 0xFD, 0xF9, 0xE9, 0xEB, 0xFB
|
||||
};
|
||||
|
||||
static const UINT8 discyx_table[5][5] =
|
||||
{
|
||||
{ 0xE3, 0xF3, 0xFB, 0xEB, 0xE9 },
|
||||
{ 0xE7, 0xE3, 0xFB, 0xE9, 0xF9 },
|
||||
{ 0xF7, 0xF7, 0xFF, 0xFD, 0xFD },
|
||||
{ 0xF6, 0xE6, 0xFE, 0xEC, 0xED },
|
||||
{ 0xE6, 0xEE, 0xFE, 0xFC, 0xEC }
|
||||
};
|
||||
|
||||
int x, y;
|
||||
UINT8 rv = 0xFF;
|
||||
|
||||
/* keypad */
|
||||
x = m_keypad[hand]->read();
|
||||
for (y = 0; y < 16; y++)
|
||||
{
|
||||
if (x & (1 << y))
|
||||
{
|
||||
rv &= keypad_table[y];
|
||||
}
|
||||
}
|
||||
|
||||
switch ((m_io_options->read() >> hand) & 1)
|
||||
{
|
||||
case 0: /* disc == digital */
|
||||
default:
|
||||
|
||||
x = m_disc[hand]->read();
|
||||
for (y = 0; y < 16; y++)
|
||||
{
|
||||
if (x & (1 << y))
|
||||
{
|
||||
rv &= disc_table[y];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* disc == _fake_ analog */
|
||||
|
||||
x = m_discx[hand]->read();
|
||||
y = m_discy[hand]->read();
|
||||
rv &= discyx_table[y / 32][x / 32];
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
READ8_MEMBER( intv_state::intv_left_control_r )
|
||||
{
|
||||
return intv_control_r(0);
|
||||
}
|
||||
|
||||
READ8_MEMBER( intv_state::intv_right_control_r )
|
||||
{
|
||||
return intv_control_r(1);
|
||||
}
|
||||
|
@ -28029,6 +28029,7 @@ garoup // 0253 (c) 1999 SNK
|
||||
ghostlop // 0228 GhostLop (prototype) 1996? Data East
|
||||
goalx3 // 0209 (c) 1995 Visco
|
||||
gowcaizr // 0094 (c) 1995 Technos
|
||||
unkneo // prototype
|
||||
gpilots // 0020 (c) 1991 SNK
|
||||
gpilotsh // 0020 (c) 1991 SNK
|
||||
gururin // 0067 (c) 1994 Face
|
||||
@ -35819,7 +35820,8 @@ cstlevna // (c) 1987 Konami licensed to Nintendo
|
||||
drmario // (c) 1990 Nintendo
|
||||
duckhunt // (c) 1985 Nintendo
|
||||
excitebk // (c) 1984 Nintendo
|
||||
excitebka // (c) 1984 Nintendo
|
||||
excitebko // (c) 1984 Nintendo
|
||||
excitebkj // (c) 1984 Nintendo
|
||||
goonies // (c) 1986 Konami
|
||||
hogalley // (c) 1985 Nintendo
|
||||
iceclimb // (c) 1984 Nintendo
|
||||
|
29
src/osd/modules/ipc/raw_tcp_connection.cpp
Normal file
29
src/osd/modules/ipc/raw_tcp_connection.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#include "raw_tcp_connection.h"
|
||||
|
||||
/* Instance methods. */
|
||||
|
||||
raw_tcp_connection::raw_tcp_connection(listener* listener, size_t bufferSize) :
|
||||
tcp_connection(bufferSize),
|
||||
m_listener(listener)
|
||||
{
|
||||
}
|
||||
|
||||
raw_tcp_connection::~raw_tcp_connection()
|
||||
{
|
||||
}
|
||||
|
||||
void raw_tcp_connection::user_on_tcp_connection_read()
|
||||
{
|
||||
// We may receive multiple packets in the same TCP chunk. If one of them is
|
||||
// a DTLS Close Alert this would be closed (close() called) so we cannot call
|
||||
// our listeners anymore.
|
||||
if (is_closing())
|
||||
return;
|
||||
|
||||
m_listener->on_data_recv(this, m_buffer, m_buffer_data_len);
|
||||
|
||||
m_buffer_data_len = 0;
|
||||
}
|
30
src/osd/modules/ipc/raw_tcp_connection.h
Normal file
30
src/osd/modules/ipc/raw_tcp_connection.h
Normal file
@ -0,0 +1,30 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#ifndef RAW_TCP_CONNECTION_H
|
||||
#define RAW_TCP_CONNECTION_H
|
||||
|
||||
#include "tcp_connection.h"
|
||||
|
||||
|
||||
class raw_tcp_connection : public tcp_connection
|
||||
{
|
||||
public:
|
||||
class listener
|
||||
{
|
||||
public:
|
||||
virtual ~listener(){ }
|
||||
virtual void on_data_recv(raw_tcp_connection *connection, const uint8_t* data, size_t len) = 0;
|
||||
};
|
||||
|
||||
raw_tcp_connection(listener* listener, size_t bufferSize);
|
||||
virtual ~raw_tcp_connection();
|
||||
|
||||
/* Pure virtual methods inherited from tcp_connection. */
|
||||
virtual void user_on_tcp_connection_read() override;
|
||||
|
||||
private:
|
||||
// Passed by argument.
|
||||
listener* m_listener;
|
||||
};
|
||||
#endif
|
42
src/osd/modules/ipc/raw_tcp_server.cpp
Normal file
42
src/osd/modules/ipc/raw_tcp_server.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#include "raw_tcp_server.h"
|
||||
#include <string>
|
||||
|
||||
#define MAX_TCP_CONNECTIONS_PER_SERVER 10
|
||||
|
||||
/* Instance methods. */
|
||||
|
||||
raw_tcp_server::raw_tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog, listener* listener, raw_tcp_connection::listener* connListener) :
|
||||
tcp_server(loop, ip, port, backlog),
|
||||
m_listener(listener),
|
||||
m_conn_listener(connListener)
|
||||
{
|
||||
}
|
||||
|
||||
void raw_tcp_server::user_on_tcp_connection_alloc(tcp_connection** connection)
|
||||
{
|
||||
// Allocate a new raw_tcp_connection for the raw_tcp_server to handle it.
|
||||
*connection = new raw_tcp_connection(m_conn_listener, 65536);
|
||||
}
|
||||
|
||||
void raw_tcp_server::user_on_new_tcp_connection(tcp_connection* connection)
|
||||
{
|
||||
// Allow just MAX_TCP_CONNECTIONS_PER_SERVER.
|
||||
if (get_num_connections() > MAX_TCP_CONNECTIONS_PER_SERVER)
|
||||
connection->close();
|
||||
}
|
||||
|
||||
void raw_tcp_server::user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer)
|
||||
{
|
||||
// Notify the listener.
|
||||
// NOTE: Don't do it if closing (since at this point the listener is already freed).
|
||||
// At the end, this is just called if the connection was remotely closed.
|
||||
if (!is_closing())
|
||||
m_listener->on_raw_tcp_connection_closed(this, static_cast<raw_tcp_connection*>(connection), is_closed_by_peer);
|
||||
}
|
||||
|
||||
void raw_tcp_server::user_on_tcp_server_closed()
|
||||
{
|
||||
}
|
36
src/osd/modules/ipc/raw_tcp_server.h
Normal file
36
src/osd/modules/ipc/raw_tcp_server.h
Normal file
@ -0,0 +1,36 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#ifndef RAW_TCP_SERVER_H
|
||||
#define RAW_TCP_SERVER_H
|
||||
|
||||
#include "tcp_server.h"
|
||||
#include "tcp_connection.h"
|
||||
#include "raw_tcp_connection.h"
|
||||
#include <uv.h>
|
||||
|
||||
class raw_tcp_server : public tcp_server
|
||||
{
|
||||
public:
|
||||
class listener
|
||||
{
|
||||
public:
|
||||
virtual ~listener() { }
|
||||
virtual void on_raw_tcp_connection_closed(raw_tcp_server* tcpServer, raw_tcp_connection* connection, bool is_closed_by_peer) = 0;
|
||||
};
|
||||
|
||||
raw_tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog, listener* listener, raw_tcp_connection::listener* connListener);
|
||||
|
||||
/* Pure virtual methods inherited from TCPServer. */
|
||||
virtual void user_on_tcp_connection_alloc(tcp_connection** connection) override;
|
||||
virtual void user_on_new_tcp_connection(tcp_connection* connection) override;
|
||||
virtual void user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) override;
|
||||
virtual void user_on_tcp_server_closed() override;
|
||||
|
||||
private:
|
||||
// Passed by argument.
|
||||
listener* m_listener;
|
||||
raw_tcp_connection::listener* m_conn_listener;
|
||||
};
|
||||
|
||||
#endif
|
150
src/osd/modules/ipc/rtc_tcp_connection.cpp
Normal file
150
src/osd/modules/ipc/rtc_tcp_connection.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
#include "emu.h"
|
||||
#include "rtc_tcp_connection.h"
|
||||
|
||||
/* Instance methods. */
|
||||
|
||||
rtc_tcp_connection::rtc_tcp_connection(listener* listener, size_t bufferSize) :
|
||||
tcp_connection(bufferSize),
|
||||
m_listener(listener),
|
||||
m_frame_start(0)
|
||||
{
|
||||
}
|
||||
|
||||
rtc_tcp_connection::~rtc_tcp_connection()
|
||||
{
|
||||
}
|
||||
|
||||
inline uint16_t get2bytes(const uint8_t* data, size_t i)
|
||||
{
|
||||
return (uint16_t)(data[i + 1]) | ((uint16_t)(data[i])) << 8;
|
||||
}
|
||||
|
||||
inline void set2bytes(uint8_t* data, size_t i, uint16_t value)
|
||||
{
|
||||
data[i + 1] = (uint8_t)(value);
|
||||
data[i] = (uint8_t)(value >> 8);
|
||||
}
|
||||
|
||||
|
||||
void rtc_tcp_connection::user_on_tcp_connection_read()
|
||||
{
|
||||
/*
|
||||
* Framing RFC 4571
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* ---------------------------------------------------------------
|
||||
* | LENGTH | STUN / DTLS / RTP / RTCP |
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* A 16-bit unsigned integer LENGTH field, coded in network byte order
|
||||
* (big-endian), begins the frame. If LENGTH is non-zero, an RTP or
|
||||
* RTCP packet follows the LENGTH field. The value coded in the LENGTH
|
||||
* field MUST equal the number of octets in the RTP or RTCP packet.
|
||||
* Zero is a valid value for LENGTH, and it codes the null packet.
|
||||
*/
|
||||
|
||||
// Be ready to parse more than a single frame in a single TCP chunk.
|
||||
while (true)
|
||||
{
|
||||
// We may receive multiple packets in the same TCP chunk. If one of them is
|
||||
// a DTLS Close Alert this would be closed (Close() called) so we cannot call
|
||||
// our listeners anymore.
|
||||
if (is_closing())
|
||||
return;
|
||||
|
||||
size_t data_len = m_buffer_data_len - m_frame_start;
|
||||
size_t packet_len = 0;
|
||||
|
||||
if (data_len >= 2)
|
||||
packet_len = (size_t)get2bytes(m_buffer + m_frame_start, 0);
|
||||
|
||||
// We have packet_len bytes.
|
||||
if ((data_len >= 2) && data_len >= 2 + packet_len)
|
||||
{
|
||||
const uint8_t* packet = m_buffer + m_frame_start + 2;
|
||||
|
||||
// Notify the listener.
|
||||
if (packet_len != 0)
|
||||
{
|
||||
m_listener->on_packet_recv(this, packet, packet_len);
|
||||
}
|
||||
|
||||
// If there is no more space available in the buffer and that is because
|
||||
// the latest parsed frame filled it, then empty the full buffer.
|
||||
if ((m_frame_start + 2 + packet_len) == m_buffer_size)
|
||||
{
|
||||
osd_printf_error("no more space in the buffer, emptying the buffer data");
|
||||
|
||||
m_frame_start = 0;
|
||||
m_buffer_data_len = 0;
|
||||
}
|
||||
// If there is still space in the buffer, set the beginning of the next
|
||||
// frame to the next position after the parsed frame.
|
||||
else
|
||||
{
|
||||
m_frame_start += 2 + packet_len;
|
||||
}
|
||||
|
||||
// If there is more data in the buffer after the parsed frame then
|
||||
// parse again. Otherwise break here and wait for more data.
|
||||
if (m_buffer_data_len > m_frame_start)
|
||||
{
|
||||
// osd_printf_error("there is more data after the parsed frame, continue parsing");
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // Incomplete packet.
|
||||
{
|
||||
// Check if the buffer is full.
|
||||
if (m_buffer_data_len == m_buffer_size)
|
||||
{
|
||||
// First case: the incomplete frame does not begin at position 0 of
|
||||
// the buffer, so move the frame to the position 0.
|
||||
if (m_frame_start != 0)
|
||||
{
|
||||
// osd_printf_error("no more space in the buffer, moving parsed bytes to the beginning of the buffer and wait for more data");
|
||||
|
||||
std::memmove(m_buffer, m_buffer + m_frame_start, m_buffer_size - m_frame_start);
|
||||
m_buffer_data_len = m_buffer_size - m_frame_start;
|
||||
m_frame_start = 0;
|
||||
}
|
||||
// Second case: the incomplete frame begins at position 0 of the buffer.
|
||||
// The frame is too big, so close the connection.
|
||||
else
|
||||
{
|
||||
osd_printf_error("no more space in the buffer for the unfinished frame being parsed, closing the connection");
|
||||
|
||||
// Close the socket.
|
||||
close();
|
||||
}
|
||||
}
|
||||
// The buffer is not full.
|
||||
else
|
||||
{
|
||||
osd_printf_verbose("frame not finished yet, waiting for more data");
|
||||
}
|
||||
|
||||
// Exit the parsing loop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_tcp_connection::send(const uint8_t* data, size_t len)
|
||||
{
|
||||
// Write according to Framing RFC 4571.
|
||||
|
||||
uint8_t frame_len[2];
|
||||
|
||||
set2bytes(frame_len, 0, len);
|
||||
|
||||
write(frame_len, 2, data, len);
|
||||
}
|
33
src/osd/modules/ipc/rtc_tcp_connection.h
Normal file
33
src/osd/modules/ipc/rtc_tcp_connection.h
Normal file
@ -0,0 +1,33 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#ifndef RTC_TCP_CONNECTION_H
|
||||
#define RTC_TCP_CONNECTION_H
|
||||
|
||||
#include "tcp_connection.h"
|
||||
|
||||
|
||||
class rtc_tcp_connection : public tcp_connection
|
||||
{
|
||||
public:
|
||||
class listener
|
||||
{
|
||||
public:
|
||||
virtual ~listener(){ }
|
||||
virtual void on_packet_recv(rtc_tcp_connection *connection, const uint8_t* data, size_t len) = 0;
|
||||
};
|
||||
|
||||
rtc_tcp_connection(listener* listener, size_t bufferSize);
|
||||
virtual ~rtc_tcp_connection();
|
||||
|
||||
/* Pure virtual methods inherited from tcp_connection. */
|
||||
virtual void user_on_tcp_connection_read() override;
|
||||
|
||||
void send(const uint8_t* data, size_t len);
|
||||
|
||||
private:
|
||||
// Passed by argument.
|
||||
listener* m_listener;
|
||||
size_t m_frame_start; // Where the latest frame starts.
|
||||
};
|
||||
#endif
|
42
src/osd/modules/ipc/rtc_tcp_server.cpp
Normal file
42
src/osd/modules/ipc/rtc_tcp_server.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#include "rtc_tcp_server.h"
|
||||
#include <string>
|
||||
|
||||
#define MAX_TCP_CONNECTIONS_PER_SERVER 10
|
||||
|
||||
/* Instance methods. */
|
||||
|
||||
rtc_tcp_server::rtc_tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog, listener* listener, rtc_tcp_connection::listener* connListener) :
|
||||
tcp_server(loop, ip, port, backlog),
|
||||
m_listener(listener),
|
||||
m_conn_listener(connListener)
|
||||
{
|
||||
}
|
||||
|
||||
void rtc_tcp_server::user_on_tcp_connection_alloc(tcp_connection** connection)
|
||||
{
|
||||
// Allocate a new rtc_tcp_connection for the rtc_tcp_server to handle it.
|
||||
*connection = new rtc_tcp_connection(m_conn_listener, 65536);
|
||||
}
|
||||
|
||||
void rtc_tcp_server::user_on_new_tcp_connection(tcp_connection* connection)
|
||||
{
|
||||
// Allow just MAX_TCP_CONNECTIONS_PER_SERVER.
|
||||
if (get_num_connections() > MAX_TCP_CONNECTIONS_PER_SERVER)
|
||||
connection->close();
|
||||
}
|
||||
|
||||
void rtc_tcp_server::user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer)
|
||||
{
|
||||
// Notify the listener.
|
||||
// NOTE: Don't do it if closing (since at this point the listener is already freed).
|
||||
// At the end, this is just called if the connection was remotely closed.
|
||||
if (!is_closing())
|
||||
m_listener->on_rtc_tcp_connection_closed(this, static_cast<rtc_tcp_connection*>(connection), is_closed_by_peer);
|
||||
}
|
||||
|
||||
void rtc_tcp_server::user_on_tcp_server_closed()
|
||||
{
|
||||
}
|
36
src/osd/modules/ipc/rtc_tcp_server.h
Normal file
36
src/osd/modules/ipc/rtc_tcp_server.h
Normal file
@ -0,0 +1,36 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#ifndef RTC_TCP_SERVER_H
|
||||
#define RTC_TCP_SERVER_H
|
||||
|
||||
#include "tcp_server.h"
|
||||
#include "tcp_connection.h"
|
||||
#include "rtc_tcp_connection.h"
|
||||
#include <uv.h>
|
||||
|
||||
class rtc_tcp_server : public tcp_server
|
||||
{
|
||||
public:
|
||||
class listener
|
||||
{
|
||||
public:
|
||||
virtual ~listener() { }
|
||||
virtual void on_rtc_tcp_connection_closed(rtc_tcp_server* tcpServer, rtc_tcp_connection* connection, bool is_closed_by_peer) = 0;
|
||||
};
|
||||
|
||||
rtc_tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog, listener* listener, rtc_tcp_connection::listener* connListener);
|
||||
|
||||
/* Pure virtual methods inherited from TCPServer. */
|
||||
virtual void user_on_tcp_connection_alloc(tcp_connection** connection) override;
|
||||
virtual void user_on_new_tcp_connection(tcp_connection* connection) override;
|
||||
virtual void user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) override;
|
||||
virtual void user_on_tcp_server_closed() override;
|
||||
|
||||
private:
|
||||
// Passed by argument.
|
||||
listener* m_listener;
|
||||
rtc_tcp_connection::listener* m_conn_listener;
|
||||
};
|
||||
|
||||
#endif
|
414
src/osd/modules/ipc/tcp_connection.cpp
Normal file
414
src/osd/modules/ipc/tcp_connection.cpp
Normal file
@ -0,0 +1,414 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#include "emu.h"
|
||||
#include "tcp_connection.h"
|
||||
#include <cstdint> // uint8_t, etc
|
||||
#include <cstdlib> // std::malloc(), std::free()
|
||||
|
||||
/* Static methods for UV callbacks. */
|
||||
|
||||
static inline void on_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
|
||||
{
|
||||
static_cast<tcp_connection*>(handle->data)->on_uv_read_alloc(suggested_size, buf);
|
||||
}
|
||||
|
||||
static inline void on_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf)
|
||||
{
|
||||
static_cast<tcp_connection*>(handle->data)->on_uv_read(nread, buf);
|
||||
}
|
||||
|
||||
static inline void on_write(uv_write_t* req, int status)
|
||||
{
|
||||
tcp_connection::tcp_uv_write_data* write_data = static_cast<tcp_connection::tcp_uv_write_data*>(req->data);
|
||||
tcp_connection* connection = write_data->connection;
|
||||
|
||||
// Delete the UvWriteData struct (which includes the uv_req_t and the store char[]).
|
||||
std::free(write_data);
|
||||
|
||||
// Just notify the TCPConnection when error.
|
||||
if (status)
|
||||
connection->on_uv_write_error(status);
|
||||
}
|
||||
|
||||
static inline void on_shutdown(uv_shutdown_t* req, int status)
|
||||
{
|
||||
static_cast<tcp_connection*>(req->data)->on_uv_shutdown(req, status);
|
||||
}
|
||||
|
||||
static inline void on_close(uv_handle_t* handle)
|
||||
{
|
||||
static_cast<tcp_connection*>(handle->data)->on_uv_closed();
|
||||
}
|
||||
|
||||
/* Instance methods. */
|
||||
|
||||
tcp_connection::tcp_connection(size_t bufferSize) :
|
||||
m_listener(nullptr),
|
||||
m_local_addr(nullptr),
|
||||
m_is_closing(false),
|
||||
m_is_closed_by_peer(false),
|
||||
m_has_error(false),
|
||||
m_buffer_size(bufferSize),
|
||||
m_buffer(nullptr),
|
||||
m_buffer_data_len(0),
|
||||
m_local_port(0),
|
||||
m_peer_port(0)
|
||||
{
|
||||
m_uv_handle = new uv_tcp_t;
|
||||
m_uv_handle->data = (void*)this;
|
||||
|
||||
// NOTE: Don't allocate the buffer here. Instead wait for the first uv_alloc_cb().
|
||||
}
|
||||
|
||||
tcp_connection::~tcp_connection()
|
||||
{
|
||||
if (m_uv_handle)
|
||||
delete m_uv_handle;
|
||||
if (m_buffer)
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
void tcp_connection::setup(uv_loop_t* loop, listener* listener, struct sockaddr_storage* localAddr, const std::string &localIP, uint16_t localPort)
|
||||
{
|
||||
int err;
|
||||
|
||||
// Set the UV handle.
|
||||
err = uv_tcp_init(loop, m_uv_handle);
|
||||
if (err)
|
||||
{
|
||||
delete m_uv_handle;
|
||||
m_uv_handle = nullptr;
|
||||
throw emu_fatalerror("uv_tcp_init() failed: %s", uv_strerror(err));
|
||||
}
|
||||
|
||||
// Set the listener.
|
||||
m_listener = listener;
|
||||
|
||||
// Set the local address.
|
||||
m_local_addr = localAddr;
|
||||
m_local_ip = localIP;
|
||||
m_local_port = localPort;
|
||||
}
|
||||
|
||||
void tcp_connection::close()
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
int err;
|
||||
|
||||
m_is_closing = true;
|
||||
|
||||
// Don't read more.
|
||||
err = uv_read_stop((uv_stream_t*)m_uv_handle);
|
||||
if (err)
|
||||
throw emu_fatalerror("uv_read_stop() failed: %s", uv_strerror(err));
|
||||
|
||||
// If there is no error and the peer didn't close its connection side then close gracefully.
|
||||
if (!m_has_error && !m_is_closed_by_peer)
|
||||
{
|
||||
// Use uv_shutdown() so pending data to be written will be sent to the peer
|
||||
// before closing.
|
||||
uv_shutdown_t* req = new uv_shutdown_t;
|
||||
req->data = (void*)this;
|
||||
err = uv_shutdown(req, (uv_stream_t*)m_uv_handle, (uv_shutdown_cb)on_shutdown);
|
||||
if (err)
|
||||
throw emu_fatalerror("uv_shutdown() failed: %s", uv_strerror(err));
|
||||
}
|
||||
// Otherwise directly close the socket.
|
||||
else
|
||||
{
|
||||
uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_connection::terminate()
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
m_is_closing = true;
|
||||
uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
|
||||
}
|
||||
|
||||
void tcp_connection::dump()
|
||||
{
|
||||
osd_printf_verbose("[TCP, local:%s :%d, remote:%s :%d, status:%s]\r\n",
|
||||
m_local_ip.c_str(), (uint16_t)m_local_port,
|
||||
m_peer_ip.c_str(), (uint16_t)m_peer_port,
|
||||
(!m_is_closing) ? "open" : "closed");
|
||||
}
|
||||
|
||||
void tcp_connection::start()
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
int err;
|
||||
|
||||
err = uv_read_start((uv_stream_t*)m_uv_handle, (uv_alloc_cb)on_alloc, (uv_read_cb)on_read);
|
||||
if (err)
|
||||
throw emu_fatalerror("uv_read_start() failed: %s", uv_strerror(err));
|
||||
|
||||
// Get the peer address.
|
||||
if (!set_peer_address())
|
||||
throw emu_fatalerror("error setting peer IP and port");
|
||||
}
|
||||
|
||||
void tcp_connection::write(const uint8_t* data, size_t len)
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
uv_buf_t buffer;
|
||||
int written;
|
||||
int err;
|
||||
|
||||
// First try uv_try_write(). In case it can not directly write all the given
|
||||
// data then build a uv_req_t and use uv_write().
|
||||
|
||||
buffer = uv_buf_init((char*)data, len);
|
||||
written = uv_try_write((uv_stream_t*)m_uv_handle, &buffer, 1);
|
||||
|
||||
// All the data was written. Done.
|
||||
if (written == (int)len)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Cannot write any data at first time. Use uv_write().
|
||||
else if (written == UV_EAGAIN || written == UV_ENOSYS)
|
||||
{
|
||||
// Set written to 0 so pending_len can be properly calculated.
|
||||
written = 0;
|
||||
}
|
||||
// Error. Should not happen.
|
||||
else if (written < 0)
|
||||
{
|
||||
osd_printf_warning("uv_try_write() failed, closing the connection: %s", uv_strerror(written));
|
||||
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
// osd_printf_info("could just write %zu bytes (%zu given) at first time, using uv_write() now", (size_t)written, len);
|
||||
|
||||
size_t pending_len = len - written;
|
||||
|
||||
// Allocate a special UvWriteData struct pointer.
|
||||
tcp_uv_write_data* write_data = (tcp_uv_write_data*)std::malloc(sizeof(tcp_uv_write_data) + pending_len);
|
||||
|
||||
write_data->connection = this;
|
||||
std::memcpy(write_data->store, data + written, pending_len);
|
||||
write_data->req.data = (void*)write_data;
|
||||
|
||||
buffer = uv_buf_init((char*)write_data->store, pending_len);
|
||||
|
||||
err = uv_write(&write_data->req, (uv_stream_t*)m_uv_handle, &buffer, 1, (uv_write_cb)on_write);
|
||||
if (err)
|
||||
throw emu_fatalerror("uv_write() failed: %s", uv_strerror(err));
|
||||
}
|
||||
|
||||
void tcp_connection::write(const uint8_t* data1, size_t len1, const uint8_t* data2, size_t len2)
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
if (len1 == 0 && len2 == 0)
|
||||
return;
|
||||
|
||||
size_t total_len = len1 + len2;
|
||||
uv_buf_t buffers[2];
|
||||
int written;
|
||||
int err;
|
||||
|
||||
// First try uv_try_write(). In case it can not directly write all the given
|
||||
// data then build a uv_req_t and use uv_write().
|
||||
|
||||
buffers[0] = uv_buf_init((char*)data1, len1);
|
||||
buffers[1] = uv_buf_init((char*)data2, len2);
|
||||
written = uv_try_write((uv_stream_t*)m_uv_handle, buffers, 2);
|
||||
|
||||
// All the data was written. Done.
|
||||
if (written == (int)total_len)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Cannot write any data at first time. Use uv_write().
|
||||
else if (written == UV_EAGAIN || written == UV_ENOSYS)
|
||||
{
|
||||
// Set written to 0 so pending_len can be properly calculated.
|
||||
written = 0;
|
||||
}
|
||||
// Error. Should not happen.
|
||||
else if (written < 0)
|
||||
{
|
||||
osd_printf_warning("uv_try_write() failed, closing the connection: %s", uv_strerror(written));
|
||||
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
// osd_printf_info("could just write %zu bytes (%zu given) at first time, using uv_write() now", (size_t)written, total_len);
|
||||
|
||||
size_t pending_len = total_len - written;
|
||||
|
||||
// Allocate a special UvWriteData struct pointer.
|
||||
tcp_uv_write_data* write_data = (tcp_uv_write_data*)std::malloc(sizeof(tcp_uv_write_data) + pending_len);
|
||||
|
||||
write_data->connection = this;
|
||||
// If the first buffer was not entirely written then splice it.
|
||||
if ((size_t)written < len1)
|
||||
{
|
||||
std::memcpy(write_data->store, data1 + (size_t)written, len1 - (size_t)written);
|
||||
std::memcpy(write_data->store + (len1 - (size_t)written), data2, len2);
|
||||
}
|
||||
// Otherwise just take the pending data in the second buffer.
|
||||
else
|
||||
{
|
||||
std::memcpy(write_data->store, data2 + ((size_t)written - len1), len2 - ((size_t)written - len1));
|
||||
}
|
||||
write_data->req.data = (void*)write_data;
|
||||
|
||||
uv_buf_t buffer = uv_buf_init((char*)write_data->store, pending_len);
|
||||
|
||||
err = uv_write(&write_data->req, (uv_stream_t*)m_uv_handle, &buffer, 1, (uv_write_cb)on_write);
|
||||
if (err)
|
||||
throw emu_fatalerror("uv_write() failed: %s", uv_strerror(err));
|
||||
}
|
||||
|
||||
void GetAddressInfo(const struct sockaddr* addr, int* family, std::string &ip, uint16_t* port)
|
||||
{
|
||||
char _ip[INET6_ADDRSTRLEN + 1];
|
||||
int err;
|
||||
|
||||
|
||||
err = uv_inet_ntop(AF_INET, &((struct sockaddr_in*)addr)->sin_addr, _ip, INET_ADDRSTRLEN);
|
||||
if (err)
|
||||
throw emu_fatalerror("uv_inet_ntop() failed: %s", uv_strerror(err));
|
||||
*port = (uint16_t)ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
|
||||
*family = addr->sa_family;
|
||||
ip.assign(_ip);
|
||||
}
|
||||
bool tcp_connection::set_peer_address()
|
||||
{
|
||||
int err;
|
||||
int len = sizeof(m_peer_addr);
|
||||
|
||||
err = uv_tcp_getpeername(m_uv_handle, (struct sockaddr*)&m_peer_addr, &len);
|
||||
if (err)
|
||||
{
|
||||
osd_printf_error("uv_tcp_getpeername() failed: %s", uv_strerror(err));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int family;
|
||||
GetAddressInfo((const struct sockaddr*)&m_peer_addr, &family, m_peer_ip, &m_peer_port);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void tcp_connection::on_uv_read_alloc(size_t suggested_size, uv_buf_t* buf)
|
||||
{
|
||||
// If this is the first call to onUvReadAlloc() then allocate the receiving buffer now.
|
||||
if (!m_buffer)
|
||||
m_buffer = new uint8_t[m_buffer_size];
|
||||
|
||||
// Tell UV to write after the last data byte in the buffer.
|
||||
buf->base = (char *)(m_buffer + m_buffer_data_len);
|
||||
// Give UV all the remaining space in the buffer.
|
||||
if (m_buffer_size > m_buffer_data_len)
|
||||
{
|
||||
buf->len = m_buffer_size - m_buffer_data_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->len = 0;
|
||||
|
||||
osd_printf_warning("no available space in the buffer");
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_connection::on_uv_read(::ssize_t nread, const uv_buf_t* buf)
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
if (nread == 0)
|
||||
return;
|
||||
|
||||
// Data received.
|
||||
if (nread > 0)
|
||||
{
|
||||
// Update the buffer data length.
|
||||
m_buffer_data_len += (size_t)nread;
|
||||
|
||||
// Notify the subclass.
|
||||
user_on_tcp_connection_read();
|
||||
}
|
||||
// Client disconneted.
|
||||
else if (nread == UV_EOF || nread == UV_ECONNRESET)
|
||||
{
|
||||
osd_printf_info("connection closed by peer, closing server side");
|
||||
|
||||
m_is_closed_by_peer = true;
|
||||
|
||||
// Close server side of the connection.
|
||||
close();
|
||||
}
|
||||
// Some error.
|
||||
else
|
||||
{
|
||||
osd_printf_info("read error, closing the connection: %s", uv_strerror(nread));
|
||||
|
||||
m_has_error = true;
|
||||
|
||||
// Close server side of the connection.
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_connection::on_uv_write_error(int error)
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
if (error == UV_EPIPE || error == UV_ENOTCONN)
|
||||
{
|
||||
osd_printf_info("write error, closing the connection: %s", uv_strerror(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
osd_printf_info("write error, closing the connection: %s", uv_strerror(error));
|
||||
|
||||
m_has_error = true;
|
||||
}
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
void tcp_connection::on_uv_shutdown(uv_shutdown_t* req, int status)
|
||||
{
|
||||
delete req;
|
||||
|
||||
if (status == UV_EPIPE || status == UV_ENOTCONN || status == UV_ECANCELED)
|
||||
osd_printf_info("shutdown error: %s", uv_strerror(status));
|
||||
else if (status)
|
||||
osd_printf_info("shutdown error: %s", uv_strerror(status));
|
||||
|
||||
// Now do close the handle.
|
||||
uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
|
||||
}
|
||||
|
||||
void tcp_connection::on_uv_closed()
|
||||
{
|
||||
// Notify the listener.
|
||||
m_listener->on_tcp_connection_closed(this, m_is_closed_by_peer);
|
||||
|
||||
// And delete this.
|
||||
delete this;
|
||||
}
|
137
src/osd/modules/ipc/tcp_connection.h
Normal file
137
src/osd/modules/ipc/tcp_connection.h
Normal file
@ -0,0 +1,137 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#ifndef TCP_CONNECTION_H
|
||||
#define TCP_CONNECTION_H
|
||||
|
||||
#include <string>
|
||||
#include <uv.h>
|
||||
|
||||
extern void GetAddressInfo(const sockaddr * addr, int * family, std::string & ip, uint16_t * port);
|
||||
|
||||
class tcp_connection
|
||||
{
|
||||
public:
|
||||
class listener
|
||||
{
|
||||
public:
|
||||
virtual ~listener() { }
|
||||
virtual void on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) = 0;
|
||||
};
|
||||
|
||||
/* Struct for the data field of uv_req_t when writing into the connection. */
|
||||
struct tcp_uv_write_data
|
||||
{
|
||||
tcp_connection* connection;
|
||||
uv_write_t req;
|
||||
uint8_t store[1];
|
||||
};
|
||||
|
||||
tcp_connection(size_t bufferSize);
|
||||
virtual ~tcp_connection();
|
||||
|
||||
void close();
|
||||
void terminate();
|
||||
virtual void dump();
|
||||
void setup(uv_loop_t* loop, listener* listener, struct sockaddr_storage* localAddr, const std::string &localIP, uint16_t localPort);
|
||||
bool is_closing();
|
||||
uv_tcp_t* get_uv_handle();
|
||||
void start();
|
||||
void write(const uint8_t* data, size_t len);
|
||||
void write(const uint8_t* data1, size_t len1, const uint8_t* data2, size_t len2);
|
||||
void write(const std::string &data);
|
||||
const struct sockaddr* get_local_address();
|
||||
const std::string& get_local_ip();
|
||||
uint16_t get_local_port();
|
||||
const struct sockaddr* get_peer_address();
|
||||
const std::string& get_peer_ip();
|
||||
uint16_t get_peer_port();
|
||||
|
||||
private:
|
||||
bool set_peer_address();
|
||||
|
||||
/* Callbacks fired by UV events. */
|
||||
public:
|
||||
void on_uv_read_alloc(size_t suggested_size, uv_buf_t* buf);
|
||||
void on_uv_read(ssize_t nread, const uv_buf_t* buf);
|
||||
void on_uv_write_error(int error);
|
||||
void on_uv_shutdown(uv_shutdown_t* req, int status);
|
||||
void on_uv_closed();
|
||||
|
||||
/* Pure virtual methods that must be implemented by the subclass. */
|
||||
protected:
|
||||
virtual void user_on_tcp_connection_read() = 0;
|
||||
|
||||
private:
|
||||
// Passed by argument.
|
||||
listener* m_listener;
|
||||
// Allocated by this.
|
||||
uv_tcp_t* m_uv_handle;
|
||||
// Others.
|
||||
struct sockaddr_storage* m_local_addr;
|
||||
bool m_is_closing;
|
||||
bool m_is_closed_by_peer;
|
||||
bool m_has_error;
|
||||
|
||||
protected:
|
||||
// Passed by argument.
|
||||
size_t m_buffer_size;
|
||||
// Allocated by this.
|
||||
uint8_t* m_buffer;
|
||||
// Others.
|
||||
size_t m_buffer_data_len;
|
||||
std::string m_local_ip;
|
||||
uint16_t m_local_port;
|
||||
struct sockaddr_storage m_peer_addr;
|
||||
std::string m_peer_ip;
|
||||
uint16_t m_peer_port;
|
||||
};
|
||||
|
||||
/* Inline methods. */
|
||||
|
||||
inline bool tcp_connection::is_closing()
|
||||
{
|
||||
return m_is_closing;
|
||||
}
|
||||
|
||||
inline uv_tcp_t* tcp_connection::get_uv_handle()
|
||||
{
|
||||
return m_uv_handle;
|
||||
}
|
||||
|
||||
inline void tcp_connection::write(const std::string &data)
|
||||
{
|
||||
write((const uint8_t*)data.c_str(), data.size());
|
||||
}
|
||||
|
||||
inline const sockaddr* tcp_connection::get_local_address()
|
||||
{
|
||||
return (const struct sockaddr*)m_local_addr;
|
||||
}
|
||||
|
||||
inline const std::string& tcp_connection::get_local_ip()
|
||||
{
|
||||
return m_local_ip;
|
||||
}
|
||||
|
||||
inline uint16_t tcp_connection::get_local_port()
|
||||
{
|
||||
return m_local_port;
|
||||
}
|
||||
|
||||
inline const sockaddr* tcp_connection::get_peer_address()
|
||||
{
|
||||
return (const struct sockaddr*)&m_peer_addr;
|
||||
}
|
||||
|
||||
inline const std::string& tcp_connection::get_peer_ip()
|
||||
{
|
||||
return m_peer_ip;
|
||||
}
|
||||
|
||||
inline uint16_t tcp_connection::get_peer_port()
|
||||
{
|
||||
return m_peer_port;
|
||||
}
|
||||
|
||||
#endif
|
279
src/osd/modules/ipc/tcp_server.cpp
Normal file
279
src/osd/modules/ipc/tcp_server.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#include "emu.h"
|
||||
#include "tcp_server.h"
|
||||
|
||||
/* Static methods for UV callbacks. */
|
||||
|
||||
static inline void on_connection(uv_stream_t* handle, int status)
|
||||
{
|
||||
static_cast<tcp_server*>(handle->data)->on_uv_connection(status);
|
||||
}
|
||||
|
||||
static inline void on_close(uv_handle_t* handle)
|
||||
{
|
||||
static_cast<tcp_server*>(handle->data)->on_uv_closed();
|
||||
}
|
||||
|
||||
static inline void on_error_close(uv_handle_t* handle)
|
||||
{
|
||||
delete handle;
|
||||
}
|
||||
|
||||
/* Instance methods. */
|
||||
|
||||
tcp_server::tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog)
|
||||
: m_uv_handle(nullptr),
|
||||
m_loop(nullptr),
|
||||
m_is_closing(false),
|
||||
m_local_port(0)
|
||||
{
|
||||
int err;
|
||||
int flags = 0;
|
||||
|
||||
m_uv_handle = new uv_tcp_t;
|
||||
m_uv_handle->data = (void*)this;
|
||||
m_loop = loop;
|
||||
|
||||
err = uv_tcp_init(loop, m_uv_handle);
|
||||
if (err)
|
||||
{
|
||||
delete m_uv_handle;
|
||||
m_uv_handle = nullptr;
|
||||
throw emu_fatalerror("uv_tcp_init() failed: %s", uv_strerror(err));
|
||||
}
|
||||
|
||||
struct sockaddr_storage bind_addr;
|
||||
|
||||
|
||||
err = uv_ip4_addr(ip.c_str(), (int)port, (struct sockaddr_in*)&bind_addr);
|
||||
if (err)
|
||||
throw emu_fatalerror("uv_ipv4_addr() failed: %s", uv_strerror(err));
|
||||
|
||||
err = uv_tcp_bind(m_uv_handle, (const struct sockaddr*)&bind_addr, flags);
|
||||
if (err)
|
||||
{
|
||||
uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_error_close);
|
||||
throw emu_fatalerror("uv_tcp_bind() failed: %s", uv_strerror(err));
|
||||
}
|
||||
|
||||
err = uv_listen((uv_stream_t*)m_uv_handle, backlog, (uv_connection_cb)on_connection);
|
||||
if (err)
|
||||
{
|
||||
uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_error_close);
|
||||
throw emu_fatalerror("uv_listen() failed: %s", uv_strerror(err));
|
||||
}
|
||||
|
||||
// Set local address.
|
||||
if (!set_local_address())
|
||||
{
|
||||
uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_error_close);
|
||||
throw emu_fatalerror("error setting local IP and port");
|
||||
}
|
||||
}
|
||||
|
||||
tcp_server::~tcp_server()
|
||||
{
|
||||
if (m_uv_handle)
|
||||
delete m_uv_handle;
|
||||
}
|
||||
|
||||
void tcp_server::close()
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
m_is_closing = true;
|
||||
|
||||
// If there are no connections then close now.
|
||||
if (m_connections.empty())
|
||||
{
|
||||
uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
|
||||
}
|
||||
// Otherwise close all the connections (but not the TCP server).
|
||||
else
|
||||
{
|
||||
osd_printf_info("closing %d active connections", (int)m_connections.size());
|
||||
|
||||
for (auto it = m_connections.begin(); it != m_connections.end(); ++it)
|
||||
{
|
||||
tcp_connection* connection = *it;
|
||||
connection->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_server::terminate()
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
m_is_closing = true;
|
||||
|
||||
// If there are no connections then close now.
|
||||
if (m_connections.empty())
|
||||
{
|
||||
uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
|
||||
}
|
||||
// Otherwise close all the connections (but not the TCP server).
|
||||
else
|
||||
{
|
||||
osd_printf_info("closing %d active connections", (int)m_connections.size());
|
||||
|
||||
for (auto it = m_connections.begin(); it != m_connections.end(); ++it)
|
||||
{
|
||||
tcp_connection* connection = *it;
|
||||
connection->terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_server::send_to_all(const uint8_t* data, size_t len)
|
||||
{
|
||||
// If there are no connections then close now.
|
||||
if (!m_connections.empty())
|
||||
{
|
||||
for (auto it = m_connections.begin(); it != m_connections.end(); ++it)
|
||||
{
|
||||
tcp_connection* connection = *it;
|
||||
connection->write(data, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_server::dump()
|
||||
{
|
||||
osd_printf_info("[TCP, local:%s :%d, status:%s, connections:%d]",
|
||||
m_local_ip.c_str(), (uint16_t)m_local_port,
|
||||
(!m_is_closing) ? "open" : "closed",
|
||||
(int)m_connections.size());
|
||||
}
|
||||
|
||||
const sockaddr* tcp_server::get_local_address()
|
||||
{
|
||||
return (const struct sockaddr*)&m_local_addr;
|
||||
}
|
||||
|
||||
const std::string& tcp_server::get_local_ip()
|
||||
{
|
||||
return m_local_ip;
|
||||
}
|
||||
|
||||
uint16_t tcp_server::get_local_port()
|
||||
{
|
||||
return m_local_port;
|
||||
}
|
||||
|
||||
bool tcp_server::set_local_address()
|
||||
{
|
||||
int err;
|
||||
int len = sizeof(m_local_addr);
|
||||
|
||||
err = uv_tcp_getsockname(m_uv_handle, (struct sockaddr*)&m_local_addr, &len);
|
||||
if (err)
|
||||
{
|
||||
osd_printf_error("uv_tcp_getsockname() failed: %s", uv_strerror(err));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int family;
|
||||
GetAddressInfo((const struct sockaddr*)&m_local_addr, &family, m_local_ip, &m_local_port);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void tcp_server::on_uv_connection(int status)
|
||||
{
|
||||
if (m_is_closing)
|
||||
return;
|
||||
|
||||
int err;
|
||||
|
||||
if (status)
|
||||
{
|
||||
osd_printf_error("error while receiving a new TCP connection: %s", uv_strerror(status));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify the subclass so it provides an allocated derived class of TCPConnection.
|
||||
tcp_connection* connection = nullptr;
|
||||
user_on_tcp_connection_alloc(&connection);
|
||||
if (connection != nullptr)
|
||||
osd_printf_error("tcp_server pointer was not allocated by the user");
|
||||
|
||||
try
|
||||
{
|
||||
connection->setup(m_loop, this, &(m_local_addr), m_local_ip, m_local_port);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete connection;
|
||||
return;
|
||||
}
|
||||
|
||||
// Accept the connection.
|
||||
err = uv_accept((uv_stream_t*)m_uv_handle, (uv_stream_t*)connection->get_uv_handle());
|
||||
if (err)
|
||||
throw emu_fatalerror("uv_accept() failed: %s", uv_strerror(err));
|
||||
|
||||
// Insert the TCPConnection in the set.
|
||||
m_connections.insert(connection);
|
||||
|
||||
// Start receiving data.
|
||||
try
|
||||
{
|
||||
connection->start();
|
||||
}
|
||||
catch (emu_exception &error)
|
||||
{
|
||||
osd_printf_error("cannot run the TCP connection, closing the connection: %s", error.what());
|
||||
connection->close();
|
||||
// NOTE: Don't return here so the user won't be notified about a "onclose" for a TCP connection
|
||||
// for which there was not a previous "onnew" event.
|
||||
}
|
||||
|
||||
osd_printf_info("new TCP connection:");
|
||||
connection->dump();
|
||||
|
||||
// Notify the subclass.
|
||||
user_on_new_tcp_connection(connection);
|
||||
}
|
||||
|
||||
void tcp_server::on_uv_closed()
|
||||
{
|
||||
// Motify the subclass.
|
||||
user_on_tcp_server_closed();
|
||||
}
|
||||
|
||||
void tcp_server::on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer)
|
||||
{
|
||||
// NOTE:
|
||||
// Worst scenario is that in which this is the latest connection,
|
||||
// which is remotely closed (no tcp_server.Close() was called) and the user
|
||||
// call tcp_server.Close() on userOnTCPConnectionClosed() callback, so Close()
|
||||
// is called with zero connections and calls uv_close(), but then
|
||||
// onTCPConnectionClosed() continues and finds that isClosing is true and
|
||||
// there are zero connections, so calls uv_close() again and get a crash.
|
||||
//
|
||||
// SOLUTION:
|
||||
// Check isClosing value *before* onTCPConnectionClosed() callback.
|
||||
|
||||
bool wasClosing = m_is_closing;
|
||||
|
||||
osd_printf_info("TCP connection closed:");
|
||||
connection->dump();
|
||||
|
||||
// Remove the TCPConnection from the set.
|
||||
m_connections.erase(connection);
|
||||
|
||||
// Notify the subclass.
|
||||
user_on_tcp_connection_closed(connection, is_closed_by_peer);
|
||||
|
||||
// Check if the server was closing connections, and if this is the last
|
||||
// connection then close the server now.
|
||||
if (wasClosing && m_connections.empty())
|
||||
uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close);
|
||||
}
|
72
src/osd/modules/ipc/tcp_server.h
Normal file
72
src/osd/modules/ipc/tcp_server.h
Normal file
@ -0,0 +1,72 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic
|
||||
|
||||
#ifndef TCP_SERVER_H
|
||||
#define TCP_SERVER_H
|
||||
|
||||
#include "tcp_connection.h"
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <uv.h>
|
||||
|
||||
class tcp_server : public tcp_connection::listener
|
||||
{
|
||||
public:
|
||||
tcp_server(uv_loop_t* m_loop, const std::string &ip, uint16_t port, int backlog);
|
||||
virtual ~tcp_server();
|
||||
|
||||
void close();
|
||||
void terminate();
|
||||
virtual void dump();
|
||||
void send_to_all(const uint8_t* data, size_t len);
|
||||
bool is_closing();
|
||||
const struct sockaddr* get_local_address();
|
||||
const std::string& get_local_ip();
|
||||
uint16_t get_local_port();
|
||||
size_t get_num_connections();
|
||||
|
||||
private:
|
||||
bool set_local_address();
|
||||
|
||||
/* Pure virtual methods that must be implemented by the subclass. */
|
||||
protected:
|
||||
virtual void user_on_tcp_connection_alloc(tcp_connection** connection) = 0;
|
||||
virtual void user_on_new_tcp_connection(tcp_connection* connection) = 0;
|
||||
virtual void user_on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) = 0;
|
||||
virtual void user_on_tcp_server_closed() = 0;
|
||||
|
||||
/* Callbacks fired by UV events. */
|
||||
public:
|
||||
void on_uv_connection(int status);
|
||||
void on_uv_closed();
|
||||
|
||||
/* Methods inherited from tcp_connection::listener. */
|
||||
virtual void on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) override;
|
||||
|
||||
private:
|
||||
// Allocated by this (may be passed by argument).
|
||||
uv_tcp_t* m_uv_handle;
|
||||
uv_loop_t* m_loop;
|
||||
// Others.
|
||||
std::unordered_set<tcp_connection*> m_connections;
|
||||
bool m_is_closing;
|
||||
|
||||
protected:
|
||||
struct sockaddr_storage m_local_addr;
|
||||
std::string m_local_ip;
|
||||
uint16_t m_local_port;
|
||||
};
|
||||
|
||||
/* Inline methods. */
|
||||
|
||||
inline bool tcp_server::is_closing()
|
||||
{
|
||||
return m_is_closing;
|
||||
}
|
||||
|
||||
inline size_t tcp_server::get_num_connections()
|
||||
{
|
||||
return m_connections.size();
|
||||
}
|
||||
|
||||
#endif
|
@ -537,7 +537,7 @@ void osd_common_t::customize_input_type_list(simple_list<input_type_entry> &type
|
||||
// list of OS-dependent slider values.
|
||||
//-------------------------------------------------
|
||||
|
||||
std::vector<slider_state*> osd_common_t::get_slider_list()
|
||||
std::vector<ui_menu_item> osd_common_t::get_slider_list()
|
||||
{
|
||||
return m_sliders;
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "modules/output/output_module.h"
|
||||
#include "cliopts.h"
|
||||
|
||||
class ui_menu_item;
|
||||
|
||||
//============================================================
|
||||
// Defines
|
||||
//============================================================
|
||||
@ -189,7 +191,7 @@ public:
|
||||
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override;
|
||||
|
||||
// video overridables
|
||||
virtual std::vector<slider_state *> get_slider_list() override;
|
||||
virtual std::vector<ui_menu_item> get_slider_list() override;
|
||||
|
||||
// command option overrides
|
||||
virtual bool execute_command(const char *command) override;
|
||||
@ -279,7 +281,7 @@ protected:
|
||||
input_module* m_lightgun_input;
|
||||
input_module* m_joystick_input;
|
||||
output_module* m_output;
|
||||
std::vector<slider_state *> m_sliders;
|
||||
std::vector<ui_menu_item> m_sliders;
|
||||
|
||||
private:
|
||||
std::vector<const char *> m_video_names;
|
||||
|
@ -6,14 +6,6 @@
|
||||
//
|
||||
//============================================================
|
||||
|
||||
// standard windows headers
|
||||
#ifdef OSD_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <mmsystem.h>
|
||||
#endif
|
||||
|
||||
#include "osdwindow.h"
|
||||
|
||||
#include "render/drawnone.h"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user