* Fixed issue where launching dmods from DFArc with a dmod path not in DFArc's dir or Dink HD's dmod dir would fail * Fixed compatibility so Freedink.exe and the dink.exe from 1.08 can be run from Dink HD's dir (previously, start.c had been hacked to skip stuff for the HD version, it now checks version and if it's being run as a dmod or not and does it right) * If you run the HD "dink" dir as a mod it now works as expected (it plays the normal game, including the old start up screen) * Now including story/*.c instead of the .d files. No reason to hide them, right? (note: if you install over HD without uninstalling, the old .d files will still be there. But .c files are checked first so it should be ok anyway) * DMODs now default to the original .midi files rather than the .ogg CD music, as it changed the desired "feel" of some DMODs to switch to CD music. Running with -game dink causes Dink itself to not use CD music as well, so for people who don't like CD music at all there's an option to play the original game with midis only * (Bugfix) Dink HD will no longer try to grab missing sprites from the base dink dir, this fixes Dink's pushing anim in Zoltron * (Bugfix) dmod installer no longer chokes on zero byte files (I'm looking at you, 9gems) * (Bugfix) Fixed memory leak and possible crash related to script loading * (Bugfix) Fixed issue with the checkerboard shadow processing where the 8 bit RLE decoder failed because it was expecting an 8 bit target (most bmps don't use RLE, but Alliance does in places) * Went ahead and decided to accept 252,252,252 as alpha if it's index 255 on an 8bit sprite. This fixed the white background issue with Alliance dmod as well as Dinkcraft * FEATURE: Can now download all DMODs from Dink Network directly from inside the game via Dan's php interface. Can sort by rating, latest update date, or alphabetically git-svn-id: svn://rtsoft.com/rtsvn/projects/RTDink@1502 353e56fe-9613-0410-8469-b96ad8e6f29c
420 lines
No EOL
10 KiB
C++
420 lines
No EOL
10 KiB
C++
#include "PlatformPrecomp.h"
|
|
#include "video_gl.h"
|
|
#include "dink/misc_util.h"
|
|
#include <cassert>
|
|
#include "Renderer/SoftSurface.h"
|
|
#include "App.h"
|
|
|
|
LPDIRECTDRAWSURFACE lpDDSBack = NULL; // DirectDraw back surface
|
|
SoftSurface g_palette;
|
|
|
|
extern LPDIRECTDRAWSURFACE lpDDSBackGround;
|
|
|
|
bool InitializeVideoSystem()
|
|
{
|
|
assert(!lpDDSBack);
|
|
lpDDSBack = InitOffscreenSurface(C_DINK_SCREENSIZE_X, C_DINK_SCREENSIZE_Y, IDirectDrawSurface::MODE_PRIMARY_GL);
|
|
|
|
g_palette.Init(8,8, SoftSurface::SURFACE_PALETTE_8BIT);
|
|
g_palette.SetPaletteFromBMP("dink/tiles/palette.bmp", SoftSurface::COLOR_KEY_NONE);
|
|
|
|
return true;
|
|
}
|
|
|
|
void KillVideoEngine()
|
|
{
|
|
SAFE_DELETE(lpDDSBack);
|
|
}
|
|
|
|
void dderror(int hErr){};
|
|
|
|
IDirectDrawSurface * LoadBitmapIntoSurface(const char *pName, eTransparencyType trans, IDirectDrawSurface::eMode mode, byte *pMem, bool bUseCheckerboardFix)
|
|
{
|
|
|
|
IDirectDrawSurface * pSurf;
|
|
pSurf = new IDirectDrawSurface;
|
|
pSurf->m_mode = mode;
|
|
pSurf->m_pSurf = new SoftSurface;
|
|
//bUseCheckerboardFix = true;
|
|
|
|
if (pMem)
|
|
{
|
|
#ifdef _DEBUG
|
|
//LogMsg("loading DDRAW bmp from mem");
|
|
#endif
|
|
//if this is set, ignore the filename
|
|
pSurf->m_pSurf->LoadFileFromMemory(pMem, SoftSurface::eColorKeyType(trans), 0, false, bUseCheckerboardFix);
|
|
} else
|
|
{
|
|
#ifdef _DEBUG
|
|
//LogMsg("loading DDRAW bmp from file");
|
|
#endif
|
|
pSurf->m_pSurf->LoadFile(pName, SoftSurface::eColorKeyType(trans), false, bUseCheckerboardFix);
|
|
}
|
|
|
|
//LogMsg("loaded bitmap");
|
|
|
|
switch( mode)
|
|
{
|
|
case IDirectDrawSurface::MODE_SHADOW_GL:
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
return pSurf;
|
|
}
|
|
|
|
void GetSizeOfSurface(IDirectDrawSurface *pdds, int *pX, int *pY)
|
|
{
|
|
|
|
if (pdds->m_pSurf)
|
|
{
|
|
*pX = pdds->m_pSurf->GetWidth();
|
|
*pY = pdds->m_pSurf->GetHeight();
|
|
return;
|
|
} else
|
|
{
|
|
assert(!"Bad surface");
|
|
return;
|
|
}
|
|
}
|
|
|
|
IDirectDrawSurface * InitOffscreenSurface(int x, int y, IDirectDrawSurface::eMode mode, bool bHiColor, SoftSurface *pSurfaceToCopyFrom)
|
|
{
|
|
IDirectDrawSurface *pdds;
|
|
pdds = new IDirectDrawSurface;
|
|
pdds->m_mode = mode;
|
|
|
|
switch (mode)
|
|
{
|
|
case IDirectDrawSurface::MODE_NORMAL:
|
|
case IDirectDrawSurface::MODE_SHADOW_GL:
|
|
|
|
|
|
pdds->m_pSurf = new SoftSurface;
|
|
if (bHiColor)
|
|
{
|
|
pdds->m_pSurf->Init(x,y, SoftSurface::SURFACE_RGBA);
|
|
pdds->m_pSurf->SetHasPremultipliedAlpha(true);
|
|
pdds->m_pSurf->SetUsesAlpha(true);
|
|
} else
|
|
{
|
|
pdds->m_pSurf->Init(x,y, SoftSurface::SURFACE_PALETTE_8BIT);
|
|
pdds->m_pSurf->SetPaletteFromBMP("dink/tiles/palette.bmp", SoftSurface::COLOR_KEY_NONE);
|
|
}
|
|
|
|
if (pSurfaceToCopyFrom)
|
|
{
|
|
pdds->m_pSurf->Blit(0,0,pSurfaceToCopyFrom);
|
|
|
|
}
|
|
if (mode == IDirectDrawSurface::MODE_SHADOW_GL)
|
|
{
|
|
pdds->m_pGLSurf = new Surface;
|
|
|
|
pdds->m_pGLSurf->SetSmoothing(GetApp()->GetVar("smoothing")->GetUINT32() != 0);
|
|
if (GetApp()->GetVar("smoothing")->GetUINT32())
|
|
{
|
|
pdds->m_pGLSurf->SetTextureType(Surface::TYPE_GUI);
|
|
|
|
} else
|
|
{
|
|
pdds->m_pGLSurf->SetTextureType(Surface::TYPE_NO_SMOOTHING);
|
|
}
|
|
|
|
pdds->m_pGLSurf->InitBlankSurface(x,y);
|
|
}
|
|
|
|
break;
|
|
|
|
case IDirectDrawSurface::MODE_PRIMARY_GL:
|
|
|
|
break;
|
|
}
|
|
|
|
return pdds;
|
|
}
|
|
|
|
|
|
IDirectDrawSurface::IDirectDrawSurface()
|
|
{
|
|
m_pSurf = NULL;
|
|
m_mode = MODE_NORMAL;
|
|
m_pGLSurf = NULL;
|
|
m_gameTickOfLastUse = 0;
|
|
}
|
|
|
|
IDirectDrawSurface::~IDirectDrawSurface()
|
|
{
|
|
SAFE_DELETE(m_pSurf);
|
|
SAFE_DELETE(m_pGLSurf);
|
|
}
|
|
|
|
glColorBytes RGBA_TO_GLCOLOR(const unsigned int color)
|
|
{
|
|
return glColorBytes(GET_RED(color), GET_GREEN(color), GET_BLUE(color), GET_ALPHA(color));
|
|
}
|
|
|
|
unsigned int GLCOLOR_TO_RGBA(const glColorBytes glColor)
|
|
{
|
|
return MAKE_RGBA(glColor.r, glColor.g, glColor.b, glColor.a);
|
|
}
|
|
|
|
Surface * IDirectDrawSurface::GetGLSuface()
|
|
{
|
|
assert(m_mode == MODE_SHADOW_GL && "We're only using this for item icons, and they always would be gl shadowed!");
|
|
|
|
UpdateShadowSurface();
|
|
return m_pGLSurf;
|
|
}
|
|
|
|
int IDirectDrawSurface::Blt( rtRect32 *pDestRect, IDirectDrawSurface * pSrcSurf, rtRect32 *pSrcRect, uint32 flags, DDBLTFX *pFX )
|
|
{
|
|
if (pSrcSurf)
|
|
{
|
|
pSrcSurf->UpdateLastUsedTime();
|
|
}
|
|
|
|
switch (m_mode)
|
|
{
|
|
|
|
case MODE_SHADOW_GL:
|
|
case MODE_NORMAL:
|
|
if (flags & DDBLT_COLORFILL)
|
|
{
|
|
assert(pFX);
|
|
assert(pDestRect == NULL && "Well, we only support modifying the entire screen");
|
|
|
|
//don't ask me why, but the original directx had these backwards. Palette is correct
|
|
if (pFX->dwFillColor == 0)
|
|
{
|
|
pFX->dwFillColor = 255;
|
|
}
|
|
else if (pFX->dwFillColor == 255)
|
|
{
|
|
pFX->dwFillColor = 0;
|
|
}
|
|
|
|
if (m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_RGB || m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_RGBA)
|
|
{
|
|
m_pSurf->FillColor(g_palette.GetPalette()[pFX->dwFillColor]);
|
|
}
|
|
else
|
|
{
|
|
//sort of a hack for 8 bit index passing
|
|
glColorBytes palIndex(pFX->dwFillColor, 0, 0, 255);
|
|
m_pSurf->FillColor(palIndex);
|
|
|
|
}
|
|
|
|
|
|
return DD_OK;
|
|
}
|
|
if (pSrcSurf && pSrcSurf->m_pSurf && pSrcSurf->m_pSurf->GetSurfaceType() != SoftSurface::SURFACE_NONE)
|
|
{
|
|
//assert(!"Dumbass alert");
|
|
m_pSurf->Blit(pDestRect->left, pDestRect->top, pSrcSurf->m_pSurf, pSrcRect->left, pSrcRect->top, pSrcRect->right-pSrcRect->left, pSrcRect->bottom-pSrcRect->top);
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_PRIMARY_GL:
|
|
{
|
|
if (flags & DDBLT_COLORFILL)
|
|
{
|
|
|
|
assert(pFX);
|
|
DrawRect(*pDestRect, GLCOLOR_TO_RGBA(g_palette.GetPalette()[pFX->dwFillColor]));
|
|
return DD_OK;
|
|
}
|
|
|
|
if (!pSrcSurf)
|
|
{
|
|
assert(!"huh?!");
|
|
return DD_OK;
|
|
}
|
|
if (pSrcSurf->m_mode == MODE_SHADOW_GL)
|
|
{
|
|
//blit from a GL surface instead
|
|
pSrcSurf->UpdateShadowSurface();
|
|
pSrcSurf->m_pGLSurf->BlitEx(rtRectf(*pDestRect) + rtRectf(0,0, 0.5f, 0.5f), rtRectf(*pSrcRect));
|
|
break;
|
|
}
|
|
|
|
SoftSurface s;
|
|
s.Init(pSrcRect->GetWidth(), pSrcRect->GetHeight(), SoftSurface::SURFACE_RGBA);
|
|
|
|
//s.FillColor(glColorBytes(0,0,0,0));
|
|
|
|
s.Blit(0,0, pSrcSurf->m_pSurf, pSrcRect->left,pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
|
|
if (pSrcSurf->m_pSurf->GetUsesAlpha())
|
|
{
|
|
s.SetUsesAlpha(true);
|
|
}
|
|
|
|
g_globalBatcher.BlitRawImage(pDestRect->left,pDestRect->top, s);
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
void IDirectDrawSurface::UpdateShadowSurface()
|
|
{
|
|
assert(m_mode == MODE_SHADOW_GL && "Don't call this on other modes!");
|
|
assert(m_pSurf);
|
|
|
|
if (m_pSurf->GetModified())
|
|
{
|
|
//init the surface if needed
|
|
if (!m_pGLSurf)
|
|
{
|
|
m_pGLSurf = new Surface;
|
|
|
|
m_pGLSurf->SetSmoothing(GetApp()->GetVar("smoothing")->GetUINT32() != 0);
|
|
|
|
if (GetApp()->GetVar("smoothing")->GetUINT32())
|
|
{
|
|
m_pGLSurf->SetTextureType(Surface::TYPE_GUI);
|
|
} else
|
|
{
|
|
m_pGLSurf->SetTextureType(Surface::TYPE_NO_SMOOTHING);
|
|
}
|
|
|
|
|
|
m_pGLSurf->InitBlankSurface(m_pSurf->GetWidth(),m_pSurf->GetHeight());
|
|
}
|
|
|
|
|
|
if (m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_PALETTE_8BIT)
|
|
{
|
|
SoftSurface s;
|
|
s.Init(m_pSurf->GetWidth(), m_pSurf->GetHeight(), SoftSurface::SURFACE_RGBA);
|
|
s.FillColor(glColorBytes(0,0,0,0));
|
|
s.Blit(0,0, m_pSurf);
|
|
s.FlipY();
|
|
|
|
|
|
|
|
//put it on the GL surface
|
|
m_pGLSurf->UpdateSurfaceRect(rtRect(0,0, s.GetWidth(), s.GetHeight()), s.GetPixelData());
|
|
m_pGLSurf->SetUsesAlpha(m_pSurf->GetUsesAlpha());
|
|
|
|
if (s.GetHasPremultipliedAlpha())
|
|
{
|
|
m_pGLSurf->SetBlendingMode(Surface::BLENDING_PREMULTIPLIED_ALPHA);
|
|
}
|
|
|
|
|
|
// if (m_pSurf) m_pSurf->SetModified(false); //WARNING: Seth changed on 8/21/2017, seems like this fixes issue with constantly re-initting surfaces
|
|
|
|
|
|
// SAFE_FREE(m_pSurf);
|
|
}
|
|
else
|
|
{
|
|
assert(m_pSurf);
|
|
assert(m_pGLSurf);
|
|
assert(m_pSurf->GetSurfaceType() == SoftSurface::SURFACE_RGBA);
|
|
//m_pSurf->FillColor(glColorBytes(0,0,0,0));
|
|
if (m_pSurf->GetPixelData())
|
|
{
|
|
m_pSurf->FlipY();
|
|
m_pGLSurf->UpdateSurfaceRect(rtRect(0,0, m_pSurf->GetWidth(), m_pSurf->GetHeight()), m_pSurf->GetPixelData(), true);
|
|
m_pSurf->FlipY();
|
|
m_pGLSurf->SetUsesAlpha(m_pSurf->GetUsesAlpha());
|
|
|
|
if (m_pSurf->GetHasPremultipliedAlpha())
|
|
{
|
|
m_pGLSurf->SetBlendingMode(Surface::BLENDING_PREMULTIPLIED_ALPHA);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m_pSurf) m_pSurf->SetModified(false);
|
|
|
|
//assert(m_pGLSurf->GetBlendingMode() == Surface::BLENDING_PREMULTIPLIED_ALPHA);
|
|
}
|
|
}
|
|
|
|
int IDirectDrawSurface::BltFast( int x, int y, IDirectDrawSurface *pSrcSurf, rtRect32 *pSrcRect, uint32 dwTrans )
|
|
{
|
|
|
|
if (pSrcSurf)
|
|
{
|
|
pSrcSurf->UpdateLastUsedTime();
|
|
}
|
|
|
|
switch (m_mode)
|
|
{
|
|
case MODE_SHADOW_GL:
|
|
case MODE_NORMAL:
|
|
|
|
|
|
if (pSrcSurf->m_mode == MODE_PRIMARY_GL)
|
|
{
|
|
//we need to copy from what is already on the screen
|
|
m_pSurf->BlitFromScreen(x, y, pSrcRect->left, pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
|
|
//m_pSurf->Blit(x, y, lpDDSBackGround->m_pSurf, pSrcRect->left, pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
|
|
//m_pSurf->SetUsesAlpha(false);
|
|
} else
|
|
{
|
|
m_pSurf->Blit(x, y, pSrcSurf->m_pSurf, pSrcRect->left, pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
|
|
}
|
|
break;
|
|
|
|
case MODE_PRIMARY_GL:
|
|
|
|
if (!pSrcSurf)
|
|
{
|
|
assert(!"Shit!");
|
|
return DD_OK;
|
|
}
|
|
|
|
if (pSrcSurf->m_mode == MODE_SHADOW_GL)
|
|
{
|
|
//blit from a GL surface instead
|
|
pSrcSurf->UpdateShadowSurface();
|
|
|
|
//skip if too big for surface
|
|
if (
|
|
(pSrcRect->GetHeight()+y > C_DINK_SCREENSIZE_Y) ||
|
|
(pSrcRect->GetWidth()+x > C_DINK_SCREENSIZE_X)
|
|
)
|
|
{
|
|
#ifdef _DEBUG
|
|
//LogMsg("Skipping blit, original Dink 1.08 would have rejected it for not fitting");
|
|
#endif
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
pSrcSurf->m_pGLSurf->BlitEx(rtRectf(x, y, x+pSrcRect->GetWidth(), y +pSrcRect->GetHeight())+ rtRectf(0,0, 0.5f, 0.5f), rtRectf(*pSrcRect));
|
|
break;
|
|
}
|
|
|
|
SoftSurface s;
|
|
s.Init(pSrcRect->GetWidth(), pSrcRect->GetHeight(), SoftSurface::SURFACE_RGBA);
|
|
s.Blit(0,0, pSrcSurf->m_pSurf, pSrcRect->left,pSrcRect->top, pSrcRect->GetWidth(), pSrcRect->GetHeight());
|
|
|
|
if (pSrcSurf->m_pSurf->GetUsesAlpha())
|
|
{
|
|
s.SetUsesAlpha(true);
|
|
}
|
|
g_globalBatcher.BlitRawImage(x,y, s);
|
|
break;
|
|
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
void IDirectDrawSurface::UpdateLastUsedTime()
|
|
{
|
|
m_gameTickOfLastUse = GetBaseApp()->GetGameTick();
|
|
} |