You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
285 lines
6.0 KiB
285 lines
6.0 KiB
#include "diablo.h" |
|
#include "../3rdParty/Storm/Source/storm.h" |
|
#include "miniwin/ddraw.h" |
|
#include "miniwin/com_macro.h" |
|
#include <SDL.h> |
|
|
|
namespace dvl { |
|
|
|
int sgdwLockCount; |
|
BYTE *gpBuffer; |
|
#ifdef _DEBUG |
|
int locktbl[256]; |
|
#endif |
|
static CCritSect sgMemCrit; |
|
HMODULE ghDiabMod; |
|
|
|
SDL_Window *window; |
|
SDL_Renderer *renderer; |
|
SDL_Texture *texture; |
|
|
|
/** Currently active palette */ |
|
SDL_Palette *palette; |
|
unsigned int pal_surface_palette_version = 0; |
|
|
|
/** 32-bit in-memory backbuffer surface */ |
|
SDL_Surface *surface; |
|
|
|
/** 8-bit surface wrapper around #gpBuffer */ |
|
SDL_Surface *pal_surface; |
|
|
|
bool bufferUpdated = false; |
|
|
|
void dx_init(HWND hWnd) |
|
{ |
|
SDL_RaiseWindow(window); |
|
MainWndProc(NULL, DVL_WM_ACTIVATEAPP, true, 0); // TODO trigger on SDL_WINDOWEVENT_FOCUS_GAINED |
|
|
|
SDL_ShowWindow(window); |
|
|
|
dx_create_primary_surface(); |
|
palette_init(); |
|
dx_create_back_buffer(); |
|
} |
|
|
|
void dx_create_back_buffer() |
|
{ |
|
pal_surface = SDL_CreateRGBSurfaceWithFormat(0, BUFFER_WIDTH, BUFFER_HEIGHT, 8, SDL_PIXELFORMAT_INDEX8); |
|
if (pal_surface == NULL) { |
|
SDL_Log(SDL_GetError()); |
|
ERR_DLG(IDD_DIALOG1, DDERR_OUTOFMEMORY); |
|
} |
|
|
|
gpBuffer = (BYTE *)pal_surface->pixels; |
|
|
|
#ifdef USE_SDL1 |
|
if (SDL_SetPalette(pal_surface, SDL_LOGPAL, palette->colors, 0, palette->ncolors) != 1) { |
|
#else |
|
if (SDL_SetSurfacePalette(pal_surface, palette) <= -1) { |
|
#endif |
|
SDL_Log(SDL_GetError()); |
|
ERR_DLG(IDD_DIALOG1, DDERR_INVALIDOBJECT); |
|
} |
|
|
|
pal_surface_palette_version = 1; |
|
} |
|
|
|
void dx_create_primary_surface() |
|
{ |
|
#ifdef USE_SDL1 |
|
surface = SDL_GetVideoSurface(); |
|
#else |
|
if (renderer) { |
|
int width, height; |
|
if (SDL_GetRendererOutputSize(renderer, &width, &height) <= -1) { |
|
SDL_Log(SDL_GetError()); |
|
} |
|
// TODO Get format from render/window |
|
surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_RGBA8888); |
|
} else { |
|
surface = SDL_GetWindowSurface(window); |
|
} |
|
#endif |
|
if (surface == NULL) { |
|
SDL_Log(SDL_GetError()); |
|
ERR_DLG(IDD_DIALOG1, DDERR_OUTOFMEMORY); |
|
} |
|
} |
|
|
|
void lock_buf(BYTE idx) |
|
{ |
|
#ifdef _DEBUG |
|
locktbl[idx]++; |
|
#endif |
|
lock_buf_priv(); |
|
} |
|
|
|
void lock_buf_priv() |
|
{ |
|
sgMemCrit.Enter(); |
|
if (sgdwLockCount != 0) { |
|
sgdwLockCount++; |
|
return; |
|
} |
|
|
|
gpBufEnd += (uintptr_t)(BYTE *)pal_surface->pixels; |
|
gpBuffer = (BYTE *)pal_surface->pixels; |
|
sgdwLockCount++; |
|
} |
|
|
|
void unlock_buf(BYTE idx) |
|
{ |
|
#ifdef _DEBUG |
|
if (!locktbl[idx]) |
|
app_fatal("Draw lock underflow: 0x%x", idx); |
|
locktbl[idx]--; |
|
#endif |
|
unlock_buf_priv(); |
|
} |
|
|
|
void unlock_buf_priv() |
|
{ |
|
HRESULT error_code; |
|
|
|
if (sgdwLockCount == 0) |
|
app_fatal("draw main unlock error"); |
|
if (!gpBuffer) |
|
app_fatal("draw consistency error"); |
|
|
|
sgdwLockCount--; |
|
if (sgdwLockCount == 0) { |
|
gpBufEnd -= (uintptr_t)gpBuffer; |
|
//gpBuffer = NULL; unable to return to menu |
|
error_code = RenderPresent(); |
|
if (error_code != DVL_S_OK) |
|
DD_ERR_MSG(error_code); |
|
} |
|
sgMemCrit.Leave(); |
|
} |
|
|
|
void dx_cleanup() |
|
{ |
|
if (ghMainWnd) |
|
ShowWindow(ghMainWnd, 0); |
|
sgMemCrit.Enter(); |
|
sgdwLockCount = 0; |
|
gpBuffer = NULL; |
|
sgMemCrit.Leave(); |
|
|
|
if (pal_surface == nullptr) |
|
return; |
|
SDL_FreeSurface(pal_surface); |
|
pal_surface = nullptr; |
|
SDL_FreePalette(palette); |
|
SDL_FreeSurface(surface); |
|
SDL_DestroyTexture(texture); |
|
SDL_DestroyRenderer(renderer); |
|
SDL_DestroyWindow(window); |
|
} |
|
|
|
void dx_reinit() |
|
{ |
|
int lockCount; |
|
|
|
sgMemCrit.Enter(); |
|
ClearCursor(); |
|
lockCount = sgdwLockCount; |
|
|
|
while (sgdwLockCount != 0) |
|
unlock_buf_priv(); |
|
|
|
dx_cleanup(); |
|
|
|
drawpanflag = 255; |
|
|
|
dx_init(ghMainWnd); |
|
|
|
while (lockCount != 0) { |
|
lock_buf_priv(); |
|
lockCount--; |
|
} |
|
|
|
sgMemCrit.Leave(); |
|
} |
|
|
|
HRESULT CreatePalette() |
|
{ |
|
palette = SDL_AllocPalette(256); |
|
if (palette == NULL) { |
|
SDL_Log(SDL_GetError()); |
|
return DDERR_OUTOFMEMORY; |
|
} |
|
|
|
return DVL_DS_OK; |
|
} |
|
|
|
HRESULT BltFast(DWORD dwX, DWORD dwY, LPRECT lpSrcRect) |
|
{ |
|
auto w = static_cast<decltype(SDL_Rect().w)>(lpSrcRect->right - lpSrcRect->left + 1); |
|
auto h = static_cast<decltype(SDL_Rect().h)>(lpSrcRect->bottom - lpSrcRect->top + 1); |
|
SDL_Rect src_rect = { |
|
static_cast<decltype(SDL_Rect().x)>(lpSrcRect->left), |
|
static_cast<decltype(SDL_Rect().y)>(lpSrcRect->top), |
|
w, h |
|
}; |
|
SDL_Rect dst_rect = { |
|
static_cast<decltype(SDL_Rect().x)>(dwX), |
|
static_cast<decltype(SDL_Rect().y)>(dwY), |
|
w, h |
|
}; |
|
|
|
// Convert from 8-bit to 32-bit |
|
if (SDL_BlitSurface(pal_surface, &src_rect, surface, &dst_rect) <= -1) { |
|
SDL_Log(SDL_GetError()); |
|
return DVL_E_FAIL; |
|
} |
|
|
|
bufferUpdated = true; |
|
|
|
return DVL_S_OK; |
|
} |
|
|
|
HRESULT RenderPresent() |
|
{ |
|
assert(!SDL_MUSTLOCK(surface)); |
|
|
|
if (!bufferUpdated) { |
|
return DVL_S_OK; |
|
} |
|
|
|
#ifdef USE_SDL1 |
|
if (SDL_Flip(surface) <= -1) { |
|
SDL_Log(SDL_GetError()); |
|
} |
|
#else |
|
if (renderer) { |
|
if (SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch) <= -1) { //pitch is 2560 |
|
SDL_Log(SDL_GetError()); |
|
} |
|
|
|
// Clear buffer to avoid artifacts in case the window was resized |
|
if (SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) <= -1) { // TODO only do this if window was resized |
|
SDL_Log(SDL_GetError()); |
|
} |
|
|
|
if (SDL_RenderClear(renderer) <= -1) { |
|
SDL_Log(SDL_GetError()); |
|
} |
|
|
|
if (SDL_RenderCopy(renderer, texture, NULL, NULL) <= -1) { |
|
SDL_Log(SDL_GetError()); |
|
} |
|
SDL_RenderPresent(renderer); |
|
} else { |
|
if (SDL_UpdateWindowSurface(window) <= -1) { |
|
SDL_Log(SDL_GetError()); |
|
} |
|
} |
|
#endif |
|
|
|
bufferUpdated = false; |
|
|
|
return DVL_S_OK; |
|
} |
|
|
|
void PaletteGetEntries(DWORD dwNumEntries, LPPALETTEENTRY lpEntries) |
|
{ |
|
for (DWORD i = 0; i < dwNumEntries; i++) { |
|
lpEntries[i].peFlags = 0; |
|
lpEntries[i].peRed = system_palette[i].peRed; |
|
lpEntries[i].peGreen = system_palette[i].peGreen; |
|
lpEntries[i].peBlue = system_palette[i].peBlue; |
|
} |
|
} |
|
|
|
void PaletteSetEntries(DWORD dwCount, LPPALETTEENTRY lpEntries) |
|
{ |
|
for (DWORD i = 0; i < dwCount; i++) { |
|
system_palette[i].peFlags = 0; |
|
system_palette[i].peRed = lpEntries[i].peRed; |
|
system_palette[i].peGreen = lpEntries[i].peGreen; |
|
system_palette[i].peBlue = lpEntries[i].peBlue; |
|
} |
|
palette_update(); |
|
} |
|
} // namespace dvl
|
|
|