rodecomp/Source/Resource/Sprites/SpriteResource.cpp
ragnarok-clanker dc3d5ce1a5 Maintenance: Resubmission of 14942 (gate: three existing in-class helpers whose lines changed lacked an annotation; marked // INLINED
Batch #14943 by ragnarok-clanker: no function's compiled code changes; checked with 741 compiled unit(s), including every includer of Source/ActorPickNode.h, Source/Client/Browser/BrowserClientSite.h, Source/Client/Browser/BrowserPopupDispatch.h, Source/Client/Mode/CGameMode.h, Source/Client/Mode/CLoginMode.h, Source/Client/Mode/CMode.h, Source/Client/Mode/ModeDragState.h, Source/Client/Replay.h, Source/Client/Session.h, Source/Client/Stove/StoveMgr.h, Source/Contents/AchievementMgr.h, Source/Contents/ActorNameCard.h, Source/Contents/Actors/CharacterRender.h, Source/Contents/Actors/EffectActors.h, Source/Contents/Actors/GameActor.h, Source/Contents/Actors/GrannyGameActor.h, Source/Contents/Actors/GroundScope.h, Source/Contents/Actors/Item.h, Source/Contents/Actors/Npc.h, Source/Contents/Actors/Pc.h, Source/Contents/Actors/RenderObjectState.h, Source/Contents/Actors/Skill.h, Source/Contents/AdventureGuideMgr.h, Source/Contents/Camera/Camera.h, Source/Contents/Camera/CameraState.h, Source/Contents/CashEmotionMgr.h, Source/Contents/Configuration/GameSettingsMgr.h, Source/Contents/EffectResourceSwitcher.h, Source/Contents/Effects/AMachineEffect.h, Source/Contents/Effects/AcidifiedThrow.h, Source/Contents/Effects/AxeBoomerang.h, Source/Contents/Effects/BlastForge.h, Source/Contents/Effects/CaneOfEvilEyeEffect.h, Source/Contents/Effects/CharacterParticleBundle.h, Source/Contents/Effects/CloudKillEffect.h, Source/Contents/Effects/Effect.h, Source/Contents/Effects/EffectActor.h, Source/Contents/Effects/EffectEmitter.h, Source/Contents/Effects/EffectMaker.h, Source/Contents/Effects/EffectPrimitiveState.h, Source/Contents/Effects/FuumaShouakuEffect.h, Source/Contents/Effects/GravityControlEffect.h, Source/Contents/Effects/HealSpEffect.h, Source/Contents/Effects/Level99Effect.h, Source/Contents/Effects/MapChainEffect.h, Source/Contents/Effects/MonsterSkillEffects.h, Source/Contents/Effects/MsgEffect.h, Source/Contents/Effects/NyanggrassEffect.h, Source/Contents/Effects/Particle.h, Source/Contents/Effects/PowderingEffect.h, Source/Contents/Effects/RagEffectState.h, Source/Contents/Effects/RectUpEffect.h, Source/Contents/Effects/ShadowExceedEffect.h, Source/Contents/Effects/SkillEffects.h, Source/Contents/Effects/SpriteParticle.h, Source/Contents/Effects/StormCannonEffect.h, Source/Contents/Effects/ThrowEffects.h, Source/Contents/EntryQueueMgr.h, Source/Contents/EquipmentResourceMgr.h, Source/Contents/FlyingShipRouteInfo.h, Source/Contents/Ground/GroundGeometry.h, Source/Contents/GuildInfo.h, Source/Contents/Items/ItemDescription.h, Source/Contents/Items/ItemInfo.h, Source/Contents/MapSkyMgr.h, Source/Contents/Messenger/MessengerWindows.h, Source/Contents/Models/ModelNode.h, Source/Contents/NavigationManager.h, Source/Contents/Party/AdventurerAgencyMgr.h, Source/Contents/RDamageVar.h, Source/Contents/RenewQuestMgr.h, Source/Contents/ReputeMgr.h, Source/Contents/RodexMailStore.h, Source/Contents/RouletteMgr.h, Source/Contents/Schedule/Schedule.h, Source/Contents/SignBoard/SignBoard.h, Source/Contents/Skills/ClientSkills.h, Source/Contents/Skills/PlayerSkillBundle.h, Source/Contents/Skills/SkillInfo.h, Source/Contents/SpriteLayerDrawing.h, Source/Contents/TipBoxTitles.h, Source/Contents/UserData/AccountLinkedUserDataMgr.h, Source/Contents/UserData/NormalItemSlots.h, Source/Contents/World/World.h, Source/Contents/WorldView/WorldViewData.h, Source/Render/Primitives/LightmappedPrimitive.h, Source/Render/Primitives/RenderPrimitive.h, Source/Render/Renderer.h, Source/Render/Textures/SpritePixels.h, Source/Render/Textures/Texture.h, Source/Resource/EZeffectResource.h, Source/Resource/Models/AnimatedModelResource.h, Source/Resource/Models/GrannyModelResource.h, Source/Resource/Sprites/ActionResource.h, Source/Resource/World/GroundResource.h, Source/Resource/World/WorldResource.h, Source/Resource/XmlNode.h, Source/UI/AdventureGuide/UIAdventureGuide.h, Source/UI/Buttons/UIBmpRadioBtn.h, Source/UI/Buttons/UIDescriptRace.h, Source/UI/Buttons/UIItemTagButton.h, Source/UI/Buttons/UISlotBmpButton.h, Source/UI/Buttons/UISpriteButton.h, Source/UI/Buttons/UITVTextButton.h, Source/UI/Buttons/UITextureButton.h, Source/UI/CashEmotion/UICashEmotionListWnd.h, Source/UI/CashEmotion/UICashEmotionPack.h, Source/UI/CashShop/UICashShopWnd.h, Source/UI/Chat/UIChatRoomMakeWnd.h, Source/UI/Chat/UIChatRoomTitle.h, Source/UI/Chat/UINewChatWnd.h, Source/UI/Chat/UISubChatHisWnd.h, Source/UI/Chat/UISubChatMiniWnd.h, Source/UI/Chat/UIWhisperWnd.h, Source/UI/Clan/UIClanWnd.h, Source/UI/Dialogs/UIBookWnd.h, Source/UI/Dialogs/UIChooseWarpWnd.h, Source/UI/Dialogs/UIMenuWnd.h, Source/UI/Dialogs/UIMiniMapWnd.h, Source/UI/Dialogs/UIMinimapZoomWnd.h, Source/UI/Dialogs/UINpcEditDialogWnd.h, Source/UI/Dialogs/UIPasswordWnd.h, Source/UI/Dialogs/UISayDialogWnd.h, Source/UI/Dialogs/UISelectCartWnd.h, Source/UI/Dialogs/UITipboxWnd.h, Source/UI/Edit/UIEditBoxEx.h, Source/UI/Edit/UIEditCtrl.h, Source/UI/Edit/UIEditCtrl_Currency.h, Source/UI/Edit/UIItemTagCtrl.h, Source/UI/Enchant/EnchantUI.h, Source/UI/Exchange/UIExchangeUI.h, Source/UI/FrameSkin.h, Source/UI/GameSettings/GameSettingsUI.h, Source/UI/Gauges/UIPcGage.h, Source/UI/Guild/UIGuildHelperWnd.h, Source/UI/Guild/UIGuildWnd.h, Source/UI/Guild/UIGuild_Storage_Log.h, Source/UI/Item/UIEquipmentPropertiesWnd.h, Source/UI/Item/UIItemBaseWnd.h, Source/UI/Item/UIItemPurchaseWnd.h, Source/UI/Item/UIItemSellWnd2.h, Source/UI/Item/UIItemShopWnd.h, Source/UI/Item/UIItemShopWnd2.h, Source/UI/Item/UIItemStoreFindWnd.h, Source/UI/Item/UIItemStoreSubWnd.h, Source/UI/Item/UIItemStoreWnd.h, Source/UI/Item/UIItemWnd.h, Source/UI/Item/UIMerchantItemLogWnd.h, Source/UI/Item/UIParaItemShopWnd.h, Source/UI/Items/UICardItemIllustWnd.h, Source/UI/Items/UIEquipWnd.h, Source/UI/Items/UIExchangeWnd.h, Source/UI/Items/UIGameItem.h, Source/UI/Items/UIItemCollectionWnd.h, Source/UI/Items/UIItemIdentifyWnd.h, Source/UI/Items/UIItemParamChangeDisplayWnd.h, Source/UI/Items/UISwapEquipmentWnd.h, Source/UI/Layout/WindowGeometry.h, Source/UI/Lists/UIChatHisBox.h, Source/UI/Lists/UIComboBoxV2Wnd.h, Source/UI/Lists/UIImgMenu.h, Source/UI/Lists/UIListBoxID.h, Source/UI/Lists/UIListBoxTemplate.h, Source/UI/Lists/UIMemberListBox.h, Source/UI/Lists/UITabControl.h, Source/UI/Lists/UITagListBox.h, Source/UI/Lists/UITreeView.h, Source/UI/Menu/UIMenuIconWnd.h, Source/UI/Navigation/UINavigationV4Wnd.h, Source/UI/ProbabilityTable/UIProbabilityTable.h, Source/UI/Quest/UIQuestDisplay.h, Source/UI/Quest/UIRenewQuestUI.h, Source/UI/Quest/UIRenewQuestWnd.h, Source/UI/Rodex/UIRodexComposeWnd.h, Source/UI/Rodex/UIRodexInboxWnd.h, Source/UI/RuneSystem/UIRuneSystemWindows.h, Source/UI/RuneSystem/UIRuneSystemWnd.h, Source/UI/Shop/UIMerchantItemMyShopWnd.h, Source/UI/Shop/UIMerchantItemPurchaseMSGWnd.h, Source/UI/Shop/UIMerchantItemPurchaseWnd.h, Source/UI/Shop/UIMerchantItemShopWnd.h, Source/UI/Shop/UIMerchantMirrorItemWnd.h, Source/UI/Shop/UIMerchantShopMakeWnd.h, Source/UI/Shop/UIMerchantShopTitle.h, Source/UI/Skill/UISkillDescribeWnd.h, Source/UI/Skill/UISkillListWnd.h, Source/UI/SkillDelayInfo/SkillDelayInfo.h, Source/UI/StylingShop/UIStylingShopWnd.h, Source/UI/Text/CreateLineInfo.h, Source/UI/Text/UIAchWnd.h, Source/UI/Text/UIBalloonText.h, Source/UI/Text/UINameBalloonText.h, Source/UI/Text/UIStaticTextControl.h, Source/UI/Text/UIString.h, Source/UI/Text/UITextViewerControl.h, Source/UI/UIBarGraph.h, Source/UI/UIBartermarketWnd.h, Source/UI/UIChangeMaterialWnd.h, Source/UI/UIGradeEnchantWnd.h, Source/UI/UILapineScrollBar.h, Source/UI/UIMacroBlackListCheckWnd.h, Source/UI/UIMacroDetectorWnd.h, Source/UI/UIMacroReport.h, Source/UI/UIMacroUserInfoWnd.h, Source/UI/UIPreviewEquipWnd.h, Source/UI/UIRefiningWnd.h, Source/UI/UIScrollWnd.h, Source/UI/UISlotBitmap.h, Source/UI/Window/FuncDrawWNDChar.h, Source/UI/Window/UIBattleMsgOptionWnd.h, Source/UI/Window/UIChatRoomWnd.h, Source/UI/Window/UICollectionSystemWnd.h, Source/UI/Window/UIControl.h, Source/UI/Window/UIHomunInfoWnd.h, Source/UI/Window/UIHotKeyWnd.h, Source/UI/Window/UIJobListWnd.h, Source/UI/Window/UILoginOTPWnd.h, Source/UI/Window/UILoginWnd.h, Source/UI/Window/UIMakeCharWnd.h, Source/UI/Window/UIMonsterDisplayWnd.h, Source/UI/Window/UIMonsterInfoWnd.h, Source/UI/Window/UINavigationHelpWnd.h, Source/UI/Window/UINavigationWnd.h, Source/UI/Window/UINewMakeCharWnd.h, Source/UI/Window/UINewSelectCharWnd.h, Source/UI/Window/UINoticeWnd.h, Source/UI/Window/UIPetInfoWnd.h, Source/UI/Window/UIRegisterMgr.h, Source/UI/Window/UIRoMapWnd.h, Source/UI/Window/UIRodexContentsWnd.h, Source/UI/Window/UISecondCostumeWnd.h, Source/UI/Window/UISeekPartyMBWnd.h, Source/UI/Window/UISeekPartyWnd.h, Source/UI/Window/UISelCharForUServerWnd.h, Source/UI/Window/UISerachStoreInfoWnd.h, Source/UI/Window/UITransMenuWnd.h, Source/UI/Window/UIWindow.h, Source/UI/Window/UIWindowMgr.h, Source/UI/Window/UIWindowMgr.inl, Source/Utility/Lexicon/LexiconSerializer.h.
2026-11-08 16:44:36 +00:00

219 lines
6.6 KiB
C++

#include "Client/Application/ErrorDialog.h"
#include "File/File.h"
#include "Render/RenderSystemBase.h"
#include "Render/Textures/Texture.h"
#include "Resource/Bitmap/BitmapResource.h"
#include "Resource/ResourceByteReader.h"
#include "Resource/Sprites/SpriteResource.h"
#include "Render/DeviceContext/DCSurface.h"
#include "Render/Textures/TextureCache.h"
#include "Resource/ResourcePreload.h"
#include "Resource/ResourceMgr.h"
#include <cstdlib>
#include <cstring>
#include <string>
// INLINED
CSprRes::CSprRes() : indexedCount(0) {
}
// OFFSET: 0x00760F50
// FUNCTION: fn_08060
CSprRes::~CSprRes() = default;
// OFFSET: 0x0075FE90
// FUNCTION: fn_08053
CSprRes* CSprRes::Create() {
return new CSprRes;
}
// OFFSET: 0x0075FF40
// FUNCTION: fn_08054
bool CSprRes::Load(const char* name) {
CFile file;
if (!file.Open(name, 0, true, false)) {
ShowErrorDialog(GetRenderSystemHolder()->system, (std::string("Spr :: Cannot find File : ") + std::string(name)).c_str(), 0);
return false;
}
struct Header {
std::uint16_t magic;
std::uint16_t version;
std::uint16_t indexed;
} header;
file.Read(&header, sizeof(header));
if (header.magic != 0x5053) {
ShowErrorDialog(GetRenderSystemHolder()->system, "Illegal File Format", 0);
ShowErrorDialog(GetRenderSystemHolder()->system, name, 0);
return false;
}
if (header.version > 0x0201) {
ShowErrorDialog(GetRenderSystemHolder()->system, "Unsupported Version. Content may be corrupted", 0);
return false;
}
this->indexedCount = header.indexed;
if (header.version >= 0x0101) {
unsigned char colors[1024];
file.Seek(-1024, FILE_END);
file.Read(colors, sizeof(colors));
file.Seek(sizeof(header), FILE_BEGIN);
ConvertSpritePalette(this->palette, colors, 256);
}
std::uint16_t trueColorCount;
if (header.version >= 0x0200) {
file.Read(&trueColorCount, sizeof(trueColorCount));
}
for (int index = 0; index < this->indexedCount; ++index) {
std::uint16_t dimensions[2];
file.Read(dimensions, sizeof(dimensions));
auto* image = new SpriteRleImage{};
image->surface = nullptr;
image->width = static_cast<std::int16_t>(dimensions[0]);
image->height = static_cast<std::int16_t>(dimensions[1]);
image->doubleWidth = 0;
image->doubleHeight = 0;
std::uint16_t encodedBytes;
if (g_spriteHalfWidth == 0 && g_spriteHalfHeight == 0) {
if (header.version >= 0x0201) {
file.Read(&encodedBytes, sizeof(encodedBytes));
auto* runs = new std::uint8_t[encodedBytes];
image->runs = runs;
file.Read(runs, encodedBytes);
} else {
const int count = image->width * image->height;
auto* pixels = new std::uint8_t[count];
file.Read(pixels, count);
image->runs = this->EncodeSpriteRuns(pixels, image->width, image->height, encodedBytes);
delete[] pixels;
}
} else {
std::uint8_t* pixels;
if (header.version >= 0x0201) {
file.Read(&encodedBytes, sizeof(encodedBytes));
auto* runs = new std::uint8_t[encodedBytes];
file.Read(runs, encodedBytes);
pixels = new std::uint8_t[dimensions[0] * dimensions[1]];
const std::uint8_t* current = runs;
std::uint16_t zeroCount = 0;
std::uint8_t value;
for (unsigned y = 0; y < dimensions[1]; ++y) {
for (unsigned x = 0; x < dimensions[0]; ++x) {
if (zeroCount == 0) {
value = *current++;
if (value == 0) {
zeroCount = *current++;
}
}
const std::uint16_t before = zeroCount;
zeroCount = zeroCount != 0 ? zeroCount - 1 : 0;
pixels[y * dimensions[0] + x] = before == 0 ? value : 0;
}
}
delete[] runs;
} else {
const int count = image->width * image->height;
pixels = new std::uint8_t[count];
file.Read(pixels, count);
}
auto* reduced = this->ReduceSprite(pixels, dimensions[0], dimensions[1], g_spriteHalfWidth, g_spriteHalfHeight);
delete[] pixels;
image->runs = this->EncodeSpriteRuns(reduced, dimensions[0] / (g_spriteHalfWidth + 1), dimensions[1] / (g_spriteHalfHeight + 1), encodedBytes);
delete[] reduced;
if (g_spriteHalfWidth != 0) {
image->width /= 2;
image->doubleWidth = 1;
}
if (g_spriteHalfHeight != 0) {
image->height /= 2;
image->doubleHeight = 1;
}
}
this->images[0].push_back(image);
}
if (header.version >= 0x0200) {
for (unsigned index = 0; index < trueColorCount; ++index) {
std::uint16_t dimensions[2];
file.Read(dimensions, sizeof(dimensions));
auto* image = new SpriteRleImage{};
image->width = static_cast<std::int16_t>(dimensions[0]);
image->height = static_cast<std::int16_t>(dimensions[1]);
auto* pixels = new std::uint32_t[image->width * image->height];
for (int y = image->height - 1; y >= 0; --y) {
for (int x = 0; x < image->width; ++x) {
std::uint8_t pixel[4];
file.Read(pixel, sizeof(pixel));
pixels[y * image->width + x] = pixel[1] | (pixel[2] << 8) | (pixel[3] << 16) | (static_cast<std::uint32_t>(pixel[0]) << 24);
}
}
const int width = g_spriteHalfWidth != 0 ? image->width / 2 : image->width;
const int height = g_spriteHalfHeight != 0 ? image->height / 2 : image->height;
CTexture* texture = CreateTexture(width, height, TextureFormat::A4R4G4B4, false, false);
image->surface = texture;
texture->Upload(0, 0, image->width, image->height, pixels, 0, 0);
delete[] pixels;
if (g_spriteHalfWidth != 0) {
image->width /= 2;
image->doubleWidth = 1;
}
if (g_spriteHalfHeight != 0) {
image->height /= 2;
image->doubleHeight = 1;
}
this->images[1].push_back(image);
}
}
file.Close();
return true;
}
// OFFSET: 0x00760B10
// FUNCTION: fn_08055
void CSprRes::Unload() {
for (int type = 0; type < 2; ++type) {
for (auto image = this->images[type].begin(); image != this->images[type].end(); ++image) {
if (type == 0) {
delete[] (*image)->runs;
} else if ((*image)->surface) {
delete static_cast<const CTexture*>((*image)->surface);
(*image)->surface = nullptr;
}
delete *image;
}
this->images[type].erase(this->images[type].begin(), this->images[type].end());
}
}
// INLINED
CSprRes::CSprRes(const char* extension, const char* prefix) {
ResourceMgr::Instance().Register(extension, prefix, this);
}
// GLOBAL: gl_25563
CSprRes g_sprPrototype("spr", "sprite\\");