This commit is contained in:
Brad Hughes 2016-04-10 13:34:23 -04:00
commit c4d91605fc
121 changed files with 6881 additions and 1583 deletions

32
3rdparty/bgfx/3rdparty/iqa/LICENSE vendored Normal file
View 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
View 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

View 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_*/

View 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
View 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_*/

View 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_ */

View 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_*/

View 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_ */

View 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);
}

View 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;
}

View 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;
}

View 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
View 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) );
}

View 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
View 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);
}

View File

@ -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; }

View File

@ -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);

View File

@ -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++)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.48 WIP
// dear imgui, v1.49 WIP
// (drawing and font code)
// Contains implementation for

View File

@ -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!

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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"),
}

View File

@ -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
View 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
View 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

View File

@ -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) )
{

View File

@ -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;
};

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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];

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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",

View File

@ -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"),

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -44,6 +44,7 @@ protected:
private:
UINT8 m_ram[768*1024];
UINT8 m_c800_ram[0x400];
UINT8 m_regs[0x400];
UINT32 m_offset;
};

View File

@ -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
-------------------------------------------------*/

View File

@ -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;

View 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

View 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

View 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;
}

View 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

View 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;
}

View 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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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()

View File

@ -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() { };

View File

@ -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__ */

View File

@ -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
//**************************************************************************

View File

@ -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__ */

View File

@ -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__

View File

@ -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

View File

@ -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
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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 &param)

View File

@ -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;

View File

@ -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_ */

View File

@ -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();

View File

@ -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);

View File

@ -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 &current_name() const { return m_curr_name; }
const std::string &current_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;

View File

@ -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 &current(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;
}

View File

@ -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

View File

@ -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) )

View File

@ -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

View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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

View 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;
}

View 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

View 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()
{
}

View 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

View 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);
}

View 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

View 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()
{
}

View 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

View 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;
}

View 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

View 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);
}

View 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

View File

@ -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;
}

View File

@ -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;

View File

@ -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