Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
skygfx_vc/src/main.cpp
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1086 lines (932 sloc)
32.7 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "skygfx.h" | |
| #include "ini_parser.hpp" | |
| #include "d3d8.h" | |
| #include "d3d8types.h" | |
| #include "debugmenu_public.h" | |
| HMODULE dllModule; | |
| DebugMenuAPI gDebugMenuAPI; | |
| char asipath[MAX_PATH]; | |
| int gtaversion = -1; | |
| void enableTrailsSetting(void); | |
| void patchWater(void); | |
| char* | |
| getpath(char *path) | |
| { | |
| static char tmppath[MAX_PATH]; | |
| FILE *f; | |
| f = fopen(path, "r"); | |
| if(f){ | |
| fclose(f); | |
| return path; | |
| } | |
| strncpy(tmppath, asipath, MAX_PATH); | |
| strcat(tmppath, path); | |
| f = fopen(tmppath, "r"); | |
| if(f){ | |
| fclose(f); | |
| return tmppath; | |
| } | |
| return NULL; | |
| } | |
| static addr rwD3D8RasterIsCubeRaster_A = AddressByVersion<addr>(0, 0, 0, 0x63EE40, 0x63EE90, 0x63DDF0); // VC only | |
| WRAPPER int rwD3D8RasterIsCubeRaster(RwRaster*) { VARJMP(rwD3D8RasterIsCubeRaster_A); } | |
| void **&RwEngineInst = *AddressByVersion<void***>(0x661228, 0x661228, 0x671248, 0x7870C0, 0x7870C8, 0x7860C8); | |
| RpLight *&pAmbient = *AddressByVersion<RpLight**>(0x885B6C, 0x885B1C, 0x895C5C, 0x974B44, 0x974B4C, 0x973B4C); | |
| RpLight *&pDirect = *AddressByVersion<RpLight**>(0x880F7C, 0x880F2C, 0x89106C, 0x94DD40, 0x94DD48, 0x94CD48); | |
| RpLight **pExtraDirectionals = AddressByVersion<RpLight**>(0x60009C, 0x5FFE84, 0x60CE7C, 0x69A140, 0x69A140, 0x699140); | |
| int &NumExtraDirLightsInWorld = *AddressByVersion<int*>(0x64C608, 0x64C608, 0x65C608, 0x94DB48, 0x94DB50, 0x94CB50); | |
| GlobalScene &Scene = *AddressByVersion<GlobalScene*>(0x726768, 0x726768, 0x7368A8, 0x8100B8, 0x8100C0, 0x80F0C0); | |
| RwD3D8Vertex *blurVertices = AddressByVersion<RwD3D8Vertex*>(0x62F780, 0x62F780, 0x63F780, 0x7097A8, 0x7097A8, 0x7087A8); | |
| RwImVertexIndex *blurIndices = AddressByVersion<RwImVertexIndex*>(0x5FDD90, 0x5FDB78, 0x60AB70, 0x697D48, 0x697D48, 0x696D50); | |
| static addr DefinedState_A = AddressByVersion<addr>(0x526330, 0x526570, 0x526500, 0x57F9C0, 0x57F9E0, 0x57F7F0); | |
| WRAPPER void DefinedState(void) { VARJMP(DefinedState_A); } | |
| RsGlobalType &RsGlobal = *AddressByVersion<RsGlobalType*>(0x8F4360, 0, 0, 0, 0, 0); | |
| SkyGFXConfig config; | |
| bool d3d9; | |
| extern "C" { | |
| __declspec(dllexport) int | |
| SkyGFXGetVersion(const char *s) | |
| { | |
| return VERSION; | |
| } | |
| __declspec(dllexport) int | |
| SkyGFXGetParam(const char *s) | |
| { | |
| #define X(v) if(strcmp(s, #v) == 0) return config.v; | |
| INTPARAMS | |
| #undef X | |
| return 0; | |
| } | |
| __declspec(dllexport) void | |
| SkyGFXSetParam(const char *s, int val) | |
| { | |
| #define X(v) if(strcmp(s, #v) == 0) { config.v = val; return; } | |
| INTPARAMS | |
| #undef X | |
| } | |
| __declspec(dllexport) float | |
| SkyGFXGetParamF(const char *s) | |
| { | |
| #define X(v) if(strcmp(s, #v) == 0) return config.v; | |
| FLOATPARAMS | |
| #undef X | |
| return 0; | |
| } | |
| __declspec(dllexport) void | |
| SkyGFXSetParamF(const char *s, float val) | |
| { | |
| #define X(v) if(strcmp(s, #v) == 0) { config.v = val; return; } | |
| FLOATPARAMS | |
| #undef X | |
| } | |
| __declspec(dllexport) void* | |
| SkyGFXGetParamPtr(const char *s) | |
| { | |
| #define X(v) if(strcmp(s, #v) == 0) return (void*)&config.v; | |
| INTPARAMS | |
| FLOATPARAMS | |
| #undef X | |
| return 0; | |
| } | |
| } | |
| MatFXEnv* | |
| getEnvData(RpMaterial *mat) | |
| { | |
| MatFX *matfx = *RWPLUGINOFFSET(MatFX*, mat, MatFXMaterialDataOffset); | |
| if(matfx == nil || matfx->effects != rpMATFXEFFECTENVMAP && matfx->effects != rpMATFXEFFECTBUMPENVMAP) | |
| return nil; | |
| MatFXNothing *n = &matfx->fx[0].n; | |
| if(n->effect == rpMATFXEFFECTENVMAP) | |
| return (MatFXEnv*)n; | |
| n = &matfx->fx[1].n; | |
| if(n->effect == rpMATFXEFFECTENVMAP) | |
| return (MatFXEnv*)n; | |
| return nil; | |
| } | |
| void | |
| rwtod3dmat(D3DMATRIX *d3d, RwMatrix *rw) | |
| { | |
| d3d->m[0][0] = rw->right.x; | |
| d3d->m[0][1] = rw->right.y; | |
| d3d->m[0][2] = rw->right.z; | |
| d3d->m[0][3] = 0.0f; | |
| d3d->m[1][0] = rw->up.x; | |
| d3d->m[1][1] = rw->up.y; | |
| d3d->m[1][2] = rw->up.z; | |
| d3d->m[1][3] = 0.0f; | |
| d3d->m[2][0] = rw->at.x; | |
| d3d->m[2][1] = rw->at.y; | |
| d3d->m[2][2] = rw->at.z; | |
| d3d->m[2][3] = 0.0f; | |
| d3d->m[3][0] = rw->pos.x; | |
| d3d->m[3][1] = rw->pos.y; | |
| d3d->m[3][2] = rw->pos.z; | |
| d3d->m[3][3] = 1.0f; | |
| } | |
| void | |
| d3dtorwmat(RwMatrix *rw, D3DMATRIX *d3d) | |
| { | |
| rw->right.x = d3d->m[0][0]; | |
| rw->right.y = d3d->m[0][1]; | |
| rw->right.z = d3d->m[0][2]; | |
| rw->up.x = d3d->m[1][0]; | |
| rw->up.y = d3d->m[1][1]; | |
| rw->up.z = d3d->m[1][2]; | |
| rw->at.x = d3d->m[2][0]; | |
| rw->at.y = d3d->m[2][1]; | |
| rw->at.z = d3d->m[2][2]; | |
| rw->pos.x = d3d->m[3][0]; | |
| rw->pos.y = d3d->m[3][1]; | |
| rw->pos.z = d3d->m[3][2]; | |
| } | |
| void | |
| _rwD3D8EnableClippingIfNeeded(void *object, RwUInt8 type) | |
| { | |
| int clip; | |
| if(type == rpATOMIC) | |
| clip = !RwD3D8CameraIsSphereFullyInsideFrustum((RwCamera*)((RwGlobals*)RwEngineInst)->curCamera, | |
| RpAtomicGetWorldBoundingSphere((RpAtomic*)object)); | |
| else | |
| clip = !RwD3D8CameraIsBBoxFullyInsideFrustum((RwCamera*)((RwGlobals*)RwEngineInst)->curCamera, | |
| &((RpWorldSector*)object)->tightBoundingBox); | |
| RwD3D8SetRenderState(D3DRS_CLIPPING, clip); | |
| } | |
| RwFrame* | |
| createIIIEnvFrame(void) | |
| { | |
| RwFrame *f; | |
| f = RwFrameCreate(); | |
| f->modelling.right.x = 1.0f; | |
| f->modelling.right.y = 0.0f; | |
| f->modelling.right.z = 0.0f; | |
| f->modelling.at.x = 0.0f; | |
| f->modelling.at.y = 0.0f; | |
| f->modelling.at.z = 1.0f; | |
| f->modelling.up.x = 0.0f; | |
| f->modelling.up.y = 1.0f; | |
| f->modelling.up.z = 0.0f; | |
| f->modelling.pos.x = 0.0f; | |
| f->modelling.pos.y = 0.0f; | |
| f->modelling.pos.z = 0.0f; | |
| f->modelling.flags |= 0x20003; | |
| RwFrameUpdateObjects(f); | |
| RwFrameGetLTM(f); | |
| return f; | |
| } | |
| void | |
| drawDualPass(RxD3D8InstanceData *inst) | |
| { | |
| if(!config.dualpass){ | |
| if(inst->indexBuffer){ | |
| RwD3D8SetIndices(inst->indexBuffer, inst->baseIndex); | |
| RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices); | |
| }else | |
| RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices); | |
| return; | |
| } | |
| RwD3D8SetIndices(inst->indexBuffer, inst->baseIndex); | |
| int hasAlpha, alphafunc, alpharef, zwrite; | |
| RwD3D8GetRenderState(D3DRS_ALPHABLENDENABLE, &hasAlpha); | |
| RwD3D8GetRenderState(D3DRS_ZWRITEENABLE, &zwrite); | |
| if(hasAlpha && zwrite){ | |
| RwD3D8GetRenderState(D3DRS_ALPHAFUNC, &alphafunc); | |
| RwD3D8GetRenderState(D3DRS_ALPHAREF, &alpharef); | |
| RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); | |
| RwD3D8SetRenderState(D3DRS_ALPHAREF, 128); | |
| if(inst->indexBuffer) RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices); | |
| else RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices); | |
| RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS); | |
| RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE); | |
| if(inst->indexBuffer) RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices); | |
| else RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices); | |
| RwD3D8SetRenderState(D3DRS_ALPHAFUNC, alphafunc); | |
| RwD3D8SetRenderState(D3DRS_ALPHAREF, alpharef); | |
| RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); | |
| }else{ | |
| if(inst->indexBuffer) RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices); | |
| else RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices); | |
| } | |
| } | |
| static addr dualPassHook_R = AddressByVersion<addr>(0x5DFBD8, 0x5DFE98, 0, 0x678DA8, 0x678DF8, 0x677D58); | |
| void __declspec(naked) | |
| dualPassHook(void) | |
| { | |
| _asm{ | |
| lea eax, [esi-10h] | |
| push eax | |
| call drawDualPass | |
| pop eax | |
| push dword ptr dualPassHook_R | |
| retn | |
| } | |
| } | |
| void __declspec(naked) | |
| dualPassHook_IIISteam(void) | |
| { | |
| _asm{ | |
| push ebx | |
| call drawDualPass | |
| mov dword ptr [esp], 0x5EE6B2 | |
| retn | |
| } | |
| } | |
| void | |
| renderSniperTrails(RwRaster *raster) | |
| { | |
| RwRGBA color; | |
| color.red = 180; | |
| color.green = 255; | |
| color.blue = 180; | |
| color.alpha = 120; | |
| DefinedState(); | |
| RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)1); | |
| RwRenderStateSet(rwRENDERSTATEFOGENABLE, 0); | |
| RwRenderStateSet(rwRENDERSTATEZTESTENABLE, 0); | |
| RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, 0); | |
| RwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster); | |
| RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)1); | |
| RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); | |
| RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); | |
| RwUInt32 emissiveColor = D3DCOLOR_ARGB(color.alpha, color.red, color.green, color.blue); | |
| for(int i = 0; i < 4; i++) | |
| blurVertices[i].emissiveColor = emissiveColor; | |
| RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, blurVertices, 4, blurIndices, 6); | |
| } | |
| static addr &sniperTrailsHook_unk_addr = *AddressByVersion<addr*>(0, 0, 0, 0x97F888, 0x97F890, 0x97E890); | |
| static addr sniperTrailsHook_R = AddressByVersion<addr>(0, 0, 0, 0x55EB90, 0x55EBB0, 0x55EA80); | |
| void __declspec(naked) | |
| sniperTrailsHook(void) | |
| { | |
| _asm{ | |
| push [esp+28h]; | |
| call renderSniperTrails | |
| pop eax | |
| } | |
| sniperTrailsHook_unk_addr = 0; | |
| _asm{ | |
| push dword ptr sniperTrailsHook_R | |
| retn | |
| } | |
| } | |
| RwFrame* | |
| createVCEnvFrame(void) | |
| { | |
| RwFrame *f; | |
| RwV3d axis = { 1.0f, 0.0f, 0.0f }; | |
| f = RwFrameCreate(); | |
| RwMatrixRotate(&f->modelling, &axis, 60.0f, rwCOMBINEREPLACE); | |
| RwFrameUpdateObjects(f); | |
| RwFrameGetLTM(f); | |
| return f; | |
| } | |
| RwTexture* | |
| CreateTextureFilterFlags(RwRaster *raster) | |
| { | |
| RwTexture *tex = RwTextureCreate(raster); | |
| tex->filterAddressing = (tex->filterAddressing & 0xFFFFFF00) | 2; | |
| return tex; | |
| } | |
| WRAPPER void rpMatFXD3D8AtomicMatFXEnvRender_ps2_IIISteam() | |
| { | |
| __asm | |
| { | |
| sub esp, 20 | |
| mov [esp], eax | |
| mov [esp+4], edx | |
| mov [esp+8], ecx | |
| mov ecx, [esp+24h] | |
| mov [esp+0Ch], ecx | |
| mov ecx, [esp+28h] | |
| mov [esp+10h], ecx | |
| call _rpMatFXD3D8AtomicMatFXEnvRender_ps2 | |
| add esp, 20 | |
| retn | |
| } | |
| } | |
| WRAPPER void ApplyEnvMapTextureMatrix_hook_IIISteam() | |
| { | |
| __asm | |
| { | |
| push ecx | |
| push edx | |
| push eax | |
| call ApplyEnvMapTextureMatrix_hook | |
| add esp, 12 | |
| retn | |
| } | |
| } | |
| struct TxdStore { | |
| static void PushCurrentTxd(void); | |
| static int PopCurrentTxd(void); | |
| static int FindTxdSlot(char*); | |
| static void SetCurrentTxd(int); | |
| //static char *GetTxdName(int handle); | |
| }; | |
| static addr TxdStore_PushCurrentTxd_A = AddressByVersion<addr>(0x527900, 0x527B40, 0x527AD0, 0, 0, 0); | |
| WRAPPER void TxdStore::PushCurrentTxd(void) { VARJMP(TxdStore_PushCurrentTxd_A); } | |
| static addr TxdStore_PopCurrentTxd_A = AddressByVersion<addr>(0x527910, 0x527B50, 0x527AE0, 0, 0, 0); | |
| WRAPPER int TxdStore::PopCurrentTxd(void) { VARJMP(TxdStore_PopCurrentTxd_A); } | |
| static addr TxdStore_FindTxdSlot_A = AddressByVersion<addr>(0x5275D0, 0x527810, 0x5277A0, 0x580D70, 0, 0); | |
| WRAPPER int TxdStore::FindTxdSlot(char*) { VARJMP(TxdStore_FindTxdSlot_A); } | |
| static addr TxdStore_SetCurrentTxd_A = AddressByVersion<addr>(0x5278C0, 0x527B00, 0x527A90, 0, 0, 0); | |
| WRAPPER void TxdStore::SetCurrentTxd(int) { VARJMP(TxdStore_SetCurrentTxd_A); } | |
| //static addr TxdStore_GetTxdName_A = AddressByVersion<addr>(0, 0, 0, 0x580E50, 0, 0); | |
| //WRAPPER void TxdStore::GetTxdName(int) { VARJMP(TxdStore_SetCurrentTxd_A); } | |
| static int &gameTxdSlot = *AddressByVersion<int*>(0x628D88, 0x628D88, 0x638D88, 0, 0, 0); // only needed in III | |
| RwTexture* | |
| RwTextureRead_generic(char *name, char *mask) | |
| { | |
| RwTexture *tex; | |
| tex = RwTextureRead(name, mask); | |
| if(tex) | |
| return tex; | |
| TxdStore::PushCurrentTxd(); | |
| TxdStore::SetCurrentTxd(gameTxdSlot); | |
| tex = RwTextureRead(name, mask); | |
| TxdStore::PopCurrentTxd(); | |
| return tex; | |
| } | |
| #if 0 | |
| void *curvePS; | |
| void | |
| setcurveps(void) | |
| { | |
| if(curvePS == NULL){ | |
| HRSRC resource = FindResource(dllModule, MAKEINTRESOURCE(IDR_CURVEPS), RT_RCDATA); | |
| RwUInt32 *shader = (RwUInt32*)LoadResource(dllModule, resource); | |
| RwD3D9CreatePixelShader(shader, &curvePS); | |
| assert(curvePS); | |
| FreeResource(shader); | |
| } | |
| RwD3D9SetIm2DPixelShader(curvePS); | |
| } | |
| class CMBlur { | |
| public: static RwRaster *&pFrontBuffer; | |
| static void CreateImmediateModeData(RwCamera*, RwRect*); | |
| }; | |
| RwRaster *&CMBlur::pFrontBuffer = *AddressByVersion<RwRaster**>(0x8E2C48, 0x8E2CFC, 0x8F2E3C, 0x9753A4, 0x9753AC, 0x9743AC); | |
| WRAPPER void CMBlur::CreateImmediateModeData(RwCamera*, RwRect*) { EAXJMP(0x50A800); } | |
| unsigned int curveIdx; | |
| #define KEYDOWN(k) (GetAsyncKeyState(k) & 0x8000) | |
| void | |
| applyCurve(void) | |
| { | |
| RwCamera *cam = *(RwCamera**)(0x6FACF8 + 0x7A0); | |
| if(GetAsyncKeyState(VK_F9) & 0x8000) | |
| return; | |
| { | |
| static bool keystate = false; | |
| if(KEYDOWN(VK_CONTROL) && KEYDOWN(VK_LEFT)){ | |
| if(!keystate){ | |
| keystate = true; | |
| curveIdx = (curveIdx-1) % 256; | |
| } | |
| }else | |
| keystate = false; | |
| } | |
| { | |
| static bool keystate = false; | |
| if(KEYDOWN(VK_CONTROL) && KEYDOWN(VK_RIGHT)){ | |
| if(!keystate){ | |
| keystate = true; | |
| curveIdx = (curveIdx+1) % 256; | |
| } | |
| }else | |
| keystate = false; | |
| } | |
| { | |
| static bool keystate = false; | |
| if(KEYDOWN(VK_CONTROL) && KEYDOWN(VK_DOWN)){ | |
| if(!keystate){ | |
| keystate = true; | |
| curveIdx = 0; | |
| } | |
| }else | |
| keystate = false; | |
| } | |
| static RwRaster *rampRaster = NULL; | |
| if(rampTex == NULL){ | |
| reloadRamp(); | |
| rampTex->filterAddressing = 0x3301; | |
| int w, h; | |
| for(w = 1; w < cam->frameBuffer->width; w <<= 1); | |
| for(h = 1; h < cam->frameBuffer->height; h <<= 1); | |
| rampRaster = RwRasterCreate(w, h, 0, 5); | |
| RwRect rect = { 0, 0, w, h }; | |
| CMBlur::CreateImmediateModeData(cam, &rect); | |
| } | |
| RwRasterPushContext(rampRaster); | |
| RwRasterRenderFast(cam->frameBuffer, 0, 0); | |
| RwRasterPopContext(); | |
| float v = curveIdx/255.0f; | |
| RwD3D9SetPixelShaderConstant(0, &v, 1); | |
| RwD3D8SetTexture(rampTex, 1); | |
| DefinedState(); | |
| RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST); | |
| RwRenderStateSet(rwRENDERSTATEFOGENABLE, 0); | |
| RwRenderStateSet(rwRENDERSTATEZTESTENABLE, 0); | |
| RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, 0); | |
| RwRenderStateSet(rwRENDERSTATETEXTURERASTER, rampRaster); | |
| RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, 0); | |
| setcurveps(); | |
| RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, blurVertices, 4, blurIndices, 6); | |
| RwD3D9SetIm2DPixelShader(NULL); | |
| DefinedState(); | |
| RwD3D8SetTexture(NULL, 1); | |
| } | |
| void __declspec(naked) | |
| curvehook(void) | |
| { | |
| _asm{ | |
| pop ebx | |
| call applyCurve | |
| retn | |
| } | |
| } | |
| #endif | |
| unsigned __int64 rand_seed = 1; | |
| float ps2randnormalize = 1.0f/0x7FFFFFFF; | |
| int ps2rand() | |
| { | |
| rand_seed = 0x5851F42D4C957F2D * rand_seed + 1; | |
| return ((rand_seed >> 32) & 0x7FFFFFFF); | |
| } | |
| void ps2srand(unsigned int seed) | |
| { | |
| rand_seed = seed; | |
| } | |
| // BETA sliding in oddjob2 text for III, thanks Fire_Head for finding this | |
| float &OddJob2XOffset = *(float*)0x8F1B5C; | |
| WRAPPER void CFont__PrintString(float x, float y, short *str) { EAXJMP(0x500F50); } | |
| void | |
| CFont__PrintString__Oddjob2(float x, float y, short *str) | |
| { | |
| CFont__PrintString(x - OddJob2XOffset * RsGlobal.width/640.0f, y, str); | |
| } | |
| void (*CMBlur__MotionBlurRenderIII_orig)(RwCamera*, RwUInt8, RwUInt8, RwUInt8, RwUInt8, int, int); | |
| void | |
| CMBlur__MotionBlurRenderIII(RwCamera *cam, RwUInt8 red, RwUInt8 green, RwUInt8 blue, RwUInt8 alpha, int type, int bluralpha) | |
| { | |
| // REMOVE: we do this in InitialiseGame_hook now | |
| if(config.trailsSwitch < 0) config.trailsSwitch = 0; | |
| if(config.disableColourOverlay) | |
| return; | |
| switch(config.trailsSwitch){ | |
| default: | |
| case 0: CMBlur__MotionBlurRenderIII_orig(cam, red, green, blue, alpha, type, bluralpha); break; | |
| case 1: CMBlur::MotionBlurRender_leeds(cam, red, green, blue, alpha, type); break; | |
| case 2: CMBlur::MotionBlurRender_mobile(cam, red, green, blue, alpha, type); break; | |
| } | |
| } | |
| void (*CMBlur__MotionBlurRenderVC_orig)(RwCamera*, RwUInt8, RwUInt8, RwUInt8, RwUInt8, int); | |
| void | |
| CMBlur__MotionBlurRenderVC(RwCamera *cam, RwUInt8 red, RwUInt8 green, RwUInt8 blue, RwUInt8 alpha, int type) | |
| { | |
| // REMOVE: we do this in InitialiseGame_hook now | |
| if(config.trailsSwitch < 0) config.trailsSwitch = 0; | |
| if(config.disableColourOverlay) | |
| return; | |
| switch(config.trailsSwitch){ | |
| default: | |
| case 0: CMBlur__MotionBlurRenderVC_orig(cam, red, green, blue, alpha, type); break; | |
| case 1: CMBlur::MotionBlurRender_leeds(cam, red, green, blue, alpha, type); break; | |
| case 2: CMBlur::MotionBlurRender_mobile(cam, red, green, blue, alpha, type); break; | |
| } | |
| } | |
| // | |
| // real time reflection test; III 1.0 | |
| // | |
| /* | |
| WRAPPER RpAtomic *CVehicleModelInfo__SetEnvironmentMapCB(RpAtomic*, RwTexture*) { EAXJMP(0x521820); } | |
| void RenderEffects(void); | |
| RwTexture *realtimeenvmap; | |
| RpAtomic* | |
| CVehicleModelInfo__SetEnvironmentMapCB_hook(RpAtomic *atomic, RwTexture *envmap) | |
| { | |
| RwCamera *cam = *(RwCamera**)(0x6FACF8 + 0x7A0); | |
| if(realtimeenvmap == NULL){ | |
| int w, h; | |
| for(w = 1; w < cam->frameBuffer->width; w <<= 1); | |
| for(h = 1; h < cam->frameBuffer->height; h <<= 1); | |
| RwRaster *envraster = RwRasterCreate(w, h, 0, 5); | |
| realtimeenvmap = RwTextureCreate(envraster); | |
| realtimeenvmap->filterAddressing = 0x1102; | |
| } | |
| return CVehicleModelInfo__SetEnvironmentMapCB(atomic, realtimeenvmap); | |
| } | |
| void | |
| RenderEffectsHook(void) | |
| { | |
| RenderEffects(); | |
| RwCamera *cam = *(RwCamera**)(0x6FACF8 + 0x7A0); | |
| RwRasterPushContext(realtimeenvmap->raster); | |
| RwRasterRenderFast(cam->frameBuffer, 0, 0); | |
| RwRasterPopContext(); | |
| } | |
| */ | |
| int dontnag; | |
| void | |
| errorMessage(char *msg) | |
| { | |
| if(dontnag) return; | |
| MessageBox(NULL, msg, "Error - SkyGFX", MB_ICONERROR | MB_OK); | |
| } | |
| #define ONCE do{ static int once = 0; assert(once == 0); once = 1; }while(0) | |
| int | |
| readhex(const char *str) | |
| { | |
| int n = 0; | |
| if(strlen(str) > 2) | |
| sscanf(str+2, "%X", &n); | |
| return n; | |
| } | |
| int | |
| readint(const std::string &s, int default = 0) | |
| { | |
| try{ | |
| return std::stoi(s); | |
| }catch(...){ | |
| return default; | |
| } | |
| } | |
| float | |
| readfloat(const std::string &s, float default = 0) | |
| { | |
| try{ | |
| return std::stof(s); | |
| }catch(...){ | |
| return default; | |
| } | |
| } | |
| void (*InitialiseGame)(void); | |
| void | |
| InitialiseGame_hook(void) | |
| { | |
| static bool postrw_once; | |
| // Post RW Init | |
| if(!postrw_once){ | |
| d3d9 = RwD3D9Supported(); | |
| // This is where we can sanitize some values: | |
| if(config.trailsSwitch < 0) config.trailsSwitch = 0; | |
| if(config.radiosity < 0) config.radiosity = 0; | |
| if(config.leedsEnvMult < 0) config.leedsEnvMult = isIII() ? 0.22f : 0.4f; | |
| if(config.leedsWorldPrelightTweakMult < 0) config.leedsWorldPrelightTweakMult = 1.0f; | |
| if(config.leedsWorldPrelightTweakAdd < 0) config.leedsWorldPrelightTweakAdd = 0.0f; | |
| if (isIII()) // fall back to generic.txd when reading from dff | |
| InjectHook(AddressByVersion<addr>(0x5AAE1B, 0x5AB0DB, 0x5AD708, 0, 0, 0), RwTextureRead_generic); | |
| CarPipe::Init(); | |
| WorldPipe::Init(); | |
| LeedsCarPipe::Get()->Init(); | |
| neoInit(); | |
| if(config.rimlight < 0) config.rimlight = 0; | |
| if(config.neoGlossPipe < 0) config.neoGlossPipe = 0; | |
| if(config.carPipeSwitch < 0) config.carPipeSwitch = 0; | |
| if(config.worldPipeSwitch < 0) config.worldPipeSwitch = 0; | |
| postrw_once = true; | |
| } | |
| InitialiseGame(); | |
| } | |
| int (*RsEventHandler_orig)(int a, int b); | |
| int | |
| delayedPatches(int a, int b) | |
| { | |
| if(DebugMenuLoad()){ | |
| DebugMenuEntry *e; | |
| static const char *ps2pcmobile[] = { "PS2", "PC", "Mobile" }; | |
| static const char *pcps2[] = { "PC", "PS2" }; | |
| e = DebugMenuAddVar("SkyGFX", "MatFX blend", &config.blendstyle, nil, 1, 0, 2, ps2pcmobile); | |
| DebugMenuEntrySetWrap(e, true); | |
| e = DebugMenuAddVar("SkyGFX", "MatFX texgen", &config.texgenstyle, nil, 1, 0, 2, ps2pcmobile); | |
| DebugMenuEntrySetWrap(e, true); | |
| e = DebugMenuAddVar("SkyGFX", "MatFX PS2 lighting", &config.ps2light, nil, 1, 0, 1, pcps2); | |
| DebugMenuEntrySetWrap(e, true); | |
| DebugMenuAddVarBool32("SkyGFX", "Dual pass", &config.dualpass, nil); | |
| static const char *pipeStr[] = { | |
| "invalid", "default", "neo", "lcs", "vcs" | |
| }; | |
| static const char *postfxStr[] = { | |
| "invalid", "default", "leeds", "mobile" | |
| }; | |
| DebugMenuAddVar("SkyGFX", "World pipe", &config.worldPipeSwitch, nil, 1, WORLD_DEFAULT, WORLD_LEEDS, pipeStr+1); | |
| DebugMenuAddVar("SkyGFX", "Car pipe", &config.carPipeSwitch, nil, 1, CAR_DEFAULT, CAR_VCS, pipeStr+1); | |
| DebugMenuAddVar("SkyGFX|Advanced", "Leeds Car Env Mult", &config.leedsEnvMult, nil, 0.1f, 0.0f, 2.0f); | |
| DebugMenuAddVar("SkyGFX|Advanced", "Trails switch", &config.trailsSwitch, nil, 1, 0, 2, postfxStr+1); | |
| DebugMenuAddVarBool32("SkyGFX", "Neo rim light pipe", &config.rimlight, nil); | |
| DebugMenuAddVarBool32("SkyGFX", "Neo gloss pipe", &config.neoGlossPipe, nil); | |
| if(config.neowaterdrops >= 0){ | |
| if(config.neowaterdrops > 3) config.neowaterdrops = 3; | |
| static const char *dropstrings[] = { "None", "Neo", "Extended", "Extended+Blood" }; | |
| DebugMenuAddVar("SkyGFX", "Neo water drops", &config.neowaterdrops, nil, 1, 0, 3, dropstrings); | |
| #ifdef DEBUG | |
| DebugMenuAddVar("SkyGFX", "Num Neo drops", &WaterDrops::ms_numDrops, nil, 0, 0, 99999999, nil); | |
| DebugMenuAddVar("SkyGFX", "Num Neo drops moving", &WaterDrops::ms_numDropsMoving, nil, 0, 0, 99999999, nil); | |
| #endif | |
| } | |
| // if(config.disableColourOverlay >= 0) | |
| DebugMenuAddVarBool32("SkyGFX", "Disable Colour Overlay", &config.disableColourOverlay, nil); | |
| void neoMenu(); | |
| neoMenu(); | |
| void leedsMenu(); | |
| leedsMenu(); | |
| extern int seamOffX; | |
| extern int seamOffY; | |
| DebugMenuAddVarBool32("SkyGFX", "Seam fixer", &config.seamfix, nil); | |
| DebugMenuAddVar("SkyGFX", "Seam Offset X", &seamOffX, nil, 1, -10, 10, nil); | |
| DebugMenuAddVar("SkyGFX", "Seam Offset Y", &seamOffY, nil, 1, -10, 10, nil); | |
| DebugMenuAddVarBool8("SkyGFX|ScreenFX", "Enable YCbCr tweak", (int8_t*)&ScreenFX::m_bYCbCrFilter, nil); | |
| DebugMenuAddVar("SkyGFX|ScreenFX", "Y scale", &ScreenFX::m_lumaScale, nil, 0.004f, 0.0f, 10.0f); | |
| DebugMenuAddVar("SkyGFX|ScreenFX", "Y offset", &ScreenFX::m_lumaOffset, nil, 0.004f, -1.0f, 1.0f); | |
| DebugMenuAddVar("SkyGFX|ScreenFX", "Cb scale", &ScreenFX::m_cbScale, nil, 0.004f, 0.0f, 10.0f); | |
| DebugMenuAddVar("SkyGFX|ScreenFX", "Cb offset", &ScreenFX::m_cbOffset, nil, 0.004f, -1.0f, 1.0f); | |
| DebugMenuAddVar("SkyGFX|ScreenFX", "Cr scale", &ScreenFX::m_crScale, nil, 0.004f, 0.0f, 10.0f); | |
| DebugMenuAddVar("SkyGFX|ScreenFX", "Cr offset", &ScreenFX::m_crOffset, nil, 0.004f, -1.0f, 1.0f); | |
| #ifdef DEBUG | |
| extern float envmult; | |
| extern bool ps2filtering; | |
| extern bool envdebug; | |
| if(gtaversion == III_10){ | |
| DebugMenuAddVar("SkyGFX", "Env Mult", &envmult, nil, 0.05f, 0.0f, 2.0f); | |
| DebugMenuAddVarBool8("SkyGFX", "ps2 env filter", (int8*)&ps2filtering, nil); | |
| #ifdef ENVTEST | |
| DebugMenuAddVarBool8("SkyGFX", "env debug", (int8*)&envdebug, nil); | |
| #endif | |
| } | |
| #endif | |
| } | |
| return RsEventHandler_orig(a, b); | |
| } | |
| //void (*RwCameraEndUpdate_hooked)(RwCamera *cam); | |
| //void endOfFrame(RwCamera *cam) | |
| //{ | |
| // ScreenFX::Render(); | |
| // RwCameraEndUpdate_hooked(cam); | |
| //} | |
| void | |
| patch(void) | |
| { | |
| using namespace std; | |
| // char tmp[32]; | |
| string tmp; | |
| char modulePath[MAX_PATH]; | |
| config.trailsBlur = 1; | |
| config.trailsMotionBlur = 1; | |
| config.currentBlurAlpha = 39.0f; | |
| config.currentBlurOffset = 2.1f; | |
| // Fail if RenderWare has already been started | |
| if(Scene.camera){ | |
| MessageBox(NULL, "SkyGFX cannot be loaded by the default Mss32 ASI loader.\nUse another ASI loader.", "Error", MB_ICONERROR | MB_OK); | |
| return; | |
| } | |
| GetModuleFileName(dllModule, modulePath, MAX_PATH); | |
| char *p = strrchr(modulePath, '\\'); | |
| if(p) p[1] = '\0'; | |
| strncpy(asipath, modulePath, MAX_PATH); | |
| strcat(modulePath, "skygfx.ini"); | |
| linb::ini cfg; | |
| cfg.load_file(modulePath); | |
| if(gtaversion == III_10 || gtaversion == VC_10){ | |
| InterceptCall(&ScreenFX::nullsub_orig, ScreenFX::Render, AddressByVersion<uint32_t>(0x48D445, 0, 0, 0x4A6151, 0, 0)); | |
| // InterceptCall(&RwCameraEndUpdate_hooked, endOfFrame, AddressByVersion<uint32_t>(0x48D450, 0, 0, 0x4A615C, 0, 0)); | |
| InterceptCall(&RsEventHandler_orig, delayedPatches, AddressByVersion<uint32_t>(0x58275E, 0, 0, 0x5FFAFE, 0, 0)); | |
| } | |
| // ADDRESS | |
| if(gtaversion == III_10 || gtaversion == VC_10){ | |
| // Everything that is initialized with RenderWare | |
| //InterceptCall(&InitialiseRenderWare, InitialiseRenderWare_hook, AddressByVersion<addr>(0x48D52F, 0, 0, 0x4A5B6B, 0, 0)); | |
| // Everything that is initialized whenever a game is started | |
| InterceptCall(&InitialiseGame, InitialiseGame_hook, AddressByVersion<addr>(0x582E6C, 0, 0, 0x600411, 0, 0)); | |
| hookplugins(); | |
| } | |
| dontnag = readint(cfg.get("SkyGfx", "dontNag", ""), 0); | |
| config.seamfix = readint(cfg.get("SkyGfx", "seamFix", ""), 0); | |
| // set to reasonable values when used | |
| config.radiosity = readint(cfg.get("SkyGfx", "radiosity", ""), -1); | |
| config.trailsSwitch = readint(cfg.get("SkyGfx", "trailsSwitch", ""), -1); | |
| config.leedsWorldPrelightTweakMult = readfloat(cfg.get("SkyGfx", "leedsWorldPrelightTweakMult", ""), -9999.0f); | |
| config.leedsWorldPrelightTweakAdd = readfloat(cfg.get("SkyGfx", "leedsWorldPrelightTweakAdd", ""), -9999.0f); | |
| config.radiosityRenderPasses = readint(cfg.get("SkyGfx", "radiosityRenderPasses", ""), 2); | |
| config.radiosityFilterPasses = readint(cfg.get("SkyGfx", "radiosityFilterPasses", ""), 4); | |
| config.disableColourOverlay = readint(cfg.get("SkyGfx", "disableColourOverlay", ""), -1); | |
| if(config.disableColourOverlay < 0) config.disableColourOverlay = 0; | |
| // TEMP | |
| // if(disableColourOverlay >= 0){ | |
| if(gtaversion == III_10) | |
| InterceptCall(&CMBlur__MotionBlurRenderIII_orig, CMBlur__MotionBlurRenderIII, 0x46F978); | |
| else if(gtaversion == VC_10) | |
| InterceptCall(&CMBlur__MotionBlurRenderVC_orig, CMBlur__MotionBlurRenderVC, 0x46BE0F); | |
| // } | |
| int ps2water = readint(cfg.get("SkyGfx", "ps2Water", ""), 0); | |
| if(gtaversion == III_10) | |
| InjectHook(AddressByVersion<addr>(0x5D0D2B, 0x0, 0, 0x0, 0x0, 0x0), _rpMatFXD3D8AtomicMatFXRenderBlack_fixed); | |
| tmp = cfg.get("SkyGfx", "texblendSwitch", ""); | |
| if(tmp != ""){ | |
| config.blendstyle = readint(tmp); | |
| // MatFX env coefficient on cars | |
| static float envCoeff = 1.0f; | |
| // static float envCoeff = 0.5f; | |
| Patch(AddressByVersion<addr>(0x5217DF, 0, 0, 0x578B7B, 0, 0) + 2, &envCoeff); | |
| if(ps2water && gtaversion == VC_10) | |
| patchWater(); | |
| InterceptCall(&_rpMatFXPipelinesCreate_orig, _rpMatFXPipelinesCreate, AddressByVersion<addr>(0x5B27B1, 0, 0, 0x656031, 0, 0)); | |
| void _rwD3D8AtomicMatFXRenderCallback(RwResEntry *repEntry, void *object, RwUInt8 type, RwUInt32 flags); | |
| InjectHook(AddressByVersion<addr>(0x5D0B80, 0, 0, 0x676460, 0, 0), _rwD3D8AtomicMatFXRenderCallback, PATCH_JUMP); | |
| // no longer needed | |
| // if(gtaversion != III_STEAM) | |
| // InjectHook(AddressByVersion<addr>(0x5D0CE8, 0x5D0FA8, 0, 0x6765C8, 0x676618, 0x675578), _rpMatFXD3D8AtomicMatFXEnvRender_ps2); | |
| // else | |
| // InjectHook(0x5D8D37, rpMatFXD3D8AtomicMatFXEnvRender_ps2_IIISteam); | |
| } | |
| // disable car colour textures (messes up matfx) | |
| // but it could be intended...what to do? | |
| if(gtaversion == III_10 && readint(cfg.get("SkyGfx", "noCarcolTex", ""), 0)){ | |
| Nop(0x520EEA, 2); | |
| Nop(0x520F8A, 2); | |
| } | |
| config.blendstyle %= 3; | |
| tmp = cfg.get("SkyGfx", "texgenSwitch", ""); | |
| if(tmp != ""){ | |
| config.texgenstyle = readint(tmp); | |
| if (gtaversion != III_STEAM) | |
| InjectHook(ApplyEnvMapTextureMatrix_A, ApplyEnvMapTextureMatrix_hook, PATCH_JUMP); | |
| else | |
| InjectHook(ApplyEnvMapTextureMatrix_A, ApplyEnvMapTextureMatrix_hook_IIISteam, PATCH_JUMP); | |
| } | |
| config.texgenstyle %= 3; | |
| config.ps2light = readint(cfg.get("SkyGfx", "ps2light", "1")); | |
| if(isVC() && readint(cfg.get("SkyGfx", "IIIEnvFrame", ""))){ | |
| InjectHook(AddressByVersion<addr>(0, 0, 0, 0x57A8BA, 0x57A8DA, 0x57A7AA), createIIIEnvFrame); | |
| InjectHook(AddressByVersion<addr>(0, 0, 0, 0x57A8C7, 0x57A8E7, 0x57A7B7), | |
| AddressByVersion<addr>(0, 0, 0, 0x57A8F4, 0x57A914, 0x57A7E4), PATCH_JUMP); | |
| } | |
| if(isIII() && readint(cfg.get("SkyGfx", "VCEnvFrame", ""))){ | |
| InjectHook(AddressByVersion<addr>(0x5218A2, 0x521AE2, 0x521A72, 0, 0, 0), createVCEnvFrame); | |
| InjectHook(AddressByVersion<addr>(0x5218AC, 0x521AEC, 0x521A7C, 0, 0, 0), | |
| AddressByVersion<addr>(0x52195E, 0x521B9E, 0x521B2E, 0, 0, 0), PATCH_JUMP); | |
| } | |
| if(isIII()) | |
| InjectHook(AddressByVersion<addr>(0x59BABF, 0x59BD7F, 0x598E6F, 0, 0, 0), CreateTextureFilterFlags); | |
| config.carPipeSwitch = readint(cfg.get("SkyGfx", "carPipe", ""), -1); | |
| config.worldPipeSwitch = readint(cfg.get("SkyGfx", "worldPipe", ""), -1); | |
| config.envMapSize = readint(cfg.get("SkyGfx", "envMapSize", ""), 128); | |
| int n = 1; | |
| while(n < config.envMapSize) n *= 2; | |
| config.envMapSize = n; | |
| // set to a reasonable value when used | |
| config.leedsEnvMult = readfloat(cfg.get("SkyGfx", "leedsEnvMult", ""), -9999.0f); | |
| config.rimlight = readint(cfg.get("SkyGfx", "neoRimLightPipe", ""), -1); | |
| config.neoGlossPipe = readint(cfg.get("SkyGfx", "neoGlossPipe", ""), -1); | |
| tmp = cfg.get("SkyGfx", "dualPass", ""); | |
| if(tmp != ""){ | |
| config.dualpass = readint(tmp); | |
| if (gtaversion != III_STEAM) | |
| InjectHook(AddressByVersion<addr>(0x5DFB99, 0x5DFE59, 0, 0x678D69, 0x678DB9, 0x677D19), dualPassHook, PATCH_JUMP); | |
| else | |
| InjectHook(0x5EE675, dualPassHook_IIISteam, PATCH_JUMP); | |
| InjectHook(AddressByVersion<addr>(0x5CEB80, 0x5CEE40, 0x5DB760, 0x674380, 0x6743D0, 0x673330), _rpMatFXD3D8AtomicMatFXDefaultRender, PATCH_JUMP); | |
| } | |
| if(isVC() && readint(cfg.get("SkyGfx", "disableBackfaceCulling", ""), 0)){ | |
| // hope I didn't miss anything | |
| Patch<uchar>(AddressByVersion<addr>(0, 0, 0, 0x4C9E5F, 0x4C9E7F, 0x4C9D1F), 1); // in CRenderer::RenderOneNonRoad() | |
| Patch<uchar>(AddressByVersion<addr>(0, 0, 0, 0x4C9F08, 0x4C9F28, 0x4C9DC8), 1); // in CRenderer::RenderBoats() | |
| Patch<uchar>(AddressByVersion<addr>(0, 0, 0, 0x4C9F5D, 0x4C9F7D, 0x4C9E1D), 1); // in CRenderer::RenderEverythingBarRoads() | |
| Patch<uchar>(AddressByVersion<addr>(0, 0, 0, 0x4CA157, 0x4CA177, 0x4CA017), 1); // in CRenderer::RenderFadingInEntities() | |
| Patch<uchar>(AddressByVersion<addr>(0, 0, 0, 0x4CA199, 0x4CA1B9, 0x4CA059), 1); // in CRenderer::RenderRoads() | |
| // ADDRESS | |
| if(gtaversion == VC_10) | |
| Patch<uchar>(AddressByVersion<addr>(0, 0, 0, 0x4E0146, 0, 0), 1); // in CCutsceneObject::Render() | |
| } | |
| // fix blend mode | |
| if(isVC()){ | |
| // auto aim | |
| Patch<uchar>(AddressByVersion<addr>(0, 0, 0, 0x5D4EEE, 0x5D4F0E, 0x5D4CBE), rwBLENDINVSRCALPHA); | |
| // sniper dot | |
| Patch<uchar>(AddressByVersion<addr>(0, 0, 0, 0x558024, 0x558044, 0x557F14), rwBLENDINVSRCALPHA); | |
| } | |
| if(isVC()) | |
| InjectHook(AddressByVersion<addr>(0, 0, 0, 0x55EA39, 0x55EA59, 0x55E929), sniperTrailsHook, PATCH_JUMP); | |
| config.neowaterdrops = readint(cfg.get("SkyGfx", "neoWaterDrops", ""), -1); | |
| if(config.neowaterdrops >= 0) | |
| hookWaterDrops(); | |
| if(readint(cfg.get("SkyGfx", "replaceDefaultPipeline", ""))){ | |
| if(gtaversion == III_10){ | |
| Patch(0x5DB427 +2, D3D8AtomicDefaultInstanceCallback_fixed); | |
| Patch(0x5DB42D +3, D3D8AtomicDefaultReinstanceCallback_fixed); | |
| Patch(0x5DB43B +3, rxD3D8DefaultRenderCallback_xbox); | |
| }else if(gtaversion == VC_10){ | |
| Patch(0x67BAB7 +2, D3D8AtomicDefaultInstanceCallback_fixed); | |
| Patch(0x67BABD +3, D3D8AtomicDefaultReinstanceCallback_fixed); | |
| Patch(0x67BACB +3, rxD3D8DefaultRenderCallback_xbox); | |
| } | |
| } | |
| if(readint(cfg.get("SkyGfx", "ps2Loadscreen", ""))){ | |
| if(gtaversion == III_10){ | |
| // ff 74 24 60 push DWORD PTR [esp+0x60] | |
| Patch<uint>(0x48D774, 0x602474ff); | |
| InjectHook(0x48D778, 0x48D79B, PATCH_JUMP); | |
| } | |
| if(gtaversion == VC_10){ | |
| // BREAKS WITH OLD OLA | |
| Nop(0x4A69D4, 1); | |
| // ff 74 24 78 push DWORD PTR [esp+0x78] | |
| Patch(0x4A69D4+1, 0x782474ff); | |
| } | |
| } | |
| ScreenFX::m_bYCbCrFilter = readint(cfg.get("SkyGfx", "YCbCrCorrection", ""), 0); | |
| ScreenFX::m_lumaScale = readfloat(cfg.get("SkyGfx", "lumaScale", ""), 219.0f/255.0f); | |
| ScreenFX::m_lumaOffset = readfloat(cfg.get("SkyGfx", "lumaOffset", ""), 16.0f/255.0f); | |
| ScreenFX::m_cbScale = readfloat(cfg.get("SkyGfx", "CbScale", ""), 1.23f); | |
| ScreenFX::m_cbOffset = readfloat(cfg.get("SkyGfx", "CbOffset", ""), 0.0f); | |
| ScreenFX::m_crScale = readfloat(cfg.get("SkyGfx", "CrScale", ""), 1.23f); | |
| ScreenFX::m_crOffset = readfloat(cfg.get("SkyGfx", "CrOffset", ""), 0.0f); | |
| enableTrailsSetting(); | |
| // Nop(0x4A6594, 5); // water | |
| // Nop(0x4A65AE, 5); // transparent water | |
| // disable inlined RenderOneFlatLargeWaterPoly | |
| // InjectHook(0x5C1265, 0x5C1442, PATCH_JUMP); | |
| // disable RenderOneFlatSmallWaterPolyBlended | |
| // InjectHook(0x5BD0A0, 0x5BD73D, PATCH_JUMP); | |
| // wavy atomic | |
| // Nop(0x5C0C46, 3); | |
| // Nop(0x5C0E15, 3); | |
| // Nop(0x5C0FEB, 3); | |
| // Nop(0x5C11C0, 3); | |
| // mask atomic | |
| // Nop(0x5C1579, 3); | |
| // use get-in-vehicle camera from PS2 (thanks, Fire_Head) | |
| if(gtaversion == III_10 && readint(cfg.get("SkyGfx", "ps2carCam", ""))){ | |
| Nop(0x4713DB, 2); | |
| Nop(0x47143B, 2); | |
| } | |
| #ifdef DEBUG | |
| if(gtaversion == III_10){ | |
| // ignore txd.img | |
| InjectHook(0x48C12E, 0x48C14C, PATCH_JUMP); | |
| #if 0 | |
| int i = readint(cfg.get("SkyGfx", "curve", ""), -1); | |
| if(i >= 0){ | |
| curveIdx = i % 256; | |
| InjectHook(0x48E44B, curvehook, PATCH_JUMP); | |
| } | |
| #endif | |
| // InjectHook(0x405DB0, printf, PATCH_JUMP); | |
| //MemoryVP::InjectHook(0x48E603, RenderEffectsHook); | |
| //MemoryVP::InjectHook(0x5219B3, CVehicleModelInfo__SetEnvironmentMapCB_hook); | |
| //MemoryVP::Patch<void*>(0x521986+1, CVehicleModelInfo__SetEnvironmentMapCB_hook); | |
| // beta sliding in text | |
| InjectHook(0x509DDE, CFont__PrintString__Oddjob2); | |
| InjectHook(0x509E51, CFont__PrintString__Oddjob2); | |
| // clear framebuffer | |
| Patch<uchar>(0x48CFC1+1, 3); | |
| Patch<uchar>(0x48D0AD+1, 3); | |
| Patch<uchar>(0x48E6A7+1, 3); | |
| Patch<uchar>(0x48E78C+1, 3); | |
| } | |
| #endif | |
| #ifdef DEBUG | |
| if(gtaversion == VC_10){ | |
| //extern void hackshit(void); | |
| //hackshit(); | |
| // remove "%s has not been pre-instanced", we don't really care | |
| Nop(0x40C32B, 5); | |
| //MemoryVP::InjectHook(0x650ACB, RwTextureRead_VC); | |
| InjectHook(0x401000, printf, PATCH_JUMP); | |
| // static float lod0dist = 150.0f; | |
| // Patch(0x5818A3 + 2, &lod0dist); | |
| // try to reduce timecyc flickering...didn't work | |
| //static float s = 0.0f; | |
| //Patch(0x4CEA71 + 2, &s); | |
| //InjectHook(0x4CF5C7, 0x4D0189, PATCH_JUMP); | |
| // | |
| //Patch(0x4CF47D, 0xc031); // xor eax, eax | |
| //Nop(0x4CF47D + 2, 2); | |
| // fix directional colour | |
| Patch(0x58051D + 2, 0x94B210); | |
| Patch(0x58054D + 2, 0x94B210+4); | |
| Patch(0x58057D + 2, 0x94B210+8); | |
| // disable Vsynch | |
| Patch<uint8>(0x6021EF + 1, 0); | |
| // disable level load screens | |
| Nop(0x40E00E, 5); | |
| Nop(0x40E01C, 5); | |
| Nop(0x40E157, 5); | |
| } | |
| #endif | |
| } | |
| BOOL WINAPI | |
| DllMain(HINSTANCE hInst, DWORD reason, LPVOID) | |
| { | |
| if(reason == DLL_PROCESS_ATTACH){ | |
| dllModule = hInst; | |
| //freopen("log.txt", "w", stdout); | |
| if(GetAsyncKeyState(VK_F8) & 0x8000){ | |
| AllocConsole(); | |
| freopen("CONIN$", "r", stdin); | |
| freopen("CONOUT$", "w", stdout); | |
| freopen("CONOUT$", "w", stderr); | |
| } | |
| AddressByVersion<addr>(0, 0, 0, 0, 0, 0); | |
| if(is10()) | |
| patch(); | |
| } | |
| return TRUE; | |
| } |