Merge branch 'master' into safek_master
This commit is contained in:
commit
b0aa98ebf2
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
name: New Issue, Bug report, Question
|
||||
about: New Issue, Bug report, Question
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## State your operating system:
|
||||
Windows/Mac/Linux. in case of linux, whether you use CLI, gtk2, or gtk3 version.
|
||||
|
||||
## DesMuME version
|
||||
e.g. 0.9.13 or git master
|
||||
|
||||
## Isse
|
||||
type here what's bothering you, in a detailed manner.
|
||||
|
||||
|
|
@ -848,7 +848,7 @@ void GPUEngineBase::UpdateRenderStates(const size_t l)
|
|||
{
|
||||
currRenderState.workingBackdropColor16 = currRenderState.backdropColor16;
|
||||
}
|
||||
currRenderState.workingBackdropColor32.value = LOCAL_TO_LE_32( (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR666_Rev) ? COLOR555TO666(LOCAL_TO_LE_16(currRenderState.workingBackdropColor16)) : COLOR555TO888(LOCAL_TO_LE_16(currRenderState.workingBackdropColor16)) );
|
||||
currRenderState.workingBackdropColor32.value = LOCAL_TO_LE_32( (this->_targetDisplay->GetColorFormat() == NDSColorFormat_BGR666_Rev) ? COLOR555TO666(currRenderState.workingBackdropColor16) : COLOR555TO888(currRenderState.workingBackdropColor16) );
|
||||
|
||||
// Save the current render states to this line's compositor info.
|
||||
compInfo.renderState = currRenderState;
|
||||
|
@ -924,6 +924,11 @@ const GPU_IOREG& GPUEngineBase::GetIORegisterMap() const
|
|||
return *this->_IORegisterMap;
|
||||
}
|
||||
|
||||
bool GPUEngineBase::IsForceBlankSet() const
|
||||
{
|
||||
return (this->_IORegisterMap->DISPCNT.ForceBlank != 0);
|
||||
}
|
||||
|
||||
bool GPUEngineBase::IsMasterBrightMaxOrMin() const
|
||||
{
|
||||
return this->_currentRenderState.masterBrightnessIsMaxOrMin;
|
||||
|
@ -2940,11 +2945,18 @@ void GPUEngineBase::RenderLayerBG(const GPULayerID layerID, u16 *dstColorBuffer)
|
|||
}
|
||||
}
|
||||
|
||||
void GPUEngineBase::_RenderLineBlank(const size_t l)
|
||||
{
|
||||
// Native rendering only.
|
||||
// Just clear the line using white pixels.
|
||||
memset_u16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH>(this->_targetDisplay->GetNativeBuffer16() + (l * GPU_FRAMEBUFFER_NATIVE_WIDTH), 0xFFFF);
|
||||
}
|
||||
|
||||
void GPUEngineBase::_HandleDisplayModeOff(const size_t l)
|
||||
{
|
||||
// Native rendering only.
|
||||
// In this display mode, the display is cleared to white.
|
||||
memset_u16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH>(this->_targetDisplay->GetNativeBuffer16() + (l * GPU_FRAMEBUFFER_NATIVE_WIDTH), 0xFFFF);
|
||||
// In this display mode, the line is cleared to white.
|
||||
this->_RenderLineBlank(l);
|
||||
}
|
||||
|
||||
void GPUEngineBase::_HandleDisplayModeNormal(const size_t l)
|
||||
|
@ -3536,23 +3548,30 @@ void GPUEngineA::RenderLine(const size_t l)
|
|||
}
|
||||
|
||||
// Fill the display output
|
||||
switch (compInfo.renderState.displayOutputMode)
|
||||
if ( this->IsForceBlankSet() )
|
||||
{
|
||||
case GPUDisplayMode_Off: // Display Off (Display white)
|
||||
this->_HandleDisplayModeOff(l);
|
||||
break;
|
||||
|
||||
case GPUDisplayMode_Normal: // Display BG and OBJ layers
|
||||
this->_HandleDisplayModeNormal(l);
|
||||
break;
|
||||
|
||||
case GPUDisplayMode_VRAM: // Display VRAM framebuffer
|
||||
this->_HandleDisplayModeVRAM<OUTPUTFORMAT>(compInfo.line);
|
||||
break;
|
||||
|
||||
case GPUDisplayMode_MainMemory: // Display Memory FIFO
|
||||
this->_HandleDisplayModeMainMemory(compInfo.line);
|
||||
break;
|
||||
this->_RenderLineBlank(l);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (compInfo.renderState.displayOutputMode)
|
||||
{
|
||||
case GPUDisplayMode_Off: // Display Off (clear line to white)
|
||||
this->_HandleDisplayModeOff(l);
|
||||
break;
|
||||
|
||||
case GPUDisplayMode_Normal: // Display BG and OBJ layers
|
||||
this->_HandleDisplayModeNormal(l);
|
||||
break;
|
||||
|
||||
case GPUDisplayMode_VRAM: // Display VRAM framebuffer
|
||||
this->_HandleDisplayModeVRAM<OUTPUTFORMAT>(compInfo.line);
|
||||
break;
|
||||
|
||||
case GPUDisplayMode_MainMemory: // Display Memory FIFO
|
||||
this->_HandleDisplayModeMainMemory(compInfo.line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//capture after displaying so that we can safely display vram before overwriting it here
|
||||
|
@ -4533,29 +4552,36 @@ void GPUEngineB::RenderLine(const size_t l)
|
|||
{
|
||||
GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[l];
|
||||
|
||||
switch (compInfo.renderState.displayOutputMode)
|
||||
if ( this->IsForceBlankSet() )
|
||||
{
|
||||
case GPUDisplayMode_Off: // Display Off(Display white)
|
||||
this->_HandleDisplayModeOff(l);
|
||||
break;
|
||||
|
||||
case GPUDisplayMode_Normal: // Display BG and OBJ layers
|
||||
this->_RenderLineBlank(l);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (compInfo.renderState.displayOutputMode)
|
||||
{
|
||||
if (compInfo.renderState.isAnyWindowEnabled)
|
||||
{
|
||||
this->_RenderLine_Layers<OUTPUTFORMAT, true>(compInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_RenderLine_Layers<OUTPUTFORMAT, false>(compInfo);
|
||||
}
|
||||
case GPUDisplayMode_Off: // Display Off (clear line to white)
|
||||
this->_HandleDisplayModeOff(l);
|
||||
break;
|
||||
|
||||
this->_HandleDisplayModeNormal(l);
|
||||
break;
|
||||
case GPUDisplayMode_Normal: // Display BG and OBJ layers
|
||||
{
|
||||
if (compInfo.renderState.isAnyWindowEnabled)
|
||||
{
|
||||
this->_RenderLine_Layers<OUTPUTFORMAT, true>(compInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_RenderLine_Layers<OUTPUTFORMAT, false>(compInfo);
|
||||
}
|
||||
|
||||
this->_HandleDisplayModeNormal(l);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (compInfo.line.indexNative >= 191)
|
||||
|
@ -5454,7 +5480,7 @@ void GPUSubsystem::RenderLine(const size_t l)
|
|||
this->_engineSub->UpdateRenderStates(l);
|
||||
}
|
||||
|
||||
if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || isDisplayCaptureNeeded) && !this->_willFrameSkip )
|
||||
if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || this->_engineMain->IsForceBlankSet() || isDisplayCaptureNeeded) && !this->_willFrameSkip )
|
||||
{
|
||||
// GPUEngineA:WillRender3DLayer() and GPUEngineA:WillCapture3DLayerDirect() both rely on register
|
||||
// states that might change on a per-line basis. Therefore, we need to check these states on a
|
||||
|
@ -5502,7 +5528,7 @@ void GPUSubsystem::RenderLine(const size_t l)
|
|||
this->_engineMain->UpdatePropertiesWithoutRender(l);
|
||||
}
|
||||
|
||||
if (isFramebufferRenderNeeded[GPUEngineID_Sub] && !this->_willFrameSkip)
|
||||
if ( (isFramebufferRenderNeeded[GPUEngineID_Sub] || this->_engineSub->IsForceBlankSet()) && !this->_willFrameSkip)
|
||||
{
|
||||
switch (this->_engineSub->GetTargetDisplay()->GetColorFormat())
|
||||
{
|
||||
|
|
|
@ -117,7 +117,7 @@ typedef union
|
|||
u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB)
|
||||
u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels
|
||||
u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB)
|
||||
u8 ForceBlank:1; // 7: A+B;
|
||||
u8 ForceBlank:1; // 7: A+B; 0=Disable, 1=Enable (causes the line to render all white)
|
||||
|
||||
u8 BG0_Enable:1; // 8: A+B; 0=Disable, 1=Enable
|
||||
u8 BG1_Enable:1; // 9: A+B; 0=Disable, 1=Enable
|
||||
|
@ -143,7 +143,7 @@ typedef union
|
|||
u8 ExBGxPalette_Enable:1; // 30: A+B; 0=Disable, 1=Enable BG extended Palette
|
||||
u8 ExOBJPalette_Enable:1; // 31: A+B; 0=Disable, 1=Enable OBJ extended Palette
|
||||
#else
|
||||
u8 ForceBlank:1; // 7: A+B;
|
||||
u8 ForceBlank:1; // 7: A+B; 0=Disable, 1=Enable (causes the line to render all white)
|
||||
u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB)
|
||||
u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels
|
||||
u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB)
|
||||
|
@ -1543,6 +1543,8 @@ protected:
|
|||
void _RenderLine_SetupSprites(GPUEngineCompositorInfo &compInfo);
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST> void _RenderLine_Layers(GPUEngineCompositorInfo &compInfo);
|
||||
|
||||
void _RenderLineBlank(const size_t l);
|
||||
|
||||
void _HandleDisplayModeOff(const size_t l);
|
||||
void _HandleDisplayModeNormal(const size_t l);
|
||||
|
||||
|
@ -1609,6 +1611,7 @@ public:
|
|||
|
||||
const GPU_IOREG& GetIORegisterMap() const;
|
||||
|
||||
bool IsForceBlankSet() const;
|
||||
bool IsMasterBrightMaxOrMin() const;
|
||||
|
||||
bool GetEnableState();
|
||||
|
|
|
@ -95,6 +95,7 @@ libdesmume_a_SOURCES = \
|
|||
addons/slot2_none.cpp \
|
||||
addons/slot2_rumblepak.cpp \
|
||||
addons/slot2_guitarGrip.cpp \
|
||||
addons/slot2_hcv1000.cpp \
|
||||
addons/slot2_expMemory.cpp \
|
||||
addons/slot2_piano.cpp \
|
||||
addons/slot2_passme.cpp \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 shash
|
||||
Copyright (C) 2008-2023 DeSmuME team
|
||||
Copyright (C) 2008-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,44 +20,41 @@
|
|||
#ifndef OGLRENDER_3_2_H
|
||||
#define OGLRENDER_3_2_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/glcorearb.h>
|
||||
|
||||
#define OGLEXT(procPtr, func) procPtr func = NULL;
|
||||
#define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func);
|
||||
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
|
||||
#elif defined(__APPLE__)
|
||||
#include <OpenGL/gl3.h>
|
||||
#include <OpenGL/gl3ext.h>
|
||||
|
||||
// Ignore dynamic linking on Apple OS
|
||||
#define OGLEXT(procPtr, func)
|
||||
#define INITOGLEXT(procPtr, func)
|
||||
#define EXTERNOGLEXT(procPtr, func)
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/glx.h>
|
||||
#include "utils/glcorearb.h"
|
||||
|
||||
#define OGLEXT(procPtr, func) procPtr func = NULL;
|
||||
#define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func);
|
||||
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
|
||||
#endif
|
||||
|
||||
// Check minimum OpenGL header version
|
||||
#if !defined(GL_VERSION_3_2)
|
||||
#error OpenGL requires v3.2 headers or later.
|
||||
#endif
|
||||
|
||||
#include "OGLRender.h"
|
||||
|
||||
#define MAX_CLIPPED_POLY_COUNT_FOR_UBO 16384
|
||||
|
||||
extern const char *GeometryVtxShader_150;
|
||||
extern const char *GeometryFragShader_150;
|
||||
extern const char *GeometryZeroDstAlphaPixelMaskVtxShader_150;
|
||||
extern const char *GeometryZeroDstAlphaPixelMaskFragShader_150;
|
||||
extern const char *MSGeometryZeroDstAlphaPixelMaskFragShader_150;
|
||||
extern const char *EdgeMarkVtxShader_150;
|
||||
extern const char *EdgeMarkFragShader_150;
|
||||
extern const char *FogVtxShader_150;
|
||||
extern const char *FogFragShader_150;
|
||||
extern const char *FramebufferOutputVtxShader_150;
|
||||
extern const char *FramebufferOutput6665FragShader_150;
|
||||
|
||||
// A port that wants to use the OpenGL 3.2 renderer must assign the two following functions
|
||||
// to OGLLoadEntryPoints_3_2_Func and OGLCreateRenderer_3_2_Func, respectively.
|
||||
//
|
||||
// In addition, the port must add the following GPU3DInterface objects to core3DList:
|
||||
// - gpu3Dgl: Automatically selects the most fully featured version of standard OpenGL that
|
||||
// is available on the host system, prefering OpenGL 3.2 Core Profile.
|
||||
// - gpu3Dgl_3_2: Selects the OpenGL 3.2 Core Profile renderer, and returns an error if it
|
||||
// is not available on the host system.
|
||||
//
|
||||
// Finally, the port must call GPU->Set3DRendererByID() and pass in the index where
|
||||
// gpu3Dgl_3_2 exists in core3DList so that the emulator can create the appropriate
|
||||
// OpenGLRenderer object.
|
||||
//
|
||||
// Example code:
|
||||
// OGLLoadEntryPoints_3_2_Func = &OGLLoadEntryPoints_3_2;
|
||||
// OGLCreateRenderer_3_2_Func = &OGLCreateRenderer_3_2;
|
||||
// GPU3DInterface *core3DList[] = { &gpu3DNull, &gpu3DRasterize, &gpu3Dgl_3_2, NULL };
|
||||
// GPU->Set3DRendererByID(2);
|
||||
|
||||
void OGLLoadEntryPoints_3_2();
|
||||
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr);
|
||||
|
||||
|
@ -65,6 +62,8 @@ class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1
|
|||
{
|
||||
protected:
|
||||
bool _is64kUBOSupported;
|
||||
bool _isTBOSupported;
|
||||
bool _isShaderFixedLocationSupported;
|
||||
bool _isDualSourceBlendingSupported;
|
||||
bool _isSampleShadingSupported;
|
||||
bool _isConservativeDepthSupported;
|
||||
|
@ -73,8 +72,7 @@ protected:
|
|||
GLsync _syncBufferSetup;
|
||||
CACHE_ALIGN OGLPolyStates _pendingPolyStates[CLIPPED_POLYLIST_SIZE];
|
||||
|
||||
virtual Render3DError InitExtensions();
|
||||
|
||||
virtual Render3DError CreatePBOs();
|
||||
virtual Render3DError CreateFBOs();
|
||||
virtual void DestroyFBOs();
|
||||
virtual Render3DError CreateMultisampledFBO(GLsizei numSamples);
|
||||
|
@ -94,7 +92,6 @@ protected:
|
|||
virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
|
||||
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
|
||||
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
|
||||
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
|
||||
virtual Render3DError EnableVertexAttributes();
|
||||
virtual Render3DError DisableVertexAttributes();
|
||||
|
@ -111,13 +108,15 @@ protected:
|
|||
virtual void SetPolygonIndex(const size_t index);
|
||||
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing);
|
||||
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
|
||||
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
|
||||
|
||||
public:
|
||||
OpenGLRenderer_3_2();
|
||||
~OpenGLRenderer_3_2();
|
||||
|
||||
virtual Render3DError InitExtensions();
|
||||
virtual Render3DError RenderFinish();
|
||||
virtual Render3DError RenderPowerOff();
|
||||
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,892 @@
|
|||
/*
|
||||
Copyright (C) 2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "OGLRender_ES3.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "utils/bits.h"
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "NDSSystem.h"
|
||||
|
||||
|
||||
// Vertex shader for geometry, GLSL ES 3.00
|
||||
static const char *GeometryVtxShader_ES300 = {"\
|
||||
IN_VTX_POSITION vec4 inPosition;\n\
|
||||
IN_VTX_TEXCOORD0 vec2 inTexCoord0;\n\
|
||||
IN_VTX_COLOR vec3 inColor; \n\
|
||||
\n\
|
||||
#if IS_USING_UBO_POLY_STATES\n\
|
||||
layout (std140) uniform PolyStates\n\
|
||||
{\n\
|
||||
ivec4 value[4096];\n\
|
||||
} polyState;\n\
|
||||
#elif IS_USING_TBO_POLY_STATES\n\
|
||||
uniform highp isamplerBuffer PolyStates;\n\
|
||||
#else\n\
|
||||
uniform highp isampler2D PolyStates;\n\
|
||||
#endif\n\
|
||||
uniform mediump int polyIndex;\n\
|
||||
uniform bool polyDrawShadow;\n\
|
||||
\n\
|
||||
out vec2 vtxTexCoord;\n\
|
||||
out vec4 vtxColor;\n\
|
||||
flat out lowp int polyID;\n\
|
||||
flat out lowp int polyMode;\n\
|
||||
flat out lowp int polyIsWireframe;\n\
|
||||
flat out lowp int polyEnableFog;\n\
|
||||
flat out lowp int polySetNewDepthForTranslucent;\n\
|
||||
flat out lowp int polyEnableTexture;\n\
|
||||
flat out lowp int texSingleBitAlpha;\n\
|
||||
flat out lowp int polyIsBackFacing;\n\
|
||||
flat out lowp int isPolyDrawable;\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
#if IS_USING_UBO_POLY_STATES\n\
|
||||
ivec4 polyStateVec = polyState.value[polyIndex >> 2];\n\
|
||||
int polyStateBits = polyStateVec[polyIndex & 0x03];\n\
|
||||
#elif IS_USING_TBO_POLY_STATES\n\
|
||||
int polyStateBits = texelFetch(PolyStates, polyIndex).r;\n\
|
||||
#else\n\
|
||||
int polyStateBits = texelFetch(PolyStates, ivec2(polyIndex & 0x00FF, (polyIndex >> 8) & 0x007F), 0).r;\n\
|
||||
#endif\n\
|
||||
int texSizeShiftS = (polyStateBits >> 18) & 0x07;\n\
|
||||
int texSizeShiftT = (polyStateBits >> 21) & 0x07;\n\
|
||||
\n\
|
||||
float polyAlpha = float((polyStateBits >> 8) & 0x1F) / 31.0;\n\
|
||||
vec2 polyTexScale = vec2(1.0 / float(8 << texSizeShiftS), 1.0 / float(8 << texSizeShiftT));\n\
|
||||
\n\
|
||||
polyID = (polyStateBits >> 0) & 0x3F;\n\
|
||||
polyMode = (polyStateBits >> 6) & 0x03;\n\
|
||||
polyIsWireframe = (polyStateBits >> 13) & 0x01;\n\
|
||||
polyEnableFog = (polyStateBits >> 14) & 0x01;\n\
|
||||
polySetNewDepthForTranslucent = (polyStateBits >> 15) & 0x01;\n\
|
||||
polyEnableTexture = (polyStateBits >> 16) & 0x01;\n\
|
||||
texSingleBitAlpha = (polyStateBits >> 17) & 0x01;\n\
|
||||
polyIsBackFacing = (polyStateBits >> 24) & 0x01;\n\
|
||||
\n\
|
||||
isPolyDrawable = int((polyMode != 3) || polyDrawShadow);\n\
|
||||
\n\
|
||||
mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\
|
||||
vec2( 0.0, polyTexScale.y)); \n\
|
||||
\n\
|
||||
vtxTexCoord = (texScaleMtx * inTexCoord0) / 16.0;\n\
|
||||
vtxColor = vec4(inColor / 63.0, polyAlpha);\n\
|
||||
gl_Position = inPosition / 4096.0;\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
// Fragment shader for geometry, GLSL ES 3.00
|
||||
static const char *GeometryFragShader_ES300 = {"\
|
||||
in vec2 vtxTexCoord;\n\
|
||||
in vec4 vtxColor;\n\
|
||||
flat in lowp int polyID;\n\
|
||||
flat in lowp int polyMode;\n\
|
||||
flat in lowp int polyIsWireframe;\n\
|
||||
flat in lowp int polyEnableFog;\n\
|
||||
flat in lowp int polySetNewDepthForTranslucent;\n\
|
||||
flat in lowp int polyEnableTexture;\n\
|
||||
flat in lowp int texSingleBitAlpha;\n\
|
||||
flat in lowp int polyIsBackFacing;\n\
|
||||
flat in lowp int isPolyDrawable;\n\
|
||||
\n\
|
||||
layout (std140) uniform RenderStates\n\
|
||||
{\n\
|
||||
bool enableAntialiasing;\n\
|
||||
bool enableFogAlphaOnly;\n\
|
||||
int clearPolyID;\n\
|
||||
float clearDepth;\n\
|
||||
float alphaTestRef;\n\
|
||||
float fogOffset;\n\
|
||||
float fogStep;\n\
|
||||
float pad_0;\n\
|
||||
vec4 fogColor;\n\
|
||||
vec4 edgeColor[8];\n\
|
||||
vec4 toonColor[32];\n\
|
||||
} state;\n\
|
||||
\n\
|
||||
uniform sampler2D texRenderObject;\n\
|
||||
uniform bool texDrawOpaque;\n\
|
||||
uniform bool drawModeDepthEqualsTest;\n\
|
||||
uniform bool polyDrawShadow;\n\
|
||||
uniform float polyDepthOffset;\n\
|
||||
\n\
|
||||
OUT_COLOR vec4 outFragColor;\n\
|
||||
\n\
|
||||
#if DRAW_MODE_OPAQUE\n\
|
||||
OUT_WORKING_BUFFER vec4 outDstBackFacing;\n\
|
||||
#elif USE_DEPTH_LEQUAL_POLYGON_FACING\n\
|
||||
uniform sampler2D inDstBackFacing;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if ENABLE_EDGE_MARK\n\
|
||||
OUT_POLY_ID vec4 outPolyID;\n\
|
||||
#endif\n\
|
||||
#if ENABLE_FOG\n\
|
||||
OUT_FOG_ATTRIBUTES vec4 outFogAttributes;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\
|
||||
bool isOpaqueDstBackFacing = bool( texelFetch(inDstBackFacing, ivec2(gl_FragCoord.xy), 0).r );\n\
|
||||
if ( drawModeDepthEqualsTest && (bool(polyIsBackFacing) || !isOpaqueDstBackFacing) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec4 mainTexColor = (ENABLE_TEXTURE_SAMPLING && bool(polyEnableTexture)) ? texture(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0);\n\
|
||||
\n\
|
||||
if (!bool(texSingleBitAlpha))\n\
|
||||
{\n\
|
||||
if (texDrawOpaque)\n\
|
||||
{\n\
|
||||
if ( (polyMode != 1) && (mainTexColor.a <= 0.999) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
else\n\
|
||||
{\n\
|
||||
if ( ((polyMode != 1) && (mainTexColor.a * vtxColor.a > 0.999)) || ((polyMode == 1) && (vtxColor.a > 0.999)) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
}\n\
|
||||
#if USE_TEXTURE_SMOOTHING\n\
|
||||
else\n\
|
||||
{\n\
|
||||
if (mainTexColor.a < 0.500)\n\
|
||||
{\n\
|
||||
mainTexColor.a = 0.0;\n\
|
||||
}\n\
|
||||
else\n\
|
||||
{\n\
|
||||
mainTexColor.rgb = mainTexColor.rgb / mainTexColor.a;\n\
|
||||
mainTexColor.a = 1.0;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
outFragColor = mainTexColor * vtxColor;\n\
|
||||
\n\
|
||||
if (polyMode == 1)\n\
|
||||
{\n\
|
||||
outFragColor.rgb = (ENABLE_TEXTURE_SAMPLING && bool(polyEnableTexture)) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb;\n\
|
||||
outFragColor.a = vtxColor.a;\n\
|
||||
}\n\
|
||||
else if (polyMode == 2)\n\
|
||||
{\n\
|
||||
vec3 newToonColor = state.toonColor[int((vtxColor.r * 31.0) + 0.5)].rgb;\n\
|
||||
#if TOON_SHADING_MODE\n\
|
||||
outFragColor.rgb = min((mainTexColor.rgb * vtxColor.r) + newToonColor.rgb, 1.0);\n\
|
||||
#else\n\
|
||||
outFragColor.rgb = mainTexColor.rgb * newToonColor.rgb;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
else if ((polyMode == 3) && polyDrawShadow)\n\
|
||||
{\n\
|
||||
outFragColor = vtxColor;\n\
|
||||
}\n\
|
||||
\n\
|
||||
if ( (isPolyDrawable != 0) && ((outFragColor.a < 0.001) || (ENABLE_ALPHA_TEST && outFragColor.a < state.alphaTestRef)) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#if ENABLE_EDGE_MARK\n\
|
||||
outPolyID = (isPolyDrawable != 0) ? vec4( float(polyID)/63.0, float(polyIsWireframe == 1), 0.0, float(outFragColor.a > 0.999) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
|
||||
#endif\n\
|
||||
#if ENABLE_FOG\n\
|
||||
outFogAttributes = (isPolyDrawable != 0) ? vec4( float(polyEnableFog), 0.0, 0.0, float((outFragColor.a > 0.999) ? 1.0 : 0.5) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
|
||||
#endif\n\
|
||||
#if DRAW_MODE_OPAQUE\n\
|
||||
outDstBackFacing = vec4(float(polyIsBackFacing), 0.0, 0.0, 1.0);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\
|
||||
// It is tempting to perform the NDS depth calculation in the vertex shader rather than in the fragment shader.\n\
|
||||
// Resist this temptation! It is much more reliable to do the depth calculation in the fragment shader due to\n\
|
||||
// subtle interpolation differences between various GPUs and/or drivers. If the depth calculation is not done\n\
|
||||
// here, then it is very possible for the user to experience Z-fighting in certain rendering situations.\n\
|
||||
\n\
|
||||
#if ENABLE_W_DEPTH\n\
|
||||
gl_FragDepth = clamp( ((1.0/gl_FragCoord.w) * (4096.0/16777215.0)) + polyDepthOffset, 0.0, 1.0 );\n\
|
||||
#else\n\
|
||||
// hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly\n\
|
||||
gl_FragDepth = clamp( (floor(gl_FragCoord.z * 4194303.0) * (4.0/16777215.0)) + polyDepthOffset, 0.0, 1.0 );\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
void OGLLoadEntryPoints_ES_3_0()
|
||||
{
|
||||
OGLLoadEntryPoints_3_2();
|
||||
}
|
||||
|
||||
void OGLCreateRenderer_ES_3_0(OpenGLRenderer **rendererPtr)
|
||||
{
|
||||
if (IsOpenGLDriverVersionSupported(3, 0, 0))
|
||||
{
|
||||
*rendererPtr = new OpenGLESRenderer_3_0;
|
||||
(*rendererPtr)->SetVersion(3, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLESRenderer_3_0::OpenGLESRenderer_3_0()
|
||||
{
|
||||
_variantID = OpenGLVariantID_ES_3_0;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::InitExtensions()
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
|
||||
// Get OpenGL extensions
|
||||
std::set<std::string> oglExtensionSet;
|
||||
this->GetExtensionSet(&oglExtensionSet);
|
||||
|
||||
// Get host GPU device properties
|
||||
GLint maxUBOSize = 0;
|
||||
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUBOSize);
|
||||
this->_is64kUBOSupported = (maxUBOSize >= 65536);
|
||||
|
||||
// TBOs are only supported in ES 3.2.
|
||||
this->_isTBOSupported = IsOpenGLDriverVersionSupported(3, 2, 0);
|
||||
|
||||
// Fixed locations in shaders are supported in ES 3.0 by default.
|
||||
this->_isShaderFixedLocationSupported = true;
|
||||
|
||||
GLfloat maxAnisotropyOGL = 1.0f;
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyOGL);
|
||||
this->_deviceInfo.maxAnisotropy = (float)maxAnisotropyOGL;
|
||||
|
||||
// OpenGL ES 3.0 needs to look up the best format and data type for glReadPixels.
|
||||
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &OGLRef.readPixelsBestFormat);
|
||||
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &OGLRef.readPixelsBestDataType);
|
||||
|
||||
this->_deviceInfo.isEdgeMarkSupported = true;
|
||||
this->_deviceInfo.isFogSupported = true;
|
||||
|
||||
// Need to generate this texture first because FBO creation needs it.
|
||||
// This texture is only required by shaders, and so if shader creation
|
||||
// fails, then we can immediately delete this texture if an error occurs.
|
||||
glGenTextures(1, &OGLRef.texFinalColorID);
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// OpenGL ES v3.0 should have all the necessary features to be able to flip and convert the framebuffer.
|
||||
this->willFlipOnlyFramebufferOnGPU = true;
|
||||
this->willFlipAndConvertFramebufferOnGPU = true;
|
||||
|
||||
this->_enableTextureSmoothing = CommonSettings.GFX3D_Renderer_TextureSmoothing;
|
||||
this->_emulateShadowPolygon = CommonSettings.OpenGL_Emulation_ShadowPolygon;
|
||||
this->_emulateSpecialZeroAlphaBlending = CommonSettings.OpenGL_Emulation_SpecialZeroAlphaBlending;
|
||||
this->_emulateNDSDepthCalculation = CommonSettings.OpenGL_Emulation_NDSDepthCalculation;
|
||||
this->_emulateDepthLEqualPolygonFacing = CommonSettings.OpenGL_Emulation_DepthLEqualPolygonFacing;
|
||||
|
||||
// Load and create shaders. Return on any error, since ES 3.0 makes shaders mandatory.
|
||||
this->isShaderSupported = true;
|
||||
|
||||
error = this->CreateGeometryPrograms();
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
error = this->CreateGeometryZeroDstAlphaProgram(GeometryZeroDstAlphaPixelMaskVtxShader_150, GeometryZeroDstAlphaPixelMaskFragShader_150);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
INFO("OpenGL: Successfully created geometry shaders.\n");
|
||||
error = this->InitPostprocessingPrograms(EdgeMarkVtxShader_150,
|
||||
EdgeMarkFragShader_150,
|
||||
FramebufferOutputVtxShader_150,
|
||||
FramebufferOutput6665FragShader_150,
|
||||
NULL);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->DestroyGeometryZeroDstAlphaProgram();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
this->isVBOSupported = true;
|
||||
this->CreateVBOs();
|
||||
|
||||
this->isPBOSupported = true;
|
||||
this->CreatePBOs();
|
||||
|
||||
this->isVAOSupported = true;
|
||||
this->CreateVAOs();
|
||||
|
||||
// Load and create FBOs. Return on any error, since v3.2 Core Profile makes FBOs mandatory.
|
||||
this->isFBOSupported = true;
|
||||
error = this->CreateFBOs();
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
this->isFBOSupported = false;
|
||||
return error;
|
||||
}
|
||||
|
||||
this->isMultisampledFBOSupported = true;
|
||||
this->_selectedMultisampleSize = CommonSettings.GFX3D_Renderer_MultisampleSize;
|
||||
|
||||
GLint maxSamplesOGL = 0;
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &maxSamplesOGL);
|
||||
this->_deviceInfo.maxSamples = (u8)maxSamplesOGL;
|
||||
|
||||
if (this->_deviceInfo.maxSamples >= 2)
|
||||
{
|
||||
// Try and initialize the multisampled FBOs with the GFX3D_Renderer_MultisampleSize.
|
||||
// However, if the client has this set to 0, then set sampleSize to 2 in order to
|
||||
// force the generation and the attachments of the buffers at a meaningful sample
|
||||
// size. If GFX3D_Renderer_MultisampleSize is 0, then we can deallocate the buffer
|
||||
// memory afterwards.
|
||||
GLsizei sampleSize = this->GetLimitedMultisampleSize();
|
||||
if (sampleSize == 0)
|
||||
{
|
||||
sampleSize = 2;
|
||||
}
|
||||
|
||||
error = this->CreateMultisampledFBO(sampleSize);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
this->isMultisampledFBOSupported = false;
|
||||
}
|
||||
|
||||
// If GFX3D_Renderer_MultisampleSize is 0, then we can deallocate the buffers now
|
||||
// in order to save some memory.
|
||||
if (this->_selectedMultisampleSize == 0)
|
||||
{
|
||||
this->ResizeMultisampledFBOs(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->isMultisampledFBOSupported = false;
|
||||
INFO("OpenGL: Driver does not support at least 2x multisampled FBOs.\n");
|
||||
}
|
||||
|
||||
this->_isDepthLEqualPolygonFacingSupported = true;
|
||||
this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported);
|
||||
|
||||
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateGeometryPrograms()
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
// Create shader resources.
|
||||
if (OGLRef.uboRenderStatesID == 0)
|
||||
{
|
||||
glGenBuffers(1, &OGLRef.uboRenderStatesID);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboRenderStatesID);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(OGLRenderStates), NULL, GL_DYNAMIC_DRAW);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, OGLBindingPointID_RenderStates, OGLRef.uboRenderStatesID);
|
||||
}
|
||||
|
||||
if (this->_is64kUBOSupported)
|
||||
{
|
||||
// Try transferring the polygon states through a UBO first. This is the fastest method,
|
||||
// but requires a GPU that supports 64k UBO transfers.
|
||||
if (OGLRef.uboPolyStatesID == 0)
|
||||
{
|
||||
glGenBuffers(1, &OGLRef.uboPolyStatesID);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboPolyStatesID);
|
||||
glBufferData(GL_UNIFORM_BUFFER, MAX_CLIPPED_POLY_COUNT_FOR_UBO * sizeof(OGLPolyStates), NULL, GL_DYNAMIC_DRAW);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, OGLBindingPointID_PolyStates, OGLRef.uboPolyStatesID);
|
||||
}
|
||||
}
|
||||
#ifdef GL_ES_VERSION_3_2
|
||||
else if (this->_isTBOSupported)
|
||||
{
|
||||
// If for some reason the GPU doesn't support 64k UBOs but still supports OpenGL ES 3.2,
|
||||
// then use a TBO as the second fastest method.
|
||||
if (OGLRef.tboPolyStatesID == 0)
|
||||
{
|
||||
// Set up poly states TBO
|
||||
glGenBuffers(1, &OGLRef.tboPolyStatesID);
|
||||
glBindBuffer(GL_TEXTURE_BUFFER, OGLRef.tboPolyStatesID);
|
||||
glBufferData(GL_TEXTURE_BUFFER, CLIPPED_POLYLIST_SIZE * sizeof(OGLPolyStates), NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
glGenTextures(1, &OGLRef.texPolyStatesID);
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_PolyStates);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, OGLRef.texPolyStatesID);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, OGLRef.tboPolyStatesID);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
// For compatibility reasons, we can transfer the polygon states through a plain old
|
||||
// integer texture.
|
||||
glGenTextures(1, &OGLRef.texPolyStatesID);
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_PolyStates);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texPolyStatesID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, 256, 128, 0, GL_RED_INTEGER, GL_INT, NULL);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
glGenTextures(1, &OGLRef.texFogDensityTableID);
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texFogDensityTableID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 1, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
OGLGeometryFlags programFlags;
|
||||
programFlags.value = 0;
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
vsHeader << "\n";
|
||||
vsHeader << "#define IS_USING_UBO_POLY_STATES " << ((OGLRef.uboPolyStatesID != 0) ? 1 : 0) << "\n";
|
||||
vsHeader << "#define IS_USING_TBO_POLY_STATES " << ((OGLRef.tboPolyStatesID != 0) ? 1 : 0) << "\n";
|
||||
vsHeader << "#define DEPTH_EQUALS_TEST_TOLERANCE " << DEPTH_EQUALS_TEST_TOLERANCE << ".0\n";
|
||||
vsHeader << "\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(GeometryVtxShader_ES300);
|
||||
|
||||
for (size_t flagsValue = 0; flagsValue < 128; flagsValue++, programFlags.value++)
|
||||
{
|
||||
std::stringstream shaderFlags;
|
||||
if (this->_isShaderFixedLocationSupported)
|
||||
{
|
||||
shaderFlags << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
shaderFlags << "#define OUT_WORKING_BUFFER layout (location = " << GeometryAttachmentWorkingBuffer[programFlags.DrawBuffersMode] << ") out\n";
|
||||
shaderFlags << "#define OUT_POLY_ID layout (location = " << GeometryAttachmentPolyID[programFlags.DrawBuffersMode] << ") out\n";
|
||||
shaderFlags << "#define OUT_FOG_ATTRIBUTES layout (location = " << GeometryAttachmentFogAttributes[programFlags.DrawBuffersMode] << ") out\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
shaderFlags << "#define OUT_COLOR out\n";
|
||||
shaderFlags << "#define OUT_WORKING_BUFFER out\n";
|
||||
shaderFlags << "#define OUT_POLY_ID out\n";
|
||||
shaderFlags << "#define OUT_FOG_ATTRIBUTES out\n";
|
||||
}
|
||||
shaderFlags << "\n";
|
||||
shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define USE_NDS_DEPTH_CALCULATION " << ((this->_emulateNDSDepthCalculation) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define USE_DEPTH_LEQUAL_POLYGON_FACING " << ((this->_emulateDepthLEqualPolygonFacing) ? 1 : 0) << "\n";
|
||||
shaderFlags << "\n";
|
||||
shaderFlags << "#define ENABLE_W_DEPTH " << ((programFlags.EnableWDepth) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define ENABLE_ALPHA_TEST " << ((programFlags.EnableAlphaTest) ? "true\n" : "false\n");
|
||||
shaderFlags << "#define ENABLE_TEXTURE_SAMPLING " << ((programFlags.EnableTextureSampling) ? "true\n" : "false\n");
|
||||
shaderFlags << "#define TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define DRAW_MODE_OPAQUE " << ((programFlags.OpaqueDrawMode) ? 1 : 0) << "\n";
|
||||
shaderFlags << "\n";
|
||||
|
||||
std::string fragShaderCode = shaderHeader.str() + shaderFlags.str() + std::string(GeometryFragShader_ES300);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexGeometryShaderID,
|
||||
OGLRef.fragmentGeometryShaderID[flagsValue],
|
||||
OGLRef.programGeometryID[flagsValue],
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL: Failed to create the GEOMETRY shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programGeometryID[flagsValue]);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programGeometryID[flagsValue]))
|
||||
{
|
||||
INFO("OpenGL: Failed to link the GEOMETRY shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programGeometryID[flagsValue]);
|
||||
glUseProgram(OGLRef.programGeometryID[flagsValue]);
|
||||
|
||||
// Set up render states UBO
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "RenderStates");
|
||||
glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
GLint uboSize = 0;
|
||||
glGetActiveUniformBlockiv(OGLRef.programGeometryID[flagsValue], uniformBlockRenderStates, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize);
|
||||
assert(uboSize == sizeof(OGLRenderStates));
|
||||
|
||||
const GLint uniformTexRenderObject = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texRenderObject");
|
||||
glUniform1i(uniformTexRenderObject, 0);
|
||||
|
||||
if (OGLRef.uboPolyStatesID != 0)
|
||||
{
|
||||
const GLuint uniformBlockPolyStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "PolyStates");
|
||||
glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockPolyStates, OGLBindingPointID_PolyStates);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLint uniformTexBufferPolyStates = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "PolyStates");
|
||||
glUniform1i(uniformTexBufferPolyStates, OGLTextureUnitID_PolyStates);
|
||||
}
|
||||
|
||||
if (this->_emulateDepthLEqualPolygonFacing && !programFlags.OpaqueDrawMode)
|
||||
{
|
||||
const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inDstBackFacing");
|
||||
glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor);
|
||||
}
|
||||
|
||||
OGLRef.uniformTexDrawOpaque[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texDrawOpaque");
|
||||
OGLRef.uniformDrawModeDepthEqualsTest[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "drawModeDepthEqualsTest");
|
||||
OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow");
|
||||
OGLRef.uniformPolyStateIndex[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyIndex");
|
||||
OGLRef.uniformPolyDepthOffset[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffset");
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vtxShaderGeometryZeroDstAlphaID,
|
||||
OGLRef.fragShaderGeometryZeroDstAlphaID,
|
||||
OGLRef.programGeometryZeroDstAlphaID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL: Failed to create the GEOMETRY ZERO DST ALPHA shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryZeroDstAlphaProgram();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programGeometryZeroDstAlphaID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programGeometryZeroDstAlphaID))
|
||||
{
|
||||
INFO("OpenGL: Failed to link the GEOMETRY ZERO DST ALPHA shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryZeroDstAlphaProgram();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programGeometryZeroDstAlphaID);
|
||||
glUseProgram(OGLRef.programGeometryZeroDstAlphaID);
|
||||
|
||||
const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programGeometryZeroDstAlphaID, "texInFragColor");
|
||||
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::stringstream fsHeader;
|
||||
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexEdgeMarkShaderID,
|
||||
OGLRef.fragmentEdgeMarkShaderID,
|
||||
OGLRef.programEdgeMarkID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL: Failed to create the EDGE MARK shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyEdgeMarkProgram();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programEdgeMarkID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programEdgeMarkID))
|
||||
{
|
||||
INFO("OpenGL: Failed to link the EDGE MARK shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyEdgeMarkProgram();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programEdgeMarkID);
|
||||
glUseProgram(OGLRef.programEdgeMarkID);
|
||||
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programEdgeMarkID, "RenderStates");
|
||||
glUniformBlockBinding(OGLRef.programEdgeMarkID, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
const GLint uniformTexGDepth = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth");
|
||||
const GLint uniformTexGPolyID = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID");
|
||||
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
|
||||
glUniform1i(uniformTexGPolyID, OGLTextureUnitID_GPolyID);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if (vtxShaderCString == NULL)
|
||||
{
|
||||
INFO("OpenGL: The FOG vertex shader is unavailable.\n");
|
||||
error = OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR;
|
||||
return error;
|
||||
}
|
||||
else if (fragShaderCString == NULL)
|
||||
{
|
||||
INFO("OpenGL: The FOG fragment shader is unavailable.\n");
|
||||
error = OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR;
|
||||
return error;
|
||||
}
|
||||
|
||||
const s32 fogOffset = fogProgramKey.offset;
|
||||
const GLfloat fogOffsetf = (GLfloat)fogOffset / 32767.0f;
|
||||
const s32 fogStep = 0x0400 >> fogProgramKey.shift;
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::stringstream fsHeader;
|
||||
fsHeader << "#define USE_DUAL_SOURCE_BLENDING " << ((this->_isDualSourceBlendingSupported) ? 1 : 0) << "\n";
|
||||
fsHeader << "\n";
|
||||
fsHeader << "#define FOG_OFFSET " << fogOffset << "\n";
|
||||
fsHeader << "#define FOG_OFFSETF " << fogOffsetf << (((fogOffsetf == 0.0f) || (fogOffsetf == 1.0f)) ? ".0" : "") << "\n";
|
||||
fsHeader << "#define FOG_STEP " << fogStep << "\n";
|
||||
fsHeader << "\n";
|
||||
fsHeader << "#define OUT_FOG_COLOR layout (location = 0, index = 0) out\n";
|
||||
fsHeader << "#define OUT_FOG_WEIGHT layout (location = 0, index = 1) out\n";
|
||||
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
OGLFogShaderID shaderID;
|
||||
shaderID.program = 0;
|
||||
shaderID.fragShader = 0;
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexFogShaderID,
|
||||
shaderID.fragShader,
|
||||
shaderID.program,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
|
||||
this->_fogProgramMap[fogProgramKey.key] = shaderID;
|
||||
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL: Failed to create the FOG shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFogProgram(fogProgramKey);
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(shaderID.program);
|
||||
if (!this->ValidateShaderProgramLink(shaderID.program))
|
||||
{
|
||||
INFO("OpenGL: Failed to link the FOG shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFogProgram(fogProgramKey);
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(shaderID.program);
|
||||
glUseProgram(shaderID.program);
|
||||
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(shaderID.program, "RenderStates");
|
||||
glUniformBlockBinding(shaderID.program, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
const GLint uniformTexGDepth = glGetUniformLocation(shaderID.program, "texInFragDepth");
|
||||
const GLint uniformTexGFog = glGetUniformLocation(shaderID.program, "texInFogAttributes");
|
||||
const GLint uniformTexFogDensityTable = glGetUniformLocation(shaderID.program, "texFogDensityTable");
|
||||
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
|
||||
glUniform1i(uniformTexGFog, OGLTextureUnitID_FogAttr);
|
||||
glUniform1i(uniformTexFogDensityTable, OGLTextureUnitID_LookupTable);
|
||||
|
||||
const GLint uniformTexGColor = glGetUniformLocation(shaderID.program, "texInFragColor");
|
||||
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::stringstream fsHeader;
|
||||
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexFramebufferOutput6665ShaderID,
|
||||
OGLRef.fragmentFramebufferRGBA6665OutputShaderID,
|
||||
OGLRef.programFramebufferRGBA6665OutputID[outColorIndex],
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL: Failed to create the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFramebufferOutput6665Programs();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]))
|
||||
{
|
||||
INFO("OpenGL: Failed to link the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFramebufferOutput6665Programs();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]);
|
||||
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]);
|
||||
|
||||
const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], "texInFragColor");
|
||||
if (outColorIndex == 0)
|
||||
{
|
||||
glUniform1i(uniformTexGColor, OGLTextureUnitID_FinalColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
|
||||
}
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Copyright (C) 2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OGLRENDER_ES3_H
|
||||
#define OGLRENDER_ES3_H
|
||||
|
||||
#include "OGLRender_3_2.h"
|
||||
|
||||
// A port that wants to use the OpenGL ES renderer must assign the two following functions
|
||||
// to OGLLoadEntryPoints_ES_3_0_Func and OGLCreateRenderer_ES_3_0_Func, respectively.
|
||||
//
|
||||
// In addition, the port must add the following GPU3DInterface objects to core3DList:
|
||||
// - gpu3Dgl_ES_3_0: Selects the OpenGL ES 3.0 renderer, and returns an error if it is
|
||||
// not available on the host system.
|
||||
//
|
||||
// Finally, the port must call GPU->Set3DRendererByID() and pass in the index where
|
||||
// gpu3Dgl_ES_3_0 exists in core3DList so that the emulator can create the appropriate
|
||||
// OpenGLRenderer object.
|
||||
//
|
||||
// Example code:
|
||||
// OGLLoadEntryPoints_ES_3_0_Func = &OGLLoadEntryPoints_ES_3_0;
|
||||
// OGLCreateRenderer_ES_3_0_Func = &OGLCreateRenderer_ES_3_0;
|
||||
// GPU3DInterface *core3DList[] = { &gpu3DNull, &gpu3DRasterize, &gpu3Dgl_ES_3_0, NULL };
|
||||
// GPU->Set3DRendererByID(2);
|
||||
|
||||
void OGLLoadEntryPoints_ES_3_0();
|
||||
void OGLCreateRenderer_ES_3_0(OpenGLRenderer **rendererPtr);
|
||||
|
||||
class OpenGLESRenderer_3_0 : public OpenGLRenderer_3_2
|
||||
{
|
||||
protected:
|
||||
virtual Render3DError CreateGeometryPrograms();
|
||||
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
|
||||
public:
|
||||
OpenGLESRenderer_3_0();
|
||||
|
||||
virtual Render3DError InitExtensions();
|
||||
};
|
||||
|
||||
#endif // OGLRENDER_ES3_H
|
|
@ -1179,7 +1179,6 @@ template<int FORMAT> static FORCEINLINE void TestForLoop(SPU_struct *SPU, channe
|
|||
if(chan->repeat != 1)
|
||||
{
|
||||
SPU->KeyOff(chan->num);
|
||||
SPU->bufpos = SPU->buflength;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1235,13 +1234,16 @@ template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE, int CHANNELS>
|
|||
{
|
||||
s16 data = 0;
|
||||
s32 pos = chan->sampcntInt;
|
||||
switch(FORMAT)
|
||||
if(chan->status != CHANSTAT_STOPPED)
|
||||
{
|
||||
case 0: data = Fetch8BitData (chan, pos); break;
|
||||
case 1: data = Fetch16BitData(chan, pos); break;
|
||||
case 2: data = FetchADPCMData(chan, pos); break;
|
||||
case 3: data = FetchPSGData (chan, pos); break;
|
||||
default: break;
|
||||
switch(FORMAT)
|
||||
{
|
||||
case 0: data = Fetch8BitData (chan, pos); break;
|
||||
case 1: data = Fetch16BitData(chan, pos); break;
|
||||
case 2: data = FetchADPCMData(chan, pos); break;
|
||||
case 3: data = FetchPSGData (chan, pos); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
chan->pcm16bOffs++;
|
||||
chan->pcm16b[SPUCHAN_PCM16B_AT(chan->pcm16bOffs)] = data;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2013-2105 DeSmuME team
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
//HCV-1000 emulation code adapted from GBE+: https://github.com/shonumi/gbe-plus
|
||||
|
||||
/*
|
||||
Modifications Copyright (C) 2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
u8 hcv1000_cnt;
|
||||
char hcv1000_data[16];
|
||||
|
||||
class Slot2_HCV1000 : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Sega Card Reader", "Sega Card Reader(HCV-1000) add-on", 0x09);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual bool init()
|
||||
{
|
||||
hcv1000_cnt = 0;
|
||||
memset(hcv1000_data, 0x5F, 16);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
|
||||
{
|
||||
if (addr == 0xA000000) { hcv1000_cnt = (val & 0x83); }
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
u8 slot_byte = 0xFF;
|
||||
//Reading these cart addresses is for detection
|
||||
if (addr < 0x8020000)
|
||||
{
|
||||
u8 data = 0xF0 | ((addr & 0x1F) >> 1);
|
||||
slot_byte = (addr & 0x1) ? 0xFD : data;
|
||||
}
|
||||
|
||||
//HCV_CNT
|
||||
else if (addr == 0xA000000) { slot_byte = hcv1000_cnt; }
|
||||
|
||||
//HCV_DATA
|
||||
else if ((addr >= 0xA000010) && (addr <= 0xA00001F))
|
||||
{
|
||||
slot_byte = (u8)hcv1000_data[addr & 0xF];
|
||||
}
|
||||
|
||||
return slot_byte;
|
||||
}
|
||||
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xFDFD; };
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFDFDFDFD; };
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_HCV1000() { return new Slot2_HCV1000(); }
|
||||
|
||||
void HCV1000_setReady()
|
||||
{
|
||||
hcv1000_cnt &= ~0x80;
|
||||
}
|
||||
|
||||
void HCV1000_setBarcode(std::string barcode)
|
||||
{
|
||||
barcode.resize(16, '_');
|
||||
memcpy(hcv1000_data, barcode.c_str(), barcode.length());
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -24,22 +24,31 @@
|
|||
|
||||
#define CHEAT_VERSION_MAJOR 2
|
||||
#define CHEAT_VERSION_MINOR 0
|
||||
#define MAX_CHEAT_LIST 100
|
||||
#define MAX_XX_CODE 1024
|
||||
#define CHEAT_FILE_MIN_FGETS_BUFFER 32768
|
||||
#define CHEAT_DB_GAME_TITLE_SIZE 256
|
||||
|
||||
#define CHEAT_TYPE_EMPTY 0xFF
|
||||
#define CHEAT_TYPE_INTERNAL 0
|
||||
#define CHEAT_TYPE_AR 1
|
||||
#define CHEAT_TYPE_CODEBREAKER 2
|
||||
|
||||
enum CheatSystemError
|
||||
{
|
||||
CheatSystemError_NoError = 0,
|
||||
CheatSystemError_FileOpenFailed = 1,
|
||||
CheatSystemError_FileFormatInvalid = 2,
|
||||
CheatSystemError_GameNotFound = 3,
|
||||
CheatSystemError_LoadEntryError = 4,
|
||||
CheatSystemError_FileSaveFailed = 5,
|
||||
CheatSystemError_FileDoesNotExist = 6
|
||||
};
|
||||
|
||||
struct CHEATS_LIST
|
||||
{
|
||||
CHEATS_LIST()
|
||||
{
|
||||
memset(this,0,sizeof(*this));
|
||||
type = 0xFF;
|
||||
type = CHEAT_TYPE_EMPTY;
|
||||
}
|
||||
u8 type;
|
||||
u8 enabled;
|
||||
|
@ -48,7 +57,18 @@ struct CHEATS_LIST
|
|||
// 1 - can decrease
|
||||
// 2 - can increase
|
||||
u32 code[MAX_XX_CODE][2];
|
||||
char description[1024];
|
||||
|
||||
union
|
||||
{
|
||||
char description[1024];
|
||||
|
||||
struct
|
||||
{
|
||||
char descriptionMajor[512];
|
||||
char descriptionMinor[512];
|
||||
};
|
||||
};
|
||||
|
||||
u32 num;
|
||||
u8 size;
|
||||
};
|
||||
|
@ -151,71 +171,156 @@ public:
|
|||
void getListReset();
|
||||
};
|
||||
|
||||
enum CHEATS_DB_TYPE
|
||||
#define CHEATDB_OFFSET_FILE_DESCRIPTION 0x00000010
|
||||
#define CHEATDB_FILEOFFSET_FIRST_FAT_ENTRY 0x00000100
|
||||
|
||||
enum CheatDBFileFormat
|
||||
{
|
||||
CHEATS_DB_R4 = 0
|
||||
CheatDBFileFormat_Undefined = 0,
|
||||
CheatDBFileFormat_R4 = 1,
|
||||
CheatDBFileFormat_Unknown = 65535
|
||||
};
|
||||
|
||||
// This struct maps to the FAT entries in the R4 cheat database file.
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
typedef struct FAT_R4
|
||||
{
|
||||
u8 serial[4];
|
||||
u32 CRC;
|
||||
u8 serial[4];
|
||||
u32 CRC;
|
||||
u64 addr;
|
||||
} FAT_R4;
|
||||
#pragma pack(pop)
|
||||
|
||||
// Wrapper for a single entry in a memory block that contains data read from a cheat database file.
|
||||
// This struct also maintains the hierarchical relationships between entries.
|
||||
struct CheatDBEntry
|
||||
{
|
||||
u8 *base; // Pointer to the entry's base location in memory.
|
||||
char *name; // Pointer to the entry's name string.
|
||||
char *note; // Pointer to the entry's note string.
|
||||
u32 *codeLength; // Pointer to the entry's 32-bit code length in bytes. This value is NULL if the entry is a directory.
|
||||
u32 *codeData; // Pointer to the entry's code data, provided in pairs of 32-bit values. This value is NULL if the entry is a directory.
|
||||
|
||||
CheatDBEntry *parent;
|
||||
std::vector<CheatDBEntry> child;
|
||||
};
|
||||
typedef struct CheatDBEntry CheatDBEntry;
|
||||
|
||||
class CheatDBGame
|
||||
{
|
||||
protected:
|
||||
u32 _baseOffset; // This offset is relative to the file head.
|
||||
u32 _firstEntryOffset; // This offset is relative to the file head.
|
||||
u32 _encryptOffset; // This offset is relative to the memory address of this->_entryDataRawPtr.
|
||||
|
||||
u32 _rawDataSize;
|
||||
u32 _workingDataSize;
|
||||
u32 _crc;
|
||||
u32 _entryCount;
|
||||
|
||||
std::string _title;
|
||||
char _serial[4 + 1];
|
||||
|
||||
u8 *_entryDataRawPtr;
|
||||
u8 *_entryData;
|
||||
CheatDBEntry _entryRoot;
|
||||
u32 _cheatItemCount;
|
||||
|
||||
void _UpdateDirectoryParents(CheatDBEntry &directory);
|
||||
bool _CreateCheatItemFromCheatEntry(const CheatDBEntry &inEntry, const bool isHierarchical, CHEATS_LIST &outCheatItem);
|
||||
size_t _DirectoryAddCheatsFlat(const CheatDBEntry &directory, const bool isHierarchical, size_t cheatIndex, CHEATS_LIST *outCheatsList);
|
||||
|
||||
public:
|
||||
CheatDBGame();
|
||||
CheatDBGame(const u32 encryptOffset, const FAT_R4 &fat, const u32 rawDataSize);
|
||||
CheatDBGame(FILE *fp, const bool isEncrypted, const u32 encryptOffset, const FAT_R4 &fat, const u32 rawDataSize, u8 (&workingBuffer)[1024]);
|
||||
~CheatDBGame();
|
||||
|
||||
void SetInitialProperties(const u32 rawDataSize, const u32 encryptOffset, const FAT_R4 &fat);
|
||||
void LoadPropertiesFromFile(FILE *fp, const bool isEncrypted, u8 (&workingBuffer)[1024]);
|
||||
|
||||
u32 GetBaseOffset() const;
|
||||
u32 GetFirstEntryOffset() const;
|
||||
u32 GetEncryptOffset() const;
|
||||
u32 GetRawDataSize() const;
|
||||
u32 GetWorkingDataSize() const;
|
||||
u32 GetCRC() const;
|
||||
u32 GetEntryCount() const;
|
||||
u32 GetCheatItemCount() const;
|
||||
const char* GetTitle() const;
|
||||
const char* GetSerial() const;
|
||||
|
||||
const CheatDBEntry& GetEntryRoot() const;
|
||||
const u8* GetEntryRawData() const;
|
||||
bool IsEntryDataLoaded() const;
|
||||
|
||||
u8* LoadEntryData(FILE *fp, const bool isEncrypted);
|
||||
size_t ParseEntriesToCheatsListFlat(CHEATS_LIST *outCheatsList);
|
||||
};
|
||||
|
||||
typedef std::vector<CheatDBGame> CheatDBGameList;
|
||||
|
||||
class CheatDBFile
|
||||
{
|
||||
protected:
|
||||
std::string _path;
|
||||
std::string _description;
|
||||
std::string _formatString;
|
||||
|
||||
CheatDBFileFormat _format;
|
||||
bool _isEncrypted;
|
||||
size_t _size;
|
||||
|
||||
FILE *_fp;
|
||||
|
||||
CheatDBGame _ReadGame(const u32 encryptOffset, const FAT_R4 &fat, const u32 gameDataSize, u8 (&workingBuffer)[1024]);
|
||||
|
||||
public:
|
||||
CheatDBFile();
|
||||
~CheatDBFile();
|
||||
|
||||
static void R4Decrypt(u8 *buf, const size_t len, u64 n);
|
||||
static bool ReadToBuffer(FILE *fp, const size_t fileOffset, const bool isEncrypted, const size_t encryptOffset, const size_t requestedSize, u8 *outBuffer);
|
||||
|
||||
FILE* GetFilePtr() const;
|
||||
bool IsEncrypted() const;
|
||||
const char* GetDescription() const;
|
||||
CheatDBFileFormat GetFormat() const;
|
||||
const char* GetFormatString() const;
|
||||
|
||||
CheatSystemError OpenFile(const char *filePath);
|
||||
void CloseFile();
|
||||
|
||||
u32 LoadGameList(const char *gameCode, const u32 gameDatabaseCRC, CheatDBGameList &outList);
|
||||
};
|
||||
|
||||
class CHEATSEXPORT
|
||||
{
|
||||
private:
|
||||
CHEATS_DB_TYPE type;
|
||||
bool encrypted;
|
||||
FILE *fp;
|
||||
size_t fsize;
|
||||
u64 dataSize;
|
||||
u64 encOffset;
|
||||
FAT_R4 fat;
|
||||
bool search();
|
||||
bool getCodes();
|
||||
void R4decrypt(u8 *buf, const size_t len, u64 n);
|
||||
|
||||
u32 numCheats;
|
||||
CHEATS_LIST *cheats;
|
||||
|
||||
u8 error; // 0 - no errors
|
||||
// 1 - open failed/file not found
|
||||
// 2 - file format is wrong (no valid header ID)
|
||||
// 3 - cheat not found in database
|
||||
// 4 - export error from database
|
||||
CheatDBFile _dbFile;
|
||||
CheatDBGameList _tempGameList;
|
||||
CheatDBGame *_selectedDbGame;
|
||||
CHEATS_LIST *_cheats;
|
||||
CheatSystemError _lastError;
|
||||
|
||||
public:
|
||||
CHEATSEXPORT() :
|
||||
fp(NULL),
|
||||
fsize(0),
|
||||
dataSize(0),
|
||||
encOffset(0),
|
||||
type(CHEATS_DB_R4),
|
||||
encrypted(false),
|
||||
numCheats(0),
|
||||
cheats(0),
|
||||
CRC(0),
|
||||
error(0)
|
||||
{
|
||||
memset(&fat, 0, sizeof(fat));
|
||||
memset(gametitle, 0, sizeof(gametitle));
|
||||
memset(date, 0, sizeof(date));
|
||||
}
|
||||
|
||||
u8 gametitle[CHEAT_DB_GAME_TITLE_SIZE];
|
||||
u8 date[17];
|
||||
u32 CRC;
|
||||
bool load(char *path);
|
||||
void close();
|
||||
CHEATS_LIST *getCheats();
|
||||
u32 getCheatsNum();
|
||||
u8 getErrorCode() { return error; }
|
||||
CHEATSEXPORT();
|
||||
~CHEATSEXPORT();
|
||||
|
||||
bool load(const char *path);
|
||||
void close();
|
||||
|
||||
CHEATS_LIST *getCheats() const;
|
||||
size_t getCheatsNum() const;
|
||||
const char* getGameTitle() const;
|
||||
const char* getDescription() const;
|
||||
CheatSystemError getErrorCode() const;
|
||||
};
|
||||
|
||||
CheatDBGame* GetCheatDBGameEntryFromList(const CheatDBGameList &gameList, const char *gameCode, const u32 gameDatabaseCRC);
|
||||
void CheatItemGenerateDescriptionHierarchical(const char *itemName, const char *itemNote, CHEATS_LIST &outCheatItem);
|
||||
void CheatItemGenerateDescriptionFlat(const char *folderName, const char *folderNote, const char *itemName, const char *itemNote, CHEATS_LIST &outCheatItem);
|
||||
|
||||
extern CHEATS *cheats;
|
||||
extern CHEATSEARCH *cheatSearch;
|
||||
|
|
|
@ -397,7 +397,7 @@ bool CommandLine::parse(int argc,char **argv)
|
|||
|
||||
if(opt_help)
|
||||
{
|
||||
printf(help_string);
|
||||
printf("%s",help_string);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -571,7 +571,7 @@ bool CommandLine::validate()
|
|||
|
||||
void CommandLine::errorHelp(const char* binName)
|
||||
{
|
||||
printerror(help_string);
|
||||
printerror("%s",help_string);
|
||||
}
|
||||
|
||||
void CommandLine::process_movieCommands()
|
||||
|
|
|
@ -1543,6 +1543,27 @@
|
|||
AB681025187D4AEF0049F2C2 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = AB681018187D4AEF0049F2C2 /* Icon_PaddleKnob_256x256.png */; };
|
||||
AB681027187D4AEF0049F2C2 /* Icon_Piano_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = AB681019187D4AEF0049F2C2 /* Icon_Piano_256x256.png */; };
|
||||
AB68A0DD16B139BC00DE0546 /* OGLRender_3_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */; };
|
||||
AB6E17F52A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E17F62A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E17F72A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E17F82A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E17F92A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E17FA2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E17FB2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E17FC2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E17FD2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E17FE2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
|
||||
AB6E18012A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E18022A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E18032A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E18042A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E18052A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E18062A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E18072A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E18082A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E18092A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E180A2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB6E180B2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
|
||||
AB74EC8A1738499C0026C41E /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB74EC891738499C0026C41E /* Carbon.framework */; };
|
||||
AB78B5C11E384F2100297FED /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3BF4401E262943003E2B24 /* Metal.framework */; settings = {ATTRIBUTES = (Required, ); }; };
|
||||
AB78B5C21E384F2200297FED /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3BF4401E262943003E2B24 /* Metal.framework */; settings = {ATTRIBUTES = (Required, ); }; };
|
||||
|
@ -2425,6 +2446,17 @@
|
|||
AB8493C01B4E614D00CD1C73 /* Icon_VolumeOneThird_16x16@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB8493AD1B4E614D00CD1C73 /* Icon_VolumeOneThird_16x16@2x.png */; };
|
||||
AB8493C11B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB8493AE1B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png */; };
|
||||
AB8493C31B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB8493AE1B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png */; };
|
||||
AB8800542AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB8800552AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB8800562AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB8800572AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB8800582AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB8800592AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB88005A2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB88005B2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB88005C2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB88005D2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB88005E2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */; };
|
||||
AB8967D916D2ED0700F826F1 /* DisplayWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8967D816D2ED0700F826F1 /* DisplayWindowController.mm */; };
|
||||
AB8967DD16D2ED2700F826F1 /* DisplayWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB8967DB16D2ED2700F826F1 /* DisplayWindow.xib */; };
|
||||
AB8B7AAC17CE8C440051CEBF /* slot1comp_protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB8B7AAB17CE8C440051CEBF /* slot1comp_protocol.cpp */; };
|
||||
|
@ -4012,6 +4044,9 @@
|
|||
AB681018187D4AEF0049F2C2 /* Icon_PaddleKnob_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_PaddleKnob_256x256.png; path = images/Icon_PaddleKnob_256x256.png; sourceTree = "<group>"; };
|
||||
AB681019187D4AEF0049F2C2 /* Icon_Piano_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Piano_256x256.png; path = images/Icon_Piano_256x256.png; sourceTree = "<group>"; };
|
||||
AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OGLRender_3_2.cpp; sourceTree = "<group>"; };
|
||||
AB6E17F32A675BF1003A564D /* CheatDatabaseWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheatDatabaseWindowController.h; sourceTree = "<group>"; };
|
||||
AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CheatDatabaseWindowController.mm; sourceTree = "<group>"; };
|
||||
AB6E18002A6B218D003A564D /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = translations/English.lproj/CheatDatabaseViewer.xib; sourceTree = "<group>"; };
|
||||
AB6FBEF5139B6258007BB045 /* slot1_retail_nand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot1_retail_nand.cpp; sourceTree = "<group>"; };
|
||||
AB74EC891738499C0026C41E /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
|
||||
AB75226D14C7BB51009B97B3 /* AppIcon_FirmwareConfig.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_FirmwareConfig.icns; sourceTree = "<group>"; };
|
||||
|
@ -4022,6 +4057,7 @@
|
|||
AB796CA215CDCB6B00C59155 /* instruction_attributes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = instruction_attributes.h; sourceTree = "<group>"; };
|
||||
AB796CA315CDCB6B00C59155 /* instructions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = instructions.h; sourceTree = "<group>"; };
|
||||
AB796D7015CDCBA200C59155 /* DeSmuME (Debug).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DeSmuME (Debug).app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
AB7DA2432833EEBA001E9A9E /* DeSmuME_arm64.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_arm64.profdata; sourceTree = "<group>"; };
|
||||
AB7EC7F2189B2B92009D198A /* Icon_AutoholdClear_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_AutoholdClear_420x420.png; path = images/Icon_AutoholdClear_420x420.png; sourceTree = "<group>"; };
|
||||
AB7EC7F3189B2B92009D198A /* Icon_AutoholdSet_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_AutoholdSet_420x420.png; path = images/Icon_AutoholdSet_420x420.png; sourceTree = "<group>"; };
|
||||
AB80E04C142BC4A800A52038 /* cocoa_util.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_util.mm; sourceTree = "<group>"; };
|
||||
|
@ -4037,6 +4073,7 @@
|
|||
AB8493AC1B4E614D00CD1C73 /* Icon_VolumeMute_16x16@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon_VolumeMute_16x16@2x.png"; path = "images/Icon_VolumeMute_16x16@2x.png"; sourceTree = "<group>"; };
|
||||
AB8493AD1B4E614D00CD1C73 /* Icon_VolumeOneThird_16x16@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon_VolumeOneThird_16x16@2x.png"; path = "images/Icon_VolumeOneThird_16x16@2x.png"; sourceTree = "<group>"; };
|
||||
AB8493AE1B4E614D00CD1C73 /* Icon_VolumeTwoThird_16x16@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon_VolumeTwoThird_16x16@2x.png"; path = "images/Icon_VolumeTwoThird_16x16@2x.png"; sourceTree = "<group>"; };
|
||||
AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot2_hcv1000.cpp; sourceTree = "<group>"; };
|
||||
AB8967D716D2ED0700F826F1 /* DisplayWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayWindowController.h; sourceTree = "<group>"; };
|
||||
AB8967D816D2ED0700F826F1 /* DisplayWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DisplayWindowController.mm; sourceTree = "<group>"; };
|
||||
AB8967DC16D2ED2700F826F1 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = translations/English.lproj/DisplayWindow.xib; sourceTree = "<group>"; };
|
||||
|
@ -4107,6 +4144,7 @@
|
|||
AB9971CE134EDA0800531BA7 /* cocoa_globals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_globals.h; sourceTree = "<group>"; };
|
||||
ABA48DF527F95C2E00D961FB /* colorspacehandler_NEON.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = colorspacehandler_NEON.h; sourceTree = "<group>"; };
|
||||
ABA48DF627F95C2E00D961FB /* colorspacehandler_NEON.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = colorspacehandler_NEON.cpp; sourceTree = "<group>"; };
|
||||
ABA5AB11282E63E20005F25D /* DeSmuME_x86_64.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_x86_64.profdata; sourceTree = "<group>"; };
|
||||
ABA6574914511EC90077E5E9 /* cocoa_cheat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_cheat.h; sourceTree = "<group>"; };
|
||||
ABA6574A14511EC90077E5E9 /* cocoa_cheat.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_cheat.mm; sourceTree = "<group>"; };
|
||||
ABA67CA52808B8D000B5208D /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
|
||||
|
@ -4212,6 +4250,7 @@
|
|||
ABC570D4134431DA00E7B0B1 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
|
||||
ABC719E1138CB25E002827A9 /* DefaultKeyMappings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DefaultKeyMappings.plist; sourceTree = "<group>"; };
|
||||
ABC8599028273FEE00A03EA9 /* DeSmuME (x86_64).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DeSmuME (x86_64).app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
ABCC191C2831F3E100B795C4 /* DeSmuME_x86_64h.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_x86_64h.profdata; sourceTree = "<group>"; };
|
||||
ABCC19332287879000DFA471 /* colorspacehandler_AVX512.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = colorspacehandler_AVX512.cpp; sourceTree = "<group>"; };
|
||||
ABCC19342287879000DFA471 /* colorspacehandler_AVX512.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = colorspacehandler_AVX512.h; sourceTree = "<group>"; };
|
||||
ABCFA9F2178BDE920030C8BA /* encrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = encrypt.h; sourceTree = "<group>"; };
|
||||
|
@ -4380,7 +4419,6 @@
|
|||
ABDDF7C41898F024007583C1 /* Icon_DisplayToggle_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_DisplayToggle_420x420.png; path = images/Icon_DisplayToggle_420x420.png; sourceTree = "<group>"; };
|
||||
ABDDF7C71898F032007583C1 /* Icon_FrameAdvance_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameAdvance_420x420.png; path = images/Icon_FrameAdvance_420x420.png; sourceTree = "<group>"; };
|
||||
ABDDF7C81898F032007583C1 /* Icon_FrameJump_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameJump_420x420.png; path = images/Icon_FrameJump_420x420.png; sourceTree = "<group>"; };
|
||||
ABE187E928274F0100B68164 /* DeSmuME_i386.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_i386.profdata; sourceTree = "<group>"; };
|
||||
ABE5DFE3143FB1DA00835AD8 /* cocoa_videofilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_videofilter.h; sourceTree = "<group>"; };
|
||||
ABE5DFE4143FB1DA00835AD8 /* cocoa_videofilter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_videofilter.mm; sourceTree = "<group>"; };
|
||||
ABE670251415DE6C00E8E4C9 /* tinystr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinystr.cpp; sourceTree = "<group>"; };
|
||||
|
@ -4393,6 +4431,7 @@
|
|||
ABE6840E189E33D5007FD69C /* OGLDisplayOutput.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OGLDisplayOutput.h; sourceTree = "<group>"; };
|
||||
ABE7F53C13EE1C7900FD3A71 /* cocoa_firmware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_firmware.h; sourceTree = "<group>"; };
|
||||
ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_firmware.mm; sourceTree = "<group>"; };
|
||||
ABECD444282DF23100AA6C0C /* DeSmuME_i386.profdata */ = {isa = PBXFileReference; lastKnownFileType = file; path = DeSmuME_i386.profdata; sourceTree = "<group>"; };
|
||||
ABEFCF5D141AB82A000CC0CD /* AppIcon_ROMSave.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_ROMSave.icns; sourceTree = "<group>"; };
|
||||
ABEFCF5E141AB82A000CC0CD /* AppIcon_DeSmuME.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_DeSmuME.icns; sourceTree = "<group>"; };
|
||||
ABEFCF5F141AB82A000CC0CD /* AppIcon_NintendoDS_ROM.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_NintendoDS_ROM.icns; sourceTree = "<group>"; };
|
||||
|
@ -4932,6 +4971,7 @@
|
|||
ABC2ECD613B1C87000FAAA2A /* Images */,
|
||||
AB00E87C14205EBC00DE561F /* MainMenu.xib */,
|
||||
AB8967DB16D2ED2700F826F1 /* DisplayWindow.xib */,
|
||||
AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */,
|
||||
AB350D3A147A1D93007165AC /* HID_usage_strings.plist */,
|
||||
8D1107310486CEB800E47090 /* Info.plist */,
|
||||
AB02791814415E4C0075E58C /* Info (Debug).plist */,
|
||||
|
@ -5224,6 +5264,7 @@
|
|||
children = (
|
||||
AB3ACB6614C2361100D7D192 /* appDelegate.h */,
|
||||
AB3ACB6814C2361100D7D192 /* cheatWindowDelegate.h */,
|
||||
AB6E17F32A675BF1003A564D /* CheatDatabaseWindowController.h */,
|
||||
AB3BF4361E25D6B4003E2B24 /* DisplayViewCALayer.h */,
|
||||
AB8967D716D2ED0700F826F1 /* DisplayWindowController.h */,
|
||||
AB3A655C16CC5416001F5D4A /* EmuControllerDelegate.h */,
|
||||
|
@ -5243,6 +5284,7 @@
|
|||
AB3FBD7E2176DE95005722D0 /* WifiSettingsPanel.h */,
|
||||
AB54718A1E27610500508C5C /* MacMetalDisplayViewShaders.metal */,
|
||||
AB3ACB6714C2361100D7D192 /* appDelegate.mm */,
|
||||
AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */,
|
||||
AB3ACB6914C2361100D7D192 /* cheatWindowDelegate.mm */,
|
||||
AB3BF4371E25D9AE003E2B24 /* DisplayViewCALayer.mm */,
|
||||
AB8967D816D2ED0700F826F1 /* DisplayWindowController.mm */,
|
||||
|
@ -5346,7 +5388,10 @@
|
|||
AB407F381A620D6E00313213 /* OptimizationProfiles */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ABE187E928274F0100B68164 /* DeSmuME_i386.profdata */,
|
||||
ABECD444282DF23100AA6C0C /* DeSmuME_i386.profdata */,
|
||||
ABA5AB11282E63E20005F25D /* DeSmuME_x86_64.profdata */,
|
||||
ABCC191C2831F3E100B795C4 /* DeSmuME_x86_64h.profdata */,
|
||||
AB7DA2432833EEBA001E9A9E /* DeSmuME_arm64.profdata */,
|
||||
);
|
||||
path = OptimizationProfiles;
|
||||
sourceTree = "<group>";
|
||||
|
@ -5732,6 +5777,7 @@
|
|||
ABD1FF031345AC9B00AF11D1 /* slot2_expMemory.cpp */,
|
||||
ABD1FF041345AC9B00AF11D1 /* slot2_gbagame.cpp */,
|
||||
ABD1FF051345AC9B00AF11D1 /* slot2_guitarGrip.cpp */,
|
||||
AB8800532AD5EC4F0090D47F /* slot2_hcv1000.cpp */,
|
||||
ABD1FF061345AC9B00AF11D1 /* slot2_mpcf.cpp */,
|
||||
ABD1FF071345AC9C00AF11D1 /* slot2_none.cpp */,
|
||||
ABD1FF081345AC9C00AF11D1 /* slot2_paddle.cpp */,
|
||||
|
@ -6445,6 +6491,7 @@
|
|||
8C43E79727E3CD0100A35F65 /* Icon_Input_420x420.png in Resources */,
|
||||
8C43E79827E3CD0100A35F65 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
8C43E79927E3CD0100A35F65 /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E18032A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
8C43E79A27E3CD0100A35F65 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
8C43E79B27E3CD0100A35F65 /* Icon_Reset_420x420.png in Resources */,
|
||||
8C43E79C27E3CD0100A35F65 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -6564,6 +6611,7 @@
|
|||
8C43E8F527E3CD4C00A35F65 /* Icon_Input_420x420.png in Resources */,
|
||||
8C43E8F627E3CD4C00A35F65 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
8C43E8F727E3CD4C00A35F65 /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E18042A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
8C43E8F827E3CD4C00A35F65 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
8C43E8F927E3CD4C00A35F65 /* Icon_Reset_420x420.png in Resources */,
|
||||
8C43E8FA27E3CD4C00A35F65 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -6683,6 +6731,7 @@
|
|||
8CCD840827E40B730024BDD5 /* Icon_Input_420x420.png in Resources */,
|
||||
8CCD840927E40B730024BDD5 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
8CCD840A27E40B730024BDD5 /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E180B2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
8CCD840B27E40B730024BDD5 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
8CCD840C27E40B730024BDD5 /* Icon_Reset_420x420.png in Resources */,
|
||||
8CCD840D27E40B730024BDD5 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -6802,6 +6851,7 @@
|
|||
AB36C78827F2C8AE00C763C8 /* Icon_Input_420x420.png in Resources */,
|
||||
AB36C78927F2C8AE00C763C8 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
AB36C78A27F2C8AE00C763C8 /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E18082A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
AB36C78B27F2C8AE00C763C8 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
AB36C78C27F2C8AE00C763C8 /* Icon_Reset_420x420.png in Resources */,
|
||||
AB36C78D27F2C8AE00C763C8 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -6921,6 +6971,7 @@
|
|||
AB497A0E27F2E97A00E8A244 /* Icon_Input_420x420.png in Resources */,
|
||||
AB497A0F27F2E97A00E8A244 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
AB497A1027F2E97A00E8A244 /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E18072A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
AB497A1127F2E97A00E8A244 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
AB497A1227F2E97A00E8A244 /* Icon_Reset_420x420.png in Resources */,
|
||||
AB497A1327F2E97A00E8A244 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -7040,6 +7091,7 @@
|
|||
AB790193215B84F20082AE82 /* Icon_Input_420x420.png in Resources */,
|
||||
AB790194215B84F20082AE82 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
AB790195215B84F20082AE82 /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E18062A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
AB790196215B84F20082AE82 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
AB790197215B84F20082AE82 /* Icon_Reset_420x420.png in Resources */,
|
||||
AB790198215B84F20082AE82 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -7159,6 +7211,7 @@
|
|||
AB796CE015CDCBA200C59155 /* Icon_Input_420x420.png in Resources */,
|
||||
AB7EC7F6189B2B92009D198A /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
ABB0FBCC1A9EED350060C55A /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E18012A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
AB796CE215CDCBA200C59155 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
AB796CE315CDCBA200C59155 /* Icon_Reset_420x420.png in Resources */,
|
||||
AB796CE415CDCBA200C59155 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -7278,6 +7331,7 @@
|
|||
AB790036215B84E50082AE82 /* Icon_Input_420x420.png in Resources */,
|
||||
AB790037215B84E50082AE82 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
AB790038215B84E50082AE82 /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E18052A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
AB790039215B84E50082AE82 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
AB79003A215B84E50082AE82 /* Icon_Reset_420x420.png in Resources */,
|
||||
AB79003B215B84E50082AE82 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -7397,6 +7451,7 @@
|
|||
AB8F3C5F1A53AC2600A80BF6 /* Icon_Input_420x420.png in Resources */,
|
||||
AB8F3C601A53AC2600A80BF6 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
ABB0FBCE1A9EED350060C55A /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E18022A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
AB8F3C621A53AC2600A80BF6 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
AB8F3C631A53AC2600A80BF6 /* Icon_Reset_420x420.png in Resources */,
|
||||
AB8F3C641A53AC2600A80BF6 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -7526,6 +7581,7 @@
|
|||
ABC8588628273FEE00A03EA9 /* Icon_Input_420x420.png in Resources */,
|
||||
ABC8588728273FEE00A03EA9 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
ABC8588828273FEE00A03EA9 /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E18092A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
ABC8588928273FEE00A03EA9 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
ABC8588A28273FEE00A03EA9 /* Icon_Reset_420x420.png in Resources */,
|
||||
ABC8588B28273FEE00A03EA9 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -7645,6 +7701,7 @@
|
|||
ABD2CD3C26E05CB000FB15F7 /* Icon_Input_420x420.png in Resources */,
|
||||
ABD2CD3D26E05CB000FB15F7 /* Icon_AutoholdSet_420x420.png in Resources */,
|
||||
ABD2CD3E26E05CB000FB15F7 /* Icon_MicrophoneBlack_256x256.png in Resources */,
|
||||
AB6E180A2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
|
||||
ABD2CD3F26E05CB000FB15F7 /* Icon_OpenROM_420x420.png in Resources */,
|
||||
ABD2CD4026E05CB000FB15F7 /* Icon_Reset_420x420.png in Resources */,
|
||||
ABD2CD4126E05CB000FB15F7 /* Icon_RotateCCW_420x420.png in Resources */,
|
||||
|
@ -7914,6 +7971,7 @@
|
|||
8C43E7F027E3CD0100A35F65 /* ClientExecutionControl.cpp in Sources */,
|
||||
8C43E7F127E3CD0100A35F65 /* rsemaphore.c in Sources */,
|
||||
8C43E7F227E3CD0100A35F65 /* movie.cpp in Sources */,
|
||||
AB6E17F72A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
8C43E7F327E3CD0100A35F65 /* slot1comp_rom.cpp in Sources */,
|
||||
8C43E7F427E3CD0100A35F65 /* NDSSystem.cpp in Sources */,
|
||||
8C43E7F527E3CD0100A35F65 /* MacBaseCaptureTool.mm in Sources */,
|
||||
|
@ -8019,6 +8077,7 @@
|
|||
8C43E86627E3CD0100A35F65 /* ftfstype.c in Sources */,
|
||||
8C43E86B27E3CD0100A35F65 /* macosx_10_5_compat.cpp in Sources */,
|
||||
8C43E86C27E3CD0100A35F65 /* retro_dirent.c in Sources */,
|
||||
AB8800562AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
8C43E87427E3CD0100A35F65 /* slot2_passme.cpp in Sources */,
|
||||
8C43E87727E3CD0100A35F65 /* psnames.c in Sources */,
|
||||
8C43E87827E3CD0100A35F65 /* ftotval.c in Sources */,
|
||||
|
@ -8083,6 +8142,7 @@
|
|||
8C43E92F27E3CD4C00A35F65 /* common.cpp in Sources */,
|
||||
8C43E93027E3CD4C00A35F65 /* cp15.cpp in Sources */,
|
||||
8C43E93127E3CD4C00A35F65 /* psaux.c in Sources */,
|
||||
AB8800572AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
8C43E93227E3CD4C00A35F65 /* cpu_detect_x86_gcc.cpp in Sources */,
|
||||
8C43E93327E3CD4C00A35F65 /* crc.cpp in Sources */,
|
||||
8C43E93427E3CD4C00A35F65 /* MacOGLDisplayView.mm in Sources */,
|
||||
|
@ -8156,6 +8216,7 @@
|
|||
8C43E97827E3CD4C00A35F65 /* slot2_rumblepak.cpp in Sources */,
|
||||
8C43E97927E3CD4C00A35F65 /* sndOSX.cpp in Sources */,
|
||||
8C43E97A27E3CD4C00A35F65 /* SndOut.cpp in Sources */,
|
||||
AB6E17F82A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
8C43E97B27E3CD4C00A35F65 /* psnames.c in Sources */,
|
||||
8C43E97C27E3CD4C00A35F65 /* Slot2WindowDelegate.mm in Sources */,
|
||||
8C43E97D27E3CD4C00A35F65 /* truetype.c in Sources */,
|
||||
|
@ -8313,6 +8374,7 @@
|
|||
8CCD846127E40B730024BDD5 /* ClientExecutionControl.cpp in Sources */,
|
||||
8CCD846227E40B730024BDD5 /* slot1.cpp in Sources */,
|
||||
8CCD846327E40B730024BDD5 /* slot1_none.cpp in Sources */,
|
||||
AB6E17FE2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
8CCD846427E40B730024BDD5 /* slot1_r4.cpp in Sources */,
|
||||
8CCD846527E40B730024BDD5 /* cff.c in Sources */,
|
||||
8CCD846627E40B730024BDD5 /* MacBaseCaptureTool.mm in Sources */,
|
||||
|
@ -8418,6 +8480,7 @@
|
|||
8CCD84DF27E40B730024BDD5 /* type1cid.c in Sources */,
|
||||
8CCD84E427E40B730024BDD5 /* cocoa_slot2.mm in Sources */,
|
||||
8CCD84E627E40B730024BDD5 /* ftbase.c in Sources */,
|
||||
AB88005D2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
8CCD84EA27E40B730024BDD5 /* fsnitro.cpp in Sources */,
|
||||
8CCD84EB27E40B730024BDD5 /* macosx_10_5_compat.cpp in Sources */,
|
||||
8CCD84EC27E40B730024BDD5 /* OGLRender_3_2.cpp in Sources */,
|
||||
|
@ -8462,6 +8525,7 @@
|
|||
AB36C7AF27F2C8AE00C763C8 /* decrypt.cpp in Sources */,
|
||||
AB36C7B027F2C8AE00C763C8 /* directory.cpp in Sources */,
|
||||
AB36C7B127F2C8AE00C763C8 /* Disassembler.cpp in Sources */,
|
||||
AB88005A2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
AB36C7B227F2C8AE00C763C8 /* disc.cpp in Sources */,
|
||||
AB36C7B327F2C8AE00C763C8 /* dlditool.cpp in Sources */,
|
||||
AB36C7B427F2C8AE00C763C8 /* driver.cpp in Sources */,
|
||||
|
@ -8647,6 +8711,7 @@
|
|||
AB36C86B27F2C8AE00C763C8 /* macosx_10_5_compat.cpp in Sources */,
|
||||
AB36C86C27F2C8AE00C763C8 /* OGLRender_3_2.cpp in Sources */,
|
||||
AB36C86D27F2C8AE00C763C8 /* ftfntfmt.c in Sources */,
|
||||
AB6E17FB2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB36C86E27F2C8AE00C763C8 /* EmuControllerDelegate.mm in Sources */,
|
||||
AB36C86F27F2C8AE00C763C8 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
AB36C87027F2C8AE00C763C8 /* cocoa_GPU.mm in Sources */,
|
||||
|
@ -8704,6 +8769,7 @@
|
|||
AB79006E215B84E50082AE82 /* emufile.cpp in Sources */,
|
||||
AB79006F215B84E50082AE82 /* fatdir.cpp in Sources */,
|
||||
AB790070215B84E50082AE82 /* ftbase.c in Sources */,
|
||||
AB6E17F92A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB790071215B84E50082AE82 /* fatfile.cpp in Sources */,
|
||||
AB790072215B84E50082AE82 /* FIFO.cpp in Sources */,
|
||||
AB790073215B84E50082AE82 /* sfnt.c in Sources */,
|
||||
|
@ -8835,6 +8901,7 @@
|
|||
AB7900EF215B84E50082AE82 /* coreaudiosound.cpp in Sources */,
|
||||
AB7900F0215B84E50082AE82 /* ringbuffer.cpp in Sources */,
|
||||
AB7900F1215B84E50082AE82 /* arm_jit.cpp in Sources */,
|
||||
AB8800582AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
AB7900F2215B84E50082AE82 /* smooth.c in Sources */,
|
||||
AB7900F3215B84E50082AE82 /* troubleshootingWindowDelegate.mm in Sources */,
|
||||
AB7900F4215B84E50082AE82 /* macOS_driver.cpp in Sources */,
|
||||
|
@ -8951,6 +9018,7 @@
|
|||
AB7901DD215B84F20082AE82 /* driver.cpp in Sources */,
|
||||
AB7901DE215B84F20082AE82 /* emufat.cpp in Sources */,
|
||||
AB7901DF215B84F20082AE82 /* type1cid.c in Sources */,
|
||||
AB8800592AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
AB7901E0215B84F20082AE82 /* emufile.cpp in Sources */,
|
||||
AB7901E1215B84F20082AE82 /* fatdir.cpp in Sources */,
|
||||
AB7901E2215B84F20082AE82 /* fatfile.cpp in Sources */,
|
||||
|
@ -9004,6 +9072,7 @@
|
|||
AB790211215B84F20082AE82 /* type1.c in Sources */,
|
||||
AB790212215B84F20082AE82 /* slot2_paddle.cpp in Sources */,
|
||||
AB790213215B84F20082AE82 /* slot2_piano.cpp in Sources */,
|
||||
AB6E17FA2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB790214215B84F20082AE82 /* slot2_rumblepak.cpp in Sources */,
|
||||
AB790215215B84F20082AE82 /* sndOSX.cpp in Sources */,
|
||||
AB790216215B84F20082AE82 /* SndOut.cpp in Sources */,
|
||||
|
@ -9161,6 +9230,7 @@
|
|||
AB796D0415CDCBA200C59155 /* emufile.cpp in Sources */,
|
||||
AB796D0515CDCBA200C59155 /* fatdir.cpp in Sources */,
|
||||
ABFEA8011BB4EC1000B08C25 /* ftbase.c in Sources */,
|
||||
AB6E17F52A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB796D0615CDCBA200C59155 /* fatfile.cpp in Sources */,
|
||||
AB796D0715CDCBA200C59155 /* FIFO.cpp in Sources */,
|
||||
ABFEA8A31BB4EC1100B08C25 /* sfnt.c in Sources */,
|
||||
|
@ -9292,6 +9362,7 @@
|
|||
AB796D6215CDCBA200C59155 /* coreaudiosound.cpp in Sources */,
|
||||
AB796D6315CDCBA200C59155 /* ringbuffer.cpp in Sources */,
|
||||
AB796D6415CDCBA200C59155 /* arm_jit.cpp in Sources */,
|
||||
AB8800542AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
ABFEA8CA1BB4EC1100B08C25 /* smooth.c in Sources */,
|
||||
ABF2B9FB16904133000FF7C0 /* troubleshootingWindowDelegate.mm in Sources */,
|
||||
AB28625920AE3E9F00EAED43 /* macOS_driver.cpp in Sources */,
|
||||
|
@ -9408,6 +9479,7 @@
|
|||
AB8F3C871A53AC2600A80BF6 /* driver.cpp in Sources */,
|
||||
AB8F3C881A53AC2600A80BF6 /* emufat.cpp in Sources */,
|
||||
ABA7316A1BB51FDC00B26147 /* type1cid.c in Sources */,
|
||||
AB8800552AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
AB8F3C891A53AC2600A80BF6 /* emufile.cpp in Sources */,
|
||||
AB8F3C8A1A53AC2600A80BF6 /* fatdir.cpp in Sources */,
|
||||
AB8F3C8B1A53AC2600A80BF6 /* fatfile.cpp in Sources */,
|
||||
|
@ -9461,6 +9533,7 @@
|
|||
ABA731701BB51FDC00B26147 /* type1.c in Sources */,
|
||||
AB8F3CBA1A53AC2600A80BF6 /* slot2_paddle.cpp in Sources */,
|
||||
AB8F3CBB1A53AC2600A80BF6 /* slot2_piano.cpp in Sources */,
|
||||
AB6E17F62A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB8F3CBC1A53AC2600A80BF6 /* slot2_rumblepak.cpp in Sources */,
|
||||
AB8F3CBD1A53AC2600A80BF6 /* sndOSX.cpp in Sources */,
|
||||
AB8F3CBE1A53AC2600A80BF6 /* SndOut.cpp in Sources */,
|
||||
|
@ -9711,6 +9784,7 @@
|
|||
AB2ABA461C9F9CFA00173B15 /* rthreads.c in Sources */,
|
||||
ABB3C6CB1501C04F00E0C22E /* rasterize.cpp in Sources */,
|
||||
ABB3C6CC1501C04F00E0C22E /* readwrite.cpp in Sources */,
|
||||
AB88005E2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
AB49B553281687B90069F1D7 /* truetype.c in Sources */,
|
||||
ABB3C6CD1501C04F00E0C22E /* render3D.cpp in Sources */,
|
||||
ABB3C6CE1501C04F00E0C22E /* ROMReader.cpp in Sources */,
|
||||
|
@ -9790,6 +9864,7 @@
|
|||
ABC858BF28273FEE00A03EA9 /* filetime.cpp in Sources */,
|
||||
ABC858C028273FEE00A03EA9 /* FIRFilter.cpp in Sources */,
|
||||
ABC858C128273FEE00A03EA9 /* firmware.cpp in Sources */,
|
||||
AB6E17FC2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
ABC858C228273FEE00A03EA9 /* async_job.c in Sources */,
|
||||
ABC858C328273FEE00A03EA9 /* gfx3d.cpp in Sources */,
|
||||
ABC858C428273FEE00A03EA9 /* DisplayViewCALayer.mm in Sources */,
|
||||
|
@ -9921,6 +9996,7 @@
|
|||
ABC8594228273FEE00A03EA9 /* buffer.cpp in Sources */,
|
||||
ABC8594328273FEE00A03EA9 /* ftotval.c in Sources */,
|
||||
ABC8594428273FEE00A03EA9 /* compiler.cpp in Sources */,
|
||||
AB88005B2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
ABC8594528273FEE00A03EA9 /* compilercontext.cpp in Sources */,
|
||||
ABC8594628273FEE00A03EA9 /* rthreads.c in Sources */,
|
||||
ABC8594728273FEE00A03EA9 /* macOS_driver.cpp in Sources */,
|
||||
|
@ -10018,6 +10094,7 @@
|
|||
ABD2CD7326E05CB000FB15F7 /* filetime.cpp in Sources */,
|
||||
ABD2CD7426E05CB000FB15F7 /* FIRFilter.cpp in Sources */,
|
||||
ABD2CD7526E05CB000FB15F7 /* firmware.cpp in Sources */,
|
||||
AB6E17FD2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
|
||||
ABD2CD7626E05CB000FB15F7 /* async_job.c in Sources */,
|
||||
ABD2CD7726E05CB000FB15F7 /* gfx3d.cpp in Sources */,
|
||||
ABD2CD7826E05CB000FB15F7 /* DisplayViewCALayer.mm in Sources */,
|
||||
|
@ -10149,6 +10226,7 @@
|
|||
ABD2CDF626E05CB000FB15F7 /* buffer.cpp in Sources */,
|
||||
ABD2CDF726E05CB000FB15F7 /* ftotval.c in Sources */,
|
||||
ABD2CDF826E05CB000FB15F7 /* compiler.cpp in Sources */,
|
||||
AB88005C2AD5EC500090D47F /* slot2_hcv1000.cpp in Sources */,
|
||||
ABD2CDF926E05CB000FB15F7 /* compilercontext.cpp in Sources */,
|
||||
ABD2CDFA26E05CB000FB15F7 /* rthreads.c in Sources */,
|
||||
ABD2CDFB26E05CB000FB15F7 /* macOS_driver.cpp in Sources */,
|
||||
|
@ -10233,6 +10311,14 @@
|
|||
name = HID_usage_strings.plist;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
AB6E18002A6B218D003A564D /* English */,
|
||||
);
|
||||
name = CheatDatabaseViewer.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
AB8967DB16D2ED2700F826F1 /* DisplayWindow.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
|
@ -10333,7 +10419,6 @@
|
|||
buildSettings = {
|
||||
ARCHS = arm64;
|
||||
CLANG_OPTIMIZATION_PROFILE_FILE = "$(SRCROOT)/OptimizationProfiles/DeSmuME_arm64.profdata";
|
||||
CLANG_USE_OPTIMIZATION_PROFILE = YES;
|
||||
GCC_FAST_OBJC_DISPATCH = YES;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = fast;
|
||||
|
@ -10666,7 +10751,6 @@
|
|||
ARCHS = x86_64;
|
||||
CLANG_CXX_LIBRARY = "libstdc++";
|
||||
CLANG_OPTIMIZATION_PROFILE_FILE = "$(SRCROOT)/OptimizationProfiles/DeSmuME_x86_64.profdata";
|
||||
CLANG_USE_OPTIMIZATION_PROFILE = YES;
|
||||
GCC_FAST_OBJC_DISPATCH = YES;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = fast;
|
||||
|
@ -10715,7 +10799,6 @@
|
|||
buildSettings = {
|
||||
ARCHS = x86_64h;
|
||||
CLANG_OPTIMIZATION_PROFILE_FILE = "$(SRCROOT)/OptimizationProfiles/DeSmuME_x86_64h.profdata";
|
||||
CLANG_USE_OPTIMIZATION_PROFILE = YES;
|
||||
GCC_FAST_OBJC_DISPATCH = YES;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = fast;
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:DeSmuME (Latest).xcodeproj">
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
|
|
@ -266,6 +266,11 @@
|
|||
AB142028186E2CD80015D52F /* Image_MemoryExpansionPak.png in Resources */ = {isa = PBXBuildFile; fileRef = AB142025186E2CD80015D52F /* Image_MemoryExpansionPak.png */; };
|
||||
AB142029186E2CD80015D52F /* Image_MemoryExpansionPak.png in Resources */ = {isa = PBXBuildFile; fileRef = AB142025186E2CD80015D52F /* Image_MemoryExpansionPak.png */; };
|
||||
AB14202A186E2CD80015D52F /* Image_MemoryExpansionPak.png in Resources */ = {isa = PBXBuildFile; fileRef = AB142025186E2CD80015D52F /* Image_MemoryExpansionPak.png */; };
|
||||
AB1B20AC2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
|
||||
AB1B20AD2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
|
||||
AB1B20AE2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
|
||||
AB1B20AF2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
|
||||
AB1B20B02AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */; };
|
||||
AB1CC8001AA509C2008B0A16 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1CC7FF1AA509C2008B0A16 /* CoreAudio.framework */; };
|
||||
AB1CC80A1AA509DF008B0A16 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1CC7FF1AA509C2008B0A16 /* CoreAudio.framework */; };
|
||||
AB1CC80B1AA509E0008B0A16 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1CC7FF1AA509C2008B0A16 /* CoreAudio.framework */; };
|
||||
|
@ -1558,6 +1563,11 @@
|
|||
ABD59849187D4A6C00069403 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = ABD59846187D4A6C00069403 /* Icon_PaddleKnob_256x256.png */; };
|
||||
ABD5984A187D4A6C00069403 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = ABD59846187D4A6C00069403 /* Icon_PaddleKnob_256x256.png */; };
|
||||
ABD5984B187D4A6C00069403 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = ABD59846187D4A6C00069403 /* Icon_PaddleKnob_256x256.png */; };
|
||||
ABEBCE372A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
|
||||
ABEBCE382A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
|
||||
ABEBCE392A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
|
||||
ABEBCE3A2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
|
||||
ABEBCE3B2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
|
||||
ABECB50918A460710052D52A /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABECB50818A460710052D52A /* xbrz.cpp */; };
|
||||
ABECB50A18A460710052D52A /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABECB50818A460710052D52A /* xbrz.cpp */; };
|
||||
ABECB50B18A460710052D52A /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABECB50818A460710052D52A /* xbrz.cpp */; };
|
||||
|
@ -1572,6 +1582,11 @@
|
|||
ABEF84831873578F00E99ADC /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C6E56186CD07E00E3EC64 /* ForceFeedback.framework */; };
|
||||
ABEF84841873579400E99ADC /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C6E56186CD07E00E3EC64 /* ForceFeedback.framework */; };
|
||||
ABEF84851873579700E99ADC /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C6E56186CD07E00E3EC64 /* ForceFeedback.framework */; };
|
||||
ABEFFDDE2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
|
||||
ABEFFDDF2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
|
||||
ABEFFDE02A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
|
||||
ABEFFDE12A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
|
||||
ABEFFDE22A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
|
||||
ABF50ABA169F5FDA0018C08D /* assembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABF50A7B169F5FDA0018C08D /* assembler.cpp */; };
|
||||
ABF50ABB169F5FDA0018C08D /* assert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABF50A7D169F5FDA0018C08D /* assert.cpp */; };
|
||||
ABF50ABC169F5FDA0018C08D /* buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABF50A7F169F5FDA0018C08D /* buffer.cpp */; };
|
||||
|
@ -1905,6 +1920,7 @@
|
|||
AB0F29A514BE7213009ABC6F /* Icon_Speaker_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Speaker_420x420.png; path = images/Icon_Speaker_420x420.png; sourceTree = "<group>"; };
|
||||
AB126D06182ECB9500EBCF22 /* slot2_passme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot2_passme.cpp; sourceTree = "<group>"; };
|
||||
AB142025186E2CD80015D52F /* Image_MemoryExpansionPak.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Image_MemoryExpansionPak.png; path = images/Image_MemoryExpansionPak.png; sourceTree = "<group>"; };
|
||||
AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot2_hcv1000.cpp; sourceTree = "<group>"; };
|
||||
AB1CC7FF1AA509C2008B0A16 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
|
||||
AB1CC8161AA50C8D008B0A16 /* Icon_MicrophoneBlack_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_MicrophoneBlack_256x256.png; path = images/Icon_MicrophoneBlack_256x256.png; sourceTree = "<group>"; };
|
||||
AB1CC8171AA50C8D008B0A16 /* Icon_MicrophoneBlueGlow_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_MicrophoneBlueGlow_256x256.png; path = images/Icon_MicrophoneBlueGlow_256x256.png; sourceTree = "<group>"; };
|
||||
|
@ -2326,6 +2342,8 @@
|
|||
ABE6702A1415DE6C00E8E4C9 /* tinyxmlparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyxmlparser.cpp; sourceTree = "<group>"; };
|
||||
ABE7F53C13EE1C7900FD3A71 /* cocoa_firmware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_firmware.h; sourceTree = "<group>"; };
|
||||
ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_firmware.mm; sourceTree = "<group>"; };
|
||||
ABEBCE352A703E260028CE8A /* CheatDatabaseWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheatDatabaseWindowController.h; sourceTree = "<group>"; };
|
||||
ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CheatDatabaseWindowController.mm; sourceTree = "<group>"; };
|
||||
ABECB50718A460710052D52A /* xbrz.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbrz.h; sourceTree = "<group>"; };
|
||||
ABECB50818A460710052D52A /* xbrz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbrz.cpp; sourceTree = "<group>"; };
|
||||
ABECB51218A460910052D52A /* OGLDisplayOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OGLDisplayOutput.h; sourceTree = "<group>"; };
|
||||
|
@ -2334,6 +2352,7 @@
|
|||
ABEFCF5E141AB82A000CC0CD /* AppIcon_DeSmuME.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_DeSmuME.icns; sourceTree = "<group>"; };
|
||||
ABEFCF5F141AB82A000CC0CD /* AppIcon_NintendoDS_ROM.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_NintendoDS_ROM.icns; sourceTree = "<group>"; };
|
||||
ABEFCF60141AB82A000CC0CD /* AppIcon_SaveState.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_SaveState.icns; sourceTree = "<group>"; };
|
||||
ABEFFDDD2A78CB67009C3A2D /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = translations/English.lproj/CheatDatabaseViewer.xib; sourceTree = "<group>"; };
|
||||
ABF50A74169F5FDA0018C08D /* AsmJit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsmJit.h; sourceTree = "<group>"; };
|
||||
ABF50A75169F5FDA0018C08D /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Config.h; sourceTree = "<group>"; };
|
||||
ABF50A76169F5FDA0018C08D /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core.h; sourceTree = "<group>"; };
|
||||
|
@ -2657,6 +2676,7 @@
|
|||
AB05E8201BBFD41200065D18 /* source-sans-pro */,
|
||||
ABC2ECD613B1C87000FAAA2A /* Images */,
|
||||
AB00E87C14205EBC00DE561F /* MainMenu.xib */,
|
||||
ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */,
|
||||
AB700DB816CDDBC400FBD336 /* DisplayWindow.xib */,
|
||||
AB350D3A147A1D93007165AC /* HID_usage_strings.plist */,
|
||||
8D1107310486CEB800E47090 /* Info.plist */,
|
||||
|
@ -3199,6 +3219,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
AB3ACB6614C2361100D7D192 /* appDelegate.h */,
|
||||
ABEBCE352A703E260028CE8A /* CheatDatabaseWindowController.h */,
|
||||
AB3ACB6814C2361100D7D192 /* cheatWindowDelegate.h */,
|
||||
AB3E69811E25FBBF00D4CC75 /* DisplayViewCALayer.h */,
|
||||
AB700DDC16CDE4C300FBD336 /* DisplayWindowController.h */,
|
||||
|
@ -3217,6 +3238,7 @@
|
|||
ABA0356E169127BB00817C69 /* troubleshootingWindowDelegate.h */,
|
||||
AB4B5A1F217E47E400381363 /* WifiSettingsPanel.h */,
|
||||
AB3ACB6714C2361100D7D192 /* appDelegate.mm */,
|
||||
ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */,
|
||||
AB3ACB6914C2361100D7D192 /* cheatWindowDelegate.mm */,
|
||||
AB3E69821E25FBBF00D4CC75 /* DisplayViewCALayer.mm */,
|
||||
AB700DDD16CDE4C300FBD336 /* DisplayWindowController.mm */,
|
||||
|
@ -3495,6 +3517,7 @@
|
|||
ABD1FF031345AC9B00AF11D1 /* slot2_expMemory.cpp */,
|
||||
ABD1FF041345AC9B00AF11D1 /* slot2_gbagame.cpp */,
|
||||
ABD1FF051345AC9B00AF11D1 /* slot2_guitarGrip.cpp */,
|
||||
AB1B20AB2AD5ED59007CA7EB /* slot2_hcv1000.cpp */,
|
||||
ABD1FF061345AC9B00AF11D1 /* slot2_mpcf.cpp */,
|
||||
ABD1FF071345AC9C00AF11D1 /* slot2_none.cpp */,
|
||||
ABD1FF081345AC9C00AF11D1 /* slot2_paddle.cpp */,
|
||||
|
@ -3870,7 +3893,7 @@
|
|||
attributes = {
|
||||
ORGANIZATIONNAME = "DeSmuME Team";
|
||||
};
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (XCode 3)" */;
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (Xcode 3)" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
|
@ -4014,6 +4037,7 @@
|
|||
ABA1659B2808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
|
||||
ABA1659C2808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
|
||||
AB6D78942809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
|
||||
ABEFFDDF2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -4133,6 +4157,7 @@
|
|||
ABA165A92808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
|
||||
ABA165AA2808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
|
||||
AB6D78952809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
|
||||
ABEFFDE02A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -4252,6 +4277,7 @@
|
|||
ABA165D32808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
|
||||
ABA165D42808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
|
||||
AB6D78982809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
|
||||
ABEFFDDE2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -4371,6 +4397,7 @@
|
|||
ABA165C52808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
|
||||
ABA165C62808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
|
||||
AB6D78972809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
|
||||
ABEFFDE22A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -4490,6 +4517,7 @@
|
|||
ABA165B72808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
|
||||
ABA165B82808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
|
||||
AB6D78962809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
|
||||
ABEFFDE12A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -4835,6 +4863,8 @@
|
|||
ABD1267720AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267820AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
AB4B5A22217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
|
||||
ABEBCE382A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB1B20AD2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -5029,6 +5059,8 @@
|
|||
ABD1267920AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267A20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
AB4B5A23217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
|
||||
ABEBCE392A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB1B20AE2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -5253,6 +5285,8 @@
|
|||
ABD1267520AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267620AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
AB4B5A21217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
|
||||
ABEBCE372A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB1B20AC2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -5477,6 +5511,8 @@
|
|||
ABD1267D20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267E20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
AB4B5A25217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
|
||||
ABEBCE3B2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB1B20B02AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -5671,6 +5707,8 @@
|
|||
ABD1267B20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267C20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
AB4B5A24217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
|
||||
ABEBCE3A2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
|
||||
AB1B20AF2AD5ED59007CA7EB /* slot2_hcv1000.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -5717,6 +5755,14 @@
|
|||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
ABEFFDDD2A78CB67009C3A2D /* English */,
|
||||
);
|
||||
name = CheatDatabaseViewer.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
|
@ -6007,7 +6053,7 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (XCode 3)" */ = {
|
||||
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (Xcode 3)" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C01FCF4F08A954540054247B /* Debug */,
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
<dict>
|
||||
<key>Advanscene_AutoDetectRomSaveType</key>
|
||||
<true/>
|
||||
<key>CheatDatabase_RecentFilePath</key>
|
||||
<array/>
|
||||
<key>CoreControl_EnableAutoFrameSkip</key>
|
||||
<true/>
|
||||
<key>CoreControl_FramesToSkipSetting</key>
|
||||
|
|
|
@ -193,8 +193,6 @@ GPU3DInterface *core3DList[GPU_3D_RENDERER_COUNT+1] = {
|
|||
|
||||
- (void)dealloc
|
||||
{
|
||||
DestroyOpenGLRenderer();
|
||||
|
||||
delete fetchObject;
|
||||
delete gpuEvent;
|
||||
|
||||
|
|
|
@ -18,9 +18,11 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include "../../cheatSystem.h"
|
||||
#undef BOOL
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
class CHEATS;
|
||||
class CHEATS_LIST;
|
||||
class CHEATSEARCH;
|
||||
|
@ -54,16 +56,6 @@ enum CheatSearchCompareStyle
|
|||
CheatSearchCompareStyle_NotEquals = 3
|
||||
};
|
||||
|
||||
enum CheatSystemError
|
||||
{
|
||||
CheatSystemError_NoError = 0,
|
||||
CheatSystemError_FileOpenFailed = 1,
|
||||
CheatSystemError_FileFormatInvalid = 2,
|
||||
CheatSystemError_CheatNotFound = 3,
|
||||
CheatSystemError_ExportError = 4,
|
||||
CheatSystemError_FileSaveFailed = 5
|
||||
};
|
||||
|
||||
union DesmumeCheatSearchItem
|
||||
{
|
||||
uint64_t data;
|
||||
|
@ -95,7 +87,8 @@ protected:
|
|||
bool _willAddFromDB;
|
||||
|
||||
CheatType _cheatType;
|
||||
std::string _descriptionString;
|
||||
std::string _nameString;
|
||||
std::string _commentString;
|
||||
|
||||
// Internal cheat type parameters
|
||||
CheatFreezeType _freezeType;
|
||||
|
@ -132,8 +125,11 @@ public:
|
|||
void SetType(CheatType requestedType);
|
||||
bool IsSupportedType() const;
|
||||
|
||||
const char* GetDescription() const;
|
||||
void SetDescription(const char *descriptionString);
|
||||
const char* GetName() const;
|
||||
void SetName(const char *nameString);
|
||||
|
||||
const char* GetComments() const;
|
||||
void SetComments(const char *commentString);
|
||||
|
||||
CheatFreezeType GetFreezeType() const;
|
||||
void SetFreezeType(CheatFreezeType theFreezeType);
|
||||
|
@ -224,7 +220,7 @@ class ClientCheatDatabase
|
|||
protected:
|
||||
ClientCheatList *_list;
|
||||
std::string _title;
|
||||
std::string _date;
|
||||
std::string _description;
|
||||
std::string _lastFilePath;
|
||||
|
||||
public:
|
||||
|
@ -235,7 +231,7 @@ public:
|
|||
ClientCheatList* LoadFromFile(const char *dbFilePath);
|
||||
|
||||
const char* GetTitle() const;
|
||||
const char* GetDate() const;
|
||||
const char* GetDescription() const;
|
||||
};
|
||||
|
||||
class ClientCheatManager
|
||||
|
@ -289,7 +285,7 @@ public:
|
|||
ClientCheatList* GetDatabaseList() const;
|
||||
ClientCheatList* DatabaseListLoadFromFile(const char *dbFilePath);
|
||||
const char* GetDatabaseTitle() const;
|
||||
const char* GetDatabaseDate() const;
|
||||
const char* GetDatabaseDescription() const;
|
||||
|
||||
bool SearchDidStart() const;
|
||||
void SearchReset();
|
||||
|
@ -345,6 +341,8 @@ public:
|
|||
- (void) destroyWorkingCopy;
|
||||
- (void) mergeToParent;
|
||||
|
||||
+ (void) setIconDirectory:(NSImage *)iconImage;
|
||||
+ (NSImage *) iconDirectory;
|
||||
+ (void) setIconInternalCheat:(NSImage *)iconImage;
|
||||
+ (NSImage *) iconInternalCheat;
|
||||
+ (void) setIconActionReplay:(NSImage *)iconImage;
|
||||
|
@ -354,11 +352,83 @@ public:
|
|||
|
||||
@end
|
||||
|
||||
@interface CocoaDSCheatDBEntry : NSObject
|
||||
{
|
||||
CheatDBEntry *_dbEntry;
|
||||
|
||||
CocoaDSCheatDBEntry *parent;
|
||||
NSMutableArray *child;
|
||||
NSInteger willAdd;
|
||||
NSString *codeString;
|
||||
|
||||
BOOL needSetMixedState;
|
||||
}
|
||||
|
||||
@property (readonly, nonatomic) NSString *name;
|
||||
@property (readonly, nonatomic) NSString *comment;
|
||||
@property (readonly, nonatomic) NSImage *icon;
|
||||
@property (readonly, nonatomic) NSInteger entryCount;
|
||||
@property (readonly, nonatomic) NSString *codeString;
|
||||
@property (readonly, nonatomic) BOOL isDirectory;
|
||||
@property (readonly, nonatomic) BOOL isCheatItem;
|
||||
@property (assign) NSInteger willAdd;
|
||||
@property (assign) BOOL needSetMixedState;
|
||||
@property (assign) CocoaDSCheatDBEntry *parent;
|
||||
@property (readonly, nonatomic) NSMutableArray *child;
|
||||
|
||||
- (id) initWithDBEntry:(const CheatDBEntry *)dbEntry;
|
||||
- (ClientCheatItem *) newClientItem;
|
||||
|
||||
@end
|
||||
|
||||
@interface CocoaDSCheatDBGame : NSObject
|
||||
{
|
||||
CheatDBGame *_dbGame;
|
||||
CocoaDSCheatDBEntry *entryRoot;
|
||||
NSUInteger index;
|
||||
}
|
||||
|
||||
@property (assign) NSUInteger index;
|
||||
@property (readonly, nonatomic) NSString *title;
|
||||
@property (readonly, nonatomic) NSString *serial;
|
||||
@property (readonly, nonatomic) NSUInteger crc;
|
||||
@property (readonly, nonatomic) NSString *crcString;
|
||||
@property (readonly, nonatomic) NSInteger dataSize;
|
||||
@property (readonly, nonatomic) NSString *dataSizeString;
|
||||
@property (readonly, nonatomic) BOOL isDataLoaded;
|
||||
@property (readonly, nonatomic) NSInteger cheatItemCount;
|
||||
@property (readonly, nonatomic) CocoaDSCheatDBEntry *entryRoot;
|
||||
|
||||
- (id) initWithGameEntry:(const CheatDBGame *)gameEntry;
|
||||
- (CocoaDSCheatDBEntry *) loadEntryDataFromFilePtr:(FILE *)fp isEncrypted:(BOOL)isEncrypted;
|
||||
|
||||
@end
|
||||
|
||||
@interface CocoaDSCheatDatabase : NSObject
|
||||
{
|
||||
CheatDBFile *_dbFile;
|
||||
CheatDBGameList *_dbGameList;
|
||||
NSMutableArray *gameList;
|
||||
|
||||
NSURL *lastFileURL;
|
||||
}
|
||||
|
||||
@property (readonly) NSURL *lastFileURL;
|
||||
@property (readonly, nonatomic) NSString *description;
|
||||
@property (readonly, nonatomic) NSString *formatString;
|
||||
@property (readonly, nonatomic) BOOL isEncrypted;
|
||||
@property (readonly) NSMutableArray *gameList;
|
||||
|
||||
- (id) initWithFileURL:(NSURL *)fileURL error:(CheatSystemError *)errorCode;
|
||||
- (CocoaDSCheatDBGame *) getGameEntryUsingCode:(const char *)gameCode crc:(NSUInteger)crc;
|
||||
- (CocoaDSCheatDBEntry *) loadGameEntry:(CocoaDSCheatDBGame *)dbGame;
|
||||
|
||||
@end
|
||||
|
||||
@interface CocoaDSCheatManager : NSObject
|
||||
{
|
||||
ClientCheatManager *_internalCheatManager;
|
||||
NSMutableArray *sessionList;
|
||||
NSMutableArray *databaseList;
|
||||
NSMutableArray *searchResultsList;
|
||||
|
||||
pthread_rwlock_t *rwlockCoreExecute;
|
||||
|
@ -366,11 +436,10 @@ public:
|
|||
|
||||
@property (readonly, nonatomic, getter=internalManager) ClientCheatManager *_internalCheatManager;
|
||||
@property (readonly) NSMutableArray *sessionList;
|
||||
@property (readonly, nonatomic) NSString *currentGameCode;
|
||||
@property (readonly, nonatomic) NSUInteger currentGameCRC;
|
||||
@property (readonly, nonatomic) NSUInteger itemTotalCount;
|
||||
@property (readonly, nonatomic) NSUInteger itemActiveCount;
|
||||
@property (readonly) NSMutableArray *databaseList;
|
||||
@property (readonly, nonatomic) NSString *databaseTitle;
|
||||
@property (readonly, nonatomic) NSString *databaseDate;
|
||||
@property (readonly) NSMutableArray *searchResultsList;
|
||||
@property (readonly, nonatomic) BOOL searchDidStart;
|
||||
@property (readonly, nonatomic) NSUInteger searchCount;
|
||||
|
@ -389,8 +458,7 @@ public:
|
|||
- (void) loadFromMaster;
|
||||
- (void) applyToMaster;
|
||||
|
||||
- (NSMutableArray *) databaseListLoadFromFile:(NSURL *)fileURL errorCode:(NSInteger *)error;
|
||||
- (NSUInteger) databaseAddSelected;
|
||||
- (NSUInteger) databaseAddSelectedInEntry:(CocoaDSCheatDBEntry *)theEntry;
|
||||
|
||||
- (NSUInteger) runExactValueSearch:(NSInteger)value byteSize:(UInt8)byteSize signType:(NSInteger)signType;
|
||||
- (NSUInteger) runComparativeSearch:(NSInteger)typeID byteSize:(UInt8)byteSize signType:(NSInteger)signType;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -226,6 +226,10 @@ volatile bool execute = true;
|
|||
delete execControl;
|
||||
NDS_DeInit();
|
||||
|
||||
// We must call DestroyOpenGLRenderer() after NDS_Init() because we need to wait for
|
||||
// the OpenGL renderer to finish before we destroy its associated context.
|
||||
DestroyOpenGLRenderer();
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2011 Roger Manuel
|
||||
Copyright (C) 2012-2022 DeSmuME Team
|
||||
Copyright (C) 2012-2023 DeSmuME Team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -30,7 +30,7 @@
|
|||
#define NSSTRING_TITLE_EXPORT_ROM_SAVE_PANEL NSLocalizedString(@"Export ROM Save File", nil)
|
||||
#define NSSTRING_TITLE_SELECT_ROM_PANEL NSLocalizedString(@"Select ROM", nil)
|
||||
#define NSSTRING_TITLE_SELECT_ADVANSCENE_DB_PANEL NSLocalizedString(@"Select ADVANsCEne Database", nil)
|
||||
#define NSSTRING_TITLE_SELECT_R4_CHEAT_DB_PANEL NSLocalizedString(@"Select R4 Cheat Database", nil)
|
||||
#define NSSTRING_TITLE_OPEN_CHEAT_DB_PANEL NSLocalizedString(@"Open Cheat Database", nil)
|
||||
#define NSSTRING_TITLE_SELECT_ARM7_IMAGE_PANEL NSLocalizedString(@"Select ARM7 BIOS Image", nil)
|
||||
#define NSSTRING_TITLE_SELECT_ARM9_IMAGE_PANEL NSLocalizedString(@"Select ARM9 BIOS Image", nil)
|
||||
#define NSSTRING_TITLE_SELECT_FIRMWARE_IMAGE_PANEL NSLocalizedString(@"Select Firmware Image", nil)
|
||||
|
@ -303,41 +303,12 @@ enum
|
|||
SPU_SYNC_METHOD_P = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHEAT_TYPE_INTERNAL = 0,
|
||||
CHEAT_TYPE_ACTION_REPLAY = 1,
|
||||
CHEAT_TYPE_CODE_BREAKER = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE = 0,
|
||||
CHEATSEARCH_SEARCHSTYLE_COMPARATIVE = 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHEATSEARCH_COMPARETYPE_GREATER_THAN = 0,
|
||||
CHEATSEARCH_COMPARETYPE_LESSER_THAN = 1,
|
||||
CHEATSEARCH_COMPARETYPE_EQUALS_TO = 2,
|
||||
CHEATSEARCH_COMPARETYPE_NOT_EQUALS_TO = 3
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHEATSEARCH_UNSIGNED = 0,
|
||||
CHEATSEARCH_SIGNED = 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHEATEXPORT_ERROR_FILE_NOT_FOUND = 1,
|
||||
CHEATEXPORT_ERROR_WRONG_FILE_FORMAT = 2,
|
||||
CHEATEXPORT_ERROR_SERIAL_NOT_FOUND = 3,
|
||||
CHEATEXPORT_ERROR_EXPORT_FAILED = 4
|
||||
};
|
||||
|
||||
/*
|
||||
PORT MESSAGES
|
||||
*/
|
||||
|
|
|
@ -1199,7 +1199,8 @@ void UpdateDisplayPropertiesFromStates(uint64_t displayModeStates, ClientDisplay
|
|||
ClientCheatItem *newCheatItem = new ClientCheatItem;
|
||||
newCheatItem->SetType(CheatType_ActionReplay); // Default to Action Replay for now
|
||||
newCheatItem->SetFreezeType(CheatFreezeType_Normal);
|
||||
newCheatItem->SetDescription(NULL); // OpenEmu takes care of this
|
||||
newCheatItem->SetName(NULL); // OpenEmu takes care of this
|
||||
newCheatItem->SetComments(NULL); // OpenEmu does not support cheat item comments
|
||||
newCheatItem->SetRawCodeString([code cStringUsingEncoding:NSUTF8StringEncoding], true);
|
||||
newCheatItem->SetEnabled((enabled) ? true : false);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
Copyright (C) 2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class CocoaDSCheatDatabase;
|
||||
@class CheatWindowDelegate;
|
||||
@class CocoaDSCheatDBGame;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
|
||||
@interface CheatDatabaseWindowController : NSWindowController <NSWindowDelegate, NSTableViewDelegate>
|
||||
#else
|
||||
@interface CheatDatabaseWindowController : NSWindowController
|
||||
#endif
|
||||
{
|
||||
NSObject *dummyObject;
|
||||
NSWindow *errorSheet;
|
||||
NSString *defaultWindowTitle;
|
||||
NSArrayController *gameListController;
|
||||
NSTreeController *entryListController;
|
||||
NSSplitView *splitView;
|
||||
NSTableView *gameTable;
|
||||
NSOutlineView *entryOutline;
|
||||
NSFont *codeViewerFont;
|
||||
|
||||
CheatWindowDelegate *cheatManagerDelegate;
|
||||
CocoaDSCheatDatabase *database;
|
||||
|
||||
NSString *filePath;
|
||||
BOOL isFileLoading;
|
||||
BOOL isCurrentGameFound;
|
||||
BOOL isSelectedGameTheCurrentGame;
|
||||
NSInteger currentGameTableRowIndex;
|
||||
NSString *currentGameIndexString;
|
||||
NSString *currentGameSerial;
|
||||
NSUInteger currentGameCRC;
|
||||
BOOL isCompatibilityCheckIgnored;
|
||||
BOOL isOptionWarningSilenced;
|
||||
|
||||
NSString *errorMajorString;
|
||||
NSString *errorMinorString;
|
||||
|
||||
NSDictionary *initProperties;
|
||||
}
|
||||
|
||||
@property (readonly) IBOutlet NSObject *dummyObject;
|
||||
@property (readonly) IBOutlet NSWindow *errorSheet;
|
||||
@property (readonly) IBOutlet NSArrayController *gameListController;
|
||||
@property (readonly) IBOutlet NSTreeController *entryListController;
|
||||
@property (readonly) IBOutlet NSSplitView *splitView;
|
||||
@property (readonly) IBOutlet NSTableView *gameTable;
|
||||
@property (readonly) IBOutlet NSOutlineView *entryOutline;
|
||||
|
||||
@property (retain) CheatWindowDelegate *cheatManagerDelegate;
|
||||
@property (assign) NSFont *codeViewerFont;
|
||||
@property (retain, nonatomic) CocoaDSCheatDatabase *database;
|
||||
@property (readonly) NSString *filePath;
|
||||
@property (readonly) NSString *databaseFormatString;
|
||||
@property (readonly) NSInteger gameCount;
|
||||
@property (readonly) NSString *isEncryptedString;
|
||||
@property (assign) BOOL isFileLoading;
|
||||
@property (assign) BOOL isCurrentGameFound;
|
||||
@property (assign) BOOL isSelectedGameTheCurrentGame;
|
||||
@property (retain, nonatomic) NSString *currentGameSerial;
|
||||
@property (assign, nonatomic) NSUInteger currentGameCRC;
|
||||
@property (readonly, nonatomic) NSString *currentGameCRCString;
|
||||
@property (assign, nonatomic) BOOL isCompatibilityCheckIgnored;
|
||||
@property (assign) BOOL isOptionWarningSilenced;
|
||||
|
||||
@property (assign) NSString *errorMajorString;
|
||||
@property (assign) NSString *errorMinorString;
|
||||
|
||||
- (id) initWithWindowNibName:(NSString *)windowNibName delegate:(CheatWindowDelegate *)theDelegate;
|
||||
- (void) loadFileStart:(NSURL *)theURL;
|
||||
- (void) loadFileOnThread:(id)object;
|
||||
- (void) loadFileDidFinish:(NSNotification *)aNotification;
|
||||
- (void) updateWindow;
|
||||
+ (void) setCurrentGameForAllWindowsSerial:(NSString *)serialString crc:(NSUInteger)crc;
|
||||
- (void) validateGameTableFonts;
|
||||
- (BOOL) validateWillAddColumn;
|
||||
- (void) showErrorSheet:(NSInteger)errorCode;
|
||||
- (void) didEndErrorSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
|
||||
|
||||
- (IBAction) openFile:(id)sender;
|
||||
- (IBAction) selectAll:(id)sender;
|
||||
- (IBAction) selectNone:(id)sender;
|
||||
- (IBAction) addSelected:(id)sender;
|
||||
- (IBAction) selectCurrentGame:(id)sender;
|
||||
- (IBAction) closeErrorSheet:(id)sender;
|
||||
|
||||
@end
|
|
@ -0,0 +1,818 @@
|
|||
/*
|
||||
Copyright (C) 2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import "CheatDatabaseWindowController.h"
|
||||
#import "cheatWindowDelegate.h"
|
||||
#import "../cocoa_globals.h"
|
||||
#import "../cocoa_cheat.h"
|
||||
#import "../cocoa_util.h"
|
||||
|
||||
NSMutableArray *cheatDatabaseWindowList = nil;
|
||||
|
||||
@implementation CheatDatabaseWindowController
|
||||
|
||||
@synthesize dummyObject;
|
||||
@synthesize errorSheet;
|
||||
@synthesize gameListController;
|
||||
@synthesize entryListController;
|
||||
@synthesize splitView;
|
||||
@synthesize gameTable;
|
||||
@synthesize entryOutline;
|
||||
|
||||
@synthesize cheatManagerDelegate;
|
||||
@synthesize codeViewerFont;
|
||||
@dynamic database;
|
||||
@dynamic filePath;
|
||||
@dynamic databaseFormatString;
|
||||
@dynamic gameCount;
|
||||
@dynamic isEncryptedString;
|
||||
@synthesize isFileLoading;
|
||||
@synthesize isCurrentGameFound;
|
||||
@synthesize isSelectedGameTheCurrentGame;
|
||||
@dynamic currentGameSerial;
|
||||
@synthesize currentGameCRC;
|
||||
@dynamic currentGameCRCString;
|
||||
@dynamic isCompatibilityCheckIgnored;
|
||||
@synthesize isOptionWarningSilenced;
|
||||
|
||||
@synthesize errorMajorString;
|
||||
@synthesize errorMinorString;
|
||||
|
||||
- (id) initWithWindowNibName:(NSString *)windowNibName delegate:(CheatWindowDelegate *)theDelegate
|
||||
{
|
||||
self = [super initWithWindowNibName:windowNibName];
|
||||
if (self == nil)
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
cheatManagerDelegate = [theDelegate retain];
|
||||
codeViewerFont = [NSFont fontWithName:@"Monaco" size:13.0];
|
||||
|
||||
dummyObject = nil;
|
||||
defaultWindowTitle = [[NSString alloc] initWithString:@"Cheat Database Viewer"];
|
||||
database = nil;
|
||||
isFileLoading = NO;
|
||||
isCurrentGameFound = NO;
|
||||
isSelectedGameTheCurrentGame = NO;
|
||||
currentGameIndexString = [[NSString alloc] initWithString:@"NSNotFound"];
|
||||
currentGameTableRowIndex = NSNotFound;
|
||||
currentGameSerial = nil;
|
||||
currentGameCRC = 0;
|
||||
isCompatibilityCheckIgnored = NO;
|
||||
isOptionWarningSilenced = NO;
|
||||
errorMajorString = @"No error has occurred!";
|
||||
errorMinorString = @"This is just a placeholder message for initialization purposes.";
|
||||
|
||||
if (cheatDatabaseWindowList == nil)
|
||||
{
|
||||
cheatDatabaseWindowList = [[NSMutableArray alloc] initWithObjects:self, nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cheatDatabaseWindowList addObject:self];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self setCheatManagerDelegate:nil];
|
||||
[self setDatabase:nil];
|
||||
[currentGameIndexString release];
|
||||
[defaultWindowTitle release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) loadFileStart:(NSURL *)theURL
|
||||
{
|
||||
if (theURL == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// First check if another cheat database window has already opened the file at this URL.
|
||||
CheatDatabaseWindowController *foundWindowController = nil;
|
||||
for (CheatDatabaseWindowController *windowController in cheatDatabaseWindowList)
|
||||
{
|
||||
NSURL *databaseURL = [[windowController database] lastFileURL];
|
||||
NSString *foundDatabaseFilePath = [databaseURL path];
|
||||
|
||||
if ( (foundDatabaseFilePath != nil) && ([foundDatabaseFilePath isEqualToString:[theURL path]]) )
|
||||
{
|
||||
foundWindowController = windowController;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundWindowController != nil)
|
||||
{
|
||||
// If the file is already open, then simply assign that database file to this window.
|
||||
[self setDatabase:[foundWindowController database]];
|
||||
[self updateWindow];
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the file is not open, then we need to open it now. Let's do this on a separate
|
||||
// thread so that we don't lock up the main thread.
|
||||
[self setIsFileLoading:YES];
|
||||
[self setDatabase:nil];
|
||||
|
||||
NSString *threadNamePrefix = @"org.desmume.DeSmuME.loadDatabaseDidFinish_";
|
||||
NSString *fullThreadName = [threadNamePrefix stringByAppendingString:[theURL absoluteString]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(loadFileDidFinish:)
|
||||
name:fullThreadName
|
||||
object:nil];
|
||||
|
||||
[theURL retain];
|
||||
[NSThread detachNewThreadSelector:@selector(loadFileOnThread:) toTarget:self withObject:theURL];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) loadFileOnThread:(id)object
|
||||
{
|
||||
NSAutoreleasePool *threadPool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSURL *workingURL = (NSURL *)object;
|
||||
NSString *threadNamePrefix = @"org.desmume.DeSmuME.loadDatabaseDidFinish_";
|
||||
NSString *fullThreadName = [threadNamePrefix stringByAppendingString:[workingURL absoluteString]];
|
||||
|
||||
CheatSystemError error = CheatSystemError_NoError;
|
||||
CocoaDSCheatDatabase *newDatabase = [[CocoaDSCheatDatabase alloc] initWithFileURL:workingURL error:&error];
|
||||
|
||||
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||
workingURL, @"URL",
|
||||
[NSNumber numberWithInteger:(NSInteger)error], @"ErrorCode",
|
||||
nil];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:fullThreadName object:newDatabase userInfo:userInfo];
|
||||
|
||||
[threadPool release];
|
||||
}
|
||||
|
||||
- (void) loadFileDidFinish:(NSNotification *)aNotification
|
||||
{
|
||||
CocoaDSCheatDatabase *newDatabase = [aNotification object];
|
||||
NSDictionary *userInfo = [aNotification userInfo];
|
||||
NSURL *workingURL = (NSURL *)[userInfo valueForKey:@"URL"];
|
||||
CheatSystemError errorCode = (CheatSystemError)[(NSNumber *)[userInfo valueForKey:@"ErrorCode"] integerValue];
|
||||
|
||||
NSString *threadNamePrefix = @"org.desmume.DeSmuME.loadDatabaseDidFinish_";
|
||||
NSString *fullThreadName = [threadNamePrefix stringByAppendingString:[workingURL absoluteString]];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:fullThreadName object:nil];
|
||||
|
||||
[self setIsFileLoading:NO];
|
||||
[self setDatabase:[newDatabase autorelease]];
|
||||
[self updateWindow];
|
||||
|
||||
if (errorCode != CheatSystemError_NoError)
|
||||
{
|
||||
[self showErrorSheet:errorCode];
|
||||
}
|
||||
|
||||
if (database == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Begin the generation of the cheat database recents menu.
|
||||
NSString *legacyFilePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
|
||||
BOOL useLegacyFilePath = ( (legacyFilePath != nil) && ([legacyFilePath length] > 0) );
|
||||
|
||||
NSArray *dbRecentsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
|
||||
NSMutableArray *newRecentsList = [NSMutableArray arrayWithCapacity:[dbRecentsList count] + 1];
|
||||
|
||||
if (useLegacyFilePath)
|
||||
{
|
||||
// We need to check if the legacy file path also exists in the recents list.
|
||||
// If it does, then the recents list version takes priority.
|
||||
for (NSDictionary *dbRecentItem in dbRecentsList)
|
||||
{
|
||||
NSString *dbRecentItemFilePath = (NSString *)[dbRecentItem valueForKey:@"FilePath"];
|
||||
if ([dbRecentItemFilePath isEqualToString:legacyFilePath])
|
||||
{
|
||||
useLegacyFilePath = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useLegacyFilePath)
|
||||
{
|
||||
// The legacy file path must always be the first entry of the recents list.
|
||||
NSDictionary *legacyRecentItem = [NSDictionary dictionaryWithObjectsAndKeys:legacyFilePath, @"FilePath",
|
||||
[legacyFilePath lastPathComponent], @"FileName",
|
||||
nil];
|
||||
[newRecentsList addObject:legacyRecentItem];
|
||||
}
|
||||
|
||||
// Next, we need to add back all of the recent items in the same order in which
|
||||
// they appear in user defaults, with the exception of our newest item.
|
||||
NSString *newFilePath = [[database lastFileURL] path];
|
||||
for (NSDictionary *dbRecentItem in dbRecentsList)
|
||||
{
|
||||
NSString *dbRecentItemFilePath = (NSString *)[dbRecentItem valueForKey:@"FilePath"];
|
||||
if ( ![newFilePath isEqualToString:dbRecentItemFilePath] )
|
||||
{
|
||||
[newRecentsList addObject:dbRecentItem];
|
||||
}
|
||||
}
|
||||
|
||||
// Create our new recent item...
|
||||
NSDictionary *newRecentItem = [NSDictionary dictionaryWithObjectsAndKeys:newFilePath, @"FilePath",
|
||||
[newFilePath lastPathComponent], @"FileName",
|
||||
[NSDate date], @"AddedDate",
|
||||
[[self window] stringWithSavedFrame], @"WindowFrame",
|
||||
[NSNumber numberWithFloat:[[[splitView subviews] objectAtIndex:0] frame].size.height], @"WindowSplitViewDividerPosition",
|
||||
[NSNumber numberWithBool:[self isCompatibilityCheckIgnored]], @"OptionIgnoreCompatibilityCheck",
|
||||
nil];
|
||||
|
||||
// ...and then add the newest recent item, ensuring that it is always last in the list.
|
||||
[newRecentsList addObject:newRecentItem];
|
||||
|
||||
// We're done generating the new recent items list, so write it back to user defaults, and then
|
||||
// send a notification that UI elements needs to be updated.
|
||||
[[NSUserDefaults standardUserDefaults] setObject:newRecentsList forKey:@"CheatDatabase_RecentFilePath"];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"org.desmume.DeSmuME.updateCheatDatabaseRecentsMenu" object:[newRecentsList retain] userInfo:nil];
|
||||
}
|
||||
|
||||
- (void) updateWindow
|
||||
{
|
||||
if ([self database] == nil)
|
||||
{
|
||||
[[self window] setTitle:defaultWindowTitle];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[self window] setTitle:[database description]];
|
||||
}
|
||||
|
||||
[[self window] setRepresentedURL:[database lastFileURL]];
|
||||
[gameListController setContent:[database gameList]];
|
||||
|
||||
NSIndexSet *selectedRows = [gameTable selectedRowIndexes];
|
||||
[gameTable deselectAll:nil];
|
||||
[gameTable selectRowIndexes:selectedRows byExtendingSelection:NO];
|
||||
|
||||
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
|
||||
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
|
||||
[self setCurrentGameSerial:[cheatManager currentGameCode]];
|
||||
[self setCurrentGameCRC:[cheatManager currentGameCRC]];
|
||||
|
||||
[self validateGameTableFonts];
|
||||
[self selectCurrentGame:nil];
|
||||
}
|
||||
|
||||
+ (void) setCurrentGameForAllWindowsSerial:(NSString *)serialString crc:(NSUInteger)crc
|
||||
{
|
||||
if (cheatDatabaseWindowList == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (CheatDatabaseWindowController *windowController in cheatDatabaseWindowList)
|
||||
{
|
||||
[windowController setCurrentGameSerial:serialString];
|
||||
[windowController setCurrentGameCRC:crc];
|
||||
|
||||
[windowController validateGameTableFonts];
|
||||
[[windowController gameTable] setNeedsDisplay];
|
||||
|
||||
[windowController validateWillAddColumn];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) validateGameTableFonts
|
||||
{
|
||||
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
|
||||
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
|
||||
|
||||
if ( (delegate == nil) || (cheatManager == nil) )
|
||||
{
|
||||
currentGameTableRowIndex = NSNotFound;
|
||||
[currentGameIndexString release];
|
||||
currentGameIndexString = [[NSString alloc] initWithString:@"NSNotFound"];
|
||||
[self setIsCurrentGameFound:NO];
|
||||
return;
|
||||
}
|
||||
|
||||
for (CocoaDSCheatDBGame *game in [gameListController content])
|
||||
{
|
||||
if ( ([game crc] == [self currentGameCRC]) && ([[game serial] isEqualToString:[self currentGameSerial]]) )
|
||||
{
|
||||
[currentGameIndexString release];
|
||||
currentGameIndexString = [[NSString alloc] initWithFormat:@"%llu", (unsigned long long)[game index]];
|
||||
[self setIsCurrentGameFound:YES];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) validateWillAddColumn
|
||||
{
|
||||
BOOL showWillAddColumn = NO;
|
||||
|
||||
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
|
||||
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
|
||||
|
||||
NSArray *selectedObjects = [gameListController selectedObjects];
|
||||
if ( (selectedObjects == nil) || ([selectedObjects count] == 0) )
|
||||
{
|
||||
return showWillAddColumn;
|
||||
}
|
||||
|
||||
CocoaDSCheatDBGame *selectedGame = [selectedObjects objectAtIndex:0];
|
||||
|
||||
if ( (delegate != nil) && (cheatManager != nil) && ([selectedGame serial] != nil) )
|
||||
{
|
||||
showWillAddColumn = ( [self isCompatibilityCheckIgnored] || (([[selectedGame serial] isEqualToString:currentGameSerial]) && ([selectedGame crc] == currentGameCRC)) );
|
||||
}
|
||||
|
||||
NSTableColumn *willAddColumn = [entryOutline tableColumnWithIdentifier:@"willAdd"];
|
||||
[willAddColumn setHidden:!showWillAddColumn];
|
||||
|
||||
[self setIsSelectedGameTheCurrentGame:showWillAddColumn];
|
||||
|
||||
return showWillAddColumn;
|
||||
}
|
||||
|
||||
- (void) showErrorSheet:(NSInteger)errorCode
|
||||
{
|
||||
switch (errorCode)
|
||||
{
|
||||
case CheatSystemError_NoError:
|
||||
[self setErrorMajorString:@"No error has occurred."];
|
||||
[self setErrorMinorString:@"This message is a placeholder. You are seeing this error as a test for this app's error handling.\n\nError Code: %i"];
|
||||
break;
|
||||
|
||||
case CheatSystemError_FileOpenFailed:
|
||||
[self setErrorMajorString:@"Failed to open file."];
|
||||
[self setErrorMinorString:[NSString stringWithFormat:@"The system could not open the cheat database file. This problem is usually because another app is using it, or because the file permissions disallow read access.\n\nError Code: %i", (int)errorCode]];
|
||||
break;
|
||||
|
||||
case CheatSystemError_FileFormatInvalid:
|
||||
[self setErrorMajorString:@"Invalid file format."];
|
||||
[self setErrorMinorString:[NSString stringWithFormat:@"DeSmuME could not recognize the file format of the cheat database file. Currently, DeSmuME only recognizes the R4 file format. It is also possible that the file data is corrupted.\n\nError Code: %i", (int)errorCode]];
|
||||
break;
|
||||
|
||||
case CheatSystemError_GameNotFound:
|
||||
{
|
||||
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
|
||||
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
|
||||
[self setErrorMajorString:@"Current game not found in database."];
|
||||
[self setErrorMinorString:[NSString stringWithFormat:@"The current game (Serial='%@', CRC=%llu) could not be found in the cheat database.\n\nError Code: %i", [cheatManager currentGameCode], (unsigned long long)[cheatManager currentGameCRC], (int)errorCode]];
|
||||
break;
|
||||
}
|
||||
|
||||
case CheatSystemError_LoadEntryError:
|
||||
[self setErrorMajorString:@"Could not read cheat entries."];
|
||||
[self setErrorMinorString:[NSString stringWithFormat:@"The entry data for the selected game could not be read. This is usually due to file data corruption.\n\nError Code: %i", (int)errorCode]];
|
||||
break;
|
||||
|
||||
case CheatSystemError_FileDoesNotExist:
|
||||
[self setErrorMajorString:@"The file does not exist."];
|
||||
[self setErrorMinorString:[NSString stringWithFormat:@"If this file was selected from the Recents Menu, then it has been removed.\n\nError Code: %i", (int)errorCode]];
|
||||
break;
|
||||
|
||||
default:
|
||||
[self setErrorMajorString:@"An unknown error has occurred."];
|
||||
[self setErrorMinorString:[NSString stringWithFormat:@"Error Code: %i", (int)errorCode]];
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(MAC_OS_X_VERSION_10_9) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9)
|
||||
if ([[self window] respondsToSelector:@selector(beginSheet:completionHandler:)])
|
||||
{
|
||||
[[self window] beginSheet:errorSheet
|
||||
completionHandler:^(NSModalResponse response) {
|
||||
[self didEndErrorSheet:nil returnCode:response contextInfo:nil];
|
||||
} ];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SILENCE_DEPRECATION_MACOS_10_10( [NSApp beginSheet:errorSheet
|
||||
modalForWindow:[self window]
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(didEndErrorSheet:returnCode:contextInfo:)
|
||||
contextInfo:nil] );
|
||||
}
|
||||
}
|
||||
|
||||
- (void) didEndErrorSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[sheet orderOut:self];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Dynamic Properties
|
||||
|
||||
- (void) setDatabase:(CocoaDSCheatDatabase *)theDatabase
|
||||
{
|
||||
[self willChangeValueForKey:@"filePath"];
|
||||
[self willChangeValueForKey:@"databaseFormatString"];
|
||||
[self willChangeValueForKey:@"gameCount"];
|
||||
[self willChangeValueForKey:@"isEncryptedString"];
|
||||
|
||||
[theDatabase retain];
|
||||
[database release];
|
||||
database = theDatabase;
|
||||
|
||||
[self didChangeValueForKey:@"filePath"];
|
||||
[self didChangeValueForKey:@"databaseFormatString"];
|
||||
[self didChangeValueForKey:@"gameCount"];
|
||||
[self didChangeValueForKey:@"isEncryptedString"];
|
||||
}
|
||||
|
||||
- (CocoaDSCheatDatabase *) database
|
||||
{
|
||||
return database;
|
||||
}
|
||||
|
||||
- (NSString *) filePath
|
||||
{
|
||||
if ( (database != nil) && ([database lastFileURL] != nil) )
|
||||
{
|
||||
return [[database lastFileURL] path];
|
||||
}
|
||||
else if ([self isFileLoading])
|
||||
{
|
||||
return @"Loading database file...";
|
||||
}
|
||||
|
||||
return @"No database file loaded.";
|
||||
}
|
||||
|
||||
- (NSString *) databaseFormatString
|
||||
{
|
||||
if (database != nil)
|
||||
{
|
||||
return [database formatString];
|
||||
}
|
||||
|
||||
return @"---";
|
||||
}
|
||||
|
||||
- (NSInteger) gameCount
|
||||
{
|
||||
if (database != nil)
|
||||
{
|
||||
return [[database gameList] count];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (NSString *) isEncryptedString
|
||||
{
|
||||
if (database != nil)
|
||||
{
|
||||
return [database isEncrypted] ? @"Yes" : @"No";
|
||||
}
|
||||
|
||||
return @"---";
|
||||
}
|
||||
|
||||
- (void) setCurrentGameSerial:(NSString *)newString
|
||||
{
|
||||
NSString *oldString = currentGameSerial;
|
||||
currentGameSerial = [newString retain];
|
||||
[oldString release];
|
||||
}
|
||||
|
||||
- (NSString *) currentGameSerial
|
||||
{
|
||||
if ( (currentGameSerial != nil) && ([currentGameSerial length] > 0) )
|
||||
{
|
||||
return currentGameSerial;
|
||||
}
|
||||
|
||||
return @"---";
|
||||
}
|
||||
|
||||
- (void) setCurrentGameCRC:(NSUInteger)crc
|
||||
{
|
||||
[self willChangeValueForKey:@"currentGameCRCString"];
|
||||
currentGameCRC = crc;
|
||||
[self didChangeValueForKey:@"currentGameCRCString"];
|
||||
}
|
||||
|
||||
- (NSUInteger) currentGameCRC
|
||||
{
|
||||
return currentGameCRC;
|
||||
}
|
||||
|
||||
- (NSString *) currentGameCRCString
|
||||
{
|
||||
if (currentGameCRC != 0)
|
||||
{
|
||||
return [NSString stringWithFormat:@"%08lX", (unsigned long)currentGameCRC];
|
||||
}
|
||||
|
||||
return @"---";
|
||||
}
|
||||
|
||||
- (BOOL) isCompatibilityCheckIgnored
|
||||
{
|
||||
return isCompatibilityCheckIgnored;
|
||||
}
|
||||
|
||||
- (void) setIsCompatibilityCheckIgnored:(BOOL)theState
|
||||
{
|
||||
isCompatibilityCheckIgnored = theState;
|
||||
|
||||
if (![self isOptionWarningSilenced] && theState)
|
||||
{
|
||||
NSAlert *criticalErrorAlert = [[[NSAlert alloc] init] autorelease];
|
||||
[criticalErrorAlert setAlertStyle:ALERTSTYLE_CRITICAL];
|
||||
[criticalErrorAlert setMessageText:@"Using an incompatible cheat may ruin your game."];
|
||||
[criticalErrorAlert setInformativeText:@"Cheats are normally restricted to the current game \
|
||||
for compatibility reasons. By choosing to ignore the compatibility check, you can add any cheat to \
|
||||
any game that you want, but you must also assume the risk of an incompatible cheat ruining your game \
|
||||
session or corrupting your game's save data."];
|
||||
[criticalErrorAlert runModal];
|
||||
}
|
||||
|
||||
[self validateWillAddColumn];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark IBActions
|
||||
|
||||
- (IBAction) openFile:(id)sender
|
||||
{
|
||||
NSOpenPanel *panel = [NSOpenPanel openPanel];
|
||||
[panel setCanChooseDirectories:NO];
|
||||
[panel setCanChooseFiles:YES];
|
||||
[panel setResolvesAliases:YES];
|
||||
[panel setAllowsMultipleSelection:NO];
|
||||
[panel setTitle:NSSTRING_TITLE_OPEN_CHEAT_DB_PANEL];
|
||||
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_R4_CHEAT_DB, nil];
|
||||
|
||||
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
|
||||
// is deprecated in Mac OS X v10.6.
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
|
||||
if (IsOSXVersionSupported(10, 6, 0))
|
||||
{
|
||||
[panel setAllowedFileTypes:fileTypes];
|
||||
[panel beginSheetModalForWindow:[self window]
|
||||
completionHandler:^(NSInteger result) {
|
||||
[self chooseCheatDatabaseDidEnd:panel returnCode:(int)result contextInfo:nil];
|
||||
} ];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SILENCE_DEPRECATION_MACOS_10_6( [panel beginSheetForDirectory:nil
|
||||
file:nil
|
||||
types:fileTypes
|
||||
modalForWindow:[self window]
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(chooseCheatDatabaseDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil] );
|
||||
}
|
||||
}
|
||||
|
||||
- (void) chooseCheatDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[sheet orderOut:self];
|
||||
|
||||
if (returnCode == GUI_RESPONSE_CANCEL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
|
||||
[self loadFileStart:selectedFileURL];
|
||||
}
|
||||
|
||||
- (IBAction) selectAll:(id)sender
|
||||
{
|
||||
NSMutableArray *entryTree = [entryListController content];
|
||||
if (entryTree == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (CocoaDSCheatDBEntry *entry in entryTree)
|
||||
{
|
||||
[entry setWillAdd:YES];
|
||||
}
|
||||
|
||||
[entryOutline setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (IBAction) selectNone:(id)sender
|
||||
{
|
||||
NSMutableArray *entryTree = [entryListController content];
|
||||
if (entryTree == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (CocoaDSCheatDBEntry *entry in entryTree)
|
||||
{
|
||||
[entry setWillAdd:NO];
|
||||
}
|
||||
|
||||
[entryOutline setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (IBAction) addSelected:(id)sender
|
||||
{
|
||||
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
|
||||
if (delegate == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
|
||||
if (cheatManager == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray *entryTree = [entryListController content];
|
||||
if (entryTree == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSInteger selectedIndex = [gameTable selectedRow];
|
||||
CocoaDSCheatDBGame *selectedGame = (CocoaDSCheatDBGame *)[[gameListController arrangedObjects] objectAtIndex:selectedIndex];
|
||||
|
||||
if ( ![self isCompatibilityCheckIgnored] && ((![[selectedGame serial] isEqualToString:[self currentGameSerial]]) || ([selectedGame crc] != [self currentGameCRC])) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CocoaDSCheatDBEntry *rootEntry = [selectedGame entryRoot];
|
||||
if (rootEntry == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const NSInteger addedItemCount = [cheatManager databaseAddSelectedInEntry:[selectedGame entryRoot]];
|
||||
if (addedItemCount > 0)
|
||||
{
|
||||
[[delegate cheatListController] setContent:[cheatManager sessionList]];
|
||||
[cheatManager save];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction) selectCurrentGame:(id)sender
|
||||
{
|
||||
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
|
||||
if (delegate == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
|
||||
if (cheatManager == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ([self currentGameSerial] == nil) || ([self currentGameCRC] == 0) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSUInteger selectionIndex = NSNotFound;
|
||||
|
||||
NSArray *arrangedObjects = (NSArray *)[gameListController arrangedObjects];
|
||||
for (CocoaDSCheatDBGame *game in arrangedObjects)
|
||||
{
|
||||
if ( ([game crc] == [self currentGameCRC]) && ([[game serial] isEqualToString:[self currentGameSerial]]) )
|
||||
{
|
||||
selectionIndex = [arrangedObjects indexOfObject:game];
|
||||
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:selectionIndex];
|
||||
[gameTable selectRowIndexes:indexSet byExtendingSelection:NO];
|
||||
[gameTable scrollRowToVisible:selectionIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction) closeErrorSheet:(id)sender
|
||||
{
|
||||
NSWindow *sheet = [(NSControl *)sender window];
|
||||
const NSInteger code = [(NSControl *)sender tag];
|
||||
|
||||
[CocoaDSUtil endSheet:sheet returnCode:code];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSWindowDelegate Protocol
|
||||
|
||||
- (void)windowDidLoad
|
||||
{
|
||||
// Save a copy of the default window title before we replace it
|
||||
// with the database file's description.
|
||||
NSString *oldDefaultWindowTitle = defaultWindowTitle;
|
||||
defaultWindowTitle = [[[self window] title] copy];
|
||||
[oldDefaultWindowTitle release];
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
NSArray *userDefaultsRecentsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
|
||||
if ( (userDefaultsRecentsList != nil) && ([userDefaultsRecentsList count] > 0) )
|
||||
{
|
||||
NSMutableArray *dbRecentsList = [NSMutableArray arrayWithCapacity:[userDefaultsRecentsList count]];
|
||||
|
||||
for (NSDictionary *recentItem in userDefaultsRecentsList)
|
||||
{
|
||||
NSString *thisFilePath = [[database lastFileURL] path];
|
||||
NSString *recentItemPath = (NSString *)[recentItem objectForKey:@"FilePath"];
|
||||
|
||||
if ( (thisFilePath != nil) && ([recentItemPath isEqualToString:thisFilePath]) )
|
||||
{
|
||||
NSMutableDictionary *newRecentItem = [NSMutableDictionary dictionaryWithDictionary:recentItem];
|
||||
[newRecentItem setObject:[[self window] stringWithSavedFrame] forKey:@"WindowFrame"];
|
||||
[newRecentItem setObject:[NSNumber numberWithFloat:[[[splitView subviews] objectAtIndex:0] frame].size.height] forKey:@"WindowSplitViewDividerPosition"];
|
||||
[newRecentItem setObject:[NSNumber numberWithBool:[self isCompatibilityCheckIgnored]] forKey:@"OptionIgnoreCompatibilityCheck"];
|
||||
|
||||
[dbRecentsList addObject:newRecentItem];
|
||||
}
|
||||
else
|
||||
{
|
||||
[dbRecentsList addObject:recentItem];
|
||||
}
|
||||
}
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setObject:dbRecentsList forKey:@"CheatDatabase_RecentFilePath"];
|
||||
}
|
||||
|
||||
[cheatDatabaseWindowList removeObject:self];
|
||||
[self release];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSTableViewDelegate Protocol
|
||||
|
||||
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
|
||||
{
|
||||
NSTableView *table = (NSTableView *)[aNotification object];
|
||||
NSInteger rowIndex = [table selectedRow];
|
||||
|
||||
if (table == gameTable)
|
||||
{
|
||||
if (rowIndex >= 0)
|
||||
{
|
||||
NSArray *selectedObjects = [gameListController selectedObjects];
|
||||
CocoaDSCheatDBGame *selectedGame = [selectedObjects objectAtIndex:0];
|
||||
CocoaDSCheatDBEntry *entryRoot = [database loadGameEntry:selectedGame];
|
||||
[self validateWillAddColumn];
|
||||
[entryListController setContent:[entryRoot child]];
|
||||
|
||||
if (entryRoot == nil)
|
||||
{
|
||||
[self showErrorSheet:CheatSystemError_LoadEntryError];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[entryListController setContent:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||||
{
|
||||
NSString *cellString = [cell stringValue];
|
||||
if ( (cellString != nil) && [cellString isEqualToString:currentGameIndexString] )
|
||||
{
|
||||
currentGameTableRowIndex = row;
|
||||
}
|
||||
|
||||
if ( (cellString != nil) && (row == currentGameTableRowIndex) )
|
||||
{
|
||||
[cell setFont:[NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize] + 1.0f]];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cell setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
|
||||
currentGameTableRowIndex = NSNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -54,8 +54,8 @@ class AudioSampleBlockGenerator;
|
|||
NSObjectController *cheatWindowController;
|
||||
NSObjectController *slot2WindowController;
|
||||
NSArrayController *inputDeviceListController;
|
||||
NSArrayController *cheatListController;
|
||||
NSArrayController *cheatDatabaseController;
|
||||
|
||||
NSMenu *cheatDatabaseRecentsMenu;
|
||||
|
||||
RomInfoPanel *romInfoPanel;
|
||||
|
||||
|
@ -148,8 +148,8 @@ class AudioSampleBlockGenerator;
|
|||
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
|
||||
@property (readonly) IBOutlet NSObjectController *slot2WindowController;
|
||||
@property (readonly) IBOutlet NSArrayController *inputDeviceListController;
|
||||
@property (readonly) IBOutlet NSArrayController *cheatListController;
|
||||
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
|
||||
|
||||
@property (readonly) IBOutlet NSMenu *cheatDatabaseRecentsMenu;
|
||||
|
||||
@property (readonly) IBOutlet RomInfoPanel *romInfoPanel;
|
||||
|
||||
|
@ -214,6 +214,9 @@ class AudioSampleBlockGenerator;
|
|||
- (IBAction) stopReplay:(id)sender;
|
||||
- (IBAction) importRomSave:(id)sender;
|
||||
- (IBAction) exportRomSave:(id)sender;
|
||||
- (IBAction) openCheatDatabaseFile:(id)sender;
|
||||
- (IBAction) clearCheatDatabaseRecents:(id)sender;
|
||||
- (IBAction) openRecentCheatDatabase:(id)sender;
|
||||
|
||||
// Emulation Menu
|
||||
- (IBAction) toggleSpeedLimiter:(id)sender;
|
||||
|
@ -299,6 +302,7 @@ class AudioSampleBlockGenerator;
|
|||
- (BOOL) loadRomByURL:(NSURL *)romURL asynchronous:(BOOL)willLoadAsync;
|
||||
- (void) loadRomDidFinish:(NSNotification *)aNotification;
|
||||
- (BOOL) unloadRom;
|
||||
- (void) updateCheatDatabaseRecentsMenu:(NSNotification *)aNotification;
|
||||
|
||||
- (void) addOutputToCore:(CocoaDSOutput *)theOutput;
|
||||
- (void) removeOutputFromCore:(CocoaDSOutput *)theOutput;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#import "DisplayWindowController.h"
|
||||
#import "InputManager.h"
|
||||
#import "cheatWindowDelegate.h"
|
||||
#import "CheatDatabaseWindowController.h"
|
||||
#import "Slot2WindowDelegate.h"
|
||||
#import "MacAVCaptureTool.h"
|
||||
#import "MacScreenshotCaptureTool.h"
|
||||
|
@ -56,11 +57,11 @@
|
|||
@synthesize cdsCoreController;
|
||||
@synthesize cdsSoundController;
|
||||
@synthesize cheatWindowController;
|
||||
@synthesize cheatListController;
|
||||
@synthesize cheatDatabaseController;
|
||||
@synthesize slot2WindowController;
|
||||
@synthesize inputDeviceListController;
|
||||
|
||||
@synthesize cheatDatabaseRecentsMenu;
|
||||
|
||||
@synthesize romInfoPanel;
|
||||
|
||||
@synthesize displayRotationPanel;
|
||||
|
@ -196,6 +197,11 @@
|
|||
name:@"org.desmume.DeSmuME.handleEmulatorExecutionState"
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(updateCheatDatabaseRecentsMenu:)
|
||||
name:@"org.desmume.DeSmuME.updateCheatDatabaseRecentsMenu"
|
||||
object:nil];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -804,6 +810,104 @@
|
|||
[self restoreCoreState];
|
||||
}
|
||||
|
||||
- (IBAction) openCheatDatabaseFile:(id)sender
|
||||
{
|
||||
CheatDatabaseWindowController *newWindowController = [[CheatDatabaseWindowController alloc] initWithWindowNibName:@"CheatDatabaseViewer" delegate:cheatWindowDelegate];
|
||||
[newWindowController window]; // Just reference the window to force the NSWindow object to load.
|
||||
|
||||
[[newWindowController window] makeKeyAndOrderFront:sender];
|
||||
[[newWindowController window] makeMainWindow];
|
||||
[newWindowController openFile:sender];
|
||||
}
|
||||
|
||||
- (IBAction) clearCheatDatabaseRecents:(id)sender
|
||||
{
|
||||
NSArray *menuItemList = [cheatDatabaseRecentsMenu itemArray];
|
||||
|
||||
for (NSMenuItem *menuItem in menuItemList)
|
||||
{
|
||||
if ( ([menuItem action] == @selector(openRecentCheatDatabase:)) || [menuItem isSeparatorItem] )
|
||||
{
|
||||
[cheatDatabaseRecentsMenu removeItem:menuItem];
|
||||
}
|
||||
}
|
||||
|
||||
NSArray *emptyArray = [[[NSArray alloc] init] autorelease];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:emptyArray forKey:@"CheatDatabase_RecentFilePath"];
|
||||
|
||||
// Also remove the legacy setting.
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"R4Cheat_DatabasePath"];
|
||||
}
|
||||
|
||||
- (IBAction) openRecentCheatDatabase:(id)sender
|
||||
{
|
||||
CheatDatabaseWindowController *newWindowController = [[CheatDatabaseWindowController alloc] initWithWindowNibName:@"CheatDatabaseViewer" delegate:cheatWindowDelegate];
|
||||
[newWindowController window]; // Just reference the window to force the NSWindow object to load.
|
||||
|
||||
[[newWindowController window] makeKeyAndOrderFront:self];
|
||||
[[newWindowController window] makeMainWindow];
|
||||
|
||||
NSArray *recentDBFilePathsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
|
||||
NSInteger index = [CocoaDSUtil getIBActionSenderTag:sender];
|
||||
NSDictionary *recentItem = (NSDictionary *)[recentDBFilePathsList objectAtIndex:index];
|
||||
NSString *recentItemFilePath = nil;
|
||||
|
||||
if (recentItem != nil)
|
||||
{
|
||||
NSNumber *compatibilityCheckNumber = (NSNumber *)[recentItem objectForKey:@"OptionIgnoreCompatibilityCheck"];
|
||||
if (compatibilityCheckNumber != nil)
|
||||
{
|
||||
[newWindowController setIsOptionWarningSilenced:YES];
|
||||
[newWindowController setIsCompatibilityCheckIgnored:[compatibilityCheckNumber boolValue]];
|
||||
[newWindowController setIsOptionWarningSilenced:NO];
|
||||
}
|
||||
|
||||
// Set up the window properties.
|
||||
NSString *windowFrameString = (NSString *)[recentItem objectForKey:@"WindowFrame"];
|
||||
if (windowFrameString != nil)
|
||||
{
|
||||
[[newWindowController window] setFrameFromString:windowFrameString];
|
||||
}
|
||||
|
||||
NSNumber *windowSplitViewDividerPositionNumber = (NSNumber *)[recentItem objectForKey:@"WindowSplitViewDividerPosition"];
|
||||
if (windowSplitViewDividerPositionNumber != nil)
|
||||
{
|
||||
CGFloat dividerPosition = [windowSplitViewDividerPositionNumber floatValue];
|
||||
[[newWindowController splitView] setPosition:dividerPosition ofDividerAtIndex:0];
|
||||
}
|
||||
|
||||
// Check for the file's existence at its path, and then handle appropriately.
|
||||
recentItemFilePath = (NSString *)[recentItem objectForKey:@"FilePath"];
|
||||
NSFileManager *fileManager = [[NSFileManager alloc] init];
|
||||
BOOL doesFileExist = [fileManager fileExistsAtPath:recentItemFilePath];
|
||||
[fileManager release];
|
||||
|
||||
if (!doesFileExist)
|
||||
{
|
||||
// If the file does not exist, then report the error to the user, and the remove the
|
||||
// nonexistent file from the recents menu.
|
||||
[newWindowController showErrorSheet:CheatSystemError_FileDoesNotExist];
|
||||
|
||||
NSMutableArray *newRecentsList = [NSMutableArray arrayWithCapacity:[recentDBFilePathsList count]];
|
||||
|
||||
for (NSDictionary *theItem in recentDBFilePathsList)
|
||||
{
|
||||
if (theItem != recentItem)
|
||||
{
|
||||
[newRecentsList addObject:theItem];
|
||||
}
|
||||
}
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setObject:newRecentsList forKey:@"CheatDatabase_RecentFilePath"];
|
||||
[self updateCheatDatabaseRecentsMenu:nil];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NSURL *dbFileURL = [NSURL fileURLWithPath:recentItemFilePath];
|
||||
[newWindowController loadFileStart:dbFileURL];
|
||||
}
|
||||
|
||||
- (IBAction) toggleExecutePause:(id)sender
|
||||
{
|
||||
[inputManager dispatchCommandUsingIBAction:_cmd sender:sender];
|
||||
|
@ -2029,6 +2133,93 @@
|
|||
return result;
|
||||
}
|
||||
|
||||
- (void) updateCheatDatabaseRecentsMenu:(NSNotification *)aNotification
|
||||
{
|
||||
NSArray *dbRecentsList = (NSArray *)[aNotification object];
|
||||
BOOL needReleaseObject = (dbRecentsList != nil);
|
||||
|
||||
if ( (dbRecentsList == nil) || ([dbRecentsList count] == 0) )
|
||||
{
|
||||
dbRecentsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
|
||||
}
|
||||
|
||||
NSMutableArray *newRecentsList = [NSMutableArray arrayWithArray:dbRecentsList];
|
||||
|
||||
// Note that we're relying on the notification object to retain this prior to
|
||||
// sending the notification.
|
||||
if (needReleaseObject)
|
||||
{
|
||||
[dbRecentsList release];
|
||||
}
|
||||
|
||||
NSString *legacyFilePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
|
||||
BOOL useLegacyFilePath = ( (legacyFilePath != nil) && ([legacyFilePath length] > 0) );
|
||||
|
||||
if (useLegacyFilePath)
|
||||
{
|
||||
// We need to check if the legacy file path also exists in the recents list.
|
||||
// If it does, then the recents list version takes priority.
|
||||
for (NSDictionary *dbRecentItem in dbRecentsList)
|
||||
{
|
||||
NSString *dbRecentItemFilePath = (NSString *)[dbRecentItem valueForKey:@"FilePath"];
|
||||
if ([dbRecentItemFilePath isEqualToString:legacyFilePath])
|
||||
{
|
||||
useLegacyFilePath = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useLegacyFilePath)
|
||||
{
|
||||
// The legacy file path must always be the first entry of the recents list.
|
||||
NSDictionary *legacyRecentItem = [NSDictionary dictionaryWithObjectsAndKeys:legacyFilePath, @"FilePath",
|
||||
[legacyFilePath lastPathComponent], @"FileName",
|
||||
nil];
|
||||
[newRecentsList insertObject:legacyRecentItem atIndex:0];
|
||||
|
||||
if ([newRecentsList count] == 1)
|
||||
{
|
||||
// If the legacy file path is the only item in the recents list, then we can write it
|
||||
// back to user defaults right now.
|
||||
[[NSUserDefaults standardUserDefaults] setObject:newRecentsList forKey:@"CheatDatabase_RecentFilePath"];
|
||||
}
|
||||
}
|
||||
|
||||
NSArray *recentsMenuItems = [cheatDatabaseRecentsMenu itemArray];
|
||||
for (NSMenuItem *menuItem in recentsMenuItems)
|
||||
{
|
||||
if ( [menuItem action] == @selector(openRecentCheatDatabase:) )
|
||||
{
|
||||
[cheatDatabaseRecentsMenu removeItem:menuItem];
|
||||
}
|
||||
}
|
||||
|
||||
if ([newRecentsList count] > 0)
|
||||
{
|
||||
if ( ![[cheatDatabaseRecentsMenu itemAtIndex:0] isSeparatorItem] )
|
||||
{
|
||||
[cheatDatabaseRecentsMenu insertItem:[NSMenuItem separatorItem] atIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
// Recent files are added in reverse order, in which least recent files appear below
|
||||
// more recent files in the menu. The most recent file should be at the top of the menu.
|
||||
for (NSDictionary *recentItem in newRecentsList)
|
||||
{
|
||||
NSString *menuNameString = [recentItem objectForKey:@"FileName"];
|
||||
if ( (menuNameString == nil) || ([menuNameString length] == 0) )
|
||||
{
|
||||
menuNameString = [recentItem objectForKey:@"FilePath"];
|
||||
}
|
||||
|
||||
NSMenuItem *newMenuItem = [[[NSMenuItem alloc] initWithTitle:menuNameString action:@selector(openRecentCheatDatabase:) keyEquivalent:@""] autorelease];
|
||||
[newMenuItem setTag:[newRecentsList indexOfObject:recentItem]];
|
||||
[newMenuItem setTarget:self];
|
||||
[cheatDatabaseRecentsMenu insertItem:newMenuItem atIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) handleNDSError:(NSNotification *)aNotification
|
||||
{
|
||||
[self setIsUserInterfaceBlockingExecution:YES];
|
||||
|
@ -2980,6 +3171,13 @@
|
|||
enable = NO;
|
||||
}
|
||||
}
|
||||
else if (theAction == @selector(clearCheatDatabaseRecents:))
|
||||
{
|
||||
if ([cheatDatabaseRecentsMenu numberOfItems] < 2)
|
||||
{
|
||||
enable = NO;
|
||||
}
|
||||
}
|
||||
else if (theAction == @selector(changeCoreSpeed:))
|
||||
{
|
||||
NSInteger speedScalar = (NSInteger)([cdsCore speedScalar] * 100.0);
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
NSObjectController *emuControlController;
|
||||
NSObjectController *prefWindowController;
|
||||
NSObjectController *cdsCoreController;
|
||||
NSObjectController *databaseFileController;
|
||||
NSArrayController *gameListController;
|
||||
FileMigrationDelegate *migrationDelegate;
|
||||
MacAVCaptureToolDelegate *avCaptureToolDelegate;
|
||||
WifiSettingsPanelDelegate *wifiSettingsPanelDelegate;
|
||||
|
@ -63,6 +65,8 @@
|
|||
@property (readonly) IBOutlet NSObjectController *emuControlController;
|
||||
@property (readonly) IBOutlet NSObjectController *prefWindowController;
|
||||
@property (readonly) IBOutlet NSObjectController *cdsCoreController;
|
||||
@property (readonly) IBOutlet NSObjectController *databaseFileController;
|
||||
@property (readonly) IBOutlet NSArrayController *gameListController;
|
||||
@property (readonly) IBOutlet FileMigrationDelegate *migrationDelegate;
|
||||
@property (readonly) IBOutlet MacAVCaptureToolDelegate *avCaptureToolDelegate;
|
||||
@property (readonly) IBOutlet WifiSettingsPanelDelegate *wifiSettingsPanelDelegate;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2011 Roger Manuel
|
||||
Copyright (C) 2011-2022 DeSmuME Team
|
||||
Copyright (C) 2011-2023 DeSmuME Team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -28,6 +28,7 @@
|
|||
#import "inputPrefsView.h"
|
||||
|
||||
#import "cocoa_core.h"
|
||||
#import "cocoa_cheat.h"
|
||||
#import "cocoa_GPU.h"
|
||||
#import "cocoa_file.h"
|
||||
#import "cocoa_firmware.h"
|
||||
|
@ -50,6 +51,8 @@
|
|||
@synthesize emuControlController;
|
||||
@synthesize prefWindowController;
|
||||
@synthesize cdsCoreController;
|
||||
@synthesize databaseFileController;
|
||||
@synthesize gameListController;
|
||||
@synthesize avCaptureToolDelegate;
|
||||
@synthesize wifiSettingsPanelDelegate;
|
||||
@synthesize migrationDelegate;
|
||||
|
@ -312,6 +315,7 @@
|
|||
// Bring the application to the front
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
[emuControl restoreDisplayWindowStates];
|
||||
[emuControl updateCheatDatabaseRecentsMenu:nil];
|
||||
|
||||
// Load a new ROM on launch per user preferences.
|
||||
if ([[NSUserDefaults standardUserDefaults] objectForKey:@"General_AutoloadROMOnLaunch"] != nil)
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
NSTableView *cheatSearchListTable;
|
||||
NSArrayController *cheatListController;
|
||||
NSArrayController *cheatSearchListController;
|
||||
NSArrayController *cheatDatabaseController;
|
||||
NSObjectController *cheatWindowController;
|
||||
NSObjectController *cheatSelectedItemController;
|
||||
|
||||
|
@ -54,13 +53,14 @@
|
|||
|
||||
NSSearchField *searchField;
|
||||
|
||||
NSWindow *cheatDatabaseSheet;
|
||||
|
||||
NSFont *codeEditorFont;
|
||||
|
||||
NSMutableDictionary *bindings;
|
||||
CocoaDSCheatItem *workingCheat;
|
||||
CocoaDSCheatManager *cdsCheats;
|
||||
|
||||
NSString *currentGameCode;
|
||||
NSInteger currentGameCRC;
|
||||
}
|
||||
|
||||
@property (assign) IBOutlet NSObject *dummyObject;
|
||||
|
@ -71,7 +71,6 @@
|
|||
@property (readonly) IBOutlet NSTableView *cheatSearchListTable;
|
||||
@property (readonly) IBOutlet NSArrayController *cheatListController;
|
||||
@property (readonly) IBOutlet NSArrayController *cheatSearchListController;
|
||||
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
|
||||
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
|
||||
@property (readonly) IBOutlet NSObjectController *cheatSelectedItemController;
|
||||
|
||||
|
@ -87,19 +86,23 @@
|
|||
|
||||
@property (readonly) IBOutlet NSSearchField *searchField;
|
||||
|
||||
@property (readonly) IBOutlet NSWindow *cheatDatabaseSheet;
|
||||
|
||||
@property (assign) NSFont *codeEditorFont;
|
||||
@property (readonly) NSMutableDictionary *bindings;
|
||||
@property (retain) CocoaDSCheatItem *workingCheat;
|
||||
@property (retain) CocoaDSCheatManager *cdsCheats;
|
||||
@property (retain) NSString *currentGameCode;
|
||||
@property (assign) NSInteger currentGameCRC;
|
||||
|
||||
- (BOOL) cheatSystemStart:(CocoaDSCheatManager *)theManager;
|
||||
- (void) cheatSystemEnd;
|
||||
|
||||
- (IBAction) addToList:(id)sender;
|
||||
- (IBAction) removeFromList:(id)sender;
|
||||
- (IBAction) viewDatabase:(id)sender;
|
||||
|
||||
- (IBAction) enableAllInList:(id)sender;
|
||||
- (IBAction) disableAllInList:(id)sender;
|
||||
- (IBAction) removeAllFromList:(id)sender;
|
||||
|
||||
- (IBAction) setInternalCheatValue:(id)sender;
|
||||
- (IBAction) applyConfiguration:(id)sender;
|
||||
- (IBAction) selectCheatType:(id)sender;
|
||||
|
@ -112,11 +115,4 @@
|
|||
- (void) setCheatConfigViewByType:(NSInteger)cheatTypeID;
|
||||
- (void) setCheatSearchViewByStyle:(NSInteger)searchStyleID;
|
||||
|
||||
- (void) databaseLoadFromFile:(NSURL *)fileURL;
|
||||
- (void) addSelectedFromCheatDatabase;
|
||||
- (IBAction) selectAllCheatsInDatabase:(id)sender;
|
||||
- (IBAction) selectNoneCheatsInDatabase:(id)sender;
|
||||
- (IBAction) closeCheatDatabaseSheet:(id)sender;
|
||||
- (void) didEndCheatDatabaseSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
|
||||
|
||||
@end
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#import "cheatWindowDelegate.h"
|
||||
#import "CheatDatabaseWindowController.h"
|
||||
|
||||
#import "cocoa_globals.h"
|
||||
#import "cocoa_cheat.h"
|
||||
|
@ -33,7 +34,6 @@
|
|||
@synthesize cheatSearchListTable;
|
||||
@synthesize cheatListController;
|
||||
@synthesize cheatSearchListController;
|
||||
@synthesize cheatDatabaseController;
|
||||
@synthesize cheatWindowController;
|
||||
@synthesize cheatSelectedItemController;
|
||||
|
||||
|
@ -48,12 +48,12 @@
|
|||
|
||||
@synthesize searchField;
|
||||
|
||||
@synthesize cheatDatabaseSheet;
|
||||
|
||||
@synthesize codeEditorFont;
|
||||
@synthesize bindings;
|
||||
@synthesize cdsCheats;
|
||||
@synthesize workingCheat;
|
||||
@synthesize currentGameCode;
|
||||
@synthesize currentGameCRC;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
|
@ -71,24 +71,26 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
currentGameCode = nil;
|
||||
currentGameCRC = 0;
|
||||
workingCheat = nil;
|
||||
currentView = nil;
|
||||
currentSearchStyleView = nil;
|
||||
codeEditorFont = [NSFont fontWithName:@"Monaco" size:13.0];
|
||||
|
||||
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasSelection"];
|
||||
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasItems"];
|
||||
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isRunningSearch"];
|
||||
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isSearchStarted"];
|
||||
[bindings setValue:[NSNumber numberWithInteger:CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE] forKey:@"cheatSearchStyle"];
|
||||
[bindings setValue:[NSNumber numberWithInteger:CheatSearchStyle_ExactValue] forKey:@"cheatSearchStyle"];
|
||||
[bindings setValue:[NSNumber numberWithInteger:CHEATSEARCH_UNSIGNED] forKey:@"cheatSearchSignType"];
|
||||
[bindings setValue:@"Search not started." forKey:@"cheatSearchAddressCount"];
|
||||
|
||||
if ([CocoaDSCheatItem iconInternalCheat] == nil || [CocoaDSCheatItem iconActionReplay] == nil || [CocoaDSCheatItem iconCodeBreaker] == nil)
|
||||
if ([CocoaDSCheatItem iconDirectory] == nil || [CocoaDSCheatItem iconInternalCheat] == nil || [CocoaDSCheatItem iconActionReplay] == nil || [CocoaDSCheatItem iconCodeBreaker] == nil)
|
||||
{
|
||||
[CocoaDSCheatItem setIconInternalCheat:[NSImage imageNamed:@"NSApplicationIcon"]];
|
||||
[CocoaDSCheatItem setIconActionReplay:[NSImage imageNamed:@"Icon_ActionReplay_128x128"]];
|
||||
[CocoaDSCheatItem setIconCodeBreaker:[NSImage imageNamed:@"Icon_CodeBreaker_128x128"]];
|
||||
[CocoaDSCheatItem setIconDirectory:[[NSImage imageNamed:@"NSFolder"] retain]];
|
||||
[CocoaDSCheatItem setIconInternalCheat:[[NSImage imageNamed:@"NSApplicationIcon"] retain]];
|
||||
[CocoaDSCheatItem setIconActionReplay:[[NSImage imageNamed:@"Icon_ActionReplay_128x128"] retain]];
|
||||
[CocoaDSCheatItem setIconCodeBreaker:[[NSImage imageNamed:@"Icon_CodeBreaker_128x128"] retain]];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -98,6 +100,7 @@
|
|||
{
|
||||
[self setWorkingCheat:nil];
|
||||
[self setCdsCheats:nil];
|
||||
[self setCurrentGameCode:nil];
|
||||
[bindings release];
|
||||
|
||||
[super dealloc];
|
||||
|
@ -113,19 +116,13 @@
|
|||
}
|
||||
|
||||
[self setCdsCheats:cheatManager];
|
||||
[self setCurrentGameCode:[cheatManager currentGameCode]];
|
||||
[self setCurrentGameCRC:[cheatManager currentGameCRC]];
|
||||
[cheatManager loadFromMaster];
|
||||
[cheatListController setContent:[cheatManager sessionList]];
|
||||
|
||||
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
|
||||
[cheatWindowBindings setValue:self forKey:@"cheatWindowDelegateKey"];
|
||||
|
||||
NSString *dbFilePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
|
||||
if (dbFilePath != nil)
|
||||
{
|
||||
[self databaseLoadFromFile:[NSURL fileURLWithPath:dbFilePath]];
|
||||
}
|
||||
|
||||
[self setCheatSearchViewByStyle:CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE];
|
||||
[self setCheatSearchViewByStyle:CheatSearchStyle_ExactValue];
|
||||
[CheatDatabaseWindowController setCurrentGameForAllWindowsSerial:[cheatManager currentGameCode] crc:[cheatManager currentGameCRC]];
|
||||
|
||||
didStartSuccessfully = YES;
|
||||
return didStartSuccessfully;
|
||||
|
@ -139,16 +136,13 @@
|
|||
[cheatManager save];
|
||||
}
|
||||
|
||||
[cheatDatabaseController setContent:nil];
|
||||
[cheatListController setContent:nil];
|
||||
[self resetSearch:nil];
|
||||
[self setCurrentGameCode:nil];
|
||||
[self setCurrentGameCRC:0];
|
||||
[self setCdsCheats:nil];
|
||||
|
||||
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
|
||||
[cheatWindowBindings setValue:@"No ROM loaded." forKey:@"cheatDBTitle"];
|
||||
[cheatWindowBindings setValue:@"No ROM loaded." forKey:@"cheatDBDate"];
|
||||
[cheatWindowBindings setValue:@"---" forKey:@"cheatDBItemCount"];
|
||||
[cheatWindowBindings setValue:nil forKey:@"cheatWindowDelegateKey"];
|
||||
[CheatDatabaseWindowController setCurrentGameForAllWindowsSerial:nil crc:0];
|
||||
}
|
||||
|
||||
- (IBAction) addToList:(id)sender
|
||||
|
@ -162,7 +156,6 @@
|
|||
if (newCheatItem != nil)
|
||||
{
|
||||
[cheatListController setContent:[[self cdsCheats] sessionList]];
|
||||
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"hasItems"];
|
||||
[[self cdsCheats] save];
|
||||
}
|
||||
}
|
||||
|
@ -202,31 +195,59 @@
|
|||
|
||||
[cheatListTable selectRowIndexes:indexSet byExtendingSelection:NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasItems"];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction) viewDatabase:(id)sender
|
||||
- (IBAction) enableAllInList:(id)sender
|
||||
{
|
||||
#if defined(MAC_OS_X_VERSION_10_9) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9)
|
||||
if ([window respondsToSelector:@selector(beginSheet:completionHandler:)])
|
||||
NSArray *cheatListArray = [cheatListController content];
|
||||
if (cheatListArray == nil)
|
||||
{
|
||||
[window beginSheet:cheatDatabaseSheet
|
||||
completionHandler:^(NSModalResponse response) {
|
||||
[self didEndCheatDatabaseSheet:nil returnCode:response contextInfo:nil];
|
||||
} ];
|
||||
return;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
for (CocoaDSCheatItem *cheatItem in cheatListArray)
|
||||
{
|
||||
SILENCE_DEPRECATION_MACOS_10_10( [NSApp beginSheet:cheatDatabaseSheet
|
||||
modalForWindow:window
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(didEndCheatDatabaseSheet:returnCode:contextInfo:)
|
||||
contextInfo:nil] );
|
||||
[cheatItem setEnabled:YES];
|
||||
}
|
||||
|
||||
[[self cdsCheats] save];
|
||||
}
|
||||
|
||||
- (IBAction) disableAllInList:(id)sender
|
||||
{
|
||||
NSArray *cheatListArray = [cheatListController content];
|
||||
if (cheatListArray == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (CocoaDSCheatItem *cheatItem in cheatListArray)
|
||||
{
|
||||
[cheatItem setEnabled:NO];
|
||||
}
|
||||
|
||||
[[self cdsCheats] save];
|
||||
}
|
||||
|
||||
- (IBAction) removeAllFromList:(id)sender
|
||||
{
|
||||
CocoaDSCheatManager *cheatManager = [self cdsCheats];
|
||||
if (cheatManager == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[cheatListTable deselectAll:sender];
|
||||
|
||||
NSUInteger itemCount = [[cheatManager sessionList] count];
|
||||
|
||||
for (NSUInteger i = 0; i < itemCount; i++)
|
||||
{
|
||||
[cheatManager removeAtIndex:0];
|
||||
}
|
||||
|
||||
[cheatListController setContent:[cheatManager sessionList]];
|
||||
[cheatManager save];
|
||||
}
|
||||
|
||||
- (IBAction) setInternalCheatValue:(id)sender
|
||||
|
@ -316,9 +337,9 @@
|
|||
[cheatSearchListController setContent:[[self cdsCheats] searchResultsList]];
|
||||
|
||||
NSInteger searchStyle = [(NSNumber *)[bindings valueForKey:@"cheatSearchStyle"] integerValue];
|
||||
if (searchStyle == CHEATSEARCH_SEARCHSTYLE_COMPARATIVE)
|
||||
if (searchStyle == CheatSearchStyle_Comparative)
|
||||
{
|
||||
[self setCheatSearchViewByStyle:CHEATSEARCH_SEARCHSTYLE_COMPARATIVE];
|
||||
[self setCheatSearchViewByStyle:CheatSearchStyle_Comparative];
|
||||
}
|
||||
|
||||
if (!wasSearchAlreadyStarted)
|
||||
|
@ -354,15 +375,15 @@
|
|||
|
||||
switch (cheatTypeID)
|
||||
{
|
||||
case CHEAT_TYPE_INTERNAL:
|
||||
case CheatType_Internal:
|
||||
newView = viewConfigureInternalCheat;
|
||||
break;
|
||||
|
||||
case CHEAT_TYPE_ACTION_REPLAY:
|
||||
case CheatType_ActionReplay:
|
||||
newView = viewConfigureActionReplayCheat;
|
||||
break;
|
||||
|
||||
case CHEAT_TYPE_CODE_BREAKER:
|
||||
case CheatType_CodeBreaker:
|
||||
newView = viewConfigureCodeBreakerCheat;
|
||||
break;
|
||||
|
||||
|
@ -391,11 +412,11 @@
|
|||
|
||||
switch (searchStyleID)
|
||||
{
|
||||
case CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE:
|
||||
case CheatSearchStyle_ExactValue:
|
||||
newView = viewSearchExactValue;
|
||||
break;
|
||||
|
||||
case CHEATSEARCH_SEARCHSTYLE_COMPARATIVE:
|
||||
case CheatSearchStyle_Comparative:
|
||||
if ([cdsCheats searchDidStart] == 0)
|
||||
{
|
||||
newView = viewSearchComparativeStart;
|
||||
|
@ -420,136 +441,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) databaseLoadFromFile:(NSURL *)fileURL
|
||||
{
|
||||
CocoaDSCheatManager *cheatManager = [self cdsCheats];
|
||||
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
|
||||
|
||||
if ( (fileURL == nil) || (cheatManager == nil) || (cheatWindowBindings == nil) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSInteger error = 0;
|
||||
NSMutableArray *dbList = [cheatManager databaseListLoadFromFile:fileURL errorCode:&error];
|
||||
if (dbList != nil)
|
||||
{
|
||||
[cheatDatabaseController setContent:dbList];
|
||||
|
||||
NSString *titleString = [cheatManager databaseTitle];
|
||||
NSString *dateString = [cheatManager databaseDate];
|
||||
|
||||
[cheatWindowBindings setValue:titleString forKey:@"cheatDBTitle"];
|
||||
[cheatWindowBindings setValue:dateString forKey:@"cheatDBDate"];
|
||||
[cheatWindowBindings setValue:[NSString stringWithFormat:@"%ld", (unsigned long)[dbList count]] forKey:@"cheatDBItemCount"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[cheatWindowBindings setValue:@"---" forKey:@"cheatDBItemCount"];
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case CHEATEXPORT_ERROR_FILE_NOT_FOUND:
|
||||
NSLog(@"R4 Cheat Database read failed! Could not load the database file!");
|
||||
[cheatWindowBindings setValue:@"Database not loaded." forKey:@"cheatDBTitle"];
|
||||
[cheatWindowBindings setValue:@"CANNOT LOAD FILE" forKey:@"cheatDBDate"];
|
||||
break;
|
||||
|
||||
case CHEATEXPORT_ERROR_WRONG_FILE_FORMAT:
|
||||
NSLog(@"R4 Cheat Database read failed! Wrong file format!");
|
||||
[cheatWindowBindings setValue:@"Database load error." forKey:@"cheatDBTitle"];
|
||||
[cheatWindowBindings setValue:@"FAILED TO LOAD FILE" forKey:@"cheatDBDate"];
|
||||
break;
|
||||
|
||||
case CHEATEXPORT_ERROR_SERIAL_NOT_FOUND:
|
||||
NSLog(@"R4 Cheat Database read failed! Could not find the serial number for this game in the database!");
|
||||
[cheatWindowBindings setValue:@"ROM not found in database." forKey:@"cheatDBTitle"];
|
||||
[cheatWindowBindings setValue:@"ROM not found." forKey:@"cheatDBDate"];
|
||||
break;
|
||||
|
||||
case CHEATEXPORT_ERROR_EXPORT_FAILED:
|
||||
NSLog(@"R4 Cheat Database read failed! Could not read the database file!");
|
||||
[cheatWindowBindings setValue:@"Database read error." forKey:@"cheatDBTitle"];
|
||||
[cheatWindowBindings setValue:@"CANNOT READ FILE" forKey:@"cheatDBDate"];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) addSelectedFromCheatDatabase
|
||||
{
|
||||
CocoaDSCheatManager *cheatManager = [self cdsCheats];
|
||||
if (cheatManager == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const NSInteger addedItemCount = [cheatManager databaseAddSelected];
|
||||
if (addedItemCount > 0)
|
||||
{
|
||||
[cheatListController setContent:[[self cdsCheats] sessionList]];
|
||||
[[self cdsCheats] save];
|
||||
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"hasItems"];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction) selectAllCheatsInDatabase:(id)sender
|
||||
{
|
||||
NSMutableArray *dbList = [cheatDatabaseController content];
|
||||
if (dbList == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (CocoaDSCheatItem *cheatItem in dbList)
|
||||
{
|
||||
[cheatItem setWillAdd:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction) selectNoneCheatsInDatabase:(id)sender
|
||||
{
|
||||
NSMutableArray *dbList = [cheatDatabaseController content];
|
||||
if (dbList == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (CocoaDSCheatItem *cheatItem in dbList)
|
||||
{
|
||||
[cheatItem setWillAdd:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction) closeCheatDatabaseSheet:(id)sender
|
||||
{
|
||||
NSWindow *sheet = [(NSControl *)sender window];
|
||||
const NSInteger code = [(NSControl *)sender tag];
|
||||
|
||||
[CocoaDSUtil endSheet:sheet returnCode:code];
|
||||
}
|
||||
|
||||
- (void) didEndCheatDatabaseSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[sheet orderOut:self];
|
||||
|
||||
switch (returnCode)
|
||||
{
|
||||
case GUI_RESPONSE_CANCEL:
|
||||
return;
|
||||
|
||||
case GUI_RESPONSE_OK:
|
||||
[self addSelectedFromCheatDatabase];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeKey:(NSNotification *)notification
|
||||
{
|
||||
[cheatWindowController setContent:bindings];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2011 Roger Manuel
|
||||
Copyright (C) 2012-2022 DeSmuME Team
|
||||
Copyright (C) 2012-2023 DeSmuME Team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -55,7 +55,6 @@ class OGLImage;
|
|||
NSObjectController *emuController;
|
||||
NSObjectController *prefWindowController;
|
||||
NSObjectController *cheatWindowController;
|
||||
NSArrayController *cheatDatabaseController;
|
||||
|
||||
NSToolbarItem *toolbarItemGeneral;
|
||||
NSToolbarItem *toolbarItemInput;
|
||||
|
@ -105,7 +104,6 @@ class OGLImage;
|
|||
@property (readonly) IBOutlet NSObjectController *emuController;
|
||||
@property (readonly) IBOutlet NSObjectController *prefWindowController;
|
||||
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
|
||||
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
|
||||
@property (readonly) IBOutlet NSToolbarItem *toolbarItemGeneral;
|
||||
@property (readonly) IBOutlet NSToolbarItem *toolbarItemInput;
|
||||
@property (readonly) IBOutlet NSToolbarItem *toolbarItemDisplay;
|
||||
|
@ -139,8 +137,6 @@ class OGLImage;
|
|||
- (void) chooseAdvansceneDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
|
||||
- (IBAction) chooseRomForAutoload:(id)sender;
|
||||
- (void) chooseRomForAutoloadDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
|
||||
- (IBAction) chooseCheatDatabase:(id)sender;
|
||||
- (void) chooseCheatDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
|
||||
|
||||
- (IBAction) selectDisplayRotation:(id)sender;
|
||||
- (void) updateDisplayRotationMenu:(double)displayRotation;
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
#pragma mark -
|
||||
@implementation DisplayPreviewView
|
||||
|
||||
@dynamic filtersPreferGPU;
|
||||
|
@ -294,7 +293,6 @@
|
|||
@synthesize emuController;
|
||||
@synthesize prefWindowController;
|
||||
@synthesize cheatWindowController;
|
||||
@synthesize cheatDatabaseController;
|
||||
|
||||
@synthesize toolbarItemGeneral;
|
||||
@synthesize toolbarItemInput;
|
||||
|
@ -525,70 +523,6 @@
|
|||
[bindings setValue:[selectedFile lastPathComponent] forKey:@"AdvansceneDatabaseName"];
|
||||
}
|
||||
|
||||
- (IBAction) chooseCheatDatabase:(id)sender
|
||||
{
|
||||
NSOpenPanel *panel = [NSOpenPanel openPanel];
|
||||
[panel setCanChooseDirectories:NO];
|
||||
[panel setCanChooseFiles:YES];
|
||||
[panel setResolvesAliases:YES];
|
||||
[panel setAllowsMultipleSelection:NO];
|
||||
[panel setTitle:NSSTRING_TITLE_SELECT_R4_CHEAT_DB_PANEL];
|
||||
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_R4_CHEAT_DB, nil];
|
||||
|
||||
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
|
||||
// is deprecated in Mac OS X v10.6.
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
|
||||
if (IsOSXVersionSupported(10, 6, 0))
|
||||
{
|
||||
[panel setAllowedFileTypes:fileTypes];
|
||||
[panel beginSheetModalForWindow:window
|
||||
completionHandler:^(NSInteger result) {
|
||||
[self chooseCheatDatabaseDidEnd:panel returnCode:(int)result contextInfo:nil];
|
||||
} ];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SILENCE_DEPRECATION_MACOS_10_6( [panel beginSheetForDirectory:nil
|
||||
file:nil
|
||||
types:fileTypes
|
||||
modalForWindow:window
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(chooseCheatDatabaseDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil] );
|
||||
}
|
||||
}
|
||||
|
||||
- (void) chooseCheatDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[sheet orderOut:self];
|
||||
|
||||
if (returnCode == GUI_RESPONSE_CANCEL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
|
||||
if(selectedFileURL == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *selectedFile = [selectedFileURL path];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setObject:selectedFile forKey:@"R4Cheat_DatabasePath"];
|
||||
[bindings setValue:[selectedFile lastPathComponent] forKey:@"R4CheatDatabaseName"];
|
||||
|
||||
const BOOL isRomLoaded = [(EmuControllerDelegate *)[emuController content] currentRom] != nil;
|
||||
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
|
||||
CheatWindowDelegate *cheatWindowDelegate = (CheatWindowDelegate *)[cheatWindowBindings valueForKey:@"cheatWindowDelegateKey"];
|
||||
|
||||
if ( (isRomLoaded == YES) && (cheatWindowDelegate != nil) )
|
||||
{
|
||||
[cheatWindowDelegate databaseLoadFromFile:selectedFileURL];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction) selectDisplayRotation:(id)sender
|
||||
{
|
||||
const NSInteger displayRotation = [(NSMenuItem *)sender tag];
|
||||
|
@ -1078,12 +1012,6 @@
|
|||
[bindings setValue:[advansceneDatabasePath lastPathComponent] forKey:@"AdvansceneDatabaseName"];
|
||||
}
|
||||
|
||||
NSString *cheatDatabasePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
|
||||
if (cheatDatabasePath != nil)
|
||||
{
|
||||
[bindings setValue:[cheatDatabasePath lastPathComponent] forKey:@"R4CheatDatabaseName"];
|
||||
}
|
||||
|
||||
NSString *autoloadRomPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"General_AutoloadROMSelectedPath"];
|
||||
if (autoloadRomPath != nil)
|
||||
{
|
||||
|
|
|
@ -109,7 +109,7 @@ libdesmume_src += [
|
|||
'../../utils/tinyxml/tinyxmlerror.cpp',
|
||||
'../../utils/tinyxml/tinyxmlparser.cpp',
|
||||
'../../utils/colorspacehandler/colorspacehandler.cpp',
|
||||
'../../addons/slot2_auto.cpp', '../../addons/slot2_mpcf.cpp', '../../addons/slot2_paddle.cpp', '../../addons/slot2_gbagame.cpp', '../../addons/slot2_none.cpp', '../../addons/slot2_rumblepak.cpp', '../../addons/slot2_guitarGrip.cpp', '../../addons/slot2_expMemory.cpp', '../../addons/slot2_piano.cpp', '../../addons/slot2_passme.cpp', '../../addons/slot1_none.cpp', '../../addons/slot1_r4.cpp', '../../addons/slot1_retail_nand.cpp', '../../addons/slot1_retail_auto.cpp', '../../addons/slot1_retail_mcrom.cpp', '../../addons/slot1_retail_mcrom_debug.cpp', '../../addons/slot1comp_mc.cpp', '../../addons/slot1comp_rom.cpp', '../../addons/slot1comp_protocol.cpp',
|
||||
'../../addons/slot2_auto.cpp', '../../addons/slot2_mpcf.cpp', '../../addons/slot2_paddle.cpp', '../../addons/slot2_gbagame.cpp', '../../addons/slot2_none.cpp', '../../addons/slot2_rumblepak.cpp', '../../addons/slot2_guitarGrip.cpp', '../../addons/slot2_hcv1000.cpp', '../../addons/slot2_expMemory.cpp', '../../addons/slot2_piano.cpp', '../../addons/slot2_passme.cpp', '../../addons/slot1_none.cpp', '../../addons/slot1_r4.cpp', '../../addons/slot1_retail_nand.cpp', '../../addons/slot1_retail_auto.cpp', '../../addons/slot1_retail_mcrom.cpp', '../../addons/slot1_retail_mcrom_debug.cpp', '../../addons/slot1comp_mc.cpp', '../../addons/slot1comp_rom.cpp', '../../addons/slot1comp_protocol.cpp',
|
||||
'../../cheatSystem.cpp',
|
||||
'../../texcache.cpp', '../../rasterize.cpp',
|
||||
'../../metaspu/metaspu.cpp',
|
||||
|
|
|
@ -268,6 +268,7 @@
|
|||
<ClCompile Include="..\..\..\addons\slot2_expMemory.cpp" />
|
||||
<ClCompile Include="..\..\..\addons\slot2_gbagame.cpp" />
|
||||
<ClCompile Include="..\..\..\addons\slot2_guitarGrip.cpp" />
|
||||
<ClCompile Include="..\..\..\addons\slot2_hcv1000.cpp" />
|
||||
<ClCompile Include="..\..\..\addons\slot2_none.cpp" />
|
||||
<ClCompile Include="..\..\..\addons\slot2_rumblepak.cpp" />
|
||||
<ClCompile Include="..\..\..\utils\guid.cpp" />
|
||||
|
|
|
@ -132,6 +132,9 @@
|
|||
<ClCompile Include="..\..\..\addons\slot2_guitarGrip.cpp">
|
||||
<Filter>addons</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\addons\slot2_hcv1000.cpp">
|
||||
<Filter>addons</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\addons\slot2_none.cpp">
|
||||
<Filter>addons</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -1370,6 +1370,17 @@ AGG2D_TEMPLATE void TAGG2D::text(double x, double y, const wchar_t* str, unsigne
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
AGG2D_TEMPLATE double TAGG2D::textWidth(const char* str)
|
||||
{
|
||||
return textWidth(str, (unsigned int)strlen(str));
|
||||
}
|
||||
|
||||
AGG2D_TEMPLATE void TAGG2D::text(double x, double y, const char* str, bool roundOff, double dx, double dy)
|
||||
{
|
||||
text(x, y, str, (unsigned int)strlen(str), roundOff, dx, dy);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -1945,11 +1956,11 @@ AGG2D_TEMPLATE void TAGG2D::render(FontRasterizer& ras, FontScanline& sl)
|
|||
{
|
||||
if(m_blendMode == BlendAlpha)
|
||||
{
|
||||
Agg2DRenderer::render(*this, m_renBase, m_renSolid, ras, sl);
|
||||
Agg2DRenderer<PixFormatSet, PixFormatSet>::render(*this, m_renBase, m_renSolid, ras, sl);
|
||||
}
|
||||
else
|
||||
{
|
||||
Agg2DRenderer::render(*this, m_renBaseComp, m_renSolidComp, ras, sl);
|
||||
Agg2DRenderer<PixFormatSet, PixFormatSet>::render(*this, m_renBaseComp, m_renSolidComp, ras, sl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,13 +50,23 @@ static s64 hudTimer;
|
|||
|
||||
static void SetHudDummy (HudCoordinates *hud)
|
||||
{
|
||||
hud->x=666;
|
||||
hud->y=666;
|
||||
hud->x=-666;
|
||||
hud->y=-666;
|
||||
}
|
||||
|
||||
static bool IsHudDummy (HudCoordinates *hud)
|
||||
{
|
||||
return (hud->x == 666 && hud->y == 666);
|
||||
return (hud->x == -666 && hud->y == -666);
|
||||
}
|
||||
|
||||
static int ScreenWidth()
|
||||
{
|
||||
return 256*osd->scale;
|
||||
}
|
||||
|
||||
static int ScreenHeight()
|
||||
{
|
||||
return 192*osd->scale;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -64,21 +74,47 @@ static T calcY(T y) // alters a GUI element y coordinate as necessary to obey sw
|
|||
{
|
||||
if(osd->singleScreen)
|
||||
{
|
||||
if(y >= 192)
|
||||
y -= 192;
|
||||
if(y >= ScreenHeight())
|
||||
y -= ScreenHeight();
|
||||
if(osd->swapScreens)
|
||||
y += 192;
|
||||
y += ScreenHeight();
|
||||
}
|
||||
else if(osd->swapScreens)
|
||||
{
|
||||
if(y >= 192)
|
||||
y -= 192;
|
||||
if(y >= ScreenHeight())
|
||||
y -= ScreenHeight();
|
||||
else
|
||||
y += 192;
|
||||
y += ScreenHeight();
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
static void RenderTextAutoVector(double x, double y, const std::string& str, bool shadow = true, double shadowOffset = 1.0)
|
||||
{
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
bool render_vect = false;
|
||||
if(osd)
|
||||
if(osd->useVectorFonts)
|
||||
render_vect = true;
|
||||
if(render_vect)
|
||||
{
|
||||
if(shadow)
|
||||
aggDraw.hud->renderVectorFontTextDropshadowed(x, y, str, shadowOffset);
|
||||
else
|
||||
aggDraw.hud->renderVectorFontText(x, y, str);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
if(shadow)
|
||||
aggDraw.hud->renderTextDropshadowed(x, y, str);
|
||||
else
|
||||
aggDraw.hud->renderText(x, y, str);
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void EditHud(s32 x, s32 y, HudStruct *hudstruct) {
|
||||
|
||||
u32 i = 0;
|
||||
|
@ -108,8 +144,10 @@ void EditHud(s32 x, s32 y, HudStruct *hudstruct) {
|
|||
//sanity checks
|
||||
if(hud.x < 0) hud.x = 0;
|
||||
if(hud.y < 0) hud.y = 0;
|
||||
if(hud.x > 245)hud.x = 245; //margins
|
||||
if(hud.y > 384-16)hud.y = 384-16;
|
||||
if(hud.x > ScreenWidth()-11*osd->scale)
|
||||
hud.x = ScreenWidth()-11*osd->scale; //margins
|
||||
if(hud.y > ScreenHeight()*2-16*osd->scale)
|
||||
hud.y = ScreenHeight()*2-16*osd->scale;
|
||||
|
||||
if(hud.clicked)
|
||||
{
|
||||
|
@ -136,45 +174,47 @@ void HudClickRelease(HudStruct *hudstruct) {
|
|||
|
||||
void HudStruct::reset()
|
||||
{
|
||||
double sc=(osd ? osd->scale : 1.0);
|
||||
|
||||
FpsDisplay.x=0;
|
||||
FpsDisplay.y=5;
|
||||
FpsDisplay.xsize=166;
|
||||
FpsDisplay.ysize=10;
|
||||
FpsDisplay.y=5*sc;
|
||||
FpsDisplay.xsize=166*sc;
|
||||
FpsDisplay.ysize=10*sc;
|
||||
|
||||
FrameCounter.x=0;
|
||||
FrameCounter.y=25;
|
||||
FrameCounter.xsize=60;
|
||||
FrameCounter.ysize=10;
|
||||
FrameCounter.y=25*sc;
|
||||
FrameCounter.xsize=60*sc;
|
||||
FrameCounter.ysize=10*sc;
|
||||
|
||||
InputDisplay.x=0;
|
||||
InputDisplay.y=45;
|
||||
InputDisplay.xsize=220;
|
||||
InputDisplay.ysize=10;
|
||||
InputDisplay.y=45*sc;
|
||||
InputDisplay.xsize=220*sc;
|
||||
InputDisplay.ysize=10*sc;
|
||||
|
||||
GraphicalInputDisplay.x=8;
|
||||
GraphicalInputDisplay.y=328;
|
||||
GraphicalInputDisplay.xsize=102;
|
||||
GraphicalInputDisplay.ysize=50;
|
||||
GraphicalInputDisplay.x=8*sc;
|
||||
GraphicalInputDisplay.y=328*sc;
|
||||
GraphicalInputDisplay.xsize=102*sc;
|
||||
GraphicalInputDisplay.ysize=50*sc;
|
||||
|
||||
LagFrameCounter.x=0;
|
||||
LagFrameCounter.y=65;
|
||||
LagFrameCounter.xsize=30;
|
||||
LagFrameCounter.ysize=10;
|
||||
LagFrameCounter.y=65*sc;
|
||||
LagFrameCounter.xsize=30*sc;
|
||||
LagFrameCounter.ysize=10*sc;
|
||||
|
||||
Microphone.x=0;
|
||||
Microphone.y=85;
|
||||
Microphone.xsize=20;
|
||||
Microphone.ysize=10;
|
||||
Microphone.y=85*sc;
|
||||
Microphone.xsize=20*sc;
|
||||
Microphone.ysize=10*sc;
|
||||
|
||||
RTCDisplay.x=0;
|
||||
RTCDisplay.y=105;
|
||||
RTCDisplay.xsize=220;
|
||||
RTCDisplay.ysize=10;
|
||||
RTCDisplay.y=105*sc;
|
||||
RTCDisplay.xsize=220*sc;
|
||||
RTCDisplay.ysize=10*sc;
|
||||
|
||||
SavestateSlots.x = 8;
|
||||
SavestateSlots.y = 160;
|
||||
SavestateSlots.xsize = 240;
|
||||
SavestateSlots.ysize = 24;
|
||||
SavestateSlots.x = 8*sc;
|
||||
SavestateSlots.y = 160*sc;
|
||||
SavestateSlots.xsize = 240*sc;
|
||||
SavestateSlots.ysize = 24*sc;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define AGG_OSD_SETTING(which,comp) which.comp = GetPrivateProfileInt("HudEdit", #which "." #comp, which.comp, IniName);
|
||||
|
@ -186,6 +226,51 @@ void HudStruct::reset()
|
|||
clicked = false;
|
||||
}
|
||||
|
||||
void HudStruct::rescale(double oldScale, double newScale)
|
||||
{
|
||||
double sc=newScale/oldScale;
|
||||
|
||||
FpsDisplay.x*=sc;
|
||||
FpsDisplay.y*=sc;
|
||||
FpsDisplay.xsize*=sc;
|
||||
FpsDisplay.ysize*=sc;
|
||||
|
||||
FrameCounter.x*=sc;
|
||||
FrameCounter.y*=sc;
|
||||
FrameCounter.xsize*=sc;
|
||||
FrameCounter.ysize*=sc;
|
||||
|
||||
InputDisplay.x*=sc;
|
||||
InputDisplay.y*=sc;
|
||||
InputDisplay.xsize*=sc;
|
||||
InputDisplay.ysize*=sc;
|
||||
|
||||
GraphicalInputDisplay.x*=sc;
|
||||
GraphicalInputDisplay.y*=sc;
|
||||
GraphicalInputDisplay.xsize*=sc;
|
||||
GraphicalInputDisplay.ysize*=sc;
|
||||
|
||||
LagFrameCounter.x*=sc;
|
||||
LagFrameCounter.y*=sc;
|
||||
LagFrameCounter.xsize*=sc;
|
||||
LagFrameCounter.ysize*=sc;
|
||||
|
||||
Microphone.x*=sc;
|
||||
Microphone.y*=sc;
|
||||
Microphone.xsize*=sc;
|
||||
Microphone.ysize*=sc;
|
||||
|
||||
RTCDisplay.x*=sc;
|
||||
RTCDisplay.y*=sc;
|
||||
RTCDisplay.xsize*=sc;
|
||||
RTCDisplay.ysize*=sc;
|
||||
|
||||
SavestateSlots.x*=sc;
|
||||
SavestateSlots.y*=sc;
|
||||
SavestateSlots.xsize*=sc;
|
||||
SavestateSlots.ysize*=sc;
|
||||
}
|
||||
|
||||
static void joyFill(int n) {
|
||||
|
||||
bool pressedForGame = NDS_getFinalUserInput().buttons.array[n];
|
||||
|
@ -235,8 +320,8 @@ static void drawPad(double x, double y, double ratio) {
|
|||
// aligning to odd half-pixel boundaries prevents agg2d from blurring thin straight lines
|
||||
x = floor(x) + 0.5;
|
||||
y = floor(calcY(y)) + 0.5;
|
||||
double xc = 41 - 0.5;
|
||||
double yc = 20 - 0.5;
|
||||
double xc = 41*osd->scale - 0.5;
|
||||
double yc = 20*osd->scale - 0.5;
|
||||
|
||||
aggDraw.hud->lineColor(128,128,128,255);
|
||||
|
||||
|
@ -252,12 +337,12 @@ static void drawPad(double x, double y, double ratio) {
|
|||
aggDraw.hud->roundedRect (screenLeft, screenTop, screenRight, screenBottom, 1);
|
||||
|
||||
|
||||
joyEllipse(.89,.45,xc,yc,x,y,ratio,1,6);//B
|
||||
joyEllipse(.89,.22,xc,yc,x,y,ratio,1,3);//X
|
||||
joyEllipse(.83,.34,xc,yc,x,y,ratio,1,4);//Y
|
||||
joyEllipse(.95,.34,xc,yc,x,y,ratio,1,5);//A
|
||||
joyEllipse(.82,.716,xc,yc,x,y,ratio,.5,7);//Start
|
||||
joyEllipse(.82,.842,xc,yc,x,y,ratio,.5,8);//Select
|
||||
joyEllipse(.89,.45,xc,yc,x,y,ratio,osd->scale,6);//B
|
||||
joyEllipse(.89,.22,xc,yc,x,y,ratio,osd->scale,3);//X
|
||||
joyEllipse(.83,.34,xc,yc,x,y,ratio,osd->scale,4);//Y
|
||||
joyEllipse(.95,.34,xc,yc,x,y,ratio,osd->scale,5);//A
|
||||
joyEllipse(.82,.716,xc,yc,x,y,ratio,osd->scale * .5,7);//Start
|
||||
joyEllipse(.82,.842,xc,yc,x,y,ratio,osd->scale * .5,8);//Select
|
||||
|
||||
|
||||
double dpadPoints [][2] = {
|
||||
|
@ -311,29 +396,29 @@ static void drawPad(double x, double y, double ratio) {
|
|||
// touch pad
|
||||
{
|
||||
BOOL gameTouchOn = nds.isTouch;
|
||||
double gameTouchX = screenLeft+1 + (nds.scr_touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0;
|
||||
double gameTouchY = screenTop+1 + (nds.scr_touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0;
|
||||
double gameTouchX = screenLeft+1 + (nds.scr_touchX * osd->scale * 0.0625) * (screenRight - screenLeft - 2) / (double)ScreenWidth();
|
||||
double gameTouchY = screenTop+1 + (nds.scr_touchY * osd->scale * 0.0625) * (screenBottom - screenTop - 2) / (double)ScreenHeight();
|
||||
bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch;
|
||||
double physicalTouchX = screenLeft+1 + (NDS_getRawUserInput().touch.touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0;
|
||||
double physicalTouchY = screenTop+1 + (NDS_getRawUserInput().touch.touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0;
|
||||
double physicalTouchX = screenLeft+1 + (NDS_getRawUserInput().touch.touchX * osd->scale * 0.0625) * (screenRight - screenLeft - 2) / (double)ScreenWidth();
|
||||
double physicalTouchY = screenTop+1 + (NDS_getRawUserInput().touch.touchY * osd->scale * 0.0625) * (screenBottom - screenTop - 2) / (double)ScreenHeight();
|
||||
if(gameTouchOn && physicalTouchOn && gameTouchX == physicalTouchX && gameTouchY == physicalTouchY)
|
||||
{
|
||||
aggDraw.hud->fillColor(0,0,0,255);
|
||||
aggDraw.hud->ellipse(gameTouchX, gameTouchY, ratio*0.37, ratio*0.37);
|
||||
aggDraw.hud->ellipse(gameTouchX, gameTouchY, osd->scale*ratio*0.37, osd->scale*ratio*0.37);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(physicalTouchOn)
|
||||
{
|
||||
aggDraw.hud->fillColor(0,0,0,128);
|
||||
aggDraw.hud->ellipse(physicalTouchX, physicalTouchY, ratio*0.5, ratio*0.5);
|
||||
aggDraw.hud->ellipse(physicalTouchX, physicalTouchY, osd->scale*ratio*0.5, osd->scale*ratio*0.5);
|
||||
aggDraw.hud->fillColor(0,255,0,255);
|
||||
aggDraw.hud->ellipse(physicalTouchX, physicalTouchY, ratio*0.37, ratio*0.37);
|
||||
aggDraw.hud->ellipse(physicalTouchX, physicalTouchY, osd->scale*ratio*0.37, osd->scale*ratio*0.37);
|
||||
}
|
||||
if(gameTouchOn)
|
||||
{
|
||||
aggDraw.hud->fillColor(255,0,0,255);
|
||||
aggDraw.hud->ellipse(gameTouchX, gameTouchY, ratio*0.37, ratio*0.37);
|
||||
aggDraw.hud->ellipse(gameTouchX, gameTouchY, osd->scale*ratio*0.37, osd->scale*ratio*0.37);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -379,8 +464,8 @@ static void TextualInputDisplay() {
|
|||
// cast from char to std::string is a bit awkward
|
||||
std::string str(buttonChars+i, 2);
|
||||
str[1] = '\0';
|
||||
|
||||
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y), str);
|
||||
|
||||
RenderTextAutoVector(x, calcY(Hud.InputDisplay.y), str, true, osd ? osd->scale : 1);
|
||||
}
|
||||
|
||||
// touch pad
|
||||
|
@ -396,7 +481,7 @@ static void TextualInputDisplay() {
|
|||
{
|
||||
sprintf(str, "%d,%d", gameTouchX, gameTouchY);
|
||||
aggDraw.hud->lineColor(255,255,255,255);
|
||||
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y), str);
|
||||
RenderTextAutoVector(x, calcY(Hud.InputDisplay.y), str, true, osd ? osd->scale : 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -404,13 +489,13 @@ static void TextualInputDisplay() {
|
|||
{
|
||||
sprintf(str, "%d,%d", gameTouchX, gameTouchY);
|
||||
aggDraw.hud->lineColor(255,48,48,255);
|
||||
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y)-(physicalTouchOn?8:0), str);
|
||||
RenderTextAutoVector(x, calcY(Hud.InputDisplay.y)-(physicalTouchOn?8:0), str, true, osd ? osd->scale : 1);
|
||||
}
|
||||
if(physicalTouchOn)
|
||||
{
|
||||
sprintf(str, "%d,%d", physicalTouchX, physicalTouchY);
|
||||
aggDraw.hud->lineColor(0,192,0,255);
|
||||
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y)+(gameTouchOn?8:0), str);
|
||||
RenderTextAutoVector(x, calcY(Hud.InputDisplay.y)+(gameTouchOn?8:0), str, true, osd ? osd->scale : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -418,10 +503,10 @@ static void TextualInputDisplay() {
|
|||
|
||||
static void OSD_HandleTouchDisplay() {
|
||||
// note: calcY should not be used in this function.
|
||||
aggDraw.hud->lineWidth(1.0);
|
||||
aggDraw.hud->lineWidth(osd->scale);
|
||||
|
||||
temptouch.X = NDS_getRawUserInput().touch.touchX >> 4;
|
||||
temptouch.Y = NDS_getRawUserInput().touch.touchY >> 4;
|
||||
temptouch.X = (NDS_getRawUserInput().touch.touchX >> 4) * osd->scale;
|
||||
temptouch.Y = (NDS_getRawUserInput().touch.touchY >> 4) * osd->scale;
|
||||
|
||||
if(touchshadow) {
|
||||
|
||||
|
@ -432,27 +517,27 @@ static void OSD_HandleTouchDisplay() {
|
|||
temptouch = touch[i];
|
||||
if(temptouch.X != 0 || temptouch.Y != 0) {
|
||||
aggDraw.hud->lineColor(0, 255, 0, touchalpha[i]);
|
||||
aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz
|
||||
aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert
|
||||
aggDraw.hud->line(temptouch.X - ScreenWidth(), temptouch.Y + ScreenHeight(), temptouch.X + ScreenWidth(), temptouch.Y + ScreenHeight()); //horiz
|
||||
aggDraw.hud->line(temptouch.X, temptouch.Y - ScreenWidth(), temptouch.X, temptouch.Y + ScreenHeight()*2); //vert
|
||||
aggDraw.hud->fillColor(0, 0, 0, touchalpha[i]);
|
||||
aggDraw.hud->rectangle(temptouch.X-1, temptouch.Y + 192-1, temptouch.X+1, temptouch.Y + 192+1);
|
||||
aggDraw.hud->rectangle(temptouch.X-1, temptouch.Y + ScreenHeight()-1, temptouch.X+1, temptouch.Y + ScreenHeight()+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if(NDS_getRawUserInput().touch.isTouch) {
|
||||
aggDraw.hud->lineColor(0, 255, 0, 128);
|
||||
aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz
|
||||
aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert
|
||||
aggDraw.hud->line(temptouch.X - ScreenWidth(), temptouch.Y + ScreenHeight(), temptouch.X + ScreenWidth(), temptouch.Y + ScreenHeight()); //horiz
|
||||
aggDraw.hud->line(temptouch.X, temptouch.Y - ScreenWidth(), temptouch.X, temptouch.Y + ScreenHeight()*2); //vert
|
||||
}
|
||||
|
||||
if(nds.isTouch)
|
||||
{
|
||||
temptouch.X = nds.scr_touchX / 16;
|
||||
temptouch.Y = nds.scr_touchY / 16;
|
||||
temptouch.X = nds.scr_touchX / 16 * osd->scale;
|
||||
temptouch.Y = nds.scr_touchY / 16 * osd->scale;
|
||||
aggDraw.hud->lineColor(255, 0, 0, 128);
|
||||
aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz
|
||||
aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert
|
||||
aggDraw.hud->line(temptouch.X - ScreenWidth(), temptouch.Y + ScreenHeight(), temptouch.X + ScreenWidth(), temptouch.Y + ScreenHeight()); //horiz
|
||||
aggDraw.hud->line(temptouch.X, temptouch.Y - ScreenWidth(), temptouch.X, temptouch.Y + ScreenHeight()*2); //vert
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -476,24 +561,24 @@ static void DrawStateSlots(){
|
|||
|
||||
if(alpha!=0)
|
||||
{
|
||||
aggDraw.hud->lineWidth(1.0);
|
||||
aggDraw.hud->lineWidth(osd->scale);
|
||||
aggDraw.hud->lineColor(0, 0, 0, alpha);
|
||||
aggDraw.hud->fillColor(255, 255, 255, alpha);
|
||||
|
||||
for ( int i = 0, xpos=0; i < 10; xpos=xpos+24) {
|
||||
for ( int i = 0, xpos=0; i < 10; xpos=xpos+24*osd->scale) {
|
||||
|
||||
int yheight=0;
|
||||
|
||||
aggDraw.hud->fillLinearGradient(xloc + xpos, yloc - yheight, xloc + 22 + xpos, yloc + 20 + yheight+20, agg::rgba8(100,200,255,alpha), agg::rgba8(255,255,255,0));
|
||||
aggDraw.hud->fillLinearGradient(xloc + xpos, yloc - yheight, xloc + 22*osd->scale + xpos, yloc + 20*osd->scale + yheight+20*osd->scale, agg::rgba8(100,200,255,alpha), agg::rgba8(255,255,255,0));
|
||||
|
||||
if(lastSaveState == i) {
|
||||
yheight = 5;
|
||||
aggDraw.hud->fillLinearGradient(xloc + xpos, yloc - yheight, 22 + xloc + xpos, yloc + 20 + yheight+20, agg::rgba8(100,255,255,alpha), agg::rgba8(255,255,255,0));
|
||||
yheight = 5*osd->scale;
|
||||
aggDraw.hud->fillLinearGradient(xloc + xpos, yloc - yheight, 22*osd->scale + xloc + xpos, yloc + 20*osd->scale + yheight+20*osd->scale, agg::rgba8(100,255,255,alpha), agg::rgba8(255,255,255,0));
|
||||
}
|
||||
|
||||
aggDraw.hud->rectangle(xloc + xpos , yloc - yheight, xloc + 22 + xpos , yloc + 20 + yheight);
|
||||
aggDraw.hud->rectangle(xloc + xpos , yloc - yheight, xloc + 22*osd->scale + xpos , yloc + 20*osd->scale + yheight);
|
||||
snprintf(number, 10, "%d", i);
|
||||
aggDraw.hud->renderText(xloc + 1 + xpos + 4, yloc+4, std::string(number));
|
||||
RenderTextAutoVector(xloc + osd->scale + xpos + 4*osd->scale, yloc+4*osd->scale, std::string(number), true, osd->scale);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -511,10 +596,10 @@ static void DrawEditableElementIndicators()
|
|||
HudCoordinates &hud = Hud.hud(i);
|
||||
aggDraw.hud->fillColor(0,0,0,0);
|
||||
aggDraw.hud->lineColor(0,0,0,64);
|
||||
aggDraw.hud->lineWidth(2.0);
|
||||
aggDraw.hud->lineWidth(2.0*osd->scale);
|
||||
aggDraw.hud->rectangle(hud.x,calcY(hud.y),hud.x+hud.xsize+1.0,calcY(hud.y)+hud.ysize+1.0);
|
||||
aggDraw.hud->lineColor(255,hud.clicked?127:255,0,255);
|
||||
aggDraw.hud->lineWidth(1.0);
|
||||
aggDraw.hud->lineWidth(osd->scale);
|
||||
aggDraw.hud->rectangle(hud.x-0.5,calcY(hud.y)-0.5,hud.x+hud.xsize+0.5,calcY(hud.y)+hud.ysize+0.5);
|
||||
i++;
|
||||
}
|
||||
|
@ -624,9 +709,11 @@ OSDCLASS::OSDCLASS(u8 core)
|
|||
|
||||
singleScreen = false;
|
||||
swapScreens = false;
|
||||
|
||||
scale = 1.0;
|
||||
needUpdate = false;
|
||||
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
useVectorFonts = false;
|
||||
#endif
|
||||
if (core==0)
|
||||
strcpy(name,"Core A");
|
||||
else
|
||||
|
@ -707,7 +794,7 @@ void OSDCLASS::update()
|
|||
for (int i=0; i < lastLineText; i++)
|
||||
{
|
||||
aggDraw.hud->lineColor(lineColor[i]);
|
||||
aggDraw.hud->renderTextDropshadowed(lineText_x,lineText_y+(i*16),lineText[i]);
|
||||
RenderTextAutoVector(lineText_x, lineText_y+(i*16), lineText[i], true, osd->scale);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -789,7 +876,7 @@ void OSDCLASS::addFixed(u16 x, u16 y, const char *fmt, ...)
|
|||
va_end(list);
|
||||
|
||||
aggDraw.hud->lineColor(255,255,255);
|
||||
aggDraw.hud->renderTextDropshadowed(x,calcY(y),msg);
|
||||
RenderTextAutoVector(x, calcY(y), msg, true, osd->scale);
|
||||
|
||||
needUpdate = true;
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ public:
|
|||
|
||||
HudCoordinates &hud(int i) { return ((HudCoordinates*)this)[i]; }
|
||||
void reset();
|
||||
void rescale(double oldScale, double newScale);
|
||||
|
||||
int fps, fps3d, cpuload[2], cpuloopIterationCount;
|
||||
char rtcString[25];
|
||||
|
@ -92,7 +93,7 @@ class OSDCLASS
|
|||
private:
|
||||
u64 offset;
|
||||
u8 mode;
|
||||
|
||||
|
||||
u16 rotAngle;
|
||||
|
||||
u16 lineText_x;
|
||||
|
@ -111,6 +112,10 @@ public:
|
|||
char name[7]; // for debuging
|
||||
bool singleScreen;
|
||||
bool swapScreens;
|
||||
double scale;
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
bool useVectorFonts;
|
||||
#endif
|
||||
|
||||
OSDCLASS(u8 core);
|
||||
~OSDCLASS();
|
||||
|
@ -125,7 +130,7 @@ public:
|
|||
void addLine(const char* fmt, va_list args);
|
||||
void addFixed(u16 x, u16 y, const char *fmt, ...);
|
||||
void border(bool enabled);
|
||||
|
||||
|
||||
void SaveHudEditor();
|
||||
};
|
||||
|
||||
|
|
|
@ -118,20 +118,17 @@ static void Agg_init_fonts()
|
|||
|
||||
AggDraw_Desmume aggDraw;
|
||||
|
||||
#if defined(WIN32) || defined(HOST_LINUX)
|
||||
T_AGG_RGBA agg_targetScreen(0, 256, 384, 1024);
|
||||
#else
|
||||
T_AGG_RGB555 agg_targetScreen(0, 256, 384, 1512);
|
||||
#endif
|
||||
T_AGG_RGBA agg_targetScreen_32bit(0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2, GPU_FRAMEBUFFER_NATIVE_WIDTH*4);
|
||||
T_AGG_RGB555 agg_targetScreen_16bit(0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2, GPU_FRAMEBUFFER_NATIVE_WIDTH*2);
|
||||
|
||||
static u32 luaBuffer[256*192*2];
|
||||
T_AGG_RGBA agg_targetLua((u8*)luaBuffer, 256, 384, 1024);
|
||||
static std::vector<u32> luaBuffer(GPU_FRAMEBUFFER_NATIVE_WIDTH*GPU_FRAMEBUFFER_NATIVE_HEIGHT*2);
|
||||
T_AGG_RGBA agg_targetLua((u8*)luaBuffer.data(), GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2, GPU_FRAMEBUFFER_NATIVE_WIDTH*4);
|
||||
|
||||
static u32 hudBuffer[256*192*2];
|
||||
T_AGG_RGBA agg_targetHud((u8*)hudBuffer, 256, 384, 1024);
|
||||
static std::vector<u32> hudBuffer(GPU_FRAMEBUFFER_NATIVE_WIDTH*GPU_FRAMEBUFFER_NATIVE_HEIGHT*2);
|
||||
T_AGG_RGBA agg_targetHud((u8*)hudBuffer.data(), GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2, GPU_FRAMEBUFFER_NATIVE_WIDTH*4);
|
||||
|
||||
static AggDrawTarget* targets[] = {
|
||||
&agg_targetScreen,
|
||||
&agg_targetScreen_32bit,
|
||||
&agg_targetHud,
|
||||
&agg_targetLua,
|
||||
};
|
||||
|
@ -139,6 +136,16 @@ static AggDrawTarget* targets[] = {
|
|||
void Agg_init()
|
||||
{
|
||||
Agg_init_fonts();
|
||||
switch(aggDraw.screenBytesPerPixel)
|
||||
{
|
||||
case 2:
|
||||
targets[0]=&agg_targetScreen_16bit;
|
||||
break;
|
||||
case 4:
|
||||
targets[0]=&agg_targetScreen_32bit;
|
||||
break;
|
||||
}
|
||||
|
||||
aggDraw.screen = targets[0];
|
||||
aggDraw.hud = targets[1];
|
||||
aggDraw.lua = targets[2];
|
||||
|
@ -149,19 +156,35 @@ void Agg_init()
|
|||
//and the more clever compositing isnt supported in non-windows
|
||||
#ifdef WIN32
|
||||
if(CommonSettings.single_core())
|
||||
aggDraw.hud = &agg_targetScreen;
|
||||
aggDraw.hud = aggDraw.screen;
|
||||
#else
|
||||
aggDraw.hud = &agg_targetScreen;
|
||||
aggDraw.hud = aggDraw.screen;
|
||||
#endif
|
||||
|
||||
aggDraw.hud->setFont("verdana18_bold");
|
||||
}
|
||||
|
||||
AggDraw_Desmume::AggDraw_Desmume()
|
||||
{
|
||||
screenBytesPerPixel = 4;
|
||||
}
|
||||
|
||||
void AggDraw_Desmume::setTarget(AggTarget newTarget)
|
||||
{
|
||||
target = targets[newTarget];
|
||||
}
|
||||
|
||||
void Agg_setCustomSize(int w, int h)
|
||||
{
|
||||
hudBuffer.resize(w*h);
|
||||
luaBuffer.resize(w*h);
|
||||
if(aggDraw.screen)
|
||||
aggDraw.screen->setDrawTargetDims(0, w, h, w*aggDraw.screenBytesPerPixel);
|
||||
if(aggDraw.hud)
|
||||
aggDraw.hud->setDrawTargetDims((u8*)hudBuffer.data(), w, h, w*4);
|
||||
if(aggDraw.lua)
|
||||
aggDraw.lua->setDrawTargetDims((u8*)luaBuffer.data(), w, h, w*4);
|
||||
}
|
||||
|
||||
|
||||
////temporary, just for testing the lib
|
||||
|
|
|
@ -19,7 +19,7 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -43,18 +43,18 @@ THE SOFTWARE.
|
|||
|
||||
#include "agg_pixfmt_rgb.h"
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#include "agg_pixfmt_rgb_packed.h"
|
||||
#include "agg_pixfmt_rgb_packed.h"
|
||||
|
||||
#include "agg2d.h"
|
||||
|
||||
typedef agg::rgba8 AggColor;
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//NOTE - these blenders are necessary to change the rgb order from the defaults, which are incorrect for us
|
||||
|
||||
//this custom blender does more correct blending math than the default
|
||||
//which is necessary or else drawing transparent pixels on (31,31,31) will yield (30,30,30)
|
||||
namespace agg
|
||||
{
|
||||
//NOTE - these blenders are necessary to change the rgb order from the defaults, which are incorrect for us
|
||||
|
||||
//this custom blender does more correct blending math than the default
|
||||
//which is necessary or else drawing transparent pixels on (31,31,31) will yield (30,30,30)
|
||||
struct my_blender_rgb555_pre
|
||||
{
|
||||
typedef rgba8 color_type;
|
||||
|
@ -242,6 +242,8 @@ public:
|
|||
bool empty;
|
||||
|
||||
virtual void clear() = 0;
|
||||
|
||||
virtual void setDrawTargetDims(agg::int8u* buf, int width, int height, int stride) = 0;
|
||||
|
||||
virtual agg::rendering_buffer & buf() = 0;
|
||||
|
||||
|
@ -408,6 +410,9 @@ public:
|
|||
virtual Agg2DBase::ImageResample imageResample() = 0;
|
||||
static const agg::int8u* lookupFont(const std::string& name);
|
||||
virtual void setFont(const std::string& name) = 0;
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
virtual void setVectorFont(const std::string& fileName, int size, bool bold) = 0;
|
||||
#endif
|
||||
virtual void renderText(double dstX, double dstY, const std::string& str) = 0;
|
||||
virtual void renderTextDropshadowed(double dstX, double dstY, const std::string& str)
|
||||
{
|
||||
|
@ -427,6 +432,30 @@ public:
|
|||
lineColor(lineColorOld);
|
||||
renderText(dstX,dstY,str);
|
||||
}
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
virtual void renderVectorFontText(double dstX, double dstY, const std::string& str) = 0;
|
||||
virtual void renderVectorFontTextDropshadowed(double dstX, double dstY, const std::string& str, double shadowOffset = 1.0)
|
||||
{
|
||||
shadowOffset*=0.5;
|
||||
AggColor lineColorOld = lineColor();
|
||||
if(lineColorOld.r+lineColorOld.g+lineColorOld.b<192)
|
||||
lineColor(255-lineColorOld.r,255-lineColorOld.g,255-lineColorOld.b);
|
||||
else
|
||||
lineColor(0,0,0);
|
||||
fillColor(lineColor());
|
||||
renderVectorFontText(dstX-shadowOffset,dstY-shadowOffset,str);
|
||||
renderVectorFontText(dstX,dstY-shadowOffset,str);
|
||||
renderVectorFontText(dstX+shadowOffset,dstY-shadowOffset,str);
|
||||
renderVectorFontText(dstX-shadowOffset,dstY,str);
|
||||
renderVectorFontText(dstX+shadowOffset,dstY,str);
|
||||
renderVectorFontText(dstX-shadowOffset,dstY+shadowOffset,str);
|
||||
renderVectorFontText(dstX,dstY+shadowOffset,str);
|
||||
renderVectorFontText(dstX+shadowOffset,dstY+shadowOffset,str);
|
||||
lineColor(lineColorOld);
|
||||
fillColor(lineColor());
|
||||
renderVectorFontText(dstX,dstY,str);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Auxiliary
|
||||
|
@ -458,6 +487,13 @@ public:
|
|||
undirty();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setDrawTargetDims(agg::int8u* buf, int width, int height, int stride)
|
||||
{
|
||||
BASE::attach(buf,width,height,stride);
|
||||
|
||||
BASE::viewport(0, 0, width-1, height-1, 0, 0, width-1, height-1, TAGG2D::Anisotropic);
|
||||
}
|
||||
|
||||
virtual agg::rendering_buffer & buf() { dirty(); return BASE::buf(); } // buf() might not always require calling dirty()
|
||||
typename BASE::MyImage image() { return BASE::MyImage(buf()); }
|
||||
|
@ -578,6 +614,9 @@ public:
|
|||
virtual void polyline(double* xy, int numPoints) {dirty(); BASE::polyline(xy, numPoints);};
|
||||
|
||||
virtual void setFont(const std::string& name) { BASE::font(lookupFont(name)); }
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
virtual void setVectorFont(const std::string& fileName, int size, bool bold) {BASE::font(fileName.c_str(), size, bold); }
|
||||
#endif
|
||||
virtual void renderText(double dstX, double dstY, const std::string& str) {
|
||||
dirty();
|
||||
int height = BASE::font()[0];
|
||||
|
@ -585,6 +624,13 @@ public:
|
|||
int offset = height-base*2;
|
||||
BASE::renderText(dstX, dstY + offset, str);
|
||||
}
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
virtual void renderVectorFontText(double dstX, double dstY, const std::string& str) {
|
||||
dirty();
|
||||
BASE::flipText(true);
|
||||
BASE::text(dstX, dstY + BASE::fontHeight(), str.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Path commands
|
||||
virtual void resetPath() {BASE::resetPath();};
|
||||
|
@ -659,15 +705,18 @@ enum AggTarget
|
|||
class AggDraw_Desmume : public AggDraw
|
||||
{
|
||||
public:
|
||||
AggDraw_Desmume();
|
||||
void setTarget(AggTarget newTarget);
|
||||
//void composite(void* dest);
|
||||
|
||||
AggDrawTarget *screen, *hud, *lua;
|
||||
int screenBytesPerPixel;
|
||||
};
|
||||
|
||||
extern AggDraw_Desmume aggDraw;
|
||||
|
||||
void Agg_init();
|
||||
void Agg_setCustomSize(int w, int h);
|
||||
|
||||
struct font_type
|
||||
{
|
||||
|
|
|
@ -98,7 +98,7 @@ libdesmume_a_SOURCES = \
|
|||
../../utils/tinyxml/tinyxmlparser.cpp \
|
||||
../../utils/glcorearb.h \
|
||||
../../utils/colorspacehandler/colorspacehandler.cpp ../../utils/colorspacehandler/colorspacehandler.h \
|
||||
../../addons/slot2_auto.cpp ../../addons/slot2_mpcf.cpp ../../addons/slot2_paddle.cpp ../../addons/slot2_gbagame.cpp ../../addons/slot2_none.cpp ../../addons/slot2_rumblepak.cpp ../../addons/slot2_guitarGrip.cpp ../../addons/slot2_expMemory.cpp ../../addons/slot2_piano.cpp ../../addons/slot2_passme.cpp ../../addons/slot1_none.cpp ../../addons/slot1_r4.cpp ../../addons/slot1_retail_nand.cpp ../../addons/slot1_retail_auto.cpp ../../addons/slot1_retail_mcrom.cpp ../../addons/slot1_retail_mcrom_debug.cpp ../../addons/slot1comp_mc.cpp ../../addons/slot1comp_mc.h ../../addons/slot1comp_rom.h ../../addons/slot1comp_rom.cpp ../../addons/slot1comp_protocol.h ../../addons/slot1comp_protocol.cpp \
|
||||
../../addons/slot2_auto.cpp ../../addons/slot2_mpcf.cpp ../../addons/slot2_paddle.cpp ../../addons/slot2_gbagame.cpp ../../addons/slot2_none.cpp ../../addons/slot2_rumblepak.cpp ../../addons/slot2_guitarGrip.cpp ../../addons/slot2_hcv1000.cpp ../../addons/slot2_expMemory.cpp ../../addons/slot2_piano.cpp ../../addons/slot2_passme.cpp ../../addons/slot1_none.cpp ../../addons/slot1_r4.cpp ../../addons/slot1_retail_nand.cpp ../../addons/slot1_retail_auto.cpp ../../addons/slot1_retail_mcrom.cpp ../../addons/slot1_retail_mcrom_debug.cpp ../../addons/slot1comp_mc.cpp ../../addons/slot1comp_mc.h ../../addons/slot1comp_rom.h ../../addons/slot1comp_rom.cpp ../../addons/slot1comp_protocol.h ../../addons/slot1comp_protocol.cpp \
|
||||
../../cheatSystem.cpp ../../cheatSystem.h \
|
||||
../../texcache.cpp ../../texcache.h ../../rasterize.cpp ../../rasterize.h \
|
||||
../../metaspu/metaspu.cpp ../../metaspu/metaspu.h \
|
||||
|
|
|
@ -63,6 +63,24 @@ void value<int>::save() {
|
|||
g_key_file_set_integer(this->mKeyFile, this->mSection.c_str(), this->mKey.c_str(), this->mData);
|
||||
}
|
||||
|
||||
/*class value<float> */
|
||||
|
||||
template<>
|
||||
void value<float>::load() {
|
||||
GError* err = NULL;
|
||||
float val = g_key_file_get_double(this->mKeyFile, this->mSection.c_str(), this->mKey.c_str(), &err);
|
||||
if (err != NULL) {
|
||||
g_error_free(err);
|
||||
} else {
|
||||
this->mData = val;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void value<float>::save() {
|
||||
g_key_file_set_double(this->mKeyFile, this->mSection.c_str(), this->mKey.c_str(), this->mData);
|
||||
}
|
||||
|
||||
/* class value<string> */
|
||||
|
||||
template<>
|
||||
|
@ -79,6 +97,25 @@ void value<string>::save() {
|
|||
g_key_file_set_string(this->mKeyFile, this->mSection.c_str(), this->mKey.c_str(), this->mData.c_str());
|
||||
}
|
||||
|
||||
/* class value<vector<int> > */
|
||||
|
||||
template<>
|
||||
void value<vector<int> >::load() {
|
||||
gsize l;
|
||||
int* val = g_key_file_get_integer_list(this->mKeyFile, this->mSection.c_str(), this->mKey.c_str(), &l, NULL);
|
||||
if(val)
|
||||
{
|
||||
this->mData.resize(l);
|
||||
std::copy(val, val+l, this->mData.begin());
|
||||
g_free(val);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void value<vector<int> >::save() {
|
||||
g_key_file_set_integer_list(this->mKeyFile, this->mSection.c_str(), this->mKey.c_str(), this->mData.data(), this->mData.size());
|
||||
}
|
||||
|
||||
/* class Config */
|
||||
|
||||
Config::Config()
|
||||
|
|
|
@ -49,6 +49,7 @@ OPT(hud_input, bool, false, HudDisplay, Input)
|
|||
OPT(hud_graphicalInput, bool, false, HudDisplay, GraphicalInput)
|
||||
OPT(hud_rtc, bool, false, HudDisplay, RTC)
|
||||
OPT(hud_mic, bool, false, HudDisplay, Mic)
|
||||
OPT(hud_layout, std::vector<int>, std::vector<int>(), HudDisplay, Layout)
|
||||
|
||||
/* Config */
|
||||
OPT(fpslimiter, bool, true, Config, FpsLimiter)
|
||||
|
@ -60,6 +61,7 @@ OPT(core3D, int, 1, Config, Core3D)
|
|||
OPT(textureDeposterize, bool, false, Config, 3DTextureDeposterization)
|
||||
OPT(textureSmoothing, bool, false, Config, 3DTextureSmoothing)
|
||||
OPT(textureUpscale, int, 1, Config, 3DTextureUpscaling)
|
||||
OPT(gpuScaleFactor, float, 1.0, Config, GPUScaleFactor)
|
||||
OPT(highColorInterpolation, bool, true, Config, HighResolutionColorInterpolation)
|
||||
OPT(multisampling, bool, false, Config, OpenGLMultisampling)
|
||||
OPT(multisamplingSize, int, 0, Config, OpenGLMultisamplingSize)
|
||||
|
|
|
@ -94,6 +94,25 @@
|
|||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">GPU scale factor:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="gpuscale">
|
||||
<property name="numeric">true</property>
|
||||
<property name="digits">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="posterize">
|
||||
<property name="label" translatable="yes">3D Texture Deposterization</property>
|
||||
|
@ -101,7 +120,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -111,7 +130,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -121,7 +140,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -130,7 +149,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -146,7 +165,7 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2007 Pascal Giard (evilynux)
|
||||
Copyright (C) 2006-2021 DeSmuME team
|
||||
Copyright (C) 2006-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -31,6 +31,9 @@
|
|||
#include <SDL.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <vector>
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "firmware.h"
|
||||
|
@ -73,7 +76,6 @@
|
|||
|
||||
#ifdef HAVE_OPENGL
|
||||
#include <GL/gl.h>
|
||||
#include "OGLRender.h"
|
||||
#include "OGLRender_3_2.h"
|
||||
#endif
|
||||
|
||||
|
@ -99,6 +101,14 @@ static int draw_count;
|
|||
extern int _scanline_filter_a, _scanline_filter_b, _scanline_filter_c, _scanline_filter_d;
|
||||
VideoFilter* video;
|
||||
|
||||
#define GPU_SCALE_FACTOR_MIN 1.0f
|
||||
#define GPU_SCALE_FACTOR_MAX 10.0f
|
||||
|
||||
float gpu_scale_factor = 1.0f;
|
||||
int real_framebuffer_width = GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
int real_framebuffer_height = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
|
||||
|
||||
|
||||
desmume::config::Config config;
|
||||
|
||||
#ifdef GDB_STUB
|
||||
|
@ -119,6 +129,15 @@ enum {
|
|||
SUB_OBJ
|
||||
};
|
||||
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
#define VECTOR_FONT_BASE_SIZE 16
|
||||
|
||||
static FcConfig* fontConfig;
|
||||
static std::string vectorFontFile;
|
||||
|
||||
static std::string FindFontFile(const char* fontName, bool bold);
|
||||
#endif
|
||||
|
||||
gboolean EmuLoop(gpointer data);
|
||||
|
||||
static AVOutX264 avout_x264;
|
||||
|
@ -182,6 +201,9 @@ static void HudLagCounter(GSimpleAction *action, GVariant *parameter, gpointer u
|
|||
static void HudRtc(GSimpleAction *action, GVariant *parameter, gpointer user_data);
|
||||
static void HudMic(GSimpleAction *action, GVariant *parameter, gpointer user_data);
|
||||
static void HudEditor(GSimpleAction *action, GVariant *parameter, gpointer user_data);
|
||||
static void HudResetLayout(GSimpleAction *action, GVariant *parameter, gpointer user_data);
|
||||
static void HudSaveLayout();
|
||||
static void HudLoadLayout();
|
||||
#endif
|
||||
#ifdef DESMUME_GTK_FIRMWARE_BROKEN
|
||||
static void SelectFirmwareFile(GSimpleAction *action, GVariant *parameter, gpointer user_data);
|
||||
|
@ -239,6 +261,7 @@ static const GActionEntry app_entries[] = {
|
|||
{ "hud_rtc", HudRtc, NULL, "false" },
|
||||
{ "hud_mic", HudMic, NULL, "false" },
|
||||
{ "hud_editor", HudEditor, NULL, "false" },
|
||||
{ "hud_reset_layout", HudResetLayout},
|
||||
#endif
|
||||
|
||||
// Config
|
||||
|
@ -289,6 +312,8 @@ enum orientation_enum {
|
|||
ORIENT_VERTICAL = 0,
|
||||
ORIENT_HORIZONTAL = 1,
|
||||
ORIENT_SINGLE = 2,
|
||||
ORIENT_HYBRID_EQUAL = 3,
|
||||
ORIENT_HYBRID_VERTICAL = 4,
|
||||
ORIENT_N
|
||||
};
|
||||
|
||||
|
@ -298,9 +323,11 @@ struct screen_size_t {
|
|||
};
|
||||
|
||||
const struct screen_size_t screen_size[ORIENT_N] = {
|
||||
{256, 384},
|
||||
{512, 192},
|
||||
{256, 192}
|
||||
{GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2},
|
||||
{GPU_FRAMEBUFFER_NATIVE_WIDTH*2, GPU_FRAMEBUFFER_NATIVE_HEIGHT},
|
||||
{GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT},
|
||||
{GPU_FRAMEBUFFER_NATIVE_WIDTH*3, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2},
|
||||
{GPU_FRAMEBUFFER_NATIVE_WIDTH*3, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2}
|
||||
};
|
||||
|
||||
enum spumode_enum {
|
||||
|
@ -515,7 +542,9 @@ struct nds_screen_t {
|
|||
gint rotation_angle;
|
||||
orientation_enum orientation;
|
||||
cairo_matrix_t touch_matrix;
|
||||
cairo_matrix_t touch_matrix_hybrid;
|
||||
cairo_matrix_t topscreen_matrix;
|
||||
cairo_matrix_t topscreen_matrix_hybrid;
|
||||
gboolean swap;
|
||||
};
|
||||
|
||||
|
@ -1189,6 +1218,33 @@ static void Reset(GSimpleAction *action, GVariant *parameter, gpointer user_data
|
|||
|
||||
|
||||
/////////////////////////////// DRAWING SCREEN //////////////////////////////////
|
||||
|
||||
struct DrawParams {
|
||||
bool valid;
|
||||
|
||||
//Drawing area size
|
||||
gint daW;
|
||||
gint daH;
|
||||
|
||||
//Image size
|
||||
gint imgW;
|
||||
gint imgH;
|
||||
|
||||
//Buffer size
|
||||
gint dstW;
|
||||
gint dstH;
|
||||
gint dstScale;
|
||||
|
||||
gint gap;
|
||||
gint gapOffset;
|
||||
|
||||
gfloat ratio;
|
||||
|
||||
gdouble hybridBigScreenScale;
|
||||
};
|
||||
|
||||
static DrawParams draw_params = {false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0.0};
|
||||
|
||||
static void UpdateDrawingAreaAspect()
|
||||
{
|
||||
gint H, W;
|
||||
|
@ -1202,11 +1258,16 @@ static void UpdateDrawingAreaAspect()
|
|||
}
|
||||
|
||||
if (nds_screen.orientation != ORIENT_SINGLE) {
|
||||
if (nds_screen.orientation == ORIENT_VERTICAL) {
|
||||
if ((nds_screen.orientation == ORIENT_VERTICAL) || (nds_screen.orientation == ORIENT_HYBRID_EQUAL) ||
|
||||
(nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) {
|
||||
if ((nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180)) {
|
||||
H += nds_screen.gap_size;
|
||||
if((nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL))
|
||||
W = (W * 2.0/3.0) * (double)(H + nds_screen.gap_size) / (double)H + W / 3.0;
|
||||
H += nds_screen.gap_size;
|
||||
} else {
|
||||
W += nds_screen.gap_size;
|
||||
if((nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL))
|
||||
H = (H * 2.0/3.0) * (double)(W + nds_screen.gap_size) / (double)W + H / 3.0;
|
||||
W += nds_screen.gap_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1219,6 +1280,8 @@ static void UpdateDrawingAreaAspect()
|
|||
gtk_window_set_resizable(GTK_WINDOW(pWindow), FALSE);
|
||||
gtk_widget_set_size_request(GTK_WIDGET(pDrawingArea), W * winsize_current / 2, H * winsize_current / 2);
|
||||
}
|
||||
|
||||
draw_params.valid = false;
|
||||
}
|
||||
|
||||
static void ToggleGap(GSimpleAction *action, GVariant *parameter, gpointer user_data)
|
||||
|
@ -1282,9 +1345,15 @@ static void SetOrientation(GSimpleAction *action, GVariant *parameter, gpointer
|
|||
orient = ORIENT_HORIZONTAL;
|
||||
else if(strcmp(string, "single") == 0)
|
||||
orient = ORIENT_SINGLE;
|
||||
else if(strcmp(string, "hybrid_equal") == 0)
|
||||
orient = ORIENT_HYBRID_EQUAL;
|
||||
else if(strcmp(string, "hybrid_vertical") == 0)
|
||||
orient = ORIENT_HYBRID_VERTICAL;
|
||||
nds_screen.orientation = orient;
|
||||
#ifdef HAVE_LIBAGG
|
||||
osd->singleScreen = nds_screen.orientation == ORIENT_SINGLE;
|
||||
bool hybrid = (nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL);
|
||||
osd->swapScreens = nds_screen.swap && !hybrid;
|
||||
#endif
|
||||
config.view_orient = nds_screen.orientation;
|
||||
UpdateDrawingAreaAspect();
|
||||
|
@ -1296,7 +1365,8 @@ static void ToggleSwapScreens(GSimpleAction *action, GVariant *parameter, gpoint
|
|||
gboolean value = !g_variant_get_boolean(variant);
|
||||
nds_screen.swap = value;
|
||||
#ifdef HAVE_LIBAGG
|
||||
osd->swapScreens = nds_screen.swap;
|
||||
bool hybrid = (nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL);
|
||||
osd->swapScreens = nds_screen.swap && !hybrid;
|
||||
#endif
|
||||
config.view_swap = nds_screen.swap;
|
||||
RedrawScreen();
|
||||
|
@ -1310,7 +1380,8 @@ static int ConfigureDrawingArea(GtkWidget *widget, GdkEventConfigure *event, gpo
|
|||
|
||||
static inline void gpu_screen_to_rgb(u32* dst)
|
||||
{
|
||||
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(GPU->GetDisplayInfo().masterNativeBuffer16, dst, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2);
|
||||
ColorspaceConvertBuffer555To8888Opaque<false, false, BESwapDst>(GPU->GetDisplayInfo().isCustomSizeRequested ? (u16*)(GPU->GetDisplayInfo().masterCustomBuffer) : GPU->GetDisplayInfo().masterNativeBuffer16,
|
||||
dst, real_framebuffer_width * real_framebuffer_height * 2);
|
||||
}
|
||||
|
||||
static inline void drawScreen(cairo_t* cr, u32* buf, gint w, gint h) {
|
||||
|
@ -1339,6 +1410,17 @@ static inline void drawTopScreen(cairo_t* cr, u32* buf, gint w, gint h, gint gap
|
|||
cairo_translate(cr, w, 0);
|
||||
}
|
||||
break;
|
||||
case ORIENT_HYBRID_EQUAL:
|
||||
case ORIENT_HYBRID_VERTICAL:
|
||||
if (!swap && (draw_params.hybridBigScreenScale > 0.0)) {
|
||||
cairo_save(cr);
|
||||
cairo_scale(cr, draw_params.hybridBigScreenScale, draw_params.hybridBigScreenScale);
|
||||
cairo_get_matrix(cr, &nds_screen.topscreen_matrix_hybrid);
|
||||
drawScreen(cr, buf, w, h);
|
||||
cairo_restore(cr);
|
||||
}
|
||||
cairo_translate(cr, w * draw_params.hybridBigScreenScale, 0);
|
||||
break;
|
||||
}
|
||||
// Used for HUD editor mode
|
||||
cairo_get_matrix(cr, &nds_screen.topscreen_matrix);
|
||||
|
@ -1362,6 +1444,19 @@ static inline void drawBottomScreen(cairo_t* cr, u32* buf, gint w, gint h, gint
|
|||
cairo_translate(cr, w, 0);
|
||||
}
|
||||
break;
|
||||
case ORIENT_HYBRID_EQUAL:
|
||||
case ORIENT_HYBRID_VERTICAL:
|
||||
if (swap && (draw_params.hybridBigScreenScale > 0.0)) {
|
||||
cairo_save(cr);
|
||||
if(orientation == ORIENT_HYBRID_VERTICAL)
|
||||
cairo_translate(cr, 0, h * (2.0 - draw_params.hybridBigScreenScale) + gap);
|
||||
cairo_scale(cr, draw_params.hybridBigScreenScale, draw_params.hybridBigScreenScale);
|
||||
cairo_get_matrix(cr, &nds_screen.touch_matrix_hybrid);
|
||||
drawScreen(cr, buf, w, h);
|
||||
cairo_restore(cr);
|
||||
}
|
||||
cairo_translate(cr, w * draw_params.hybridBigScreenScale, h + gap);
|
||||
break;
|
||||
}
|
||||
// Store the matrix for converting touchscreen coordinates
|
||||
cairo_get_matrix(cr, &nds_screen.touch_matrix);
|
||||
|
@ -1369,6 +1464,21 @@ static inline void drawBottomScreen(cairo_t* cr, u32* buf, gint w, gint h, gint
|
|||
cairo_restore(cr);
|
||||
}
|
||||
|
||||
static void calc_hybrid_vertical_params(gint daW, gint daH, gint gap, gint dstScale, gint & imgW, gint & imgH)
|
||||
{
|
||||
gdouble hyb_hratio1, hyb_hratio2, hyb_vratio1, hyb_vratio2, hyb_ratio1, hyb_ratio2;
|
||||
hyb_hratio1 = (gdouble)daW / (gdouble)(GPU_FRAMEBUFFER_NATIVE_WIDTH * dstScale / 2);
|
||||
hyb_vratio1 = (gdouble)daH / (gdouble)(GPU_FRAMEBUFFER_NATIVE_HEIGHT * dstScale + gap);
|
||||
hyb_ratio1 = MIN(hyb_hratio1, hyb_vratio1);
|
||||
gint w_rem = daW - GPU_FRAMEBUFFER_NATIVE_WIDTH * dstScale / 2.0 * hyb_ratio1;
|
||||
hyb_hratio2 = (gdouble)w_rem / (gdouble)(GPU_FRAMEBUFFER_NATIVE_WIDTH * dstScale / 2);
|
||||
hyb_vratio2 = (gdouble)daH / (gdouble)(GPU_FRAMEBUFFER_NATIVE_HEIGHT * dstScale / 2);
|
||||
hyb_ratio2 = MIN(hyb_hratio2, hyb_vratio2);
|
||||
imgW = GPU_FRAMEBUFFER_NATIVE_WIDTH * dstScale / 2 * (1.0 + hyb_ratio2 / hyb_ratio1);
|
||||
imgH = GPU_FRAMEBUFFER_NATIVE_HEIGHT * dstScale + gap;
|
||||
draw_params.hybridBigScreenScale = hyb_ratio2 / hyb_ratio1;
|
||||
}
|
||||
|
||||
/* Drawing callback */
|
||||
static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpointer data)
|
||||
{
|
||||
|
@ -1383,51 +1493,96 @@ static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpo
|
|||
u32* fbuf = video->GetDstBufferPtr();
|
||||
gint dstW = video->GetDstWidth();
|
||||
gint dstH = video->GetDstHeight();
|
||||
|
||||
gint dstScale = dstW * 2 / 256; // Actual scale * 2 to handle 1.5x filters
|
||||
|
||||
gint gap = nds_screen.orientation == ORIENT_VERTICAL ? nds_screen.gap_size * dstScale / 2 : 0;
|
||||
gint imgW, imgH;
|
||||
if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180) {
|
||||
imgW = screen_size[nds_screen.orientation].width * dstScale / 2;
|
||||
imgH = screen_size[nds_screen.orientation].height * dstScale / 2 + gap;
|
||||
} else {
|
||||
imgH = screen_size[nds_screen.orientation].width * dstScale / 2;
|
||||
imgW = screen_size[nds_screen.orientation].height * dstScale / 2 + gap;
|
||||
if(draw_params.valid)
|
||||
if(draw_params.daW != daW || draw_params.daH != daH || draw_params.dstW != dstW || draw_params.dstH != dstH)
|
||||
draw_params.valid = false;
|
||||
|
||||
if(!draw_params.valid) {
|
||||
draw_params.daW = daW;
|
||||
draw_params.daH = daH;
|
||||
draw_params.dstW = dstW;
|
||||
draw_params.dstH = dstH;
|
||||
|
||||
draw_params.dstScale = dstW * 2 / GPU_FRAMEBUFFER_NATIVE_WIDTH; // Actual scale * 2 to handle 1.5x filters
|
||||
|
||||
draw_params.gap = ((nds_screen.orientation == ORIENT_VERTICAL) || (nds_screen.orientation == ORIENT_HYBRID_EQUAL)
|
||||
|| (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) ? nds_screen.gap_size * draw_params.dstScale / 2 : 0;
|
||||
if(nds_screen.orientation == ORIENT_HYBRID_VERTICAL) {
|
||||
if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180)
|
||||
calc_hybrid_vertical_params(daW, daH, draw_params.gap, draw_params.dstScale, draw_params.imgW, draw_params.imgH);
|
||||
else
|
||||
calc_hybrid_vertical_params(daH, daW, draw_params.gap, draw_params.dstScale, draw_params.imgH, draw_params.imgW);
|
||||
}
|
||||
else {
|
||||
if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180) {
|
||||
draw_params.imgW = screen_size[nds_screen.orientation].width * draw_params.dstScale / 2;
|
||||
draw_params.imgH = screen_size[nds_screen.orientation].height * draw_params.dstScale / 2 + draw_params.gap;
|
||||
if(nds_screen.orientation == ORIENT_HYBRID_EQUAL)
|
||||
draw_params.imgW = (draw_params.imgW * 2.0/3.0) * (double)draw_params.imgH /
|
||||
(double)(draw_params.imgH - draw_params.gap) + draw_params.imgW / 3.0;
|
||||
} else {
|
||||
draw_params.imgH = screen_size[nds_screen.orientation].width * draw_params.dstScale / 2;
|
||||
draw_params.imgW = screen_size[nds_screen.orientation].height * draw_params.dstScale / 2 + draw_params.gap;
|
||||
if(nds_screen.orientation == ORIENT_HYBRID_EQUAL)
|
||||
draw_params.imgH = (draw_params.imgH * 2.0/3.0) * (double)draw_params.imgW /
|
||||
(double)(draw_params.imgW - draw_params.gap) + draw_params.imgH / 3.0;
|
||||
}
|
||||
if(nds_screen.orientation == ORIENT_HYBRID_EQUAL)
|
||||
draw_params.hybridBigScreenScale = (double)(dstH + draw_params.gap) / (double)(dstH / 2);
|
||||
}
|
||||
|
||||
// Calculate scale to fit display area to window
|
||||
gfloat hratio = (gfloat)daW / (gfloat)draw_params.imgW;
|
||||
gfloat vratio = (gfloat)daH / (gfloat)draw_params.imgH;
|
||||
draw_params.ratio = MIN(hratio, vratio);
|
||||
|
||||
draw_params.gapOffset = 0;
|
||||
switch(nds_screen.orientation) {
|
||||
case ORIENT_HYBRID_EQUAL:
|
||||
draw_params.gapOffset = dstW * ((gdouble)(dstH + draw_params.gap) / (dstH / 2.0));
|
||||
break;
|
||||
case ORIENT_HYBRID_VERTICAL:
|
||||
draw_params.gapOffset = dstW * draw_params.hybridBigScreenScale;
|
||||
break;
|
||||
}
|
||||
|
||||
draw_params.valid = true;
|
||||
}
|
||||
|
||||
// Calculate scale to fit display area to window
|
||||
gfloat hratio = (gfloat)daW / (gfloat)imgW;
|
||||
gfloat vratio = (gfloat)daH / (gfloat)imgH;
|
||||
hratio = MIN(hratio, vratio);
|
||||
vratio = hratio;
|
||||
|
||||
GdkDrawingContext *context = gdk_window_begin_draw_frame(window, gdk_window_get_clip_region(window));
|
||||
cairo_t* cr = gdk_drawing_context_get_cairo_context(context);
|
||||
|
||||
// Scale to window size at center of area
|
||||
cairo_translate(cr, daW / 2, daH / 2);
|
||||
cairo_scale(cr, hratio, vratio);
|
||||
cairo_scale(cr, draw_params.ratio, draw_params.ratio);
|
||||
// Rotate area
|
||||
cairo_rotate(cr, M_PI / 180 * nds_screen.rotation_angle);
|
||||
// Translate area to top-left corner
|
||||
if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180) {
|
||||
cairo_translate(cr, -imgW / 2, -imgH / 2);
|
||||
cairo_translate(cr, -draw_params.imgW / 2, -draw_params.imgH / 2);
|
||||
} else {
|
||||
cairo_translate(cr, -imgH / 2, -imgW / 2);
|
||||
cairo_translate(cr, -draw_params.imgH / 2, -draw_params.imgW / 2);
|
||||
}
|
||||
// Draw both screens
|
||||
drawTopScreen(cr, fbuf, dstW, dstH / 2, gap, nds_screen.rotation_angle, nds_screen.swap, nds_screen.orientation);
|
||||
drawBottomScreen(cr, fbuf + dstW * dstH / 2, dstW, dstH / 2, gap, nds_screen.rotation_angle, nds_screen.swap, nds_screen.orientation);
|
||||
drawTopScreen(cr, fbuf, dstW, dstH / 2, draw_params.gap, nds_screen.rotation_angle, nds_screen.swap, nds_screen.orientation);
|
||||
drawBottomScreen(cr, fbuf + dstW * dstH / 2, dstW, dstH / 2, draw_params.gap, nds_screen.rotation_angle, nds_screen.swap, nds_screen.orientation);
|
||||
// Draw gap
|
||||
|
||||
cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
|
||||
cairo_rectangle(cr, 0, dstH / 2, dstW, gap);
|
||||
cairo_rectangle(cr, draw_params.gapOffset, dstH / 2, dstW, draw_params.gap);
|
||||
cairo_fill(cr);
|
||||
// Complete the touch transformation matrix
|
||||
cairo_matrix_scale(&nds_screen.topscreen_matrix, (double)dstScale / 2, (double)dstScale / 2);
|
||||
cairo_matrix_scale(&nds_screen.topscreen_matrix, (double)draw_params.dstScale / 2, (double)draw_params.dstScale / 2);
|
||||
cairo_matrix_invert(&nds_screen.topscreen_matrix);
|
||||
cairo_matrix_scale(&nds_screen.touch_matrix, (double)dstScale / 2, (double)dstScale / 2);
|
||||
cairo_matrix_scale(&nds_screen.touch_matrix, (double)draw_params.dstScale / 2, (double)draw_params.dstScale / 2);
|
||||
cairo_matrix_invert(&nds_screen.touch_matrix);
|
||||
if((nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) {
|
||||
cairo_matrix_scale(&nds_screen.topscreen_matrix_hybrid, (double)draw_params.dstScale / 2, (double)draw_params.dstScale / 2);
|
||||
cairo_matrix_invert(&nds_screen.topscreen_matrix_hybrid);
|
||||
cairo_matrix_scale(&nds_screen.touch_matrix_hybrid, (double)draw_params.dstScale / 2, (double)draw_params.dstScale / 2);
|
||||
cairo_matrix_invert(&nds_screen.touch_matrix_hybrid);
|
||||
}
|
||||
|
||||
gdk_window_end_draw_frame(window, context);
|
||||
draw_count++;
|
||||
|
@ -1436,9 +1591,11 @@ static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpo
|
|||
}
|
||||
|
||||
static void RedrawScreen() {
|
||||
ColorspaceConvertBuffer555To8888Opaque<true, false, BESwapDst>(GPU->GetDisplayInfo().masterNativeBuffer16, (uint32_t *)video->GetSrcBufferPtr(), GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2);
|
||||
ColorspaceConvertBuffer555To8888Opaque<true, false, BESwapDst>(
|
||||
GPU->GetDisplayInfo().isCustomSizeRequested ? (u16*)(GPU->GetDisplayInfo().masterCustomBuffer) : GPU->GetDisplayInfo().masterNativeBuffer16,
|
||||
(uint32_t *)video->GetSrcBufferPtr(), real_framebuffer_width * real_framebuffer_height * 2);
|
||||
#ifdef HAVE_LIBAGG
|
||||
aggDraw.hud->attach((u8*)video->GetSrcBufferPtr(), 256, 384, 1024);
|
||||
aggDraw.hud->setDrawTargetDims((u8*)video->GetSrcBufferPtr(), real_framebuffer_width, real_framebuffer_height * 2, real_framebuffer_width * 4);
|
||||
osd->update();
|
||||
DrawHUD();
|
||||
osd->clear();
|
||||
|
@ -1449,44 +1606,91 @@ static void RedrawScreen() {
|
|||
|
||||
/////////////////////////////// KEYS AND STYLUS UPDATE ///////////////////////////////////////
|
||||
|
||||
static bool move_started_in_big_screen = false;
|
||||
static bool hud_move_started_in_big_screen = false;
|
||||
|
||||
#ifdef HAVE_LIBAGG
|
||||
static gboolean rotoscaled_hudedit(gint x, gint y, gboolean start)
|
||||
{
|
||||
double devX, devY;
|
||||
gint X, Y, topX = -1, topY = -1, botX = -1, botY = -1;
|
||||
gint X, Y, topX = -1, topY = -1, botX = -1, botY = -1, hybTopX = -1, hybTopY = -1, hybBotX = -1, hybBotY = -1;
|
||||
static gint startScreen = 0;
|
||||
bool hybrid = ((nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) &&
|
||||
(draw_params.hybridBigScreenScale > 0.0);
|
||||
|
||||
if (nds_screen.orientation != ORIENT_SINGLE || !nds_screen.swap) {
|
||||
devX = x;
|
||||
devY = y;
|
||||
cairo_matrix_transform_point(&nds_screen.topscreen_matrix, &devX, &devY);
|
||||
topX = devX;
|
||||
topY = devY;
|
||||
topX = devX * gpu_scale_factor;
|
||||
topY = devY * gpu_scale_factor;
|
||||
|
||||
if(hybrid && !nds_screen.swap) {
|
||||
devX = x;
|
||||
devY = y;
|
||||
cairo_matrix_transform_point(&nds_screen.topscreen_matrix_hybrid, &devX, &devY);
|
||||
hybTopX = devX * gpu_scale_factor;
|
||||
hybTopY = devY * gpu_scale_factor;
|
||||
}
|
||||
}
|
||||
|
||||
if (nds_screen.orientation != ORIENT_SINGLE || nds_screen.swap) {
|
||||
devX = x;
|
||||
devY = y;
|
||||
cairo_matrix_transform_point(&nds_screen.touch_matrix, &devX, &devY);
|
||||
botX = devX;
|
||||
botY = devY;
|
||||
botX = devX * gpu_scale_factor;
|
||||
botY = devY * gpu_scale_factor;
|
||||
|
||||
if(hybrid && nds_screen.swap) {
|
||||
devX = x;
|
||||
devY = y;
|
||||
cairo_matrix_transform_point(&nds_screen.touch_matrix_hybrid, &devX, &devY);
|
||||
hybBotX = devX * gpu_scale_factor;
|
||||
hybBotY = devY * gpu_scale_factor;
|
||||
}
|
||||
}
|
||||
|
||||
if (topX >= 0 && topY >= 0 && topX < 256 && topY < 192) {
|
||||
if (topX >= 0 && topY >= 0 && topX < real_framebuffer_width && topY < real_framebuffer_height) {
|
||||
X = topX;
|
||||
Y = topY + (nds_screen.swap ? 192 : 0);
|
||||
Y = topY + (osd->swapScreens ? real_framebuffer_height : 0);
|
||||
startScreen = 0;
|
||||
} else if (botX >= 0 && botY >= 0 && botX < 256 && botY < 192) {
|
||||
if(start)
|
||||
hud_move_started_in_big_screen = false;
|
||||
} else if (hybTopX >= 0 && hybTopY >= 0 && hybTopX < real_framebuffer_width && hybTopY < real_framebuffer_height) {
|
||||
X = hybTopX;
|
||||
Y = hybTopY;
|
||||
startScreen = 0;
|
||||
if(start)
|
||||
hud_move_started_in_big_screen = true;
|
||||
} else if (botX >= 0 && botY >= 0 && botX < real_framebuffer_width && botY < real_framebuffer_height) {
|
||||
X = botX;
|
||||
Y = botY + (nds_screen.swap ? 0 : 192);
|
||||
Y = botY + (osd->swapScreens ? 0 : real_framebuffer_height);
|
||||
startScreen = 1;
|
||||
if(start)
|
||||
hud_move_started_in_big_screen = false;
|
||||
} else if (hybBotX >= 0 && hybBotY >= 0 && hybBotX < real_framebuffer_width && hybBotY < real_framebuffer_height) {
|
||||
X = hybBotX;
|
||||
Y = hybBotY + real_framebuffer_height;
|
||||
startScreen = 1;
|
||||
if(start)
|
||||
hud_move_started_in_big_screen = true;
|
||||
} else if (!start) {
|
||||
if (startScreen == 0) {
|
||||
X = CLAMP(topX, 0, 255);
|
||||
Y = CLAMP(topY, 0, 191) + (nds_screen.swap ? 192 : 0);
|
||||
if(!hud_move_started_in_big_screen || !hybrid) {
|
||||
X = CLAMP(topX, 0, real_framebuffer_width-1);
|
||||
Y = CLAMP(topY, 0, real_framebuffer_height-1) + (osd->swapScreens ? real_framebuffer_height : 0);
|
||||
} else {
|
||||
X = CLAMP(hybTopX, 0, real_framebuffer_width-1);
|
||||
Y = CLAMP(hybTopY, 0, real_framebuffer_height-1);
|
||||
}
|
||||
} else {
|
||||
X = CLAMP(botX, 0, 255);
|
||||
Y = CLAMP(botY, 0, 191) + (nds_screen.swap ? 0 : 192);
|
||||
if(!hud_move_started_in_big_screen || !hybrid) {
|
||||
X = CLAMP(botX, 0, real_framebuffer_width-1);
|
||||
Y = CLAMP(botY, 0, real_framebuffer_height-1) + (osd->swapScreens ? 0 : real_framebuffer_height);
|
||||
} else {
|
||||
X = CLAMP(hybBotX, 0, real_framebuffer_width-1);
|
||||
Y = CLAMP(hybBotY, 0, real_framebuffer_height-1) + real_framebuffer_height;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG("TopX=%d, TopY=%d, BotX=%d, BotY=%d\n", topX, topY, botX, botY);
|
||||
|
@ -1518,13 +1722,33 @@ static gboolean rotoscaled_touchpos(gint x, gint y, gboolean start)
|
|||
|
||||
LOG("X=%d, Y=%d\n", X, Y);
|
||||
|
||||
if (!start || (X >= 0 && Y >= 0 && X < 256 && Y < 192)) {
|
||||
if ((!start && !move_started_in_big_screen) || (X >= 0 && Y >= 0 && X < 256 && Y < 192)) {
|
||||
if(start)
|
||||
move_started_in_big_screen = false;
|
||||
EmuX = CLAMP(X, 0, 255);
|
||||
EmuY = CLAMP(Y, 0, 191);
|
||||
NDS_setTouchPos(EmuX, EmuY);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
if((((nds_screen.orientation == ORIENT_HYBRID_EQUAL) ||
|
||||
(nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) && (draw_params.hybridBigScreenScale > 0.0)) && (nds_screen.swap)) {
|
||||
devX = x;
|
||||
devY = y;
|
||||
cairo_matrix_transform_point(&nds_screen.touch_matrix_hybrid, &devX, &devY);
|
||||
X = devX;
|
||||
Y = devY;
|
||||
|
||||
if ((!start && move_started_in_big_screen) || (X >= 0 && Y >= 0 && X < 256 && Y < 192)) {
|
||||
if(start)
|
||||
move_started_in_big_screen = true;
|
||||
EmuX = CLAMP(X, 0, 255);
|
||||
EmuY = CLAMP(Y, 0, 191);
|
||||
NDS_setTouchPos(EmuX, EmuY);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -1989,12 +2213,16 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g
|
|||
GtkGrid *wGrid;
|
||||
GtkComboBox *coreCombo, *wScale, *wMultisample;
|
||||
GtkToggleButton *wPosterize, *wSmoothing, *wHCInterpolate;
|
||||
GtkSpinButton *wGPUScale;
|
||||
|
||||
GtkBuilder *builder = gtk_builder_new_from_resource("/org/desmume/DeSmuME/graphics.ui");
|
||||
dialog = GTK_DIALOG(gtk_builder_get_object(builder, "dialog"));
|
||||
wGrid = GTK_GRID(gtk_builder_get_object(builder, "graphics_grid"));
|
||||
coreCombo = GTK_COMBO_BOX(gtk_builder_get_object(builder, "core_combo"));
|
||||
wScale = GTK_COMBO_BOX(gtk_builder_get_object(builder, "scale"));
|
||||
wGPUScale = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "gpuscale"));
|
||||
gtk_spin_button_set_range(wGPUScale, GPU_SCALE_FACTOR_MIN, GPU_SCALE_FACTOR_MAX);
|
||||
gtk_spin_button_set_increments(wGPUScale, 1.0, 1.0);
|
||||
wMultisample = GTK_COMBO_BOX(gtk_builder_get_object(builder, "multisample"));
|
||||
wPosterize = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "posterize"));
|
||||
wSmoothing = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "smoothing"));
|
||||
|
@ -2010,6 +2238,9 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g
|
|||
// The shift it work for scale up to 4. For scaling more than 4, a mapping function is required
|
||||
gtk_combo_box_set_active(wScale, CommonSettings.GFX3D_Renderer_TextureScalingFactor >> 1);
|
||||
|
||||
//GPU scaling factor
|
||||
gtk_spin_button_set_value(wGPUScale, gpu_scale_factor);
|
||||
|
||||
// 3D Texture Deposterization
|
||||
gtk_toggle_button_set_active(wPosterize, CommonSettings.GFX3D_Renderer_TextureDeposterize);
|
||||
|
||||
|
@ -2080,6 +2311,33 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g
|
|||
default:
|
||||
break;
|
||||
}
|
||||
double old_scale_factor = gpu_scale_factor;
|
||||
gpu_scale_factor = gtk_spin_button_get_value(wGPUScale);
|
||||
if(gpu_scale_factor < GPU_SCALE_FACTOR_MIN)
|
||||
gpu_scale_factor = GPU_SCALE_FACTOR_MIN;
|
||||
if(gpu_scale_factor > GPU_SCALE_FACTOR_MAX)
|
||||
gpu_scale_factor = GPU_SCALE_FACTOR_MAX;
|
||||
gtk_spin_button_set_value(wGPUScale, gpu_scale_factor);
|
||||
config.gpuScaleFactor = gpu_scale_factor;
|
||||
real_framebuffer_width = GPU_FRAMEBUFFER_NATIVE_WIDTH * gpu_scale_factor;
|
||||
real_framebuffer_height = GPU_FRAMEBUFFER_NATIVE_HEIGHT * gpu_scale_factor;
|
||||
GPU->SetCustomFramebufferSize(real_framebuffer_width, real_framebuffer_height);
|
||||
video->SetSourceSize(real_framebuffer_width, real_framebuffer_height * 2);
|
||||
#ifdef HAVE_LIBAGG
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
if(vectorFontFile.size() > 0)
|
||||
{
|
||||
aggDraw.hud->setVectorFont(vectorFontFile, VECTOR_FONT_BASE_SIZE * gpu_scale_factor, true);
|
||||
osd->useVectorFonts=(gpu_scale_factor >= 1.1);
|
||||
}
|
||||
else
|
||||
osd->useVectorFonts=false;
|
||||
#endif
|
||||
Agg_setCustomSize(real_framebuffer_width, real_framebuffer_height*2);
|
||||
osd->scale=gpu_scale_factor;
|
||||
Hud.rescale(old_scale_factor, gpu_scale_factor);
|
||||
HudSaveLayout();
|
||||
#endif
|
||||
CommonSettings.GFX3D_Renderer_TextureDeposterize = config.textureDeposterize = gtk_toggle_button_get_active(wPosterize);
|
||||
CommonSettings.GFX3D_Renderer_TextureSmoothing = config.textureSmoothing = gtk_toggle_button_get_active(wSmoothing);
|
||||
CommonSettings.GFX3D_Renderer_TextureScalingFactor = config.textureUpscale = scale;
|
||||
|
@ -2140,7 +2398,7 @@ static void Printscreen(GSimpleAction *action, GVariant *parameter, gpointer use
|
|||
const gchar *dir;
|
||||
gchar *filename = NULL, *filen = NULL;
|
||||
GError *error = NULL;
|
||||
u8 rgb[256 * 384 * 4];
|
||||
u8 *rgb = (u8*)malloc(real_framebuffer_width * real_framebuffer_height * 2 * 4);
|
||||
static int seq = 0;
|
||||
gint H, W;
|
||||
|
||||
|
@ -2149,11 +2407,11 @@ static void Printscreen(GSimpleAction *action, GVariant *parameter, gpointer use
|
|||
// return;
|
||||
|
||||
if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180) {
|
||||
W = screen_size[nds_screen.orientation].width;
|
||||
H = screen_size[nds_screen.orientation].height;
|
||||
W = real_framebuffer_width;
|
||||
H = real_framebuffer_height * 2;
|
||||
} else {
|
||||
W = screen_size[nds_screen.orientation].height;
|
||||
H = screen_size[nds_screen.orientation].width;
|
||||
W = real_framebuffer_height * 2;
|
||||
H = real_framebuffer_width;
|
||||
}
|
||||
|
||||
gpu_screen_to_rgb((u32*)rgb);
|
||||
|
@ -2190,7 +2448,7 @@ static void Printscreen(GSimpleAction *action, GVariant *parameter, gpointer use
|
|||
seq--;
|
||||
}
|
||||
|
||||
//free(rgb);
|
||||
free(rgb);
|
||||
g_object_unref(screenshot);
|
||||
g_free(filename);
|
||||
g_free(filen);
|
||||
|
@ -2744,6 +3002,8 @@ static void ToggleHudDisplay(hud_display_enum hudId, gboolean active)
|
|||
break;
|
||||
case HUD_DISPLAY_EDITOR:
|
||||
HudEditorMode = active;
|
||||
if(!active)
|
||||
HudSaveLayout();
|
||||
break;
|
||||
default:
|
||||
g_printerr("Unknown HUD toggle %u!", hudId);
|
||||
|
@ -2770,6 +3030,60 @@ HudMacro(HudRtc, HUD_DISPLAY_RTC)
|
|||
HudMacro(HudMic, HUD_DISPLAY_MIC)
|
||||
HudMacro(HudEditor, HUD_DISPLAY_EDITOR)
|
||||
|
||||
static void HudResetLayout(GSimpleAction *action, GVariant *parameter, gpointer user_data)
|
||||
{
|
||||
Hud.reset();
|
||||
HudSaveLayout();
|
||||
}
|
||||
|
||||
static void HudSaveCoordsToVector(HudCoordinates* pCoords, int* pDest)
|
||||
{
|
||||
pDest[0]=pCoords->x;
|
||||
pDest[1]=pCoords->y;
|
||||
pDest[2]=pCoords->xsize;
|
||||
pDest[3]=pCoords->ysize;
|
||||
}
|
||||
|
||||
static void HudLoadCoordsFromVector(HudCoordinates* pCoords, int* pSrc)
|
||||
{
|
||||
pCoords->x=pSrc[0];
|
||||
pCoords->y=pSrc[1];
|
||||
pCoords->xsize=pSrc[2];
|
||||
pCoords->ysize=pSrc[3];
|
||||
}
|
||||
|
||||
static void HudSaveLayout()
|
||||
{
|
||||
std::vector<int> vec(8*4); //8 HudCoordinates
|
||||
HudSaveCoordsToVector(&Hud.SavestateSlots, vec.data());
|
||||
HudSaveCoordsToVector(&Hud.FpsDisplay, vec.data()+4);
|
||||
HudSaveCoordsToVector(&Hud.FrameCounter, vec.data()+8);
|
||||
HudSaveCoordsToVector(&Hud.InputDisplay, vec.data()+12);
|
||||
HudSaveCoordsToVector(&Hud.GraphicalInputDisplay, vec.data()+16);
|
||||
HudSaveCoordsToVector(&Hud.LagFrameCounter, vec.data()+20);
|
||||
HudSaveCoordsToVector(&Hud.Microphone, vec.data()+24);
|
||||
HudSaveCoordsToVector(&Hud.RTCDisplay, vec.data()+28);
|
||||
config.hud_layout=vec;
|
||||
}
|
||||
|
||||
static void HudLoadLayout()
|
||||
{
|
||||
std::vector<int> vec=config.hud_layout;
|
||||
if(vec.size()==8*4)
|
||||
{
|
||||
HudLoadCoordsFromVector(&Hud.SavestateSlots, vec.data());
|
||||
HudLoadCoordsFromVector(&Hud.FpsDisplay, vec.data()+4);
|
||||
HudLoadCoordsFromVector(&Hud.FrameCounter, vec.data()+8);
|
||||
HudLoadCoordsFromVector(&Hud.InputDisplay, vec.data()+12);
|
||||
HudLoadCoordsFromVector(&Hud.GraphicalInputDisplay, vec.data()+16);
|
||||
HudLoadCoordsFromVector(&Hud.LagFrameCounter, vec.data()+20);
|
||||
HudLoadCoordsFromVector(&Hud.Microphone, vec.data()+24);
|
||||
HudLoadCoordsFromVector(&Hud.RTCDisplay, vec.data()+28);
|
||||
}
|
||||
else
|
||||
Hud.reset();
|
||||
}
|
||||
|
||||
static void desmume_gtk_menu_view_hud(GtkApplication *app)
|
||||
{
|
||||
const struct {
|
||||
|
@ -2969,6 +3283,10 @@ common_gtk_main(GApplication *app, gpointer user_data)
|
|||
|
||||
/* Init the hud / osd stuff */
|
||||
#ifdef HAVE_LIBAGG
|
||||
SDL_DisplayMode cur_mode;
|
||||
if(!SDL_GetCurrentDisplayMode(0, &cur_mode))
|
||||
aggDraw.screenBytesPerPixel = SDL_BYTESPERPIXEL(cur_mode.format);
|
||||
|
||||
Desmume_InitOnce();
|
||||
Hud.reset();
|
||||
osd = new OSDCLASS(-1);
|
||||
|
@ -3026,8 +3344,32 @@ common_gtk_main(GApplication *app, gpointer user_data)
|
|||
memset(&nds_screen, 0, sizeof(nds_screen));
|
||||
nds_screen.orientation = ORIENT_VERTICAL;
|
||||
|
||||
gpu_scale_factor = config.gpuScaleFactor;
|
||||
if(gpu_scale_factor < GPU_SCALE_FACTOR_MIN)
|
||||
gpu_scale_factor = GPU_SCALE_FACTOR_MIN;
|
||||
if(gpu_scale_factor > GPU_SCALE_FACTOR_MAX)
|
||||
gpu_scale_factor = GPU_SCALE_FACTOR_MAX;
|
||||
config.gpuScaleFactor = gpu_scale_factor;
|
||||
real_framebuffer_width = GPU_FRAMEBUFFER_NATIVE_WIDTH * gpu_scale_factor;
|
||||
real_framebuffer_height = GPU_FRAMEBUFFER_NATIVE_HEIGHT * gpu_scale_factor;
|
||||
|
||||
g_printerr("Using %d threads for video filter.\n", CommonSettings.num_cores);
|
||||
video = new VideoFilter(256, 384, VideoFilterTypeID_None, CommonSettings.num_cores);
|
||||
GPU->SetCustomFramebufferSize(real_framebuffer_width, real_framebuffer_height);
|
||||
video = new VideoFilter(real_framebuffer_width, real_framebuffer_height * 2, VideoFilterTypeID_None, CommonSettings.num_cores);
|
||||
#ifdef HAVE_LIBAGG
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
if(vectorFontFile.size() > 0)
|
||||
{
|
||||
aggDraw.hud->setVectorFont(vectorFontFile, VECTOR_FONT_BASE_SIZE * gpu_scale_factor, true);
|
||||
osd->useVectorFonts=(gpu_scale_factor >= 1.1);
|
||||
}
|
||||
else
|
||||
osd->useVectorFonts=false;
|
||||
#endif
|
||||
Agg_setCustomSize(real_framebuffer_width, real_framebuffer_height*2);
|
||||
osd->scale=gpu_scale_factor;
|
||||
HudLoadLayout();
|
||||
#endif
|
||||
|
||||
/* Fetch the main elements from the window */
|
||||
GtkBuilder *builder = gtk_builder_new_from_resource("/org/desmume/DeSmuME/main.ui");
|
||||
|
@ -3305,7 +3647,7 @@ common_gtk_main(GApplication *app, gpointer user_data)
|
|||
}
|
||||
g_simple_action_set_state(G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "winsize")), g_variant_new_string(string.c_str()));
|
||||
|
||||
if (config.view_orient < ORIENT_VERTICAL || config.view_orient > ORIENT_SINGLE) {
|
||||
if (config.view_orient < ORIENT_VERTICAL || config.view_orient > ORIENT_HYBRID_VERTICAL) {
|
||||
config.view_orient = ORIENT_VERTICAL;
|
||||
}
|
||||
nds_screen.orientation = (orientation_enum)config.view_orient.get();
|
||||
|
@ -3319,6 +3661,12 @@ common_gtk_main(GApplication *app, gpointer user_data)
|
|||
case ORIENT_SINGLE:
|
||||
string = "single";
|
||||
break;
|
||||
case ORIENT_HYBRID_EQUAL:
|
||||
string = "hybrid_equal";
|
||||
break;
|
||||
case ORIENT_HYBRID_VERTICAL:
|
||||
string = "hybrid_vertical";
|
||||
break;
|
||||
}
|
||||
g_simple_action_set_state(G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "orient")), g_variant_new_string(string.c_str()));
|
||||
|
||||
|
@ -3339,6 +3687,10 @@ common_gtk_main(GApplication *app, gpointer user_data)
|
|||
nds_screen.gap_size = config.view_gap ? GAP_SIZE : 0;
|
||||
|
||||
nds_screen.swap = config.view_swap;
|
||||
#ifdef HAVE_LIBAGG
|
||||
bool hybrid = (nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL);
|
||||
osd->swapScreens = nds_screen.swap && !hybrid;
|
||||
#endif
|
||||
g_simple_action_set_state(G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "swapscreens")), g_variant_new_boolean(config.view_swap));
|
||||
|
||||
builder = gtk_builder_new_from_resource("/org/desmume/DeSmuME/menu.ui");
|
||||
|
@ -3562,7 +3914,9 @@ common_gtk_main(GApplication *app, gpointer user_data)
|
|||
|
||||
static void Teardown() {
|
||||
delete video;
|
||||
|
||||
#ifdef HAVE_LIBAGG
|
||||
HudSaveLayout();
|
||||
#endif
|
||||
config.save();
|
||||
avout_x264.end();
|
||||
avout_flac.end();
|
||||
|
@ -3605,10 +3959,46 @@ handle_open(GApplication *application,
|
|||
common_gtk_main(application, user_data);
|
||||
}
|
||||
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
|
||||
static std::string FindFontFile(const char* fontName, bool bold)
|
||||
{
|
||||
std::string fontFile;
|
||||
FcPattern* pat = FcNameParse((const FcChar8*)fontName);
|
||||
if(bold)
|
||||
FcPatternAddInteger(pat, FC_WEIGHT, FC_WEIGHT_BOLD);
|
||||
FcConfigSubstitute(fontConfig, pat, FcMatchPattern);
|
||||
FcDefaultSubstitute(pat);
|
||||
|
||||
// find the font
|
||||
FcResult res;
|
||||
FcPattern* font = FcFontMatch(fontConfig, pat, &res);
|
||||
if (font)
|
||||
{
|
||||
FcChar8* file = NULL;
|
||||
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch)
|
||||
{
|
||||
// save the file to another std::string
|
||||
fontFile = (char*)file;
|
||||
}
|
||||
FcPatternDestroy(font);
|
||||
}
|
||||
FcPatternDestroy(pat);
|
||||
return fontFile;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
configured_features my_config;
|
||||
|
||||
#ifdef AGG2D_USE_VECTORFONTS
|
||||
fontConfig = FcInitLoadConfigAndFonts();
|
||||
vectorFontFile = FindFontFile("mono", true);
|
||||
if(!vectorFontFile.size())
|
||||
vectorFontFile = FindFontFile("sans", true);
|
||||
#endif
|
||||
// The global menu screws up the window size...
|
||||
unsetenv("UBUNTU_MENUPROXY");
|
||||
|
||||
|
|
|
@ -254,6 +254,18 @@
|
|||
<attribute name='action'>app.orient</attribute>
|
||||
<attribute name='target'>single</attribute>
|
||||
<attribute name='accel'><Control>0</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name='label' translatable='yes'>Hybrid (_equal height)</attribute>
|
||||
<attribute name='action'>app.orient</attribute>
|
||||
<attribute name='target'>hybrid_equal</attribute>
|
||||
<attribute name='accel'><Control>3</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name='label' translatable='yes'>Hybrid (e_mphasize vertical)</attribute>
|
||||
<attribute name='action'>app.orient</attribute>
|
||||
<attribute name='target'>hybrid_vertical</attribute>
|
||||
<attribute name='accel'><Control>4</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
|
@ -834,6 +846,10 @@
|
|||
<attribute name='label' translatable='yes'>_Editor mode</attribute>
|
||||
<attribute name='action'>app.hud_editor</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name='label' translatable='yes'>Reset layout</attribute>
|
||||
<attribute name='action'>app.hud_reset_layout</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
<menu id='hud_unsupported'>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2009 Guillaume Duhamel
|
||||
Copyright (C) 2009-2017 DeSmuME team
|
||||
Copyright (C) 2009-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <GL/osmesa.h>
|
||||
#include "../OGLRender.h"
|
||||
#include "../OGLRender_3_2.h"
|
||||
|
||||
#include "osmesa_3Demu.h"
|
||||
|
|
|
@ -28,6 +28,9 @@ static bool sdl_init(void) { return is_sdl_initialized(); }
|
|||
static SDL_Window *win = NULL;
|
||||
static SDL_GLContext ctx = NULL;
|
||||
|
||||
extern int real_framebuffer_width;
|
||||
extern int real_framebuffer_height;
|
||||
|
||||
bool deinit_sdl_3Demu(void)
|
||||
{
|
||||
bool ret = false;
|
||||
|
@ -60,7 +63,8 @@ bool init_sdl_3Demu(void)
|
|||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||
|
||||
win = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 256, 192, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
|
||||
win = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, real_framebuffer_width,
|
||||
real_framebuffer_height, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
|
||||
if (!win) {
|
||||
fprintf(stderr, "SDL: Failed to create a window: %s\n", SDL_GetError());
|
||||
return false;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2007 Pascal Giard (evilynux)
|
||||
Copyright (C) 2006-2021 DeSmuME team
|
||||
Copyright (C) 2006-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -72,7 +72,6 @@
|
|||
|
||||
#ifdef HAVE_OPENGL
|
||||
#include <GL/gl.h>
|
||||
#include "OGLRender.h"
|
||||
#include "OGLRender_3_2.h"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2009 Guillaume Duhamel
|
||||
Copyright (C) 2009-2017 DeSmuME team
|
||||
Copyright (C) 2009-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <GL/osmesa.h>
|
||||
#include "../OGLRender.h"
|
||||
#include "../OGLRender_3_2.h"
|
||||
|
||||
#include "osmesa_3Demu.h"
|
||||
|
|
|
@ -20,6 +20,7 @@ dep_openal = dependency('openal', required: get_option('openal'))
|
|||
dep_alsa = dependency('alsa', required: false)
|
||||
dep_soundtouch = dependency('soundtouch', required: false)
|
||||
dep_agg = dependency('libagg', required: false)
|
||||
dep_fontconfig = dependency('fontconfig', required: false)
|
||||
|
||||
# XXX: something wrong with this one.
|
||||
#dep_lua = dependency('lua-5.1', required: false)
|
||||
|
@ -104,7 +105,7 @@ libdesmume_src = [
|
|||
'../../utils/tinyxml/tinyxmlerror.cpp',
|
||||
'../../utils/tinyxml/tinyxmlparser.cpp',
|
||||
'../../utils/colorspacehandler/colorspacehandler.cpp',
|
||||
'../../addons/slot2_auto.cpp', '../../addons/slot2_mpcf.cpp', '../../addons/slot2_paddle.cpp', '../../addons/slot2_gbagame.cpp', '../../addons/slot2_none.cpp', '../../addons/slot2_rumblepak.cpp', '../../addons/slot2_guitarGrip.cpp', '../../addons/slot2_expMemory.cpp', '../../addons/slot2_piano.cpp', '../../addons/slot2_passme.cpp', '../../addons/slot1_none.cpp', '../../addons/slot1_r4.cpp', '../../addons/slot1_retail_nand.cpp', '../../addons/slot1_retail_auto.cpp', '../../addons/slot1_retail_mcrom.cpp', '../../addons/slot1_retail_mcrom_debug.cpp', '../../addons/slot1comp_mc.cpp', '../../addons/slot1comp_rom.cpp', '../../addons/slot1comp_protocol.cpp',
|
||||
'../../addons/slot2_auto.cpp', '../../addons/slot2_mpcf.cpp', '../../addons/slot2_paddle.cpp', '../../addons/slot2_gbagame.cpp', '../../addons/slot2_none.cpp', '../../addons/slot2_rumblepak.cpp', '../../addons/slot2_guitarGrip.cpp', '../../addons/slot2_hcv1000.cpp', '../../addons/slot2_expMemory.cpp', '../../addons/slot2_piano.cpp', '../../addons/slot2_passme.cpp', '../../addons/slot1_none.cpp', '../../addons/slot1_r4.cpp', '../../addons/slot1_retail_nand.cpp', '../../addons/slot1_retail_auto.cpp', '../../addons/slot1_retail_mcrom.cpp', '../../addons/slot1_retail_mcrom_debug.cpp', '../../addons/slot1comp_mc.cpp', '../../addons/slot1comp_rom.cpp', '../../addons/slot1comp_protocol.cpp',
|
||||
'../../cheatSystem.cpp',
|
||||
'../../texcache.cpp', '../../rasterize.cpp',
|
||||
'../../metaspu/metaspu.cpp',
|
||||
|
@ -203,6 +204,11 @@ endif
|
|||
if dep_agg.found()
|
||||
dependencies += dep_agg
|
||||
add_global_arguments('-DHAVE_LIBAGG', language: ['c', 'cpp'])
|
||||
if dep_fontconfig.found()
|
||||
dependencies += dep_fontconfig
|
||||
add_global_arguments('-DAGG2D_USE_VECTORFONTS', language: ['c', 'cpp'])
|
||||
add_global_link_arguments('-laggfontfreetype', language: ['c', 'cpp'])
|
||||
endif
|
||||
libdesmume_src += [
|
||||
'../modules/osd/agg/aggdraw.cpp',
|
||||
'../modules/osd/agg/agg_osd.cpp',
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
<ClCompile Include="..\..\addons\slot1_retail_mcrom.cpp" />
|
||||
<ClCompile Include="..\..\addons\slot1_retail_mcrom_debug.cpp" />
|
||||
<ClCompile Include="..\..\addons\slot2_auto.cpp" />
|
||||
<ClCompile Include="..\..\addons\slot2_hcv1000.cpp" />
|
||||
<ClCompile Include="..\..\addons\slot2_passme.cpp" />
|
||||
<ClCompile Include="..\..\addons\slot2_piano.cpp" />
|
||||
<ClCompile Include="..\..\addons\slot1_none.cpp" />
|
||||
|
|
|
@ -930,6 +930,9 @@
|
|||
<ClCompile Include="display.cpp">
|
||||
<Filter>frontend\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\addons\slot2_hcv1000.cpp">
|
||||
<Filter>addons</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\utils\guid.h">
|
||||
|
|
|
@ -1534,13 +1534,13 @@ INT_PTR CALLBACK CheatsExportProc(HWND dialog, UINT msg,WPARAM wparam,LPARAM lpa
|
|||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
SetWindowText(GetDlgItem(dialog, IDC_CDATE), (LPCSTR)cheatsExport->date);
|
||||
if (cheatsExport->gametitle && strlen((char*)cheatsExport->gametitle) > 0)
|
||||
SetWindowText(GetDlgItem(dialog, IDC_CDATE), (LPCSTR)cheatsExport->getDescription());
|
||||
if ( strlen(cheatsExport->getGameTitle()) > 0 )
|
||||
{
|
||||
char buf[512] = {0};
|
||||
GetWindowText(dialog, &buf[0], sizeof(buf));
|
||||
strcat(buf, ": ");
|
||||
strcat(buf, (char*)cheatsExport->gametitle);
|
||||
strcat(buf, cheatsExport->getGameTitle());
|
||||
SetWindowText(dialog, (LPCSTR)buf);
|
||||
}
|
||||
LV_COLUMN lvColumn;
|
||||
|
@ -1639,19 +1639,31 @@ bool CheatsExportDialog(HWND hwnd)
|
|||
else
|
||||
{
|
||||
char buf2[512] = {0};
|
||||
if (cheatsExport->getErrorCode() == 1)
|
||||
sprintf(buf2, "Error loading cheats database. File not found\n\"%s\"\nCheck your path (Menu->Config->Path Settings->\"Cheats\")\n\nYou can download it from http://www.codemasters-project.net/vb/forumdisplay.php?44-Nintendo-DS", buf);
|
||||
else
|
||||
if (cheatsExport->getErrorCode() == 2)
|
||||
CheatSystemError theError = cheatsExport->getErrorCode();
|
||||
|
||||
switch (theError)
|
||||
{
|
||||
case CheatSystemError_FileOpenFailed:
|
||||
sprintf(buf2, "Error loading cheats database. File not found\n\"%s\"\nCheck your path (Menu->Config->Path Settings->\"Cheats\")\n\nYou can download it from http://www.codemasters-project.net/vb/forumdisplay.php?44-Nintendo-DS", buf);
|
||||
break;
|
||||
|
||||
case CheatSystemError_FileFormatInvalid:
|
||||
sprintf(buf2, "File \"%s\" is not R4 cheats database.\nWrong file format!", buf);
|
||||
else
|
||||
if (cheatsExport->getErrorCode() == 3)
|
||||
sprintf(buf2, "CRC %8X not found in database.", gameInfo.crcForCheatsDb);
|
||||
else
|
||||
if (cheatsExport->getErrorCode() == 4)
|
||||
sprintf(buf2, "Error export from database");
|
||||
else
|
||||
sprintf(buf2, "Unknown error!!!");
|
||||
break;
|
||||
|
||||
case CheatSystemError_GameNotFound:
|
||||
sprintf(buf2, "CRC %8X not found in database.", gameInfo.crcForCheatsDb);
|
||||
break;
|
||||
|
||||
case CheatSystemError_LoadEntryError:
|
||||
sprintf(buf2, "Error export from database");
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(buf2, "Unknown error!!!");
|
||||
break;
|
||||
}
|
||||
|
||||
MessageBox(hwnd, buf2, "DeSmuME", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2009-2016 DeSmuME team
|
||||
Copyright (C) 2009-2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -36,12 +36,14 @@ u8 last_type = 0;
|
|||
char tmp_cflash_filename[MAX_PATH] = { 0 };
|
||||
char tmp_cflash_path[MAX_PATH] = { 0 };
|
||||
char tmp_gbagame_filename[MAX_PATH] = { 0 };
|
||||
char tmp_hcv1000_barcode[17] = { 0 };
|
||||
ADDON_CFLASH_MODE tmp_CFlashMode = ADDON_CFLASH_MODE_RomPath;
|
||||
HWND OKbutton = NULL;
|
||||
bool _OKbutton = false;
|
||||
SGuitar tmp_Guitar;
|
||||
SPiano tmp_Piano;
|
||||
SPaddle tmp_Paddle;
|
||||
SHCV1000 tmp_HCV1000;
|
||||
|
||||
//these are the remembered preset values for directory and filename
|
||||
//they are named very verbosely to distinguish them from the currently-configured values in addons.cpp
|
||||
|
@ -49,6 +51,8 @@ std::string win32_CFlash_cfgDirectory, win32_CFlash_cfgFileName;
|
|||
UINT win32_CFlash_cfgMode;
|
||||
std::string win32_GBA_cfgRomPath;
|
||||
|
||||
std::string slot2_HCV1000_barcode;
|
||||
|
||||
INT_PTR CALLBACK GbaSlotNone(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam)
|
||||
{
|
||||
switch(msg)
|
||||
|
@ -263,6 +267,54 @@ INT_PTR CALLBACK GbaSlotPaddle(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK GbaSlotHCV1000(HWND dialog, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
int which = 0;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
_OKbutton = TRUE;
|
||||
SendDlgItemMessage(dialog, IDC_HCVSCAN, WM_USER + 44, tmp_HCV1000.SCANKEY, 0);
|
||||
SendDlgItemMessage(dialog, IDC_HCVBARCODE, EM_SETLIMITTEXT, 16, 0);
|
||||
SendDlgItemMessage(dialog, IDC_HCVBARCODE, EM_SETSEL, 0, 16);
|
||||
SetWindowText(GetDlgItem(dialog, IDC_HCVBARCODE), tmp_hcv1000_barcode);
|
||||
|
||||
return TRUE;
|
||||
|
||||
case WM_USER + 46:
|
||||
SendDlgItemMessage(dialog, IDC_HCVSCAN, WM_USER + 44, tmp_HCV1000.SCANKEY, 0);
|
||||
return TRUE;
|
||||
|
||||
case WM_USER + 43:
|
||||
//MessageBox(hDlg,"USER+43 CAUGHT","moo",MB_OK);
|
||||
which = GetDlgCtrlID((HWND)lparam);
|
||||
switch (which)
|
||||
{
|
||||
case IDC_HCVSCAN:
|
||||
tmp_HCV1000.SCANKEY = wparam;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
SendDlgItemMessage(dialog, IDC_HCVSCAN, WM_USER + 44, tmp_HCV1000.SCANKEY, 0);
|
||||
PostMessage(dialog, WM_NEXTDLGCTL, 0, 0);
|
||||
return true;
|
||||
|
||||
case WM_COMMAND:
|
||||
case EN_UPDATE:
|
||||
switch (LOWORD(wparam))
|
||||
{
|
||||
case IDC_HCVBARCODE:
|
||||
GetWindowText(GetDlgItem(dialog, IDC_HCVBARCODE), tmp_hcv1000_barcode, 17);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK GbaSlotRumblePak(HWND dialog, UINT msg,WPARAM wparam,LPARAM lparam)
|
||||
{
|
||||
switch(msg)
|
||||
|
@ -478,6 +530,7 @@ u32 GBAslot_IDDs[NDS_SLOT2_COUNT] = {
|
|||
IDD_GBASLOT_PIANO,
|
||||
IDD_GBASLOT_PADDLE, //paddle
|
||||
IDD_GBASLOT_NONE, //PassME
|
||||
IDD_GBASLOT_HCV1000, //HCV-1000
|
||||
};
|
||||
|
||||
DLGPROC GBAslot_Procs[NDS_SLOT2_COUNT] = {
|
||||
|
@ -490,7 +543,8 @@ DLGPROC GBAslot_Procs[NDS_SLOT2_COUNT] = {
|
|||
GbaSlotNone, //expmem
|
||||
GbaSlotPiano,
|
||||
GbaSlotPaddle,
|
||||
GbaSlotNone // PassME
|
||||
GbaSlotNone, // PassME
|
||||
GbaSlotHCV1000, //HCV-1000
|
||||
};
|
||||
|
||||
|
||||
|
@ -566,9 +620,11 @@ void GBAslotDialog(HWND hwnd)
|
|||
strcpy(tmp_cflash_filename, win32_CFlash_cfgFileName.c_str());
|
||||
strcpy(tmp_cflash_path, win32_CFlash_cfgDirectory.c_str());
|
||||
strcpy(tmp_gbagame_filename, win32_GBA_cfgRomPath.c_str());
|
||||
strcpy(tmp_hcv1000_barcode, slot2_HCV1000_barcode.c_str());
|
||||
memcpy(&tmp_Guitar, &Guitar, sizeof(Guitar));
|
||||
memcpy(&tmp_Piano, &Piano, sizeof(Piano));
|
||||
memcpy(&tmp_Paddle, &Paddle, sizeof(Paddle));
|
||||
memcpy(&tmp_HCV1000, &HCV1000, sizeof(HCV1000));
|
||||
tmp_CFlashMode = CFlash_Mode;
|
||||
_OKbutton = false;
|
||||
|
||||
|
@ -633,6 +689,13 @@ void GBAslotDialog(HWND hwnd)
|
|||
break;
|
||||
case NDS_SLOT2_PASSME:
|
||||
break;
|
||||
case NDS_SLOT2_HCV1000:
|
||||
slot2_HCV1000_barcode = tmp_hcv1000_barcode;
|
||||
memcpy(&HCV1000, &tmp_HCV1000, sizeof(tmp_HCV1000));
|
||||
HCV1000_setBarcode(slot2_HCV1000_barcode);
|
||||
WritePrivateProfileString("Slot2.HCV1000", "barcode", tmp_hcv1000_barcode, IniName);
|
||||
WritePrivateProfileInt("Slot2.HCV1000", "scankey", HCV1000.SCANKEY, IniName);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -644,6 +707,7 @@ void GBAslotDialog(HWND hwnd)
|
|||
Guitar.Enabled = (slot2_GetCurrentType() == NDS_SLOT2_GUITARGRIP)?true:false;
|
||||
Piano.Enabled = (slot2_GetCurrentType() == NDS_SLOT2_EASYPIANO)?true:false;
|
||||
Paddle.Enabled = (slot2_GetCurrentType() == NDS_SLOT2_PADDLE)?true:false;
|
||||
HCV1000.Enabled = (slot2_GetCurrentType() == NDS_SLOT2_HCV1000)?true:false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2009-2015 DeSmuME team
|
||||
Copyright (C) 2009-2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -25,6 +25,8 @@ extern std::string win32_CFlash_cfgDirectory, win32_CFlash_cfgFileName;
|
|||
extern UINT win32_CFlash_cfgMode;
|
||||
extern std::string win32_GBA_cfgRomPath;
|
||||
|
||||
extern std::string slot2_HCV1000_barcode;
|
||||
|
||||
extern void GBAslotDialog(HWND hwnd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
licensed under the terms supplied at the end of this file (for the terms are very long!)
|
||||
Differences from that baseline version are:
|
||||
|
||||
Copyright (C) 2009-2019 DeSmuME team
|
||||
Copyright (C) 2009-2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -51,6 +51,13 @@
|
|||
#include "main.h"
|
||||
#include "winutil.h"
|
||||
|
||||
//60 is a poor choice for a threshold; the theoretical maximum you can get even at an exact 45 degree angle is 70
|
||||
//Sloshy sticks or slightly-off angles make it impossible to reach 60, as it's far too close to 70.
|
||||
//Too-small values feel bad, too
|
||||
//50 is a more normal choice
|
||||
//#define S9X_JOY_NEUTRAL 60
|
||||
int S9X_JOY_NEUTRAL = 50;
|
||||
|
||||
// Gamepad Dialog Strings
|
||||
// Support Unicode display
|
||||
//#define INPUTCONFIG_TITLE "Input Configuration"
|
||||
|
@ -258,6 +265,9 @@ SPiano DefaultPiano = { false, 'Z', 'S', 'X', 'D', 'C', 'V', 'G', 'B', 'H', 'N',
|
|||
SPaddle Paddle;
|
||||
SPaddle DefaultPaddle = { false, 'K', 'L' };
|
||||
|
||||
SHCV1000 HCV1000;
|
||||
SHCV1000 DefaultHCV1000 = { false, 'L'};
|
||||
|
||||
bool killStylusTopScreen = false;
|
||||
bool killStylusOffScreen = false;
|
||||
bool allowUpAndDown = false;
|
||||
|
@ -390,6 +400,15 @@ static void ReadPaddleControl(const char* name, WORD& output)
|
|||
}
|
||||
}
|
||||
|
||||
static void ReadHCV1000Control(const char* name, WORD& output)
|
||||
{
|
||||
UINT temp;
|
||||
temp = GetPrivateProfileInt("Slot2.HCV1000", name, -1, IniName);
|
||||
if (temp != -1) {
|
||||
output = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadHotkeyConfig()
|
||||
{
|
||||
SCustomKey *key = &CustomKeys.key(0);
|
||||
|
@ -452,6 +471,15 @@ static void LoadPaddleConfig()
|
|||
ReadPaddleControl("INC", Paddle.INC);
|
||||
}
|
||||
|
||||
static void LoadHCV1000Config()
|
||||
{
|
||||
memcpy(&HCV1000, &DefaultHCV1000, sizeof(HCV1000));
|
||||
|
||||
#define DO(X) ReadHCV1000Control(#X,HCV1000.X);
|
||||
DO(SCANKEY);
|
||||
#undef DO
|
||||
}
|
||||
|
||||
|
||||
static void LoadInputConfig()
|
||||
{
|
||||
|
@ -499,6 +527,9 @@ BOOL di_init()
|
|||
{
|
||||
HWND hParentWnd = MainWindow->getHWnd();
|
||||
|
||||
S9X_JOY_NEUTRAL = GetPrivateProfileInt("Controls", "DigitalizationThreshold", S9X_JOY_NEUTRAL, IniName);
|
||||
|
||||
|
||||
pDI = NULL;
|
||||
memset(cDIBuf, 0, sizeof(cDIBuf));
|
||||
|
||||
|
@ -648,10 +679,6 @@ int FunkyNormalize(int cur, int min, int max)
|
|||
return Result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define S9X_JOY_NEUTRAL 60
|
||||
|
||||
void CheckAxis (short joy, short control, int val,
|
||||
int min, int max,
|
||||
bool &first, bool &second)
|
||||
|
@ -2690,6 +2717,7 @@ void input_init()
|
|||
LoadGuitarConfig();
|
||||
LoadPianoConfig();
|
||||
LoadPaddleConfig();
|
||||
LoadHCV1000Config();
|
||||
|
||||
di_init();
|
||||
FeedbackON = input_feedback;
|
||||
|
@ -2816,6 +2844,12 @@ void input_acquire()
|
|||
if (inc) nds.paddle += 5;
|
||||
if (dec) nds.paddle -= 5;
|
||||
}
|
||||
|
||||
if (HCV1000.Enabled)
|
||||
{
|
||||
bool scan = !S9xGetState(HCV1000.SCANKEY);
|
||||
if (scan) HCV1000_setReady();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
licensed under the terms supplied at the end of this file (for the terms are very long!)
|
||||
Differences from that baseline version are:
|
||||
|
||||
Copyright (C) 2008-2010 DeSmuME team
|
||||
Copyright (C) 2008-2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -153,9 +153,15 @@ struct SPaddle {
|
|||
WORD INC;
|
||||
};
|
||||
|
||||
struct SHCV1000 {
|
||||
BOOL Enabled;
|
||||
WORD SCANKEY;
|
||||
};
|
||||
|
||||
extern SGuitar Guitar;
|
||||
extern SPiano Piano;
|
||||
extern SPaddle Paddle;
|
||||
extern SHCV1000 HCV1000;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
/*
|
||||
Copyright (C) 2006 Theo Berkau
|
||||
Copyright (C) 2006-2019 DeSmuME team
|
||||
Copyright (C) 2006-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -52,7 +52,6 @@
|
|||
#include "slot2.h"
|
||||
#include "GPU.h"
|
||||
#include "SPU.h"
|
||||
#include "OGLRender.h"
|
||||
#include "OGLRender_3_2.h"
|
||||
#include "rasterize.h"
|
||||
#include "gfx3d.h"
|
||||
|
@ -1580,6 +1579,7 @@ static BOOL LoadROM(const char * filename, const char * physicalName, const char
|
|||
Guitar.Enabled = (selectedSlot2Type == NDS_SLOT2_GUITARGRIP)?true:false;
|
||||
Piano.Enabled = (selectedSlot2Type == NDS_SLOT2_EASYPIANO)?true:false;
|
||||
Paddle.Enabled = (selectedSlot2Type == NDS_SLOT2_PADDLE)?true:false;
|
||||
HCV1000.Enabled = (selectedSlot2Type == NDS_SLOT2_HCV1000)?true:false;
|
||||
|
||||
LoadSaveStateInfo();
|
||||
lagframecounter=0;
|
||||
|
@ -2198,6 +2198,9 @@ int _main()
|
|||
win32_CFlash_cfgFileName = GetPrivateProfileStdString("Slot2.CFlash", "filename", "");
|
||||
win32_GBA_cfgRomPath = GetPrivateProfileStdString("Slot2.GBAgame", "filename", "");
|
||||
|
||||
slot2_HCV1000_barcode = GetPrivateProfileStdString("Slot2.HCV1000", "barcode", "").substr(0, 16);
|
||||
HCV1000_setBarcode(slot2_HCV1000_barcode);
|
||||
|
||||
cmdline.process_addonCommands();
|
||||
WIN_InstallCFlash();
|
||||
WIN_InstallGBACartridge();
|
||||
|
@ -2258,6 +2261,8 @@ int _main()
|
|||
break;
|
||||
case NDS_SLOT2_PASSME:
|
||||
break;
|
||||
case NDS_SLOT2_HCV1000:
|
||||
break;
|
||||
default:
|
||||
slot2_device_type = NDS_SLOT2_NONE;
|
||||
break;
|
||||
|
@ -2268,6 +2273,7 @@ int _main()
|
|||
Guitar.Enabled = (slot2_device_type == NDS_SLOT2_GUITARGRIP)?true:false;
|
||||
Piano.Enabled = (slot2_device_type == NDS_SLOT2_EASYPIANO)?true:false;
|
||||
Paddle.Enabled = (slot2_device_type == NDS_SLOT2_PADDLE)?true:false;
|
||||
HCV1000.Enabled = (slot2_device_type == NDS_SLOT2_HCV1000)?true:false;
|
||||
|
||||
CommonSettings.WifiBridgeDeviceID = GetPrivateProfileInt("Wifi", "BridgeAdapter", 0, IniName);
|
||||
|
||||
|
|
|
@ -514,7 +514,9 @@
|
|||
#define IDC_WIFI_ENABLED 1065
|
||||
#define IDC_STATIC_RANGE 1066
|
||||
#define IDC_WIFI_COMPAT 1066
|
||||
#define IDC_HCVSCAN 1066
|
||||
#define IDC_TEXSCALE 1067
|
||||
#define IDC_HCVBARCODE 1067
|
||||
#define IDC_BADD 1068
|
||||
#define IDC_LIST 1069
|
||||
#define IDC_TEX_DEPOSTERIZE 1070
|
||||
|
@ -923,6 +925,7 @@
|
|||
#define IDD_SLOT1_R4 10012
|
||||
#define IDD_SLOT1_DEBUG 10013
|
||||
#define IDD_GBASLOT_PADDLE 10014
|
||||
#define IDD_GBASLOT_HCV1000 10015
|
||||
#define IDM_FILE_STOPAVI 40000
|
||||
#define IDM_SCREENSEP_NONE 40000
|
||||
#define IDM_FILE_STOPWAV 40001
|
||||
|
@ -1156,7 +1159,7 @@
|
|||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 128
|
||||
#define _APS_NEXT_COMMAND_VALUE 40159
|
||||
#define _APS_NEXT_CONTROL_VALUE 1066
|
||||
#define _APS_NEXT_CONTROL_VALUE 1068
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1591,6 +1591,17 @@ BEGIN
|
|||
RTEXT "Decrease",-1,81,40,44,8
|
||||
END
|
||||
|
||||
IDD_GBASLOT_HCV1000 DIALOGEX 7, 48, 302, 109
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
EDITTEXT IDC_HCVBARCODE,129,42,72,14,ES_AUTOHSCROLL
|
||||
CONTROL " ",IDC_HCVSCAN,"InputCustomGuitar",WS_TABSTOP,129,24,71,12,WS_EX_CLIENTEDGE
|
||||
RTEXT "Scan key",-1,80,27,46,8
|
||||
LTEXT "Card reader",-1,137,8,53,15
|
||||
RTEXT "Barcode",-1,79,46,46,8
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
|
@ -87,7 +87,7 @@ void GetINIPath()
|
|||
}
|
||||
|
||||
FCEUD_MakePathDirs(IniName);
|
||||
wcscpy(IniNameW,mbstowcs(IniName).c_str()); //careful to use locale C-style mbstowcs to get IniName (which is with locale encoding) to unicode
|
||||
wcscpy(IniNameW,mbstowcs_locale(IniName).c_str());
|
||||
|
||||
//write BOM to get unicode
|
||||
FILE* test = fopen(IniName,"rb");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2008-2023 DeSmuME team
|
||||
Copyright (C) 2008-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -561,7 +561,7 @@ bool GFX3D_IsPolyWireframe(const POLY &p);
|
|||
bool GFX3D_IsPolyOpaque(const POLY &p);
|
||||
bool GFX3D_IsPolyTranslucent(const POLY &p);
|
||||
|
||||
#define POLYLIST_SIZE 16383
|
||||
#define POLYLIST_SIZE 16384
|
||||
#define CLIPPED_POLYLIST_SIZE (POLYLIST_SIZE * 2)
|
||||
#define VERTLIST_SIZE (POLYLIST_SIZE * 4)
|
||||
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef __MACH__
|
||||
#define _DARWIN_C_SOURCE /* As below, plus strl* functions */
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500 /* For strdup, realpath */
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <boolean.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -170,7 +170,7 @@ void createDirectoryRecursively(std::wstring path)
|
|||
|
||||
void FCEUD_MakePathDirs(const char *fname)
|
||||
{
|
||||
createDirectoryRecursively(mbstowcs(fname));
|
||||
createDirectoryRecursively(mbstowcs_locale(fname));
|
||||
}
|
||||
#endif
|
||||
//------------------------------
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2009-2015 DeSmuME team
|
||||
Copyright (C) 2009-2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -58,6 +58,7 @@ void slot2_Init()
|
|||
extern TISlot2InterfaceConstructor construct_Slot2_EasyPiano;
|
||||
extern TISlot2InterfaceConstructor construct_Slot2_Paddle;
|
||||
extern TISlot2InterfaceConstructor construct_Slot2_PassME;
|
||||
extern TISlot2InterfaceConstructor construct_Slot2_HCV1000;
|
||||
|
||||
slot2_List[NDS_SLOT2_NONE] = construct_Slot2_None();
|
||||
slot2_List[NDS_SLOT2_AUTO] = construct_Slot2_Auto();
|
||||
|
@ -69,6 +70,7 @@ void slot2_Init()
|
|||
slot2_List[NDS_SLOT2_EASYPIANO] = construct_Slot2_EasyPiano();
|
||||
slot2_List[NDS_SLOT2_PADDLE] = construct_Slot2_Paddle();
|
||||
slot2_List[NDS_SLOT2_PASSME] = construct_Slot2_PassME();
|
||||
slot2_List[NDS_SLOT2_HCV1000] = construct_Slot2_HCV1000();
|
||||
|
||||
}
|
||||
|
||||
|
@ -106,7 +108,7 @@ void slot2_Reset()
|
|||
|
||||
bool slot2_Change(NDS_SLOT2_TYPE changeToType)
|
||||
{
|
||||
if (changeToType > NDS_SLOT2_COUNT || changeToType < 0)
|
||||
if (changeToType >= NDS_SLOT2_COUNT || changeToType < 0)
|
||||
return false;
|
||||
|
||||
if (slot2_device_type == changeToType)
|
||||
|
@ -163,7 +165,7 @@ bool slot2_Change(NDS_SLOT2_TYPE changeToType)
|
|||
|
||||
void slot2_setDeviceByType(NDS_SLOT2_TYPE theType)
|
||||
{
|
||||
if (theType > NDS_SLOT2_COUNT || theType < 0)
|
||||
if (theType >= NDS_SLOT2_COUNT || theType < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -252,6 +254,9 @@ NDS_SLOT2_TYPE slot2_DetermineTypeByGameCode(const char *theGameCode)
|
|||
{"CV8", NDS_SLOT2_PADDLE}, // Space Invaders Extreme 2
|
||||
{"AMH", NDS_SLOT2_RUMBLEPAK}, // Metroid Prime Hunters
|
||||
{"AP2", NDS_SLOT2_RUMBLEPAK}, // Metroid Prime Pinball
|
||||
{"C4A", NDS_SLOT2_HCV1000}, // Card de Asobu! Hajimete no DS
|
||||
{"A6I", NDS_SLOT2_HCV1000}, // Kouchuu Ouja: Mushi King Super Collection
|
||||
{"ALB", NDS_SLOT2_HCV1000}, // Oshare Majo Berry and Love
|
||||
};
|
||||
|
||||
for(size_t i = 0; i < ARRAY_SIZE(gameCodeDeviceTypes); i++)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2009-2015 DeSmuME team
|
||||
Copyright (C) 2009-2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -97,6 +97,7 @@ enum NDS_SLOT2_TYPE
|
|||
NDS_SLOT2_EASYPIANO, // 0x06 - Easy Piano
|
||||
NDS_SLOT2_PADDLE, // 0x07 - Arkanoids DS paddle
|
||||
NDS_SLOT2_PASSME, // 0x08 - PassME/Homebrew
|
||||
NDS_SLOT2_HCV1000, // 0x09 - HCV-1000 Sega Card Reader
|
||||
NDS_SLOT2_COUNT // use for counter addons - MUST TO BE LAST!!!
|
||||
};
|
||||
|
||||
|
@ -157,4 +158,6 @@ void Paddle_SetValue(u16 theValue);
|
|||
|
||||
extern void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue); // Guitar grip keys
|
||||
extern void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic); //piano keys
|
||||
extern void HCV1000_setReady();
|
||||
extern void HCV1000_setBarcode(std::string barcode);
|
||||
#endif //__SLOT_H__
|
||||
|
|
|
@ -309,7 +309,6 @@ typedef float32x4_t v128f32;
|
|||
#endif
|
||||
|
||||
#ifdef ENABLE_SSE
|
||||
#include <immintrin.h>
|
||||
#include <xmmintrin.h>
|
||||
typedef __m128 v128f32;
|
||||
#define AVAILABLE_TYPE_v128f32
|
||||
|
|
|
@ -284,6 +284,19 @@ std::string mass_replace(const std::string &source, const std::string &victim, c
|
|||
return answer;
|
||||
}
|
||||
|
||||
std::wstring mbstowcs_locale(std::string str)
|
||||
{
|
||||
#ifdef HOST_WINDOWS
|
||||
int plenty = str.size()*4+1;
|
||||
wchar_t *wgarbage = new wchar_t[plenty];
|
||||
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str.data(), -1, wgarbage, plenty);
|
||||
std::wstring ret = wgarbage;
|
||||
delete[] wgarbage;
|
||||
return ret;
|
||||
#endif
|
||||
return mbstowcs(str);
|
||||
}
|
||||
|
||||
//convert a std::string to std::wstring
|
||||
std::wstring mbstowcs(std::string str)
|
||||
{
|
||||
|
|
|
@ -107,5 +107,7 @@ std::string mass_replace(const std::string &source, const std::string &victim, c
|
|||
std::wstring mbstowcs(std::string str);
|
||||
std::string wcstombs(std::wstring str);
|
||||
|
||||
std::wstring mbstowcs_locale(std::string str);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue