diff --git a/.editorconfig b/.editorconfig index bd11302d2..d62a3b32a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,6 +20,12 @@ end_of_line = lf [SourceX/storm/storm_dx.cpp] end_of_line = lf +[SourceX/DiabloUI/*] +end_of_line = lf + +[SourceX/DiabloUI/diabloui.cpp] +end_of_line = crlf + [*.yml] indent_style = space end_of_line = lf diff --git a/SourceX/DiabloUI/credits.cpp b/SourceX/DiabloUI/credits.cpp index 8e15f0006..affdc2a70 100644 --- a/SourceX/DiabloUI/credits.cpp +++ b/SourceX/DiabloUI/credits.cpp @@ -479,8 +479,7 @@ void credts_Load() void credts_Free() { - mem_free_dbg(ArtBackground.data); - ArtBackground.data = NULL; + ArtBackground.Unload(); } void credts_Render() @@ -523,16 +522,16 @@ void credts_Render() text_surface = TTF_RenderUTF8_Solid(font, the_long_credits[creditLine + i] + offset, color); shadow_surface = TTF_RenderUTF8_Solid(font, the_long_credits[creditLine + i] + offset, black_color); if (text_surface && shadow_surface) { - SDL_Rect src_rect = { 0, -y, SCREEN_WIDTH, 251 }; + SDL_Rect src_rect = { 0, -y, text_surface->w, 251 }; // draw text shadow. - SDL_Rect dsc_rect2 = { 64 + x + 2, SCREEN_Y + 114 + 2, SCREEN_WIDTH, SCREEN_HEIGHT }; + SDL_Rect dsc_rect2 = { 64 + x + 2, SCREEN_Y + 114 + 2, src_rect.w, src_rect.h }; if (SDL_BlitSurface(shadow_surface, &src_rect, pal_surface, &dsc_rect2) <= -1) { SDL_Log(SDL_GetError()); } // draw text. - SDL_Rect dsc_rect = { 64 + x, SCREEN_Y + 114, SCREEN_WIDTH, SCREEN_HEIGHT }; + SDL_Rect dsc_rect = { 64 + x, SCREEN_Y + 114, src_rect.w, src_rect.h }; if (SDL_BlitSurface(text_surface, &src_rect, pal_surface, &dsc_rect) <= -1) { SDL_Log(SDL_GetError()); } diff --git a/SourceX/DiabloUI/diabloui.cpp b/SourceX/DiabloUI/diabloui.cpp index 5289ab57b..fdaa961e8 100644 --- a/SourceX/DiabloUI/diabloui.cpp +++ b/SourceX/DiabloUI/diabloui.cpp @@ -133,8 +133,7 @@ BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, void UiDestroy() { DUMMY(); - mem_free_dbg(ArtHero.data); - ArtHero.data = NULL; + ArtHero.Unload(); if (font) TTF_CloseFont(font); @@ -369,27 +368,50 @@ bool IsInsideRect(const SDL_Event *event, const SDL_Rect *rect) void LoadArt(char *pszFile, Art *art, int frames, PALETTEENTRY *pPalette) { - if (art == NULL || art->data != NULL) + if (art == NULL || art->surface != NULL) return; - if (!SBmpLoadImage(pszFile, 0, 0, 0, &art->width, &art->height, 0)) + DWORD width, height, bpp; + if (!SBmpLoadImage(pszFile, 0, 0, 0, &width, &height, &bpp)) return; - art->data = (BYTE *)malloc(art->width * art->height); - if (!SBmpLoadImage(pszFile, pPalette, art->data, art->width * art->height, 0, 0, 0)) - return; + Uint32 format; + switch (bpp) { + case 8: + format = SDL_PIXELFORMAT_INDEX8; + break; + case 24: + format = SDL_PIXELFORMAT_RGB888; + break; + case 32: + format = SDL_PIXELFORMAT_RGBA8888; + break; + default: + format = 0; + break; + } + SDL_Surface *art_surface = SDL_CreateRGBSurfaceWithFormat(SDL_SWSURFACE, width, height, bpp, format); - if (art->data == NULL) + if (!SBmpLoadImage(pszFile, pPalette, static_cast(art_surface->pixels), + art_surface->pitch * art_surface->format->BytesPerPixel * height, 0, 0, 0)) { + SDL_Log("Failed to load image"); + SDL_FreeSurface(art_surface); return; + } - art->height /= frames; + art->surface = art_surface; + art->frames = frames; + art->frame_height = height / frames; } void LoadMaskedArtFont(char *pszFile, Art *art, int frames, int mask) { LoadArt(pszFile, art, frames); - art->masked = true; - art->mask = mask; +#ifdef USE_SDL1 + SDL_SetColorKey(art->surface, SDL_SRCCOLORKEY | SDL_RLEACCEL, mask); +#else + SDL_SetColorKey(art->surface, SDL_TRUE, mask); +#endif } void LoadArtFont(char *pszFile, int size, int color) @@ -577,27 +599,25 @@ BOOL UiCreatePlayerDescription(_uiheroinfo *info, DWORD mode, char *desc) void DrawArt(int screenX, int screenY, Art *art, int nFrame, DWORD drawW) { - if (screenY >= SCREEN_WIDTH || screenX >= SCREEN_WIDTH) + if (screenY >= SCREEN_Y + SCREEN_HEIGHT || screenX >= SCREEN_X + SCREEN_WIDTH) return; - BYTE *__restrict src = (BYTE *)art->data + (art->width * art->height * nFrame); - BYTE *__restrict dst = &gpBuffer[screenX + 64 + (screenY + SCREEN_Y) * BUFFER_WIDTH]; - drawW = drawW ? drawW : art->width; + SDL_Rect src_rect = {0, nFrame * art->h(), art->w(), art->h()}; + if (drawW && drawW < src_rect.w) + src_rect.w = drawW; + SDL_Rect dst_rect = {screenX + SCREEN_X, screenY + SCREEN_Y, src_rect.w, src_rect.h}; - const DWORD iSize = std::min(art->height, static_cast(SCREEN_HEIGHT - screenY)); - const DWORD jSize = std::min(art->width, std::min(drawW, static_cast(SCREEN_WIDTH - screenX))); + if (art->surface->format->BitsPerPixel == 8) { +#ifdef USE_SDL1 + if (SDL_SetPalette(art->surface, SDL_LOGPAL, pal_surface->format->palette->colors, 0, 256) != 1) +#else + if (SDL_SetSurfacePalette(art->surface, pal_surface->format->palette) <= -1) +#endif + SDL_Log(SDL_GetError()); + } - if (art->masked) { - for (DWORD i = 0; i < iSize; i++, src += art->width, dst += BUFFER_WIDTH) { - for (DWORD j = 0; j < jSize; j++) { - if (src[j] != art->mask) - dst[j] = src[j]; - } - } - } else { - for (DWORD i = 0; i < iSize; i++, src += art->width, dst += BUFFER_WIDTH) { - memcpy(dst, src, jSize * sizeof(dst[0])); - } + if (SDL_BlitSurface(art->surface, &src_rect, pal_surface, &dst_rect) <= -1) { + SDL_Log(SDL_GetError()); } } @@ -702,12 +722,12 @@ void DrawArtStr(UI_Item *item) int sx = x; int sy = item->rect.y; if (item->flags & UIS_VCENTER) - sy += (item->rect.h - ArtFonts[size][color].height) / 2; + sy += (item->rect.h - ArtFonts[size][color].h()) / 2; for (size_t i = 0; i < strlen((char *)item->caption); i++) { if (item->caption[i] == '\n') { sx = x; - sy += ArtFonts[size][color].height; + sy += ArtFonts[size][color].h(); continue; } BYTE w = FontTables[size][*(BYTE *)&item->caption[i] + 2] ? FontTables[size][*(BYTE *)&item->caption[i] + 2] : FontTables[size][0]; @@ -775,12 +795,13 @@ void DrawSelector(UI_Item *item = 0) size = FOCUS_BIG; else if (item->rect.h >= 30) size = FOCUS_MED; + Art *art = &ArtFocus[size]; - int frame = GetAnimationFrame(8); - int y = item->rect.y + (item->rect.h - ArtFocus[size].height) / 2; // TODO FOCUS_MED appares higher then the box + int frame = GetAnimationFrame(art->frames); + int y = item->rect.y + (item->rect.h - art->h()) / 2; // TODO FOCUS_MED appares higher then the box - DrawArt(item->rect.x, y, &ArtFocus[size], frame); - DrawArt(item->rect.x + item->rect.w - ArtFocus[size].width, y, &ArtFocus[size], frame); + DrawArt(item->rect.x, y, art, frame); + DrawArt(item->rect.x + item->rect.w - art->w(), y, art, frame); } void DrawEditBox(UI_Item item) @@ -878,7 +899,7 @@ bool UiItemMouseEvents(SDL_Event *event, UI_Item *items, int size) void DrawLogo(int t, int size) { - DrawArt(GetCenterOffset(ArtLogos[size].width), t, &ArtLogos[size], GetAnimationFrame(15)); + DrawArt(GetCenterOffset(ArtLogos[size].w()), t, &ArtLogos[size], GetAnimationFrame(15)); } void DrawMouse() diff --git a/SourceX/DiabloUI/diabloui.h b/SourceX/DiabloUI/diabloui.h index 182ab02f0..c18853e60 100644 --- a/SourceX/DiabloUI/diabloui.h +++ b/SourceX/DiabloUI/diabloui.h @@ -55,11 +55,22 @@ typedef enum UiFlags { } UiFlags; typedef struct Art { - BYTE *data; - DWORD width; - DWORD height; - bool masked = false; - BYTE mask; + SDL_Surface *surface = NULL; + int frames = 1; + int frame_height = 0; + + int w() const { + return surface->w; + } + + int h() const { + return frame_height; + } + + void Unload() { + SDL_FreeSurface(surface); + surface = NULL; + } } Art; typedef struct UI_Item { diff --git a/SourceX/DiabloUI/mainmenu.cpp b/SourceX/DiabloUI/mainmenu.cpp index 941641e6f..aa2ea6321 100644 --- a/SourceX/DiabloUI/mainmenu.cpp +++ b/SourceX/DiabloUI/mainmenu.cpp @@ -49,15 +49,14 @@ void mainmenu_Load(char *name, void(*fnSound)(char *file)) void mainmenu_Free() { - mem_free_dbg(ArtBackground.data); - ArtBackground.data = NULL; + ArtBackground.Unload(); } BOOL UiMainMenuDialog(char *name, int *pdwResult, void(*fnSound)(char *file), int attractTimeOut) { mainmenu_attract_time_out = attractTimeOut; mainmenu_Load(name, fnSound); - + mainmenu_restart_repintro(); // for automatic starts while (MainMenuResult == 0) { diff --git a/SourceX/DiabloUI/progress.cpp b/SourceX/DiabloUI/progress.cpp index 579cd0fb6..80fd81694 100644 --- a/SourceX/DiabloUI/progress.cpp +++ b/SourceX/DiabloUI/progress.cpp @@ -32,16 +32,11 @@ void progress_Load(char *msg) void progress_Free() { - mem_free_dbg(ArtBackground.data); - ArtBackground.data = NULL; - mem_free_dbg(ArtPopupSm.data); - ArtPopupSm.data = NULL; - mem_free_dbg(ArtProgBG.data); - ArtProgBG.data = NULL; - mem_free_dbg(ProgFil.data); - ProgFil.data = NULL; - mem_free_dbg(ButImage.data); - ButImage.data = NULL; + ArtBackground.Unload(); + ArtPopupSm.Unload(); + ArtProgBG.Unload(); + ProgFil.Unload(); + ButImage.Unload(); SDL_FreeSurface(msgSurface); msgSurface = NULL; SDL_FreeSurface(cancleSurface); diff --git a/SourceX/DiabloUI/selconn.cpp b/SourceX/DiabloUI/selconn.cpp index 77792a723..643277410 100644 --- a/SourceX/DiabloUI/selconn.cpp +++ b/SourceX/DiabloUI/selconn.cpp @@ -45,8 +45,7 @@ void selconn_Load() void selconn_Free() { - mem_free_dbg(ArtBackground.data); - ArtBackground.data = NULL; + ArtBackground.Unload(); } void selconn_Esc() diff --git a/SourceX/DiabloUI/selgame.cpp b/SourceX/DiabloUI/selgame.cpp index 526e65fe1..ffb48257b 100644 --- a/SourceX/DiabloUI/selgame.cpp +++ b/SourceX/DiabloUI/selgame.cpp @@ -71,8 +71,7 @@ UI_Item ENTERPASSWORD_DIALOG[] = { void selgame_Free() { - mem_free_dbg(ArtBackground.data); - ArtBackground.data = NULL; + ArtBackground.Unload(); } void selgame_GameSelection_Init() diff --git a/SourceX/DiabloUI/selhero.cpp b/SourceX/DiabloUI/selhero.cpp index a189b8381..cdd429251 100644 --- a/SourceX/DiabloUI/selhero.cpp +++ b/SourceX/DiabloUI/selhero.cpp @@ -88,8 +88,7 @@ void selhero_UiFocusNavigationYesNo() void selhero_Free() { - mem_free_dbg(ArtBackground.data); - ArtBackground.data = NULL; + ArtBackground.Unload(); memset(listItems, 0, sizeof(listItems)); } diff --git a/SourceX/DiabloUI/selyesno.cpp b/SourceX/DiabloUI/selyesno.cpp index 23bf05425..5fc1cc79f 100644 --- a/SourceX/DiabloUI/selyesno.cpp +++ b/SourceX/DiabloUI/selyesno.cpp @@ -22,8 +22,7 @@ UI_Item SELYESNO_DIALOG[] = { void selyesno_Free() { - mem_free_dbg(ArtBackground.data); - ArtBackground.data = NULL; + ArtBackground.Unload(); } void selyesno_Select(int value) diff --git a/SourceX/DiabloUI/title.cpp b/SourceX/DiabloUI/title.cpp index 27d5c7568..da3491f51 100644 --- a/SourceX/DiabloUI/title.cpp +++ b/SourceX/DiabloUI/title.cpp @@ -11,10 +11,8 @@ void title_Load() void title_Free() { - mem_free_dbg(ArtBackground.data); - ArtBackground.data = NULL; - mem_free_dbg(ArtLogos[LOGO_BIG].data); - ArtLogos[LOGO_BIG].data = NULL; + ArtBackground.Unload(); + ArtLogos[LOGO_BIG].Unload(); } BOOL UiTitleDialog(int a1) diff --git a/SourceX/storm/storm.cpp b/SourceX/storm/storm.cpp index bcafbef6b..30a7aa0ff 100644 --- a/SourceX/storm/storm.cpp +++ b/SourceX/storm/storm.cpp @@ -243,6 +243,13 @@ BOOL SBmpLoadImage(const char *pszFileName, PALETTEENTRY *pPalette, BYTE *pBuffe int width = SDL_SwapLE16(pcxhdr.Xmax) - SDL_SwapLE16(pcxhdr.Xmin) + 1; int height = SDL_SwapLE16(pcxhdr.Ymax) - SDL_SwapLE16(pcxhdr.Ymin) + 1; + // If the given buffer is larger than width * height, assume the extra data + // is scanline padding. + // + // This is useful because in SDL the pitch size is often slightly larger + // than image width for efficiency. + const int x_skip = dwBuffersize / height - width; + if (pdwWidth) *pdwWidth = width; if (dwHeight) @@ -279,6 +286,8 @@ BOOL SBmpLoadImage(const char *pszFileName, PALETTEENTRY *pPalette, BYTE *pBuffe x++; } } + // Skip the pitch padding. + pBuffer += x_skip; } free(fileBuffer);