- Reorganize 3d code to defer rendering to vblank. eliminates tearing, and maybe some texturing artifacts. also possibly helps performance a bit by letting the hardware pipeline work some more before blocking for framebuffer read.
- Tweak optimization flags and change entire source code to use fastcall. - Add opengl state caching. This is of dubious performance assistance, but it is easy to take out so I am leaving it for now. - Add MMU->GPU signal for when vram mappings change, which allows it to assume textures are unchanged unless vram has changed. (big 3d speedup)
This commit is contained in:
parent
f11b11b18e
commit
11d989908f
|
@ -44,6 +44,12 @@
|
||||||
- Defer rendering until after flush. This was a necessary architectural change, as it permits savestate
|
- Defer rendering until after flush. This was a necessary architectural change, as it permits savestate
|
||||||
for the display list, and allows us eventually to separate the GE emulation from the rendering [zeromus]
|
for the display list, and allows us eventually to separate the GE emulation from the rendering [zeromus]
|
||||||
- Fix the 2d/3d compositing well enough for NSMB to fix bugs, but it is still bad [zeromus]
|
- Fix the 2d/3d compositing well enough for NSMB to fix bugs, but it is still bad [zeromus]
|
||||||
|
- Reorganize 3d code to defer rendering to vblank. eliminates tearing, and maybe some texturing artifacts.
|
||||||
|
also possibly helps performance a bit by letting the hardware pipeline work some more before blocking for
|
||||||
|
framebuffer read. [zeromus]
|
||||||
|
- Tweak optimization flags and change entire source code to use fastcall [zeromus]
|
||||||
|
- Add opengl state caching. This is of dubious performance assistance, but it is easy to take out so I am leaving it for now. [zeromus]
|
||||||
|
- Add MMU->GPU signal for when vram mappings change, which allows it to assume textures are unchanged unless vram has changed [zeromus]
|
||||||
|
|
||||||
|
|
||||||
0.7.3 -> 0.8
|
0.7.3 -> 0.8
|
||||||
|
|
|
@ -23,7 +23,7 @@ typedef struct {
|
||||||
u8 * ObjExtPal[2][2];
|
u8 * ObjExtPal[2][2];
|
||||||
u8 * texPalSlot[4];
|
u8 * texPalSlot[4];
|
||||||
|
|
||||||
const u8 *textureSlotAddr[4];
|
u8 *textureSlotAddr[4];
|
||||||
|
|
||||||
u8 *blank_memory[0x20000];
|
u8 *blank_memory[0x20000];
|
||||||
} ARM9_struct;
|
} ARM9_struct;
|
||||||
|
|
|
@ -1060,6 +1060,8 @@ void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val)
|
||||||
|
|
||||||
ARM9Mem.textureSlotAddr[slot_index] =
|
ARM9Mem.textureSlotAddr[slot_index] =
|
||||||
&ARM9Mem.ARM9_LCD[0x20000 * (adr - REG_VRAMCNTA)];
|
&ARM9Mem.ARM9_LCD[0x20000 * (adr - REG_VRAMCNTA)];
|
||||||
|
|
||||||
|
gpu3D->NDS_3D_VramReconfigureSignal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTA,val) ;
|
MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTA,val) ;
|
||||||
|
|
|
@ -1022,6 +1022,8 @@ NDS_exec(s32 nb, BOOL force)
|
||||||
nds.lignerendu = FALSE;
|
nds.lignerendu = FALSE;
|
||||||
if(nds.VCount==192)
|
if(nds.VCount==192)
|
||||||
{
|
{
|
||||||
|
gpu3D->NDS_3D_VBlankSignal();
|
||||||
|
|
||||||
T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 1);
|
T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 1);
|
||||||
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1);
|
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1);
|
||||||
NDS_ARM9VBlankInt();
|
NDS_ARM9VBlankInt();
|
||||||
|
|
|
@ -21,11 +21,8 @@
|
||||||
#ifndef GPU_3D
|
#ifndef GPU_3D
|
||||||
#define GPU_3D
|
#define GPU_3D
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
//not using this right now
|
||||||
#define CALL_CONVENTION __cdecl
|
|
||||||
#else
|
|
||||||
#define CALL_CONVENTION
|
#define CALL_CONVENTION
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
enum DRIVER_3D
|
enum DRIVER_3D
|
||||||
|
@ -125,7 +122,9 @@ typedef struct GPU3DInterface
|
||||||
long (CALL_CONVENTION* NDS_3D_GetPosRes) (unsigned int index);
|
long (CALL_CONVENTION* NDS_3D_GetPosRes) (unsigned int index);
|
||||||
long (CALL_CONVENTION* NDS_3D_GetVecRes) (unsigned int index);
|
long (CALL_CONVENTION* NDS_3D_GetVecRes) (unsigned int index);
|
||||||
|
|
||||||
void (CALL_CONVENTION* NDS_3D_UpdateToonTable) (void* toonTable);
|
void (CALL_CONVENTION* NDS_3D_UpdateToonTable) (void* toonTable);
|
||||||
|
void (CALL_CONVENTION* NDS_3D_VBlankSignal) ();
|
||||||
|
void (CALL_CONVENTION* NDS_3D_VramReconfigureSignal) ();
|
||||||
|
|
||||||
|
|
||||||
} GPU3DInterface;
|
} GPU3DInterface;
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
IntermediateDirectory="$(SolutionDir)\.VS2005\$(ConfigurationName)\$(PlatformName)"
|
IntermediateDirectory="$(SolutionDir)\.VS2005\$(ConfigurationName)\$(PlatformName)"
|
||||||
ConfigurationType="1"
|
ConfigurationType="1"
|
||||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCPreBuildEventTool"
|
Name="VCPreBuildEventTool"
|
||||||
|
@ -135,16 +136,19 @@
|
||||||
InlineFunctionExpansion="2"
|
InlineFunctionExpansion="2"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
|
OmitFramePointers="true"
|
||||||
EnableFiberSafeOptimizations="true"
|
EnableFiberSafeOptimizations="true"
|
||||||
WholeProgramOptimization="true"
|
WholeProgramOptimization="true"
|
||||||
AdditionalIncludeDirectories="..;.\zlib123;.\zziplib"
|
AdditionalIncludeDirectories="..;.\zlib123;.\zziplib"
|
||||||
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"0.8.0b2\";WIN32;HAVE_LIBZ;HAVE_LIBZZIP;BETA_VERSION"
|
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"0.8.0b2\";WIN32;HAVE_LIBZ;HAVE_LIBZZIP;BETA_VERSION"
|
||||||
|
StringPooling="true"
|
||||||
ExceptionHandling="0"
|
ExceptionHandling="0"
|
||||||
BufferSecurityCheck="false"
|
BufferSecurityCheck="false"
|
||||||
EnableEnhancedInstructionSet="0"
|
EnableEnhancedInstructionSet="0"
|
||||||
|
FloatingPointModel="2"
|
||||||
WarningLevel="1"
|
WarningLevel="1"
|
||||||
DebugInformationFormat="3"
|
DebugInformationFormat="3"
|
||||||
CallingConvention="0"
|
CallingConvention="1"
|
||||||
CompileAs="0"
|
CompileAs="0"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -195,6 +199,7 @@
|
||||||
IntermediateDirectory="$(SolutionDir)\.VS2005\$(ConfigurationName)\$(PlatformName)"
|
IntermediateDirectory="$(SolutionDir)\.VS2005\$(ConfigurationName)\$(PlatformName)"
|
||||||
ConfigurationType="1"
|
ConfigurationType="1"
|
||||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCPreBuildEventTool"
|
Name="VCPreBuildEventTool"
|
||||||
|
@ -219,16 +224,19 @@
|
||||||
InlineFunctionExpansion="2"
|
InlineFunctionExpansion="2"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
|
OmitFramePointers="true"
|
||||||
EnableFiberSafeOptimizations="true"
|
EnableFiberSafeOptimizations="true"
|
||||||
WholeProgramOptimization="true"
|
WholeProgramOptimization="true"
|
||||||
AdditionalIncludeDirectories="..;.\zlib123;.\zziplib"
|
AdditionalIncludeDirectories="..;.\zlib123;.\zziplib"
|
||||||
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"0.8.0b2 SSE2\";WIN32;HAVE_LIBZ;HAVE_LIBZZIP;SSE2;BETA_VERSION"
|
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"0.8.0b2 SSE2\";WIN32;HAVE_LIBZ;HAVE_LIBZZIP;SSE2;BETA_VERSION"
|
||||||
|
StringPooling="true"
|
||||||
ExceptionHandling="0"
|
ExceptionHandling="0"
|
||||||
BufferSecurityCheck="false"
|
BufferSecurityCheck="false"
|
||||||
EnableEnhancedInstructionSet="0"
|
EnableEnhancedInstructionSet="2"
|
||||||
|
FloatingPointModel="2"
|
||||||
WarningLevel="1"
|
WarningLevel="1"
|
||||||
DebugInformationFormat="3"
|
DebugInformationFormat="3"
|
||||||
CallingConvention="0"
|
CallingConvention="1"
|
||||||
CompileAs="0"
|
CompileAs="0"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
|
@ -807,10 +815,26 @@
|
||||||
<File
|
<File
|
||||||
RelativePath="..\ROMReader.cpp"
|
RelativePath="..\ROMReader.cpp"
|
||||||
>
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release (SSE2)|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
CallingConvention="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\saves.cpp"
|
RelativePath="..\saves.cpp"
|
||||||
>
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release (SSE2)|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
CallingConvention="1"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\snddx.cpp"
|
RelativePath=".\snddx.cpp"
|
||||||
|
@ -832,6 +856,10 @@
|
||||||
RelativePath="..\wifi.cpp"
|
RelativePath="..\wifi.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<Filter
|
||||||
|
Name="windows"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header Files"
|
Name="Header Files"
|
||||||
|
|
|
@ -48,12 +48,15 @@
|
||||||
#include "../NDSSystem.h"
|
#include "../NDSSystem.h"
|
||||||
#include "OGLRender.h"
|
#include "OGLRender.h"
|
||||||
|
|
||||||
|
#ifndef CTASSERT
|
||||||
|
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1]
|
||||||
|
#endif
|
||||||
|
|
||||||
#define fix2float(v) (((float)((s32)(v))) / (float)(1<<12))
|
#define fix2float(v) (((float)((s32)(v))) / (float)(1<<12))
|
||||||
#define fix10_2float(v) (((float)((s32)(v))) / (float)(1<<9))
|
#define fix10_2float(v) (((float)((s32)(v))) / (float)(1<<9))
|
||||||
|
|
||||||
static unsigned char GPU_screen3D [256*256*4]={0};
|
static __declspec(align(16)) unsigned char GPU_screen3D [256*256*4]={0};
|
||||||
static unsigned char GPU_screenStencil[256*256]={0};
|
static __declspec(align(16)) unsigned char GPU_screenStencil[256*256]={0};
|
||||||
|
|
||||||
// Acceleration tables
|
// Acceleration tables
|
||||||
static float* float16table = NULL;
|
static float* float16table = NULL;
|
||||||
|
@ -89,6 +92,8 @@ static const unsigned short map3d_cull[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BAC
|
||||||
static const int texEnv[4] = { GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE };
|
static const int texEnv[4] = { GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE };
|
||||||
static const int depthFunc[2] = { GL_LESS, GL_EQUAL };
|
static const int depthFunc[2] = { GL_LESS, GL_EQUAL };
|
||||||
|
|
||||||
|
static bool needRefreshFramebuffer = false;
|
||||||
|
|
||||||
//is this a crazy idea? this table spreads 5 bits evenly over 31 from exactly 0 to INT_MAX
|
//is this a crazy idea? this table spreads 5 bits evenly over 31 from exactly 0 to INT_MAX
|
||||||
static const int material_5bit_to_31bit[] = {
|
static const int material_5bit_to_31bit[] = {
|
||||||
0x00000000, 0x04210842, 0x08421084, 0x0C6318C6,
|
0x00000000, 0x04210842, 0x08421084, 0x0C6318C6,
|
||||||
|
@ -133,7 +138,7 @@ static float fogColor[4] = {0.f};
|
||||||
static float fogOffset = 0.f;
|
static float fogOffset = 0.f;
|
||||||
static float alphaTestRef = 0.01f;
|
static float alphaTestRef = 0.01f;
|
||||||
|
|
||||||
static float alphaTestBase = 0.1f;
|
static float alphaTestBase = 0;
|
||||||
static unsigned long clCmd = 0;
|
static unsigned long clCmd = 0;
|
||||||
static unsigned long clInd = 0;
|
static unsigned long clInd = 0;
|
||||||
static unsigned long clInd2 = 0;
|
static unsigned long clInd2 = 0;
|
||||||
|
@ -200,10 +205,97 @@ static void twiddleLists() {
|
||||||
vertlist->count = 0;
|
vertlist->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#define OGLEXT(x,y) x y;
|
||||||
|
#define INITOGLEXT(x,y) y = (x)wglGetProcAddress(#y);
|
||||||
|
|
||||||
|
OGLEXT(PFNGLCREATESHADERPROC,glCreateShader)
|
||||||
|
//zero: i dont understand this at all. my glext.h has the wrong thing declared here... so I have to do it myself
|
||||||
|
typedef void (APIENTRYP X_PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLchar **source, GLsizei *length);
|
||||||
|
OGLEXT(X_PFNGLGETSHADERSOURCEPROC,glShaderSource)
|
||||||
|
OGLEXT(PFNGLCOMPILESHADERPROC,glCompileShader)
|
||||||
|
OGLEXT(PFNGLCREATEPROGRAMPROC,glCreateProgram)
|
||||||
|
OGLEXT(PFNGLATTACHSHADERPROC,glAttachShader)
|
||||||
|
OGLEXT(PFNGLLINKPROGRAMPROC,glLinkProgram)
|
||||||
|
OGLEXT(PFNGLUSEPROGRAMPROC,glUseProgram)
|
||||||
|
OGLEXT(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog)
|
||||||
|
|
||||||
|
//opengl state caching:
|
||||||
|
//This is of dubious performance assistance, but it is easy to take out so I am leaving it for now.
|
||||||
|
//every function that is xgl* can be replaced with gl* if we decide to rip this out or if anyone else
|
||||||
|
//doesnt feel like sticking with it (or if it causes trouble)
|
||||||
|
|
||||||
|
void xglDepthFunc(GLenum func) {
|
||||||
|
static GLenum oldfunc = -1;
|
||||||
|
if(oldfunc == func) return;
|
||||||
|
glDepthFunc(oldfunc=func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xglPolygonMode(GLenum face,GLenum mode) {
|
||||||
|
static GLenum oldmodes[2] = {-1,-1};
|
||||||
|
switch(face) {
|
||||||
|
case GL_FRONT: if(oldmodes[0]==mode) return; else glPolygonMode(GL_FRONT,oldmodes[0]=mode); return;
|
||||||
|
case GL_BACK: if(oldmodes[1]==mode) return; else glPolygonMode(GL_BACK,oldmodes[1]=mode); return;
|
||||||
|
case GL_FRONT_AND_BACK: if(oldmodes[0]==mode && oldmodes[1]==mode) return; else glPolygonMode(GL_FRONT_AND_BACK,oldmodes[0]=oldmodes[1]=mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void xglUseProgram(GLuint program) {
|
||||||
|
if(!glUseProgram) return;
|
||||||
|
static GLuint oldprogram = -1;
|
||||||
|
if(oldprogram==program) return;
|
||||||
|
glUseProgram(oldprogram=program);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xglDepthMask (GLboolean flag) {
|
||||||
|
static GLboolean oldflag = -1;
|
||||||
|
if(oldflag==flag) return;
|
||||||
|
glDepthMask(oldflag=flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GLCaps {
|
||||||
|
u8 caps[0x100];
|
||||||
|
GLCaps() {
|
||||||
|
memset(caps,0xFF,sizeof(caps));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static GLCaps glcaps;
|
||||||
|
|
||||||
|
void _xglEnable(GLenum cap) {
|
||||||
|
cap -= 0x0B00;
|
||||||
|
if(glcaps.caps[cap] == 0xFF || glcaps.caps[cap] == 0) {
|
||||||
|
glEnable(cap+0x0B00);
|
||||||
|
glcaps.caps[cap] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _xglDisable(GLenum cap) {
|
||||||
|
cap -= 0x0B00;
|
||||||
|
if(glcaps.caps[cap]) {
|
||||||
|
glDisable(cap+0x0B00);
|
||||||
|
glcaps.caps[cap] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define xglEnable(cap) { \
|
||||||
|
CTASSERT((cap-0x0B00)<0x100); \
|
||||||
|
_xglEnable(cap); }
|
||||||
|
|
||||||
|
#define xglDisable(cap) {\
|
||||||
|
CTASSERT((cap-0x0B00)<0x100); \
|
||||||
|
_xglDisable(cap); }
|
||||||
|
|
||||||
|
|
||||||
//================================================= Textures
|
//================================================= Textures
|
||||||
#define MAX_TEXTURE 500
|
#define MAX_TEXTURE 500
|
||||||
typedef struct
|
struct TextureCache
|
||||||
{
|
{
|
||||||
|
TextureCache()
|
||||||
|
: suspectedInvalid(true)
|
||||||
|
{}
|
||||||
|
|
||||||
GLenum id;
|
GLenum id;
|
||||||
unsigned int frm;
|
unsigned int frm;
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
|
@ -217,7 +309,10 @@ typedef struct
|
||||||
float invSizeY;
|
float invSizeY;
|
||||||
unsigned char texture[128*1024]; // 128Kb texture slot
|
unsigned char texture[128*1024]; // 128Kb texture slot
|
||||||
|
|
||||||
} TextureCache;
|
//set if this texture is suspected be invalid due to a vram reconfigure
|
||||||
|
bool suspectedInvalid;
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
TextureCache texcache[MAX_TEXTURE+1];
|
TextureCache texcache[MAX_TEXTURE+1];
|
||||||
u32 texcache_count;
|
u32 texcache_count;
|
||||||
|
@ -283,20 +378,6 @@ static void NDS_3D_UpdateToonTable(void* toonTable) {
|
||||||
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbToonTable);
|
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbToonTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OGLEXT(x,y) x y;
|
|
||||||
#define INITOGLEXT(x,y) y = (x)wglGetProcAddress(#y);
|
|
||||||
|
|
||||||
OGLEXT(PFNGLCREATESHADERPROC,glCreateShader)
|
|
||||||
//zero: i dont understand this at all. my glext.h has the wrong thing declared here... so I have to do it myself
|
|
||||||
typedef void (APIENTRYP X_PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLchar **source, GLsizei *length);
|
|
||||||
OGLEXT(X_PFNGLGETSHADERSOURCEPROC,glShaderSource)
|
|
||||||
OGLEXT(PFNGLCOMPILESHADERPROC,glCompileShader)
|
|
||||||
OGLEXT(PFNGLCREATEPROGRAMPROC,glCreateProgram)
|
|
||||||
OGLEXT(PFNGLATTACHSHADERPROC,glAttachShader)
|
|
||||||
OGLEXT(PFNGLLINKPROGRAMPROC,glLinkProgram)
|
|
||||||
OGLEXT(PFNGLUSEPROGRAMPROC,glUseProgram)
|
|
||||||
OGLEXT(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog)
|
|
||||||
|
|
||||||
char NDS_glInit(void)
|
char NDS_glInit(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -343,12 +424,14 @@ char NDS_glInit(void)
|
||||||
#endif
|
#endif
|
||||||
glClearColor (0.f, 0.f, 0.f, 1.f);
|
glClearColor (0.f, 0.f, 0.f, 1.f);
|
||||||
|
|
||||||
glEnable (GL_NORMALIZE);
|
glPixelStorei(GL_PACK_ALIGNMENT,8);
|
||||||
glEnable (GL_DEPTH_TEST);
|
|
||||||
|
xglEnable (GL_NORMALIZE);
|
||||||
|
xglEnable (GL_DEPTH_TEST);
|
||||||
glEnable (GL_TEXTURE_2D);
|
glEnable (GL_TEXTURE_2D);
|
||||||
|
|
||||||
glAlphaFunc (GL_GREATER, 0);
|
glAlphaFunc (GL_GREATER, 0);
|
||||||
glEnable (GL_ALPHA_TEST);
|
xglEnable (GL_ALPHA_TEST);
|
||||||
|
|
||||||
glGenTextures (MAX_TEXTURE, &oglTempTextureID[0]);
|
glGenTextures (MAX_TEXTURE, &oglTempTextureID[0]);
|
||||||
|
|
||||||
|
@ -710,6 +793,22 @@ __forceinline void NDS_glMultMatrix4x4(signed long v)
|
||||||
|
|
||||||
//todo - make all color conversions go through a properly spread table!!
|
//todo - make all color conversions go through a properly spread table!!
|
||||||
|
|
||||||
|
//I think this is slower than the regular memcmp.. doesnt make sense to me, but my
|
||||||
|
//asm optimization knowlege is 15 years old..
|
||||||
|
__forceinline int memcmp_slow(const void* src, const void* dst, u32 count) {
|
||||||
|
int retval;
|
||||||
|
__asm {
|
||||||
|
mov [retval], 0;
|
||||||
|
mov ecx, [count];
|
||||||
|
shr ecx, 2;
|
||||||
|
mov esi, [src];
|
||||||
|
mov edi, [dst];
|
||||||
|
repe cmpsd;
|
||||||
|
setc byte ptr [retval];
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
__forceinline void* memcpy_fast(void* dest, const void* src, size_t count)
|
__forceinline void* memcpy_fast(void* dest, const void* src, size_t count)
|
||||||
{
|
{
|
||||||
size_t blockCnt = count / 64;
|
size_t blockCnt = count / 64;
|
||||||
|
@ -781,6 +880,7 @@ static void DebugDumpTexture(int which)
|
||||||
}
|
}
|
||||||
|
|
||||||
//================================================================================
|
//================================================================================
|
||||||
|
static int lastTexture = -1;
|
||||||
__forceinline void setTexture(unsigned int format, unsigned int texpal)
|
__forceinline void setTexture(unsigned int format, unsigned int texpal)
|
||||||
{
|
{
|
||||||
int palSize[7]={32,4,16,256,0,8,32768};
|
int palSize[7]={32,4,16,256,0,8,32768};
|
||||||
|
@ -817,17 +917,27 @@ __forceinline void setTexture(unsigned int format, unsigned int texpal)
|
||||||
|
|
||||||
i=texcache_start;
|
i=texcache_start;
|
||||||
|
|
||||||
if(false)
|
//if(false)
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
if (texcache_stop==i) break;
|
if (texcache_stop==i) break;
|
||||||
if (texcache[i].frm==0) break;
|
if (texcache[i].frm==0) break;
|
||||||
if ((texcache[i].frm==format)&&(texcache[i].pal==texpal))
|
if ((texcache[i].frm==format)&&(texcache[i].pal==texpal))
|
||||||
{
|
{
|
||||||
if (!memcmp(adr,texcache[i].texture,imageSize))
|
//TODO - we need to compare the palette also.
|
||||||
|
//TODO - this doesnt correctly span bank boundaries. in fact, it seems quite dangerous.
|
||||||
|
if (!texcache[i].suspectedInvalid || !memcmp(adr,texcache[i].texture,min(imageSize,sizeof(texcache[i].texture))))
|
||||||
{
|
{
|
||||||
|
texcache[i].suspectedInvalid = false;
|
||||||
texcache_count=i;
|
texcache_count=i;
|
||||||
glBindTexture(GL_TEXTURE_2D,texcache[i].id);
|
if(i != lastTexture)
|
||||||
|
{
|
||||||
|
lastTexture = i;
|
||||||
|
glBindTexture(GL_TEXTURE_2D,texcache[i].id);
|
||||||
|
glMatrixMode (GL_TEXTURE);
|
||||||
|
glLoadIdentity ();
|
||||||
|
glScaled (texcache[i].invSizeX, texcache[i].invSizeY, 1.0f);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -846,7 +956,10 @@ __forceinline void setTexture(unsigned int format, unsigned int texpal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastTexture = i;
|
||||||
glBindTexture(GL_TEXTURE_2D, texcache[i].id);
|
glBindTexture(GL_TEXTURE_2D, texcache[i].id);
|
||||||
|
|
||||||
|
texcache[i].suspectedInvalid = false;
|
||||||
texcache[i].mode=textureMode;
|
texcache[i].mode=textureMode;
|
||||||
texcache[i].pal=texpal;
|
texcache[i].pal=texpal;
|
||||||
texcache[i].sizeX=sizeX;
|
texcache[i].sizeX=sizeX;
|
||||||
|
@ -856,11 +969,15 @@ __forceinline void setTexture(unsigned int format, unsigned int texpal)
|
||||||
texcache[i].invSizeY=1.0f/((float)sizeY*(1<<4));
|
texcache[i].invSizeY=1.0f/((float)sizeY*(1<<4));
|
||||||
texcache[i].texenv=envMode;
|
texcache[i].texenv=envMode;
|
||||||
//memcpy(texcache[i].texture,adr,imageSize); //======================= copy
|
//memcpy(texcache[i].texture,adr,imageSize); //======================= copy
|
||||||
memcpy_fast(texcache[i].texture,adr,imageSize); //======================= copy
|
memcpy_fast(texcache[i].texture,adr,min(imageSize,sizeof(texcache[i].texture))); //======================= copy
|
||||||
texcache[i].numcolors=palSize[texcache[i].mode];
|
texcache[i].numcolors=palSize[texcache[i].mode];
|
||||||
|
|
||||||
texcache[i].frm=format;
|
texcache[i].frm=format;
|
||||||
|
|
||||||
|
glMatrixMode (GL_TEXTURE);
|
||||||
|
glLoadIdentity ();
|
||||||
|
glScaled (texcache[i].invSizeX, texcache[i].invSizeY, 1.0f);
|
||||||
|
|
||||||
if(i==62 || textureMode==1) {
|
if(i==62 || textureMode==1) {
|
||||||
int zzz=9;
|
int zzz=9;
|
||||||
}
|
}
|
||||||
|
@ -1135,29 +1252,32 @@ __forceinline void NDS_glBegin(unsigned long v)
|
||||||
tempVertList.count = 0;
|
tempVertList.count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//controls states:
|
||||||
|
//glStencilFunc
|
||||||
|
//glStencilOp
|
||||||
|
//glColorMask
|
||||||
|
static u32 stencilStateSet = -1;
|
||||||
|
|
||||||
static void BeginRenderPoly()
|
static void BeginRenderPoly()
|
||||||
{
|
{
|
||||||
int enableDepthWrite = 1;
|
int enableDepthWrite = 1;
|
||||||
u32 tmp=0;
|
u32 tmp=0;
|
||||||
|
|
||||||
tempVertList.count = 0;
|
xglDepthFunc (depthFuncMode);
|
||||||
|
|
||||||
glDepthFunc (depthFuncMode);
|
|
||||||
|
|
||||||
// Cull face
|
// Cull face
|
||||||
if (cullingMask != 0xC0)
|
if (cullingMask != 0xC0)
|
||||||
{
|
{
|
||||||
glEnable(GL_CULL_FACE);
|
xglEnable(GL_CULL_FACE);
|
||||||
glCullFace(map3d_cull[cullingMask>>6]);
|
glCullFace(map3d_cull[cullingMask>>6]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
glDisable(GL_CULL_FACE);
|
xglDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
// Alpha value, actually not well handled, 0 should be wireframe
|
// Alpha value, actually not well handled, 0 should be wireframe
|
||||||
if (colorAlpha > 0)
|
if (colorAlpha > 0)
|
||||||
{
|
{
|
||||||
glPolygonMode (GL_FRONT, GL_FILL);
|
xglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
||||||
glPolygonMode (GL_BACK, GL_FILL);
|
|
||||||
|
|
||||||
//non-31 alpha polys are translucent
|
//non-31 alpha polys are translucent
|
||||||
if(colorAlpha != 0x7FFFFFFF)
|
if(colorAlpha != 0x7FFFFFFF)
|
||||||
|
@ -1165,21 +1285,10 @@ static void BeginRenderPoly()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glPolygonMode (GL_FRONT, GL_LINE);
|
xglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
|
||||||
glPolygonMode (GL_BACK, GL_LINE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// texture environment
|
|
||||||
setTexture(textureFormat, texturePalette);
|
setTexture(textureFormat, texturePalette);
|
||||||
//=================
|
|
||||||
if (texcache_count!=-1)
|
|
||||||
{
|
|
||||||
texCoordinateTransform = texcache[texcache_count].coord;
|
|
||||||
|
|
||||||
glMatrixMode (GL_TEXTURE);
|
|
||||||
glLoadIdentity ();
|
|
||||||
glScaled (texcache[texcache_count].invSizeX, texcache[texcache_count].invSizeY, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
//a5i3 or a3i5 textures are translucent
|
//a5i3 or a3i5 textures are translucent
|
||||||
alphaDepthWrite = 0; //zero - as a hack, we are never going to write depth buffer for alpha values
|
alphaDepthWrite = 0; //zero - as a hack, we are never going to write depth buffer for alpha values
|
||||||
|
@ -1194,43 +1303,48 @@ static void BeginRenderPoly()
|
||||||
//handle shadow polys
|
//handle shadow polys
|
||||||
if(envMode == 3)
|
if(envMode == 3)
|
||||||
{
|
{
|
||||||
glEnable(GL_STENCIL_TEST);
|
xglEnable(GL_STENCIL_TEST);
|
||||||
if(polyID == 0) {
|
if(polyID == 0) {
|
||||||
//when the polyID is zero, we are writing the shadow mask.
|
|
||||||
//set stencilbuf = 1 where the shadow volume is obstructed by geometry.
|
|
||||||
//do not write color or depth information.
|
|
||||||
glStencilFunc(GL_ALWAYS,2,255);
|
|
||||||
glStencilOp(GL_KEEP,GL_REPLACE,GL_KEEP);
|
|
||||||
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
|
|
||||||
enableDepthWrite = 1;
|
enableDepthWrite = 1;
|
||||||
|
if(stencilStateSet!=0) {
|
||||||
|
stencilStateSet = 0;
|
||||||
|
//when the polyID is zero, we are writing the shadow mask.
|
||||||
|
//set stencilbuf = 1 where the shadow volume is obstructed by geometry.
|
||||||
|
//do not write color or depth information.
|
||||||
|
glStencilFunc(GL_ALWAYS,2,255);
|
||||||
|
glStencilOp(GL_KEEP,GL_REPLACE,GL_KEEP);
|
||||||
|
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
//when the polyid is nonzero, we are drawing the shadow poly.
|
|
||||||
//only draw the shadow poly where the stencilbuf==1.
|
|
||||||
//I am not sure whether to update the depth buffer here--so I chose not to.
|
|
||||||
glStencilFunc(GL_EQUAL,2,255);
|
|
||||||
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
|
|
||||||
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
|
|
||||||
enableDepthWrite = 0;
|
enableDepthWrite = 0;
|
||||||
|
if(stencilStateSet!=1) {
|
||||||
|
stencilStateSet = 1;
|
||||||
|
//when the polyid is nonzero, we are drawing the shadow poly.
|
||||||
|
//only draw the shadow poly where the stencilbuf==1.
|
||||||
|
//I am not sure whether to update the depth buffer here--so I chose not to.
|
||||||
|
glStencilFunc(GL_EQUAL,2,255);
|
||||||
|
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
|
||||||
|
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
glEnable(GL_STENCIL_TEST);
|
xglEnable(GL_STENCIL_TEST);
|
||||||
glStencilFunc(GL_ALWAYS,1,255);
|
if(stencilStateSet!=2) {
|
||||||
glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE);
|
stencilStateSet=2;
|
||||||
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
|
glStencilFunc(GL_ALWAYS,1,255);
|
||||||
|
glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE);
|
||||||
|
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle toon rendering
|
//handle toon rendering
|
||||||
if(glUseProgram) {
|
if(glUseProgram) {
|
||||||
if(envMode == 2) {
|
if(envMode == 2) {
|
||||||
glUseProgram(toonProgram);
|
xglUseProgram(toonProgram);
|
||||||
} else glUseProgram(0);
|
} else xglUseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
glDepthMask(enableDepthWrite?GL_TRUE:GL_FALSE);
|
xglDepthMask(enableDepthWrite?GL_TRUE:GL_FALSE);
|
||||||
|
|
||||||
//just to be sure
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void NDS_glEnd (void)
|
__forceinline void NDS_glEnd (void)
|
||||||
|
@ -1427,60 +1541,6 @@ __forceinline int NDS_glGetNumVertex (void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//NHerve mod3 - Fixed blending with 2D backgrounds (New Super Mario Bros looks better)
|
|
||||||
//zeromus post-mod3: fix even better
|
|
||||||
__forceinline void NDS_glGetLine (int line, unsigned short * dst)
|
|
||||||
{
|
|
||||||
int i, t;
|
|
||||||
u8 *screen3D = (u8 *)&GPU_screen3D [(191-(line%192))*1024];
|
|
||||||
u8 *screenStencil = (u8*)&GPU_screenStencil[(191-(line%192))*256];
|
|
||||||
|
|
||||||
//the renderer clears the stencil to 0
|
|
||||||
//then it sets it to 1 whenever it renders a pixel that passes the alpha test
|
|
||||||
//(it also sets it to 2 under some circumstances when rendering shadow volumes)
|
|
||||||
//so, we COULD use a zero stencil value to indicate that nothing should get composited.
|
|
||||||
//in fact, we are going to do that to fix some problems.
|
|
||||||
//but beware that it i figure it might could CAUSE some problems
|
|
||||||
|
|
||||||
//this alpha compositing blending logic isnt thought through at all
|
|
||||||
//someone needs to think about what bitdepth it should take place at and how to do it efficiently
|
|
||||||
|
|
||||||
u32 a,r,g,b,stencil,oldcolor,oldr,oldg,oldb;
|
|
||||||
|
|
||||||
for(i = 0, t=0; i < 256; i++)
|
|
||||||
{
|
|
||||||
stencil = screenStencil[i];
|
|
||||||
|
|
||||||
//you would use this if you wanted to use the stencil buffer to make decisions here
|
|
||||||
if(!stencil) continue;
|
|
||||||
|
|
||||||
t=i*4;
|
|
||||||
r = screen3D[t+0];
|
|
||||||
g = screen3D[t+1];
|
|
||||||
b = screen3D[t+2];
|
|
||||||
a = screen3D[t+3];
|
|
||||||
|
|
||||||
if(a != 0xFF && a != 0) {
|
|
||||||
int zzz=9;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldcolor = RGB15TO32(dst[i],0);
|
|
||||||
oldr = oldcolor&0xFF;
|
|
||||||
oldg = (oldcolor>>8)&0xFF;
|
|
||||||
oldb = (oldcolor>>16)&0xFF;
|
|
||||||
|
|
||||||
r = (r*a + oldr*(255-a)) / 255;
|
|
||||||
g = (g*a + oldg*(255-a)) / 255;
|
|
||||||
b = (b*a + oldb*(255-a)) / 255;
|
|
||||||
|
|
||||||
r=min(255,r);
|
|
||||||
g=min(255,g);
|
|
||||||
b=min(255,b);
|
|
||||||
|
|
||||||
dst[i] = ((b>>3)<<10) | ((g>>3)<<5) | (r>>3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InstallPolygonAttrib(unsigned long val)
|
static void InstallPolygonAttrib(unsigned long val)
|
||||||
{
|
{
|
||||||
// Light enable/disable
|
// Light enable/disable
|
||||||
|
@ -1512,92 +1572,6 @@ __forceinline void NDS_glPolygonAttrib (unsigned long val)
|
||||||
InstallPolygonAttrib(polyAttr);
|
InstallPolygonAttrib(polyAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void NDS_glFlush(unsigned long v)
|
|
||||||
{
|
|
||||||
u32 wbuffer = v&1;
|
|
||||||
u32 sortmode = (v>>1)&1;
|
|
||||||
|
|
||||||
// Set back some secure render states
|
|
||||||
glPolygonMode (GL_BACK, GL_FILL);
|
|
||||||
glPolygonMode (GL_FRONT, GL_FILL);
|
|
||||||
|
|
||||||
glDepthMask (GL_TRUE);
|
|
||||||
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
||||||
|
|
||||||
//render display list
|
|
||||||
//TODO - properly doublebuffer the display lists
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i=0;i<polylist->count;i++) {
|
|
||||||
POLY *poly = &polylist->list[i];
|
|
||||||
int type = poly->type;
|
|
||||||
int j;
|
|
||||||
InstallPolygonAttrib(poly->polyAttr);
|
|
||||||
textureFormat = poly->texParam;
|
|
||||||
texturePalette = poly->texPalette;
|
|
||||||
BeginRenderPoly();
|
|
||||||
|
|
||||||
//since we havent got the whole pipeline working yet, lets use opengl for the projection
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadMatrixf(poly->projMatrix);
|
|
||||||
|
|
||||||
glBegin(type==3?GL_TRIANGLES:GL_QUADS);
|
|
||||||
for(j=0;j<type;j++) {
|
|
||||||
VERT* vert = &vertlist->list[poly->vertIndexes[j]];
|
|
||||||
|
|
||||||
//float tempCoord[4];
|
|
||||||
//Vector4Copy(tempCoord,vert->coord);
|
|
||||||
//we havent got the whole pipeline working yet, so we cant do this
|
|
||||||
////convert from ds device coords to opengl
|
|
||||||
//tempCoord[0] *= 2;
|
|
||||||
//tempCoord[1] *= 2;
|
|
||||||
//tempCoord[0] -= 1;
|
|
||||||
//tempCoord[1] -= 1;
|
|
||||||
|
|
||||||
//todo - edge flag?
|
|
||||||
glTexCoord2fv(vert->texcoord);
|
|
||||||
glColor4iv(vert->color);
|
|
||||||
//glVertex3fv(tempCoord);
|
|
||||||
glVertex3fv(vert->coord);
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
twiddleLists();
|
|
||||||
|
|
||||||
//reset gpu state
|
|
||||||
clCmd = 0;
|
|
||||||
clInd = 0;
|
|
||||||
|
|
||||||
//capture rendering results
|
|
||||||
glFlush();
|
|
||||||
glReadPixels(0,0,256,192,GL_RGBA, GL_UNSIGNED_BYTE, GPU_screen3D);
|
|
||||||
glReadPixels(0,0,256,192,GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, GPU_screenStencil);
|
|
||||||
|
|
||||||
//debug: view depth buffer via color buffer for debugging
|
|
||||||
{
|
|
||||||
//int ctr=0;
|
|
||||||
//for(ctr=0;ctr<256*192;ctr++) {
|
|
||||||
// float zval = GPU_screen3Ddepth[ctr];
|
|
||||||
// u8* colorPtr = GPU_screen3D+ctr*3;
|
|
||||||
// if(zval<0) {
|
|
||||||
// colorPtr[0] = 255;
|
|
||||||
// colorPtr[1] = 0;
|
|
||||||
// colorPtr[2] = 0;
|
|
||||||
// } else if(zval>1) {
|
|
||||||
// colorPtr[0] = 0;
|
|
||||||
// colorPtr[1] = 0;
|
|
||||||
// colorPtr[2] = 255;
|
|
||||||
// } else {
|
|
||||||
// colorPtr[0] = colorPtr[1] = colorPtr[2] = zval*255;
|
|
||||||
// //printlog("%f %f %d\n",zval, zval*255,colorPtr[0]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
0-4 Diffuse Reflection Red
|
0-4 Diffuse Reflection Red
|
||||||
5-9 Diffuse Reflection Green
|
5-9 Diffuse Reflection Green
|
||||||
|
@ -1734,6 +1708,7 @@ __forceinline void NDS_glLightColor (unsigned long v)
|
||||||
__forceinline void NDS_glAlphaFunc(unsigned long v)
|
__forceinline void NDS_glAlphaFunc(unsigned long v)
|
||||||
{
|
{
|
||||||
alphaTestRef = (v&31)/31.f;
|
alphaTestRef = (v&31)/31.f;
|
||||||
|
glAlphaFunc (GL_GREATER, alphaTestBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void NDS_glControl(unsigned long v)
|
__forceinline void NDS_glControl(unsigned long v)
|
||||||
|
@ -1749,11 +1724,11 @@ __forceinline void NDS_glControl(unsigned long v)
|
||||||
|
|
||||||
if(v&(1<<2))
|
if(v&(1<<2))
|
||||||
{
|
{
|
||||||
//glAlphaFunc (GL_GREATER, alphaTestBase);
|
glAlphaFunc (GL_GREATER, alphaTestBase);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//glAlphaFunc (GL_GREATER, 0.1f);
|
glAlphaFunc (GL_GREATER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(v&(1<<3))
|
if(v&(1<<3))
|
||||||
|
@ -1878,6 +1853,181 @@ __forceinline void NDS_glNormal(unsigned long v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool flushPending = false;
|
||||||
|
static u32 flush_wbuffer;
|
||||||
|
static u32 flush_sortmode;
|
||||||
|
|
||||||
|
void NDS_glFlush(unsigned long v)
|
||||||
|
{
|
||||||
|
flushPending = true;
|
||||||
|
flush_wbuffer = v&1;
|
||||||
|
flush_sortmode = (v>>1)&1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_Draw()
|
||||||
|
{
|
||||||
|
xglDepthMask (GL_TRUE);
|
||||||
|
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
|
//render display list
|
||||||
|
//TODO - properly doublebuffer the display lists
|
||||||
|
{
|
||||||
|
|
||||||
|
u32 lastTextureFormat, lastTexturePalette, lastPolyAttr;
|
||||||
|
|
||||||
|
for(int i=0;i<polylist->count;i++) {
|
||||||
|
POLY *poly = &polylist->list[i];
|
||||||
|
int type = poly->type;
|
||||||
|
|
||||||
|
//a very macro-level state caching approach:
|
||||||
|
//these are the only things which control the GPU rendering state.
|
||||||
|
if(i==0 || lastTextureFormat != poly->texParam || lastTexturePalette != poly->texPalette || lastPolyAttr != poly->polyAttr)
|
||||||
|
{
|
||||||
|
InstallPolygonAttrib(lastPolyAttr=poly->polyAttr);
|
||||||
|
lastTextureFormat = textureFormat = poly->texParam;
|
||||||
|
lastTexturePalette = texturePalette = poly->texPalette;
|
||||||
|
BeginRenderPoly();
|
||||||
|
}
|
||||||
|
|
||||||
|
//since we havent got the whole pipeline working yet, lets use opengl for the projection
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadMatrixf(poly->projMatrix);
|
||||||
|
|
||||||
|
glBegin(type==3?GL_TRIANGLES:GL_QUADS);
|
||||||
|
for(int j=0;j<type;j++) {
|
||||||
|
VERT* vert = &vertlist->list[poly->vertIndexes[j]];
|
||||||
|
|
||||||
|
//float tempCoord[4];
|
||||||
|
//Vector4Copy(tempCoord,vert->coord);
|
||||||
|
//we havent got the whole pipeline working yet, so we cant do this
|
||||||
|
////convert from ds device coords to opengl
|
||||||
|
//tempCoord[0] *= 2;
|
||||||
|
//tempCoord[1] *= 2;
|
||||||
|
//tempCoord[0] -= 1;
|
||||||
|
//tempCoord[1] -= 1;
|
||||||
|
|
||||||
|
//todo - edge flag?
|
||||||
|
glTexCoord2fv(vert->texcoord);
|
||||||
|
glColor4iv(vert->color);
|
||||||
|
//glVertex3fv(tempCoord);
|
||||||
|
glVertex3fv(vert->coord);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//since we just redrew, we need to refresh the framebuffers
|
||||||
|
needRefreshFramebuffer = true;
|
||||||
|
|
||||||
|
twiddleLists();
|
||||||
|
|
||||||
|
//reset GE state
|
||||||
|
clCmd = 0;
|
||||||
|
clInd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NDS_3D_VBlankSignal()
|
||||||
|
{
|
||||||
|
//the 3d buffers are swapped when a vblank begins.
|
||||||
|
//so, if we have a redraw pending, now is a safe time to do it
|
||||||
|
if(!flushPending) return;
|
||||||
|
flushPending = false;
|
||||||
|
GL_Draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NDS_3D_VramReconfigureSignal()
|
||||||
|
{
|
||||||
|
//well, this is a very blunt instrument.
|
||||||
|
//lets just flag all the textures as invalid.
|
||||||
|
for(int i=0;i<MAX_TEXTURE+1;i++)
|
||||||
|
texcache[i].suspectedInvalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_ReadFramebuffer()
|
||||||
|
{
|
||||||
|
glFinish();
|
||||||
|
glReadPixels(0,0,256,192,GL_RGBA, GL_UNSIGNED_BYTE, GPU_screen3D);
|
||||||
|
glReadPixels(0,0,256,192,GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, GPU_screenStencil);
|
||||||
|
|
||||||
|
//debug: view depth buffer via color buffer for debugging
|
||||||
|
//int ctr=0;
|
||||||
|
//for(ctr=0;ctr<256*192;ctr++) {
|
||||||
|
// float zval = GPU_screen3Ddepth[ctr];
|
||||||
|
// u8* colorPtr = GPU_screen3D+ctr*3;
|
||||||
|
// if(zval<0) {
|
||||||
|
// colorPtr[0] = 255;
|
||||||
|
// colorPtr[1] = 0;
|
||||||
|
// colorPtr[2] = 0;
|
||||||
|
// } else if(zval>1) {
|
||||||
|
// colorPtr[0] = 0;
|
||||||
|
// colorPtr[1] = 0;
|
||||||
|
// colorPtr[2] = 255;
|
||||||
|
// } else {
|
||||||
|
// colorPtr[0] = colorPtr[1] = colorPtr[2] = zval*255;
|
||||||
|
// //printlog("%f %f %d\n",zval, zval*255,colorPtr[0]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
//NHerve mod3 - Fixed blending with 2D backgrounds (New Super Mario Bros looks better)
|
||||||
|
//zeromus post-mod3: fix even better
|
||||||
|
__forceinline void NDS_glGetLine (int line, unsigned short * dst)
|
||||||
|
{
|
||||||
|
if(needRefreshFramebuffer) {
|
||||||
|
needRefreshFramebuffer = false;
|
||||||
|
GL_ReadFramebuffer();
|
||||||
|
}
|
||||||
|
int i, t;
|
||||||
|
u8 *screen3D = (u8 *)&GPU_screen3D [(191-(line%192))*1024];
|
||||||
|
u8 *screenStencil = (u8*)&GPU_screenStencil[(191-(line%192))*256];
|
||||||
|
|
||||||
|
//the renderer clears the stencil to 0
|
||||||
|
//then it sets it to 1 whenever it renders a pixel that passes the alpha test
|
||||||
|
//(it also sets it to 2 under some circumstances when rendering shadow volumes)
|
||||||
|
//so, we COULD use a zero stencil value to indicate that nothing should get composited.
|
||||||
|
//in fact, we are going to do that to fix some problems.
|
||||||
|
//but beware that it i figure it might could CAUSE some problems
|
||||||
|
|
||||||
|
//this alpha compositing blending logic isnt thought through at all
|
||||||
|
//someone needs to think about what bitdepth it should take place at and how to do it efficiently
|
||||||
|
|
||||||
|
u32 a,r,g,b,stencil,oldcolor,oldr,oldg,oldb;
|
||||||
|
|
||||||
|
for(i = 0, t=0; i < 256; i++)
|
||||||
|
{
|
||||||
|
stencil = screenStencil[i];
|
||||||
|
|
||||||
|
//you would use this if you wanted to use the stencil buffer to make decisions here
|
||||||
|
if(!stencil) continue;
|
||||||
|
|
||||||
|
t=i*4;
|
||||||
|
r = screen3D[t+0];
|
||||||
|
g = screen3D[t+1];
|
||||||
|
b = screen3D[t+2];
|
||||||
|
a = screen3D[t+3];
|
||||||
|
|
||||||
|
if(a != 0xFF && a != 0) {
|
||||||
|
int zzz=9;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldcolor = RGB15TO32(dst[i],0);
|
||||||
|
oldr = oldcolor&0xFF;
|
||||||
|
oldg = (oldcolor>>8)&0xFF;
|
||||||
|
oldb = (oldcolor>>16)&0xFF;
|
||||||
|
|
||||||
|
r = (r*a + oldr*(255-a)) / 255;
|
||||||
|
g = (g*a + oldg*(255-a)) / 255;
|
||||||
|
b = (b*a + oldb*(255-a)) / 255;
|
||||||
|
|
||||||
|
r=min(255,r);
|
||||||
|
g=min(255,g);
|
||||||
|
b=min(255,b);
|
||||||
|
|
||||||
|
dst[i] = ((b>>3)<<10) | ((g>>3)<<5) | (r>>3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
__forceinline void NDS_glBoxTest(unsigned long v)
|
__forceinline void NDS_glBoxTest(unsigned long v)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -2405,7 +2555,9 @@ GPU3DInterface gpu3Dgl = { NDS_glInit,
|
||||||
NDS_glVecTest,
|
NDS_glVecTest,
|
||||||
NDS_glGetPosRes,
|
NDS_glGetPosRes,
|
||||||
NDS_glGetVecRes,
|
NDS_glGetVecRes,
|
||||||
NDS_3D_UpdateToonTable
|
NDS_3D_UpdateToonTable,
|
||||||
|
NDS_3D_VBlankSignal,
|
||||||
|
NDS_3D_VramReconfigureSignal,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,7 @@
|
||||||
# define ZEXTERN extern
|
# define ZEXTERN extern
|
||||||
#endif
|
#endif
|
||||||
#ifndef ZEXPORT
|
#ifndef ZEXPORT
|
||||||
# define ZEXPORT
|
# define ZEXPORT __cdecl
|
||||||
#endif
|
#endif
|
||||||
#ifndef ZEXPORTVA
|
#ifndef ZEXPORTVA
|
||||||
# define ZEXPORTVA
|
# define ZEXPORTVA
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#ifndef _ZZIP__MSVC_H
|
#ifndef _ZZIP__MSVC_H
|
||||||
#define _ZZIP__MSVC_H 1
|
#define _ZZIP__MSVC_H 1
|
||||||
|
|
||||||
|
#define _zzip_calltype __cdecl
|
||||||
|
|
||||||
/* zzip/_msvc.h. Generated automatically at end of configure. */
|
/* zzip/_msvc.h. Generated automatically at end of configure. */
|
||||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
|
@ -94,9 +94,9 @@ struct zzip_dirent
|
||||||
* zzip/err.c
|
* zzip/err.c
|
||||||
*/
|
*/
|
||||||
_zzip_export /* error in _opendir : */
|
_zzip_export /* error in _opendir : */
|
||||||
zzip_char_t* zzip_strerror(int errcode);
|
zzip_char_t* _zzip_calltype zzip_strerror(int errcode);
|
||||||
_zzip_export /* error in other functions : */
|
_zzip_export /* error in other functions : */
|
||||||
zzip_char_t* zzip_strerror_of(ZZIP_DIR * dir);
|
zzip_char_t* _zzip_calltype zzip_strerror_of(ZZIP_DIR * dir);
|
||||||
_zzip_export /* error mapped to errno.h defines : */
|
_zzip_export /* error mapped to errno.h defines : */
|
||||||
int zzip_errno(int errcode);
|
int zzip_errno(int errcode);
|
||||||
|
|
||||||
|
@ -107,46 +107,46 @@ int zzip_errno(int errcode);
|
||||||
* zzip/info.c
|
* zzip/info.c
|
||||||
*/
|
*/
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_error(ZZIP_DIR * dir);
|
int _zzip_calltype zzip_error(ZZIP_DIR * dir);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
void zzip_seterror(ZZIP_DIR * dir, int errcode);
|
void _zzip_calltype zzip_seterror(ZZIP_DIR * dir, int errcode);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
zzip_char_t* zzip_compr_str(int compr);
|
zzip_char_t* zzip_compr_str(int compr);
|
||||||
|
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_DIR * zzip_dirhandle(ZZIP_FILE * fp);
|
ZZIP_DIR * _zzip_calltype zzip_dirhandle(ZZIP_FILE * fp);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_dirfd(ZZIP_DIR * dir);
|
int _zzip_calltype zzip_dirfd(ZZIP_DIR * dir);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_dir_real(ZZIP_DIR * dir);
|
int _zzip_calltype zzip_dir_real(ZZIP_DIR * dir);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_file_real(ZZIP_FILE * fp);
|
int _zzip_calltype zzip_file_real(ZZIP_FILE * fp);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
void* zzip_realdir(ZZIP_DIR * dir);
|
void* _zzip_calltype zzip_realdir(ZZIP_DIR * dir);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_realfd(ZZIP_FILE * fp);
|
int _zzip_calltype zzip_realfd(ZZIP_FILE * fp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* zip handle management
|
* zip handle management
|
||||||
* zzip/zip.c
|
* zzip/zip.c
|
||||||
*/
|
*/
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_DIR * zzip_dir_alloc(zzip_strings_t* fileext);
|
ZZIP_DIR * _zzip_calltype zzip_dir_alloc(zzip_strings_t* fileext);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_dir_free(ZZIP_DIR *);
|
int _zzip_calltype zzip_dir_free(ZZIP_DIR *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opening/closing a zip archive
|
* Opening/closing a zip archive
|
||||||
* zzip-zip.c
|
* zzip-zip.c
|
||||||
*/
|
*/
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_DIR * zzip_dir_fdopen(int fd, zzip_error_t * errcode_p);
|
ZZIP_DIR * _zzip_calltype zzip_dir_fdopen(int fd, zzip_error_t * errcode_p);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_DIR * zzip_dir_open(zzip_char_t* filename, zzip_error_t * errcode_p);
|
ZZIP_DIR * _zzip_calltype zzip_dir_open(zzip_char_t* filename, zzip_error_t * errcode_p);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_dir_close(ZZIP_DIR * dir);
|
int _zzip_calltype zzip_dir_close(ZZIP_DIR * dir);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_dir_read(ZZIP_DIR * dir, ZZIP_DIRENT * dirent);
|
int _zzip_calltype zzip_dir_read(ZZIP_DIR * dir, ZZIP_DIRENT * dirent);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -155,46 +155,46 @@ int zzip_dir_read(ZZIP_DIR * dir, ZZIP_DIRENT * dirent);
|
||||||
* zzip/zip.c
|
* zzip/zip.c
|
||||||
*/
|
*/
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_DIR * zzip_opendir(zzip_char_t* filename);
|
ZZIP_DIR * _zzip_calltype zzip_opendir(zzip_char_t* filename);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_closedir(ZZIP_DIR * dir);
|
int _zzip_calltype zzip_closedir(ZZIP_DIR * dir);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_DIRENT * zzip_readdir(ZZIP_DIR * dir);
|
ZZIP_DIRENT * _zzip_calltype zzip_readdir(ZZIP_DIR * dir);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
void zzip_rewinddir(ZZIP_DIR * dir);
|
void _zzip_calltype zzip_rewinddir(ZZIP_DIR * dir);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
zzip_off_t zzip_telldir(ZZIP_DIR * dir);
|
zzip_off_t _zzip_calltype zzip_telldir(ZZIP_DIR * dir);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
void zzip_seekdir(ZZIP_DIR * dir, zzip_off_t offset);
|
void _zzip_calltype zzip_seekdir(ZZIP_DIR * dir, zzip_off_t offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 'opening', 'closing' and reading invidual files in zip archive.
|
* 'opening', 'closing' and reading invidual files in zip archive.
|
||||||
* zzip/file.c
|
* zzip/file.c
|
||||||
*/
|
*/
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_FILE * zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int flags);
|
ZZIP_FILE * _zzip_calltype zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int flags);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_file_close(ZZIP_FILE * fp);
|
int _zzip_calltype zzip_file_close(ZZIP_FILE * fp);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
zzip_ssize_t zzip_file_read(ZZIP_FILE * fp, void* buf, zzip_size_t len);
|
zzip_ssize_t _zzip_calltype zzip_file_read(ZZIP_FILE * fp, void* buf, zzip_size_t len);
|
||||||
|
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_FILE * zzip_open(zzip_char_t* name, int flags);
|
ZZIP_FILE * _zzip_calltype zzip_open(zzip_char_t* name, int flags);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_close(ZZIP_FILE * fp);
|
int _zzip_calltype zzip_close(ZZIP_FILE * fp);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
zzip_ssize_t zzip_read(ZZIP_FILE * fp, void * buf, zzip_size_t len);
|
zzip_ssize_t _zzip_calltype zzip_read(ZZIP_FILE * fp, void * buf, zzip_size_t len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the stdc variant to open/read/close files. - Take note of the freopen()
|
* the stdc variant to open/read/close files. - Take note of the freopen()
|
||||||
* call as it may reuse an existing preparsed copy of a zip central directory
|
* call as it may reuse an existing preparsed copy of a zip central directory
|
||||||
*/
|
*/
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_FILE* zzip_freopen(zzip_char_t* name, zzip_char_t* mode, ZZIP_FILE*);
|
ZZIP_FILE* _zzip_calltype zzip_freopen(zzip_char_t* name, zzip_char_t* mode, ZZIP_FILE*);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_FILE* zzip_fopen(zzip_char_t* name, zzip_char_t* mode);
|
ZZIP_FILE* _zzip_calltype zzip_fopen(zzip_char_t* name, zzip_char_t* mode);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
zzip_size_t zzip_fread(void *ptr, zzip_size_t size, zzip_size_t nmemb,
|
zzip_size_t _zzip_calltype zzip_fread(void *ptr, zzip_size_t size, zzip_size_t nmemb,
|
||||||
ZZIP_FILE * file);
|
ZZIP_FILE * file);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_fclose(ZZIP_FILE * fp);
|
int zzip_fclose(ZZIP_FILE * fp);
|
||||||
|
@ -203,23 +203,23 @@ int zzip_fclose(ZZIP_FILE * fp);
|
||||||
* seek and tell functions
|
* seek and tell functions
|
||||||
*/
|
*/
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_rewind(ZZIP_FILE *fp);
|
int _zzip_calltype zzip_rewind(ZZIP_FILE *fp);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
zzip_off_t zzip_seek(ZZIP_FILE * fp, zzip_off_t offset, int whence);
|
zzip_off_t _zzip_calltype zzip_seek(ZZIP_FILE * fp, zzip_off_t offset, int whence);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
zzip_off_t zzip_tell(ZZIP_FILE * fp);
|
zzip_off_t _zzip_calltype zzip_tell(ZZIP_FILE * fp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* reading info of a single file
|
* reading info of a single file
|
||||||
* zzip/stat.c
|
* zzip/stat.c
|
||||||
*/
|
*/
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_dir_stat(ZZIP_DIR * dir, zzip_char_t* name,
|
int _zzip_calltype zzip_dir_stat(ZZIP_DIR * dir, zzip_char_t* name,
|
||||||
ZZIP_STAT * zs, int flags);
|
ZZIP_STAT * zs, int flags);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_file_stat(ZZIP_FILE * fp, ZZIP_STAT * zs);
|
int _zzip_calltype zzip_file_stat(ZZIP_FILE * fp, ZZIP_STAT * zs);
|
||||||
_zzip_export
|
_zzip_export
|
||||||
int zzip_fstat(ZZIP_FILE * fp, ZZIP_STAT * zs);
|
int _zzip_calltype zzip_fstat(ZZIP_FILE * fp, ZZIP_STAT * zs);
|
||||||
|
|
||||||
#ifdef ZZIP_LARGEFILE_RENAME
|
#ifdef ZZIP_LARGEFILE_RENAME
|
||||||
#define zzip_open_shared_io zzip_open_shared_io64
|
#define zzip_open_shared_io zzip_open_shared_io64
|
||||||
|
@ -236,20 +236,20 @@ int zzip_fstat(ZZIP_FILE * fp, ZZIP_STAT * zs);
|
||||||
typedef union _zzip_plugin_io _zzip_const * zzip_plugin_io_t;
|
typedef union _zzip_plugin_io _zzip_const * zzip_plugin_io_t;
|
||||||
|
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_FILE * zzip_open_shared_io(ZZIP_FILE* stream,
|
ZZIP_FILE * _zzip_calltype zzip_open_shared_io(ZZIP_FILE* stream,
|
||||||
zzip_char_t* name, int o_flags, int o_modes,
|
zzip_char_t* name, int o_flags, int o_modes,
|
||||||
zzip_strings_t* ext, zzip_plugin_io_t io);
|
zzip_strings_t* ext, zzip_plugin_io_t io);
|
||||||
|
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_FILE * zzip_open_ext_io(zzip_char_t* name, int o_flags, int o_modes,
|
ZZIP_FILE * _zzip_calltype zzip_open_ext_io(zzip_char_t* name, int o_flags, int o_modes,
|
||||||
zzip_strings_t* ext, zzip_plugin_io_t io);
|
zzip_strings_t* ext, zzip_plugin_io_t io);
|
||||||
|
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_DIR * zzip_opendir_ext_io(zzip_char_t* name, int o_modes,
|
ZZIP_DIR * _zzip_calltype zzip_opendir_ext_io(zzip_char_t* name, int o_modes,
|
||||||
zzip_strings_t* ext, zzip_plugin_io_t io);
|
zzip_strings_t* ext, zzip_plugin_io_t io);
|
||||||
|
|
||||||
_zzip_export
|
_zzip_export
|
||||||
ZZIP_DIR * zzip_dir_open_ext_io(zzip_char_t* filename,
|
ZZIP_DIR * _zzip_calltype zzip_dir_open_ext_io(zzip_char_t* filename,
|
||||||
zzip_error_t* errcode_p,
|
zzip_error_t* errcode_p,
|
||||||
zzip_strings_t* ext, zzip_plugin_io_t io);
|
zzip_strings_t* ext, zzip_plugin_io_t io);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue