Skip to content

Commit

Permalink
Saving the thumbnail images from game, with full roundtrip
Browse files Browse the repository at this point in the history
  • Loading branch information
KKhanhH committed Sep 14, 2024
1 parent 830ed91 commit 4aff2ce
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 23 deletions.
38 changes: 30 additions & 8 deletions src/games/cclcc/savesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ SaveError SaveSystem::MountSaveFile() {
entryArray[i] = new SaveFileEntry();

entryArray[i]->Status = Io::ReadLE<uint16_t>(stream);
if(entryArray[i]->Status == 1 && entryArray == QuickSaveEntries) {
QuickSaveCount++;
}
// Not sure about these two
entryArray[i]->Checksum = Io::ReadLE<uint16_t>(stream);
Io::ReadLE<uint32_t>(stream);
Expand Down Expand Up @@ -199,7 +202,7 @@ void SaveSystem::FlushWorkingSaveEntry(SaveType type, int id) {
SaveFileEntry* entry = 0;
switch (type) {
case SaveQuick:
entry = (SaveFileEntry*)QuickSaveEntries[id];
entry = (SaveFileEntry*)QuickSaveEntries[QuickSaveCount++];
break;
case SaveFull:
entry = (SaveFileEntry*)FullSaveEntries[id];
Expand All @@ -214,17 +217,20 @@ void SaveSystem::FlushWorkingSaveEntry(SaveType type, int id) {
time(&rawtime);
entry->SaveDate = *localtime(&rawtime);
auto captureBuffer = Renderer->GetImageFromTexture(
WorkingSaveThumbnail.Sheet.Texture,
WorkingSaveThumbnail.Bounds);
WorkingSaveThumbnail.Sheet.Texture, WorkingSaveThumbnail.Bounds);

Texture tex;
tex.Init(TexFmt_RGBA, SaveThumbnailWidth, SaveThumbnailHeight);

entry->SaveThumbnail.Sheet = SpriteSheet(SaveThumbnailWidth, SaveThumbnailHeight);
entry->SaveThumbnail.Bounds = RectF(0.0f, 0.0f, SaveThumbnailWidth, SaveThumbnailHeight);
entry->SaveThumbnail.Sheet =
SpriteSheet(SaveThumbnailWidth, SaveThumbnailHeight);
entry->SaveThumbnail.Bounds =
RectF(0.0f, 0.0f, SaveThumbnailWidth, SaveThumbnailHeight);

int result = ResizeImage(WorkingSaveThumbnail.Bounds, entry->SaveThumbnail.Bounds,
captureBuffer, tcb::span{tex.Buffer, static_cast<size_t>(tex.BufferSize)});
int result = ResizeImage(
WorkingSaveThumbnail.Bounds, entry->SaveThumbnail.Bounds,
captureBuffer,
tcb::span{tex.Buffer, static_cast<size_t>(tex.BufferSize)}, true);
if (result < 0) {
ImpLog(LL_Error, LC_General, "Failed to resize save thumbnail\n");
}
Expand Down Expand Up @@ -337,7 +343,23 @@ void SaveSystem::WriteSaveFile() {
assert(stream->Position - startPos == 0x3ec0);
Io::WriteArrayLE<uint8_t>(entry->MapLoadData, stream, 0x6ac8);
Io::WriteArrayLE<uint8_t>(entry->YesNoData, stream, 0x54);
stream->Seek(67380, SEEK_CUR);

// CCLCC PS4 Save thumbnails are 240x135 RGB16
std::vector<uint8_t> thumbnailData = Renderer->GetImageFromTexture(
entry->SaveThumbnail.Sheet.Texture, entry->SaveThumbnail.Bounds);



int thumbnailPadding = 0xA14;
stream->Seek(thumbnailPadding, SEEK_CUR);

for (int i = 0; i < thumbnailData.size(); i+=4) {
uint8_t r = thumbnailData[i];
uint8_t g = thumbnailData[i + 1];
uint8_t b = thumbnailData[i + 2];
uint16_t pixel = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
Io::WriteLE<uint16_t>(stream, pixel);
}
}
}
}
Expand Down
7 changes: 0 additions & 7 deletions src/renderer/opengl/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,6 @@ std::vector<uint8_t> Renderer::GetImageFromTexture(uint32_t texture,

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo);
auto itr = result.begin();
auto revItr = result.rbegin();
while (itr < revItr.base()) {
std::swap_ranges(itr, itr + dimensions.Width * 4, revItr.base() - (dimensions.Width * 4));
itr += dimensions.Width * 4;
revItr += dimensions.Width * 4;
}
return result;
}

Expand Down
23 changes: 16 additions & 7 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,31 +83,30 @@ char* DumpMat4(glm::mat4* matrix, const char* columnSeparator,
}

int ResizeImage(Rect const& srcRect, Rect const& dstRect,
tcb::span<uint8_t> src, tcb::span<uint8_t> dst) {
tcb::span<uint8_t> src, tcb::span<uint8_t> dst, bool flipY) {
using SurfacePtr = std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)>;
if (srcRect.Width == dstRect.Width && srcRect.Height == dstRect.Height) {
assert(dst.size() >= src.size());
memcpy(dst.data(), src.data(), src.size());
return 0;
}


assert(src.size() >= srcRect.Width * srcRect.Height * 4);
SurfacePtr srcSurface(SDL_CreateRGBSurfaceWithFormatFrom(
src.data(), srcRect.Width, srcRect.Height, 32,
srcRect.Width * 4, SDL_PIXELFORMAT_RGBA32),
SDL_FreeSurface);
SDL_SetSurfaceBlendMode(srcSurface.get() , SDL_BLENDMODE_NONE);
SDL_SetSurfaceBlendMode(srcSurface.get(), SDL_BLENDMODE_NONE);
if (!srcSurface) {
ImpLog(LL_Error, LC_Render,
"SDL_CreateRGBSurfaceWithFormatFrom failed: %s\n", SDL_GetError());
return -1;
}
assert(dst.size() >= dstRect.Width * dstRect.Height * 4);
SurfacePtr dstSurface(
SDL_CreateRGBSurfaceWithFormatFrom(dst.data(), dstRect.Width, dstRect.Height, 32,
dstRect.Width * 4, SDL_PIXELFORMAT_RGBA32),
SDL_FreeSurface);
SurfacePtr dstSurface(SDL_CreateRGBSurfaceWithFormatFrom(
dst.data(), dstRect.Width, dstRect.Height, 32,
dstRect.Width * 4, SDL_PIXELFORMAT_RGBA32),
SDL_FreeSurface);
if (!dstSurface) {
ImpLog(LL_Error, LC_Render, "SDL_CreateRGBSurfaceWithFormat failed: %s\n",
SDL_GetError());
Expand All @@ -122,6 +121,16 @@ int ResizeImage(Rect const& srcRect, Rect const& dstRect,
ImpLog(LL_Error, LC_Render, "SDL_BlitScaled failed: %s\n", SDL_GetError());
return -1;
}
if (flipY) {
auto itr = dst.begin();
auto revItr = dst.rbegin();
while (itr < revItr.base() - (dstRect.Width * 4)) {
std::swap_ranges(itr, itr + dstRect.Width * 4,
revItr.base() - (dstRect.Width * 4));
itr += dstRect.Width * 4;
revItr += dstRect.Width * 4;
}
}
return 0;
}
} // namespace Impacto
2 changes: 1 addition & 1 deletion src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,6 @@ constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept {
}

int ResizeImage(Rect const& srcRect, Rect const& dstRect, tcb::span<uint8_t> src,
tcb::span<uint8_t> dst);
tcb::span<uint8_t> dst, bool flipY = false);

} // namespace Impacto

0 comments on commit 4aff2ce

Please sign in to comment.