From a47d20f8bed94c5c220091e5fb14b02b600153f8 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Sun, 25 Oct 2026 07:42:41 +0000 Subject: [PATCH] Reconstruct readable C++ and organize cohesive source subsystems Administrative source import: native x86 compilation passed for 423 authored units. Source placement and submission states are migrated separately; this commit does not imply peer acceptance. Previous head: 35d2a8cb3660525f49801e8695f00889016a5502 Payload SHA256: 592f016d2730c5593bb653aa054c1e5f76a6df72c8f5a09e66f74876e2e33dee --- .clang-format | 78 +- CMakeLists.txt | 757 ++-- CODING_RULES.md | 25 +- README.md | 2 +- Source/Archive/GPak.cpp | 56 +- Source/Archive/MemMapPakFile.cpp | 35 +- Source/Archive/MemMapPakFile.h | 1 - Source/Archive/PakCipher.cpp | 146 +- Source/Archive/PakCipher.h | 11 +- Source/Archive/PakFile.cpp | 22 +- Source/Archive/PakFile.h | 2 - Source/Archive/PakName.cpp | 6 +- Source/Archive/PakName.h | 2 - Source/Archive/PakRegistry.cpp | 3 + .../Application/ApplicationActivation.cpp | 19 + .../Application/ApplicationActivation.h | 17 + .../Application/ApplicationMessages.cpp | 46 + .../Client/Application/ApplicationMessages.h | 20 + .../Client/Application/ApplicationWindow.cpp | 24 + Source/Client/Application/ApplicationWindow.h | 13 + .../Client/{ => Application}/ErrorDialog.cpp | 3 +- Source/Client/Application/ErrorDialog.h | 10 + Source/Client/Application/Launcher.cpp | 40 + Source/Client/Application/Launcher.h | 11 + .../UnhandledExceptionHandler.cpp | 70 +- .../UnhandledExceptionHandler.h | 14 +- Source/Client/ApplicationActivation.cpp | 20 - Source/Client/ApplicationActivation.h | 23 - Source/Client/ApplicationMessages.cpp | 47 - Source/Client/ApplicationMessages.h | 26 - Source/Client/ApplicationWindow.cpp | 39 - Source/Client/ApplicationWindow.h | 29 - .../{ => Browser}/BrowserAddressBar.cpp | 21 +- Source/Client/Browser/BrowserAddressBar.h | 18 + .../{ => Browser}/BrowserAddressEdit.cpp | 5 +- Source/Client/Browser/BrowserAddressEdit.h | 13 + .../{ => Browser}/BrowserClientSite.cpp | 16 +- .../Client/{ => Browser}/BrowserClientSite.h | 17 +- Source/Client/{ => Browser}/BrowserClose.cpp | 4 +- Source/Client/Browser/BrowserClose.h | 21 + .../{ => Browser}/BrowserCommandTarget.cpp | 13 +- .../{ => Browser}/BrowserCommandTarget.h | 12 +- .../Client/{ => Browser}/BrowserCreation.cpp | 4 +- Source/Client/Browser/BrowserCreation.h | 18 + Source/Client/{ => Browser}/BrowserCursor.cpp | 9 +- Source/Client/Browser/BrowserCursor.h | 19 + .../{ => Browser}/BrowserDocumentUI.cpp | 19 +- .../Client/{ => Browser}/BrowserDocumentUI.h | 17 +- .../{UI => Client/Browser}/BrowserFactory.cpp | 9 +- .../{UI => Client/Browser}/BrowserFactory.h | 7 +- Source/Client/{ => Browser}/BrowserFrame.cpp | 7 +- Source/Client/Browser/BrowserFrame.h | 18 + .../{ => Browser}/BrowserHostWindow.cpp | 8 +- Source/Client/Browser/BrowserHostWindow.h | 15 + .../Client/{ => Browser}/BrowserInPlace.cpp | 14 +- Source/Client/{ => Browser}/BrowserInPlace.h | 20 +- .../{ => Browser}/BrowserInputHandoff.cpp | 14 +- Source/Client/Browser/BrowserInputHandoff.h | 21 + .../Client/{ => Browser}/BrowserInterface.cpp | 29 +- Source/Client/Browser/BrowserInterface.h | 19 + .../Client/{ => Browser}/BrowserMessages.cpp | 8 +- Source/Client/{ => Browser}/BrowserMessages.h | 8 +- .../Browser}/BrowserPopupDispatch.cpp | 25 +- .../Browser}/BrowserPopupDispatch.h | 21 +- .../Client/{ => Browser}/BrowserRegistry.cpp | 6 +- Source/Client/{ => Browser}/BrowserRegistry.h | 7 +- .../{ => Browser}/BrowserSiteAttachment.cpp | 8 +- Source/Client/Browser/BrowserSiteAttachment.h | 20 + .../{ => Browser}/BrowserWindowSizing.cpp | 3 +- .../{ => Browser}/BrowserWindowSizing.h | 11 +- Source/Client/{ => Browser}/WebBrowser.cpp | 67 +- Source/Client/{ => Browser}/WebBrowser.h | 17 +- .../Client/{ => Browser}/WebEventReceiver.cpp | 41 +- .../Client/{ => Browser}/WebEventReceiver.h | 21 +- Source/Client/BrowserAddressBar.h | 23 - Source/Client/BrowserAddressEdit.h | 16 - Source/Client/BrowserClose.h | 24 - Source/Client/BrowserCreation.h | 21 - Source/Client/BrowserCursor.h | 21 - Source/Client/BrowserFrame.h | 20 - Source/Client/BrowserHostWindow.h | 18 - Source/Client/BrowserInputHandoff.h | 25 - Source/Client/BrowserInterface.h | 30 - Source/Client/BrowserSiteAttachment.h | 23 - Source/Client/ClientOptions.cpp | 9 +- Source/Client/ClientOptions.h | 1 - Source/Client/ErrorDialog.h | 12 - Source/Client/{ => Input}/ImeInput.cpp | 19 +- Source/Client/{ => Input}/ImeInput.h | 13 +- Source/Client/{ => Input}/InputCharset.cpp | 4 +- Source/Client/{ => Input}/InputCharset.h | 6 +- Source/Client/{ => Input}/Mouse.cpp | 17 +- Source/Client/{ => Input}/Mouse.h | 10 +- Source/Client/{ => Input}/TextInputBuffer.cpp | 43 +- Source/Client/Input/TextInputBuffer.h | 57 + .../{ => Input}/TraditionalKeyInput.cpp | 19 +- .../Client/{ => Input}/TraditionalKeyInput.h | 7 +- Source/Client/Launcher.cpp | 46 - Source/Client/Launcher.h | 18 - Source/Client/{ => Mode}/ActiveGameMode.cpp | 2 +- Source/Client/{ => Mode}/ActiveGameMode.h | 6 +- Source/Client/{ => Mode}/ModeCursor.cpp | 7 +- Source/Client/{ => Mode}/ModeCursor.h | 5 +- Source/Client/{ => Mode}/ModeDragState.cpp | 35 +- Source/Client/{ => Mode}/ModeDragState.h | 25 +- Source/Client/Mode/ModeEvents.h | 14 + Source/Client/{ => Mode}/ModeTooltip.cpp | 34 +- Source/Client/{ => Mode}/ModeTooltip.h | 9 +- Source/Client/ModeEvents.h | 22 - Source/Client/ReplayPacketRecorder.cpp | 18 +- Source/Client/ReplayPacketRecorder.h | 27 +- Source/Client/TextInputBuffer.h | 73 - Source/Contents/AccountService.h | 17 - Source/Contents/AccountUserData.h | 9 - Source/Contents/{ => Actors}/AttackMotion.cpp | 2 +- Source/Contents/Actors/AttackMotion.h | 6 + Source/Contents/{ => Actors}/GameObject.cpp | 11 +- Source/Contents/{ => Actors}/GameObject.h | 24 +- Source/Contents/{ => Actors}/RenderObject.cpp | 13 +- Source/Contents/Actors/RenderObject.h | 25 + .../{ => Actors}/RenderObjectState.cpp | 11 +- .../Contents/{ => Actors}/RenderObjectState.h | 6 +- .../{ => Actors}/SpriteDrawingPolicy.cpp | 11 +- Source/Contents/Actors/SpriteDrawingPolicy.h | 21 + Source/Contents/{ => Async}/AsyncWorkMgr.cpp | 175 +- Source/Contents/Async/AsyncWorkMgr.h | 83 + .../AsyncWorkRecycleObjectPoolMgr.cpp | 42 +- .../AsyncWorkRecycleObjectPoolMgr.h | 7 +- Source/Contents/AsyncWorkMgr.h | 163 - Source/Contents/AttackMotion.h | 10 - Source/Contents/{ => Camera}/CameraFrame.cpp | 20 +- Source/Contents/{ => Camera}/CameraFrame.h | 23 +- .../Contents/{ => Camera}/CameraQueries.cpp | 21 +- Source/Contents/{ => Camera}/CameraShake.cpp | 20 +- .../Contents/{ => Camera}/CameraSmoothing.cpp | 18 +- Source/Contents/{ => Camera}/CameraState.h | 12 +- Source/Contents/CashEmotionMgr.cpp | 9 +- Source/Contents/CashEmotionMgr.h | 1 + Source/Contents/ClientSkills.h | 89 - .../GraphicsConfiguration.cpp | 11 +- .../GraphicsConfiguration.h | 10 +- .../{ => Configuration}/OptionWriter.cpp | 10 +- Source/Contents/Configuration/OptionWriter.h | 16 + .../{ => Configuration}/ScriptOptions.cpp | 2 +- .../{ => Configuration}/ScriptOptions.h | 6 +- .../{ => Configuration}/ServiceOptions.cpp | 2 +- .../{ => Configuration}/ServiceOptions.h | 9 +- Source/Contents/EffectParticle.h | 37 - Source/Contents/EffectPrimitiveColor.cpp | 82 - Source/Contents/EffectPrimitiveMotion.h | 26 - Source/Contents/EffectPrimitiveRendering.h | 37 - Source/Contents/EffectTypes.cpp | 428 -- Source/Contents/EffectTypes.h | 6 - .../Contents/{ => Effects}/AttachedEffect.cpp | 2 +- .../Contents/{ => Effects}/AttachedEffect.h | 8 +- Source/Contents/{ => Effects}/Effect.cpp | 6 +- Source/Contents/{ => Effects}/Effect.h | 8 +- Source/Contents/{ => Effects}/EffectActor.cpp | 6 +- Source/Contents/{ => Effects}/EffectActor.h | 9 +- .../{ => Effects}/EffectAttachments.cpp | 7 +- .../{ => Effects}/EffectAttachments.h | 6 +- Source/Contents/{ => Effects}/EffectLists.cpp | 7 +- Source/Contents/{ => Effects}/EffectLists.h | 10 +- .../Contents/{ => Effects}/EffectParticle.cpp | 17 +- Source/Contents/Effects/EffectParticle.h | 28 + .../Contents/Effects/EffectPrimitiveColor.cpp | 72 + .../{ => Effects}/EffectPrimitiveMotion.cpp | 104 +- .../Contents/Effects/EffectPrimitiveMotion.h | 20 + .../{ => Effects}/EffectPrimitiveRecords.cpp | 15 +- .../EffectPrimitiveRendering.cpp | 37 +- .../Effects/EffectPrimitiveRendering.h | 27 + .../{ => Effects}/EffectPrimitiveState.cpp | 14 +- .../{ => Effects}/EffectPrimitiveState.h | 52 +- Source/Contents/Effects/EffectTypes.cpp | 325 ++ Source/Contents/Effects/EffectTypes.h | 6 + .../{ => Effects}/EffectVisibility.cpp | 10 +- .../Contents/{ => Effects}/EffectVisibility.h | 7 +- Source/Contents/{ => Effects}/PartyEffect.cpp | 31 +- Source/Contents/Effects/PartyEffect.h | 20 + .../{ => Effects}/PartyMemberEffects.cpp | 19 +- .../{ => Effects}/PartyMemberEffects.h | 6 +- .../{ => Effects}/RagEffectInitialization.cpp | 20 +- .../Effects/RagEffectInitialization.h | 17 + .../RagEffectResourceSelection.cpp | 6 +- .../Contents/{ => Effects}/RagEffectState.cpp | 18 +- .../Contents/{ => Effects}/RagEffectState.h | 11 +- Source/Contents/EmblemDownload.h | 19 - Source/Contents/{ => Emblems}/EmblemCache.cpp | 15 +- Source/Contents/{ => Emblems}/EmblemCache.h | 14 +- .../EmblemDataDownloadAsyncWork.cpp | 29 +- .../EmblemDataDownloadAsyncWork.h | 17 +- .../Contents/{ => Emblems}/EmblemDataMgr.cpp | 29 +- Source/Contents/{ => Emblems}/EmblemDataMgr.h | 21 +- .../EmblemDataUploadAsyncWork.cpp | 23 +- .../{ => Emblems}/EmblemDataUploadAsyncWork.h | 17 +- .../Contents/{ => Emblems}/EmblemDownload.cpp | 16 +- Source/Contents/Emblems/EmblemDownload.h | 14 + .../Contents/{ => Emblems}/EmblemUpload.cpp | 19 +- Source/Contents/{ => Emblems}/EmblemUpload.h | 4 +- .../{ => Emblems}/GuildEmblemReqBundle.cpp | 16 +- .../{ => Emblems}/GuildEmblemReqBundle.h | 11 +- Source/Contents/ForbiddenWords.cpp | 28 +- Source/Contents/ForbiddenWords.h | 2 - Source/Contents/{ => Ground}/GroundDecals.cpp | 71 +- .../Contents/{ => Ground}/GroundGeometry.cpp | 81 +- Source/Contents/{ => Ground}/GroundGeometry.h | 69 +- .../Contents/{ => Ground}/GroundLighting.cpp | 39 +- .../GroundLightingInitialization.cpp | 23 +- .../Contents/{ => Ground}/GroundLightmaps.cpp | 18 +- .../Contents/{ => Ground}/GroundPicking.cpp | 23 +- .../Contents/{ => Ground}/GroundRendering.cpp | 19 +- .../Contents/{ => Ground}/GroundRendering.h | 4 +- .../Contents/{ => Ground}/GroundSamples.cpp | 50 +- .../Contents/{ => Ground}/GroundSpatial.cpp | 27 +- Source/Contents/{ => Ground}/GroundSpatial.h | 7 +- .../{ => Ground}/GroundWaterRendering.cpp | 36 +- .../{ => Ground}/GroundWaterState.cpp | 42 +- .../Contents/{ => Ground}/GroundWaterState.h | 8 +- .../{ => Ground}/TerrainCoordinates.cpp | 40 +- .../Contents/{ => Ground}/TerrainHeight.cpp | 23 +- Source/Contents/{ => Ground}/TerrainHeight.h | 9 +- Source/Contents/Ground/TerrainPicking.cpp | 38 + Source/Contents/Ground/TerrainPlane.cpp | 40 + .../Contents/{ => Hotkeys}/EmotionHotkeys.cpp | 23 +- .../Contents/{ => Hotkeys}/EmotionHotkeys.h | 6 +- Source/Contents/{ => Hotkeys}/HotkeyInfo.cpp | 5 +- Source/Contents/{ => Hotkeys}/HotkeyInfo.h | 6 +- .../Contents/{ => Hotkeys}/UserHotkeyMgr.cpp | 30 +- Source/Contents/{ => Hotkeys}/UserHotkeyMgr.h | 6 +- .../{ => Hotkeys}/UserHotkeyScript.cpp | 4 +- .../Contents/{ => Hotkeys}/UserHotkeyScript.h | 7 +- Source/Contents/InstantVar.h | 4 - .../Contents/{ => Items}/ItemDescription.cpp | 15 +- Source/Contents/{ => Items}/ItemDescription.h | 7 +- Source/Contents/{ => Items}/ItemInfo.cpp | 11 +- Source/Contents/{ => Items}/ItemInfo.h | 14 +- Source/Contents/{ => Items}/ItemLink.cpp | 19 +- Source/Contents/{ => Items}/ItemLink.h | 5 +- Source/Contents/{ => Items}/ItemNaming.cpp | 51 +- Source/Contents/{ => Items}/ItemNaming.h | 7 +- Source/Contents/{ => Items}/ItemResources.cpp | 7 +- Source/Contents/{ => Items}/ItemResources.h | 4 +- Source/Contents/JobInheritance.h | 21 - Source/Contents/{ => Jobs}/JobInheritance.cpp | 13 +- Source/Contents/Jobs/JobInheritance.h | 15 + .../{ => Jobs}/JobNameInitialization.cpp | 10 +- Source/Contents/{ => Jobs}/JobNames.cpp | 2 +- Source/Contents/{ => Jobs}/JobNames.h | 8 +- Source/Contents/MessageTable.cpp | 24 +- Source/Contents/MessageTable.h | 5 +- .../{ => Messenger}/ClientMessenger.cpp | 5 +- .../{ => Messenger}/ClientMessenger.h | 8 +- .../{ => Messenger}/MessengerMember.cpp | 8 +- .../{ => Messenger}/MessengerMember.h | 7 +- .../{ => Messenger}/WhisperBlockMgr.cpp | 8 +- .../{ => Messenger}/WhisperBlockMgr.h | 6 +- Source/Contents/ModelAnimation.h | 36 - Source/Contents/{ => Models}/ModelActor.cpp | 14 +- Source/Contents/{ => Models}/ModelActor.h | 10 +- .../{ => Models}/ModelActorBounds.cpp | 14 +- .../Contents/{ => Models}/ModelAnimation.cpp | 59 +- Source/Contents/Models/ModelAnimation.h | 18 + .../Contents/{ => Models}/ModelLighting.cpp | 39 +- Source/Contents/{ => Models}/ModelMovies.cpp | 4 +- Source/Contents/{ => Models}/ModelNode.cpp | 12 +- Source/Contents/{ => Models}/ModelNode.h | 36 +- .../Contents/{ => Models}/ModelNodeBounds.cpp | 14 +- .../Contents/{ => Models}/ModelOcclusion.cpp | 7 +- .../Contents/{ => Models}/ModelPlayback.cpp | 25 +- .../Contents/{ => Models}/ModelQuaternion.cpp | 16 +- .../Contents/{ => Models}/ModelRendering.cpp | 94 +- Source/Contents/{ => Models}/ModelRendering.h | 43 +- Source/Contents/{ => Models}/ModelSpatial.cpp | 32 +- Source/Contents/{ => Models}/ModelSpatial.h | 5 +- .../{ => Models}/ModelTextureAnimation.cpp | 18 +- .../Contents/{ => Models}/ModelTextureUV.cpp | 11 +- Source/Contents/{ => Movies}/BinkMovie.cpp | 13 +- Source/Contents/{ => Movies}/BinkMovie.h | 6 +- Source/Contents/{ => Movies}/BinkMovies.cpp | 17 +- Source/Contents/{ => Movies}/BinkMovies.h | 10 +- Source/Contents/NormalItemSlots.h | 41 - Source/Contents/OptionWriter.h | 18 - .../Contents/{ => Party}/AdvenPartyInfo.cpp | 5 +- Source/Contents/{ => Party}/AdvenPartyInfo.h | 5 +- .../{ => Party}/AdventurerAgencyMgr.cpp | 23 +- .../{ => Party}/AdventurerAgencyMgr.h | 26 +- .../{ => Party}/AgencyRequestContext.h | 6 +- .../Contents/{ => Party}/AgencyRequests.cpp | 72 +- .../ChangePartyMasterAsyncWork.cpp | 40 +- .../{ => Party}/ChangePartyMasterAsyncWork.h | 22 +- .../ChangePartyMasterCompletion.cpp | 14 +- .../{ => Party}/LoadMyPartyAsyncWork.cpp | 22 +- .../{ => Party}/LoadMyPartyAsyncWork.h | 19 +- .../{ => Party}/LoadPartyInfoAsyncWork.cpp | 22 +- .../{ => Party}/LoadPartyInfoAsyncWork.h | 17 +- .../{ => Party}/LoadPartyListAsyncWork.cpp | 25 +- .../{ => Party}/LoadPartyListAsyncWork.h | 21 +- .../{ => Party}/MyPartyCompletion.cpp | 15 +- .../{ => Party}/PartyInfoCompletion.cpp | 28 +- .../Contents/{ => Party}/PartyInvitation.cpp | 6 +- Source/Contents/{ => Party}/PartyInvitation.h | 4 +- .../Contents/{ => Party}/PartyJoinResult.cpp | 14 +- Source/Contents/{ => Party}/PartyJoinResult.h | 4 +- .../{ => Party}/PartyListCompletion.cpp | 14 +- .../PartyRegistrationCompletion.cpp | 14 +- .../{ => Party}/RegisterPartyAsyncWork.cpp | 22 +- .../{ => Party}/RegisterPartyAsyncWork.h | 20 +- .../{ => Party}/StopRecruitingAsyncWork.cpp | 22 +- .../{ => Party}/StopRecruitingAsyncWork.h | 20 +- .../{ => Party}/StopRecruitingCompletion.cpp | 16 +- Source/Contents/PartyEffect.h | 27 - Source/Contents/PlayerNameDictionary.cpp | 21 +- Source/Contents/PlayerNameDictionary.h | 2 - Source/Contents/RagEffectInitialization.h | 29 - Source/Contents/RenderObject.h | 46 - Source/Contents/ShowRankingScheduler.cpp | 1 + Source/Contents/SkillLevelConfig.h | 12 - Source/Contents/SkillTreeScript.h | 15 - .../Contents/{ => Skills}/AutomaticSkills.cpp | 12 +- .../Contents/{ => Skills}/AutomaticSkills.h | 7 +- Source/Contents/{ => Skills}/ClientSkills.cpp | 40 +- Source/Contents/Skills/ClientSkills.h | 68 + .../{ => Skills}/PlayerSkillBundle.cpp | 42 +- .../Contents/{ => Skills}/PlayerSkillBundle.h | 8 +- Source/Contents/{ => Skills}/SkillInfo.cpp | 28 +- Source/Contents/{ => Skills}/SkillInfo.h | 8 +- .../{ => Skills}/SkillLevelConfig.cpp | 5 +- Source/Contents/Skills/SkillLevelConfig.h | 9 + .../{ => Skills}/SkillLevelRegistry.cpp | 9 +- .../{ => Skills}/SkillLevelRegistry.h | 4 +- .../Contents/{ => Skills}/SkillTreeScript.cpp | 5 +- Source/Contents/Skills/SkillTreeScript.h | 9 + Source/Contents/SkinInfo.cpp | 3 +- Source/Contents/SkinInfo.h | 2 - .../{ => Sound}/SoundConfiguration.cpp | 11 +- .../Contents/{ => Sound}/SoundConfiguration.h | 6 +- Source/Contents/{ => Sound}/SoundMgr.cpp | 80 +- Source/Contents/{ => Sound}/SoundMgr.h | 48 +- Source/Contents/SpriteDrawingPolicy.h | 26 - .../{ => Store}/MCStoreInfoBackup.cpp | 82 +- .../Contents/{ => Store}/MCStoreInfoBackup.h | 32 +- .../MCStoreInfoBackupAsyncWork.cpp | 51 +- .../{ => Store}/MCStoreInfoBackupAsyncWork.h | 31 +- .../Contents/{ => Store}/StoreBackupData.cpp | 17 +- Source/Contents/Store/StoreBackupData.h | 21 + Source/Contents/StoreBackupData.h | 23 - Source/Contents/TerrainPicking.cpp | 41 - Source/Contents/TerrainPlane.cpp | 40 - Source/Contents/TipBoxTitles.cpp | 2 - Source/Contents/TipBoxTitles.h | 2 - .../{ => UserData}/AccountConfigLoad.h | 5 +- .../AccountLinkedUserDataLoadAsyncWork.cpp | 27 +- .../AccountLinkedUserDataLoadAsyncWork.h | 10 +- .../AccountLinkedUserDataMgr.cpp | 76 +- .../{ => UserData}/AccountLinkedUserDataMgr.h | 23 +- .../AccountLinkedUserDataSaveAsyncWork.cpp | 21 +- .../AccountLinkedUserDataSaveAsyncWork.h | 9 +- .../{ => UserData}/AccountService.cpp | 17 +- Source/Contents/UserData/AccountService.h | 10 + .../{ => UserData}/AccountUserData.cpp | 5 +- Source/Contents/UserData/AccountUserData.h | 8 + .../{ => UserData}/CharacterConfigLoad.cpp | 35 +- .../{ => UserData}/CharacterConfigLoad.h | 4 +- .../{ => UserData}/CharacterConfigSave.cpp | 21 +- .../{ => UserData}/CharacterConfigSave.h | 7 +- .../CharacterLinkedUserDataLoadAsyncWork.cpp | 19 +- .../CharacterLinkedUserDataLoadAsyncWork.h | 19 +- .../CharacterLinkedUserDataMgr.cpp | 21 +- .../CharacterLinkedUserDataMgr.h | 18 +- .../CharacterLinkedUserDataSaveAsyncWork.cpp | 21 +- .../CharacterLinkedUserDataSaveAsyncWork.h | 17 +- .../{ => UserData}/NormalItemSlots.cpp | 23 +- Source/Contents/UserData/NormalItemSlots.h | 33 + Source/Contents/{ => World}/WorldActors.cpp | 7 +- Source/Contents/World/WorldActors.h | 19 + .../Contents/{ => World}/WorldEnvironment.cpp | 12 +- Source/Contents/World/WorldEnvironment.h | 19 + .../{ => World}/WorldGroundImport.cpp | 35 +- Source/Contents/World/WorldGroundImport.h | 16 + .../{ => World}/WorldModelLoading.cpp | 25 +- .../Contents/{ => World}/WorldModelLoading.h | 7 +- .../{ => World}/WorldModelPlacement.cpp | 16 +- Source/Contents/World/WorldModelPlacement.h | 12 + .../Contents/{ => World}/WorldModelView.cpp | 66 +- Source/Contents/World/WorldModelView.h | 39 + Source/Contents/{ => World}/WorldObjects.cpp | 6 +- Source/Contents/World/WorldObjects.h | 15 + .../Contents/{ => World}/WorldOcclusion.cpp | 43 +- Source/Contents/World/WorldOcclusion.h | 15 + .../Contents/{ => World}/WorldProximity.cpp | 12 +- Source/Contents/World/WorldProximity.h | 14 + Source/Contents/{ => World}/WorldRayQuery.cpp | 21 +- Source/Contents/{ => World}/WorldRayQuery.h | 5 +- .../WorldSpatialInitialization.cpp | 31 +- .../World/WorldSpatialInitialization.h | 17 + .../Contents/{ => World}/WorldSpatialTree.cpp | 19 +- .../Contents/{ => World}/WorldSpatialTree.h | 5 +- .../{ => World}/WorldTerrainPicking.cpp | 26 +- Source/Contents/World/WorldTerrainPicking.h | 13 + .../Contents/{ => World}/WorldViewSpatial.cpp | 4 +- Source/Contents/WorldActors.h | 25 - Source/Contents/WorldEnvironment.h | 27 - Source/Contents/WorldGroundImport.h | 27 - Source/Contents/WorldModelPlacement.h | 20 - Source/Contents/WorldModelView.h | 54 - Source/Contents/WorldObjects.h | 17 - Source/Contents/WorldOcclusion.h | 35 - Source/Contents/WorldProximity.h | 22 - Source/Contents/WorldSpatialInitialization.h | 26 - Source/Contents/WorldTerrainPicking.h | 22 - Source/File/CommonObject.cpp | 8 +- Source/File/CommonObject.h | 2 - Source/File/File.cpp | 12 +- Source/File/File.h | 13 +- Source/File/MapName.h | 5 - Source/File/ResourcePath.cpp | 6 +- Source/File/ResourcePath.h | 5 - Source/File/ShortcutFilename.cpp | 3 + Source/File/ShortcutFilename.h | 1 - .../Network/{ => Connection}/Connection.cpp | 63 +- Source/Network/{ => Connection}/Connection.h | 15 +- .../{ => Connection}/ConnectionBuffer.cpp | 28 +- .../{ => Connection}/ConnectionBuffer.h | 7 +- .../{ => Connection}/ConnectionRuntime.cpp | 9 +- .../{ => Connection}/ConnectionRuntime.h | 5 +- Source/Network/{ => Http}/CURLMgr.cpp | 9 +- Source/Network/{ => Http}/CURLMgr.h | 5 +- Source/Network/{ => Http}/CURLPostHander.cpp | 15 +- Source/Network/{ => Http}/CURLPostHander.h | 7 +- .../Network/{ => Packets}/PacketLengths.cpp | 9 +- Source/Network/{ => Packets}/PacketLengths.h | 5 +- .../{ => Packets}/PacketRegistrations.inc | 3488 ++++++++--------- .../Network/{ => Packets}/PartyJoinPacket.cpp | 30 +- Source/Network/Packets/PartyJoinPacket.h | 18 + .../{ => Packets}/PartyJoinRequest.cpp | 7 +- .../Network/{ => Packets}/ShortcutPacket.cpp | 18 +- Source/Network/Packets/ShortcutPacket.h | 13 + .../{ => Packets}/SkillUpdatePacket.cpp | 22 +- Source/Network/Packets/SkillUpdatePacket.h | 45 + Source/Network/PartyJoinPacket.h | 34 - Source/Network/ShortcutPacket.h | 19 - Source/Network/SkillUpdatePacket.h | 59 - Source/Network/TextEncoding.cpp | 20 +- Source/Network/TextEncoding.h | 3 - Source/Render/AlphaRectangle.h | 26 - Source/Render/BitmapPixels.h | 126 - Source/Render/BlendColor.cpp | 1 + Source/Render/ClientTextureSources.h | 34 - Source/Render/D3DX9Runtime.cpp | 32 - Source/Render/DCBitmap.h | 118 - Source/Render/{ => DX7}/BackBufferDX7.cpp | 3 +- .../{ => DX7}/DeviceCapabilitiesDX7.cpp | 27 +- Source/Render/{ => DX7}/DeviceOwnerDX7.cpp | 130 +- Source/Render/{ => DX7}/DeviceOwnerDX7.h | 35 +- .../{ => DX7}/DirectDrawEnumeration.cpp | 23 +- .../Render/{ => DX7}/DirectDrawEnumeration.h | 6 +- Source/Render/{ => DX7}/DisplayModeDX7.cpp | 5 +- Source/Render/{ => DX7}/RenderAdapterDX7.cpp | 2 +- Source/Render/{ => DX7}/RenderSystemDX7.cpp | 40 +- Source/Render/{ => DX7}/RenderSystemDX7.h | 12 +- .../Render/{ => DX7}/RenderToTextureDX7.cpp | 36 +- .../{ => DX7}/RendererDX7Operations.cpp | 22 +- .../Render/{ => DX7}/RendererDX7Operations.h | 25 +- Source/Render/{ => DX7}/RendererFogDX7.cpp | 19 +- Source/Render/{ => DX7}/RendererFogDX7.h | 12 +- .../{ => DX7}/RendererPresentationDX7.cpp | 12 +- .../{ => DX7}/RendererPresentationDX7.h | 6 +- Source/Render/{ => DX7}/ScreenshotDX7.cpp | 63 +- Source/Render/{ => DX7}/SurfaceDX7.cpp | 58 +- Source/Render/{ => DX7}/SurfaceDX7.h | 8 +- .../Render/{ => DX7}/TextureAllocationDX7.cpp | 2 +- .../Render/{ => DX7}/TextureAllocationDX7.h | 5 +- Source/Render/{ => DX7}/TextureBindingDX7.cpp | 4 +- Source/Render/{ => DX7}/TextureBindingDX7.h | 6 +- .../{ => DX7}/TextureCalibrationDX7.cpp | 36 +- Source/Render/{ => DX7}/TextureDX7.cpp | 186 +- Source/Render/{ => DX7}/TextureDX7.h | 27 +- Source/Render/{ => DX7}/TextureModesDX7.cpp | 2 +- Source/Render/{ => DX9}/AlphaQueuesDX9.cpp | 15 +- Source/Render/{ => DX9}/BackBufferDX9.cpp | 13 +- Source/Render/DX9/D3DX9Runtime.cpp | 25 + Source/Render/{ => DX9}/D3DX9Runtime.h | 26 +- Source/Render/{ => DX9}/DeviceOwnerDX9.cpp | 40 +- Source/Render/{ => DX9}/DeviceOwnerDX9.h | 26 +- Source/Render/{ => DX9}/DeviceRecoveryDX9.cpp | 8 +- Source/Render/{ => DX9}/DeviceStateDX9.cpp | 34 +- Source/Render/{ => DX9}/DeviceStateDX9.h | 5 +- Source/Render/{ => DX9}/GroundQueuesDX9.cpp | 34 +- Source/Render/{ => DX9}/OpaqueQueuesDX9.cpp | 16 +- Source/Render/{ => DX9}/QueuedDrawingDX9.cpp | 64 +- Source/Render/{ => DX9}/RenderSystemDX9.cpp | 50 +- Source/Render/{ => DX9}/RenderSystemDX9.h | 20 +- .../Render/{ => DX9}/RendererBackBuffer.cpp | 4 +- Source/Render/{ => DX9}/RendererDX9.cpp | 52 +- Source/Render/{ => DX9}/RendererDX9.h | 16 +- .../{ => DX9}/RendererDX9Operations.cpp | 91 +- .../Render/{ => DX9}/RendererDX9Operations.h | 22 +- Source/Render/{ => DX9}/RendererFogDX9.cpp | 15 +- Source/Render/DX9/RendererFogDX9.h | 23 + Source/Render/DX9/RendererFrameDX9.cpp | 34 + Source/Render/{ => DX9}/RendererFrameDX9.h | 13 +- .../Render/{ => DX9}/RendererPresentation.cpp | 8 +- .../Render/{ => DX9}/RendererPresentation.h | 6 +- Source/Render/{ => DX9}/ScreenshotDX9.cpp | 26 +- Source/Render/{ => DX9}/SurfaceDX9.cpp | 46 +- Source/Render/{ => DX9}/SurfaceDX9.h | 8 +- Source/Render/{ => DX9}/TextureDX9.cpp | 207 +- Source/Render/{ => DX9}/TextureDX9.h | 36 +- Source/Render/{ => DX9}/TextureModesDX9.cpp | 4 +- Source/Render/DepthAlpha.cpp | 55 - Source/Render/DeviceContext.h | 114 - .../Render/{ => DeviceContext}/DCBitmap.cpp | 99 +- Source/Render/DeviceContext/DCBitmap.h | 57 + .../Render/{ => DeviceContext}/DCSurface.cpp | 71 +- Source/Render/{ => DeviceContext}/DCSurface.h | 87 +- .../{ => DeviceContext}/DeviceContext.cpp | 2 +- Source/Render/DeviceContext/DeviceContext.h | 51 + Source/Render/Direct3DErrors.cpp | 92 +- Source/Render/DisplayMode.cpp | 12 +- Source/Render/FogConfiguration.h | 2 - Source/Render/Primitives/AlphaRectangle.h | 15 + Source/Render/Primitives/DepthAlpha.cpp | 43 + Source/Render/{ => Primitives}/DepthAlpha.h | 4 +- .../{ => Primitives}/LightmappedPrimitive.cpp | 21 +- .../{ => Primitives}/LightmappedPrimitive.h | 12 +- .../{ => Primitives}/RenderCommandPool.cpp | 3 +- .../{ => Primitives}/RenderCommandPool.h | 7 +- .../{ => Primitives}/RenderPrimitive.cpp | 18 +- .../Render/{ => Primitives}/RenderPrimitive.h | 9 +- .../{ => Primitives}/RenderPrimitivePool.cpp | 5 +- .../{ => Primitives}/RenderPrimitivePool.h | 8 +- .../Render/{ => Primitives}/RenderQueues.cpp | 24 +- Source/Render/{ => Primitives}/RenderQueues.h | 19 +- .../{ => Primitives}/RenderVertexPool.cpp | 5 +- .../{ => Primitives}/RenderVertexPool.h | 8 +- Source/Render/{ => Primitives}/UIRPData.cpp | 29 +- Source/Render/Primitives/UIRPData.h | 26 + .../{ => Projection}/RenderProjection.cpp | 15 +- .../{ => Projection}/RenderProjection.h | 6 +- Source/Render/{ => Projection}/RenderRay.cpp | 5 +- .../{ => Projection}/RendererViewport.cpp | 13 +- Source/Render/Projection/RendererViewport.h | 27 + Source/Render/RenderAdapter.cpp | 20 +- Source/Render/RenderAdapter.h | 93 +- Source/Render/RenderBackends.cpp | 5 +- Source/Render/RenderBackends.h | 3 - Source/Render/RenderSystemBase.h | 5 +- Source/Render/Renderer.cpp | 3 +- Source/Render/Renderer.h | 21 +- Source/Render/RendererBackBuffer.h | 2 - Source/Render/RendererFogDX9.h | 30 - Source/Render/RendererFrameDX9.cpp | 39 - Source/Render/RendererViewport.h | 30 - Source/Render/{ => Text}/FontCache.cpp | 50 +- Source/Render/{ => Text}/FontCache.h | 10 +- Source/Render/{ => Text}/TextContext.cpp | 114 +- Source/Render/{ => Text}/TextContext.h | 5 +- Source/Render/TextureStageModes.cpp | 144 +- Source/Render/TextureStageModes.h | 2 - Source/Render/{ => Textures}/BitmapPixels.cpp | 316 +- Source/Render/Textures/BitmapPixels.h | 62 + .../{ => Textures}/BitmapTextureCache.cpp | 38 +- .../{ => Textures}/BitmapTextureCache.h | 5 +- .../{ => Textures}/ClientTextureSources.cpp | 11 +- Source/Render/Textures/ClientTextureSources.h | 26 + Source/Render/{ => Textures}/SpriteAtlas.cpp | 51 +- Source/Render/{ => Textures}/SpriteAtlas.h | 15 +- Source/Render/{ => Textures}/SpritePixels.h | 6 +- Source/Render/{ => Textures}/Surface.cpp | 2 +- Source/Render/{ => Textures}/Surface.h | 8 +- Source/Render/{ => Textures}/Texture.cpp | 51 +- Source/Render/{ => Textures}/Texture.h | 52 +- Source/Render/{ => Textures}/TextureCache.cpp | 42 +- Source/Render/{ => Textures}/TextureCache.h | 30 +- Source/Render/UIRPData.h | 37 - Source/Resource/Audio/MilesRuntime.cpp | 82 + Source/Resource/{ => Audio}/MilesRuntime.h | 9 +- Source/Resource/{ => Audio}/WaveResource.cpp | 14 +- Source/Resource/{ => Audio}/WaveResource.h | 10 +- Source/Resource/BinkRuntime.cpp | 9 +- Source/Resource/BinkRuntime.h | 3 - Source/Resource/{ => Bitmap}/BitmapImage.cpp | 47 +- Source/Resource/{ => Bitmap}/BitmapImage.h | 7 +- .../Resource/{ => Bitmap}/BitmapImageJpeg.cpp | 17 +- .../Resource/{ => Bitmap}/BitmapImagePng.cpp | 21 +- .../Resource/{ => Bitmap}/BitmapResource.cpp | 13 +- Source/Resource/{ => Bitmap}/BitmapResource.h | 9 +- Source/Resource/{ => Bitmap}/IJL15Runtime.cpp | 9 +- Source/Resource/{ => Bitmap}/IJL15Runtime.h | 9 +- Source/Resource/EZeffectResource.cpp | 9 +- Source/Resource/EZeffectResource.h | 6 - Source/Resource/MilesRuntime.cpp | 134 - .../{ => Models}/AnimatedModelResource.cpp | 18 +- .../{ => Models}/AnimatedModelResource.h | 8 +- Source/Resource/{ => Models}/ModelMesh.cpp | 5 +- Source/Resource/{ => Models}/ModelMesh.h | 16 +- .../{ => Models}/ModelNodeLoading.cpp | 12 +- .../{ => Models}/ModelNodeLoadingV2.cpp | 18 +- .../Resource/{ => Models}/ModelResource.cpp | 23 +- Source/Resource/{ => Models}/ModelResource.h | 21 +- .../Resource/{ => Models}/ModelResourceV2.cpp | 17 +- Source/Resource/Resource.cpp | 14 +- Source/Resource/Resource.h | 4 - Source/Resource/ResourceAliases.cpp | 4 +- Source/Resource/ResourceAliases.h | 2 - Source/Resource/ResourceByteReader.h | 3 - Source/Resource/ResourceFailures.cpp | 4 +- Source/Resource/ResourceFailures.h | 2 - Source/Resource/ResourceMgr.cpp | 37 +- Source/Resource/ResourceMgr.h | 2 - Source/Resource/ResourceTransient.cpp | 1 + .../Resource/{ => Sprites}/ActionResource.cpp | 27 +- .../Resource/{ => Sprites}/ActionResource.h | 11 +- .../Resource/{ => Sprites}/SpriteEncoding.cpp | 6 +- .../Resource/{ => Sprites}/SpriteResource.cpp | 24 +- .../Resource/{ => Sprites}/SpriteResource.h | 10 +- Source/Resource/TextureNames.cpp | 8 +- .../Resource/{ => World}/GroundResource.cpp | 27 +- Source/Resource/{ => World}/GroundResource.h | 27 +- .../Resource/{ => World}/TerrainResource.cpp | 11 +- Source/Resource/{ => World}/TerrainResource.h | 9 +- .../Resource/{ => World}/WorldEnvironment.cpp | 7 +- Source/Resource/{ => World}/WorldObjects.cpp | 5 +- Source/Resource/{ => World}/WorldResource.cpp | 19 +- Source/Resource/{ => World}/WorldResource.h | 9 +- Source/Script/LuaInstance.cpp | 17 +- Source/Script/LuaScript.cpp | 28 +- Source/Script/LuaScript.h | 2 - .../{ => Acceptance}/UIChooseSellBuyWnd.cpp | 35 +- .../{ => Acceptance}/UIExchangeAcceptWnd.cpp | 39 +- .../{ => Acceptance}/UIJoinPartyAcceptWnd.cpp | 29 +- .../{ => Acceptance}/UIJoinPartyAcceptWnd.h | 40 +- Source/UI/{ => Buttons}/UIBasicButton.cpp | 41 +- Source/UI/{ => Buttons}/UIBasicButton.h | 7 +- Source/UI/{ => Buttons}/UIBitmapButton.cpp | 13 +- Source/UI/{ => Buttons}/UIBitmapButton.h | 7 +- Source/UI/{ => Buttons}/UIBmpTextButton.cpp | 44 +- Source/UI/{ => Buttons}/UIBmpTextButton.h | 7 +- Source/UI/{ => Buttons}/UIButton.cpp | 60 +- Source/UI/{ => Buttons}/UIButton.h | 17 +- Source/UI/{ => Buttons}/UICheckBox.cpp | 60 +- Source/UI/{ => Buttons}/UICheckBox.h | 8 +- Source/UI/{ => Buttons}/UIJobSlotButton.cpp | 5 +- Source/UI/{ => Buttons}/UIJobSlotButton.h | 8 +- Source/UI/{ => Buttons}/UINaviLinkButton.cpp | 11 +- Source/UI/{ => Buttons}/UINaviLinkButton.h | 6 +- Source/UI/{ => Buttons}/UITextButton.cpp | 39 +- Source/UI/{ => Buttons}/UITextButton.h | 16 +- Source/UI/{ => Chat}/ChatNotifications.cpp | 19 +- Source/UI/{ => Chat}/ChatNotifications.h | 7 +- Source/UI/{ => Chat}/ChatSuggestions.cpp | 24 +- Source/UI/Chat/ChatSuggestions.h | 74 + Source/UI/ChatSuggestions.h | 91 - Source/UI/ColoredText.h | 56 - Source/UI/CooldownDrawing.h | 39 - Source/UI/{ => Cooldowns}/CooldownDrawing.cpp | 75 +- Source/UI/Cooldowns/CooldownDrawing.h | 27 + Source/UI/{ => Cooldowns}/CooldownOwner.cpp | 4 +- Source/UI/{ => Cooldowns}/CooldownOwner.h | 9 +- Source/UI/{ => Cooldowns}/CooldownState.cpp | 33 +- Source/UI/{ => Cooldowns}/CooldownState.h | 19 +- Source/UI/{ => Edit}/EditPainting.cpp | 66 +- Source/UI/{ => Edit}/EditPainting.h | 11 +- Source/UI/{ => Edit}/EditTextState.cpp | 4 +- Source/UI/Edit/EditTextState.h | 24 + Source/UI/Edit/EditViewport.cpp | 67 + Source/UI/{ => Edit}/EditViewport.h | 4 +- Source/UI/{ => Edit}/ItemTagRetirement.cpp | 6 +- Source/UI/{ => Edit}/ItemTagRetirement.h | 9 +- Source/UI/{ => Edit}/UIEditCtrl.cpp | 80 +- Source/UI/{ => Edit}/UIEditCtrl.h | 55 +- Source/UI/{ => Edit}/UIEditLinks.cpp | 57 +- Source/UI/{ => Edit}/UIEditVariants.cpp | 27 +- Source/UI/EditTextState.h | 26 - Source/UI/EditViewport.cpp | 79 - Source/UI/InputFocus.h | 20 - Source/UI/ItemDrawing.cpp | 63 - Source/UI/ItemDrawing.h | 33 - Source/UI/{ => Layout}/SnapMgr.cpp | 72 +- Source/UI/{ => Layout}/SnapMgr.h | 6 +- Source/UI/{ => Layout}/SnapObject.cpp | 38 +- Source/UI/{ => Layout}/SnapObject.h | 5 +- Source/UI/{ => Layout}/SnapRectangle.cpp | 33 +- Source/UI/{ => Layout}/SnapRectangle.h | 6 +- Source/UI/{ => Layout}/WindowCoordinates.cpp | 32 +- Source/UI/Layout/WindowCoordinates.h | 12 + Source/UI/{ => Layout}/WindowGeometry.cpp | 17 +- Source/UI/{ => Layout}/WindowGeometry.h | 6 +- Source/UI/{ => Layout}/WindowSnapping.cpp | 18 +- Source/UI/{ => Layout}/WindowSnapping.h | 8 +- Source/UI/{ => Lists}/UIComboBoxDefWnd.cpp | 79 +- Source/UI/{ => Lists}/UIComboBoxDefWnd.h | 19 +- Source/UI/{ => Lists}/UIComboBoxEx.cpp | 116 +- Source/UI/{ => Lists}/UIComboBoxEx.h | 19 +- Source/UI/{ => Lists}/UIDropDownBox.cpp | 12 +- Source/UI/{ => Lists}/UIDropDownBox.h | 10 +- Source/UI/{ => Lists}/UIListBox.cpp | 120 +- Source/UI/{ => Lists}/UIListBox.h | 25 +- Source/UI/{ => Lists}/UIListBoxEx.cpp | 107 +- Source/UI/{ => Lists}/UIListBoxEx.h | 25 +- Source/UI/{ => Lists}/UIScrollBar.cpp | 92 +- Source/UI/{ => Lists}/UIScrollBar.h | 10 +- Source/UI/{ => Lists}/UIScrollBarNavi.cpp | 38 +- Source/UI/{ => Lists}/UIScrollBarNavi.h | 7 +- Source/UI/NormalItemSlotLoad.h | 18 - .../UI/{ => Party}/UIAdvenPartyBoardWnd.cpp | 116 +- Source/UI/{ => Party}/UIAdvenPartyBoardWnd.h | 20 +- Source/UI/{ => Party}/UIApplyForPartyWnd.cpp | 69 +- Source/UI/{ => Party}/UIApplyForPartyWnd.h | 18 +- Source/UI/{ => Party}/UIPartyInfoWnd.cpp | 20 +- Source/UI/{ => Party}/UIPartyInfoWnd.h | 10 +- Source/UI/{ => Party}/UIRegisterPartyWnd.cpp | 87 +- Source/UI/{ => Party}/UIRegisterPartyWnd.h | 18 +- .../UI/{ => Party}/UIRequestJoinPartyMgr.cpp | 18 +- Source/UI/{ => Party}/UIRequestJoinPartyMgr.h | 6 +- .../UI/{ => Party}/UIRequestJoinPartyWnd.cpp | 64 +- Source/UI/{ => Party}/UIRequestJoinPartyWnd.h | 16 +- Source/UI/PixelTextWrapping.h | 21 - Source/UI/Shop/ItemDrawing.cpp | 45 + Source/UI/Shop/ItemDrawing.h | 17 + Source/UI/{ => Shop}/MerchantShopRefresh.cpp | 34 +- Source/UI/{ => Shop}/MerchantShopRefresh.h | 6 +- Source/UI/{ => Shop}/PriceColor.cpp | 2 +- Source/UI/{ => Shop}/PriceColor.h | 4 +- Source/UI/ShortcutActivation.cpp | 39 - Source/UI/ShortcutActivation.h | 23 - Source/UI/ShortcutBindings.h | 37 - Source/UI/ShortcutControls.h | 29 - Source/UI/ShortcutCooldowns.h | 84 - Source/UI/ShortcutDetails.h | 34 - Source/UI/ShortcutGrid.h | 17 - Source/UI/ShortcutPainting.h | 42 - Source/UI/ShortcutPress.h | 36 - Source/UI/ShortcutTooltip.h | 35 - .../UI/{ => Shortcuts}/NormalItemSlotLoad.cpp | 15 +- Source/UI/Shortcuts/NormalItemSlotLoad.h | 13 + Source/UI/Shortcuts/ShortcutActivation.cpp | 31 + Source/UI/Shortcuts/ShortcutActivation.h | 16 + .../UI/{ => Shortcuts}/ShortcutBindings.cpp | 93 +- Source/UI/Shortcuts/ShortcutBindings.h | 28 + .../{ => Shortcuts}/ShortcutControlEvents.cpp | 16 +- .../{ => Shortcuts}/ShortcutControlEvents.h | 8 +- .../UI/{ => Shortcuts}/ShortcutControls.cpp | 46 +- Source/UI/Shortcuts/ShortcutControls.h | 22 + .../UI/{ => Shortcuts}/ShortcutCooldowns.cpp | 101 +- Source/UI/Shortcuts/ShortcutCooldowns.h | 57 + Source/UI/{ => Shortcuts}/ShortcutDetails.cpp | 52 +- Source/UI/Shortcuts/ShortcutDetails.h | 27 + Source/UI/{ => Shortcuts}/ShortcutDrop.cpp | 58 +- Source/UI/{ => Shortcuts}/ShortcutDrop.h | 10 +- Source/UI/{ => Shortcuts}/ShortcutGrid.cpp | 11 +- Source/UI/Shortcuts/ShortcutGrid.h | 15 + Source/UI/{ => Shortcuts}/ShortcutLayout.cpp | 48 +- Source/UI/{ => Shortcuts}/ShortcutLayout.h | 10 +- .../UI/{ => Shortcuts}/ShortcutPainting.cpp | 113 +- Source/UI/Shortcuts/ShortcutPainting.h | 35 + Source/UI/{ => Shortcuts}/ShortcutPress.cpp | 35 +- Source/UI/Shortcuts/ShortcutPress.h | 29 + Source/UI/{ => Shortcuts}/ShortcutTooltip.cpp | 66 +- Source/UI/Shortcuts/ShortcutTooltip.h | 28 + Source/UI/{ => Shortcuts}/ShortcutUse.cpp | 17 +- Source/UI/{ => Shortcuts}/ShortcutUse.h | 12 +- .../UI/{ => Shortcuts}/ShortcutVisibility.cpp | 8 +- .../UI/{ => Shortcuts}/ShortcutVisibility.h | 5 +- .../UI/{ => Shortcuts}/SkillDetailClose.cpp | 12 +- Source/UI/{ => Shortcuts}/SkillDetailClose.h | 5 +- Source/UI/{ => Shortcuts}/UIShortCutWnd.cpp | 79 +- Source/UI/{ => Shortcuts}/UIShortCutWnd.h | 20 +- Source/UI/{ => Text}/ColoredText.cpp | 81 +- Source/UI/Text/ColoredText.h | 24 + Source/UI/{ => Text}/ItemLinkDisplay.cpp | 14 +- Source/UI/{ => Text}/ItemLinkDisplay.h | 4 +- Source/UI/{ => Text}/NavigationLink.cpp | 6 +- Source/UI/{ => Text}/NavigationLink.h | 4 +- Source/UI/{ => Text}/PixelTextWrapping.cpp | 38 +- Source/UI/Text/PixelTextWrapping.h | 15 + Source/UI/{ => Text}/TextFitting.cpp | 6 +- Source/UI/{ => Text}/TextFitting.h | 4 +- Source/UI/{ => Text}/TextMarkup.cpp | 16 +- Source/UI/{ => Text}/TextMarkup.h | 6 +- Source/UI/{ => Text}/TextWrapping.cpp | 32 +- Source/UI/Text/TextWrapping.h | 15 + Source/UI/{ => Text}/UIBalloonText.cpp | 37 +- Source/UI/{ => Text}/UIBalloonText.h | 7 +- Source/UI/{ => Text}/UIStaticText.cpp | 44 +- Source/UI/{ => Text}/UIStaticText.h | 7 +- Source/UI/{ => Text}/UITextViewer.cpp | 37 +- Source/UI/{ => Text}/UITextViewer.h | 21 +- Source/UI/{ => Text}/UITextViewerLinks.cpp | 30 +- Source/UI/{ => Text}/UITextViewerMessages.cpp | 33 +- Source/UI/{ => Text}/UITransBalloonText.cpp | 35 +- Source/UI/{ => Text}/UITransBalloonText.h | 8 +- Source/UI/TextWrapping.h | 27 - Source/UI/UIStaticBitmap.cpp | 32 +- Source/UI/UIStaticBitmap.h | 3 +- Source/UI/{ => Window}/FrameFocus.cpp | 27 +- Source/UI/{ => Window}/FrameFocus.h | 7 +- Source/UI/{ => Window}/FrameTextCache.cpp | 6 +- Source/UI/{ => Window}/FrameTextCache.h | 6 +- Source/UI/{ => Window}/InputFocus.cpp | 6 +- Source/UI/Window/InputFocus.h | 18 + Source/UI/{ => Window}/UIControl.cpp | 2 +- Source/UI/{ => Window}/UIControl.h | 8 +- Source/UI/{ => Window}/UIFrameWnd.cpp | 115 +- Source/UI/{ => Window}/UIFrameWnd.h | 19 +- Source/UI/{ => Window}/UIMessageBox.cpp | 97 +- Source/UI/{ => Window}/UIMessageBox.h | 28 +- Source/UI/{ => Window}/UIWindow.cpp | 185 +- Source/UI/{ => Window}/UIWindow.h | 83 +- Source/UI/{ => Window}/WindowAncestry.cpp | 13 +- Source/UI/Window/WindowAncestry.h | 16 + Source/UI/Window/WindowBorder.cpp | 46 + Source/UI/{ => Window}/WindowBorder.h | 7 +- Source/UI/{ => Window}/WindowDialogs.cpp | 16 +- Source/UI/{ => Window}/WindowDialogs.h | 21 +- Source/UI/{ => Window}/WindowFrameUpdate.cpp | 9 +- Source/UI/Window/WindowFrameUpdate.h | 18 + Source/UI/Window/WindowManagerWindows.h | 17 + Source/UI/{ => Window}/WindowMouseHit.cpp | 47 +- Source/UI/{ => Window}/WindowMouseHit.h | 13 +- Source/UI/Window/WindowNotifications.h | 12 + Source/UI/{ => Window}/WindowOrdering.cpp | 16 +- Source/UI/Window/WindowOrdering.h | 20 + Source/UI/{ => Window}/WindowPolicy.cpp | 4 +- Source/UI/Window/WindowPolicy.h | 6 + Source/UI/{ => Window}/WindowRegistration.cpp | 5 +- Source/UI/Window/WindowRegistration.h | 21 + Source/UI/{ => Window}/WindowRetirement.cpp | 15 +- Source/UI/Window/WindowRetirement.h | 31 + Source/UI/WindowAncestry.h | 24 - Source/UI/WindowBorder.cpp | 57 - Source/UI/WindowCoordinates.h | 15 - Source/UI/WindowFrameUpdate.h | 21 - Source/UI/WindowManagerWindows.h | 18 - Source/UI/WindowNotifications.h | 15 - Source/UI/WindowOrdering.h | 22 - Source/UI/WindowPolicy.h | 7 - Source/UI/WindowRegistration.h | 24 - Source/UI/WindowRetirement.h | 39 - .../Utility/{ => Async}/AsyncDiagnostic.cpp | 4 +- Source/Utility/{ => Async}/AsyncDiagnostic.h | 6 +- Source/Utility/{ => Async}/NAsyncWork.cpp | 5 +- Source/Utility/{ => Async}/NAsyncWork.h | 8 +- Source/Utility/{ => Async}/NAsyncWorkMgr.cpp | 18 +- Source/Utility/{ => Async}/NAsyncWorkMgr.h | 6 +- .../Utility/{ => Async}/NAsyncWorkQueue.cpp | 12 +- Source/Utility/{ => Async}/NAsyncWorkQueue.h | 6 +- .../Utility/{ => Async}/NAsyncWorkThread.cpp | 8 +- Source/Utility/{ => Async}/NAsyncWorkThread.h | 14 +- Source/Utility/{ => Async}/NMessageMgr.cpp | 8 +- Source/Utility/{ => Async}/NMessageMgr.h | 4 +- Source/Utility/{ => Async}/NMessageQueue.cpp | 10 +- Source/Utility/{ => Async}/NMessageQueue.h | 6 +- Source/Utility/{ => Async}/NObject.cpp | 4 +- Source/Utility/{ => Async}/NObject.h | 5 +- Source/Utility/{ => Async}/NRecycleObject.cpp | 2 +- Source/Utility/{ => Async}/NRecycleObject.h | 11 +- .../{ => Async}/NRecycleObjectPoolMgr.cpp | 9 +- .../{ => Async}/NRecycleObjectPoolMgr.h | 11 +- Source/Utility/Base64.cpp | 9 + Source/Utility/Base64.h | 2 - Source/Utility/GroupedInteger.h | 13 - Source/Utility/GuidParse.cpp | 14 +- Source/Utility/GuidParse.h | 2 - Source/Utility/LanguageCharset.cpp | 87 - Source/Utility/{ => Math}/AffineLookAt.cpp | 8 +- Source/Utility/{ => Math}/AffineMatrix.cpp | 18 +- Source/Utility/{ => Math}/AffineMatrix.h | 6 +- Source/Utility/{ => Math}/ClientAngles.cpp | 6 +- Source/Utility/{ => Math}/RayTriangle.cpp | 12 +- Source/Utility/Math/RayTriangle.h | 6 + Source/Utility/Math/ScalarConversion.h | 10 + Source/Utility/RayTriangle.h | 16 - Source/Utility/Rijndael.cpp | 1177 ++---- Source/Utility/Rijndael.h | 25 +- Source/Utility/{ => Text}/FormatString.cpp | 6 +- Source/Utility/{ => Text}/FormatString.h | 4 +- Source/Utility/{ => Text}/GroupedInteger.cpp | 6 +- Source/Utility/Text/GroupedInteger.h | 11 + Source/Utility/Text/LanguageCharset.cpp | 89 + Source/Utility/{ => Text}/LanguageCharset.h | 4 +- .../Utility/{ => Threading}/CSyncObject.cpp | 2 +- Source/Utility/{ => Threading}/CSyncObject.h | 5 +- .../Utility/{ => Threading}/NSyncObject.cpp | 2 +- Source/Utility/{ => Threading}/NSyncObject.h | 5 +- Source/Utility/{ => Threading}/NThread.cpp | 18 +- Source/Utility/{ => Threading}/NThread.h | 5 +- Source/Utility/XorBytes.cpp | 2 - Source/Utility/XorBytes.h | 1 - compile.json | 760 ++-- 890 files changed, 11783 insertions(+), 16651 deletions(-) create mode 100644 Source/Client/Application/ApplicationActivation.cpp create mode 100644 Source/Client/Application/ApplicationActivation.h create mode 100644 Source/Client/Application/ApplicationMessages.cpp create mode 100644 Source/Client/Application/ApplicationMessages.h create mode 100644 Source/Client/Application/ApplicationWindow.cpp create mode 100644 Source/Client/Application/ApplicationWindow.h rename Source/Client/{ => Application}/ErrorDialog.cpp (86%) create mode 100644 Source/Client/Application/ErrorDialog.h create mode 100644 Source/Client/Application/Launcher.cpp create mode 100644 Source/Client/Application/Launcher.h rename Source/Client/{ => Application}/UnhandledExceptionHandler.cpp (86%) rename Source/Client/{ => Application}/UnhandledExceptionHandler.h (76%) delete mode 100644 Source/Client/ApplicationActivation.cpp delete mode 100644 Source/Client/ApplicationActivation.h delete mode 100644 Source/Client/ApplicationMessages.cpp delete mode 100644 Source/Client/ApplicationMessages.h delete mode 100644 Source/Client/ApplicationWindow.cpp delete mode 100644 Source/Client/ApplicationWindow.h rename Source/Client/{ => Browser}/BrowserAddressBar.cpp (55%) create mode 100644 Source/Client/Browser/BrowserAddressBar.h rename Source/Client/{ => Browser}/BrowserAddressEdit.cpp (67%) create mode 100644 Source/Client/Browser/BrowserAddressEdit.h rename Source/Client/{ => Browser}/BrowserClientSite.cpp (83%) rename Source/Client/{ => Browser}/BrowserClientSite.h (63%) rename Source/Client/{ => Browser}/BrowserClose.cpp (91%) create mode 100644 Source/Client/Browser/BrowserClose.h rename Source/Client/{ => Browser}/BrowserCommandTarget.cpp (71%) rename Source/Client/{ => Browser}/BrowserCommandTarget.h (52%) rename Source/Client/{ => Browser}/BrowserCreation.cpp (82%) create mode 100644 Source/Client/Browser/BrowserCreation.h rename Source/Client/{ => Browser}/BrowserCursor.cpp (73%) create mode 100644 Source/Client/Browser/BrowserCursor.h rename Source/Client/{ => Browser}/BrowserDocumentUI.cpp (86%) rename Source/Client/{ => Browser}/BrowserDocumentUI.h (76%) rename Source/{UI => Client/Browser}/BrowserFactory.cpp (79%) rename Source/{UI => Client/Browser}/BrowserFactory.h (53%) rename Source/Client/{ => Browser}/BrowserFrame.cpp (82%) create mode 100644 Source/Client/Browser/BrowserFrame.h rename Source/Client/{ => Browser}/BrowserHostWindow.cpp (76%) create mode 100644 Source/Client/Browser/BrowserHostWindow.h rename Source/Client/{ => Browser}/BrowserInPlace.cpp (92%) rename Source/Client/{ => Browser}/BrowserInPlace.h (80%) rename Source/Client/{ => Browser}/BrowserInputHandoff.cpp (66%) create mode 100644 Source/Client/Browser/BrowserInputHandoff.h rename Source/Client/{ => Browser}/BrowserInterface.cpp (83%) create mode 100644 Source/Client/Browser/BrowserInterface.h rename Source/Client/{ => Browser}/BrowserMessages.cpp (83%) rename Source/Client/{ => Browser}/BrowserMessages.h (51%) rename Source/{UI => Client/Browser}/BrowserPopupDispatch.cpp (68%) rename Source/{UI => Client/Browser}/BrowserPopupDispatch.h (61%) rename Source/Client/{ => Browser}/BrowserRegistry.cpp (84%) rename Source/Client/{ => Browser}/BrowserRegistry.h (51%) rename Source/Client/{ => Browser}/BrowserSiteAttachment.cpp (84%) create mode 100644 Source/Client/Browser/BrowserSiteAttachment.h rename Source/Client/{ => Browser}/BrowserWindowSizing.cpp (97%) rename Source/Client/{ => Browser}/BrowserWindowSizing.h (50%) rename Source/Client/{ => Browser}/WebBrowser.cpp (60%) rename Source/Client/{ => Browser}/WebBrowser.h (75%) rename Source/Client/{ => Browser}/WebEventReceiver.cpp (81%) rename Source/Client/{ => Browser}/WebEventReceiver.h (61%) delete mode 100644 Source/Client/BrowserAddressBar.h delete mode 100644 Source/Client/BrowserAddressEdit.h delete mode 100644 Source/Client/BrowserClose.h delete mode 100644 Source/Client/BrowserCreation.h delete mode 100644 Source/Client/BrowserCursor.h delete mode 100644 Source/Client/BrowserFrame.h delete mode 100644 Source/Client/BrowserHostWindow.h delete mode 100644 Source/Client/BrowserInputHandoff.h delete mode 100644 Source/Client/BrowserInterface.h delete mode 100644 Source/Client/BrowserSiteAttachment.h delete mode 100644 Source/Client/ErrorDialog.h rename Source/Client/{ => Input}/ImeInput.cpp (88%) rename Source/Client/{ => Input}/ImeInput.h (51%) rename Source/Client/{ => Input}/InputCharset.cpp (86%) rename Source/Client/{ => Input}/InputCharset.h (59%) rename Source/Client/{ => Input}/Mouse.cpp (85%) rename Source/Client/{ => Input}/Mouse.h (68%) rename Source/Client/{ => Input}/TextInputBuffer.cpp (85%) create mode 100644 Source/Client/Input/TextInputBuffer.h rename Source/Client/{ => Input}/TraditionalKeyInput.cpp (83%) rename Source/Client/{ => Input}/TraditionalKeyInput.h (71%) delete mode 100644 Source/Client/Launcher.cpp delete mode 100644 Source/Client/Launcher.h rename Source/Client/{ => Mode}/ActiveGameMode.cpp (74%) rename Source/Client/{ => Mode}/ActiveGameMode.h (58%) rename Source/Client/{ => Mode}/ModeCursor.cpp (79%) rename Source/Client/{ => Mode}/ModeCursor.h (55%) rename Source/Client/{ => Mode}/ModeDragState.cpp (76%) rename Source/Client/{ => Mode}/ModeDragState.h (64%) create mode 100644 Source/Client/Mode/ModeEvents.h rename Source/Client/{ => Mode}/ModeTooltip.cpp (69%) rename Source/Client/{ => Mode}/ModeTooltip.h (66%) delete mode 100644 Source/Client/ModeEvents.h delete mode 100644 Source/Client/TextInputBuffer.h delete mode 100644 Source/Contents/AccountService.h delete mode 100644 Source/Contents/AccountUserData.h rename Source/Contents/{ => Actors}/AttackMotion.cpp (94%) create mode 100644 Source/Contents/Actors/AttackMotion.h rename Source/Contents/{ => Actors}/GameObject.cpp (76%) rename Source/Contents/{ => Actors}/GameObject.h (51%) rename Source/Contents/{ => Actors}/RenderObject.cpp (61%) create mode 100644 Source/Contents/Actors/RenderObject.h rename Source/Contents/{ => Actors}/RenderObjectState.cpp (92%) rename Source/Contents/{ => Actors}/RenderObjectState.h (92%) rename Source/Contents/{ => Actors}/SpriteDrawingPolicy.cpp (63%) create mode 100644 Source/Contents/Actors/SpriteDrawingPolicy.h rename Source/Contents/{ => Async}/AsyncWorkMgr.cpp (52%) create mode 100644 Source/Contents/Async/AsyncWorkMgr.h rename Source/Contents/{ => Async}/AsyncWorkRecycleObjectPoolMgr.cpp (56%) rename Source/Contents/{ => Async}/AsyncWorkRecycleObjectPoolMgr.h (63%) delete mode 100644 Source/Contents/AsyncWorkMgr.h delete mode 100644 Source/Contents/AttackMotion.h rename Source/Contents/{ => Camera}/CameraFrame.cpp (79%) rename Source/Contents/{ => Camera}/CameraFrame.h (50%) rename Source/Contents/{ => Camera}/CameraQueries.cpp (74%) rename Source/Contents/{ => Camera}/CameraShake.cpp (82%) rename Source/Contents/{ => Camera}/CameraSmoothing.cpp (87%) rename Source/Contents/{ => Camera}/CameraState.h (67%) delete mode 100644 Source/Contents/ClientSkills.h rename Source/Contents/{ => Configuration}/GraphicsConfiguration.cpp (90%) rename Source/Contents/{ => Configuration}/GraphicsConfiguration.h (54%) rename Source/Contents/{ => Configuration}/OptionWriter.cpp (74%) create mode 100644 Source/Contents/Configuration/OptionWriter.h rename Source/Contents/{ => Configuration}/ScriptOptions.cpp (95%) rename Source/Contents/{ => Configuration}/ScriptOptions.h (51%) rename Source/Contents/{ => Configuration}/ServiceOptions.cpp (93%) rename Source/Contents/{ => Configuration}/ServiceOptions.h (51%) delete mode 100644 Source/Contents/EffectParticle.h delete mode 100644 Source/Contents/EffectPrimitiveColor.cpp delete mode 100644 Source/Contents/EffectPrimitiveMotion.h delete mode 100644 Source/Contents/EffectPrimitiveRendering.h delete mode 100644 Source/Contents/EffectTypes.cpp delete mode 100644 Source/Contents/EffectTypes.h rename Source/Contents/{ => Effects}/AttachedEffect.cpp (71%) rename Source/Contents/{ => Effects}/AttachedEffect.h (53%) rename Source/Contents/{ => Effects}/Effect.cpp (82%) rename Source/Contents/{ => Effects}/Effect.h (76%) rename Source/Contents/{ => Effects}/EffectActor.cpp (63%) rename Source/Contents/{ => Effects}/EffectActor.h (72%) rename Source/Contents/{ => Effects}/EffectAttachments.cpp (86%) rename Source/Contents/{ => Effects}/EffectAttachments.h (55%) rename Source/Contents/{ => Effects}/EffectLists.cpp (95%) rename Source/Contents/{ => Effects}/EffectLists.h (58%) rename Source/Contents/{ => Effects}/EffectParticle.cpp (61%) create mode 100644 Source/Contents/Effects/EffectParticle.h create mode 100644 Source/Contents/Effects/EffectPrimitiveColor.cpp rename Source/Contents/{ => Effects}/EffectPrimitiveMotion.cpp (63%) create mode 100644 Source/Contents/Effects/EffectPrimitiveMotion.h rename Source/Contents/{ => Effects}/EffectPrimitiveRecords.cpp (62%) rename Source/Contents/{ => Effects}/EffectPrimitiveRendering.cpp (74%) create mode 100644 Source/Contents/Effects/EffectPrimitiveRendering.h rename Source/Contents/{ => Effects}/EffectPrimitiveState.cpp (94%) rename Source/Contents/{ => Effects}/EffectPrimitiveState.h (77%) create mode 100644 Source/Contents/Effects/EffectTypes.cpp create mode 100644 Source/Contents/Effects/EffectTypes.h rename Source/Contents/{ => Effects}/EffectVisibility.cpp (76%) rename Source/Contents/{ => Effects}/EffectVisibility.h (63%) rename Source/Contents/{ => Effects}/PartyEffect.cpp (63%) create mode 100644 Source/Contents/Effects/PartyEffect.h rename Source/Contents/{ => Effects}/PartyMemberEffects.cpp (69%) rename Source/Contents/{ => Effects}/PartyMemberEffects.h (69%) rename Source/Contents/{ => Effects}/RagEffectInitialization.cpp (73%) create mode 100644 Source/Contents/Effects/RagEffectInitialization.h rename Source/Contents/{ => Effects}/RagEffectResourceSelection.cpp (99%) rename Source/Contents/{ => Effects}/RagEffectState.cpp (58%) rename Source/Contents/{ => Effects}/RagEffectState.h (79%) delete mode 100644 Source/Contents/EmblemDownload.h rename Source/Contents/{ => Emblems}/EmblemCache.cpp (91%) rename Source/Contents/{ => Emblems}/EmblemCache.h (60%) rename Source/Contents/{ => Emblems}/EmblemDataDownloadAsyncWork.cpp (74%) rename Source/Contents/{ => Emblems}/EmblemDataDownloadAsyncWork.h (62%) rename Source/Contents/{ => Emblems}/EmblemDataMgr.cpp (72%) rename Source/Contents/{ => Emblems}/EmblemDataMgr.h (59%) rename Source/Contents/{ => Emblems}/EmblemDataUploadAsyncWork.cpp (82%) rename Source/Contents/{ => Emblems}/EmblemDataUploadAsyncWork.h (64%) rename Source/Contents/{ => Emblems}/EmblemDownload.cpp (80%) create mode 100644 Source/Contents/Emblems/EmblemDownload.h rename Source/Contents/{ => Emblems}/EmblemUpload.cpp (72%) rename Source/Contents/{ => Emblems}/EmblemUpload.h (72%) rename Source/Contents/{ => Emblems}/GuildEmblemReqBundle.cpp (78%) rename Source/Contents/{ => Emblems}/GuildEmblemReqBundle.h (69%) rename Source/Contents/{ => Ground}/GroundDecals.cpp (76%) rename Source/Contents/{ => Ground}/GroundGeometry.cpp (81%) rename Source/Contents/{ => Ground}/GroundGeometry.h (59%) rename Source/Contents/{ => Ground}/GroundLighting.cpp (74%) rename Source/Contents/{ => Ground}/GroundLightingInitialization.cpp (64%) rename Source/Contents/{ => Ground}/GroundLightmaps.cpp (81%) rename Source/Contents/{ => Ground}/GroundPicking.cpp (76%) rename Source/Contents/{ => Ground}/GroundRendering.cpp (85%) rename Source/Contents/{ => Ground}/GroundRendering.h (89%) rename Source/Contents/{ => Ground}/GroundSamples.cpp (57%) rename Source/Contents/{ => Ground}/GroundSpatial.cpp (62%) rename Source/Contents/{ => Ground}/GroundSpatial.h (76%) rename Source/Contents/{ => Ground}/GroundWaterRendering.cpp (76%) rename Source/Contents/{ => Ground}/GroundWaterState.cpp (62%) rename Source/Contents/{ => Ground}/GroundWaterState.h (75%) rename Source/Contents/{ => Ground}/TerrainCoordinates.cpp (67%) rename Source/Contents/{ => Ground}/TerrainHeight.cpp (56%) rename Source/Contents/{ => Ground}/TerrainHeight.h (72%) create mode 100644 Source/Contents/Ground/TerrainPicking.cpp create mode 100644 Source/Contents/Ground/TerrainPlane.cpp rename Source/Contents/{ => Hotkeys}/EmotionHotkeys.cpp (88%) rename Source/Contents/{ => Hotkeys}/EmotionHotkeys.h (70%) rename Source/Contents/{ => Hotkeys}/HotkeyInfo.cpp (96%) rename Source/Contents/{ => Hotkeys}/HotkeyInfo.h (73%) rename Source/Contents/{ => Hotkeys}/UserHotkeyMgr.cpp (92%) rename Source/Contents/{ => Hotkeys}/UserHotkeyMgr.h (85%) rename Source/Contents/{ => Hotkeys}/UserHotkeyScript.cpp (96%) rename Source/Contents/{ => Hotkeys}/UserHotkeyScript.h (75%) rename Source/Contents/{ => Items}/ItemDescription.cpp (91%) rename Source/Contents/{ => Items}/ItemDescription.h (78%) rename Source/Contents/{ => Items}/ItemInfo.cpp (95%) rename Source/Contents/{ => Items}/ItemInfo.h (83%) rename Source/Contents/{ => Items}/ItemLink.cpp (91%) rename Source/Contents/{ => Items}/ItemLink.h (68%) rename Source/Contents/{ => Items}/ItemNaming.cpp (98%) rename Source/Contents/{ => Items}/ItemNaming.h (83%) rename Source/Contents/{ => Items}/ItemResources.cpp (90%) rename Source/Contents/{ => Items}/ItemResources.h (66%) delete mode 100644 Source/Contents/JobInheritance.h rename Source/Contents/{ => Jobs}/JobInheritance.cpp (85%) create mode 100644 Source/Contents/Jobs/JobInheritance.h rename Source/Contents/{ => Jobs}/JobNameInitialization.cpp (78%) rename Source/Contents/{ => Jobs}/JobNames.cpp (99%) rename Source/Contents/{ => Jobs}/JobNames.h (63%) rename Source/Contents/{ => Messenger}/ClientMessenger.cpp (96%) rename Source/Contents/{ => Messenger}/ClientMessenger.h (75%) rename Source/Contents/{ => Messenger}/MessengerMember.cpp (80%) rename Source/Contents/{ => Messenger}/MessengerMember.h (69%) rename Source/Contents/{ => Messenger}/WhisperBlockMgr.cpp (97%) rename Source/Contents/{ => Messenger}/WhisperBlockMgr.h (80%) delete mode 100644 Source/Contents/ModelAnimation.h rename Source/Contents/{ => Models}/ModelActor.cpp (94%) rename Source/Contents/{ => Models}/ModelActor.h (90%) rename Source/Contents/{ => Models}/ModelActorBounds.cpp (90%) rename Source/Contents/{ => Models}/ModelAnimation.cpp (76%) create mode 100644 Source/Contents/Models/ModelAnimation.h rename Source/Contents/{ => Models}/ModelLighting.cpp (80%) rename Source/Contents/{ => Models}/ModelMovies.cpp (79%) rename Source/Contents/{ => Models}/ModelNode.cpp (92%) rename Source/Contents/{ => Models}/ModelNode.h (67%) rename Source/Contents/{ => Models}/ModelNodeBounds.cpp (61%) rename Source/Contents/{ => Models}/ModelOcclusion.cpp (92%) rename Source/Contents/{ => Models}/ModelPlayback.cpp (57%) rename Source/Contents/{ => Models}/ModelQuaternion.cpp (88%) rename Source/Contents/{ => Models}/ModelRendering.cpp (69%) rename Source/Contents/{ => Models}/ModelRendering.h (51%) rename Source/Contents/{ => Models}/ModelSpatial.cpp (71%) rename Source/Contents/{ => Models}/ModelSpatial.h (51%) rename Source/Contents/{ => Models}/ModelTextureAnimation.cpp (51%) rename Source/Contents/{ => Models}/ModelTextureUV.cpp (81%) rename Source/Contents/{ => Movies}/BinkMovie.cpp (89%) rename Source/Contents/{ => Movies}/BinkMovie.h (76%) rename Source/Contents/{ => Movies}/BinkMovies.cpp (82%) rename Source/Contents/{ => Movies}/BinkMovies.h (65%) delete mode 100644 Source/Contents/NormalItemSlots.h delete mode 100644 Source/Contents/OptionWriter.h rename Source/Contents/{ => Party}/AdvenPartyInfo.cpp (76%) rename Source/Contents/{ => Party}/AdvenPartyInfo.h (81%) rename Source/Contents/{ => Party}/AdventurerAgencyMgr.cpp (81%) rename Source/Contents/{ => Party}/AdventurerAgencyMgr.h (75%) rename Source/Contents/{ => Party}/AgencyRequestContext.h (63%) rename Source/Contents/{ => Party}/AgencyRequests.cpp (54%) rename Source/Contents/{ => Party}/ChangePartyMasterAsyncWork.cpp (68%) rename Source/Contents/{ => Party}/ChangePartyMasterAsyncWork.h (57%) rename Source/Contents/{ => Party}/ChangePartyMasterCompletion.cpp (62%) rename Source/Contents/{ => Party}/LoadMyPartyAsyncWork.cpp (80%) rename Source/Contents/{ => Party}/LoadMyPartyAsyncWork.h (56%) rename Source/Contents/{ => Party}/LoadPartyInfoAsyncWork.cpp (81%) rename Source/Contents/{ => Party}/LoadPartyInfoAsyncWork.h (73%) rename Source/Contents/{ => Party}/LoadPartyListAsyncWork.cpp (84%) rename Source/Contents/{ => Party}/LoadPartyListAsyncWork.h (58%) rename Source/Contents/{ => Party}/MyPartyCompletion.cpp (79%) rename Source/Contents/{ => Party}/PartyInfoCompletion.cpp (72%) rename Source/Contents/{ => Party}/PartyInvitation.cpp (86%) rename Source/Contents/{ => Party}/PartyInvitation.h (71%) rename Source/Contents/{ => Party}/PartyJoinResult.cpp (81%) rename Source/Contents/{ => Party}/PartyJoinResult.h (75%) rename Source/Contents/{ => Party}/PartyListCompletion.cpp (69%) rename Source/Contents/{ => Party}/PartyRegistrationCompletion.cpp (74%) rename Source/Contents/{ => Party}/RegisterPartyAsyncWork.cpp (85%) rename Source/Contents/{ => Party}/RegisterPartyAsyncWork.h (62%) rename Source/Contents/{ => Party}/StopRecruitingAsyncWork.cpp (80%) rename Source/Contents/{ => Party}/StopRecruitingAsyncWork.h (62%) rename Source/Contents/{ => Party}/StopRecruitingCompletion.cpp (75%) delete mode 100644 Source/Contents/PartyEffect.h delete mode 100644 Source/Contents/RagEffectInitialization.h delete mode 100644 Source/Contents/RenderObject.h delete mode 100644 Source/Contents/SkillLevelConfig.h delete mode 100644 Source/Contents/SkillTreeScript.h rename Source/Contents/{ => Skills}/AutomaticSkills.cpp (89%) rename Source/Contents/{ => Skills}/AutomaticSkills.h (80%) rename Source/Contents/{ => Skills}/ClientSkills.cpp (90%) create mode 100644 Source/Contents/Skills/ClientSkills.h rename Source/Contents/{ => Skills}/PlayerSkillBundle.cpp (94%) rename Source/Contents/{ => Skills}/PlayerSkillBundle.h (90%) rename Source/Contents/{ => Skills}/SkillInfo.cpp (76%) rename Source/Contents/{ => Skills}/SkillInfo.h (85%) rename Source/Contents/{ => Skills}/SkillLevelConfig.cpp (86%) create mode 100644 Source/Contents/Skills/SkillLevelConfig.h rename Source/Contents/{ => Skills}/SkillLevelRegistry.cpp (82%) rename Source/Contents/{ => Skills}/SkillLevelRegistry.h (62%) rename Source/Contents/{ => Skills}/SkillTreeScript.cpp (93%) create mode 100644 Source/Contents/Skills/SkillTreeScript.h rename Source/Contents/{ => Sound}/SoundConfiguration.cpp (71%) rename Source/Contents/{ => Sound}/SoundConfiguration.h (58%) rename Source/Contents/{ => Sound}/SoundMgr.cpp (86%) rename Source/Contents/{ => Sound}/SoundMgr.h (76%) delete mode 100644 Source/Contents/SpriteDrawingPolicy.h rename Source/Contents/{ => Store}/MCStoreInfoBackup.cpp (64%) rename Source/Contents/{ => Store}/MCStoreInfoBackup.h (64%) rename Source/Contents/{ => Store}/MCStoreInfoBackupAsyncWork.cpp (76%) rename Source/Contents/{ => Store}/MCStoreInfoBackupAsyncWork.h (67%) rename Source/Contents/{ => Store}/StoreBackupData.cpp (82%) create mode 100644 Source/Contents/Store/StoreBackupData.h delete mode 100644 Source/Contents/StoreBackupData.h delete mode 100644 Source/Contents/TerrainPicking.cpp delete mode 100644 Source/Contents/TerrainPlane.cpp rename Source/Contents/{ => UserData}/AccountConfigLoad.h (65%) rename Source/Contents/{ => UserData}/AccountLinkedUserDataLoadAsyncWork.cpp (75%) rename Source/Contents/{ => UserData}/AccountLinkedUserDataLoadAsyncWork.h (67%) rename Source/Contents/{ => UserData}/AccountLinkedUserDataMgr.cpp (69%) rename Source/Contents/{ => UserData}/AccountLinkedUserDataMgr.h (66%) rename Source/Contents/{ => UserData}/AccountLinkedUserDataSaveAsyncWork.cpp (83%) rename Source/Contents/{ => UserData}/AccountLinkedUserDataSaveAsyncWork.h (71%) rename Source/Contents/{ => UserData}/AccountService.cpp (54%) create mode 100644 Source/Contents/UserData/AccountService.h rename Source/Contents/{ => UserData}/AccountUserData.cpp (77%) create mode 100644 Source/Contents/UserData/AccountUserData.h rename Source/Contents/{ => UserData}/CharacterConfigLoad.cpp (63%) rename Source/Contents/{ => UserData}/CharacterConfigLoad.h (80%) rename Source/Contents/{ => UserData}/CharacterConfigSave.cpp (80%) rename Source/Contents/{ => UserData}/CharacterConfigSave.h (72%) rename Source/Contents/{ => UserData}/CharacterLinkedUserDataLoadAsyncWork.cpp (85%) rename Source/Contents/{ => UserData}/CharacterLinkedUserDataLoadAsyncWork.h (57%) rename Source/Contents/{ => UserData}/CharacterLinkedUserDataMgr.cpp (84%) rename Source/Contents/{ => UserData}/CharacterLinkedUserDataMgr.h (72%) rename Source/Contents/{ => UserData}/CharacterLinkedUserDataSaveAsyncWork.cpp (85%) rename Source/Contents/{ => UserData}/CharacterLinkedUserDataSaveAsyncWork.h (62%) rename Source/Contents/{ => UserData}/NormalItemSlots.cpp (62%) create mode 100644 Source/Contents/UserData/NormalItemSlots.h rename Source/Contents/{ => World}/WorldActors.cpp (93%) create mode 100644 Source/Contents/World/WorldActors.h rename Source/Contents/{ => World}/WorldEnvironment.cpp (78%) create mode 100644 Source/Contents/World/WorldEnvironment.h rename Source/Contents/{ => World}/WorldGroundImport.cpp (57%) create mode 100644 Source/Contents/World/WorldGroundImport.h rename Source/Contents/{ => World}/WorldModelLoading.cpp (79%) rename Source/Contents/{ => World}/WorldModelLoading.h (69%) rename Source/Contents/{ => World}/WorldModelPlacement.cpp (76%) create mode 100644 Source/Contents/World/WorldModelPlacement.h rename Source/Contents/{ => World}/WorldModelView.cpp (59%) create mode 100644 Source/Contents/World/WorldModelView.h rename Source/Contents/{ => World}/WorldObjects.cpp (74%) create mode 100644 Source/Contents/World/WorldObjects.h rename Source/Contents/{ => World}/WorldOcclusion.cpp (53%) create mode 100644 Source/Contents/World/WorldOcclusion.h rename Source/Contents/{ => World}/WorldProximity.cpp (67%) create mode 100644 Source/Contents/World/WorldProximity.h rename Source/Contents/{ => World}/WorldRayQuery.cpp (75%) rename Source/Contents/{ => World}/WorldRayQuery.h (71%) rename Source/Contents/{ => World}/WorldSpatialInitialization.cpp (62%) create mode 100644 Source/Contents/World/WorldSpatialInitialization.h rename Source/Contents/{ => World}/WorldSpatialTree.cpp (92%) rename Source/Contents/{ => World}/WorldSpatialTree.h (88%) rename Source/Contents/{ => World}/WorldTerrainPicking.cpp (61%) create mode 100644 Source/Contents/World/WorldTerrainPicking.h rename Source/Contents/{ => World}/WorldViewSpatial.cpp (96%) delete mode 100644 Source/Contents/WorldActors.h delete mode 100644 Source/Contents/WorldEnvironment.h delete mode 100644 Source/Contents/WorldGroundImport.h delete mode 100644 Source/Contents/WorldModelPlacement.h delete mode 100644 Source/Contents/WorldModelView.h delete mode 100644 Source/Contents/WorldObjects.h delete mode 100644 Source/Contents/WorldOcclusion.h delete mode 100644 Source/Contents/WorldProximity.h delete mode 100644 Source/Contents/WorldSpatialInitialization.h delete mode 100644 Source/Contents/WorldTerrainPicking.h rename Source/Network/{ => Connection}/Connection.cpp (90%) rename Source/Network/{ => Connection}/Connection.h (71%) rename Source/Network/{ => Connection}/ConnectionBuffer.cpp (77%) rename Source/Network/{ => Connection}/ConnectionBuffer.h (71%) rename Source/Network/{ => Connection}/ConnectionRuntime.cpp (89%) rename Source/Network/{ => Connection}/ConnectionRuntime.h (68%) rename Source/Network/{ => Http}/CURLMgr.cpp (91%) rename Source/Network/{ => Http}/CURLMgr.h (83%) rename Source/Network/{ => Http}/CURLPostHander.cpp (90%) rename Source/Network/{ => Http}/CURLPostHander.h (81%) rename Source/Network/{ => Packets}/PacketLengths.cpp (93%) rename Source/Network/{ => Packets}/PacketLengths.h (75%) rename Source/Network/{ => Packets}/PacketRegistrations.inc (95%) rename Source/Network/{ => Packets}/PartyJoinPacket.cpp (64%) create mode 100644 Source/Network/Packets/PartyJoinPacket.h rename Source/Network/{ => Packets}/PartyJoinRequest.cpp (74%) rename Source/Network/{ => Packets}/ShortcutPacket.cpp (72%) create mode 100644 Source/Network/Packets/ShortcutPacket.h rename Source/Network/{ => Packets}/SkillUpdatePacket.cpp (85%) create mode 100644 Source/Network/Packets/SkillUpdatePacket.h delete mode 100644 Source/Network/PartyJoinPacket.h delete mode 100644 Source/Network/ShortcutPacket.h delete mode 100644 Source/Network/SkillUpdatePacket.h delete mode 100644 Source/Render/AlphaRectangle.h delete mode 100644 Source/Render/BitmapPixels.h delete mode 100644 Source/Render/ClientTextureSources.h delete mode 100644 Source/Render/D3DX9Runtime.cpp delete mode 100644 Source/Render/DCBitmap.h rename Source/Render/{ => DX7}/BackBufferDX7.cpp (97%) rename Source/Render/{ => DX7}/DeviceCapabilitiesDX7.cpp (62%) rename Source/Render/{ => DX7}/DeviceOwnerDX7.cpp (74%) rename Source/Render/{ => DX7}/DeviceOwnerDX7.h (74%) rename Source/Render/{ => DX7}/DirectDrawEnumeration.cpp (88%) rename Source/Render/{ => DX7}/DirectDrawEnumeration.h (85%) rename Source/Render/{ => DX7}/DisplayModeDX7.cpp (89%) rename Source/Render/{ => DX7}/RenderAdapterDX7.cpp (92%) rename Source/Render/{ => DX7}/RenderSystemDX7.cpp (52%) rename Source/Render/{ => DX7}/RenderSystemDX7.h (83%) rename Source/Render/{ => DX7}/RenderToTextureDX7.cpp (64%) rename Source/Render/{ => DX7}/RendererDX7Operations.cpp (67%) rename Source/Render/{ => DX7}/RendererDX7Operations.h (56%) rename Source/Render/{ => DX7}/RendererFogDX7.cpp (91%) rename Source/Render/{ => DX7}/RendererFogDX7.h (60%) rename Source/Render/{ => DX7}/RendererPresentationDX7.cpp (86%) rename Source/Render/{ => DX7}/RendererPresentationDX7.h (63%) rename Source/Render/{ => DX7}/ScreenshotDX7.cpp (81%) rename Source/Render/{ => DX7}/SurfaceDX7.cpp (79%) rename Source/Render/{ => DX7}/SurfaceDX7.h (84%) rename Source/Render/{ => DX7}/TextureAllocationDX7.cpp (90%) rename Source/Render/{ => DX7}/TextureAllocationDX7.h (50%) rename Source/Render/{ => DX7}/TextureBindingDX7.cpp (87%) rename Source/Render/{ => DX7}/TextureBindingDX7.h (74%) rename Source/Render/{ => DX7}/TextureCalibrationDX7.cpp (76%) rename Source/Render/{ => DX7}/TextureDX7.cpp (65%) rename Source/Render/{ => DX7}/TextureDX7.h (68%) rename Source/Render/{ => DX7}/TextureModesDX7.cpp (87%) rename Source/Render/{ => DX9}/AlphaQueuesDX9.cpp (85%) rename Source/Render/{ => DX9}/BackBufferDX9.cpp (68%) create mode 100644 Source/Render/DX9/D3DX9Runtime.cpp rename Source/Render/{ => DX9}/D3DX9Runtime.h (51%) rename Source/Render/{ => DX9}/DeviceOwnerDX9.cpp (85%) rename Source/Render/{ => DX9}/DeviceOwnerDX9.h (65%) rename Source/Render/{ => DX9}/DeviceRecoveryDX9.cpp (88%) rename Source/Render/{ => DX9}/DeviceStateDX9.cpp (95%) rename Source/Render/{ => DX9}/DeviceStateDX9.h (87%) rename Source/Render/{ => DX9}/GroundQueuesDX9.cpp (72%) rename Source/Render/{ => DX9}/OpaqueQueuesDX9.cpp (71%) rename Source/Render/{ => DX9}/QueuedDrawingDX9.cpp (80%) rename Source/Render/{ => DX9}/RenderSystemDX9.cpp (75%) rename Source/Render/{ => DX9}/RenderSystemDX9.h (79%) rename Source/Render/{ => DX9}/RendererBackBuffer.cpp (91%) rename Source/Render/{ => DX9}/RendererDX9.cpp (74%) rename Source/Render/{ => DX9}/RendererDX9.h (81%) rename Source/Render/{ => DX9}/RendererDX9Operations.cpp (65%) rename Source/Render/{ => DX9}/RendererDX9Operations.h (69%) rename Source/Render/{ => DX9}/RendererFogDX9.cpp (85%) create mode 100644 Source/Render/DX9/RendererFogDX9.h create mode 100644 Source/Render/DX9/RendererFrameDX9.cpp rename Source/Render/{ => DX9}/RendererFrameDX9.h (60%) rename Source/Render/{ => DX9}/RendererPresentation.cpp (85%) rename Source/Render/{ => DX9}/RendererPresentation.h (55%) rename Source/Render/{ => DX9}/ScreenshotDX9.cpp (64%) rename Source/Render/{ => DX9}/SurfaceDX9.cpp (85%) rename Source/Render/{ => DX9}/SurfaceDX9.h (81%) rename Source/Render/{ => DX9}/TextureDX9.cpp (72%) rename Source/Render/{ => DX9}/TextureDX9.h (70%) rename Source/Render/{ => DX9}/TextureModesDX9.cpp (78%) delete mode 100644 Source/Render/DepthAlpha.cpp delete mode 100644 Source/Render/DeviceContext.h rename Source/Render/{ => DeviceContext}/DCBitmap.cpp (63%) create mode 100644 Source/Render/DeviceContext/DCBitmap.h rename Source/Render/{ => DeviceContext}/DCSurface.cpp (79%) rename Source/Render/{ => DeviceContext}/DCSurface.h (59%) rename Source/Render/{ => DeviceContext}/DeviceContext.cpp (70%) create mode 100644 Source/Render/DeviceContext/DeviceContext.h create mode 100644 Source/Render/Primitives/AlphaRectangle.h create mode 100644 Source/Render/Primitives/DepthAlpha.cpp rename Source/Render/{ => Primitives}/DepthAlpha.h (73%) rename Source/Render/{ => Primitives}/LightmappedPrimitive.cpp (77%) rename Source/Render/{ => Primitives}/LightmappedPrimitive.h (79%) rename Source/Render/{ => Primitives}/RenderCommandPool.cpp (93%) rename Source/Render/{ => Primitives}/RenderCommandPool.h (60%) rename Source/Render/{ => Primitives}/RenderPrimitive.cpp (81%) rename Source/Render/{ => Primitives}/RenderPrimitive.h (79%) rename Source/Render/{ => Primitives}/RenderPrimitivePool.cpp (87%) rename Source/Render/{ => Primitives}/RenderPrimitivePool.h (55%) rename Source/Render/{ => Primitives}/RenderQueues.cpp (89%) rename Source/Render/{ => Primitives}/RenderQueues.h (70%) rename Source/Render/{ => Primitives}/RenderVertexPool.cpp (97%) rename Source/Render/{ => Primitives}/RenderVertexPool.h (63%) rename Source/Render/{ => Primitives}/UIRPData.cpp (79%) create mode 100644 Source/Render/Primitives/UIRPData.h rename Source/Render/{ => Projection}/RenderProjection.cpp (50%) rename Source/Render/{ => Projection}/RenderProjection.h (58%) rename Source/Render/{ => Projection}/RenderRay.cpp (92%) rename Source/Render/{ => Projection}/RendererViewport.cpp (85%) create mode 100644 Source/Render/Projection/RendererViewport.h delete mode 100644 Source/Render/RendererFogDX9.h delete mode 100644 Source/Render/RendererFrameDX9.cpp delete mode 100644 Source/Render/RendererViewport.h rename Source/Render/{ => Text}/FontCache.cpp (76%) rename Source/Render/{ => Text}/FontCache.h (80%) rename Source/Render/{ => Text}/TextContext.cpp (80%) rename Source/Render/{ => Text}/TextContext.h (87%) rename Source/Render/{ => Textures}/BitmapPixels.cpp (74%) create mode 100644 Source/Render/Textures/BitmapPixels.h rename Source/Render/{ => Textures}/BitmapTextureCache.cpp (81%) rename Source/Render/{ => Textures}/BitmapTextureCache.h (77%) rename Source/Render/{ => Textures}/ClientTextureSources.cpp (76%) create mode 100644 Source/Render/Textures/ClientTextureSources.h rename Source/Render/{ => Textures}/SpriteAtlas.cpp (88%) rename Source/Render/{ => Textures}/SpriteAtlas.h (77%) rename Source/Render/{ => Textures}/SpritePixels.h (68%) rename Source/Render/{ => Textures}/Surface.cpp (60%) rename Source/Render/{ => Textures}/Surface.h (76%) rename Source/Render/{ => Textures}/Texture.cpp (79%) rename Source/Render/{ => Textures}/Texture.h (56%) rename Source/Render/{ => Textures}/TextureCache.cpp (79%) rename Source/Render/{ => Textures}/TextureCache.h (55%) delete mode 100644 Source/Render/UIRPData.h create mode 100644 Source/Resource/Audio/MilesRuntime.cpp rename Source/Resource/{ => Audio}/MilesRuntime.h (86%) rename Source/Resource/{ => Audio}/WaveResource.cpp (84%) rename Source/Resource/{ => Audio}/WaveResource.h (60%) rename Source/Resource/{ => Bitmap}/BitmapImage.cpp (94%) rename Source/Resource/{ => Bitmap}/BitmapImage.h (64%) rename Source/Resource/{ => Bitmap}/BitmapImageJpeg.cpp (84%) rename Source/Resource/{ => Bitmap}/BitmapImagePng.cpp (98%) rename Source/Resource/{ => Bitmap}/BitmapResource.cpp (90%) rename Source/Resource/{ => Bitmap}/BitmapResource.h (70%) rename Source/Resource/{ => Bitmap}/IJL15Runtime.cpp (80%) rename Source/Resource/{ => Bitmap}/IJL15Runtime.h (71%) delete mode 100644 Source/Resource/MilesRuntime.cpp rename Source/Resource/{ => Models}/AnimatedModelResource.cpp (91%) rename Source/Resource/{ => Models}/AnimatedModelResource.h (87%) rename Source/Resource/{ => Models}/ModelMesh.cpp (96%) rename Source/Resource/{ => Models}/ModelMesh.h (67%) rename Source/Resource/{ => Models}/ModelNodeLoading.cpp (94%) rename Source/Resource/{ => Models}/ModelNodeLoadingV2.cpp (90%) rename Source/Resource/{ => Models}/ModelResource.cpp (85%) rename Source/Resource/{ => Models}/ModelResource.h (85%) rename Source/Resource/{ => Models}/ModelResourceV2.cpp (84%) rename Source/Resource/{ => Sprites}/ActionResource.cpp (88%) rename Source/Resource/{ => Sprites}/ActionResource.h (75%) rename Source/Resource/{ => Sprites}/SpriteEncoding.cpp (90%) rename Source/Resource/{ => Sprites}/SpriteResource.cpp (88%) rename Source/Resource/{ => Sprites}/SpriteResource.h (73%) rename Source/Resource/{ => World}/GroundResource.cpp (83%) rename Source/Resource/{ => World}/GroundResource.h (71%) rename Source/Resource/{ => World}/TerrainResource.cpp (84%) rename Source/Resource/{ => World}/TerrainResource.h (68%) rename Source/Resource/{ => World}/WorldEnvironment.cpp (92%) rename Source/Resource/{ => World}/WorldObjects.cpp (93%) rename Source/Resource/{ => World}/WorldResource.cpp (89%) rename Source/Resource/{ => World}/WorldResource.h (88%) rename Source/UI/{ => Acceptance}/UIChooseSellBuyWnd.cpp (85%) rename Source/UI/{ => Acceptance}/UIExchangeAcceptWnd.cpp (76%) rename Source/UI/{ => Acceptance}/UIJoinPartyAcceptWnd.cpp (78%) rename Source/UI/{ => Acceptance}/UIJoinPartyAcceptWnd.h (65%) rename Source/UI/{ => Buttons}/UIBasicButton.cpp (62%) rename Source/UI/{ => Buttons}/UIBasicButton.h (71%) rename Source/UI/{ => Buttons}/UIBitmapButton.cpp (95%) rename Source/UI/{ => Buttons}/UIBitmapButton.h (83%) rename Source/UI/{ => Buttons}/UIBmpTextButton.cpp (62%) rename Source/UI/{ => Buttons}/UIBmpTextButton.h (76%) rename Source/UI/{ => Buttons}/UIButton.cpp (85%) rename Source/UI/{ => Buttons}/UIButton.h (70%) rename Source/UI/{ => Buttons}/UICheckBox.cpp (77%) rename Source/UI/{ => Buttons}/UICheckBox.h (80%) rename Source/UI/{ => Buttons}/UIJobSlotButton.cpp (88%) rename Source/UI/{ => Buttons}/UIJobSlotButton.h (65%) rename Source/UI/{ => Buttons}/UINaviLinkButton.cpp (74%) rename Source/UI/{ => Buttons}/UINaviLinkButton.h (79%) rename Source/UI/{ => Buttons}/UITextButton.cpp (80%) rename Source/UI/{ => Buttons}/UITextButton.h (74%) rename Source/UI/{ => Chat}/ChatNotifications.cpp (69%) rename Source/UI/{ => Chat}/ChatNotifications.h (63%) rename Source/UI/{ => Chat}/ChatSuggestions.cpp (92%) create mode 100644 Source/UI/Chat/ChatSuggestions.h delete mode 100644 Source/UI/ChatSuggestions.h delete mode 100644 Source/UI/ColoredText.h delete mode 100644 Source/UI/CooldownDrawing.h rename Source/UI/{ => Cooldowns}/CooldownDrawing.cpp (75%) create mode 100644 Source/UI/Cooldowns/CooldownDrawing.h rename Source/UI/{ => Cooldowns}/CooldownOwner.cpp (87%) rename Source/UI/{ => Cooldowns}/CooldownOwner.h (64%) rename Source/UI/{ => Cooldowns}/CooldownState.cpp (76%) rename Source/UI/{ => Cooldowns}/CooldownState.h (66%) rename Source/UI/{ => Edit}/EditPainting.cpp (61%) rename Source/UI/{ => Edit}/EditPainting.h (75%) rename Source/UI/{ => Edit}/EditTextState.cpp (95%) create mode 100644 Source/UI/Edit/EditTextState.h create mode 100644 Source/UI/Edit/EditViewport.cpp rename Source/UI/{ => Edit}/EditViewport.h (81%) rename Source/UI/{ => Edit}/ItemTagRetirement.cpp (82%) rename Source/UI/{ => Edit}/ItemTagRetirement.h (58%) rename Source/UI/{ => Edit}/UIEditCtrl.cpp (76%) rename Source/UI/{ => Edit}/UIEditCtrl.h (72%) rename Source/UI/{ => Edit}/UIEditLinks.cpp (77%) rename Source/UI/{ => Edit}/UIEditVariants.cpp (77%) delete mode 100644 Source/UI/EditTextState.h delete mode 100644 Source/UI/EditViewport.cpp delete mode 100644 Source/UI/InputFocus.h delete mode 100644 Source/UI/ItemDrawing.cpp delete mode 100644 Source/UI/ItemDrawing.h rename Source/UI/{ => Layout}/SnapMgr.cpp (85%) rename Source/UI/{ => Layout}/SnapMgr.h (86%) rename Source/UI/{ => Layout}/SnapObject.cpp (82%) rename Source/UI/{ => Layout}/SnapObject.h (77%) rename Source/UI/{ => Layout}/SnapRectangle.cpp (77%) rename Source/UI/{ => Layout}/SnapRectangle.h (61%) rename Source/UI/{ => Layout}/WindowCoordinates.cpp (55%) create mode 100644 Source/UI/Layout/WindowCoordinates.h rename Source/UI/{ => Layout}/WindowGeometry.cpp (71%) rename Source/UI/{ => Layout}/WindowGeometry.h (72%) rename Source/UI/{ => Layout}/WindowSnapping.cpp (91%) rename Source/UI/{ => Layout}/WindowSnapping.h (58%) rename Source/UI/{ => Lists}/UIComboBoxDefWnd.cpp (69%) rename Source/UI/{ => Lists}/UIComboBoxDefWnd.h (77%) rename Source/UI/{ => Lists}/UIComboBoxEx.cpp (65%) rename Source/UI/{ => Lists}/UIComboBoxEx.h (70%) rename Source/UI/{ => Lists}/UIDropDownBox.cpp (88%) rename Source/UI/{ => Lists}/UIDropDownBox.h (67%) rename Source/UI/{ => Lists}/UIListBox.cpp (65%) rename Source/UI/{ => Lists}/UIListBox.h (69%) rename Source/UI/{ => Lists}/UIListBoxEx.cpp (65%) rename Source/UI/{ => Lists}/UIListBoxEx.h (66%) rename Source/UI/{ => Lists}/UIScrollBar.cpp (62%) rename Source/UI/{ => Lists}/UIScrollBar.h (81%) rename Source/UI/{ => Lists}/UIScrollBarNavi.cpp (54%) rename Source/UI/{ => Lists}/UIScrollBarNavi.h (66%) delete mode 100644 Source/UI/NormalItemSlotLoad.h rename Source/UI/{ => Party}/UIAdvenPartyBoardWnd.cpp (86%) rename Source/UI/{ => Party}/UIAdvenPartyBoardWnd.h (85%) rename Source/UI/{ => Party}/UIApplyForPartyWnd.cpp (79%) rename Source/UI/{ => Party}/UIApplyForPartyWnd.h (72%) rename Source/UI/{ => Party}/UIPartyInfoWnd.cpp (88%) rename Source/UI/{ => Party}/UIPartyInfoWnd.h (82%) rename Source/UI/{ => Party}/UIRegisterPartyWnd.cpp (84%) rename Source/UI/{ => Party}/UIRegisterPartyWnd.h (81%) rename Source/UI/{ => Party}/UIRequestJoinPartyMgr.cpp (84%) rename Source/UI/{ => Party}/UIRequestJoinPartyMgr.h (81%) rename Source/UI/{ => Party}/UIRequestJoinPartyWnd.cpp (84%) rename Source/UI/{ => Party}/UIRequestJoinPartyWnd.h (79%) delete mode 100644 Source/UI/PixelTextWrapping.h create mode 100644 Source/UI/Shop/ItemDrawing.cpp create mode 100644 Source/UI/Shop/ItemDrawing.h rename Source/UI/{ => Shop}/MerchantShopRefresh.cpp (69%) rename Source/UI/{ => Shop}/MerchantShopRefresh.h (81%) rename Source/UI/{ => Shop}/PriceColor.cpp (95%) rename Source/UI/{ => Shop}/PriceColor.h (62%) delete mode 100644 Source/UI/ShortcutActivation.cpp delete mode 100644 Source/UI/ShortcutActivation.h delete mode 100644 Source/UI/ShortcutBindings.h delete mode 100644 Source/UI/ShortcutControls.h delete mode 100644 Source/UI/ShortcutCooldowns.h delete mode 100644 Source/UI/ShortcutDetails.h delete mode 100644 Source/UI/ShortcutGrid.h delete mode 100644 Source/UI/ShortcutPainting.h delete mode 100644 Source/UI/ShortcutPress.h delete mode 100644 Source/UI/ShortcutTooltip.h rename Source/UI/{ => Shortcuts}/NormalItemSlotLoad.cpp (83%) create mode 100644 Source/UI/Shortcuts/NormalItemSlotLoad.h create mode 100644 Source/UI/Shortcuts/ShortcutActivation.cpp create mode 100644 Source/UI/Shortcuts/ShortcutActivation.h rename Source/UI/{ => Shortcuts}/ShortcutBindings.cpp (60%) create mode 100644 Source/UI/Shortcuts/ShortcutBindings.h rename Source/UI/{ => Shortcuts}/ShortcutControlEvents.cpp (83%) rename Source/UI/{ => Shortcuts}/ShortcutControlEvents.h (62%) rename Source/UI/{ => Shortcuts}/ShortcutControls.cpp (67%) create mode 100644 Source/UI/Shortcuts/ShortcutControls.h rename Source/UI/{ => Shortcuts}/ShortcutCooldowns.cpp (69%) create mode 100644 Source/UI/Shortcuts/ShortcutCooldowns.h rename Source/UI/{ => Shortcuts}/ShortcutDetails.cpp (52%) create mode 100644 Source/UI/Shortcuts/ShortcutDetails.h rename Source/UI/{ => Shortcuts}/ShortcutDrop.cpp (77%) rename Source/UI/{ => Shortcuts}/ShortcutDrop.h (60%) rename Source/UI/{ => Shortcuts}/ShortcutGrid.cpp (81%) create mode 100644 Source/UI/Shortcuts/ShortcutGrid.h rename Source/UI/{ => Shortcuts}/ShortcutLayout.cpp (56%) rename Source/UI/{ => Shortcuts}/ShortcutLayout.h (60%) rename Source/UI/{ => Shortcuts}/ShortcutPainting.cpp (54%) create mode 100644 Source/UI/Shortcuts/ShortcutPainting.h rename Source/UI/{ => Shortcuts}/ShortcutPress.cpp (57%) create mode 100644 Source/UI/Shortcuts/ShortcutPress.h rename Source/UI/{ => Shortcuts}/ShortcutTooltip.cpp (61%) create mode 100644 Source/UI/Shortcuts/ShortcutTooltip.h rename Source/UI/{ => Shortcuts}/ShortcutUse.cpp (78%) rename Source/UI/{ => Shortcuts}/ShortcutUse.h (56%) rename Source/UI/{ => Shortcuts}/ShortcutVisibility.cpp (78%) rename Source/UI/{ => Shortcuts}/ShortcutVisibility.h (65%) rename Source/UI/{ => Shortcuts}/SkillDetailClose.cpp (65%) rename Source/UI/{ => Shortcuts}/SkillDetailClose.h (74%) rename Source/UI/{ => Shortcuts}/UIShortCutWnd.cpp (69%) rename Source/UI/{ => Shortcuts}/UIShortCutWnd.h (83%) rename Source/UI/{ => Text}/ColoredText.cpp (71%) create mode 100644 Source/UI/Text/ColoredText.h rename Source/UI/{ => Text}/ItemLinkDisplay.cpp (90%) rename Source/UI/{ => Text}/ItemLinkDisplay.h (83%) rename Source/UI/{ => Text}/NavigationLink.cpp (94%) rename Source/UI/{ => Text}/NavigationLink.h (78%) rename Source/UI/{ => Text}/PixelTextWrapping.cpp (69%) create mode 100644 Source/UI/Text/PixelTextWrapping.h rename Source/UI/{ => Text}/TextFitting.cpp (88%) rename Source/UI/{ => Text}/TextFitting.h (66%) rename Source/UI/{ => Text}/TextMarkup.cpp (89%) rename Source/UI/{ => Text}/TextMarkup.h (78%) rename Source/UI/{ => Text}/TextWrapping.cpp (86%) create mode 100644 Source/UI/Text/TextWrapping.h rename Source/UI/{ => Text}/UIBalloonText.cpp (71%) rename Source/UI/{ => Text}/UIBalloonText.h (86%) rename Source/UI/{ => Text}/UIStaticText.cpp (61%) rename Source/UI/{ => Text}/UIStaticText.h (88%) rename Source/UI/{ => Text}/UITextViewer.cpp (81%) rename Source/UI/{ => Text}/UITextViewer.h (76%) rename Source/UI/{ => Text}/UITextViewerLinks.cpp (90%) rename Source/UI/{ => Text}/UITextViewerMessages.cpp (77%) rename Source/UI/{ => Text}/UITransBalloonText.cpp (77%) rename Source/UI/{ => Text}/UITransBalloonText.h (78%) delete mode 100644 Source/UI/TextWrapping.h rename Source/UI/{ => Window}/FrameFocus.cpp (56%) rename Source/UI/{ => Window}/FrameFocus.h (68%) rename Source/UI/{ => Window}/FrameTextCache.cpp (95%) rename Source/UI/{ => Window}/FrameTextCache.h (72%) rename Source/UI/{ => Window}/InputFocus.cpp (95%) create mode 100644 Source/UI/Window/InputFocus.h rename Source/UI/{ => Window}/UIControl.cpp (98%) rename Source/UI/{ => Window}/UIControl.h (76%) rename Source/UI/{ => Window}/UIFrameWnd.cpp (64%) rename Source/UI/{ => Window}/UIFrameWnd.h (74%) rename Source/UI/{ => Window}/UIMessageBox.cpp (70%) rename Source/UI/{ => Window}/UIMessageBox.h (71%) rename Source/UI/{ => Window}/UIWindow.cpp (83%) rename Source/UI/{ => Window}/UIWindow.h (65%) rename Source/UI/{ => Window}/WindowAncestry.cpp (84%) create mode 100644 Source/UI/Window/WindowAncestry.h create mode 100644 Source/UI/Window/WindowBorder.cpp rename Source/UI/{ => Window}/WindowBorder.h (51%) rename Source/UI/{ => Window}/WindowDialogs.cpp (92%) rename Source/UI/{ => Window}/WindowDialogs.h (53%) rename Source/UI/{ => Window}/WindowFrameUpdate.cpp (78%) create mode 100644 Source/UI/Window/WindowFrameUpdate.h create mode 100644 Source/UI/Window/WindowManagerWindows.h rename Source/UI/{ => Window}/WindowMouseHit.cpp (77%) rename Source/UI/{ => Window}/WindowMouseHit.h (63%) create mode 100644 Source/UI/Window/WindowNotifications.h rename Source/UI/{ => Window}/WindowOrdering.cpp (75%) create mode 100644 Source/UI/Window/WindowOrdering.h rename Source/UI/{ => Window}/WindowPolicy.cpp (89%) create mode 100644 Source/UI/Window/WindowPolicy.h rename Source/UI/{ => Window}/WindowRegistration.cpp (90%) create mode 100644 Source/UI/Window/WindowRegistration.h rename Source/UI/{ => Window}/WindowRetirement.cpp (87%) create mode 100644 Source/UI/Window/WindowRetirement.h delete mode 100644 Source/UI/WindowAncestry.h delete mode 100644 Source/UI/WindowBorder.cpp delete mode 100644 Source/UI/WindowCoordinates.h delete mode 100644 Source/UI/WindowFrameUpdate.h delete mode 100644 Source/UI/WindowManagerWindows.h delete mode 100644 Source/UI/WindowNotifications.h delete mode 100644 Source/UI/WindowOrdering.h delete mode 100644 Source/UI/WindowPolicy.h delete mode 100644 Source/UI/WindowRegistration.h delete mode 100644 Source/UI/WindowRetirement.h rename Source/Utility/{ => Async}/AsyncDiagnostic.cpp (94%) rename Source/Utility/{ => Async}/AsyncDiagnostic.h (62%) rename Source/Utility/{ => Async}/NAsyncWork.cpp (91%) rename Source/Utility/{ => Async}/NAsyncWork.h (75%) rename Source/Utility/{ => Async}/NAsyncWorkMgr.cpp (93%) rename Source/Utility/{ => Async}/NAsyncWorkMgr.h (81%) rename Source/Utility/{ => Async}/NAsyncWorkQueue.cpp (97%) rename Source/Utility/{ => Async}/NAsyncWorkQueue.h (89%) rename Source/Utility/{ => Async}/NAsyncWorkThread.cpp (85%) rename Source/Utility/{ => Async}/NAsyncWorkThread.h (68%) rename Source/Utility/{ => Async}/NMessageMgr.cpp (92%) rename Source/Utility/{ => Async}/NMessageMgr.h (89%) rename Source/Utility/{ => Async}/NMessageQueue.cpp (84%) rename Source/Utility/{ => Async}/NMessageQueue.h (76%) rename Source/Utility/{ => Async}/NObject.cpp (89%) rename Source/Utility/{ => Async}/NObject.h (58%) rename Source/Utility/{ => Async}/NRecycleObject.cpp (88%) rename Source/Utility/{ => Async}/NRecycleObject.h (84%) rename Source/Utility/{ => Async}/NRecycleObjectPoolMgr.cpp (86%) rename Source/Utility/{ => Async}/NRecycleObjectPoolMgr.h (58%) delete mode 100644 Source/Utility/GroupedInteger.h delete mode 100644 Source/Utility/LanguageCharset.cpp rename Source/Utility/{ => Math}/AffineLookAt.cpp (94%) rename Source/Utility/{ => Math}/AffineMatrix.cpp (90%) rename Source/Utility/{ => Math}/AffineMatrix.h (77%) rename Source/Utility/{ => Math}/ClientAngles.cpp (87%) rename Source/Utility/{ => Math}/RayTriangle.cpp (88%) create mode 100644 Source/Utility/Math/RayTriangle.h create mode 100644 Source/Utility/Math/ScalarConversion.h delete mode 100644 Source/Utility/RayTriangle.h rename Source/Utility/{ => Text}/FormatString.cpp (94%) rename Source/Utility/{ => Text}/FormatString.h (63%) rename Source/Utility/{ => Text}/GroupedInteger.cpp (89%) create mode 100644 Source/Utility/Text/GroupedInteger.h create mode 100644 Source/Utility/Text/LanguageCharset.cpp rename Source/Utility/{ => Text}/LanguageCharset.h (54%) rename Source/Utility/{ => Threading}/CSyncObject.cpp (86%) rename Source/Utility/{ => Threading}/CSyncObject.h (61%) rename Source/Utility/{ => Threading}/NSyncObject.cpp (89%) rename Source/Utility/{ => Threading}/NSyncObject.h (62%) rename Source/Utility/{ => Threading}/NThread.cpp (76%) rename Source/Utility/{ => Threading}/NThread.h (80%) diff --git a/.clang-format b/.clang-format index 3c3b030..9c893cf 100644 --- a/.clang-format +++ b/.clang-format @@ -1,45 +1,33 @@ -BasedOnStyle: LLVM -IndentWidth: 2 -NamespaceIndentation: All -FixNamespaceComments: false -TabWidth: 2 -UseTab: Never -ColumnLimit: 120 -AlignAfterOpenBracket: BlockIndent -ContinuationIndentWidth: 2 -AlwaysBreakAfterReturnType: None -BreakBeforeBraces: Custom -BraceWrapping: - AfterFunction: false -AllowShortIfStatementsOnASingleLine: Never -InsertBraces: true -AllowShortLoopsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortBlocksOnASingleLine: Never -SpacesInParentheses: false -SpaceBeforeParens: Custom -SpaceBeforeParensOptions: - AfterControlStatements: true - AfterFunctionDefinitionName: false -BinPackParameters: false -AllowAllParametersOfDeclarationOnNextLine: false -PenaltyBreakBeforeFirstCallParameter: 0 -PointerAlignment: Left -# Include sorting: -# 1. pch (must stay first) 2. other WoW.exe project headers -# 3. generated gen/ headers 4. system <...> headers -# Each group is alphabetised; Regroup re-buckets across blank lines. -# IncludeIsMainRegex is set to never match so no header is auto-pinned above pch -# (clang-format otherwise forces the "main" header to the very top). -SortIncludes: CaseSensitive -IncludeBlocks: Regroup -IncludeIsMainRegex: "(WILL_NEVER_MATCH_zzz)$" -IncludeCategories: - - Regex: '^"pch(-impl)?\.h"' - Priority: 1 - - Regex: '^"gen/' - Priority: 3 - - Regex: '^<' - Priority: 4 - - Regex: '^"' - Priority: 2 +BasedOnStyle: LLVM +IndentWidth: 2 +NamespaceIndentation: All +FixNamespaceComments: false +TabWidth: 2 +UseTab: Never +ColumnLimit: 160 +AlignAfterOpenBracket: BlockIndent +ContinuationIndentWidth: 2 +AlwaysBreakAfterReturnType: None +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: false +AllowShortIfStatementsOnASingleLine: Never +InsertBraces: false +AllowShortLoopsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortBlocksOnASingleLine: Never +SpacesInParentheses: false +SpaceBeforeParens: Custom +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterFunctionDefinitionName: false +BinPackArguments: true +BinPackParameters: BinPack +AllowAllParametersOfDeclarationOnNextLine: true +PenaltyBreakBeforeFirstCallParameter: 19 +PointerAlignment: Left +BreakStringLiterals: false +ReflowComments: Never +MaxEmptyLinesToKeep: 1 +SortIncludes: Never +IncludeBlocks: Preserve diff --git a/CMakeLists.txt b/CMakeLists.txt index 1be93fb..6b39769 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,12 +10,12 @@ add_subdirectory(ThirdParty) add_library(RagnarokUtility STATIC Source/Utility/XorBytes.cpp Source/Utility/Base64.cpp - Source/Utility/GroupedInteger.cpp - Source/Utility/LanguageCharset.cpp - Source/Utility/ClientAngles.cpp - Source/Utility/AffineMatrix.cpp - Source/Utility/AffineLookAt.cpp - Source/Utility/RayTriangle.cpp + Source/Utility/Text/GroupedInteger.cpp + Source/Utility/Text/LanguageCharset.cpp + Source/Utility/Math/ClientAngles.cpp + Source/Utility/Math/AffineMatrix.cpp + Source/Utility/Math/AffineLookAt.cpp + Source/Utility/Math/RayTriangle.cpp Source/Utility/Rijndael.cpp ) @@ -28,21 +28,21 @@ set_target_properties(RagnarokUtility PROPERTIES CXX_EXTENSIONS OFF) if(WIN32) target_sources(RagnarokUtility PRIVATE Source/Utility/GuidParse.cpp - Source/Utility/NSyncObject.cpp - Source/Utility/CSyncObject.cpp - Source/Utility/NThread.cpp - Source/Utility/NMessageQueue.cpp - Source/Utility/NMessageMgr.cpp - Source/Utility/NObject.cpp - Source/Utility/NRecycleObject.cpp - Source/Utility/NRecycleObjectPoolMgr.cpp - Source/Utility/NAsyncWork.cpp - Source/Utility/NAsyncWorkQueue.cpp - Source/Utility/NAsyncWorkThread.cpp - Source/Utility/NAsyncWorkMgr.cpp - Source/Utility/AsyncDiagnostic.cpp + Source/Utility/Threading/NSyncObject.cpp + Source/Utility/Threading/CSyncObject.cpp + Source/Utility/Threading/NThread.cpp + Source/Utility/Async/NMessageQueue.cpp + Source/Utility/Async/NMessageMgr.cpp + Source/Utility/Async/NObject.cpp + Source/Utility/Async/NRecycleObject.cpp + Source/Utility/Async/NRecycleObjectPoolMgr.cpp + Source/Utility/Async/NAsyncWork.cpp + Source/Utility/Async/NAsyncWorkQueue.cpp + Source/Utility/Async/NAsyncWorkThread.cpp + Source/Utility/Async/NAsyncWorkMgr.cpp + Source/Utility/Async/AsyncDiagnostic.cpp Source/Contents/InstantVar.cpp - Source/Utility/FormatString.cpp + Source/Utility/Text/FormatString.cpp ) target_compile_definitions(RagnarokUtility PUBLIC WIN32_LEAN_AND_MEAN NOMINMAX _ITERATOR_DEBUG_LEVEL=0 @@ -69,31 +69,32 @@ if(WIN32) set_target_properties(RagnarokArchive PROPERTIES CXX_EXTENSIONS OFF) add_library(RagnarokClientStartup STATIC - Source/Client/Launcher.cpp - Source/Client/ApplicationWindow.cpp - Source/Client/ErrorDialog.cpp - Source/Client/UnhandledExceptionHandler.cpp - Source/Client/ModeCursor.cpp - Source/Client/Mouse.cpp + Source/Client/Application/Launcher.cpp + Source/Client/Application/ApplicationWindow.cpp + Source/Client/Application/ErrorDialog.cpp + Source/Client/Application/UnhandledExceptionHandler.cpp + Source/Client/Mode/ModeCursor.cpp + Source/Client/Mode/ActiveGameMode.cpp + Source/Client/Input/Mouse.cpp Source/Client/ClientOptions.cpp - Source/Client/TextInputBuffer.cpp - Source/Client/ImeInput.cpp - Source/Client/TraditionalKeyInput.cpp - Source/Client/InputCharset.cpp - Source/Client/BrowserWindowSizing.cpp - Source/Client/BrowserInterface.cpp - Source/Client/BrowserCursor.cpp - Source/Client/BrowserAddressEdit.cpp - Source/Client/BrowserHostWindow.cpp - Source/Client/BrowserCommandTarget.cpp - Source/Client/BrowserInPlace.cpp - Source/Client/BrowserDocumentUI.cpp - Source/Client/BrowserClientSite.cpp - Source/Client/BrowserAddressBar.cpp - Source/Client/BrowserFrame.cpp - Source/Client/BrowserSiteAttachment.cpp - Source/Client/BrowserClose.cpp - Source/Client/BrowserCreation.cpp + Source/Client/Input/TextInputBuffer.cpp + Source/Client/Input/ImeInput.cpp + Source/Client/Input/TraditionalKeyInput.cpp + Source/Client/Input/InputCharset.cpp + Source/Client/Browser/BrowserWindowSizing.cpp + Source/Client/Browser/BrowserInterface.cpp + Source/Client/Browser/BrowserCursor.cpp + Source/Client/Browser/BrowserAddressEdit.cpp + Source/Client/Browser/BrowserHostWindow.cpp + Source/Client/Browser/BrowserCommandTarget.cpp + Source/Client/Browser/BrowserInPlace.cpp + Source/Client/Browser/BrowserDocumentUI.cpp + Source/Client/Browser/BrowserClientSite.cpp + Source/Client/Browser/BrowserAddressBar.cpp + Source/Client/Browser/BrowserFrame.cpp + Source/Client/Browser/BrowserSiteAttachment.cpp + Source/Client/Browser/BrowserClose.cpp + Source/Client/Browser/BrowserCreation.cpp ) target_include_directories(RagnarokClientStartup PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/Source" @@ -104,74 +105,74 @@ if(WIN32) set_target_properties(RagnarokClientStartup PROPERTIES CXX_EXTENSIONS OFF) add_library(RagnarokRender STATIC - Source/Render/RenderPrimitive.cpp - Source/Render/RenderPrimitivePool.cpp - Source/Render/RenderCommandPool.cpp - Source/Render/LightmappedPrimitive.cpp - Source/Render/DepthAlpha.cpp - Source/Render/RenderVertexPool.cpp - Source/Render/RenderProjection.cpp - Source/Render/RendererViewport.cpp - Source/Render/RenderRay.cpp - Source/Render/BitmapPixels.cpp - Source/Render/Surface.cpp - Source/Render/RenderQueues.cpp - Source/Render/Texture.cpp - Source/Render/UIRPData.cpp - Source/Render/SurfaceDX9.cpp - Source/Render/SurfaceDX7.cpp - Source/Render/D3DX9Runtime.cpp - Source/Render/TextureDX9.cpp - Source/Render/TextureDX7.cpp - Source/Render/TextureBindingDX7.cpp - Source/Render/TextureAllocationDX7.cpp - Source/Render/BitmapTextureCache.cpp - Source/Render/SpriteAtlas.cpp - Source/Render/DeviceContext.cpp - Source/Render/DCBitmap.cpp - Source/Render/DCSurface.cpp - Source/Render/DeviceStateDX9.cpp - Source/Render/DeviceOwnerDX9.cpp - Source/Render/DeviceOwnerDX7.cpp - Source/Render/DeviceCapabilitiesDX7.cpp - Source/Render/TextureCalibrationDX7.cpp + Source/Render/Primitives/RenderPrimitive.cpp + Source/Render/Primitives/RenderPrimitivePool.cpp + Source/Render/Primitives/RenderCommandPool.cpp + Source/Render/Primitives/LightmappedPrimitive.cpp + Source/Render/Primitives/DepthAlpha.cpp + Source/Render/Primitives/RenderVertexPool.cpp + Source/Render/Projection/RenderProjection.cpp + Source/Render/Projection/RendererViewport.cpp + Source/Render/Projection/RenderRay.cpp + Source/Render/Textures/BitmapPixels.cpp + Source/Render/Textures/Surface.cpp + Source/Render/Primitives/RenderQueues.cpp + Source/Render/Textures/Texture.cpp + Source/Render/Primitives/UIRPData.cpp + Source/Render/DX9/SurfaceDX9.cpp + Source/Render/DX7/SurfaceDX7.cpp + Source/Render/DX9/D3DX9Runtime.cpp + Source/Render/DX9/TextureDX9.cpp + Source/Render/DX7/TextureDX7.cpp + Source/Render/DX7/TextureBindingDX7.cpp + Source/Render/DX7/TextureAllocationDX7.cpp + Source/Render/Textures/BitmapTextureCache.cpp + Source/Render/Textures/SpriteAtlas.cpp + Source/Render/DeviceContext/DeviceContext.cpp + Source/Render/DeviceContext/DCBitmap.cpp + Source/Render/DeviceContext/DCSurface.cpp + Source/Render/DX9/DeviceStateDX9.cpp + Source/Render/DX9/DeviceOwnerDX9.cpp + Source/Render/DX7/DeviceOwnerDX7.cpp + Source/Render/DX7/DeviceCapabilitiesDX7.cpp + Source/Render/DX7/TextureCalibrationDX7.cpp Source/Render/RenderAdapter.cpp - Source/Render/RenderAdapterDX7.cpp + Source/Render/DX7/RenderAdapterDX7.cpp Source/Render/RenderBackends.cpp Source/Render/DisplayMode.cpp - Source/Render/DisplayModeDX7.cpp - Source/Render/DirectDrawEnumeration.cpp - Source/Render/DeviceRecoveryDX9.cpp - Source/Render/BackBufferDX9.cpp - Source/Render/BackBufferDX7.cpp + Source/Render/DX7/DisplayModeDX7.cpp + Source/Render/DX7/DirectDrawEnumeration.cpp + Source/Render/DX9/DeviceRecoveryDX9.cpp + Source/Render/DX9/BackBufferDX9.cpp + Source/Render/DX7/BackBufferDX7.cpp Source/Render/Direct3DErrors.cpp - Source/Render/RendererBackBuffer.cpp + Source/Render/DX9/RendererBackBuffer.cpp Source/Render/Renderer.cpp - Source/Render/RendererDX9.cpp - Source/Render/RenderSystemDX7.cpp - Source/Render/RenderSystemDX9.cpp - Source/Render/RendererDX9Operations.cpp - Source/Render/RendererDX7Operations.cpp - Source/Render/RenderToTextureDX7.cpp - Source/Render/TextureModesDX9.cpp - Source/Render/TextureModesDX7.cpp + Source/Render/DX9/RendererDX9.cpp + Source/Render/DX7/RenderSystemDX7.cpp + Source/Render/DX9/RenderSystemDX9.cpp + Source/Render/DX9/RendererDX9Operations.cpp + Source/Render/DX7/RendererDX7Operations.cpp + Source/Render/DX7/RenderToTextureDX7.cpp + Source/Render/DX9/TextureModesDX9.cpp + Source/Render/DX7/TextureModesDX7.cpp Source/Render/TextureStageModes.cpp - Source/Render/RendererFogDX9.cpp - Source/Render/RendererFogDX7.cpp - Source/Render/OpaqueQueuesDX9.cpp - Source/Render/GroundQueuesDX9.cpp - Source/Render/AlphaQueuesDX9.cpp - Source/Render/QueuedDrawingDX9.cpp - Source/Render/RendererFrameDX9.cpp - Source/Render/ScreenshotDX9.cpp - Source/Render/ScreenshotDX7.cpp - Source/Contents/Effect.cpp - Source/Contents/EffectLists.cpp + Source/Render/DX9/RendererFogDX9.cpp + Source/Render/DX7/RendererFogDX7.cpp + Source/Render/DX9/OpaqueQueuesDX9.cpp + Source/Render/DX9/GroundQueuesDX9.cpp + Source/Render/DX9/AlphaQueuesDX9.cpp + Source/Render/DX9/QueuedDrawingDX9.cpp + Source/Render/DX9/RendererFrameDX9.cpp + Source/Render/DX9/ScreenshotDX9.cpp + Source/Render/DX7/ScreenshotDX7.cpp + Source/Contents/Effects/Effect.cpp + Source/Contents/Effects/EffectLists.cpp Source/Render/BlendColor.cpp - Source/Render/RendererPresentation.cpp - Source/Render/RendererPresentationDX7.cpp - Source/Render/FontCache.cpp - Source/Render/TextContext.cpp + Source/Render/DX9/RendererPresentation.cpp + Source/Render/DX7/RendererPresentationDX7.cpp + Source/Render/Text/FontCache.cpp + Source/Render/Text/TextContext.cpp ) target_include_directories(RagnarokRender PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/Source") target_compile_features(RagnarokRender PUBLIC cxx_std_20) @@ -180,116 +181,116 @@ if(WIN32) target_link_libraries(RagnarokRender PUBLIC gdi32 winmm gdiplus d3d9 ddraw dxguid) add_library(RagnarokUI STATIC - Source/UI/WindowGeometry.cpp - Source/UI/WindowCoordinates.cpp - Source/UI/WindowAncestry.cpp - Source/UI/WindowRegistration.cpp - Source/UI/WindowRetirement.cpp - Source/UI/WindowOrdering.cpp - Source/UI/WindowMouseHit.cpp - Source/UI/UIWindow.cpp - Source/UI/UIControl.cpp - Source/UI/UIDropDownBox.cpp - Source/UI/ChatSuggestions.cpp - Source/UI/ItemTagRetirement.cpp - Source/UI/SnapRectangle.cpp - Source/UI/SnapObject.cpp - Source/UI/SnapMgr.cpp - Source/UI/WindowSnapping.cpp - Source/UI/FrameTextCache.cpp - Source/UI/FrameFocus.cpp - Source/UI/InputFocus.cpp - Source/UI/UIFrameWnd.cpp - Source/UI/ShortcutGrid.cpp - Source/UI/WindowPolicy.cpp - Source/UI/UIButton.cpp - Source/UI/UIBasicButton.cpp - Source/UI/UITextButton.cpp - Source/UI/UINaviLinkButton.cpp - Source/UI/UIEditCtrl.cpp - Source/UI/UIEditVariants.cpp - Source/UI/UIEditLinks.cpp - Source/UI/UIBitmapButton.cpp - Source/UI/UIBmpTextButton.cpp - Source/UI/UIJobSlotButton.cpp - Source/UI/UIPartyInfoWnd.cpp - Source/UI/UIAdvenPartyBoardWnd.cpp - Source/UI/UIApplyForPartyWnd.cpp - Source/UI/UIRegisterPartyWnd.cpp - Source/UI/UIRequestJoinPartyMgr.cpp - Source/UI/UIRequestJoinPartyWnd.cpp - Source/UI/UIChooseSellBuyWnd.cpp - Source/UI/UIExchangeAcceptWnd.cpp - Source/UI/UIJoinPartyAcceptWnd.cpp - Source/Network/PartyJoinRequest.cpp - Source/UI/UICheckBox.cpp - Source/UI/UIScrollBar.cpp - Source/UI/UIScrollBarNavi.cpp - Source/UI/UIListBox.cpp - Source/UI/UIListBoxEx.cpp - Source/UI/UIComboBoxEx.cpp - Source/UI/UIComboBoxDefWnd.cpp - Source/UI/TextMarkup.cpp - Source/UI/PixelTextWrapping.cpp - Source/UI/ItemLinkDisplay.cpp - Source/UI/UITextViewer.cpp - Source/UI/UITextViewerLinks.cpp - Source/UI/UITextViewerMessages.cpp + Source/UI/Layout/WindowGeometry.cpp + Source/UI/Layout/WindowCoordinates.cpp + Source/UI/Window/WindowAncestry.cpp + Source/UI/Window/WindowRegistration.cpp + Source/UI/Window/WindowRetirement.cpp + Source/UI/Window/WindowOrdering.cpp + Source/UI/Window/WindowMouseHit.cpp + Source/UI/Window/UIWindow.cpp + Source/UI/Window/UIControl.cpp + Source/UI/Lists/UIDropDownBox.cpp + Source/UI/Chat/ChatSuggestions.cpp + Source/UI/Edit/ItemTagRetirement.cpp + Source/UI/Layout/SnapRectangle.cpp + Source/UI/Layout/SnapObject.cpp + Source/UI/Layout/SnapMgr.cpp + Source/UI/Layout/WindowSnapping.cpp + Source/UI/Window/FrameTextCache.cpp + Source/UI/Window/FrameFocus.cpp + Source/UI/Window/InputFocus.cpp + Source/UI/Window/UIFrameWnd.cpp + Source/UI/Shortcuts/ShortcutGrid.cpp + Source/UI/Window/WindowPolicy.cpp + Source/UI/Buttons/UIButton.cpp + Source/UI/Buttons/UIBasicButton.cpp + Source/UI/Buttons/UITextButton.cpp + Source/UI/Buttons/UINaviLinkButton.cpp + Source/UI/Edit/UIEditCtrl.cpp + Source/UI/Edit/UIEditVariants.cpp + Source/UI/Edit/UIEditLinks.cpp + Source/UI/Buttons/UIBitmapButton.cpp + Source/UI/Buttons/UIBmpTextButton.cpp + Source/UI/Buttons/UIJobSlotButton.cpp + Source/UI/Party/UIPartyInfoWnd.cpp + Source/UI/Party/UIAdvenPartyBoardWnd.cpp + Source/UI/Party/UIApplyForPartyWnd.cpp + Source/UI/Party/UIRegisterPartyWnd.cpp + Source/UI/Party/UIRequestJoinPartyMgr.cpp + Source/UI/Party/UIRequestJoinPartyWnd.cpp + Source/UI/Acceptance/UIChooseSellBuyWnd.cpp + Source/UI/Acceptance/UIExchangeAcceptWnd.cpp + Source/UI/Acceptance/UIJoinPartyAcceptWnd.cpp + Source/Network/Packets/PartyJoinRequest.cpp + Source/UI/Buttons/UICheckBox.cpp + Source/UI/Lists/UIScrollBar.cpp + Source/UI/Lists/UIScrollBarNavi.cpp + Source/UI/Lists/UIListBox.cpp + Source/UI/Lists/UIListBoxEx.cpp + Source/UI/Lists/UIComboBoxEx.cpp + Source/UI/Lists/UIComboBoxDefWnd.cpp + Source/UI/Text/TextMarkup.cpp + Source/UI/Text/PixelTextWrapping.cpp + Source/UI/Text/ItemLinkDisplay.cpp + Source/UI/Text/UITextViewer.cpp + Source/UI/Text/UITextViewerLinks.cpp + Source/UI/Text/UITextViewerMessages.cpp Source/UI/UIStaticBitmap.cpp - Source/UI/UIStaticText.cpp - Source/UI/UIMessageBox.cpp - Source/UI/WindowDialogs.cpp + Source/UI/Text/UIStaticText.cpp + Source/UI/Window/UIMessageBox.cpp + Source/UI/Window/WindowDialogs.cpp Source/Client/ReplayPacketRecorder.cpp - Source/UI/CooldownState.cpp - Source/UI/CooldownDrawing.cpp - Source/UI/CooldownOwner.cpp - Source/UI/ShortcutCooldowns.cpp - Source/UI/ItemDrawing.cpp - Source/UI/ShortcutPainting.cpp - Source/UI/ShortcutBindings.cpp - Source/UI/ShortcutLayout.cpp - Source/UI/ShortcutActivation.cpp - Source/UI/ShortcutControls.cpp - Source/UI/ShortcutControlEvents.cpp - Source/UI/ShortcutTooltip.cpp - Source/UI/ShortcutPress.cpp - Source/UI/ShortcutDrop.cpp - Source/UI/ShortcutUse.cpp - Source/UI/ShortcutVisibility.cpp - Source/UI/ShortcutDetails.cpp - Source/UI/SkillDetailClose.cpp - Source/UI/NormalItemSlotLoad.cpp - Source/UI/UIShortCutWnd.cpp - Source/UI/TextWrapping.cpp - Source/UI/ChatNotifications.cpp - Source/UI/BrowserFactory.cpp - Source/UI/BrowserPopupDispatch.cpp - Source/UI/WindowFrameUpdate.cpp - Source/UI/UIBalloonText.cpp - Source/UI/UITransBalloonText.cpp - Source/UI/ColoredText.cpp - Source/UI/WindowBorder.cpp - Source/UI/EditTextState.cpp - Source/UI/EditViewport.cpp - Source/UI/EditPainting.cpp - Source/UI/PriceColor.cpp - Source/UI/MerchantShopRefresh.cpp - Source/UI/NavigationLink.cpp - Source/UI/TextFitting.cpp - Source/Client/ModeDragState.cpp - Source/Client/ModeTooltip.cpp - Source/Contents/CharacterConfigLoad.cpp - Source/Contents/CharacterLinkedUserDataLoadAsyncWork.cpp - Source/Contents/EmblemCache.cpp - Source/Contents/EmblemUpload.cpp - Source/Contents/ChangePartyMasterCompletion.cpp - Source/Contents/PartyListCompletion.cpp - Source/Contents/StopRecruitingCompletion.cpp - Source/Contents/MyPartyCompletion.cpp - Source/Contents/PartyRegistrationCompletion.cpp - Source/Contents/PartyInfoCompletion.cpp - Source/Contents/PartyJoinResult.cpp - Source/Contents/PartyInvitation.cpp + Source/UI/Cooldowns/CooldownState.cpp + Source/UI/Cooldowns/CooldownDrawing.cpp + Source/UI/Cooldowns/CooldownOwner.cpp + Source/UI/Shortcuts/ShortcutCooldowns.cpp + Source/UI/Shop/ItemDrawing.cpp + Source/UI/Shortcuts/ShortcutPainting.cpp + Source/UI/Shortcuts/ShortcutBindings.cpp + Source/UI/Shortcuts/ShortcutLayout.cpp + Source/UI/Shortcuts/ShortcutActivation.cpp + Source/UI/Shortcuts/ShortcutControls.cpp + Source/UI/Shortcuts/ShortcutControlEvents.cpp + Source/UI/Shortcuts/ShortcutTooltip.cpp + Source/UI/Shortcuts/ShortcutPress.cpp + Source/UI/Shortcuts/ShortcutDrop.cpp + Source/UI/Shortcuts/ShortcutUse.cpp + Source/UI/Shortcuts/ShortcutVisibility.cpp + Source/UI/Shortcuts/ShortcutDetails.cpp + Source/UI/Shortcuts/SkillDetailClose.cpp + Source/UI/Shortcuts/NormalItemSlotLoad.cpp + Source/UI/Shortcuts/UIShortCutWnd.cpp + Source/UI/Text/TextWrapping.cpp + Source/UI/Chat/ChatNotifications.cpp + Source/Client/Browser/BrowserFactory.cpp + Source/Client/Browser/BrowserPopupDispatch.cpp + Source/UI/Window/WindowFrameUpdate.cpp + Source/UI/Text/UIBalloonText.cpp + Source/UI/Text/UITransBalloonText.cpp + Source/UI/Text/ColoredText.cpp + Source/UI/Window/WindowBorder.cpp + Source/UI/Edit/EditTextState.cpp + Source/UI/Edit/EditViewport.cpp + Source/UI/Edit/EditPainting.cpp + Source/UI/Shop/PriceColor.cpp + Source/UI/Shop/MerchantShopRefresh.cpp + Source/UI/Text/NavigationLink.cpp + Source/UI/Text/TextFitting.cpp + Source/Client/Mode/ModeDragState.cpp + Source/Client/Mode/ModeTooltip.cpp + Source/Contents/UserData/CharacterConfigLoad.cpp + Source/Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.cpp + Source/Contents/Emblems/EmblemCache.cpp + Source/Contents/Emblems/EmblemUpload.cpp + Source/Contents/Party/ChangePartyMasterCompletion.cpp + Source/Contents/Party/PartyListCompletion.cpp + Source/Contents/Party/StopRecruitingCompletion.cpp + Source/Contents/Party/MyPartyCompletion.cpp + Source/Contents/Party/PartyRegistrationCompletion.cpp + Source/Contents/Party/PartyInfoCompletion.cpp + Source/Contents/Party/PartyJoinResult.cpp + Source/Contents/Party/PartyInvitation.cpp ) target_include_directories(RagnarokUI PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/Source") target_compile_features(RagnarokUI PUBLIC cxx_std_20) @@ -310,68 +311,68 @@ if(WIN32) add_library(RagnarokResource STATIC Source/Resource/ResourceAliases.cpp - Source/Resource/BitmapImage.cpp - Source/Resource/BitmapImagePng.cpp - Source/Resource/BitmapImageJpeg.cpp - Source/Resource/IJL15Runtime.cpp - Source/Resource/MilesRuntime.cpp - Source/Resource/WaveResource.cpp + Source/Resource/Bitmap/BitmapImage.cpp + Source/Resource/Bitmap/BitmapImagePng.cpp + Source/Resource/Bitmap/BitmapImageJpeg.cpp + Source/Resource/Bitmap/IJL15Runtime.cpp + Source/Resource/Audio/MilesRuntime.cpp + Source/Resource/Audio/WaveResource.cpp Source/Resource/Resource.cpp - Source/Resource/BitmapResource.cpp - Source/Resource/SpriteResource.cpp - Source/Resource/SpriteEncoding.cpp - Source/Resource/ActionResource.cpp - Source/Resource/TerrainResource.cpp - Source/Resource/GroundResource.cpp - Source/Resource/WorldResource.cpp - Source/Resource/WorldEnvironment.cpp - Source/Resource/WorldObjects.cpp - Source/Resource/ModelMesh.cpp - Source/Resource/ModelResource.cpp - Source/Resource/ModelNodeLoading.cpp - Source/Resource/ModelResourceV2.cpp - Source/Resource/ModelNodeLoadingV2.cpp - Source/Resource/AnimatedModelResource.cpp - Source/Contents/ModelAnimation.cpp - Source/Contents/ModelQuaternion.cpp - Source/Contents/ModelNode.cpp - Source/Contents/ModelTextureAnimation.cpp - Source/Contents/ModelRendering.cpp - Source/Contents/ModelTextureUV.cpp - Source/Contents/ModelLighting.cpp - Source/Contents/ModelNodeBounds.cpp - Source/Contents/ModelActor.cpp - Source/Contents/ModelActorBounds.cpp - Source/Contents/ModelPlayback.cpp - Source/Contents/ModelOcclusion.cpp - Source/Contents/ModelMovies.cpp - Source/Contents/WorldModelPlacement.cpp - Source/Contents/WorldModelLoading.cpp - Source/Contents/WorldGroundImport.cpp - Source/Contents/WorldEnvironment.cpp - Source/Contents/WorldSpatialTree.cpp - Source/Contents/WorldSpatialInitialization.cpp - Source/Contents/WorldRayQuery.cpp - Source/Contents/WorldOcclusion.cpp - Source/Contents/WorldModelView.cpp - Source/Contents/WorldViewSpatial.cpp - Source/Contents/CameraSmoothing.cpp - Source/Contents/CameraShake.cpp - Source/Contents/CameraFrame.cpp - Source/Contents/CameraQueries.cpp - Source/Contents/ModelSpatial.cpp - Source/Contents/GroundSpatial.cpp - Source/Contents/GroundGeometry.cpp - Source/Contents/GroundLightmaps.cpp - Source/Contents/GroundRendering.cpp - Source/Contents/GroundPicking.cpp - Source/Contents/GroundDecals.cpp - Source/Contents/GroundWaterState.cpp - Source/Contents/GroundWaterRendering.cpp - Source/Contents/GroundLighting.cpp - Source/Contents/GroundSamples.cpp - Source/Contents/GroundLightingInitialization.cpp - Source/Render/TextureCache.cpp + Source/Resource/Bitmap/BitmapResource.cpp + Source/Resource/Sprites/SpriteResource.cpp + Source/Resource/Sprites/SpriteEncoding.cpp + Source/Resource/Sprites/ActionResource.cpp + Source/Resource/World/TerrainResource.cpp + Source/Resource/World/GroundResource.cpp + Source/Resource/World/WorldResource.cpp + Source/Resource/World/WorldEnvironment.cpp + Source/Resource/World/WorldObjects.cpp + Source/Resource/Models/ModelMesh.cpp + Source/Resource/Models/ModelResource.cpp + Source/Resource/Models/ModelNodeLoading.cpp + Source/Resource/Models/ModelResourceV2.cpp + Source/Resource/Models/ModelNodeLoadingV2.cpp + Source/Resource/Models/AnimatedModelResource.cpp + Source/Contents/Models/ModelAnimation.cpp + Source/Contents/Models/ModelQuaternion.cpp + Source/Contents/Models/ModelNode.cpp + Source/Contents/Models/ModelTextureAnimation.cpp + Source/Contents/Models/ModelRendering.cpp + Source/Contents/Models/ModelTextureUV.cpp + Source/Contents/Models/ModelLighting.cpp + Source/Contents/Models/ModelNodeBounds.cpp + Source/Contents/Models/ModelActor.cpp + Source/Contents/Models/ModelActorBounds.cpp + Source/Contents/Models/ModelPlayback.cpp + Source/Contents/Models/ModelOcclusion.cpp + Source/Contents/Models/ModelMovies.cpp + Source/Contents/World/WorldModelPlacement.cpp + Source/Contents/World/WorldModelLoading.cpp + Source/Contents/World/WorldGroundImport.cpp + Source/Contents/World/WorldEnvironment.cpp + Source/Contents/World/WorldSpatialTree.cpp + Source/Contents/World/WorldSpatialInitialization.cpp + Source/Contents/World/WorldRayQuery.cpp + Source/Contents/World/WorldOcclusion.cpp + Source/Contents/World/WorldModelView.cpp + Source/Contents/World/WorldViewSpatial.cpp + Source/Contents/Camera/CameraSmoothing.cpp + Source/Contents/Camera/CameraShake.cpp + Source/Contents/Camera/CameraFrame.cpp + Source/Contents/Camera/CameraQueries.cpp + Source/Contents/Models/ModelSpatial.cpp + Source/Contents/Ground/GroundSpatial.cpp + Source/Contents/Ground/GroundGeometry.cpp + Source/Contents/Ground/GroundLightmaps.cpp + Source/Contents/Ground/GroundRendering.cpp + Source/Contents/Ground/GroundPicking.cpp + Source/Contents/Ground/GroundDecals.cpp + Source/Contents/Ground/GroundWaterState.cpp + Source/Contents/Ground/GroundWaterRendering.cpp + Source/Contents/Ground/GroundLighting.cpp + Source/Contents/Ground/GroundSamples.cpp + Source/Contents/Ground/GroundLightingInitialization.cpp + Source/Render/Textures/TextureCache.cpp Source/Resource/EZeffectResource.cpp Source/Resource/ResourceMgr.cpp Source/Resource/ResourceFailures.cpp @@ -379,9 +380,9 @@ if(WIN32) Source/Resource/TextureNames.cpp Source/Contents/SkinInfo.cpp Source/Resource/BinkRuntime.cpp - Source/Contents/BinkMovie.cpp - Source/Contents/BinkMovies.cpp - Source/Render/ClientTextureSources.cpp + Source/Contents/Movies/BinkMovie.cpp + Source/Contents/Movies/BinkMovies.cpp + Source/Render/Textures/ClientTextureSources.cpp ) target_include_directories(RagnarokResource PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/Source") target_compile_features(RagnarokResource PUBLIC cxx_std_20) @@ -390,15 +391,15 @@ if(WIN32) set_target_properties(RagnarokResource PROPERTIES CXX_EXTENSIONS OFF) add_library(RagnarokNetwork STATIC - Source/Network/CURLMgr.cpp - Source/Network/CURLPostHander.cpp + Source/Network/Http/CURLMgr.cpp + Source/Network/Http/CURLPostHander.cpp Source/Network/TextEncoding.cpp - Source/Network/ConnectionBuffer.cpp - Source/Network/Connection.cpp - Source/Network/PacketLengths.cpp - Source/Network/ConnectionRuntime.cpp - Source/Network/ShortcutPacket.cpp - Source/Network/PartyJoinPacket.cpp + Source/Network/Connection/ConnectionBuffer.cpp + Source/Network/Connection/Connection.cpp + Source/Network/Packets/PacketLengths.cpp + Source/Network/Connection/ConnectionRuntime.cpp + Source/Network/Packets/ShortcutPacket.cpp + Source/Network/Packets/PartyJoinPacket.cpp ) target_include_directories(RagnarokNetwork PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/Source") target_compile_features(RagnarokNetwork PUBLIC cxx_std_20) @@ -406,104 +407,104 @@ if(WIN32) set_target_properties(RagnarokNetwork PROPERTIES CXX_EXTENSIONS OFF) add_library(RagnarokContents STATIC - Source/Contents/WhisperBlockMgr.cpp + Source/Contents/Messenger/WhisperBlockMgr.cpp Source/Contents/CashEmotionMgr.cpp - Source/Contents/AccountUserData.cpp - Source/Contents/EmotionHotkeys.cpp - Source/Contents/UserHotkeyScript.cpp - Source/Contents/UserHotkeyMgr.cpp - Source/Contents/AccountLinkedUserDataMgr.cpp - Source/Contents/AccountService.cpp - Source/Contents/ScriptOptions.cpp - Source/Contents/GraphicsConfiguration.cpp - Source/Contents/SoundConfiguration.cpp - Source/Contents/SoundMgr.cpp - Source/Contents/OptionWriter.cpp + Source/Contents/UserData/AccountUserData.cpp + Source/Contents/Hotkeys/EmotionHotkeys.cpp + Source/Contents/Hotkeys/UserHotkeyScript.cpp + Source/Contents/Hotkeys/UserHotkeyMgr.cpp + Source/Contents/UserData/AccountLinkedUserDataMgr.cpp + Source/Contents/UserData/AccountService.cpp + Source/Contents/Configuration/ScriptOptions.cpp + Source/Contents/Configuration/GraphicsConfiguration.cpp + Source/Contents/Sound/SoundConfiguration.cpp + Source/Contents/Sound/SoundMgr.cpp + Source/Contents/Configuration/OptionWriter.cpp Source/Contents/MessageTable.cpp - Source/Contents/AccountLinkedUserDataSaveAsyncWork.cpp - Source/Contents/AccountLinkedUserDataLoadAsyncWork.cpp - Source/Contents/CharacterLinkedUserDataMgr.cpp - Source/Contents/CharacterLinkedUserDataSaveAsyncWork.cpp - Source/Contents/CharacterConfigSave.cpp - Source/Contents/SkillLevelConfig.cpp - Source/Contents/SkillLevelRegistry.cpp - Source/Contents/ServiceOptions.cpp - Source/Contents/NormalItemSlots.cpp - Source/Contents/SkillInfo.cpp - Source/Contents/PlayerSkillBundle.cpp - Source/Contents/SkillTreeScript.cpp - Source/Contents/ClientSkills.cpp - Source/Network/SkillUpdatePacket.cpp - Source/Contents/ItemInfo.cpp - Source/Contents/ItemDescription.cpp - Source/Contents/ItemLink.cpp + Source/Contents/UserData/AccountLinkedUserDataSaveAsyncWork.cpp + Source/Contents/UserData/AccountLinkedUserDataLoadAsyncWork.cpp + Source/Contents/UserData/CharacterLinkedUserDataMgr.cpp + Source/Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.cpp + Source/Contents/UserData/CharacterConfigSave.cpp + Source/Contents/Skills/SkillLevelConfig.cpp + Source/Contents/Skills/SkillLevelRegistry.cpp + Source/Contents/Configuration/ServiceOptions.cpp + Source/Contents/UserData/NormalItemSlots.cpp + Source/Contents/Skills/SkillInfo.cpp + Source/Contents/Skills/PlayerSkillBundle.cpp + Source/Contents/Skills/SkillTreeScript.cpp + Source/Contents/Skills/ClientSkills.cpp + Source/Network/Packets/SkillUpdatePacket.cpp + Source/Contents/Items/ItemInfo.cpp + Source/Contents/Items/ItemDescription.cpp + Source/Contents/Items/ItemLink.cpp Source/Contents/TipBoxTitles.cpp - Source/Contents/AutomaticSkills.cpp - Source/Contents/AttackMotion.cpp - Source/Client/ApplicationActivation.cpp - Source/Client/ApplicationMessages.cpp - Source/Client/BrowserInputHandoff.cpp - Source/Client/WebBrowser.cpp - Source/Client/BrowserRegistry.cpp - Source/Client/WebEventReceiver.cpp - Source/Client/BrowserMessages.cpp - Source/Contents/HotkeyInfo.cpp + Source/Contents/Skills/AutomaticSkills.cpp + Source/Contents/Actors/AttackMotion.cpp + Source/Client/Application/ApplicationActivation.cpp + Source/Client/Application/ApplicationMessages.cpp + Source/Client/Browser/BrowserInputHandoff.cpp + Source/Client/Browser/WebBrowser.cpp + Source/Client/Browser/BrowserRegistry.cpp + Source/Client/Browser/WebEventReceiver.cpp + Source/Client/Browser/BrowserMessages.cpp + Source/Contents/Hotkeys/HotkeyInfo.cpp Source/Contents/PlayerNameDictionary.cpp - Source/Contents/ItemNaming.cpp - Source/Contents/ItemResources.cpp - Source/Contents/StoreBackupData.cpp - Source/Contents/MCStoreInfoBackup.cpp - Source/Contents/MCStoreInfoBackupAsyncWork.cpp - Source/Contents/EmblemDownload.cpp - Source/Contents/EmblemDataDownloadAsyncWork.cpp - Source/Contents/EmblemDataMgr.cpp - Source/Contents/GuildEmblemReqBundle.cpp - Source/Contents/EmblemDataUploadAsyncWork.cpp - Source/Contents/AdvenPartyInfo.cpp - Source/Contents/AdventurerAgencyMgr.cpp - Source/Contents/ChangePartyMasterAsyncWork.cpp - Source/Contents/LoadPartyListAsyncWork.cpp - Source/Contents/StopRecruitingAsyncWork.cpp - Source/Contents/LoadMyPartyAsyncWork.cpp - Source/Contents/RegisterPartyAsyncWork.cpp - Source/Contents/LoadPartyInfoAsyncWork.cpp - Source/Contents/AsyncWorkRecycleObjectPoolMgr.cpp - Source/Contents/AsyncWorkMgr.cpp - Source/Contents/AgencyRequests.cpp + Source/Contents/Items/ItemNaming.cpp + Source/Contents/Items/ItemResources.cpp + Source/Contents/Store/StoreBackupData.cpp + Source/Contents/Store/MCStoreInfoBackup.cpp + Source/Contents/Store/MCStoreInfoBackupAsyncWork.cpp + Source/Contents/Emblems/EmblemDownload.cpp + Source/Contents/Emblems/EmblemDataDownloadAsyncWork.cpp + Source/Contents/Emblems/EmblemDataMgr.cpp + Source/Contents/Emblems/GuildEmblemReqBundle.cpp + Source/Contents/Emblems/EmblemDataUploadAsyncWork.cpp + Source/Contents/Party/AdvenPartyInfo.cpp + Source/Contents/Party/AdventurerAgencyMgr.cpp + Source/Contents/Party/ChangePartyMasterAsyncWork.cpp + Source/Contents/Party/LoadPartyListAsyncWork.cpp + Source/Contents/Party/StopRecruitingAsyncWork.cpp + Source/Contents/Party/LoadMyPartyAsyncWork.cpp + Source/Contents/Party/RegisterPartyAsyncWork.cpp + Source/Contents/Party/LoadPartyInfoAsyncWork.cpp + Source/Contents/Async/AsyncWorkRecycleObjectPoolMgr.cpp + Source/Contents/Async/AsyncWorkMgr.cpp + Source/Contents/Party/AgencyRequests.cpp Source/Contents/ForbiddenWords.cpp - Source/Contents/JobNames.cpp - Source/Contents/SpriteDrawingPolicy.cpp - Source/Contents/JobInheritance.cpp - Source/Contents/MessengerMember.cpp - Source/Contents/ClientMessenger.cpp - Source/Contents/RenderObjectState.cpp - Source/Contents/GameObject.cpp - Source/Contents/RenderObject.cpp - Source/Contents/WorldObjects.cpp - Source/Contents/WorldActors.cpp - Source/Contents/EffectAttachments.cpp - Source/Contents/EffectTypes.cpp - Source/Contents/RagEffectState.cpp - Source/Contents/RagEffectInitialization.cpp - Source/Contents/RagEffectResourceSelection.cpp - Source/Contents/EffectPrimitiveState.cpp - Source/Contents/EffectPrimitiveColor.cpp - Source/Contents/EffectPrimitiveMotion.cpp - Source/Contents/EffectPrimitiveRendering.cpp - Source/Contents/EffectPrimitiveRecords.cpp - Source/Contents/EffectParticle.cpp - Source/Contents/PartyEffect.cpp - Source/Contents/EffectActor.cpp - Source/Contents/AttachedEffect.cpp - Source/Contents/PartyMemberEffects.cpp - Source/Contents/EffectVisibility.cpp - Source/Contents/TerrainHeight.cpp - Source/Contents/TerrainCoordinates.cpp - Source/Contents/TerrainPicking.cpp - Source/Contents/TerrainPlane.cpp - Source/Contents/WorldTerrainPicking.cpp - Source/Contents/WorldProximity.cpp - Source/Contents/JobNameInitialization.cpp + Source/Contents/Jobs/JobNames.cpp + Source/Contents/Actors/SpriteDrawingPolicy.cpp + Source/Contents/Jobs/JobInheritance.cpp + Source/Contents/Messenger/MessengerMember.cpp + Source/Contents/Messenger/ClientMessenger.cpp + Source/Contents/Actors/RenderObjectState.cpp + Source/Contents/Actors/GameObject.cpp + Source/Contents/Actors/RenderObject.cpp + Source/Contents/World/WorldObjects.cpp + Source/Contents/World/WorldActors.cpp + Source/Contents/Effects/EffectAttachments.cpp + Source/Contents/Effects/EffectTypes.cpp + Source/Contents/Effects/RagEffectState.cpp + Source/Contents/Effects/RagEffectInitialization.cpp + Source/Contents/Effects/RagEffectResourceSelection.cpp + Source/Contents/Effects/EffectPrimitiveState.cpp + Source/Contents/Effects/EffectPrimitiveColor.cpp + Source/Contents/Effects/EffectPrimitiveMotion.cpp + Source/Contents/Effects/EffectPrimitiveRendering.cpp + Source/Contents/Effects/EffectPrimitiveRecords.cpp + Source/Contents/Effects/EffectParticle.cpp + Source/Contents/Effects/PartyEffect.cpp + Source/Contents/Effects/EffectActor.cpp + Source/Contents/Effects/AttachedEffect.cpp + Source/Contents/Effects/PartyMemberEffects.cpp + Source/Contents/Effects/EffectVisibility.cpp + Source/Contents/Ground/TerrainHeight.cpp + Source/Contents/Ground/TerrainCoordinates.cpp + Source/Contents/Ground/TerrainPicking.cpp + Source/Contents/Ground/TerrainPlane.cpp + Source/Contents/World/WorldTerrainPicking.cpp + Source/Contents/World/WorldProximity.cpp + Source/Contents/Jobs/JobNameInitialization.cpp Source/Contents/ShowRankingScheduler.cpp ) target_include_directories(RagnarokContents PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/Source") diff --git a/CODING_RULES.md b/CODING_RULES.md index a046537..41ee25b 100644 --- a/CODING_RULES.md +++ b/CODING_RULES.md @@ -80,7 +80,7 @@ static void BuildFullKeyName(const char* keyname, char* buffer) { changes. Include the real prerequisite interfaces, implementations and affected callers, or land them first. - Preserve functions that already match. Fix compile errors and structural differences; byte identity is a bonus, not permission to distort source or spend unbounded time tuning it. -- Do not add WoW `// VERIFY:` hashes or use `re/tools/verify.py`; neither is this project's verification workflow. +- Do not add game `// VERIFY:` hashes or use `re/tools/verify.py`; neither is this project's verification workflow. - Claims, submission scope and peer-review procedure follow `AGENTS.md` and current server guidance. ## 2b. Cast chains mean the types are wrong @@ -152,7 +152,7 @@ class CResourceCache { - Reuse the appropriate header under `Source/` for shared enums and data types. - Use an existing `Types.h` if the subsystem has one; do not create a repository-wide `Types.h` migration. -- Keep dependencies small and avoid cycles. Do not introduce WoW-specific DB or event headers. +- Keep dependencies small and avoid cycles. Do not introduce game-specific DB or event headers. ## 6. Diagnostic file and line arguments preserve original behavior @@ -166,6 +166,25 @@ the original instructions. - This target is Windows x86. Keep code in its assigned existing translation unit and subsystem headers. - Use the original Win32, DirectDraw, Direct3D, Lua and codec ABIs where evidenced. Preserve calling conventions, ownership, field widths and failure behavior. -- Do not introduce WoW architecture macros, parallel `Win32/` / `Win64/` trees or a new portability layer. - Compile individual units with the configured Clank toolchain and `compile.json`, not a new build system. - Missing original instructions are a blocker, not permission to invent a fallback or partial implementation. + +## 8. Reconstruct source, not instructions + +- Prefer the original programmer's types and algorithms over instruction-shaped C++. Byte identity is a bonus, + never a reason for cryptic code. Use compiler intrinsics only with clear evidence that the original source + used them; an optimized SIMD instruction alone is not evidence. Scalar data is not `__m128i`. +- Recover records and members instead of dereferencing integer pointers cast onto byte buffers. At a real + binary-format boundary, use a typed record or `memcpy` for unaligned fields; preserve layout and aliasing. +- Apply namespace and API conventions consistently throughout a subsystem, including declarations and callers. +- Group cohesive implementations and their headers in subsystem folders, e.g. `Client/Browser/`. Group by + actual ownership and dependencies, not a loose keyword; update includes and build metadata with every move. +- Use SDK/library constants and identifiers directly: `WS_CHILD | WS_VISIBLE`, `CGID_DocHostCommandHandler`. + Do not duplicate documented definitions. Name game-specific choices with an enum, or `constexpr` when an enum + is unsuitable; do not turn serialized data, hashes or lookup tables into invented symbolic constants. +- Do not include ``; include the specific Windows API headers actually required. Formatter-control + comments are forbidden too. Preserve include dependencies without `clang-format` suppression comments. +- Separate different logical phases with a blank line; keep related assignments together. Use a 160-column + limit, rather than wrapping short calls into instruction-like fragments. Formatting must not change behavior. +- Leave exactly one blank line after an include block before declarations, including in headers. Never keep + more than one consecutive blank line; whitespace-only lines count as blank. diff --git a/README.md b/README.md index 10fb69e..3cdc21b 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,5 @@ This tree is coordinated with Clank Together. Functions and data carry stable symbol IDs instead of addresses (`// FUNCTION: fn_01234`, `// GLOBAL: gl_00042`); the coordinator's symbol database holds their addresses in every client build, so a new client version needs new addresses, not a retagged tree. -`decomp.json` and `config/compile.json` pin the VS compiler and the exact command line of every source. +`decomp.json` and `compile.json` pin the VS compiler and the exact command line of every source. See `AGENTS.md` for how to contribute. diff --git a/Source/Archive/GPak.cpp b/Source/Archive/GPak.cpp index fefada0..f00e599 100644 --- a/Source/Archive/GPak.cpp +++ b/Source/Archive/GPak.cpp @@ -4,11 +4,9 @@ #include #include #include -#include #include namespace { - std::uint32_t Read32(const std::uint8_t* bytes) { std::uint32_t value; std::memcpy(&value, bytes, sizeof(value)); @@ -29,22 +27,18 @@ namespace { // FUNCTION: fn_05116 std::uint64_t ReadAuxiliaryIdentifier(const void* data, std::size_t size) { if (size != 0) { - const __m128i header = _mm_loadu_si128(static_cast(data)); - if (static_cast(_mm_cvtsi128_si32(header)) <= 1) { - std::uint64_t identifier; - _mm_storel_epi64(reinterpret_cast<__m128i*>(&identifier), _mm_srli_si128(header, 4)); - return identifier; + const auto* header = static_cast(data); + if (header[0] <= 1) { + return Read64(header + 4); } } + return UINT64_MAX; } void SortEntries(std::vector& entries) { - std::sort(entries.begin(), entries.end(), [](const auto& first, const auto& second) { - return first.name < second.name; - }); + std::sort(entries.begin(), entries.end(), [](const auto& first, const auto& second) { return first.name < second.name; }); } - } // OFFSET: 0x00E555A0 @@ -80,6 +74,7 @@ bool CGPak::Open(CPakFile* file) { if (!file) { return false; } + this->m_file = file; const std::uint8_t* header = file->Read(0, 46); if (std::memcmp(header, "Event Horizon", 14) == 0) { @@ -95,6 +90,7 @@ bool CGPak::Open(CPakFile* file) { } bool loaded; + switch (this->m_version & 0xFF00) { case 0x100: loaded = this->ReadTableV1(); @@ -109,9 +105,11 @@ bool CGPak::Open(CPakFile* file) { loaded = false; break; } + if (loaded) { return true; } + this->Reset(); return false; } @@ -119,20 +117,22 @@ bool CGPak::Open(CPakFile* file) { // OFFSET: 0x00AEC050 // FUNCTION: fn_18133 bool CGPak::ReadTableV1() { - this->m_tableSize = - static_cast(this->m_file->GetSize()) - static_cast(this->m_tableOffset); + this->m_tableSize = static_cast(this->m_file->GetSize()) - static_cast(this->m_tableOffset); const std::uint8_t* cursor = this->m_file->Read(this->m_tableOffset, this->m_tableSize); this->m_entries.resize(this->m_entryCount); std::uint32_t maximum = 0; std::uint32_t sequence = 1; std::int32_t legacyKey = 95001; + for (std::uint32_t i = 0; i < this->m_entryCount; ++i) { std::uint32_t nameSize = Read32(cursor); cursor += 4; char name[256]; + if (this->m_version < 0x101) { std::int32_t length = static_cast(std::strlen(reinterpret_cast(cursor)) + 1); + for (std::int32_t j = 0; j < length; ++j) { name[j] = static_cast(SwapNibbles(cursor[j])); } @@ -140,18 +140,23 @@ bool CGPak::ReadTableV1() { if (this->m_version > 0x103) { return false; } + cursor += 2; std::int32_t length = static_cast(nameSize - 6); + for (std::int32_t j = 0; j < length; ++j) { name[j] = static_cast(SwapNibbles(cursor[j])); } + std::int32_t number = legacyKey; if (this->m_version != 0x101) { number = static_cast(3 * (31669u - (sequence >> 1))); } + if (number < 10000) { number += 85000; } + char digits[20]; _itoa(number, digits, 10); std::uint8_t key[8]; @@ -178,13 +183,14 @@ bool CGPak::ReadTableV1() { entry.name.Assign(name); const char* extension = std::strrchr(name, '.'); - bool special = extension && (_stricmp(extension, ".gnd") == 0 || _stricmp(extension, ".gat") == 0 || - _stricmp(extension, ".act") == 0 || _stricmp(extension, ".str") == 0); + bool special = extension && (_stricmp(extension, ".gnd") == 0 || _stricmp(extension, ".gat") == 0 || _stricmp(extension, ".act") == 0 || + _stricmp(extension, ".str") == 0); entry.flags |= special ? 4 : 2; maximum = std::max(maximum, entry.alignedSize); sequence += 5; legacyKey -= 2; } + SortEntries(this->m_entries); this->m_scratch.resize(maximum); return true; @@ -200,6 +206,7 @@ bool CGPak::ReadTableV2() { const std::uint8_t* source = this->m_file->Read(this->m_tableOffset + 8, compressed); uLongf length = original + 8; std::vector decoded(length); + if (uncompress(decoded.data(), &length, source, compressed) != Z_OK) { return false; } @@ -207,6 +214,7 @@ bool CGPak::ReadTableV2() { this->m_entries.resize(this->m_entryCount); const std::uint8_t* cursor = decoded.data(); std::uint32_t maximum = 0; + for (std::uint32_t i = 0; i < this->m_entryCount; ++i) { const char* name = reinterpret_cast(cursor); const std::uint8_t* metadata = cursor + std::strlen(name) + 1; @@ -220,6 +228,7 @@ bool CGPak::ReadTableV2() { entry.name.Assign(name); maximum = std::max(maximum, entry.alignedSize); } + SortEntries(this->m_entries); this->m_scratch.resize(maximum); return true; @@ -236,6 +245,7 @@ bool CGPak::ReadTableV3() { const std::uint8_t* source = this->m_file->Read(this->m_tableOffset + 12, compressed); uLongf length = original + 8; std::vector decoded(length); + if (uncompress(decoded.data(), &length, source, compressed) != Z_OK) { return false; } @@ -243,6 +253,7 @@ bool CGPak::ReadTableV3() { this->m_entries.resize(this->m_entryCount); const std::uint8_t* cursor = decoded.data(); std::uint32_t maximum = 0; + for (std::uint32_t i = 0; i < this->m_entryCount; ++i) { const char* name = reinterpret_cast(cursor); const std::uint8_t* metadata = cursor + std::strlen(name) + 1; @@ -252,12 +263,11 @@ bool CGPak::ReadTableV3() { entry.alignedSize = Read32(metadata + 4); entry.originalSize = Read32(metadata + 8); entry.flags = metadata[12]; - const std::uint32_t offsetLow = Read32(metadata + 13); - reinterpret_cast(&entry.dataOffset)[1] = Read32(metadata + 17); - reinterpret_cast(&entry.dataOffset)[0] = offsetLow; + entry.dataOffset = Read64(metadata + 13); entry.name.Assign(name); maximum = std::max(maximum, entry.alignedSize); } + SortEntries(this->m_entries); this->m_scratch.resize(maximum); return true; @@ -266,16 +276,17 @@ bool CGPak::ReadTableV3() { // OFFSET: 0x00AEBA30 // FUNCTION: fn_18128 bool CGPak::Find(const myGPack::PakName& name, myGPack::PakEntry* entry) const { - auto found = std::lower_bound( - this->m_entries.begin(), this->m_entries.end(), name, - [](const myGPack::PakEntry& candidate, const myGPack::PakName& key) { return candidate.name < key; } - ); + auto found = std::lower_bound(this->m_entries.begin(), this->m_entries.end(), name, [](const myGPack::PakEntry& candidate, const myGPack::PakName& key) { + return candidate.name < key; + }); if (found == this->m_entries.end() || found->name != name) { return false; } + if (entry) { std::memcpy(entry, &*found, sizeof(*entry)); } + return true; } @@ -290,6 +301,7 @@ void CGPak::ReadAuxiliary(std::vector& output, std::uint64_t* iden std::uint32_t size; std::uint64_t offset; + switch (this->m_version & 0xFF00) { case 0x200: if (this->m_version < 0x201) { diff --git a/Source/Archive/MemMapPakFile.cpp b/Source/Archive/MemMapPakFile.cpp index 8803171..4ca9299 100644 --- a/Source/Archive/MemMapPakFile.cpp +++ b/Source/Archive/MemMapPakFile.cpp @@ -1,14 +1,10 @@ #include "Archive/MemMapPakFile.h" -#include - // OFFSET: 0x00AE99D0 // FUNCTION: fn_18111 // OFFSET: 0x00AECAA0 // FUNCTION: fn_18140 -CMemMapPakFile::CMemMapPakFile() - : m_handle(nullptr), m_mapping(nullptr), m_viewSize(0), m_windowSize(0x20000000), m_size(0), m_viewOffset(0), - m_view(nullptr) { +CMemMapPakFile::CMemMapPakFile() : m_handle(nullptr), m_mapping(nullptr), m_viewSize(0), m_windowSize(0x20000000), m_size(0), m_viewOffset(0), m_view(nullptr) { SYSTEM_INFO information; GetSystemInfo(&information); this->m_offsetMask = 0xFFFFFFFF00000000ULL | static_cast(~(information.dwAllocationGranularity - 1)); @@ -30,8 +26,7 @@ std::uint64_t CMemMapPakFile::GetSize() const { // OFFSET: 0x00AECB10 // FUNCTION: fn_18141 bool CMemMapPakFile::Open(const char* filename) { - this->m_handle = - CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + this->m_handle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (this->m_handle == INVALID_HANDLE_VALUE) { this->m_handle = nullptr; return false; @@ -39,13 +34,15 @@ bool CMemMapPakFile::Open(const char* filename) { LARGE_INTEGER size; GetFileSizeEx(this->m_handle, &size); - this->m_size = std::bit_cast(size.QuadPart); + this->m_size = static_cast(size.QuadPart); this->m_viewOffset = 0; this->m_viewSize = 0; this->m_mapping = CreateFileMappingA(this->m_handle, nullptr, PAGE_READONLY, 0, 0, nullptr); + if (this->m_mapping) { return true; } + this->m_windowSize = 0; return false; } @@ -57,10 +54,12 @@ void CMemMapPakFile::Close() { UnmapViewOfFile(this->m_view); this->m_view = nullptr; } + if (this->m_mapping) { CloseHandle(this->m_mapping); this->m_mapping = nullptr; } + if (this->m_handle) { CloseHandle(this->m_handle); this->m_handle = nullptr; @@ -74,27 +73,29 @@ std::uint8_t* CMemMapPakFile::Read(std::uint64_t offset, std::uint32_t length) { if (offset >= this->m_viewOffset && offset + length <= this->m_viewOffset + this->m_viewSize) { return this->m_view + static_cast(offset - this->m_viewOffset); } + if (this->m_view) { UnmapViewOfFile(this->m_view); this->m_view = nullptr; } - while (this->m_windowSize >= - length + (static_cast(offset) & ~static_cast(this->m_offsetMask))) { + while (this->m_windowSize >= length + (static_cast(offset) & ~static_cast(this->m_offsetMask))) { this->m_viewOffset = offset & this->m_offsetMask; this->m_viewSize = this->m_windowSize; SIZE_T bytes = this->m_windowSize; + if (this->m_viewOffset + this->m_windowSize > this->m_size) { bytes = 0; this->m_viewSize = static_cast(this->m_size - this->m_viewOffset); } - this->m_view = static_cast(MapViewOfFile( - this->m_mapping, FILE_MAP_READ, static_cast(this->m_viewOffset >> 32), - static_cast(this->m_viewOffset), bytes - )); + + this->m_view = static_cast( + MapViewOfFile(this->m_mapping, FILE_MAP_READ, static_cast(this->m_viewOffset >> 32), static_cast(this->m_viewOffset), bytes) + ); if (this->m_view) { return this->m_view + static_cast(offset - this->m_viewOffset); } + this->m_windowSize >>= 1; if (!this->m_windowSize) { break; @@ -113,14 +114,16 @@ std::uint8_t* CMemMapPakFile::Read(std::uint64_t offset, std::uint32_t length) { this->m_buffer.resize(length); this->m_view = this->m_buffer.data(); } + LARGE_INTEGER position; - position.QuadPart = std::bit_cast(offset); + position.QuadPart = static_cast(offset); SetFilePointerEx(this->m_handle, position, nullptr, FILE_BEGIN); DWORD read = 0; + if (ReadFile(this->m_handle, this->m_buffer.data(), length, &read, nullptr)) { - // The original accepts a successful short read; it does not compare read. this->m_view = this->m_buffer.empty() ? nullptr : this->m_buffer.data(); return this->m_view; } + return nullptr; } diff --git a/Source/Archive/MemMapPakFile.h b/Source/Archive/MemMapPakFile.h index e5f8c82..8cec2ec 100644 --- a/Source/Archive/MemMapPakFile.h +++ b/Source/Archive/MemMapPakFile.h @@ -3,7 +3,6 @@ #include "Archive/PakFile.h" -// Class name established by original RTTI; field/method names reconstructed. class CMemMapPakFile : public CPakFile { public: CMemMapPakFile(); diff --git a/Source/Archive/PakCipher.cpp b/Source/Archive/PakCipher.cpp index c0796b5..3756211 100644 --- a/Source/Archive/PakCipher.cpp +++ b/Source/Archive/PakCipher.cpp @@ -5,21 +5,18 @@ namespace myGPack { namespace { - // STATIC: 0x01159EC8 // GLOBAL: gl_13428 constexpr std::uint8_t s_initialPermutation[64] = { - 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, - 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, - 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7, + 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7, }; // STATIC: 0x01159F08 // GLOBAL: gl_13429 constexpr std::uint8_t s_finalPermutation[64] = { - 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, - 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, - 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25, + 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25, }; // STATIC: 0x01159FC0 @@ -32,42 +29,38 @@ namespace myGPack { // STATIC: 0x01159FF0 // GLOBAL: gl_13431 constexpr std::uint8_t s_roundPermutation[32] = { - 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, - 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25, + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25, }; // STATIC: 0x0115A010 // GLOBAL: gl_13432 constexpr std::uint8_t s_substitution[512] = { - 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, - 5, 0, 3, 7, 8, 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, 15, 5, 12, 11, 9, 3, - 7, 14, 3, 10, 10, 0, 5, 6, 0, 13, 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, 9, - 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, - 13, 4, 1, 2, 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9, 10, 13, 0, 7, 9, 0, 14, - 9, 6, 3, 3, 4, 15, 6, 5, 10, 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, 13, 1, - 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, - 2, 7, 12, 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, 1, 4, 2, 7, 8, 2, 5, 12, - 11, 1, 12, 10, 4, 14, 15, 9, 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, 15, 9, 1, - 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14, 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, - 6, 1, 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, 4, 11, 2, 8, 1, 12, 11, 7, 10, - 1, 13, 14, 7, 2, 8, 13, 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3, 12, 10, 1, 15, - 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, - 8, 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, - 13, 0, 11, 8, 6, 13, 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, 3, 14, 12, 3, 9, - 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, - 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12, 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, - 3, 11, 7, 1, 4, 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, 7, 2, 11, 1, 4, 14, - 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11, + 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, 4, 15, 1, 12, 14, + 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13, 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, + 11, 2, 3, 8, 4, 14, 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, + 2, 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9, 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, 1, 2, 13, 8, + 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, 11, 4, 1, 15, 2, 14, 12, 3, 5, + 11, 10, 5, 14, 2, 7, 12, 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, + 15, 9, 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14, 2, 14, 12, + 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, 4, 11, 2, 8, 1, 12, 11, 7, + 10, 1, 13, 14, 7, 2, 8, 13, 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3, 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, + 9, 8, 5, 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, 7, 11, + 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13, 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, 3, 14, 12, 3, 9, 5, 7, + 12, 5, 2, 10, 15, 6, 8, 1, 6, 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, + 9, 3, 2, 12, 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, 7, + 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11, }; void Permute(std::uint8_t* block, const std::uint8_t* table, unsigned count) { std::uint8_t result[8] = {}; + for (unsigned i = 0; i < count; ++i) { unsigned bit = table[i] - 1; if (block[bit >> 3] & (0x80u >> (bit & 7))) { result[i >> 3] |= static_cast(0x80u >> (i & 7)); } } + std::memcpy(block, result, sizeof(result)); } @@ -105,7 +98,6 @@ namespace myGPack { return value; } } - } // OFFSET: 0x00AE8480 @@ -118,9 +110,6 @@ namespace myGPack { // OFFSET: 0x00AE92F0 // FUNCTION: fn_18105 PakCipher::PakCipher(const std::uint8_t* key) { - // The original key permutation ANDs into zeroed state. Every resulting - // round key is zero, independent of the eight key bytes it reads. - // This is intentional original behavior, not standard DES key expansion. (void)key; std::memset(this->m_roundKeys, 0, sizeof(this->m_roundKeys)); } @@ -133,22 +122,30 @@ namespace myGPack { // OFFSET: 0x00AE8E70 // FUNCTION: fn_18101 int PakCipher::DecodeBlock(int rounds, const std::uint8_t* input, std::uint8_t* output) const { - std::memcpy(output, input, 8); + std::uint32_t inputLow; + std::uint32_t inputHigh; + std::memcpy(&inputLow, input, sizeof(inputLow)); + std::memcpy(&inputHigh, input + 4, sizeof(inputHigh)); + std::memcpy(output, &inputLow, sizeof(inputLow)); + std::memcpy(output + 4, &inputHigh, sizeof(inputHigh)); Permute(output, s_initialPermutation, 64); for (int round = 0; round < rounds; ++round) { std::uint8_t expanded[8] = {}; + for (unsigned i = 0; i < 48; ++i) { unsigned bit = s_expansion[i] + 31; if (output[bit >> 3] & (0x80u >> (bit & 7))) { expanded[i / 6] |= static_cast(0x80u >> (i % 6)); } } + for (unsigned i = 0; i < 8; ++i) { expanded[i] ^= this->m_roundKeys[15 - round][i]; } std::uint8_t substituted[4] = {}; + for (unsigned i = 0; i < 8; ++i) { std::uint8_t value = s_substitution[64 * i + (expanded[i] >> 2)]; if (i & 1) { @@ -159,15 +156,18 @@ namespace myGPack { } std::uint8_t transformed[4] = {}; + for (unsigned i = 0; i < 32; ++i) { unsigned bit = s_roundPermutation[i] - 1; if (substituted[bit >> 3] & (0x80u >> (bit & 7))) { transformed[i >> 3] |= static_cast(0x80u >> (i & 7)); } } + std::uint8_t previous[4]; std::memcpy(previous, output, 4); std::memcpy(output, output + 4, 4); + for (unsigned i = 0; i < 4; ++i) { output[i + 4] = transformed[i] ^ previous[i]; } @@ -176,22 +176,18 @@ namespace myGPack { for (unsigned i = 0; i < 4; ++i) { std::swap(output[i], output[i + 4]); } + Permute(output, s_finalPermutation, 64); return 1; } // OFFSET: 0x00AE84A0 // FUNCTION: fn_18099 - int PakCipher::Decode( - const std::uint8_t* input, - int length, - std::uint8_t* output, - int* outputLength, - int cycle - ) const { + int PakCipher::Decode(const std::uint8_t* input, int length, std::uint8_t* output, int* outputLength, int cycle) const { if (!input || !output || !outputLength) { return 0; } + *outputLength = length; if (cycle < 3) { cycle = 1; @@ -206,10 +202,10 @@ namespace myGPack { int shuffled = 0; int block = 0; int offset = 0; + do { if (block >= 20 && block % cycle != 0) { if (shuffled == 7) { - // Preserve the original store/load order, including in-place use. std::uint16_t pair; std::memcpy(&pair, input + offset + 3, 2); std::memcpy(output + offset, &pair, 2); @@ -221,11 +217,12 @@ namespace myGPack { output[offset + 7] = SubstituteLastByte(input[offset + 7]); shuffled = 1; } else { - std::uint32_t word; - std::memcpy(&word, input + offset, 4); - std::memcpy(output + offset, &word, 4); - std::memcpy(&word, input + offset + 4, 4); - std::memcpy(output + offset + 4, &word, 4); + std::uint32_t low; + std::uint32_t high; + std::memcpy(&low, input + offset, sizeof(low)); + std::memcpy(&high, input + offset + 4, sizeof(high)); + std::memcpy(output + offset, &low, sizeof(low)); + std::memcpy(output + offset + 4, &high, sizeof(high)); ++shuffled; } } else { @@ -235,9 +232,11 @@ namespace myGPack { this->DecodeBlock(1, blockInput, blockOutput); std::memcpy(output + offset, blockOutput, 8); } + offset += 8; ++block; } while (offset < length); + return 1; } @@ -248,6 +247,7 @@ namespace myGPack { std::memcpy(output, input, static_cast(length)); int offset = 0; int block = 0; + do { std::uint8_t blockInput[8]; std::uint8_t decoded[8]; @@ -257,6 +257,7 @@ namespace myGPack { offset += 8; ++block; } while (offset < length && block < 20); + return 1; } @@ -264,49 +265,56 @@ namespace myGPack { // FUNCTION: fn_18104 int __stdcall InitialPermutation(std::uint8_t* block) { std::uint8_t result[8] = {}; + for (unsigned i = 0; i < 64; ++i) { unsigned bit = s_initialPermutation[i] - 1; if (block[bit >> 3] & (0x80u >> (bit & 7))) { result[i >> 3] |= static_cast(0x80u >> (i & 7)); } } + std::memcpy(block, result, 8); - return *reinterpret_cast(result + 4); + int high; + std::memcpy(&high, result + 4, sizeof(high)); + + return high; } // OFFSET: 0x00AE91D0 // FUNCTION: fn_18103 int __stdcall FinalPermutation(std::uint8_t* block) { std::uint8_t result[8] = {}; + for (unsigned i = 0; i < 64; ++i) { unsigned bit = s_finalPermutation[i] - 1; if (block[bit >> 3] & (0x80u >> (bit & 7))) { result[i >> 3] |= static_cast(0x80u >> (i & 7)); } } + std::memcpy(block, result, 8); - return *reinterpret_cast(result + 4); + int high; + std::memcpy(&high, result + 4, sizeof(high)); + + return high; } // OFFSET: 0x00AE9020 // FUNCTION: fn_18102 - int __stdcall EncodeBlock( - int rounds, - const std::uint8_t (*roundKeys)[8], - std::uint32_t inputLow, - std::uint32_t inputHigh, - std::uint8_t* output - ) { + int __stdcall EncodeBlock(int rounds, const std::uint8_t (*roundKeys)[8], std::uint32_t inputLow, std::uint32_t inputHigh, std::uint8_t* output) { std::memcpy(output, &inputLow, 4); std::memcpy(output + 4, &inputHigh, 4); InitialPermutation(output); if (rounds > 0) { - std::uint32_t left = *reinterpret_cast(output); - std::uint32_t right = *reinterpret_cast(output + 4); + std::uint32_t left; + std::uint32_t right; + std::memcpy(&left, output, sizeof(left)); + std::memcpy(&right, output + 4, sizeof(right)); for (int round = 0; round < rounds; ++round) { std::uint8_t expanded[8] = {}; + for (unsigned i = 0; i < 48; ++i) { unsigned bit = s_expansion[i] + 31; if (output[bit >> 3] & (0x80u >> (bit & 7))) { @@ -319,6 +327,7 @@ namespace myGPack { } std::uint8_t substituted[4] = {}; + for (unsigned i = 0; i < 8; ++i) { std::uint8_t value = s_substitution[64 * i + (expanded[i] >> 2)]; if (i & 1) { @@ -329,6 +338,7 @@ namespace myGPack { } std::uint8_t transformed[4] = {}; + for (unsigned i = 0; i < 32; ++i) { unsigned bit = s_roundPermutation[i] - 1; if (substituted[bit >> 3] & (0x80u >> (bit & 7))) { @@ -336,19 +346,24 @@ namespace myGPack { } } - std::uint32_t newRight = left ^ *reinterpret_cast(transformed); + std::uint32_t transformedWord; + std::memcpy(&transformedWord, transformed, sizeof(transformedWord)); + std::uint32_t newRight = left ^ transformedWord; left = right; right = newRight; - *reinterpret_cast(output) = left; - *reinterpret_cast(output + 4) = right; + std::memcpy(output, &left, sizeof(left)); + std::memcpy(output + 4, &right, sizeof(right)); } - *reinterpret_cast(output) = right; - *reinterpret_cast(output + 4) = left; + std::memcpy(output, &right, sizeof(right)); + std::memcpy(output + 4, &left, sizeof(left)); } else { - std::uint32_t temp = *reinterpret_cast(output); - *reinterpret_cast(output) = *reinterpret_cast(output + 4); - *reinterpret_cast(output + 4) = temp; + std::uint32_t left; + std::uint32_t right; + std::memcpy(&left, output, sizeof(left)); + std::memcpy(&right, output + 4, sizeof(right)); + std::memcpy(output, &right, sizeof(right)); + std::memcpy(output + 4, &left, sizeof(left)); } FinalPermutation(output); @@ -382,5 +397,4 @@ namespace myGPack { return key; } - } diff --git a/Source/Archive/PakCipher.h b/Source/Archive/PakCipher.h index 210495b..ed3b4c9 100644 --- a/Source/Archive/PakCipher.h +++ b/Source/Archive/PakCipher.h @@ -5,9 +5,6 @@ namespace myGPack { - // Reconstructed semantic class name; original symbol unavailable. - // The original stream routine processes complete eight-byte blocks, including - // one block for length <= 0. Callers must provide corresponding buffer space. class PakCipher { public: PakCipher(); @@ -25,13 +22,7 @@ namespace myGPack { std::uint8_t* __stdcall DerivePakKey(const char* name, std::uint8_t* key); int __stdcall InitialPermutation(std::uint8_t* block); int __stdcall FinalPermutation(std::uint8_t* block); - int __stdcall EncodeBlock( - int rounds, - const std::uint8_t (*roundKeys)[8], - std::uint32_t inputLow, - std::uint32_t inputHigh, - std::uint8_t* output - ); + int __stdcall EncodeBlock(int rounds, const std::uint8_t (*roundKeys)[8], std::uint32_t inputLow, std::uint32_t inputHigh, std::uint8_t* output); } diff --git a/Source/Archive/PakFile.cpp b/Source/Archive/PakFile.cpp index 7db56d9..1790a13 100644 --- a/Source/Archive/PakFile.cpp +++ b/Source/Archive/PakFile.cpp @@ -1,13 +1,10 @@ #include "Archive/PakFile.h" -#include - // OFFSET: 0x005EF660 // FUNCTION: fn_04009 CPakFile::~CPakFile() = default; namespace myGPack { - // OFFSET: 0x005F7790 // FUNCTION: fn_04046 CReadPakFile::CReadPakFile() : m_handle(INVALID_HANDLE_VALUE), m_size(0) { @@ -31,7 +28,6 @@ namespace myGPack { // OFFSET: 0x005F7810 // FUNCTION: fn_04047 void CReadPakFile::Close() { - // The original tests for null, not INVALID_HANDLE_VALUE. if (this->m_handle) { CloseHandle(this->m_handle); this->m_handle = nullptr; @@ -41,18 +37,15 @@ namespace myGPack { // OFFSET: 0x005F7890 // FUNCTION: fn_04048 bool CWritePakFile::Open(const char* filename) { - this->m_handle = CreateFileA( - filename, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL, - nullptr - ); + this->m_handle = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL, nullptr); if (this->m_handle == INVALID_HANDLE_VALUE) { return false; } LARGE_INTEGER size; - // The original does not check GetFileSizeEx's return value. + GetFileSizeEx(this->m_handle, &size); - this->m_size = std::bit_cast(size.QuadPart); + this->m_size = static_cast(size.QuadPart); return true; } @@ -66,14 +59,15 @@ namespace myGPack { this->m_buffer.resize(length); LARGE_INTEGER position; - position.QuadPart = std::bit_cast(offset); - // Seeking errors are not checked before the original ReadFile call. + position.QuadPart = static_cast(offset); + SetFilePointerEx(this->m_handle, position, nullptr, FILE_BEGIN); DWORD read; if (ReadFile(this->m_handle, this->m_buffer.data(), length, &read, nullptr) && read == length) { return this->m_buffer.data(); } + return nullptr; } @@ -81,7 +75,7 @@ namespace myGPack { // FUNCTION: fn_04050 bool CWritePakFile::Write(std::uint64_t offset, const void* bytes, std::uint32_t length) { LARGE_INTEGER position; - position.QuadPart = std::bit_cast(offset); + position.QuadPart = static_cast(offset); SetFilePointerEx(this->m_handle, position, nullptr, FILE_BEGIN); DWORD written; @@ -93,7 +87,7 @@ namespace myGPack { if (this->m_size < end) { this->m_size = end; } + return true; } - } diff --git a/Source/Archive/PakFile.h b/Source/Archive/PakFile.h index f21868a..a09cb56 100644 --- a/Source/Archive/PakFile.h +++ b/Source/Archive/PakFile.h @@ -5,8 +5,6 @@ #include #include -// Class names and inheritance are established by original RTTI. -// Method and member names are reconstructed from their behavior. class CPakFile { public: virtual ~CPakFile(); diff --git a/Source/Archive/PakName.cpp b/Source/Archive/PakName.cpp index ca57c49..4fa2fe9 100644 --- a/Source/Archive/PakName.cpp +++ b/Source/Archive/PakName.cpp @@ -4,7 +4,6 @@ #include namespace myGPack { - // OFFSET: 0x00AECE00 // FUNCTION: fn_18145 PakName::PakName() { @@ -19,14 +18,15 @@ namespace myGPack { } void AssignNameKey(std::uint32_t& result, char* destination, const char* source) { - // Source helper: copies through NUL without bounds checking. std::strcpy(destination, source); _strlwr(destination); const std::size_t length = std::strlen(destination); std::uint32_t hash = 5381; + for (std::size_t i = 0; i < length; ++i) { hash = 33 * hash + static_cast(destination[i]); } + result = hash; } @@ -48,7 +48,7 @@ namespace myGPack { if (this->m_hash == other.m_hash) { return std::strcmp(this->m_name, other.m_name) < 0; } + return this->m_hash < other.m_hash; } - } diff --git a/Source/Archive/PakName.h b/Source/Archive/PakName.h index 423f505..516f284 100644 --- a/Source/Archive/PakName.h +++ b/Source/Archive/PakName.h @@ -6,10 +6,8 @@ namespace myGPack { - // Shared machine algorithm used with different owner-reserved buffer extents. void AssignNameKey(std::uint32_t& hash, char* destination, const char* source); - // Reconstructed name for the key embedded at archive entry offset 0x1C. class PakName { public: PakName(); diff --git a/Source/Archive/PakRegistry.cpp b/Source/Archive/PakRegistry.cpp index 0b3d236..29db64b 100644 --- a/Source/Archive/PakRegistry.cpp +++ b/Source/Archive/PakRegistry.cpp @@ -12,6 +12,7 @@ PakRegistry::~PakRegistry() { delete archive.first; delete archive.second; } + this->m_archives.clear(); } @@ -23,6 +24,7 @@ bool PakRegistry::Add(const char* filename) { if (file) { file->Open(filename); } + this->m_archives.emplace_front(file, archive); return this->m_archives.front().second->Open(this->m_archives.front().first); } @@ -79,6 +81,7 @@ bool PakRegistry::Exists(const char* filename, bool looseOnly) const { if (search == INVALID_HANDLE_VALUE) { return false; } + FindClose(search); return true; } diff --git a/Source/Client/Application/ApplicationActivation.cpp b/Source/Client/Application/ApplicationActivation.cpp new file mode 100644 index 0000000..9f7606a --- /dev/null +++ b/Source/Client/Application/ApplicationActivation.cpp @@ -0,0 +1,19 @@ +#include "Client/Application/ApplicationActivation.h" +#include "Client/Application/ApplicationWindow.h" +#include "Contents/Configuration/ServiceOptions.h" + +// OFFSET: 0x00E5A190 +// FUNCTION: fn_24369 +void ApplicationActivation::Set(int value) { + this->active = value; + if (value != 0) { + SetPriorityClass(GetCurrentProcess(), this->priority); + if (this->service.Get(ServiceOption::ConfineCursor) != 0) { + ClipApplicationCursor(this->window); + } + } else { + SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS); + ClipCursor(nullptr); + this->automaticSkills.DisableAll(); + } +} diff --git a/Source/Client/Application/ApplicationActivation.h b/Source/Client/Application/ApplicationActivation.h new file mode 100644 index 0000000..dd91096 --- /dev/null +++ b/Source/Client/Application/ApplicationActivation.h @@ -0,0 +1,17 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_APPLICATION_APPLICATIONACTIVATION_H +#define RAGNAROK_SOURCE_CLIENT_APPLICATION_APPLICATIONACTIVATION_H + +#include "Contents/Skills/AutomaticSkills.h" +#include "Contents/Configuration/ServiceOptions.h" + +struct ApplicationActivation { + HWND& window; + const DWORD& priority; + int& active; + ServiceOptions& service; + AutomaticSkills& automaticSkills; + + void Set(int value); +}; + +#endif diff --git a/Source/Client/Application/ApplicationMessages.cpp b/Source/Client/Application/ApplicationMessages.cpp new file mode 100644 index 0000000..66c78da --- /dev/null +++ b/Source/Client/Application/ApplicationMessages.cpp @@ -0,0 +1,46 @@ +#include "Client/Application/ApplicationMessages.h" +#include "Client/Application/ApplicationWindow.h" +#include "Client/Input/TraditionalKeyInput.h" +#include "Contents/Configuration/ServiceOptions.h" + +#include +#include + +// OFFSET: 0x00E57380 +// FUNCTION: fn_24357 +void ApplicationMessages::Pump() { + MSG message; + + while (PeekMessageA(&message, nullptr, 0, 0, PM_REMOVE)) { + if (message.message == WM_KEYDOWN && message.wParam == VK_PROCESSKEY) { + const UINT key = ImmGetVirtualKey(message.hwnd); + if (this->traditional) { + this->traditional->Key(static_cast(key)); + } + } + + TranslateMessage(&message); + DispatchMessageA(&message); + } + + if (this->dragging == 1) { + POINT point; + GetCursorPos(&point); + const int deltaX = point.x - this->dragStart.x; + const int deltaY = point.y - this->dragStart.y; + + if (deltaX != 0 || deltaY != 0) { + MoveWindow( + this->window, this->dragRectangle.left + deltaX, this->dragRectangle.top + deltaY, this->dragRectangle.right - this->dragRectangle.left, + this->dragRectangle.bottom - this->dragRectangle.top, TRUE + ); + } + + if ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0) { + this->dragging = 0; + if (this->service.Get(ServiceOption::ConfineCursor) != 0) { + ClipApplicationCursor(this->window); + } + } + } +} diff --git a/Source/Client/Application/ApplicationMessages.h b/Source/Client/Application/ApplicationMessages.h new file mode 100644 index 0000000..bd255ad --- /dev/null +++ b/Source/Client/Application/ApplicationMessages.h @@ -0,0 +1,20 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_APPLICATION_APPLICATIONMESSAGES_H +#define RAGNAROK_SOURCE_CLIENT_APPLICATION_APPLICATIONMESSAGES_H + +#include + +struct TraditionalKeyInput; +struct ServiceOptions; + +struct ApplicationMessages { + HWND& window; + unsigned char& dragging; + POINT& dragStart; + RECT& dragRectangle; + TraditionalKeyInput* const& traditional; + ServiceOptions& service; + + void Pump(); +}; + +#endif diff --git a/Source/Client/Application/ApplicationWindow.cpp b/Source/Client/Application/ApplicationWindow.cpp new file mode 100644 index 0000000..749151c --- /dev/null +++ b/Source/Client/Application/ApplicationWindow.cpp @@ -0,0 +1,24 @@ +#include "Client/Application/ApplicationWindow.h" + +// OFFSET: 0x03DE9F37 +// FUNCTION: fn_45411 +HWND CreateApplicationWindow( + DWORD extendedStyle, const char* className, const char*, DWORD style, int x, int y, int width, int height, HWND parent, HMENU menu, HINSTANCE instance, + void* parameter +) { + return CreateWindowExA(extendedStyle, className, "Ragnarok 2026", style | WS_SYSMENU, x, y, width, height, parent, menu, instance, parameter); +} + +// OFFSET: 0x00E57DD0 +// FUNCTION: fn_24360 +BOOL ClipApplicationCursor(HWND window) { + RECT rectangle; + GetClientRect(window, &rectangle); + POINT first{rectangle.left, rectangle.top}; + POINT last{rectangle.right, rectangle.bottom}; + ClientToScreen(window, &first); + ClientToScreen(window, &last); + + RECT clip{first.x, first.y, last.x, last.y}; + return ClipCursor(&clip); +} diff --git a/Source/Client/Application/ApplicationWindow.h b/Source/Client/Application/ApplicationWindow.h new file mode 100644 index 0000000..bfd69b0 --- /dev/null +++ b/Source/Client/Application/ApplicationWindow.h @@ -0,0 +1,13 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_APPLICATION_APPLICATIONWINDOW_H +#define RAGNAROK_SOURCE_CLIENT_APPLICATION_APPLICATIONWINDOW_H + +#include + +HWND CreateApplicationWindow( + DWORD extendedStyle, const char* className, const char* ignoredTitle, DWORD style, int x, int y, int width, int height, HWND parent, HMENU menu, + HINSTANCE instance, void* parameter +); + +BOOL ClipApplicationCursor(HWND window); + +#endif diff --git a/Source/Client/ErrorDialog.cpp b/Source/Client/Application/ErrorDialog.cpp similarity index 86% rename from Source/Client/ErrorDialog.cpp rename to Source/Client/Application/ErrorDialog.cpp index 43386f6..6540e49 100644 --- a/Source/Client/ErrorDialog.cpp +++ b/Source/Client/Application/ErrorDialog.cpp @@ -1,4 +1,4 @@ -#include "Client/ErrorDialog.h" +#include "Client/Application/ErrorDialog.h" #include "Render/RenderSystemBase.h" // OFFSET: 0x00AD6360 @@ -7,5 +7,6 @@ int ShowErrorDialog(CRenderSystemBase* renderSystem, const char* text, UINT type if (renderSystem) { renderSystem->PrepareErrorDialog(); } + return MessageBoxA(nullptr, text, "Error", type); } diff --git a/Source/Client/Application/ErrorDialog.h b/Source/Client/Application/ErrorDialog.h new file mode 100644 index 0000000..38dc35f --- /dev/null +++ b/Source/Client/Application/ErrorDialog.h @@ -0,0 +1,10 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_APPLICATION_ERRORDIALOG_H +#define RAGNAROK_SOURCE_CLIENT_APPLICATION_ERRORDIALOG_H + +#include + +class CRenderSystemBase; + +int ShowErrorDialog(CRenderSystemBase* renderSystem, const char* text, UINT type); + +#endif diff --git a/Source/Client/Application/Launcher.cpp b/Source/Client/Application/Launcher.cpp new file mode 100644 index 0000000..71641d0 --- /dev/null +++ b/Source/Client/Application/Launcher.cpp @@ -0,0 +1,40 @@ +#include "Client/Application/Launcher.h" + +#include +#include + +// OFFSET: 0x00E58820 +// FUNCTION: fn_24363 +bool RestartFromCommandLine(char* commandLine) { + char* marker = std::strstr(commandLine, "/launcherRESTART:"); + if (!marker) { + return false; + } + + STARTUPINFOA startup = {}; + startup.cb = sizeof(startup); + startup.dwFlags = STARTF_USESHOWWINDOW; + startup.wShowWindow = SW_SHOWNORMAL; + PROCESS_INFORMATION process; + + CreateProcessA(nullptr, marker + std::strlen("/launcherRESTART:"), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startup, &process); + CloseHandle(process.hProcess); + CloseHandle(process.hThread); + + return true; +} + +// OFFSET: 0x00E5D390 +// FUNCTION: fn_24380 +void ExitForProtectionCheck(const char* commandLine) { + if (std::strstr(commandLine, "/check_themida")) { + ExitProcess(0); + } +} + +// OFFSET: 0x00E5D390 +// FUNCTION: fn_24380 +bool AcquireInstanceMutex(HANDLE* mutex) { + *mutex = CreateMutexA(nullptr, TRUE, "MutexInit"); + return GetLastError() != ERROR_ALREADY_EXISTS; +} diff --git a/Source/Client/Application/Launcher.h b/Source/Client/Application/Launcher.h new file mode 100644 index 0000000..f127803 --- /dev/null +++ b/Source/Client/Application/Launcher.h @@ -0,0 +1,11 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_APPLICATION_LAUNCHER_H +#define RAGNAROK_SOURCE_CLIENT_APPLICATION_LAUNCHER_H + +#include + +bool RestartFromCommandLine(char* commandLine); + +void ExitForProtectionCheck(const char* commandLine); +bool AcquireInstanceMutex(HANDLE* mutex); + +#endif diff --git a/Source/Client/UnhandledExceptionHandler.cpp b/Source/Client/Application/UnhandledExceptionHandler.cpp similarity index 86% rename from Source/Client/UnhandledExceptionHandler.cpp rename to Source/Client/Application/UnhandledExceptionHandler.cpp index 82feea1..997cb99 100644 --- a/Source/Client/UnhandledExceptionHandler.cpp +++ b/Source/Client/Application/UnhandledExceptionHandler.cpp @@ -1,4 +1,5 @@ -#include "Client/UnhandledExceptionHandler.h" +#include "Client/Mode/ActiveGameMode.h" +#include "Client/Application/UnhandledExceptionHandler.h" #include #include @@ -56,35 +57,36 @@ extern int64_t g_loginTimeTicks; // GLOBAL: gl_24474 extern const uint8_t g_session[]; -// STATIC: 0x013495b8 -// GLOBAL: gl_24475 -extern const uint8_t g_world[]; - namespace { int ReadPlayerJob() { - return *reinterpret_cast(reinterpret_cast(g_session) + 0x1628); + int job; + std::memcpy(&job, g_session + 0x1628, sizeof(job)); + return job; } const char* ReadPlayerJobName(int jobId) { - const auto* const* namesBegin = *reinterpret_cast(reinterpret_cast(g_session) + 0xFA8); - const auto* const* namesEnd = *reinterpret_cast(reinterpret_cast(g_session) + 0xFAC); + const char* const* namesBegin; + const char* const* namesEnd; + std::memcpy(&namesBegin, g_session + 0xFA8, sizeof(namesBegin)); + std::memcpy(&namesEnd, g_session + 0xFAC, sizeof(namesEnd)); + if (!namesBegin || !namesEnd || namesBegin >= namesEnd) { return ""; } + size_t count = namesEnd - namesBegin; if (static_cast(jobId) >= count || !namesBegin[jobId]) { return ""; } + return namesBegin[jobId]; } const char* ReadCurrentMapName() { - if (*reinterpret_cast(reinterpret_cast(g_world) + 0x58) == 1) { - void* zone = *reinterpret_cast(reinterpret_cast(g_world) + 0x04); - if (zone != nullptr) { - return reinterpret_cast(reinterpret_cast(zone) + 0x68); - } + if (g_world.state == 1 && g_world.gameMode != nullptr) { + return reinterpret_cast(g_world.gameMode) + 0x68; } + return nullptr; } } @@ -149,6 +151,7 @@ int CleanupUnhandledExceptionHandler() { delete g_unhandledExceptionHandler; g_unhandledExceptionHandler = nullptr; } + return 0; } @@ -216,13 +219,7 @@ BOOL CALLBACK EnumerateLoadedModulesCallback(PCSTR moduleName, ULONG moduleBase, // OFFSET: 0x00635E00 // FUNCTION: fn_04707 -void __cdecl InvalidParameterHandler( - const wchar_t* expression, - const wchar_t* function, - const wchar_t* file, - unsigned int line, - uintptr_t pReserved -) { +void __cdecl InvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) { EXCEPTION_RECORD record = {}; CONTEXT context = {}; EXCEPTION_POINTERS exceptionInfo = {&record, &context}; @@ -262,17 +259,14 @@ LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) { if (dbgHelp != nullptr) { auto pStackWalk = reinterpret_cast(GetProcAddress(dbgHelp, "StackWalk")); - auto pGetTimestamp = reinterpret_cast( - GetProcAddress(dbgHelp, "GetTimestampForLoadedLibrary") - ); + auto pGetTimestamp = reinterpret_cast(GetProcAddress(dbgHelp, "GetTimestampForLoadedLibrary")); - auto pEnumerateLoadedModules = reinterpret_cast(GetProcAddress(dbgHelp, "EnumerateLoadedModules")); + auto pEnumerateLoadedModules = + reinterpret_cast(GetProcAddress(dbgHelp, "EnumerateLoadedModules")); HMODULE module = GetModuleHandleA(nullptr); CHAR filename[256] = {}; @@ -281,7 +275,9 @@ LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) { DWORD timestamp = pGetTimestamp ? pGetTimestamp(module) : 0; sprintf(&g_crashString[strlen(g_crashString)], "Module Name: %s\r\n", filename); - const char* timeString = _ctime32(reinterpret_cast(×tamp)); + __time32_t timestampTime; + std::memcpy(×tampTime, ×tamp, sizeof(timestampTime)); + const char* timeString = _ctime32(×tampTime); sprintf(&g_crashString[strlen(g_crashString)], "Time Stamp: 0x%08x - %s\r\n", timestamp, timeString); sprintf(&g_crashString[strlen(g_crashString)], "Version: 0x%08x\r\n", g_clientVersion); sprintf(&g_crashString[strlen(g_crashString)], "\r\n"); @@ -310,6 +306,7 @@ LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) { if (frame.AddrPC.Offset == 0) { break; } + if (!pStackWalk(IMAGE_FILE_MACHINE_I386, process, thread, &frame, context, nullptr, nullptr, nullptr, nullptr)) { break; } @@ -322,26 +319,28 @@ LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) { const auto* stack = reinterpret_cast(context->Esp); sprintf(&g_crashString[strlen(g_crashString)], "\r\n"); sprintf( - &g_crashString[strlen(g_crashString)], - "stack %08x - %08x\r\n", - static_cast(reinterpret_cast(stack)), + &g_crashString[strlen(g_crashString)], "stack %08x - %08x\r\n", static_cast(reinterpret_cast(stack)), static_cast(reinterpret_cast(stack + 1024)) ); for (int i = 0; i < 16; ++i) { sprintf(&g_crashString[strlen(g_crashString)], "%08X : ", static_cast(reinterpret_cast(stack))); + for (int j = 0; j < 16; ++j) { sprintf(&g_crashString[strlen(g_crashString)], "%02X ", *stack++); } + sprintf(&g_crashString[strlen(g_crashString)], "\r\n"); } sprintf(&g_crashString[strlen(g_crashString)], "\r\nLaunch Info \r\n"); int launchIndex = 0; + for (int k = 0; k < 4; ++k) { for (int m = 0; m < 8; ++m) { sprintf(&g_crashString[strlen(g_crashString)], "%04X ", g_launchInfo[launchIndex++]); } + sprintf(&g_crashString[strlen(g_crashString)], "\r\n"); } @@ -354,12 +353,7 @@ LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) { sprintf(&g_crashString[strlen(g_crashString)], "%s %d %d\r\n", mapName, g_playerX, g_playerY); } - sprintf( - &g_crashString[strlen(g_crashString)], - "\r\n%I64d - %I64d", - g_startTimeTicks / 10000000LL, - g_loginTimeTicks / 10000000LL - ); + sprintf(&g_crashString[strlen(g_crashString)], "\r\n%I64d - %I64d", g_startTimeTicks / 10000000LL, g_loginTimeTicks / 10000000LL); int64_t reportTime = _Xtime_get_ticks() / 10000000LL; PROCESS_MEMORY_COUNTERS memCounters = {}; diff --git a/Source/Client/UnhandledExceptionHandler.h b/Source/Client/Application/UnhandledExceptionHandler.h similarity index 76% rename from Source/Client/UnhandledExceptionHandler.h rename to Source/Client/Application/UnhandledExceptionHandler.h index 0acbcfb..2944250 100644 --- a/Source/Client/UnhandledExceptionHandler.h +++ b/Source/Client/Application/UnhandledExceptionHandler.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_UNHANDLEDEXCEPTIONHANDLER_H -#define RAGNAROK_SOURCE_CLIENT_UNHANDLEDEXCEPTIONHANDLER_H +#ifndef RAGNAROK_SOURCE_CLIENT_APPLICATION_UNHANDLEDEXCEPTIONHANDLER_H +#define RAGNAROK_SOURCE_CLIENT_APPLICATION_UNHANDLEDEXCEPTIONHANDLER_H #include #include @@ -39,13 +39,7 @@ BOOL CALLBACK EnumerateLoadedModulesCallback(PCSTR moduleName, ULONG moduleBase, // OFFSET: 0x00635E00 // FUNCTION: fn_04707 -void __cdecl InvalidParameterHandler( - const wchar_t* expression, - const wchar_t* function, - const wchar_t* file, - unsigned int line, - uintptr_t pReserved -); +void __cdecl InvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved); // OFFSET: 0x00635E90 // FUNCTION: fn_04708 @@ -55,4 +49,4 @@ void __cdecl PurecallHandler(); // FUNCTION: fn_04709 LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* exceptionInfo); -#endif // RAGNAROK_SOURCE_CLIENT_UNHANDLEDEXCEPTIONHANDLER_H +#endif diff --git a/Source/Client/ApplicationActivation.cpp b/Source/Client/ApplicationActivation.cpp deleted file mode 100644 index 444df86..0000000 --- a/Source/Client/ApplicationActivation.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "Client/ApplicationActivation.h" -#include "Client/ApplicationWindow.h" - -namespace client { - // OFFSET: 0x00E5A190 - // FUNCTION: fn_24369 - void ApplicationActivation::Set(int value) { - this->active = value; - if (value != 0) { - SetPriorityClass(GetCurrentProcess(), this->priority); - if (this->service.Get(271) != 0) { - ClipApplicationCursor(this->window); - } - } else { - SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS); - ClipCursor(nullptr); - this->automaticSkills.DisableAll(); - } - } -} diff --git a/Source/Client/ApplicationActivation.h b/Source/Client/ApplicationActivation.h deleted file mode 100644 index e8e6cb3..0000000 --- a/Source/Client/ApplicationActivation.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_APPLICATIONACTIVATION_H -#define RAGNAROK_SOURCE_CLIENT_APPLICATIONACTIVATION_H - -#include "Contents/AutomaticSkills.h" -#include "Contents/ServiceOptions.h" - -namespace client { - // Borrowed original main-window/priority/active globals and concrete owners. - struct ApplicationActivation { - HWND& window; - const DWORD& priority; - int& active; - ServiceOptions& service; - AutomaticSkills& automaticSkills; - - // Publishes value verbatim. Nonzero restores configured process priority - // and clips only when option 271 is enabled. Zero selects idle priority, - // releases clipping, then cancels automatic skills through their connection. - void Set(int value); - }; -} - -#endif diff --git a/Source/Client/ApplicationMessages.cpp b/Source/Client/ApplicationMessages.cpp deleted file mode 100644 index 1270c9d..0000000 --- a/Source/Client/ApplicationMessages.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "Client/ApplicationMessages.h" -#include "Client/ApplicationWindow.h" -#include "Client/TraditionalKeyInput.h" -#include "Contents/ServiceOptions.h" - -#include -#include - -namespace client { - // OFFSET: 0x00E57380 - // FUNCTION: fn_24357 - void ApplicationMessages::Pump() { - MSG message; - while (PeekMessageA(&message, nullptr, 0, 0, PM_REMOVE)) { - if (message.message == WM_KEYDOWN && message.wParam == VK_PROCESSKEY) { - const UINT key = ImmGetVirtualKey(message.hwnd); - if (this->traditional) { - this->traditional->Key(static_cast(key)); - } - } - - TranslateMessage(&message); - DispatchMessageA(&message); - } - - if (this->dragging == 1) { - POINT point; - GetCursorPos(&point); - const int deltaX = point.x - this->dragStart.x; - const int deltaY = point.y - this->dragStart.y; - if (deltaX != 0 || deltaY != 0) { - MoveWindow( - this->window, this->dragRectangle.left + deltaX, this->dragRectangle.top + deltaY, - this->dragRectangle.right - this->dragRectangle.left, this->dragRectangle.bottom - this->dragRectangle.top, - TRUE - ); - } - - if ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0) { - this->dragging = 0; - if (this->service.Get(271) != 0) { - ClipApplicationCursor(this->window); - } - } - } - } -} diff --git a/Source/Client/ApplicationMessages.h b/Source/Client/ApplicationMessages.h deleted file mode 100644 index c65c185..0000000 --- a/Source/Client/ApplicationMessages.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_APPLICATIONMESSAGES_H -#define RAGNAROK_SOURCE_CLIENT_APPLICATIONMESSAGES_H - -#include - -struct TraditionalKeyInput; -struct ServiceOptions; - -namespace client { - // Borrowed application globals. A non-null traditional input view denotes - // CLanguageTC; base/TH/ARB virtual-key delivery is an established empty entry. - struct ApplicationMessages { - HWND& window; - unsigned char& dragging; - POINT& dragStart; - RECT& dragRectangle; - TraditionalKeyInput* const& traditional; - ServiceOptions& service; - - // Drains all messages (including WM_QUIT) through Translate/Dispatch, then - // updates native window dragging. Does not invent the main window procedure. - void Pump(); - }; -} - -#endif diff --git a/Source/Client/ApplicationWindow.cpp b/Source/Client/ApplicationWindow.cpp deleted file mode 100644 index 9b23884..0000000 --- a/Source/Client/ApplicationWindow.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "Client/ApplicationWindow.h" - -namespace client { - // OFFSET: 0x03DE9F37 - // FUNCTION: fn_45411 - HWND CreateApplicationWindow( - DWORD extendedStyle, - const char* className, - const char*, - DWORD style, - int x, - int y, - int width, - int height, - HWND parent, - HMENU menu, - HINSTANCE instance, - void* parameter - ) { - return CreateWindowExA( - extendedStyle, className, "Ragnarok 2026", style | WS_SYSMENU, x, y, width, height, parent, menu, instance, - parameter - ); - } - - // OFFSET: 0x00E57DD0 - // FUNCTION: fn_24360 - BOOL ClipApplicationCursor(HWND window) { - RECT rectangle; - GetClientRect(window, &rectangle); - POINT first{rectangle.left, rectangle.top}; - POINT last{rectangle.right, rectangle.bottom}; - ClientToScreen(window, &first); - ClientToScreen(window, &last); - - RECT clip{first.x, first.y, last.x, last.y}; - return ClipCursor(&clip); - } -} diff --git a/Source/Client/ApplicationWindow.h b/Source/Client/ApplicationWindow.h deleted file mode 100644 index 61ab1c2..0000000 --- a/Source/Client/ApplicationWindow.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_APPLICATIONWINDOW_H -#define RAGNAROK_SOURCE_CLIENT_APPLICATIONWINDOW_H - -#include - -namespace client { - // Recovered CreateWindowExA wrapper, not the full application initializer. - // Forces the title "Ragnarok 2026" and adds WS_SYSMENU to the caller's style. - HWND CreateApplicationWindow( - DWORD extendedStyle, - const char* className, - const char* ignoredTitle, - DWORD style, - int x, - int y, - int width, - int height, - HWND parent, - HMENU menu, - HINSTANCE instance, - void* parameter - ); - - // Original global main-window handle is borrowed; clips its client rectangle - // after converting both corners to screen coordinates. Returns ClipCursor. - BOOL ClipApplicationCursor(HWND window); -} - -#endif diff --git a/Source/Client/BrowserAddressBar.cpp b/Source/Client/Browser/BrowserAddressBar.cpp similarity index 55% rename from Source/Client/BrowserAddressBar.cpp rename to Source/Client/Browser/BrowserAddressBar.cpp index 9fbd02a..b5b0679 100644 --- a/Source/Client/BrowserAddressBar.cpp +++ b/Source/Client/Browser/BrowserAddressBar.cpp @@ -1,4 +1,4 @@ -#include "Client/BrowserAddressBar.h" +#include "Client/Browser/BrowserAddressBar.h" #include @@ -6,7 +6,10 @@ // FUNCTION: fn_17416 bool BrowserAddressBar::Create(int width, int requestedHeight) { this->rebar = CreateWindowExA( - 0x80, "ReBarWindow32", "rebar", 0x56809648, 0, 0, width, 0, this->host, nullptr, GetModuleHandleA(nullptr), nullptr + WS_EX_TOOLWINDOW, REBARCLASSNAMEA, "rebar", + WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_REGISTERDROP | RBS_DBLCLKTOGGLE | + CCS_NOPARENTALIGN | CCS_NODIVIDER, + 0, 0, width, 0, this->host, nullptr, GetModuleHandleA(nullptr), nullptr ); if (!this->rebar) { return false; @@ -19,33 +22,31 @@ bool BrowserAddressBar::Create(int width, int requestedHeight) { } HWND combo = CreateWindowExA( - 0x200, "COMBOBOX", "addressbar", 0x50000002, 10, 10, 160, 22, this->rebar, nullptr, GetModuleHandleA(nullptr), + WS_EX_CLIENTEDGE, WC_COMBOBOXA, "addressbar", WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, 10, 10, 160, 22, this->rebar, nullptr, GetModuleHandleA(nullptr), nullptr ); REBARBANDINFOA band{}; band.cbSize = sizeof(band); - band.fMask = 0xF1; - band.fStyle = 0x24; + band.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_BACKGROUND; + band.fStyle = RBBS_CHILDEDGE | RBBS_FIXEDBMP; band.hwndChild = combo; band.cxMinChild = 0; band.cyMinChild = requestedHeight; band.cx = 160; band.hbmBack = LoadBitmapA(GetModuleHandleA(nullptr), nullptr); + if (!SendMessageA(this->rebar, RB_INSERTBANDA, static_cast(-1), reinterpret_cast(&band))) { return false; } this->combo = combo; HWND edit = GetWindow(combo, GW_CHILD); - this->previous = - reinterpret_cast(SetWindowLongPtrA(edit, GWLP_WNDPROC, reinterpret_cast(this->procedure))); + this->previous = reinterpret_cast(SetWindowLongPtrA(edit, GWLP_WNDPROC, reinterpret_cast(this->procedure))); RECT rectangle; GetClientRect(this->host, &rectangle); - SetWindowPos( - this->rebar, nullptr, 0, 0, rectangle.right - rectangle.left, rectangle.bottom - rectangle.top, SWP_NOMOVE - ); + SetWindowPos(this->rebar, nullptr, 0, 0, rectangle.right - rectangle.left, rectangle.bottom - rectangle.top, SWP_NOMOVE); ShowWindow(this->rebar, SW_HIDE); this->height = 0; diff --git a/Source/Client/Browser/BrowserAddressBar.h b/Source/Client/Browser/BrowserAddressBar.h new file mode 100644 index 0000000..0058454 --- /dev/null +++ b/Source/Client/Browser/BrowserAddressBar.h @@ -0,0 +1,18 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERADDRESSBAR_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERADDRESSBAR_H + +#include + +struct BrowserAddressBar { + HWND const& host; + HWND& rebar; + HWND& combo; + int& height; + const unsigned char& visible; + WNDPROC& previous; + WNDPROC procedure; + + bool Create(int width, int height); +}; + +#endif diff --git a/Source/Client/BrowserAddressEdit.cpp b/Source/Client/Browser/BrowserAddressEdit.cpp similarity index 67% rename from Source/Client/BrowserAddressEdit.cpp rename to Source/Client/Browser/BrowserAddressEdit.cpp index e20f16e..8907d59 100644 --- a/Source/Client/BrowserAddressEdit.cpp +++ b/Source/Client/Browser/BrowserAddressEdit.cpp @@ -1,4 +1,5 @@ -#include "Client/BrowserAddressEdit.h" +#include "Client/Browser/BrowserAddressEdit.h" +#include "Client/Browser/BrowserMessages.h" // OFFSET: 0x00AB21F0 // FUNCTION: fn_17412 @@ -9,7 +10,7 @@ LRESULT BrowserAddressEdit::Message(HWND window, UINT message, WPARAM value, LPA } if (message == WM_KEYDOWN && this->activeHost) { - SendMessageA(*this->activeHost, WM_COMMAND, 1000, 0); + SendMessageA(*this->activeHost, WM_COMMAND, static_cast(BrowserCommand::Navigate), 0); return 0; } } diff --git a/Source/Client/Browser/BrowserAddressEdit.h b/Source/Client/Browser/BrowserAddressEdit.h new file mode 100644 index 0000000..b71efd1 --- /dev/null +++ b/Source/Client/Browser/BrowserAddressEdit.h @@ -0,0 +1,13 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERADDRESSEDIT_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERADDRESSEDIT_H + +#include + +struct BrowserAddressEdit { + WNDPROC const& previous; + HWND const* const& activeHost; + + LRESULT Message(HWND window, UINT message, WPARAM value, LPARAM flags); +}; + +#endif diff --git a/Source/Client/BrowserClientSite.cpp b/Source/Client/Browser/BrowserClientSite.cpp similarity index 83% rename from Source/Client/BrowserClientSite.cpp rename to Source/Client/Browser/BrowserClientSite.cpp index e1ea9d2..a93b326 100644 --- a/Source/Client/BrowserClientSite.cpp +++ b/Source/Client/Browser/BrowserClientSite.cpp @@ -1,16 +1,10 @@ -#include "Client/BrowserClientSite.h" +#include "Client/Browser/BrowserClientSite.h" // OFFSET: 0x00AB1310 // FUNCTION: fn_17334 -BrowserClientSite::BrowserClientSite( - HWND window, - IUnknown& browser, - BrowserFactory& factory, - const int& width, - const int& height -) - : m_window(window), m_browser(&browser), m_events(*this, factory, width, height), - m_inPlace(*this, this->m_window, this->m_browser), m_documentUI(*this), m_commands(*this) { +BrowserClientSite::BrowserClientSite(HWND window, IUnknown& browser, BrowserFactory& factory, const int& width, const int& height) + : m_window(window), m_browser(&browser), m_events(*this, factory, width, height), m_inPlace(*this, this->m_window, this->m_browser), m_documentUI(*this), + m_commands(*this) { this->m_browser->AddRef(); } @@ -40,8 +34,6 @@ HRESULT STDMETHODCALLTYPE BrowserClientSite::QueryInterface(REFIID iid, void** o } else if (iid == IID_IOleCommandTarget) { *output = static_cast(&this->m_commands); } else { - // Unlike standard COM helpers, the original does not clear a failed output - // and does not AddRef a successful result. return E_NOINTERFACE; } diff --git a/Source/Client/BrowserClientSite.h b/Source/Client/Browser/BrowserClientSite.h similarity index 63% rename from Source/Client/BrowserClientSite.h rename to Source/Client/Browser/BrowserClientSite.h index f5b04f9..f96ae76 100644 --- a/Source/Client/BrowserClientSite.h +++ b/Source/Client/Browser/BrowserClientSite.h @@ -1,16 +1,11 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERCLIENTSITE_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERCLIENTSITE_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCLIENTSITE_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCLIENTSITE_H -#include "Client/BrowserCommandTarget.h" -#include "Client/BrowserDocumentUI.h" -#include "Client/BrowserInPlace.h" -#include "UI/BrowserPopupDispatch.h" +#include "Client/Browser/BrowserCommandTarget.h" +#include "Client/Browser/BrowserDocumentUI.h" +#include "Client/Browser/BrowserInPlace.h" +#include "Client/Browser/BrowserPopupDispatch.h" -// Recovered site COM contracts with its owned popup-dispatch tear-off. -// Factory and renderer dimensions must outlive the site. QueryInterface does -// not acquire references; the containing browser controls this site's lifetime. -// Retains the browser until destruction. COM reference calls return one; -// lifetime is controlled by the containing CWebBrowser, not COM reference counts. class BrowserClientSite final : public IOleClientSite { public: BrowserClientSite(HWND window, IUnknown& browser, BrowserFactory& factory, const int& width, const int& height); diff --git a/Source/Client/BrowserClose.cpp b/Source/Client/Browser/BrowserClose.cpp similarity index 91% rename from Source/Client/BrowserClose.cpp rename to Source/Client/Browser/BrowserClose.cpp index deeff89..f6b8e5b 100644 --- a/Source/Client/BrowserClose.cpp +++ b/Source/Client/Browser/BrowserClose.cpp @@ -1,5 +1,5 @@ -#include "Client/BrowserClose.h" -#include "Client/Mouse.h" +#include "Client/Browser/BrowserClose.h" +#include "Client/Input/Mouse.h" // OFFSET: 0x00AB24D0 // FUNCTION: fn_45432 diff --git a/Source/Client/Browser/BrowserClose.h b/Source/Client/Browser/BrowserClose.h new file mode 100644 index 0000000..136dbe3 --- /dev/null +++ b/Source/Client/Browser/BrowserClose.h @@ -0,0 +1,21 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCLOSE_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCLOSE_H + +#include "Client/Browser/BrowserSiteAttachment.h" + +class CMouse; + +struct BrowserClose { + BrowserSiteAttachment& attachment; + IWebBrowser2*& browser; + IUnknown*& externalEvents; + HWND& host; + HWND const& browserWindow; + HWND const& applicationWindow; + int& cursorState; + CMouse& mouse; + + bool Close(); +}; + +#endif diff --git a/Source/Client/BrowserCommandTarget.cpp b/Source/Client/Browser/BrowserCommandTarget.cpp similarity index 71% rename from Source/Client/BrowserCommandTarget.cpp rename to Source/Client/Browser/BrowserCommandTarget.cpp index f5c759c..4e25efa 100644 --- a/Source/Client/BrowserCommandTarget.cpp +++ b/Source/Client/Browser/BrowserCommandTarget.cpp @@ -1,4 +1,6 @@ -#include "Client/BrowserCommandTarget.h" +#include "Client/Browser/BrowserCommandTarget.h" + +#include // OFFSET: 0x00AB1A80 // FUNCTION: fn_17379 @@ -21,7 +23,6 @@ ULONG STDMETHODCALLTYPE BrowserCommandTarget::Release() { // OFFSET: 0x00AB1C50 // FUNCTION: fn_17385 HRESULT STDMETHODCALLTYPE BrowserCommandTarget::QueryStatus(const GUID*, ULONG, OLECMD[], OLECMDTEXT*) { - // The original reports success without reading or publishing command flags. return S_OK; } @@ -29,15 +30,11 @@ HRESULT STDMETHODCALLTYPE BrowserCommandTarget::QueryStatus(const GUID*, ULONG, // FUNCTION: fn_17353 HRESULT STDMETHODCALLTYPE BrowserCommandTarget::Exec(const GUID* group, DWORD command, DWORD, VARIANT*, VARIANT*) { // STATIC: 0x011B0880 (CGID_DocHostCommandHandler) - static constexpr GUID documentHostCommands = { - 0xF38BC242, 0xB950, 0x11D1, {0x89, 0x18, 0x00, 0xC0, 0x4F, 0xC2, 0xC8, 0x36} - }; - - if (!group || !IsEqualGUID(*group, documentHostCommands)) { + if (!group || !IsEqualGUID(*group, CGID_DocHostCommandHandler)) { return OLECMDERR_E_UNKNOWNGROUP; } - if (command == 40 || command == 41) { + if (command == OLECMDID_SHOWSCRIPTERROR || command == OLECMDID_SHOWMESSAGE) { return S_OK; } diff --git a/Source/Client/BrowserCommandTarget.h b/Source/Client/Browser/BrowserCommandTarget.h similarity index 52% rename from Source/Client/BrowserCommandTarget.h rename to Source/Client/Browser/BrowserCommandTarget.h index 6f36058..c0507f0 100644 --- a/Source/Client/BrowserCommandTarget.h +++ b/Source/Client/Browser/BrowserCommandTarget.h @@ -1,15 +1,10 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERCOMMANDTARGET_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERCOMMANDTARGET_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCOMMANDTARGET_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCOMMANDTARGET_H -// clang-format off #include #include #include -// clang-format on -// CWebBrowser's site owns this tear-off interface. -// Identity delegates to that site; AddRef/Release deliberately return one. -// The caller must keep the site alive for this interface's entire lifetime. class BrowserCommandTarget final : public IOleCommandTarget { public: explicit BrowserCommandTarget(IUnknown& site) : m_site(site) { @@ -19,8 +14,7 @@ public: ULONG STDMETHODCALLTYPE AddRef() override; ULONG STDMETHODCALLTYPE Release() override; HRESULT STDMETHODCALLTYPE QueryStatus(const GUID* group, ULONG count, OLECMD commands[], OLECMDTEXT* text) override; - HRESULT STDMETHODCALLTYPE - Exec(const GUID* group, DWORD command, DWORD options, VARIANT* input, VARIANT* output) override; + HRESULT STDMETHODCALLTYPE Exec(const GUID* group, DWORD command, DWORD options, VARIANT* input, VARIANT* output) override; private: IUnknown& m_site; diff --git a/Source/Client/BrowserCreation.cpp b/Source/Client/Browser/BrowserCreation.cpp similarity index 82% rename from Source/Client/BrowserCreation.cpp rename to Source/Client/Browser/BrowserCreation.cpp index cd7c230..b620c63 100644 --- a/Source/Client/BrowserCreation.cpp +++ b/Source/Client/Browser/BrowserCreation.cpp @@ -1,5 +1,5 @@ -#include "Client/BrowserCreation.h" -#include "Client/BrowserInterface.h" +#include "Client/Browser/BrowserCreation.h" +#include "Client/Browser/BrowserInterface.h" // OFFSET: 0x00AB22B0 // FUNCTION: fn_17413 diff --git a/Source/Client/Browser/BrowserCreation.h b/Source/Client/Browser/BrowserCreation.h new file mode 100644 index 0000000..8b57562 --- /dev/null +++ b/Source/Client/Browser/BrowserCreation.h @@ -0,0 +1,18 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCREATION_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCREATION_H + +#include "Client/Browser/BrowserAddressBar.h" +#include "Client/Browser/BrowserHostWindow.h" +#include "Client/Browser/BrowserSiteAttachment.h" + +struct BrowserCreation { + IWebBrowser2*& browser; + HWND& browserWindow; + BrowserHostWindow& window; + BrowserSiteAttachment& attachment; + BrowserAddressBar& addressBar; + + bool Create(HWND parent, HINSTANCE instance, int width, int height); +}; + +#endif diff --git a/Source/Client/BrowserCursor.cpp b/Source/Client/Browser/BrowserCursor.cpp similarity index 73% rename from Source/Client/BrowserCursor.cpp rename to Source/Client/Browser/BrowserCursor.cpp index 329aef8..62762f3 100644 --- a/Source/Client/BrowserCursor.cpp +++ b/Source/Client/Browser/BrowserCursor.cpp @@ -1,5 +1,5 @@ -#include "Client/BrowserCursor.h" -#include "Client/Mouse.h" +#include "Client/Browser/BrowserCursor.h" +#include "Client/Input/Mouse.h" #include "Render/RenderSystemBase.h" // OFFSET: 0x00AB32E0 @@ -10,9 +10,8 @@ void BrowserCursor::Set(int value) { } if (value != 0) { - SetCursor(LoadCursorA(nullptr, MAKEINTRESOURCEA(32512))); - // Original mouse centering queries Width then Height before replacing - // both coordinates with -100. Retain these virtual calls and their order. + SetCursor(LoadCursorA(nullptr, reinterpret_cast(IDC_ARROW))); + this->mouse.SetX(static_cast(this->renderSystem.Width()) / 2); this->mouse.SetY(static_cast(this->renderSystem.Height()) / 2); this->mouse.SetX(-100); diff --git a/Source/Client/Browser/BrowserCursor.h b/Source/Client/Browser/BrowserCursor.h new file mode 100644 index 0000000..3a46459 --- /dev/null +++ b/Source/Client/Browser/BrowserCursor.h @@ -0,0 +1,19 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCURSOR_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERCURSOR_H + +#include + +class CMouse; +class CRenderSystemBase; + +struct BrowserCursor { + int& state; + CMouse& mouse; + CRenderSystemBase& renderSystem; + HWND const& applicationWindow; + + void Set(int value); + void Poll(); +}; + +#endif diff --git a/Source/Client/BrowserDocumentUI.cpp b/Source/Client/Browser/BrowserDocumentUI.cpp similarity index 86% rename from Source/Client/BrowserDocumentUI.cpp rename to Source/Client/Browser/BrowserDocumentUI.cpp index d7d49fd..8518804 100644 --- a/Source/Client/BrowserDocumentUI.cpp +++ b/Source/Client/Browser/BrowserDocumentUI.cpp @@ -1,4 +1,4 @@ -#include "Client/BrowserDocumentUI.h" +#include "Client/Browser/BrowserDocumentUI.h" // OFFSET: 0x00AB1AC0 // FUNCTION: fn_17381 @@ -27,23 +27,16 @@ HRESULT STDMETHODCALLTYPE BrowserDocumentUI::ShowContextMenu(DWORD, POINT*, IUnk // OFFSET: 0x00AB1770 // FUNCTION: fn_17359 HRESULT STDMETHODCALLTYPE BrowserDocumentUI::GetHostInfo(DOCHOSTUIINFO* info) { - // Original x86 cbSize, even when compiling for a wider host. The two optional - // string pointers are not initialized by this operation. - info->cbSize = 20; - info->dwFlags = 4; - info->dwDoubleClick = 0; + info->cbSize = sizeof(*info); + info->dwFlags = DOCHOSTUIFLAG_NO3DBORDER; + info->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; + return S_OK; } // OFFSET: 0x00AB1D80 // FUNCTION: fn_17404 -HRESULT STDMETHODCALLTYPE BrowserDocumentUI::ShowUI( - DWORD, - IOleInPlaceActiveObject*, - IOleCommandTarget*, - IOleInPlaceFrame*, - IOleInPlaceUIWindow* -) { +HRESULT STDMETHODCALLTYPE BrowserDocumentUI::ShowUI(DWORD, IOleInPlaceActiveObject*, IOleCommandTarget*, IOleInPlaceFrame*, IOleInPlaceUIWindow*) { return S_OK; } diff --git a/Source/Client/BrowserDocumentUI.h b/Source/Client/Browser/BrowserDocumentUI.h similarity index 76% rename from Source/Client/BrowserDocumentUI.h rename to Source/Client/Browser/BrowserDocumentUI.h index 0292932..aaae4f1 100644 --- a/Source/Client/BrowserDocumentUI.h +++ b/Source/Client/Browser/BrowserDocumentUI.h @@ -1,14 +1,10 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERDOCUMENTUI_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERDOCUMENTUI_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERDOCUMENTUI_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERDOCUMENTUI_H -// clang-format off #include #include #include -// clang-format on -// Site-owned IDocHostUIHandler tear-off. Identity delegates to the borrowed -// site; reference calls do not manage lifetime. Unwritten outputs stay unwritten. class BrowserDocumentUI final : public IDocHostUIHandler { public: explicit BrowserDocumentUI(IUnknown& site) : m_site(site) { @@ -19,13 +15,8 @@ public: ULONG STDMETHODCALLTYPE Release() override; HRESULT STDMETHODCALLTYPE ShowContextMenu(DWORD id, POINT* point, IUnknown* reserved, IDispatch* dispatch) override; HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO* info) override; - HRESULT STDMETHODCALLTYPE ShowUI( - DWORD id, - IOleInPlaceActiveObject* active, - IOleCommandTarget* commands, - IOleInPlaceFrame* frame, - IOleInPlaceUIWindow* document - ) override; + HRESULT STDMETHODCALLTYPE + ShowUI(DWORD id, IOleInPlaceActiveObject* active, IOleCommandTarget* commands, IOleInPlaceFrame* frame, IOleInPlaceUIWindow* document) override; HRESULT STDMETHODCALLTYPE HideUI() override; HRESULT STDMETHODCALLTYPE UpdateUI() override; HRESULT STDMETHODCALLTYPE EnableModeless(BOOL enable) override; diff --git a/Source/UI/BrowserFactory.cpp b/Source/Client/Browser/BrowserFactory.cpp similarity index 79% rename from Source/UI/BrowserFactory.cpp rename to Source/Client/Browser/BrowserFactory.cpp index 1fe95db..ca0a60c 100644 --- a/Source/UI/BrowserFactory.cpp +++ b/Source/Client/Browser/BrowserFactory.cpp @@ -1,8 +1,8 @@ -#include "Client/BrowserRegistry.h" -#include "Client/WebBrowser.h" +#include "Client/Browser/BrowserRegistry.h" +#include "Client/Browser/WebBrowser.h" #include "Contents/MessageTable.h" -#include "UI/BrowserFactory.h" -#include "UI/ChatNotifications.h" +#include "Client/Browser/BrowserFactory.h" +#include "UI/Chat/ChatNotifications.h" #include @@ -13,6 +13,7 @@ CWebBrowser* BrowserFactory::Create(int width, int height) { this->notifications.Refresh(); const char* message = LookupMessage(1578, this->languagePrefix, this->serviceType, this->language); this->notifications.Text(message, 255, nullptr, 0, false); + return nullptr; } diff --git a/Source/UI/BrowserFactory.h b/Source/Client/Browser/BrowserFactory.h similarity index 53% rename from Source/UI/BrowserFactory.h rename to Source/Client/Browser/BrowserFactory.h index 561a898..bbc9601 100644 --- a/Source/UI/BrowserFactory.h +++ b/Source/Client/Browser/BrowserFactory.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_BROWSERFACTORY_H -#define RAGNAROK_SOURCE_UI_BROWSERFACTORY_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERFACTORY_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERFACTORY_H #include @@ -8,9 +8,6 @@ struct WebBrowserContext; struct BrowserRegistry; struct ChatNotifications; -// Ordinary browser creation is distinct from the special-browser factory. -// The limit counts all map nodes, not nonnull entries. Failed ordinary creation -// retains the allocated browser in the original; it is not published or deleted. struct BrowserFactory { BrowserRegistry& registry; WebBrowserContext& context; diff --git a/Source/Client/BrowserFrame.cpp b/Source/Client/Browser/BrowserFrame.cpp similarity index 82% rename from Source/Client/BrowserFrame.cpp rename to Source/Client/Browser/BrowserFrame.cpp index eed1086..886529d 100644 --- a/Source/Client/BrowserFrame.cpp +++ b/Source/Client/Browser/BrowserFrame.cpp @@ -1,4 +1,4 @@ -#include "Client/BrowserFrame.h" +#include "Client/Browser/BrowserFrame.h" // OFFSET: 0x00AB2610 // FUNCTION: fn_17414 @@ -9,10 +9,7 @@ void BrowserFrame::Normalize() { RECT rectangle; GetWindowRect(this->browserWindow, &rectangle); - if ( - rectangle.right - rectangle.left != this->sizing.screenWidth || - rectangle.bottom - rectangle.top != this->sizing.screenHeight - ) { + if (rectangle.right - rectangle.left != this->sizing.screenWidth || rectangle.bottom - rectangle.top != this->sizing.screenHeight) { return; } diff --git a/Source/Client/Browser/BrowserFrame.h b/Source/Client/Browser/BrowserFrame.h new file mode 100644 index 0000000..dec5b06 --- /dev/null +++ b/Source/Client/Browser/BrowserFrame.h @@ -0,0 +1,18 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERFRAME_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERFRAME_H + +#include "Client/Browser/BrowserCursor.h" +#include "Client/Browser/BrowserWindowSizing.h" + +struct BrowserFrame { + BrowserWindowSizing& sizing; + BrowserCursor& cursor; + HWND const& host; + HWND const& browserWindow; + const bool& hasExternalEvents; + + void Normalize(); + void Poll(); +}; + +#endif diff --git a/Source/Client/BrowserHostWindow.cpp b/Source/Client/Browser/BrowserHostWindow.cpp similarity index 76% rename from Source/Client/BrowserHostWindow.cpp rename to Source/Client/Browser/BrowserHostWindow.cpp index 10bc55c..2a3d15f 100644 --- a/Source/Client/BrowserHostWindow.cpp +++ b/Source/Client/Browser/BrowserHostWindow.cpp @@ -1,4 +1,4 @@ -#include "Client/BrowserHostWindow.h" +#include "Client/Browser/BrowserHostWindow.h" // OFFSET: 0x00AB29D0 // FUNCTION: fn_45435 @@ -11,10 +11,7 @@ bool BrowserHostWindow::Create(HWND parent, HINSTANCE instance, int width, int h windowClass.lpszClassName = "ROWebBrowser"; RegisterClassExA(&windowClass); - this->host = CreateWindowExA( - 0, "ROWebBrowser", this->title, WS_POPUP | WS_OVERLAPPEDWINDOW, 0, 0, width, height, parent, nullptr, instance, - nullptr - ); + this->host = CreateWindowExA(0, "ROWebBrowser", this->title, WS_POPUP | WS_OVERLAPPEDWINDOW, 0, 0, width, height, parent, nullptr, instance, nullptr); if (!this->host) { OutputDebugStringA("failed : CreateWindow() \n"); return false; @@ -23,5 +20,6 @@ bool BrowserHostWindow::Create(HWND parent, HINSTANCE instance, int width, int h UpdateWindow(this->host); SetParent(this->browser, this->host); SetWindowLongA(this->browser, GWL_STYLE, WS_CHILD); + return true; } diff --git a/Source/Client/Browser/BrowserHostWindow.h b/Source/Client/Browser/BrowserHostWindow.h new file mode 100644 index 0000000..eb3183b --- /dev/null +++ b/Source/Client/Browser/BrowserHostWindow.h @@ -0,0 +1,15 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERHOSTWINDOW_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERHOSTWINDOW_H + +#include + +struct BrowserHostWindow { + HWND& host; + HWND const& browser; + const char* const& title; + WNDPROC procedure; + + bool Create(HWND parent, HINSTANCE instance, int width, int height); +}; + +#endif diff --git a/Source/Client/BrowserInPlace.cpp b/Source/Client/Browser/BrowserInPlace.cpp similarity index 92% rename from Source/Client/BrowserInPlace.cpp rename to Source/Client/Browser/BrowserInPlace.cpp index ef555ba..42be356 100644 --- a/Source/Client/BrowserInPlace.cpp +++ b/Source/Client/Browser/BrowserInPlace.cpp @@ -1,4 +1,4 @@ -#include "Client/BrowserInPlace.h" +#include "Client/Browser/BrowserInPlace.h" // OFFSET: 0x00AB1AE0 // FUNCTION: fn_17382 @@ -142,19 +142,15 @@ HRESULT STDMETHODCALLTYPE BrowserInPlaceSite::OnUIActivate() { // OFFSET: 0x00AB1820 // FUNCTION: fn_17367 -HRESULT STDMETHODCALLTYPE BrowserInPlaceSite::GetWindowContext( - IOleInPlaceFrame** frame, - IOleInPlaceUIWindow** document, - RECT*, - RECT*, - OLEINPLACEFRAMEINFO* info -) { +HRESULT STDMETHODCALLTYPE +BrowserInPlaceSite::GetWindowContext(IOleInPlaceFrame** frame, IOleInPlaceUIWindow** document, RECT*, RECT*, OLEINPLACEFRAMEINFO* info) { *frame = &this->m_frame; *document = nullptr; info->fMDIApp = FALSE; info->hwndFrame = this->m_window; info->haccel = nullptr; info->cAccelEntries = 0; + return S_OK; } @@ -191,8 +187,6 @@ HRESULT STDMETHODCALLTYPE BrowserInPlaceSite::DeactivateAndUndo() { // OFFSET: 0x00AB19F0 // FUNCTION: fn_17375 HRESULT STDMETHODCALLTYPE BrowserInPlaceSite::OnPosRectChange(const RECT* position) { - // The original requires an attached browser and retains this IOleObject - // reference, including when its subsequent in-place QueryInterface fails. IOleObject* object; HRESULT result = this->m_browser->QueryInterface(IID_IOleObject, reinterpret_cast(&object)); if (SUCCEEDED(result)) { diff --git a/Source/Client/BrowserInPlace.h b/Source/Client/Browser/BrowserInPlace.h similarity index 80% rename from Source/Client/BrowserInPlace.h rename to Source/Client/Browser/BrowserInPlace.h index 5308741..375b11b 100644 --- a/Source/Client/BrowserInPlace.h +++ b/Source/Client/Browser/BrowserInPlace.h @@ -1,13 +1,9 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERINPLACE_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERINPLACE_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERINPLACE_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERINPLACE_H -// clang-format off #include #include -// clang-format on -// Site-owned tear-offs: borrowed identity, HWND and browser, with fixed-one -// reference counts. These interfaces do not own or extend the site's lifetime. class BrowserInPlaceFrame final : public IOleInPlaceFrame { public: BrowserInPlaceFrame(IUnknown& site, HWND const& window) : m_site(site), m_window(window) { @@ -36,8 +32,7 @@ private: class BrowserInPlaceSite final : public IOleInPlaceSite { public: - BrowserInPlaceSite(IUnknown& site, HWND const& window, IUnknown* const& browser) - : m_site(site), m_window(window), m_browser(browser), m_frame(site, window) { + BrowserInPlaceSite(IUnknown& site, HWND const& window, IUnknown* const& browser) : m_site(site), m_window(window), m_browser(browser), m_frame(site, window) { } HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** output) override; @@ -48,13 +43,8 @@ public: HRESULT STDMETHODCALLTYPE CanInPlaceActivate() override; HRESULT STDMETHODCALLTYPE OnInPlaceActivate() override; HRESULT STDMETHODCALLTYPE OnUIActivate() override; - HRESULT STDMETHODCALLTYPE GetWindowContext( - IOleInPlaceFrame** frame, - IOleInPlaceUIWindow** document, - RECT* position, - RECT* clip, - OLEINPLACEFRAMEINFO* info - ) override; + HRESULT STDMETHODCALLTYPE + GetWindowContext(IOleInPlaceFrame** frame, IOleInPlaceUIWindow** document, RECT* position, RECT* clip, OLEINPLACEFRAMEINFO* info) override; HRESULT STDMETHODCALLTYPE Scroll(SIZE extent) override; HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL undoable) override; HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() override; diff --git a/Source/Client/BrowserInputHandoff.cpp b/Source/Client/Browser/BrowserInputHandoff.cpp similarity index 66% rename from Source/Client/BrowserInputHandoff.cpp rename to Source/Client/Browser/BrowserInputHandoff.cpp index b1e53b1..f0a09cf 100644 --- a/Source/Client/BrowserInputHandoff.cpp +++ b/Source/Client/Browser/BrowserInputHandoff.cpp @@ -1,17 +1,17 @@ -#include "Client/ApplicationActivation.h" -#include "Client/BrowserInputHandoff.h" -#include "Client/Mouse.h" -#include "Contents/ServiceOptions.h" +#include "Client/Application/ApplicationActivation.h" +#include "Client/Browser/BrowserInputHandoff.h" +#include "Client/Input/Mouse.h" +#include "Contents/Configuration/ServiceOptions.h" // OFFSET: 0x00AB2720 // FUNCTION: fn_45433 void BrowserInputHandoff::Enter() { - if (this->service.Get(271) == 0) { + if (this->service.Get(ServiceOption::ConfineCursor) == 0) { return; } POINT position{this->mouse.x, this->mouse.y}; - this->service.Set(271, 0); + this->service.Set(ServiceOption::ConfineCursor, 0); this->mouse.SetX(position.x); this->mouse.SetY(position.y); this->restoreOption = 1; @@ -29,7 +29,7 @@ void BrowserInputHandoff::Restore() { POINT position; GetCursorPos(&position); ScreenToClient(this->applicationWindow, &position); - this->service.Set(271, 1); + this->service.Set(ServiceOption::ConfineCursor, 1); this->mouse.SetX(position.x); this->mouse.SetY(position.y); SetActiveWindow(this->applicationWindow); diff --git a/Source/Client/Browser/BrowserInputHandoff.h b/Source/Client/Browser/BrowserInputHandoff.h new file mode 100644 index 0000000..3e47b10 --- /dev/null +++ b/Source/Client/Browser/BrowserInputHandoff.h @@ -0,0 +1,21 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERINPUTHANDOFF_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERINPUTHANDOFF_H + +#include + +class CMouse; +struct ServiceOptions; +struct ApplicationActivation; + +struct BrowserInputHandoff { + unsigned char& restoreOption; + HWND const& applicationWindow; + ServiceOptions& service; + CMouse& mouse; + ApplicationActivation& activation; + + void Enter(); + void Restore(); +}; + +#endif diff --git a/Source/Client/BrowserInterface.cpp b/Source/Client/Browser/BrowserInterface.cpp similarity index 83% rename from Source/Client/BrowserInterface.cpp rename to Source/Client/Browser/BrowserInterface.cpp index 823f023..c2cc374 100644 --- a/Source/Client/BrowserInterface.cpp +++ b/Source/Client/Browser/BrowserInterface.cpp @@ -1,4 +1,4 @@ -#include "Client/BrowserInterface.h" +#include "Client/Browser/BrowserInterface.h" #include #include @@ -6,19 +6,17 @@ // OFFSET: 0x00AB2CD0 // FUNCTION: fn_45437 bool CreateBrowserInterface(IWebBrowser2*& browser, HWND& window) { - const HRESULT result = CoCreateInstance( - CLSID_WebBrowser, nullptr, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, IID_IWebBrowser2, - reinterpret_cast(&browser) - ); + const HRESULT result = + CoCreateInstance(CLSID_WebBrowser, nullptr, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, IID_IWebBrowser2, reinterpret_cast(&browser)); if (FAILED(result)) { OutputDebugStringA("error : MakeWebBrowserInterface_InProc FAILED \n"); HLOCAL message = nullptr; FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, - GetLastError(), 0, reinterpret_cast(&message), 0, nullptr + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(), 0, + reinterpret_cast(&message), 0, nullptr ); - // The reference locks and reports this buffer without freeing it. + OutputDebugStringA(static_cast(LocalLock(message))); return false; } @@ -33,18 +31,17 @@ bool CreateBrowserInterface(IWebBrowser2*& browser, HWND& window) { // OFFSET: 0x00AB2C10 // FUNCTION: fn_45436 bool CreateExternalBrowserInterface(IWebBrowser2*& browser, HWND& window, HWND const& host) { - const HRESULT result = CoCreateInstance( - CLSID_InternetExplorer, nullptr, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, reinterpret_cast(&browser) - ); + const HRESULT result = CoCreateInstance(CLSID_InternetExplorer, nullptr, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, reinterpret_cast(&browser)); if (FAILED(result)) { OutputDebugStringA("error : MakeWebBrowserInterface FAILED \n"); HLOCAL message = nullptr; FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, - GetLastError(), 0, reinterpret_cast(&message), 0, nullptr + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(), 0, + reinterpret_cast(&message), 0, nullptr ); OutputDebugStringA(static_cast(LocalLock(message))); + return false; } @@ -103,6 +100,7 @@ HRESULT AdviseBrowserEvents(IUnknown* source, IUnknown* sink, REFIID events, DWO IConnectionPointContainer* container = nullptr; IConnectionPoint* point = nullptr; HRESULT result = source->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast(&container)); + if (SUCCEEDED(result)) { result = container->FindConnectionPoint(events, &point); if (SUCCEEDED(result)) { @@ -113,9 +111,11 @@ HRESULT AdviseBrowserEvents(IUnknown* source, IUnknown* sink, REFIID events, DWO if (point) { point->Release(); } + if (container) { container->Release(); } + return result; } @@ -129,6 +129,7 @@ HRESULT UnadviseBrowserEvents(IUnknown* source, REFIID events, DWORD cookie) { IConnectionPointContainer* container = nullptr; IConnectionPoint* point = nullptr; HRESULT result = source->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast(&container)); + if (SUCCEEDED(result)) { result = container->FindConnectionPoint(events, &point); if (SUCCEEDED(result)) { @@ -139,8 +140,10 @@ HRESULT UnadviseBrowserEvents(IUnknown* source, REFIID events, DWORD cookie) { if (point) { point->Release(); } + if (container) { container->Release(); } + return result; } diff --git a/Source/Client/Browser/BrowserInterface.h b/Source/Client/Browser/BrowserInterface.h new file mode 100644 index 0000000..c09cd23 --- /dev/null +++ b/Source/Client/Browser/BrowserInterface.h @@ -0,0 +1,19 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERINTERFACE_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERINTERFACE_H + +#include +#include +#include + +#include + +bool CreateBrowserInterface(IWebBrowser2*& browser, HWND& window); + +bool CreateExternalBrowserInterface(IWebBrowser2*& browser, HWND& window, HWND const& host); + +bool NavigateBrowser(IWebBrowser2* const& browser, HWND const& host, HWND const& title, std::string address); + +HRESULT AdviseBrowserEvents(IUnknown* source, IUnknown* sink, REFIID events, DWORD* cookie); +HRESULT UnadviseBrowserEvents(IUnknown* source, REFIID events, DWORD cookie); + +#endif diff --git a/Source/Client/BrowserMessages.cpp b/Source/Client/Browser/BrowserMessages.cpp similarity index 83% rename from Source/Client/BrowserMessages.cpp rename to Source/Client/Browser/BrowserMessages.cpp index b3ffcf5..cdf4736 100644 --- a/Source/Client/BrowserMessages.cpp +++ b/Source/Client/Browser/BrowserMessages.cpp @@ -1,6 +1,6 @@ -#include "Client/BrowserMessages.h" -#include "Client/BrowserRegistry.h" -#include "Client/WebBrowser.h" +#include "Client/Browser/BrowserMessages.h" +#include "Client/Browser/BrowserRegistry.h" +#include "Client/Browser/WebBrowser.h" #include @@ -36,7 +36,7 @@ LRESULT BrowserMessages::Message(HWND window, UINT message, WPARAM value, LPARAM } break; case WM_COMMAND: - if (static_cast(value) == 1000 && browser) { + if (LOWORD(value) == static_cast(BrowserCommand::Navigate) && browser) { char address[512]; GetWindowTextA(browser->combo, address, sizeof(address)); browser->Navigate(address); diff --git a/Source/Client/BrowserMessages.h b/Source/Client/Browser/BrowserMessages.h similarity index 51% rename from Source/Client/BrowserMessages.h rename to Source/Client/Browser/BrowserMessages.h index a21549d..9bb9d08 100644 --- a/Source/Client/BrowserMessages.h +++ b/Source/Client/Browser/BrowserMessages.h @@ -1,13 +1,13 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERMESSAGES_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERMESSAGES_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERMESSAGES_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERMESSAGES_H #include class CWebBrowser; struct BrowserRegistry; -// Borrowed UIWindowMgr browser registry, active browser and main HWND. -// Caller installs its native thunk; this implements the entire original body. +enum class BrowserCommand : WORD { Navigate = 1000 }; + struct BrowserMessages { BrowserRegistry& registry; CWebBrowser*& active; diff --git a/Source/UI/BrowserPopupDispatch.cpp b/Source/Client/Browser/BrowserPopupDispatch.cpp similarity index 68% rename from Source/UI/BrowserPopupDispatch.cpp rename to Source/Client/Browser/BrowserPopupDispatch.cpp index e095bb2..2614a83 100644 --- a/Source/UI/BrowserPopupDispatch.cpp +++ b/Source/Client/Browser/BrowserPopupDispatch.cpp @@ -1,10 +1,11 @@ -#include "Client/WebBrowser.h" -#include "UI/BrowserFactory.h" -#include "UI/BrowserPopupDispatch.h" +#include "Client/Browser/WebBrowser.h" +#include "Client/Browser/BrowserFactory.h" +#include "Client/Browser/BrowserPopupDispatch.h" +#include "Utility/Math/ScalarConversion.h" +#include #include #include -#include // OFFSET: 0x00AB1AA0 // FUNCTION: fn_17380 @@ -44,23 +45,22 @@ HRESULT STDMETHODCALLTYPE BrowserPopupDispatch::GetIDsOfNames(REFIID, LPOLESTR*, // OFFSET: 0x00AB1880 // FUNCTION: fn_17370 -HRESULT STDMETHODCALLTYPE -BrowserPopupDispatch::Invoke(DISPID id, REFIID, LCID, WORD, DISPPARAMS* args, VARIANT*, EXCEPINFO*, UINT*) { - if (id != 273) { +HRESULT STDMETHODCALLTYPE BrowserPopupDispatch::Invoke(DISPID id, REFIID, LCID, WORD, DISPPARAMS* args, VARIANT*, EXCEPINFO*, UINT*) { + if (id != DISPID_NEWWINDOW3) { return S_OK; } const wchar_t* url = args->rgvarg[0].bstrVal; - // Original writes literal 11 through Cancel's by-reference boolean. Preserve - // that noncanonical true value, and write it before the factory callback. + *args->rgvarg[3].pboolVal = 11; // STATIC: 0x01115448 // GLOBAL: gl_13426 - const __m128 scale = _mm_set_ss(0.7f); - const int height = _mm_cvtt_ss2si(_mm_mul_ss(_mm_cvtsi32_ss(_mm_setzero_ps(), this->m_height), scale)); - const int width = _mm_cvtt_ss2si(_mm_mul_ss(_mm_cvtsi32_ss(_mm_setzero_ps(), this->m_width), scale)); + const float scale = 0.7f; + const int height = TruncateToInt(static_cast(this->m_height) * scale); + const int width = TruncateToInt(static_cast(this->m_width) * scale); CWebBrowser* browser = this->m_factory.Create(width, height); + if (!browser) { return S_OK; } @@ -70,5 +70,6 @@ BrowserPopupDispatch::Invoke(DISPID id, REFIID, LCID, WORD, DISPPARAMS* args, VA WideCharToMultiByte(CP_ACP, 0, url, -1, converted.get(), static_cast(length), nullptr, nullptr); converted[length] = '\0'; browser->Navigate(converted.get()); + return S_OK; } diff --git a/Source/UI/BrowserPopupDispatch.h b/Source/Client/Browser/BrowserPopupDispatch.h similarity index 61% rename from Source/UI/BrowserPopupDispatch.h rename to Source/Client/Browser/BrowserPopupDispatch.h index fb31ec0..0e7651f 100644 --- a/Source/UI/BrowserPopupDispatch.h +++ b/Source/Client/Browser/BrowserPopupDispatch.h @@ -1,16 +1,11 @@ -#ifndef RAGNAROK_SOURCE_UI_BROWSERPOPUPDISPATCH_H -#define RAGNAROK_SOURCE_UI_BROWSERPOPUPDISPATCH_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERPOPUPDISPATCH_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERPOPUPDISPATCH_H -// clang-format off #include #include -// clang-format on struct BrowserFactory; -// Site-owned dispatch tear-off. Identity and renderer dimensions are borrowed. -// Fixed-one reference methods match the other site tear-offs, not -// CWebEventReceiver's independently reference-counted lifetime. class BrowserPopupDispatch final : public IDispatch { public: BrowserPopupDispatch(IUnknown& site, BrowserFactory& factory, const int& width, const int& height) @@ -23,16 +18,8 @@ public: HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* count) override; HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT index, LCID locale, ITypeInfo** output) override; HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID iid, LPOLESTR* names, UINT count, LCID locale, DISPID* ids) override; - HRESULT STDMETHODCALLTYPE Invoke( - DISPID id, - REFIID iid, - LCID locale, - WORD flags, - DISPPARAMS* args, - VARIANT* result, - EXCEPINFO* error, - UINT* argumentError - ) override; + HRESULT STDMETHODCALLTYPE + Invoke(DISPID id, REFIID iid, LCID locale, WORD flags, DISPPARAMS* args, VARIANT* result, EXCEPINFO* error, UINT* argumentError) override; private: IUnknown& m_site; diff --git a/Source/Client/BrowserRegistry.cpp b/Source/Client/Browser/BrowserRegistry.cpp similarity index 84% rename from Source/Client/BrowserRegistry.cpp rename to Source/Client/Browser/BrowserRegistry.cpp index b7be741..6153ca0 100644 --- a/Source/Client/BrowserRegistry.cpp +++ b/Source/Client/Browser/BrowserRegistry.cpp @@ -1,5 +1,5 @@ -#include "Client/BrowserRegistry.h" -#include "Client/WebBrowser.h" +#include "Client/Browser/BrowserRegistry.h" +#include "Client/Browser/WebBrowser.h" #include @@ -28,8 +28,6 @@ void BrowserRegistry::Remove(HWND window) { return; } - // The reference dereferences the special browser on this miss path before - // checking it; a nonnull special owner is a caller precondition here. if (window == this->special->host) { delete this->special; this->special = nullptr; diff --git a/Source/Client/BrowserRegistry.h b/Source/Client/Browser/BrowserRegistry.h similarity index 51% rename from Source/Client/BrowserRegistry.h rename to Source/Client/Browser/BrowserRegistry.h index a7c72b7..833a529 100644 --- a/Source/Client/BrowserRegistry.h +++ b/Source/Client/Browser/BrowserRegistry.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERREGISTRY_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERREGISTRY_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERREGISTRY_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERREGISTRY_H #include #include @@ -7,9 +7,6 @@ class CWebBrowser; struct WebBrowserContext; -// Borrowed UIWindowMgr browser map and special-browser pointer. -// Map nodes survive browser destruction, permitting native callbacks to look up -// the original entry. The special alias is cleared before mapped destruction. struct BrowserRegistry { std::map& browsers; CWebBrowser*& special; diff --git a/Source/Client/BrowserSiteAttachment.cpp b/Source/Client/Browser/BrowserSiteAttachment.cpp similarity index 84% rename from Source/Client/BrowserSiteAttachment.cpp rename to Source/Client/Browser/BrowserSiteAttachment.cpp index 766e99a..60dd508 100644 --- a/Source/Client/BrowserSiteAttachment.cpp +++ b/Source/Client/Browser/BrowserSiteAttachment.cpp @@ -1,5 +1,5 @@ -#include "Client/BrowserInterface.h" -#include "Client/BrowserSiteAttachment.h" +#include "Client/Browser/BrowserInterface.h" +#include "Client/Browser/BrowserSiteAttachment.h" #include #include @@ -7,8 +7,7 @@ // OFFSET: 0x00AB2AB0 // FUNCTION: fn_17417 bool BrowserSiteAttachment::Attach() { - this->site = new (std::nothrow) - BrowserClientSite(this->host, *this->sizing.browser, this->factory, this->renderWidth, this->renderHeight); + this->site = new (std::nothrow) BrowserClientSite(this->host, *this->sizing.browser, this->factory, this->renderWidth, this->renderHeight); IOleObject* object; HRESULT result = this->sizing.browser->QueryInterface(IID_IOleObject, reinterpret_cast(&object)); @@ -22,6 +21,7 @@ bool BrowserSiteAttachment::Attach() { RECT rectangle; GetClientRect(this->host, &rectangle); result = object->DoVerb(OLEIVERB_INPLACEACTIVATE, nullptr, this->site, 0, this->host, &rectangle); + if (SUCCEEDED(result)) { const int width = rectangle.right - rectangle.left; const int height = rectangle.bottom - rectangle.top; diff --git a/Source/Client/Browser/BrowserSiteAttachment.h b/Source/Client/Browser/BrowserSiteAttachment.h new file mode 100644 index 0000000..09cc780 --- /dev/null +++ b/Source/Client/Browser/BrowserSiteAttachment.h @@ -0,0 +1,20 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERSITEATTACHMENT_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERSITEATTACHMENT_H + +#include "Client/Browser/BrowserClientSite.h" +#include "Client/Browser/BrowserWindowSizing.h" + +struct BrowserSiteAttachment { + BrowserWindowSizing& sizing; + HWND const& host; + BrowserClientSite*& site; + DWORD& cookie; + BrowserFactory& factory; + const int& renderWidth; + const int& renderHeight; + + bool Attach(); + void Detach(); +}; + +#endif diff --git a/Source/Client/BrowserWindowSizing.cpp b/Source/Client/Browser/BrowserWindowSizing.cpp similarity index 97% rename from Source/Client/BrowserWindowSizing.cpp rename to Source/Client/Browser/BrowserWindowSizing.cpp index 718d6cc..164b819 100644 --- a/Source/Client/BrowserWindowSizing.cpp +++ b/Source/Client/Browser/BrowserWindowSizing.cpp @@ -1,4 +1,4 @@ -#include "Client/BrowserWindowSizing.h" +#include "Client/Browser/BrowserWindowSizing.h" // OFFSET: 0x00AB3060 // FUNCTION: fn_17421 @@ -67,6 +67,7 @@ void BrowserAuxiliaryVisibility::Show(unsigned char value) { GetClientRect(this->sizing.auxiliary, &rectangle); top = rectangle.bottom - rectangle.top + 4; } + this->sizing.browser->put_Top(top); RECT rectangle; diff --git a/Source/Client/BrowserWindowSizing.h b/Source/Client/Browser/BrowserWindowSizing.h similarity index 50% rename from Source/Client/BrowserWindowSizing.h rename to Source/Client/Browser/BrowserWindowSizing.h index ea7a294..1448868 100644 --- a/Source/Client/BrowserWindowSizing.h +++ b/Source/Client/Browser/BrowserWindowSizing.h @@ -1,14 +1,10 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERWINDOWSIZING_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERWINDOWSIZING_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERWINDOWSIZING_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_BROWSERWINDOWSIZING_H -// clang-format off #include #include #include -// clang-format on -// Borrowed IWebBrowser2 and original browser-owner dimensions. COM lifetime, -// activation and navigation are separate; this view owns no references. struct BrowserWindowSizing { IWebBrowser2* const& browser; const int& screenWidth; @@ -18,13 +14,10 @@ struct BrowserWindowSizing { int& width; int& height; - // Exact screen dimensions are reduced by one, then optional auxiliary - // client height plus four is removed. Native setter errors are ignored. void Resize(int requestedWidth, int requestedHeight); void Refresh(); }; -// Browser host-site presence, host HWND and auxiliary-visible byte. struct BrowserAuxiliaryVisibility { BrowserWindowSizing& sizing; const bool& hasSite; diff --git a/Source/Client/WebBrowser.cpp b/Source/Client/Browser/WebBrowser.cpp similarity index 60% rename from Source/Client/WebBrowser.cpp rename to Source/Client/Browser/WebBrowser.cpp index a70b485..a805c93 100644 --- a/Source/Client/WebBrowser.cpp +++ b/Source/Client/Browser/WebBrowser.cpp @@ -1,31 +1,27 @@ -#include "Client/BrowserClose.h" -#include "Client/BrowserCreation.h" -#include "Client/BrowserFrame.h" -#include "Client/BrowserInputHandoff.h" -#include "Client/WebBrowser.h" -#include "Client/WebEventReceiver.h" +#include "Client/Browser/BrowserClose.h" +#include "Client/Browser/BrowserCreation.h" +#include "Client/Browser/BrowserFrame.h" +#include "Client/Browser/BrowserInputHandoff.h" +#include "Client/Browser/WebBrowser.h" +#include "Client/Browser/WebEventReceiver.h" #include #include namespace { BrowserWindowSizing Sizing(CWebBrowser& owner) { - return {owner.browser, owner.screenWidth, owner.screenHeight, owner.rebar, - owner.auxiliaryVisible, owner.width, owner.height}; + return {owner.browser, owner.screenWidth, owner.screenHeight, owner.rebar, owner.auxiliaryVisible, owner.width, owner.height}; } } // OFFSET: 0x00AB1DE0 // FUNCTION: fn_17409 CWebBrowser::CWebBrowser(WebBrowserContext& context) - : browser(nullptr), externalEvents(nullptr), site(nullptr), host(nullptr), browserWindow(nullptr), cursorState(0), - auxiliaryVisible(0), screenWidth(GetSystemMetrics(SM_CXSCREEN)), screenHeight(GetSystemMetrics(SM_CYSCREEN)), - cookie(0), rebar(nullptr), combo(nullptr), barHeight(0), width(0), height(0), restoreOption(0), - context(&context) { + : browser(nullptr), externalEvents(nullptr), site(nullptr), host(nullptr), browserWindow(nullptr), cursorState(0), auxiliaryVisible(0), + screenWidth(GetSystemMetrics(SM_CXSCREEN)), screenHeight(GetSystemMetrics(SM_CYSCREEN)), cookie(0), rebar(nullptr), combo(nullptr), barHeight(0), + width(0), height(0), restoreOption(0), context(&context) { OutputDebugStringA("CWebBrowser() \n"); - BrowserInputHandoff handoff{ - this->restoreOption, context.applicationWindow, context.service, context.mouse, context.activation - }; + BrowserInputHandoff handoff{this->restoreOption, context.applicationWindow, context.service, context.mouse, context.activation}; handoff.Enter(); } @@ -34,10 +30,7 @@ CWebBrowser::CWebBrowser(WebBrowserContext& context) CWebBrowser::~CWebBrowser() { OutputDebugStringA("~CWebBrowser() \n"); auto& dependencies = *this->context; - BrowserInputHandoff handoff{ - this->restoreOption, dependencies.applicationWindow, dependencies.service, dependencies.mouse, - dependencies.activation - }; + BrowserInputHandoff handoff{this->restoreOption, dependencies.applicationWindow, dependencies.service, dependencies.mouse, dependencies.activation}; handoff.Restore(); this->Close(); } @@ -49,24 +42,13 @@ bool CWebBrowser::Create(int requestedWidth, int requestedHeight) { auto sizing = Sizing(*this); BrowserHostWindow window{this->host, this->browserWindow, dependencies.title, dependencies.hostProcedure}; BrowserSiteAttachment attachment{ - sizing, - this->host, - this->site, - this->cookie, - dependencies.popupFactory, - dependencies.renderWidth, - dependencies.renderHeight + sizing, this->host, this->site, this->cookie, dependencies.popupFactory, dependencies.renderWidth, dependencies.renderHeight }; BrowserAddressBar addressBar{ - this->host, - this->rebar, - this->combo, - this->barHeight, - this->auxiliaryVisible, - dependencies.previousEditProcedure, - dependencies.editProcedure + this->host, this->rebar, this->combo, this->barHeight, this->auxiliaryVisible, dependencies.previousEditProcedure, dependencies.editProcedure }; BrowserCreation creation{this->browser, this->browserWindow, window, attachment, addressBar}; + return creation.Create(dependencies.applicationWindow, dependencies.instance, requestedWidth, requestedHeight); } @@ -76,17 +58,11 @@ bool CWebBrowser::Close() { auto& dependencies = *this->context; auto sizing = Sizing(*this); BrowserSiteAttachment attachment{ - sizing, - this->host, - this->site, - this->cookie, - dependencies.popupFactory, - dependencies.renderWidth, - dependencies.renderHeight + sizing, this->host, this->site, this->cookie, dependencies.popupFactory, dependencies.renderWidth, dependencies.renderHeight }; - BrowserClose operation{attachment, this->browser, this->externalEvents, - this->host, this->browserWindow, dependencies.applicationWindow, + BrowserClose operation{attachment, this->browser, this->externalEvents, this->host, this->browserWindow, dependencies.applicationWindow, this->cursorState, dependencies.mouse}; + return operation.Close(); } @@ -96,6 +72,7 @@ bool CWebBrowser::AttachExternalEvents(BrowserRegistry& registry) { auto* receiver = new (std::nothrow) CWebEventReceiver(registry); this->externalEvents = receiver; receiver->AddRef(); + return receiver->Register(this->browser, this->host); } @@ -111,9 +88,7 @@ void CWebBrowser::Resize(int requestedWidth, int requestedHeight) { void CWebBrowser::Poll() { auto& dependencies = *this->context; auto sizing = Sizing(*this); - BrowserCursor cursor{ - this->cursorState, dependencies.mouse, dependencies.renderSystem, dependencies.applicationWindow - }; + BrowserCursor cursor{this->cursorState, dependencies.mouse, dependencies.renderSystem, dependencies.applicationWindow}; const bool hasExternalEvents = this->externalEvents != nullptr; BrowserFrame frame{sizing, cursor, this->host, this->browserWindow, hasExternalEvents}; frame.Poll(); @@ -129,7 +104,7 @@ bool CWebBrowser::Navigate(std::string address) { // FUNCTION: fn_17422 void CWebBrowser::ShowAuxiliary(unsigned char value) { auto sizing = Sizing(*this); - // The original gate is external-event receiver presence at +4, not site +8. + const bool hasExternalEvents = this->externalEvents != nullptr; BrowserAuxiliaryVisibility visibility{sizing, hasExternalEvents, this->host, this->auxiliaryVisible}; visibility.Show(value); diff --git a/Source/Client/WebBrowser.h b/Source/Client/Browser/WebBrowser.h similarity index 75% rename from Source/Client/WebBrowser.h rename to Source/Client/Browser/WebBrowser.h index 732dd40..c6557ef 100644 --- a/Source/Client/WebBrowser.h +++ b/Source/Client/Browser/WebBrowser.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_WEBBROWSER_H -#define RAGNAROK_SOURCE_CLIENT_WEBBROWSER_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_WEBBROWSER_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_WEBBROWSER_H -#include "Client/BrowserInterface.h" +#include "Client/Browser/BrowserInterface.h" #include @@ -11,13 +11,8 @@ class CRenderSystemBase; struct ServiceOptions; struct BrowserRegistry; struct BrowserFactory; -namespace client { - struct ApplicationActivation; -} +struct ApplicationActivation; -// Borrowed application globals, concrete popup factory and native procedures. -// All must outlive the browser. Renderer dimensions retain their original -// separately owned globals rather than querying virtuals during popup dispatch. struct WebBrowserContext { HWND const& applicationWindow; HINSTANCE const& instance; @@ -25,7 +20,7 @@ struct WebBrowserContext { CMouse& mouse; CRenderSystemBase& renderSystem; ServiceOptions& service; - client::ApplicationActivation& activation; + ApplicationActivation& activation; BrowserFactory& popupFactory; const int& renderWidth; const int& renderHeight; @@ -34,8 +29,6 @@ struct WebBrowserContext { WNDPROC& previousEditProcedure; }; -// Original nonpolymorphic 64-byte CWebBrowser prefix. Context follows it as a -// host dependency view; no original executable addresses are used at runtime. class CWebBrowser { public: explicit CWebBrowser(WebBrowserContext& context); diff --git a/Source/Client/WebEventReceiver.cpp b/Source/Client/Browser/WebEventReceiver.cpp similarity index 81% rename from Source/Client/WebEventReceiver.cpp rename to Source/Client/Browser/WebEventReceiver.cpp index 988f947..05cc89e 100644 --- a/Source/Client/WebEventReceiver.cpp +++ b/Source/Client/Browser/WebEventReceiver.cpp @@ -1,13 +1,15 @@ -#include "Client/BrowserRegistry.h" -#include "Client/WebEventReceiver.h" +#include "Client/Browser/BrowserRegistry.h" +#include "Client/Browser/WebEventReceiver.h" + +#include +#include #include // OFFSET: 0x00AB3710 // FUNCTION: fn_17424 CWebEventReceiver::CWebEventReceiver(BrowserRegistry& registry) - : m_references(0), m_browser(nullptr), m_browserCookie(0), m_document(nullptr), m_documentCookie(0), - m_host(nullptr), m_registry(registry) { + : m_references(0), m_browser(nullptr), m_browserCookie(0), m_document(nullptr), m_documentCookie(0), m_host(nullptr), m_registry(registry) { OutputDebugStringA("CWebEventReceiver() \n"); } @@ -22,6 +24,7 @@ bool CWebEventReceiver::Register(IWebBrowser2* browser, HWND host) { this->m_browser = browser; this->m_host = host; this->m_browser->AddRef(); + return SUCCEEDED(AdviseBrowserEvents(this->m_browser, this, DIID_DWebBrowserEvents2, &this->m_browserCookie)); } @@ -98,20 +101,17 @@ HRESULT CWebEventReceiver::Disconnect() { // OFFSET: 0x00AB3B20 // FUNCTION: fn_17433 -HRESULT STDMETHODCALLTYPE -CWebEventReceiver::Invoke(DISPID id, REFIID, LCID, WORD, DISPPARAMS* args, VARIANT*, EXCEPINFO*, UINT*) { - if (id == 253) { +HRESULT STDMETHODCALLTYPE CWebEventReceiver::Invoke(DISPID id, REFIID, LCID, WORD, DISPPARAMS* args, VARIANT*, EXCEPINFO*, UINT*) { + if (id == DISPID_ONQUIT) { return this->Disconnect(); } - if (id == 259) { + if (id == DISPID_DOCUMENTCOMPLETE) { IDispatch* browserIdentity = nullptr; if (FAILED(this->m_browser->QueryInterface(IID_IDispatch, reinterpret_cast(&browserIdentity)))) { return S_OK; } - // DocumentComplete's pDisp is the second reverse-order VARIANT. The - // reference retains browserIdentity on an identity mismatch. if (args->rgvarg[1].pdispVal != browserIdentity) { return S_OK; } @@ -125,7 +125,7 @@ CWebEventReceiver::Invoke(DISPID id, REFIID, LCID, WORD, DISPPARAMS* args, VARIA return S_OK; } - if (id != -602 && id != static_cast(0x8001000A) && id != 1023) { + if (id != DISPID_HTMLDOCUMENTEVENTS2_ONKEYDOWN && id != DISPID_HTMLDOCUMENTEVENTS2_ONHELP && id != DISPID_HTMLDOCUMENTEVENTS2_ONCONTEXTMENU) { return S_OK; } @@ -134,26 +134,26 @@ CWebEventReceiver::Invoke(DISPID id, REFIID, LCID, WORD, DISPPARAMS* args, VARIA return S_OK; } - if (id == -602) { + if (id == DISPID_HTMLDOCUMENTEVENTS2_ONKEYDOWN) { long key = 0; if (FAILED(event->get_keyCode(&key))) { return S_OK; } switch (key) { - case 18: - case 112: - case 114: - case 115: - case 122: + case VK_MENU: + case VK_F1: + case VK_F3: + case VK_F4: + case VK_F11: break; default: - // Deliberately retained reference on the original non-filtered branch. + return S_OK; } } - if (id != 1023) { + if (id != DISPID_HTMLDOCUMENTEVENTS2_ONCONTEXTMENU) { event->put_keyCode(0); } @@ -163,5 +163,6 @@ CWebEventReceiver::Invoke(DISPID id, REFIID, LCID, WORD, DISPPARAMS* args, VARIA cancelled.boolVal = VARIANT_FALSE; event->put_returnValue(cancelled); event->Release(); - return id == -602 ? S_FALSE : S_OK; + + return id == DISPID_HTMLDOCUMENTEVENTS2_ONKEYDOWN ? S_FALSE : S_OK; } diff --git a/Source/Client/WebEventReceiver.h b/Source/Client/Browser/WebEventReceiver.h similarity index 61% rename from Source/Client/WebEventReceiver.h rename to Source/Client/Browser/WebEventReceiver.h index d9e2a70..201752b 100644 --- a/Source/Client/WebEventReceiver.h +++ b/Source/Client/Browser/WebEventReceiver.h @@ -1,13 +1,10 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_WEBEVENTRECEIVER_H -#define RAGNAROK_SOURCE_CLIENT_WEBEVENTRECEIVER_H +#ifndef RAGNAROK_SOURCE_CLIENT_BROWSER_WEBEVENTRECEIVER_H +#define RAGNAROK_SOURCE_CLIENT_BROWSER_WEBEVENTRECEIVER_H -#include "Client/BrowserInterface.h" +#include "Client/Browser/BrowserInterface.h" struct BrowserRegistry; -// Original receiver starts with zero references. Caller acquires its owning -// reference before registration. Destruction only reports diagnostics; explicit -// Disconnect performs COM and registry teardown, not the destructor. class CWebEventReceiver final : public IDispatch { public: explicit CWebEventReceiver(BrowserRegistry& registry); @@ -20,16 +17,8 @@ public: HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* count) override; HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT index, LCID locale, ITypeInfo** output) override; HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID iid, LPOLESTR* names, UINT count, LCID locale, DISPID* ids) override; - HRESULT STDMETHODCALLTYPE Invoke( - DISPID id, - REFIID iid, - LCID locale, - WORD flags, - DISPPARAMS* args, - VARIANT* result, - EXCEPINFO* error, - UINT* argumentError - ) override; + HRESULT STDMETHODCALLTYPE + Invoke(DISPID id, REFIID iid, LCID locale, WORD flags, DISPPARAMS* args, VARIANT* result, EXCEPINFO* error, UINT* argumentError) override; private: ~CWebEventReceiver(); diff --git a/Source/Client/BrowserAddressBar.h b/Source/Client/BrowserAddressBar.h deleted file mode 100644 index 447dd74..0000000 --- a/Source/Client/BrowserAddressBar.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERADDRESSBAR_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERADDRESSBAR_H - -#include - -// Borrowed host, rebar, combo, height, visible, and shared -// previous-edit-procedure global. Caller initializes common controls and supplies -// the actual BrowserAddressEdit thunk. Native verification requires v6 controls -// for the original 100-byte x86 band; startup activation policy is not recovered. -// Failed creation retains native children; normal host destruction owns them. -struct BrowserAddressBar { - HWND const& host; - HWND& rebar; - HWND& combo; - int& height; - const unsigned char& visible; - WNDPROC& previous; - WNDPROC procedure; - - bool Create(int width, int height); -}; - -#endif diff --git a/Source/Client/BrowserAddressEdit.h b/Source/Client/BrowserAddressEdit.h deleted file mode 100644 index 804436f..0000000 --- a/Source/Client/BrowserAddressEdit.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERADDRESSEDIT_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERADDRESSEDIT_H - -#include - -// Borrowed original subclass procedure and active browser-host selection. -// Null activeHost denotes no active CWebBrowser, not a null HWND field inside -// an otherwise active object. -struct BrowserAddressEdit { - WNDPROC const& previous; - HWND const* const& activeHost; - - LRESULT Message(HWND window, UINT message, WPARAM value, LPARAM flags); -}; - -#endif diff --git a/Source/Client/BrowserClose.h b/Source/Client/BrowserClose.h deleted file mode 100644 index 2ec8480..0000000 --- a/Source/Client/BrowserClose.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERCLOSE_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERCLOSE_H - -#include "Client/BrowserSiteAttachment.h" - -class CMouse; - -// Borrowed original browser fields. External events use a separate COM reference -// independent of the client-site dispatch dependency. Auxiliary HWNDs and -// cookie remain untouched even after their host destroys the native children. -struct BrowserClose { - BrowserSiteAttachment& attachment; - IWebBrowser2*& browser; - IUnknown*& externalEvents; - HWND& host; - HWND const& browserWindow; - HWND const& applicationWindow; - int& cursorState; - CMouse& mouse; - - bool Close(); -}; - -#endif diff --git a/Source/Client/BrowserCreation.h b/Source/Client/BrowserCreation.h deleted file mode 100644 index cd3755a..0000000 --- a/Source/Client/BrowserCreation.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERCREATION_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERCREATION_H - -#include "Client/BrowserAddressBar.h" -#include "Client/BrowserHostWindow.h" -#include "Client/BrowserSiteAttachment.h" - -// Views must refer to the same CWebBrowser fields. Caller supplies the complete -// host procedure, edit subclass and site event dependency. No rollback on error: -// browser, host, site and native children remain published at their original steps. -struct BrowserCreation { - IWebBrowser2*& browser; - HWND& browserWindow; - BrowserHostWindow& window; - BrowserSiteAttachment& attachment; - BrowserAddressBar& addressBar; - - bool Create(HWND parent, HINSTANCE instance, int width, int height); -}; - -#endif diff --git a/Source/Client/BrowserCursor.h b/Source/Client/BrowserCursor.h deleted file mode 100644 index 2908020..0000000 --- a/Source/Client/BrowserCursor.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERCURSOR_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERCURSOR_H - -#include - -class CMouse; -class CRenderSystemBase; - -// Borrowed CWebBrowser cursor state and the actual global mouse/render -// owners. ShowCursor receives the full integer, not a normalized boolean. -struct BrowserCursor { - int& state; - CMouse& mouse; - CRenderSystemBase& renderSystem; - HWND const& applicationWindow; - - void Set(int value); - void Poll(); -}; - -#endif diff --git a/Source/Client/BrowserFrame.h b/Source/Client/BrowserFrame.h deleted file mode 100644 index 3aa2b0c..0000000 --- a/Source/Client/BrowserFrame.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERFRAME_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERFRAME_H - -#include "Client/BrowserCursor.h" -#include "Client/BrowserWindowSizing.h" - -// Borrowed original browser owner. Presence means the separate external event -// receiver is attached, not merely that an OLE client site exists. -struct BrowserFrame { - BrowserWindowSizing& sizing; - BrowserCursor& cursor; - HWND const& host; - HWND const& browserWindow; - const bool& hasExternalEvents; - - void Normalize(); - void Poll(); -}; - -#endif diff --git a/Source/Client/BrowserHostWindow.h b/Source/Client/BrowserHostWindow.h deleted file mode 100644 index d002a2f..0000000 --- a/Source/Client/BrowserHostWindow.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERHOSTWINDOW_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERHOSTWINDOW_H - -#include - -// Borrowed CWebBrowser host and browser HWND, application -// title and complete browser window procedure. This operation does not replace -// that procedure with DefWindowProc or invent the browser host-site lifecycle. -struct BrowserHostWindow { - HWND& host; - HWND const& browser; - const char* const& title; - WNDPROC procedure; - - bool Create(HWND parent, HINSTANCE instance, int width, int height); -}; - -#endif diff --git a/Source/Client/BrowserInputHandoff.h b/Source/Client/BrowserInputHandoff.h deleted file mode 100644 index 14ee213..0000000 --- a/Source/Client/BrowserInputHandoff.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERINPUTHANDOFF_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERINPUTHANDOFF_H - -#include - -class CMouse; -struct ServiceOptions; -namespace client { - struct ApplicationActivation; -} - -// Borrowed original CWebBrowser service-option latch, main HWND and global -// input owners. Restoration retains the latch; it is not a one-shot operation. -struct BrowserInputHandoff { - unsigned char& restoreOption; - HWND const& applicationWindow; - ServiceOptions& service; - CMouse& mouse; - client::ApplicationActivation& activation; - - void Enter(); - void Restore(); -}; - -#endif diff --git a/Source/Client/BrowserInterface.h b/Source/Client/BrowserInterface.h deleted file mode 100644 index 2ffef19..0000000 --- a/Source/Client/BrowserInterface.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERINTERFACE_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERINTERFACE_H - -// clang-format off -#include -#include -#include -// clang-format on - -#include - -// Caller supplies the original owner fields and controls COM initialization -// and release. Successful creation publishes HWND only when browser is nonnull; -// get_HWND failure does not change the creation result. -bool CreateBrowserInterface(IWebBrowser2*& browser, HWND& window); - -// Distinct original local-server route; never falls back to the in-process -// control. Success reparents its HWND and clears Top, Left and StatusBar. -bool CreateExternalBrowserInterface(IWebBrowser2*& browser, HWND& window, HWND const& host); - -// Navigation's four optional arguments alias one VT_EMPTY VARIANT. Host show, -// browser visibility and title publication occur even when Navigate fails. -bool NavigateBrowser(IWebBrowser2* const& browser, HWND const& host, HWND const& title, std::string address); - -// Connection-point helpers retain native HRESULTs; cookie writes belong to -// Advise. Release the connection point before its container on every path. -HRESULT AdviseBrowserEvents(IUnknown* source, IUnknown* sink, REFIID events, DWORD* cookie); -HRESULT UnadviseBrowserEvents(IUnknown* source, REFIID events, DWORD cookie); - -#endif diff --git a/Source/Client/BrowserSiteAttachment.h b/Source/Client/BrowserSiteAttachment.h deleted file mode 100644 index a29da8b..0000000 --- a/Source/Client/BrowserSiteAttachment.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_BROWSERSITEATTACHMENT_H -#define RAGNAROK_SOURCE_CLIENT_BROWSERSITEATTACHMENT_H - -#include "Client/BrowserClientSite.h" -#include "Client/BrowserWindowSizing.h" - -// Borrowed original owner fields, real popup factory and renderer dimensions. -// Site publication precedes COM work and remains on failure. Detach destroys the -// site even when QueryInterface fails; it does not clear the COM client site. -struct BrowserSiteAttachment { - BrowserWindowSizing& sizing; - HWND const& host; - BrowserClientSite*& site; - DWORD& cookie; - BrowserFactory& factory; - const int& renderWidth; - const int& renderHeight; - - bool Attach(); - void Detach(); -}; - -#endif diff --git a/Source/Client/ClientOptions.cpp b/Source/Client/ClientOptions.cpp index 1e54937..4637d37 100644 --- a/Source/Client/ClientOptions.cpp +++ b/Source/Client/ClientOptions.cpp @@ -1,17 +1,14 @@ #include "Client/ClientOptions.h" -#include - // OFFSET: 0x0091BE20 // FUNCTION: fn_12610 int ClientOptions::Get(int id) const { - return std::bit_cast(static_cast(this->values.Get(id))); + return static_cast(this->values.Get(id)); } // OFFSET: 0x005E7970 // FUNCTION: fn_03937 void ClientOptions::Set(int id, int value, int extra) { - const std::uint64_t bits = - static_cast(value) | (static_cast(static_cast(extra)) << 32); - this->values.Set(id, std::bit_cast(bits)); + const std::uint64_t bits = static_cast(value) | (static_cast(extra) << 32); + this->values.Set(id, static_cast(bits)); } diff --git a/Source/Client/ClientOptions.h b/Source/Client/ClientOptions.h index 1ee9316..80004d6 100644 --- a/Source/Client/ClientOptions.h +++ b/Source/Client/ClientOptions.h @@ -3,7 +3,6 @@ #include "Contents/InstantVar.h" -// Low/high-word client operations on its CInstantVar at +0x7FA8. struct ClientOptions { CInstantVar& values; int Get(int id) const; diff --git a/Source/Client/ErrorDialog.h b/Source/Client/ErrorDialog.h deleted file mode 100644 index 6974cdf..0000000 --- a/Source/Client/ErrorDialog.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_ERRORDIALOG_H -#define RAGNAROK_SOURCE_CLIENT_ERRORDIALOG_H - -#include - -class CRenderSystemBase; - -// Obtained through the render-system owner. -// Keep the real owner dependency explicit until its lifecycle is reconstructed. -int ShowErrorDialog(CRenderSystemBase* renderSystem, const char* text, UINT type); - -#endif diff --git a/Source/Client/ImeInput.cpp b/Source/Client/Input/ImeInput.cpp similarity index 88% rename from Source/Client/ImeInput.cpp rename to Source/Client/Input/ImeInput.cpp index a0cc752..1cb2bcb 100644 --- a/Source/Client/ImeInput.cpp +++ b/Source/Client/Input/ImeInput.cpp @@ -1,6 +1,6 @@ -#include "Client/ImeInput.h" -#include "Client/TraditionalKeyInput.h" -#include "Utility/LanguageCharset.h" +#include "Client/Input/ImeInput.h" +#include "Client/Input/TraditionalKeyInput.h" +#include "Utility/Text/LanguageCharset.h" #include #include @@ -10,6 +10,7 @@ // FUNCTION: fn_17793 LRESULT ImeInput::Message(HWND, UINT message, WPARAM value, LPARAM flags, std::uint8_t& handled) { const auto options = static_cast(flags); + switch (message) { case WM_INPUTLANGCHANGE: this->language = options; @@ -48,13 +49,13 @@ LRESULT ImeInput::Message(HWND, UINT message, WPARAM value, LPARAM flags, std::u if (context) { WCHAR wide[256]; char converted[256]; - const auto bytes = - static_cast(ImmGetCompositionStringW(context, GCS_RESULTSTR, wide, sizeof(wide))); - const unsigned size = - WideCharToMultiByte(this->codePage, 0, wide, bytes >> 1, converted, sizeof(converted), nullptr, nullptr); + const auto bytes = static_cast(ImmGetCompositionStringW(context, GCS_RESULTSTR, wide, sizeof(wide))); + const unsigned size = WideCharToMultiByte(this->codePage, 0, wide, bytes >> 1, converted, sizeof(converted), nullptr, nullptr); + if (size >= sizeof(converted)) { - __fastfail(8); + __fastfail(FAST_FAIL_RANGE_CHECK_FAILURE); } + converted[size] = 0; ImmReleaseContext(this->input.window, context); this->input.Insert(converted); @@ -78,6 +79,7 @@ LRESULT ImeInput::Message(HWND, UINT message, WPARAM value, LPARAM flags, std::u } else { this->input.compositionState = 0; } + ImmReleaseContext(this->input.window, context); } else { this->input.compositionState = 0; @@ -109,5 +111,6 @@ const char* ImeInput::Candidate(int index) const { const WCHAR* text = reinterpret_cast(bytes + this->candidateList->dwOffset[index]); const unsigned size = WideCharToMultiByte(this->codePage, 0, text, -1, output, sizeof(output), nullptr, nullptr); output[std::min(size, 255)] = 0; + return output; } diff --git a/Source/Client/ImeInput.h b/Source/Client/Input/ImeInput.h similarity index 51% rename from Source/Client/ImeInput.h rename to Source/Client/Input/ImeInput.h index aa1ff5f..97c7948 100644 --- a/Source/Client/ImeInput.h +++ b/Source/Client/Input/ImeInput.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_IMEINPUT_H -#define RAGNAROK_SOURCE_CLIENT_IMEINPUT_H +#ifndef RAGNAROK_SOURCE_CLIENT_INPUT_IMEINPUT_H +#define RAGNAROK_SOURCE_CLIENT_INPUT_IMEINPUT_H -#include "Client/TextInputBuffer.h" +#include "Client/Input/TextInputBuffer.h" #include #include @@ -9,8 +9,6 @@ struct TraditionalKeyInput; -// Borrowed CLanguage fields, with optional concrete CLanguageTC key view. -// Base/TH/ARB composition hooks are established empty entries. struct ImeInput { TextInputBuffer& input; std::uint16_t& language; @@ -24,11 +22,8 @@ struct ImeInput { int& compositionCursor; TraditionalKeyInput* traditional; - // Original ignores the passed HWND and uses the global main-window handle - // borrowed by input. Flags are truncated to the low WORD. LRESULT Message(HWND unused, UINT message, WPARAM value, LPARAM flags, std::uint8_t& handled); - // Shared 256-byte output; later successful lookups overwrite prior strings. - // Original checks index < count only (no negative-index guard). + const char* Candidate(int index) const; }; diff --git a/Source/Client/InputCharset.cpp b/Source/Client/Input/InputCharset.cpp similarity index 86% rename from Source/Client/InputCharset.cpp rename to Source/Client/Input/InputCharset.cpp index 71602f3..7ada0aa 100644 --- a/Source/Client/InputCharset.cpp +++ b/Source/Client/Input/InputCharset.cpp @@ -1,5 +1,5 @@ -#include "Client/InputCharset.h" -#include "Utility/LanguageCharset.h" +#include "Client/Input/InputCharset.h" +#include "Utility/Text/LanguageCharset.h" #include diff --git a/Source/Client/InputCharset.h b/Source/Client/Input/InputCharset.h similarity index 59% rename from Source/Client/InputCharset.h rename to Source/Client/Input/InputCharset.h index cb80a68..c4483cf 100644 --- a/Source/Client/InputCharset.h +++ b/Source/Client/Input/InputCharset.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_INPUTCHARSET_H -#define RAGNAROK_SOURCE_CLIENT_INPUTCHARSET_H +#ifndef RAGNAROK_SOURCE_CLIENT_INPUT_INPUTCHARSET_H +#define RAGNAROK_SOURCE_CLIENT_INPUT_INPUTCHARSET_H #include @@ -9,7 +9,7 @@ struct InputCharset { const std::uint16_t& alternateLanguage; const char* Prefix(bool alternate) const; - // Shared selection used by composition refresh/language-change handling. + unsigned CodePage(unsigned fallback) const; }; diff --git a/Source/Client/Mouse.cpp b/Source/Client/Input/Mouse.cpp similarity index 85% rename from Source/Client/Mouse.cpp rename to Source/Client/Input/Mouse.cpp index cc6cd7d..3814a5f 100644 --- a/Source/Client/Mouse.cpp +++ b/Source/Client/Input/Mouse.cpp @@ -1,11 +1,8 @@ -#include "Client/Mouse.h" -#include "Render/DCSurface.h" +#include "Client/Input/Mouse.h" +#include "Render/DeviceContext/DCSurface.h" -#include #include -// clang-format off -#include -// clang-format on +#include // OFFSET: 0x006370C0 // FUNCTION: fn_04724 @@ -20,11 +17,12 @@ void CMouse::Update() { return; } - this->deltaX = std::bit_cast(static_cast(this->pendingX) - static_cast(this->x)); - this->deltaY = std::bit_cast(static_cast(this->pendingY) - static_cast(this->y)); + this->deltaX = this->pendingX - this->x; + this->deltaY = this->pendingY - this->y; this->x = this->pendingX; this->y = this->pendingY; const std::uint32_t now = timeGetTime(); + for (unsigned index = 0; index < 2; ++index) { if (this->deltaX != 0 || this->deltaY != 0) { this->pressTicks[index] = now - this->doubleClickTime; @@ -71,6 +69,7 @@ int CMouse::Center() { const int halfHeight = static_cast(GetRenderSystemHolder()->Height()) / 2; this->pendingY = halfHeight; this->y = halfHeight; + return halfHeight; } @@ -120,7 +119,7 @@ void CMouse::Message(CMouse& global, HWND mainWindow, HWND source, UINT message, this->pendingButtons[1] = 0; break; case WM_MOUSEWHEEL: - this->pendingWheel = std::bit_cast(static_cast(keys >> 16)); + this->pendingWheel = GET_WHEEL_DELTA_WPARAM(keys); break; } } diff --git a/Source/Client/Mouse.h b/Source/Client/Input/Mouse.h similarity index 68% rename from Source/Client/Mouse.h rename to Source/Client/Input/Mouse.h index cf1280e..a5c9db1 100644 --- a/Source/Client/Mouse.h +++ b/Source/Client/Input/Mouse.h @@ -1,11 +1,9 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_MOUSE_H -#define RAGNAROK_SOURCE_CLIENT_MOUSE_H +#ifndef RAGNAROK_SOURCE_CLIENT_INPUT_MOUSE_H +#define RAGNAROK_SOURCE_CLIENT_INPUT_MOUSE_H #include #include -// RTTI CMouse. Defaults below are the original -// static-data initializer, not evidence of a separate allocating constructor. class CMouse { public: virtual ~CMouse(); @@ -14,9 +12,7 @@ public: int Center(); void SetX(int value); void SetY(int value); - // Message position comes from GetCursorPos/mainWindow, not lParam or source. - // The original resets the global mouse on first message; pass that owner - // separately so non-global instances retain the same distinction. + void Message(CMouse& global, HWND mainWindow, HWND source, UINT message, WPARAM keys, LPARAM unused); /* 0004 */ int x = 0; diff --git a/Source/Client/TextInputBuffer.cpp b/Source/Client/Input/TextInputBuffer.cpp similarity index 85% rename from Source/Client/TextInputBuffer.cpp rename to Source/Client/Input/TextInputBuffer.cpp index 7193dac..c1b3500 100644 --- a/Source/Client/TextInputBuffer.cpp +++ b/Source/Client/Input/TextInputBuffer.cpp @@ -1,9 +1,8 @@ -#include "Client/TextInputBuffer.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "Client/Input/TextInputBuffer.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" #include -#include #include #include #include @@ -14,7 +13,7 @@ void TextInputBuffer::CancelComposition() { HIMC context = ImmGetContext(this->window); if (context) { - ImmNotifyIME(context, 0x15, 4, 0); + ImmNotifyIME(context, NI_COMPOSITIONSTR, CPS_CANCEL, 0); ImmReleaseContext(this->window, context); } @@ -34,8 +33,7 @@ void TextInputBuffer::DeleteSelection() { } const int begin = std::min(this->cursor, this->anchor); - const auto length = - static_cast(std::max(this->cursor, this->anchor)) - static_cast(begin); + const int length = std::max(this->cursor, this->anchor) - begin; this->text.erase(static_cast(begin), length); this->cursor = begin; this->anchor = begin; @@ -50,9 +48,7 @@ void TextInputBuffer::DeleteSelection() { void TextInputBuffer::Insert(const char* value) { this->DeleteSelection(); this->text.insert(static_cast(this->cursor), value, std::strlen(value)); - this->anchor = std::bit_cast( - static_cast(std::strlen(value)) + static_cast(this->cursor) - ); + this->anchor = this->cursor + static_cast(std::strlen(value)); this->cursor = this->anchor; if (this->suggestionsEnabled && this->chatOpen && this->chatInput && this->focused == this->chatInput) { @@ -77,9 +73,7 @@ void TextInputBuffer::CopyDisplayText(std::string& output) const { } if (!this->candidate.empty()) { - output.insert( - static_cast(this->cursor), this->candidate.c_str(), std::strlen(this->candidate.c_str()) - ); + output.insert(static_cast(this->cursor), this->candidate.c_str(), std::strlen(this->candidate.c_str())); } } @@ -102,8 +96,7 @@ void TextInputBuffer::RefreshComposition(unsigned codePage) { WCHAR wide[256]; char converted[256]; const auto bytes = static_cast(ImmGetCompositionStringW(context, GCS_COMPSTR, wide, sizeof(wide))); - const unsigned size = - WideCharToMultiByte(codePage, 0, wide, bytes >> 1, converted, sizeof(converted), nullptr, nullptr); + const unsigned size = WideCharToMultiByte(codePage, 0, wide, bytes >> 1, converted, sizeof(converted), nullptr, nullptr); ImmReleaseContext(this->window, context); this->candidate.assign(converted, size); @@ -122,8 +115,7 @@ void TextInputBuffer::RefreshComposition(unsigned codePage) { // OFFSET: 0x00ACD5C0 // FUNCTION: fn_17765 void TextInputBuffer::CopySelection(bool password) { - const auto difference = static_cast(this->cursor) - static_cast(this->anchor); - const auto length = std::bit_cast(difference) < 0 ? 0u - difference : difference; + const int length = std::max(this->cursor, this->anchor) - std::min(this->cursor, this->anchor); if (!length || !OpenClipboard(this->window)) { return; } @@ -138,6 +130,7 @@ void TextInputBuffer::CopySelection(bool password) { } else { std::memcpy(data, this->text.data() + begin, length); } + data[length] = 0; GlobalUnWire(memory); EmptyClipboard(); @@ -200,7 +193,7 @@ void TextInputBuffer::MoveForward(unsigned codePage) { const auto length = static_cast(this->text.size()); const auto position = static_cast(this->cursor); if (position > length) { - this->cursor = std::bit_cast(length); + this->cursor = static_cast(length); } else if (position < length) { const char* begin = this->text.c_str(); this->cursor = static_cast(CharNextExA(static_cast(codePage), begin + position, 0) - begin); @@ -214,6 +207,7 @@ void TextInputBuffer::Character(unsigned value, LPARAM, unsigned codePage) { if (this->cursor == this->anchor) { this->MoveBack(codePage); } + this->DeleteSelection(); return; } @@ -222,8 +216,6 @@ void TextInputBuffer::Character(unsigned value, LPARAM, unsigned codePage) { return; } - // Keep the original little-endian DWORD representation and stop at its first - // zero byte; valid WM_CHAR payloads provide that terminator within the word. char bytes[sizeof(value)]; std::memcpy(bytes, &value, sizeof(value)); this->Insert(bytes); @@ -232,13 +224,7 @@ void TextInputBuffer::Character(unsigned value, LPARAM, unsigned codePage) { // OFFSET: 0x00ACE880 // FUNCTION: fn_17792 void TextInputBuffer::KeyDown( - unsigned key, - LPARAM, - unsigned codePage, - bool password, - UIWindow* blockedPasteFocus, - WindowManagerWindows& windows, - UIWindow* const& chatArrows + unsigned key, LPARAM, unsigned codePage, bool password, UIWindow* blockedPasteFocus, WindowManagerWindows& windows, UIWindow* const& chatArrows ) { const auto cut = [&]() { this->CopySelection(password); @@ -266,6 +252,7 @@ void TextInputBuffer::KeyDown( cut(); break; } + return; } @@ -285,6 +272,7 @@ void TextInputBuffer::KeyDown( this->cursor = std::max(static_cast(this->text.size()), 0); break; } + return; } @@ -305,6 +293,7 @@ void TextInputBuffer::KeyDown( } else { this->MoveForward(codePage); } + this->anchor = this->cursor; } break; diff --git a/Source/Client/Input/TextInputBuffer.h b/Source/Client/Input/TextInputBuffer.h new file mode 100644 index 0000000..7b90691 --- /dev/null +++ b/Source/Client/Input/TextInputBuffer.h @@ -0,0 +1,57 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_INPUT_TEXTINPUTBUFFER_H +#define RAGNAROK_SOURCE_CLIENT_INPUT_TEXTINPUTBUFFER_H + +#include +#include + +class UIWindow; +class WindowManagerWindows; + +class TextInputSuggestions { +public: + virtual void Update(const char* text) = 0; + +protected: + ~TextInputSuggestions() = default; +}; + +struct TextInputBuffer { + std::string& text; + int& cursor; + int& anchor; + std::string& composition; + std::string& candidate; + int& compositionState; + HWND& window; + const bool& suggestionsEnabled; + UIWindow* const& focused; + UIWindow* const& chatInput; + const bool& chatOpen; + TextInputSuggestions& suggestions; + + void CancelComposition(); + void DeleteSelection(); + void Insert(const char* value); + void Select(int anchor, int cursor); + void CopyDisplayText(std::string& output) const; + void Selection(int& anchor, int& cursor) const; + + void SelectionRange(int& begin, int& end) const; + + void RefreshComposition(unsigned codePage); + + void CopySelection(bool password); + void Paste(UIWindow* blockedFocus, WindowManagerWindows& windows); + + void MoveBack(unsigned codePage); + + void MoveForward(unsigned codePage); + + void Character(unsigned value, LPARAM unused, unsigned codePage); + + void KeyDown( + unsigned key, LPARAM unused, unsigned codePage, bool password, UIWindow* blockedPasteFocus, WindowManagerWindows& windows, UIWindow* const& chatArrows + ); +}; + +#endif diff --git a/Source/Client/TraditionalKeyInput.cpp b/Source/Client/Input/TraditionalKeyInput.cpp similarity index 83% rename from Source/Client/TraditionalKeyInput.cpp rename to Source/Client/Input/TraditionalKeyInput.cpp index 1ec9ce9..c3695a1 100644 --- a/Source/Client/TraditionalKeyInput.cpp +++ b/Source/Client/Input/TraditionalKeyInput.cpp @@ -1,4 +1,4 @@ -#include "Client/TraditionalKeyInput.h" +#include "Client/Input/TraditionalKeyInput.h" #include "Network/TextEncoding.h" #include @@ -7,17 +7,16 @@ void TraditionalKeyInput::InitializeMappings() { // STATIC: 0x011594E0 // GLOBAL: gl_13427 - static constexpr std::uint8_t bytes[] = {0xA3, 0x74, 0xA3, 0x78, 0xA3, 0xBE, 0xA3, 0xBF, 0xA3, 0xA4, 0xA3, 0xBD, - 0xA3, 0xBB, 0xA3, 0xAB, 0xA3, 0xAF, 0xA3, 0xB3, 0xA3, 0x76, 0xA3, 0xA7, - 0xA3, 0x74, 0xA3, 0x74, 0xA3, 0x74, 0xA3, 0xA2, 0xA3, 0xA6, 0xA3, 0xA9, - 0xA3, 0xAC, 0xA3, 0xB9, 0xA3, 0xAD, 0xA3, 0xB1, 0xA3, 0xAA, 0xA3, 0xBA, - 0xA3, 0xB0, 0xA3, 0xB4, 0xA3, 0x75, 0xA3, 0xA1, 0xA3, 0x7A, 0xA3, 0xA5, - 0xA3, 0x74, 0xA3, 0xA3, 0xA3, 0x79, 0xA3, 0x74, 0xA3, 0xA8, 0xA3, 0x77, - 0xA3, 0xB7, 0xA3, 0xB5, 0xA3, 0xAE, 0xA3, 0xB2, 0xA3, 0xB6}; + static constexpr std::uint8_t bytes[] = {0xA3, 0x74, 0xA3, 0x78, 0xA3, 0xBE, 0xA3, 0xBF, 0xA3, 0xA4, 0xA3, 0xBD, 0xA3, 0xBB, 0xA3, 0xAB, 0xA3, + 0xAF, 0xA3, 0xB3, 0xA3, 0x76, 0xA3, 0xA7, 0xA3, 0x74, 0xA3, 0x74, 0xA3, 0x74, 0xA3, 0xA2, 0xA3, 0xA6, + 0xA3, 0xA9, 0xA3, 0xAC, 0xA3, 0xB9, 0xA3, 0xAD, 0xA3, 0xB1, 0xA3, 0xAA, 0xA3, 0xBA, 0xA3, 0xB0, 0xA3, + 0xB4, 0xA3, 0x75, 0xA3, 0xA1, 0xA3, 0x7A, 0xA3, 0xA5, 0xA3, 0x74, 0xA3, 0xA3, 0xA3, 0x79, 0xA3, 0x74, + 0xA3, 0xA8, 0xA3, 0x77, 0xA3, 0xB7, 0xA3, 0xB5, 0xA3, 0xAE, 0xA3, 0xB2, 0xA3, 0xB6}; static constexpr char categories[] = "11441443331111111132331233111121111133333"; static constexpr unsigned char keys[] = "1234567890ABCDEFGHIJKLNMOPQRSTUVWXYZ\xBD\xBA\xBC\xBE\xBF"; this->unknown04C1 = 0; + for (auto& mapping : this->mappings) { mapping.category = 4; } @@ -50,6 +49,7 @@ void TraditionalKeyInput::Key(int virtualKey) { if (!this->keys.empty()) { this->keys.pop_back(); } + return; } @@ -59,6 +59,7 @@ void TraditionalKeyInput::Key(int virtualKey) { break; } } + this->keys.push_back(key); } @@ -72,6 +73,7 @@ const char* TraditionalKeyInput::DisplayText() const { // FUNCTION: fn_17778 const char* TraditionalKeyInput::Display() { char bytes[8] = {}; + for (std::uint8_t key : this->keys) { const auto& mapping = this->mappings[key]; if (mapping.category < 4) { @@ -96,6 +98,7 @@ int TraditionalKeyInput::Count() const { if (this->keys.size() == 1 && this->mappings[this->keys.back()].category == 4) { return 0; } + return static_cast(this->keys.size()); } diff --git a/Source/Client/TraditionalKeyInput.h b/Source/Client/Input/TraditionalKeyInput.h similarity index 71% rename from Source/Client/TraditionalKeyInput.h rename to Source/Client/Input/TraditionalKeyInput.h index 6a5e14b..fa89ef5 100644 --- a/Source/Client/TraditionalKeyInput.h +++ b/Source/Client/Input/TraditionalKeyInput.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_TRADITIONALKEYINPUT_H -#define RAGNAROK_SOURCE_CLIENT_TRADITIONALKEYINPUT_H +#ifndef RAGNAROK_SOURCE_CLIENT_INPUT_TRADITIONALKEYINPUT_H +#define RAGNAROK_SOURCE_CLIENT_INPUT_TRADITIONALKEYINPUT_H #include #include @@ -11,15 +11,12 @@ struct TraditionalKeyMapping { std::uint8_t bytes[3]; }; -// Borrowed CLanguageTC fields; not a substitute for its base-language/IME -// lifecycle. Key sequence is +0xB8, mappings +0xC0, display +0x58, flag +0x4C1. struct TraditionalKeyInput { std::list& keys; std::array& mappings; std::string& display; std::uint8_t& unknown04C1; - // Unmapped byte triples are deliberately untouched; their category becomes 4. void InitializeMappings(); void Key(int virtualKey); void DefaultKey(int virtualKey); diff --git a/Source/Client/Launcher.cpp b/Source/Client/Launcher.cpp deleted file mode 100644 index a60a106..0000000 --- a/Source/Client/Launcher.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "Client/Launcher.h" - -#include -#include - -namespace client { - - // OFFSET: 0x00E58820 - // FUNCTION: fn_24363 - bool RestartFromCommandLine(char* commandLine) { - char* marker = std::strstr(commandLine, "/launcherRESTART:"); - if (!marker) { - return false; - } - - STARTUPINFOA startup = {}; - startup.cb = sizeof(startup); - startup.dwFlags = STARTF_USESHOWWINDOW; - startup.wShowWindow = SW_SHOWNORMAL; - PROCESS_INFORMATION process; - // Original behavior ignores CreateProcessA failure and still returns true. - CreateProcessA( - nullptr, marker + std::strlen("/launcherRESTART:"), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startup, - &process - ); - CloseHandle(process.hProcess); - CloseHandle(process.hThread); - return true; - } - - // OFFSET: 0x00E5D390 - // FUNCTION: fn_24380 - void ExitForProtectionCheck(const char* commandLine) { - if (std::strstr(commandLine, "/check_themida")) { - ExitProcess(0); - } - } - - // OFFSET: 0x00E5D390 - // FUNCTION: fn_24380 - bool AcquireInstanceMutex(HANDLE* mutex) { - *mutex = CreateMutexA(nullptr, TRUE, "MutexInit"); - return GetLastError() != ERROR_ALREADY_EXISTS; - } - -} diff --git a/Source/Client/Launcher.h b/Source/Client/Launcher.h deleted file mode 100644 index e6eccee..0000000 --- a/Source/Client/Launcher.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_LAUNCHER_H -#define RAGNAROK_SOURCE_CLIENT_LAUNCHER_H - -#include - -namespace client { - - // Reconstructed semantic name for the original launcher restart branch. - // A mutable buffer is required because CreateProcessA may modify its tail. - bool RestartFromCommandLine(char* commandLine); - - // Named source extractions of the established WinMain guard blocks. - void ExitForProtectionCheck(const char* commandLine); - bool AcquireInstanceMutex(HANDLE* mutex); - -} - -#endif diff --git a/Source/Client/ActiveGameMode.cpp b/Source/Client/Mode/ActiveGameMode.cpp similarity index 74% rename from Source/Client/ActiveGameMode.cpp rename to Source/Client/Mode/ActiveGameMode.cpp index d8fba1a..fa995e0 100644 --- a/Source/Client/ActiveGameMode.cpp +++ b/Source/Client/Mode/ActiveGameMode.cpp @@ -1,4 +1,4 @@ -#include "Client/ActiveGameMode.h" +#include "Client/Mode/ActiveGameMode.h" // FUNCTION: fn_17831 CGameMode* CWorld::ActiveGameMode() { diff --git a/Source/Client/ActiveGameMode.h b/Source/Client/Mode/ActiveGameMode.h similarity index 58% rename from Source/Client/ActiveGameMode.h rename to Source/Client/Mode/ActiveGameMode.h index c662427..c7a1622 100644 --- a/Source/Client/ActiveGameMode.h +++ b/Source/Client/Mode/ActiveGameMode.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_ACTIVEGAMEMODE_H -#define RAGNAROK_SOURCE_CLIENT_ACTIVEGAMEMODE_H +#ifndef RAGNAROK_SOURCE_CLIENT_MODE_ACTIVEGAMEMODE_H +#define RAGNAROK_SOURCE_CLIENT_MODE_ACTIVEGAMEMODE_H class CGameMode; @@ -12,6 +12,8 @@ struct CWorld { CGameMode* ActiveGameMode(); }; +// STATIC: 0x013495b8 +// GLOBAL: gl_24475 extern CWorld g_world; #endif diff --git a/Source/Client/ModeCursor.cpp b/Source/Client/Mode/ModeCursor.cpp similarity index 79% rename from Source/Client/ModeCursor.cpp rename to Source/Client/Mode/ModeCursor.cpp index 5103731..3445151 100644 --- a/Source/Client/ModeCursor.cpp +++ b/Source/Client/Mode/ModeCursor.cpp @@ -1,9 +1,7 @@ -#include "Client/ModeCursor.h" +#include "Client/Mode/ModeCursor.h" #include -// clang-format off -#include -// clang-format on +#include // OFFSET: 0x00AD52D0 // FUNCTION: fn_17820 @@ -16,6 +14,7 @@ void ModeCursor::Set(std::int32_t value, std::uint32_t& changeTick) { if (this->type == value) { return; } + this->type = value; this->frame = 0; changeTick = timeGetTime(); diff --git a/Source/Client/ModeCursor.h b/Source/Client/Mode/ModeCursor.h similarity index 55% rename from Source/Client/ModeCursor.h rename to Source/Client/Mode/ModeCursor.h index 71ce4f3..084b8ff 100644 --- a/Source/Client/ModeCursor.h +++ b/Source/Client/Mode/ModeCursor.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_MODECURSOR_H -#define RAGNAROK_SOURCE_CLIENT_MODECURSOR_H +#ifndef RAGNAROK_SOURCE_CLIENT_MODE_MODECURSOR_H +#define RAGNAROK_SOURCE_CLIENT_MODE_MODECURSOR_H #include -// CMode fields+0x50..+0x57; change tick remains at its actual owner field+0x24. struct ModeCursor { std::int32_t type; std::uint32_t frame; diff --git a/Source/Client/ModeDragState.cpp b/Source/Client/Mode/ModeDragState.cpp similarity index 76% rename from Source/Client/ModeDragState.cpp rename to Source/Client/Mode/ModeDragState.cpp index 41d404f..25756f2 100644 --- a/Source/Client/ModeDragState.cpp +++ b/Source/Client/Mode/ModeDragState.cpp @@ -1,10 +1,9 @@ -#include "Client/ModeDragState.h" -#include "Contents/ItemInfo.h" -#include "Contents/ItemResources.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "Client/Mode/ModeDragState.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/Items/ItemResources.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" -#include #include // OFFSET: 0x00CEC930 @@ -28,21 +27,18 @@ void ModeDragState::Clear() { // OFFSET: 0x00CFE140 // FUNCTION: fn_21429 void ModeDragState::BeginItem( - WindowManagerWindows& windows, - ItemDescriptions& descriptions, - int sourceValue, - const ItemInfo& item, - int quantityValue, - int slotValue + WindowManagerWindows& windows, ItemDescriptions& descriptions, int sourceValue, const ItemInfo& item, int quantityValue, int slotValue ) { UIWindow* window = windows.EnsureWindow(15); if (window->geometry.visible != 0) { window->Show(0); } + this->Clear(); if (item.unknown_0000[1] == 0) { return; } + this->source = sourceValue; this->skill = 0; this->id = item.unknown_0000[1]; @@ -56,31 +52,28 @@ void ModeDragState::BeginItem( this->slot = slotValue; this->refine = item.unknown_0060; std::memcpy(this->cards, item.unknown_001C, sizeof(this->cards)); - this->optionCount = std::bit_cast(item.unknown_0098); + this->optionCount = item.unknown_0098; + for (int index = 0; index < this->optionCount; ++index) { std::memcpy(this->options + 5 * index, item.unknown_009C + 5 * index, 5); } + this->grade = static_cast(item.unknown_0088); this->unknown_03B6 = item.unknown_0074[3]; this->unknown_03B8 = item.unknown_0000[2]; - this->unknown_03C0 = std::bit_cast(item.unknown_0070); + this->unknown_03C0 = item.unknown_0070; } // OFFSET: 0x00CFE2A0 // FUNCTION: fn_21430 void ModeDragState::BeginSkill( - WindowManagerWindows& windows, - ResourceMgr& resources, - int sourceValue, - std::uint32_t idValue, - const char* nameValue, - int level, - int slotValue + WindowManagerWindows& windows, ResourceMgr& resources, int sourceValue, std::uint32_t idValue, const char* nameValue, int level, int slotValue ) { UIWindow* window = windows.EnsureWindow(15); if (window->geometry.visible != 0) { window->Show(0); } + this->Clear(); this->source = sourceValue; this->id = idValue; diff --git a/Source/Client/ModeDragState.h b/Source/Client/Mode/ModeDragState.h similarity index 64% rename from Source/Client/ModeDragState.h rename to Source/Client/Mode/ModeDragState.h index 5dc9bd1..80e4c92 100644 --- a/Source/Client/ModeDragState.h +++ b/Source/Client/Mode/ModeDragState.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_MODEDRAGSTATE_H -#define RAGNAROK_SOURCE_CLIENT_MODEDRAGSTATE_H +#ifndef RAGNAROK_SOURCE_CLIENT_MODE_MODEDRAGSTATE_H +#define RAGNAROK_SOURCE_CLIENT_MODE_MODEDRAGSTATE_H #include #include @@ -9,8 +9,6 @@ class ResourceMgr; struct ItemDescriptions; struct ItemInfo; -// Original contiguous CGameMode fields+0x308..+0x3C7. Strings own their data; -// callers keep this value at the real mode owner rather than a second singleton. struct ModeDragState { /* 0308 */ int source; /* 030C */ std::uint32_t id; @@ -37,23 +35,8 @@ struct ModeDragState { /* 03C0 */ std::int64_t unknown_03C0; void Clear(); - void BeginItem( - WindowManagerWindows& windows, - ItemDescriptions& descriptions, - int source, - const ItemInfo& item, - int quantity, - int slot - ); - void BeginSkill( - WindowManagerWindows& windows, - ResourceMgr& resources, - int source, - std::uint32_t id, - const char* name, - int level, - int slot - ); + void BeginItem(WindowManagerWindows& windows, ItemDescriptions& descriptions, int source, const ItemInfo& item, int quantity, int slot); + void BeginSkill(WindowManagerWindows& windows, ResourceMgr& resources, int source, std::uint32_t id, const char* name, int level, int slot); }; #if defined(_WIN32) && !defined(_WIN64) diff --git a/Source/Client/Mode/ModeEvents.h b/Source/Client/Mode/ModeEvents.h new file mode 100644 index 0000000..800cde5 --- /dev/null +++ b/Source/Client/Mode/ModeEvents.h @@ -0,0 +1,14 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_MODE_MODEEVENTS_H +#define RAGNAROK_SOURCE_CLIENT_MODE_MODEEVENTS_H + +#include + +class ModeEvents { +public: + virtual std::intptr_t SendModeMessage(int event, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) = 0; + +protected: + ~ModeEvents() = default; +}; + +#endif diff --git a/Source/Client/ModeTooltip.cpp b/Source/Client/Mode/ModeTooltip.cpp similarity index 69% rename from Source/Client/ModeTooltip.cpp rename to Source/Client/Mode/ModeTooltip.cpp index fbf0161..30bc342 100644 --- a/Source/Client/ModeTooltip.cpp +++ b/Source/Client/Mode/ModeTooltip.cpp @@ -1,34 +1,16 @@ -#include "Client/ModeTooltip.h" -#include "UI/UITransBalloonText.h" -#include "UI/WindowOrdering.h" -#include "UI/WindowRetirement.h" +#include "Client/Mode/ModeTooltip.h" +#include "UI/Text/UITransBalloonText.h" +#include "UI/Window/WindowOrdering.h" +#include "UI/Window/WindowRetirement.h" -#include #include #include #include -// clang-format off -#include -// clang-format on - -namespace { - - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - -} +#include // OFFSET: 0x00AD6510 // FUNCTION: fn_17834 -void ModeTooltip::Show( - const char* value, - int x, - int y, - std::uint32_t color, - unsigned char option, - unsigned char convert -) { +void ModeTooltip::Show(const char* value, int x, int y, std::uint32_t color, unsigned char option, unsigned char convert) { if (std::strlen(value) == 0) { return; } @@ -68,8 +50,8 @@ void ModeTooltip::Show( this->window->SetColors(rgb, 0); this->window->SetBackground(0x88000000u); - const int maximumX = Add(Add(this->screenWidth, -this->window->geometry.width), 3); - const int maximumY = Add(Add(this->screenHeight, -this->window->geometry.height), 3); + const int maximumX = this->screenWidth - this->window->geometry.width + 3; + const int maximumY = this->screenHeight - this->window->geometry.height + 3; const int left = x < -3 ? -3 : x; const int top = y < -3 ? -3 : y; diff --git a/Source/Client/ModeTooltip.h b/Source/Client/Mode/ModeTooltip.h similarity index 66% rename from Source/Client/ModeTooltip.h rename to Source/Client/Mode/ModeTooltip.h index e249c2a..c796a8a 100644 --- a/Source/Client/ModeTooltip.h +++ b/Source/Client/Mode/ModeTooltip.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_MODETOOLTIP_H -#define RAGNAROK_SOURCE_CLIENT_MODETOOLTIP_H +#ifndef RAGNAROK_SOURCE_CLIENT_MODE_MODETOOLTIP_H +#define RAGNAROK_SOURCE_CLIENT_MODE_MODETOOLTIP_H #include #include @@ -11,8 +11,6 @@ struct BalloonTextContext; struct WindowOrdering; struct WindowRetirement; -// Borrowed CMode tooltip pointer, timestamp and actual -// manager render list. struct ModeTooltip { UITransBalloonText*& window; std::uint32_t& tick; @@ -24,8 +22,7 @@ struct ModeTooltip { const int& screenHeight; void Show(const char* value, int x, int y, std::uint32_t color, unsigned char option, unsigned char convert); - // Schedules the tooltip for manager retirement 100 ms after Show; the - // deadline uses wrapping 32-bit tick arithmetic. + void Expire(WindowRetirement& retirement); }; diff --git a/Source/Client/ModeEvents.h b/Source/Client/ModeEvents.h deleted file mode 100644 index 66eac79..0000000 --- a/Source/Client/ModeEvents.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_MODEEVENTS_H -#define RAGNAROK_SOURCE_CLIENT_MODEEVENTS_H - -#include - -// Source view of active CMode's virtual slot6, not a replacement CMode owner. -// Concrete mode implementations must supply their real event handling. -class ModeEvents { -public: - virtual std::intptr_t SendModeMessage( - int event, - std::intptr_t argument1, - std::intptr_t argument2, - std::intptr_t argument3, - std::intptr_t argument4 - ) = 0; - -protected: - ~ModeEvents() = default; -}; - -#endif diff --git a/Source/Client/ReplayPacketRecorder.cpp b/Source/Client/ReplayPacketRecorder.cpp index d17cbdb..caa80ba 100644 --- a/Source/Client/ReplayPacketRecorder.cpp +++ b/Source/Client/ReplayPacketRecorder.cpp @@ -1,13 +1,10 @@ #include "Client/ReplayPacketRecorder.h" -#include "Network/PacketLengths.h" +#include "Network/Packets/PacketLengths.h" -#include #include #include #include -// clang-format off -#include -// clang-format on +#include // OFFSET: 0x00B86880 // FUNCTION: fn_19332 @@ -64,10 +61,11 @@ bool ReplayPacketRecorder::Record(std::uint16_t bytes, const void* packet, int e std::memcpy(record.data() + 10 + index * 4, &word, sizeof(word)); } - std::fseek(this->file, std::bit_cast(this->fileOffset), SEEK_SET); + std::fseek(this->file, static_cast(this->fileOffset), SEEK_SET); std::fwrite(record.data(), record.size(), 1, this->file); this->fileOffset += static_cast(record.size()); ++this->records; + return true; } @@ -88,12 +86,6 @@ void WindowResponseRecorder::Record(int windowId, int response, std::intptr_t b, }; #pragma pack(pop) static_assert(sizeof(Response) == 26); - const Response packet{ - 0x038408AEu, - 26, - windowId, - response, - {static_cast(b), static_cast(c), static_cast(d)} - }; + const Response packet{0x038408AEu, 26, windowId, response, {static_cast(b), static_cast(c), static_cast(d)}}; this->packets.Record(sizeof(packet), &packet, 42, 0); } diff --git a/Source/Client/ReplayPacketRecorder.h b/Source/Client/ReplayPacketRecorder.h index fde7aeb..da9ac2e 100644 --- a/Source/Client/ReplayPacketRecorder.h +++ b/Source/Client/ReplayPacketRecorder.h @@ -6,27 +6,24 @@ struct PacketLengths; -// Borrowed fields of the original replay owner. File creation, header writing -// and mode transitions remain the enclosing owner's responsibility. struct ReplayPacketRecorder { const PacketLengths& lengths; - const std::uint32_t& baseFrame; // +0x10 - const std::uint32_t& started; // +0x14 - const std::uint32_t& frame; // +0x1C - const std::uint32_t& key0; // +0x2C - const std::uint32_t& key1; // +0x30 - const unsigned char& recordRestricted; // +0xB6 - std::FILE*& file; // +0x1DC - std::uint32_t& fileOffset; // +0x1E0 - std::uint32_t& records; // +0x1E4 - std::uint32_t& cipherIndex; // +0x1E8 - std::uint32_t& cipherBase; // +0x1EC - std::uint32_t& cipherKey; // +0x1F0 + const std::uint32_t& baseFrame; + const std::uint32_t& started; + const std::uint32_t& frame; + const std::uint32_t& key0; + const std::uint32_t& key1; + const unsigned char& recordRestricted; + std::FILE*& file; + std::uint32_t& fileOffset; + std::uint32_t& records; + std::uint32_t& cipherIndex; + std::uint32_t& cipherBase; + std::uint32_t& cipherKey; bool Record(std::uint16_t bytes, const void* packet, int event, std::uint32_t delay); }; -// UIWindow response serialization, gated by replay mode +0x0C. struct WindowResponseRecorder { const int& mode; ReplayPacketRecorder& packets; diff --git a/Source/Client/TextInputBuffer.h b/Source/Client/TextInputBuffer.h deleted file mode 100644 index dd113d2..0000000 --- a/Source/Client/TextInputBuffer.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CLIENT_TEXTINPUTBUFFER_H -#define RAGNAROK_SOURCE_CLIENT_TEXTINPUTBUFFER_H - -#include -#include - -class UIWindow; -class WindowManagerWindows; - -class TextInputSuggestions { -public: - virtual void Update(const char* text) = 0; - -protected: - ~TextInputSuggestions() = default; -}; - -// Borrowed fields of the original input owner, not a replacement IME singleton. -struct TextInputBuffer { - std::string& text; - int& cursor; - int& anchor; - std::string& composition; - std::string& candidate; - int& compositionState; - HWND& window; - const bool& suggestionsEnabled; - UIWindow* const& focused; - UIWindow* const& chatInput; - const bool& chatOpen; - TextInputSuggestions& suggestions; - - void CancelComposition(); - void DeleteSelection(); - void Insert(const char* value); - void Select(int anchor, int cursor); - void CopyDisplayText(std::string& output) const; - void Selection(int& anchor, int& cursor) const; - // Sorted selection endpoints, preserving sequential output writes/aliasing. - void SelectionRange(int& begin, int& end) const; - // Reads GCS_COMPSTR through the native IME, converts with the caller's language - // codepage and publishes candidate. - // Suggestions concatenate committed text + candidate, truncated to 255 bytes; - // missing IME context clears candidate without publishing suggestions. - void RefreshComposition(unsigned codePage); - // Copies CF_TEXT with original GlobalAlloc/clipboard ownership. Password - // mode masks through text end (not selection end), matching the reference; - // callers must retain its original selection/storage preconditions. - void CopySelection(bool password); - void Paste(UIWindow* blockedFocus, WindowManagerWindows& windows); - // Only cursor moves; anchor/selection remains unchanged. Negative cursor - // becomes zero; positive cursor uses CharPrevExA with the low codepage WORD. - void MoveBack(unsigned codePage); - // Unsigned cursor comparison: out-of-range (including negative) clamps to - // text length; in-range advances via CharNextExA. Anchor is unchanged. - void MoveForward(unsigned codePage); - // Original ANSI character payload is a NUL-terminated byte sequence in the - // low DWORD (not Unicode). Control bytes <=31 are ignored except backspace. - void Character(unsigned value, LPARAM unused, unsigned codePage); - // Shift wins over Control. The borrowed chat-arrow child is the actual - // Chat owner child; visible children receive message 176 instead of movement. - void KeyDown( - unsigned key, - LPARAM unused, - unsigned codePage, - bool password, - UIWindow* blockedPasteFocus, - WindowManagerWindows& windows, - UIWindow* const& chatArrows - ); -}; - -#endif diff --git a/Source/Contents/AccountService.h b/Source/Contents/AccountService.h deleted file mode 100644 index b58661a..0000000 --- a/Source/Contents/AccountService.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ACCOUNTSERVICE_H -#define RAGNAROK_SOURCE_CONTENTS_ACCOUNTSERVICE_H - -#include - -class LuaScript; - -// Explicit state: settings script, table script, host/port/override pointers. -std::string ResolveAccountServiceBase( - LuaScript& settings, - LuaScript& tables, - const char* host, - const char* port, - const char* overrideKey -); - -#endif diff --git a/Source/Contents/AccountUserData.h b/Source/Contents/AccountUserData.h deleted file mode 100644 index 97c7176..0000000 --- a/Source/Contents/AccountUserData.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ACCOUNTUSERDATA_H -#define RAGNAROK_SOURCE_CONTENTS_ACCOUNTUSERDATA_H - -#include - -// Reconstructed semantic name for the original complete whisper-list operation. -void LoadWhisperBlockList(Json::Value& data); - -#endif diff --git a/Source/Contents/AttackMotion.cpp b/Source/Contents/Actors/AttackMotion.cpp similarity index 94% rename from Source/Contents/AttackMotion.cpp rename to Source/Contents/Actors/AttackMotion.cpp index c600668..1500473 100644 --- a/Source/Contents/AttackMotion.cpp +++ b/Source/Contents/Actors/AttackMotion.cpp @@ -1,4 +1,4 @@ -#include "Contents/AttackMotion.h" +#include "Contents/Actors/AttackMotion.h" // OFFSET: 0x00DDFB50 // FUNCTION: fn_23444 diff --git a/Source/Contents/Actors/AttackMotion.h b/Source/Contents/Actors/AttackMotion.h new file mode 100644 index 0000000..46575bd --- /dev/null +++ b/Source/Contents/Actors/AttackMotion.h @@ -0,0 +1,6 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_ACTORS_ATTACKMOTION_H +#define RAGNAROK_SOURCE_CONTENTS_ACTORS_ATTACKMOTION_H + +float AttackMotionLength(int job, int appearance, int equipment, int attackMode); + +#endif diff --git a/Source/Contents/GameObject.cpp b/Source/Contents/Actors/GameObject.cpp similarity index 76% rename from Source/Contents/GameObject.cpp rename to Source/Contents/Actors/GameObject.cpp index 20b32c8..0e4dc0d 100644 --- a/Source/Contents/GameObject.cpp +++ b/Source/Contents/Actors/GameObject.cpp @@ -1,7 +1,5 @@ -#include "Contents/GameObject.h" - -#include -#include +#include "Contents/Actors/GameObject.h" +#include "Utility/Math/ScalarConversion.h" namespace { // STATIC: 0x0135EF80 @@ -27,8 +25,7 @@ bool CGameObject::Update() { // OFFSET: 0x00CBF850 // FUNCTION: fn_21113 -void CGameObject:: - SendObjectMessage(CGameObject*, int, int, int, int, int, int, int, int, int, int, int, int, int, int) { +void CGameObject::SendObjectMessage(CGameObject*, int, int, int, int, int, int, int, int, int, int, int, int, int, int) { } // OFFSET: 0x00CB20A0 @@ -54,5 +51,5 @@ int CGameObject::Direction(float angle, const CameraDirectionContext& camera) { relative -= 360.0f; } - return _mm_cvttss_si32(_mm_div_ss(_mm_set_ss(relative), _mm_set_ss(45.0f))); + return TruncateToInt(relative / 45.0f); } diff --git a/Source/Contents/GameObject.h b/Source/Contents/Actors/GameObject.h similarity index 51% rename from Source/Contents/GameObject.h rename to Source/Contents/Actors/GameObject.h index 23c7ba4..a5977b8 100644 --- a/Source/Contents/GameObject.h +++ b/Source/Contents/Actors/GameObject.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_GAMEOBJECT_H -#define RAGNAROK_SOURCE_CONTENTS_GAMEOBJECT_H +#ifndef RAGNAROK_SOURCE_CONTENTS_ACTORS_GAMEOBJECT_H +#define RAGNAROK_SOURCE_CONTENTS_ACTORS_GAMEOBJECT_H #include @@ -8,30 +8,12 @@ struct CameraDirectionContext { const float* const& cameraAngle; }; -// RTTI CGameObject. Original virtual methods -// with empty/default behavior remain real base behavior, not actor stand-ins. class CGameObject { public: CGameObject(); virtual ~CGameObject(); virtual bool Update(); - virtual void SendObjectMessage( - CGameObject* sender, - int message, - int a, - int b, - int c, - int d, - int e, - int f, - int g, - int h, - int i, - int j, - int k, - int l, - int m - ); + virtual void SendObjectMessage(CGameObject* sender, int message, int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m); virtual void Draw(int argument); virtual int Direction(float angle, const CameraDirectionContext& camera); diff --git a/Source/Contents/RenderObject.cpp b/Source/Contents/Actors/RenderObject.cpp similarity index 61% rename from Source/Contents/RenderObject.cpp rename to Source/Contents/Actors/RenderObject.cpp index c8d2d07..8824ce7 100644 --- a/Source/Contents/RenderObject.cpp +++ b/Source/Contents/Actors/RenderObject.cpp @@ -1,6 +1,6 @@ -#include "Contents/RenderObject.h" +#include "Contents/Actors/RenderObject.h" -#include +#include "Utility/Math/ScalarConversion.h" // OFFSET: 0x00CA8730 // FUNCTION: fn_20991 @@ -19,9 +19,8 @@ bool CRenderObject::Update() { // OFFSET: 0x00CBF920 // FUNCTION: fn_21115 -// CRenderObject's own empty override, separate from CGameObject's 0x00CBF850. -void CRenderObject:: - SendObjectMessage(CGameObject*, int, int, int, int, int, int, int, int, int, int, int, int, int, int) { + +void CRenderObject::SendObjectMessage(CGameObject*, int, int, int, int, int, int, int, int, int, int, int, int, int, int) { } // OFFSET: 0x00CC2D40 @@ -32,6 +31,6 @@ void CRenderObject::SetScreenBounds(const float*, float, float) { // OFFSET: 0x00CC3DC0 // FUNCTION: fn_21154 void CRenderObject::SetScreenPosition(float x, float y) { - this->render.screenX = _mm_cvttss_si32(_mm_set_ss(x)); - this->render.screenY = _mm_cvttss_si32(_mm_set_ss(y)); + this->render.screenX = TruncateToInt(x); + this->render.screenY = TruncateToInt(y); } diff --git a/Source/Contents/Actors/RenderObject.h b/Source/Contents/Actors/RenderObject.h new file mode 100644 index 0000000..69ec0e5 --- /dev/null +++ b/Source/Contents/Actors/RenderObject.h @@ -0,0 +1,25 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_ACTORS_RENDEROBJECT_H +#define RAGNAROK_SOURCE_CONTENTS_ACTORS_RENDEROBJECT_H + +#include "Contents/Actors/GameObject.h" +#include "Contents/Actors/RenderObjectState.h" + +class CRenderObject : public CGameObject { +public: + CRenderObject(ResourceMgr& resources, JobNames& names); + ~CRenderObject() override; + bool Update() override; + void SendObjectMessage(CGameObject* sender, int message, int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m) override; + + virtual void SetScreenBounds(const float* bounds, float x, float y); + + virtual void SetScreenPosition(float x, float y); + + RenderObjectState render; +}; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(CRenderObject) == 0x138); +#endif + +#endif diff --git a/Source/Contents/RenderObjectState.cpp b/Source/Contents/Actors/RenderObjectState.cpp similarity index 92% rename from Source/Contents/RenderObjectState.cpp rename to Source/Contents/Actors/RenderObjectState.cpp index 35b3c8d..fdfae5c 100644 --- a/Source/Contents/RenderObjectState.cpp +++ b/Source/Contents/Actors/RenderObjectState.cpp @@ -1,11 +1,12 @@ -#include "Contents/JobNames.h" -#include "Contents/RenderObjectState.h" -#include "Resource/ActionResource.h" +#include "Contents/Jobs/JobNames.h" +#include "Contents/Actors/RenderObjectState.h" +#include "Resource/Sprites/ActionResource.h" #include "Resource/ResourceMgr.h" -#include "Resource/SpriteResource.h" +#include "Resource/Sprites/SpriteResource.h" #include -#include +#include +#include // OFFSET: 0x00CA8730 // FUNCTION: fn_20991 diff --git a/Source/Contents/RenderObjectState.h b/Source/Contents/Actors/RenderObjectState.h similarity index 92% rename from Source/Contents/RenderObjectState.h rename to Source/Contents/Actors/RenderObjectState.h index 469d0cf..9d5096d 100644 --- a/Source/Contents/RenderObjectState.h +++ b/Source/Contents/Actors/RenderObjectState.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_RENDEROBJECTSTATE_H -#define RAGNAROK_SOURCE_CONTENTS_RENDEROBJECTSTATE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_ACTORS_RENDEROBJECTSTATE_H +#define RAGNAROK_SOURCE_CONTENTS_ACTORS_RENDEROBJECTSTATE_H #include "Contents/InstantVar.h" @@ -11,8 +11,6 @@ class ResourceMgr; class CSprRes; class CActRes; -// Original CRenderObject fields +0x10..+0x137, without its CGameObject base. -// This owns only the recovered lifecycle state, not unresolved render virtuals. struct RenderObjectState { RenderObjectState(ResourceMgr& resources, JobNames& names); ~RenderObjectState(); diff --git a/Source/Contents/SpriteDrawingPolicy.cpp b/Source/Contents/Actors/SpriteDrawingPolicy.cpp similarity index 63% rename from Source/Contents/SpriteDrawingPolicy.cpp rename to Source/Contents/Actors/SpriteDrawingPolicy.cpp index 295c3a6..53ee0d9 100644 --- a/Source/Contents/SpriteDrawingPolicy.cpp +++ b/Source/Contents/Actors/SpriteDrawingPolicy.cpp @@ -1,4 +1,4 @@ -#include "Contents/SpriteDrawingPolicy.h" +#include "Contents/Actors/SpriteDrawingPolicy.h" #include "Script/LuaScript.h" // OFFSET: 0x0080E3A0 @@ -9,14 +9,11 @@ bool SpriteDrawingPolicy::DrawOnTop() const { if (this->newDrawOnTop == 1) { int unusedPriority = 1; this->script.Call( - "_New_DrawOnTop", "ddddd>bd", this->argument00BC, this->argument0018, this->argument0010, - this->argument0040, this->argument0044, &drawOnTop, &unusedPriority + "_New_DrawOnTop", "ddddd>bd", this->argument00BC, this->argument0018, this->argument0010, this->argument0040, this->argument0044, &drawOnTop, + &unusedPriority ); } else { - this->script.Call( - "DrawOnTop", "ddddd>b", this->argument00BC, this->argument0018, this->argument0010, - this->argument0040, this->argument0044, &drawOnTop - ); + this->script.Call("DrawOnTop", "ddddd>b", this->argument00BC, this->argument0018, this->argument0010, this->argument0040, this->argument0044, &drawOnTop); } return drawOnTop; diff --git a/Source/Contents/Actors/SpriteDrawingPolicy.h b/Source/Contents/Actors/SpriteDrawingPolicy.h new file mode 100644 index 0000000..4b4e377 --- /dev/null +++ b/Source/Contents/Actors/SpriteDrawingPolicy.h @@ -0,0 +1,21 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_ACTORS_SPRITEDRAWINGPOLICY_H +#define RAGNAROK_SOURCE_CONTENTS_ACTORS_SPRITEDRAWINGPOLICY_H + +class LuaScript; + +struct SpriteDrawingPolicy { + LuaScript& script; + const unsigned char& newDrawOnTop; + int& argument00BC; + const int& argument0018; + const int& argument0010; + const int& argument0040; + const int& argument0044; + bool& helmRobe; + + bool DrawOnTop() const; + + bool SetRobe(int robe); +}; + +#endif diff --git a/Source/Contents/AsyncWorkMgr.cpp b/Source/Contents/Async/AsyncWorkMgr.cpp similarity index 52% rename from Source/Contents/AsyncWorkMgr.cpp rename to Source/Contents/Async/AsyncWorkMgr.cpp index dfb6de5..540396d 100644 --- a/Source/Contents/AsyncWorkMgr.cpp +++ b/Source/Contents/Async/AsyncWorkMgr.cpp @@ -1,18 +1,18 @@ -#include "Contents/AccountLinkedUserDataLoadAsyncWork.h" -#include "Contents/AccountLinkedUserDataSaveAsyncWork.h" -#include "Contents/AsyncWorkMgr.h" -#include "Contents/AsyncWorkRecycleObjectPoolMgr.h" -#include "Contents/ChangePartyMasterAsyncWork.h" -#include "Contents/CharacterLinkedUserDataLoadAsyncWork.h" -#include "Contents/CharacterLinkedUserDataSaveAsyncWork.h" -#include "Contents/EmblemDataDownloadAsyncWork.h" -#include "Contents/EmblemDataUploadAsyncWork.h" -#include "Contents/LoadMyPartyAsyncWork.h" -#include "Contents/LoadPartyInfoAsyncWork.h" -#include "Contents/LoadPartyListAsyncWork.h" -#include "Contents/MCStoreInfoBackupAsyncWork.h" -#include "Contents/RegisterPartyAsyncWork.h" -#include "Contents/StopRecruitingAsyncWork.h" +#include "Contents/UserData/AccountLinkedUserDataLoadAsyncWork.h" +#include "Contents/UserData/AccountLinkedUserDataSaveAsyncWork.h" +#include "Contents/Async/AsyncWorkMgr.h" +#include "Contents/Async/AsyncWorkRecycleObjectPoolMgr.h" +#include "Contents/Party/ChangePartyMasterAsyncWork.h" +#include "Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.h" +#include "Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.h" +#include "Contents/Emblems/EmblemDataDownloadAsyncWork.h" +#include "Contents/Emblems/EmblemDataUploadAsyncWork.h" +#include "Contents/Party/LoadMyPartyAsyncWork.h" +#include "Contents/Party/LoadPartyInfoAsyncWork.h" +#include "Contents/Party/LoadPartyListAsyncWork.h" +#include "Contents/Store/MCStoreInfoBackupAsyncWork.h" +#include "Contents/Party/RegisterPartyAsyncWork.h" +#include "Contents/Party/StopRecruitingAsyncWork.h" #include @@ -76,12 +76,7 @@ void CAsyncWorkMgr::Shutdown() { // OFFSET: 0x00573DB0 // FUNCTION: fn_02499 -void CAsyncWorkMgr::LoadAccount( - std::uint32_t accountId, - std::string world, - std::string url, - AccountConfigLoad& context -) { +void CAsyncWorkMgr::LoadAccount(std::uint32_t accountId, std::string world, std::string url, AccountConfigLoad& context) { NAsyncWorkPtr work(this->m_pools, "AccountLinkedUserData_Load"); if (work.Get()) { @@ -92,13 +87,7 @@ void CAsyncWorkMgr::LoadAccount( // OFFSET: 0x00573EC0 // FUNCTION: fn_02500 -void CAsyncWorkMgr::SaveAccount( - std::uint32_t accountId, - std::string world, - std::string url, - std::string token, - std::string data -) { +void CAsyncWorkMgr::SaveAccount(std::uint32_t accountId, std::string world, std::string url, std::string token, std::string data) { NAsyncWorkPtr work(this->m_pools, "AccountLinkedUserData_Save"); if (work.Get()) { @@ -110,25 +99,14 @@ void CAsyncWorkMgr::SaveAccount( // OFFSET: 0x00574010 // FUNCTION: fn_02501 void CAsyncWorkMgr::ChangePartyMaster( - std::uint32_t accountId, - std::uint32_t characterId, - std::string characterName, - std::uint32_t targetAccountId, - std::uint32_t targetCharacterId, - std::string targetName, - std::string world, - std::string url, - std::string token, - WindowManagerWindows& windows + std::uint32_t accountId, std::uint32_t characterId, std::string characterName, std::uint32_t targetAccountId, std::uint32_t targetCharacterId, + std::string targetName, std::string world, std::string url, std::string token, WindowManagerWindows& windows ) { NAsyncWorkPtr work(this->m_pools, "Change_PartyMaster"); if (work.Get()) { static_cast(work.Get()) - ->Bind( - accountId, characterId, characterName, targetAccountId, targetCharacterId, targetName, world, url, token, - windows - ); + ->Bind(accountId, characterId, characterName, targetAccountId, targetCharacterId, targetName, world, url, token, windows); this->Submit(work); } } @@ -136,37 +114,23 @@ void CAsyncWorkMgr::ChangePartyMaster( // OFFSET: 0x00574190 // FUNCTION: fn_02502 void CAsyncWorkMgr::LoadCharacter( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - CharacterConfigLoad& context + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, CharacterConfigLoad& context ) { NAsyncWorkPtr work(this->m_pools, "CharacterLinkedUserData_Load"); if (work.Get()) { - static_cast(work.Get()) - ->Bind(accountId, characterId, world, url, token, context); + static_cast(work.Get())->Bind(accountId, characterId, world, url, token, context); this->Submit(work); } } // OFFSET: 0x005742D0 // FUNCTION: fn_02503 -void CAsyncWorkMgr::SaveCharacter( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - std::string data -) { +void CAsyncWorkMgr::SaveCharacter(std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, std::string data) { NAsyncWorkPtr work(this->m_pools, "CharacterLinkedUserData_Save"); if (work.Get()) { - static_cast(work.Get()) - ->Bind(accountId, characterId, world, url, token, data); + static_cast(work.Get())->Bind(accountId, characterId, world, url, token, data); this->Submit(work); } } @@ -174,19 +138,12 @@ void CAsyncWorkMgr::SaveCharacter( // OFFSET: 0x00574430 // FUNCTION: fn_02504 void CAsyncWorkMgr::DownloadEmblem( - std::string url, - std::uint32_t accountId, - std::string token, - std::string world, - std::uint32_t guildId, - std::uint32_t version, - CConnection& connection + std::string url, std::uint32_t accountId, std::string token, std::string world, std::uint32_t guildId, std::uint32_t version, CConnection& connection ) { NAsyncWorkPtr work(this->m_pools, "Emblem_Download"); if (work.Get()) { - static_cast(work.Get()) - ->Bind(url, accountId, token, world, guildId, version, connection); + static_cast(work.Get())->Bind(url, accountId, token, world, guildId, version, connection); this->Submit(work); } } @@ -194,20 +151,13 @@ void CAsyncWorkMgr::DownloadEmblem( // OFFSET: 0x00574570 // FUNCTION: fn_02505 void CAsyncWorkMgr::UploadEmblem( - std::string url, - std::uint32_t accountId, - std::string token, - std::string world, - std::uint32_t guildId, - std::string path, - CEmblemDataMgr& owner, + std::string url, std::uint32_t accountId, std::string token, std::string world, std::uint32_t guildId, std::string path, CEmblemDataMgr& owner, EmblemUploadContext& context ) { NAsyncWorkPtr work(this->m_pools, "Emblem_Upload"); if (work.Get()) { - static_cast(work.Get()) - ->Bind(url, accountId, token, world, guildId, path, owner, context); + static_cast(work.Get())->Bind(url, accountId, token, world, guildId, path, owner, context); this->Submit(work); } } @@ -215,12 +165,7 @@ void CAsyncWorkMgr::UploadEmblem( // OFFSET: 0x005746D0 // FUNCTION: fn_02506 void CAsyncWorkMgr::LoadMyParty( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - WindowManagerWindows& windows + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, WindowManagerWindows& windows ) { NAsyncWorkPtr work(this->m_pools, "MyParty_Load"); @@ -233,19 +178,13 @@ void CAsyncWorkMgr::LoadMyParty( // OFFSET: 0x00574810 // FUNCTION: fn_02507 void CAsyncWorkMgr::LoadPartyInfo( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - std::uint32_t queryAccountId, + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, std::uint32_t queryAccountId, PartyInfoContext& context ) { NAsyncWorkPtr work(this->m_pools, "PartyInfo_Load"); if (work.Get()) { - static_cast(work.Get()) - ->Bind(accountId, characterId, world, url, token, queryAccountId, context); + static_cast(work.Get())->Bind(accountId, characterId, world, url, token, queryAccountId, context); this->Submit(work); } } @@ -253,21 +192,13 @@ void CAsyncWorkMgr::LoadPartyInfo( // OFFSET: 0x00574950 // FUNCTION: fn_02508 void CAsyncWorkMgr::LoadPartyList( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - int search, - CAdvenPartyInfo filter, - int page, + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, int search, CAdvenPartyInfo filter, int page, WindowManagerWindows& windows ) { NAsyncWorkPtr work(this->m_pools, "PartyList_Load"); if (work.Get()) { - static_cast(work.Get()) - ->Bind(accountId, characterId, world, url, token, filter, search, page, windows); + static_cast(work.Get())->Bind(accountId, characterId, world, url, token, filter, search, page, windows); this->Submit(work); } } @@ -275,20 +206,13 @@ void CAsyncWorkMgr::LoadPartyList( // OFFSET: 0x00574B30 // FUNCTION: fn_02509 void CAsyncWorkMgr::LoadStore( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - int type, - CMCStoreInfoBackup& owner, + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, int type, CMCStoreInfoBackup& owner, StoreBackupContext& context ) { NAsyncWorkPtr work(this->m_pools, "MerchantStoreInformation_Load"); if (work.Get()) { - static_cast(work.Get()) - ->Bind(url, accountId, characterId, world, token, type, owner, context); + static_cast(work.Get())->Bind(url, accountId, characterId, world, token, type, owner, context); this->Submit(work); } } @@ -296,21 +220,13 @@ void CAsyncWorkMgr::LoadStore( // OFFSET: 0x00574C70 // FUNCTION: fn_02510 void CAsyncWorkMgr::SaveStore( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - std::string data, - int type, - CMCStoreInfoBackup& owner, - StoreBackupContext& context + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, std::string data, int type, + CMCStoreInfoBackup& owner, StoreBackupContext& context ) { NAsyncWorkPtr work(this->m_pools, "MerchantStoreInformation_Save"); if (work.Get()) { - static_cast(work.Get()) - ->Bind(url, accountId, characterId, world, token, data, type, owner, context); + static_cast(work.Get())->Bind(url, accountId, characterId, world, token, data, type, owner, context); this->Submit(work); } } @@ -318,13 +234,7 @@ void CAsyncWorkMgr::SaveStore( // OFFSET: 0x00574DD0 // FUNCTION: fn_02511 void CAsyncWorkMgr::RegisterParty( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - CAdvenPartyInfo info, - RegisterPartyContext& context + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, CAdvenPartyInfo info, RegisterPartyContext& context ) { NAsyncWorkPtr work(this->m_pools, "Register_Party"); @@ -337,12 +247,7 @@ void CAsyncWorkMgr::RegisterParty( // OFFSET: 0x00574F40 // FUNCTION: fn_02512 void CAsyncWorkMgr::StopRecruiting( - std::uint32_t accountId, - std::string world, - std::string url, - std::string token, - std::uint32_t masterAccountId, - StopRecruitingContext& context + std::uint32_t accountId, std::string world, std::string url, std::string token, std::uint32_t masterAccountId, StopRecruitingContext& context ) { NAsyncWorkPtr work(this->m_pools, "Stop_Recruiting"); diff --git a/Source/Contents/Async/AsyncWorkMgr.h b/Source/Contents/Async/AsyncWorkMgr.h new file mode 100644 index 0000000..28185c2 --- /dev/null +++ b/Source/Contents/Async/AsyncWorkMgr.h @@ -0,0 +1,83 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_ASYNC_ASYNCWORKMGR_H +#define RAGNAROK_SOURCE_CONTENTS_ASYNC_ASYNCWORKMGR_H + +#include "Contents/Party/AdvenPartyInfo.h" +#include "Utility/Async/NAsyncWorkMgr.h" + +class CAsyncWorkRecycleObjectPoolMgr; +class CConnection; +class CEmblemDataMgr; +class CMCStoreInfoBackup; +class WindowManagerWindows; +struct AccountConfigLoad; +struct CharacterConfigLoad; +struct EmblemUploadContext; +struct StoreBackupContext; +struct RegisterPartyContext; +struct StopRecruitingContext; +struct PartyInfoContext; + +class CAsyncWorkMgr : public NAsyncWorkMgr { +public: + explicit CAsyncWorkMgr(std::uint32_t workers); + ~CAsyncWorkMgr() override; + static bool Initialize(std::uint32_t workers); + static void Shutdown(); + + void LoadAccount(std::uint32_t accountId, std::string world, std::string url, AccountConfigLoad& context); + void SaveAccount(std::uint32_t accountId, std::string world, std::string url, std::string token, std::string data); + void ChangePartyMaster( + std::uint32_t accountId, std::uint32_t characterId, std::string characterName, std::uint32_t targetAccountId, std::uint32_t targetCharacterId, + std::string targetName, std::string world, std::string url, std::string token, WindowManagerWindows& windows + ); + void LoadCharacter(std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, CharacterConfigLoad& context); + void SaveCharacter(std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, std::string data); + void DownloadEmblem( + std::string url, std::uint32_t accountId, std::string token, std::string world, std::uint32_t guildId, std::uint32_t version, CConnection& connection + ); + void UploadEmblem( + std::string url, std::uint32_t accountId, std::string token, std::string world, std::uint32_t guildId, std::string path, CEmblemDataMgr& owner, + EmblemUploadContext& context + ); + void LoadMyParty(std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, WindowManagerWindows& windows); + void LoadPartyInfo( + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, std::uint32_t queryAccountId, + PartyInfoContext& context + ); + void LoadPartyList( + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, int search, CAdvenPartyInfo filter, int page, + WindowManagerWindows& windows + ); + void LoadStore( + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, int type, CMCStoreInfoBackup& owner, + StoreBackupContext& context + ); + void SaveStore( + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, std::string data, int type, + CMCStoreInfoBackup& owner, StoreBackupContext& context + ); + void RegisterParty( + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, CAdvenPartyInfo info, + RegisterPartyContext& context + ); + void + StopRecruiting(std::uint32_t accountId, std::string world, std::string url, std::string token, std::uint32_t masterAccountId, StopRecruitingContext& context); + + CAsyncWorkRecycleObjectPoolMgr& Pools() { + return *this->m_pools; + } + +private: + /* 0020 */ bool m_ready; + /* 0024 */ CAsyncWorkRecycleObjectPoolMgr* m_pools; +}; + +// STATIC: 0x0138968C +// GLOBAL: gl_24349 +extern CAsyncWorkMgr* g_asyncWorkMgr; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(CAsyncWorkMgr) == 40); +#endif + +#endif diff --git a/Source/Contents/AsyncWorkRecycleObjectPoolMgr.cpp b/Source/Contents/Async/AsyncWorkRecycleObjectPoolMgr.cpp similarity index 56% rename from Source/Contents/AsyncWorkRecycleObjectPoolMgr.cpp rename to Source/Contents/Async/AsyncWorkRecycleObjectPoolMgr.cpp index 7cd0a92..9870d56 100644 --- a/Source/Contents/AsyncWorkRecycleObjectPoolMgr.cpp +++ b/Source/Contents/Async/AsyncWorkRecycleObjectPoolMgr.cpp @@ -1,17 +1,17 @@ -#include "Contents/AccountLinkedUserDataLoadAsyncWork.h" -#include "Contents/AccountLinkedUserDataSaveAsyncWork.h" -#include "Contents/AsyncWorkRecycleObjectPoolMgr.h" -#include "Contents/ChangePartyMasterAsyncWork.h" -#include "Contents/CharacterLinkedUserDataLoadAsyncWork.h" -#include "Contents/CharacterLinkedUserDataSaveAsyncWork.h" -#include "Contents/EmblemDataDownloadAsyncWork.h" -#include "Contents/EmblemDataUploadAsyncWork.h" -#include "Contents/LoadMyPartyAsyncWork.h" -#include "Contents/LoadPartyInfoAsyncWork.h" -#include "Contents/LoadPartyListAsyncWork.h" -#include "Contents/MCStoreInfoBackupAsyncWork.h" -#include "Contents/RegisterPartyAsyncWork.h" -#include "Contents/StopRecruitingAsyncWork.h" +#include "Contents/UserData/AccountLinkedUserDataLoadAsyncWork.h" +#include "Contents/UserData/AccountLinkedUserDataSaveAsyncWork.h" +#include "Contents/Async/AsyncWorkRecycleObjectPoolMgr.h" +#include "Contents/Party/ChangePartyMasterAsyncWork.h" +#include "Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.h" +#include "Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.h" +#include "Contents/Emblems/EmblemDataDownloadAsyncWork.h" +#include "Contents/Emblems/EmblemDataUploadAsyncWork.h" +#include "Contents/Party/LoadMyPartyAsyncWork.h" +#include "Contents/Party/LoadPartyInfoAsyncWork.h" +#include "Contents/Party/LoadPartyListAsyncWork.h" +#include "Contents/Store/MCStoreInfoBackupAsyncWork.h" +#include "Contents/Party/RegisterPartyAsyncWork.h" +#include "Contents/Party/StopRecruitingAsyncWork.h" #include #include @@ -34,8 +34,6 @@ CAsyncWorkRecycleObjectPoolMgr::~CAsyncWorkRecycleObjectPoolMgr() { // OFFSET: 0x00578F30 // FUNCTION: fn_02566 bool CAsyncWorkRecycleObjectPoolMgr::RegisterPools() { - // The original inserts all fourteen owning pointers, including null on - // nothrow allocation failure. Duplicate keys fail registration, not null pools. const auto insert = [&](const char* name) { std::unique_ptr pool(new (std::nothrow) NRecycleObjectPool(2)); if (!this->m_pools.emplace(name, pool.get()).second) { @@ -50,14 +48,10 @@ bool CAsyncWorkRecycleObjectPoolMgr::RegisterPools() { insert.operator()("AccountLinkedUserData_Save") && insert.operator()("CharacterLinkedUserData_Load") && insert.operator()("CharacterLinkedUserData_Save") && - insert.operator()("Emblem_Upload") && - insert.operator()("Emblem_Download") && + insert.operator()("Emblem_Upload") && insert.operator()("Emblem_Download") && insert.operator()("MerchantStoreInformation_Load") && - insert.operator()("MerchantStoreInformation_Save") && - insert.operator()("PartyList_Load") && - insert.operator()("MyParty_Load") && - insert.operator()("Register_Party") && - insert.operator()("Stop_Recruiting") && - insert.operator()("Change_PartyMaster") && + insert.operator()("MerchantStoreInformation_Save") && insert.operator()("PartyList_Load") && + insert.operator()("MyParty_Load") && insert.operator()("Register_Party") && + insert.operator()("Stop_Recruiting") && insert.operator()("Change_PartyMaster") && insert.operator()("PartyInfo_Load"); } diff --git a/Source/Contents/AsyncWorkRecycleObjectPoolMgr.h b/Source/Contents/Async/AsyncWorkRecycleObjectPoolMgr.h similarity index 63% rename from Source/Contents/AsyncWorkRecycleObjectPoolMgr.h rename to Source/Contents/Async/AsyncWorkRecycleObjectPoolMgr.h index cc37a66..917783a 100644 --- a/Source/Contents/AsyncWorkRecycleObjectPoolMgr.h +++ b/Source/Contents/Async/AsyncWorkRecycleObjectPoolMgr.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ASYNCWORKRECYCLEOBJECTPOOLMGR_H -#define RAGNAROK_SOURCE_CONTENTS_ASYNCWORKRECYCLEOBJECTPOOLMGR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_ASYNC_ASYNCWORKRECYCLEOBJECTPOOLMGR_H +#define RAGNAROK_SOURCE_CONTENTS_ASYNC_ASYNCWORKRECYCLEOBJECTPOOLMGR_H -#include "Utility/NRecycleObjectPoolMgr.h" +#include "Utility/Async/NRecycleObjectPoolMgr.h" -// RTTI CAsyncWorkRecycleObjectPoolMgr, original x86 size 48. class CAsyncWorkRecycleObjectPoolMgr : public NRecycleObjectPoolMgr { public: CAsyncWorkRecycleObjectPoolMgr(); diff --git a/Source/Contents/AsyncWorkMgr.h b/Source/Contents/AsyncWorkMgr.h deleted file mode 100644 index 6dd435f..0000000 --- a/Source/Contents/AsyncWorkMgr.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ASYNCWORKMGR_H -#define RAGNAROK_SOURCE_CONTENTS_ASYNCWORKMGR_H - -#include "Contents/AdvenPartyInfo.h" -#include "Utility/NAsyncWorkMgr.h" - -class CAsyncWorkRecycleObjectPoolMgr; -class CConnection; -class CEmblemDataMgr; -class CMCStoreInfoBackup; -class WindowManagerWindows; -struct AccountConfigLoad; -struct CharacterConfigLoad; -struct EmblemUploadContext; -struct StoreBackupContext; -struct RegisterPartyContext; -struct StopRecruitingContext; -struct PartyInfoContext; - -// RTTI CAsyncWorkMgr, original x86 size 40. Work binding contexts expose -// original global dependencies without changing the queue/pool owner. -class CAsyncWorkMgr : public NAsyncWorkMgr { -public: - explicit CAsyncWorkMgr(std::uint32_t workers); - ~CAsyncWorkMgr() override; - static bool Initialize(std::uint32_t workers); - static void Shutdown(); - - void LoadAccount(std::uint32_t accountId, std::string world, std::string url, AccountConfigLoad& context); - void SaveAccount(std::uint32_t accountId, std::string world, std::string url, std::string token, std::string data); - void ChangePartyMaster( - std::uint32_t accountId, - std::uint32_t characterId, - std::string characterName, - std::uint32_t targetAccountId, - std::uint32_t targetCharacterId, - std::string targetName, - std::string world, - std::string url, - std::string token, - WindowManagerWindows& windows - ); - void LoadCharacter( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - CharacterConfigLoad& context - ); - void SaveCharacter( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - std::string data - ); - void DownloadEmblem( - std::string url, - std::uint32_t accountId, - std::string token, - std::string world, - std::uint32_t guildId, - std::uint32_t version, - CConnection& connection - ); - void UploadEmblem( - std::string url, - std::uint32_t accountId, - std::string token, - std::string world, - std::uint32_t guildId, - std::string path, - CEmblemDataMgr& owner, - EmblemUploadContext& context - ); - void LoadMyParty( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - WindowManagerWindows& windows - ); - void LoadPartyInfo( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - std::uint32_t queryAccountId, - PartyInfoContext& context - ); - void LoadPartyList( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - int search, - CAdvenPartyInfo filter, - int page, - WindowManagerWindows& windows - ); - void LoadStore( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - int type, - CMCStoreInfoBackup& owner, - StoreBackupContext& context - ); - void SaveStore( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - std::string data, - int type, - CMCStoreInfoBackup& owner, - StoreBackupContext& context - ); - void RegisterParty( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - CAdvenPartyInfo info, - RegisterPartyContext& context - ); - void StopRecruiting( - std::uint32_t accountId, - std::string world, - std::string url, - std::string token, - std::uint32_t masterAccountId, - StopRecruitingContext& context - ); - - // Source view of the original pool-owner field, for direct owner operations. - CAsyncWorkRecycleObjectPoolMgr& Pools() { - return *this->m_pools; - } - -private: - /* 0020 */ bool m_ready; - /* 0024 */ CAsyncWorkRecycleObjectPoolMgr* m_pools; -}; - -// STATIC: 0x0138968C -// GLOBAL: gl_24349 -extern CAsyncWorkMgr* g_asyncWorkMgr; - -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(CAsyncWorkMgr) == 40); -#endif - -#endif diff --git a/Source/Contents/AttackMotion.h b/Source/Contents/AttackMotion.h deleted file mode 100644 index d82def6..0000000 --- a/Source/Contents/AttackMotion.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ATTACKMOTION_H -#define RAGNAROK_SOURCE_CONTENTS_ATTACKMOTION_H - -// Length selected by the sprite actor's attack-state transition. job is the -// actor's resolved job, appearance is its original +0x260 field, and equipment -// is the original main equipment value. attackMode distinguishes exactly 0 -// and 1; all other integer values retain the default six-frame length. -float AttackMotionLength(int job, int appearance, int equipment, int attackMode); - -#endif diff --git a/Source/Contents/CameraFrame.cpp b/Source/Contents/Camera/CameraFrame.cpp similarity index 79% rename from Source/Contents/CameraFrame.cpp rename to Source/Contents/Camera/CameraFrame.cpp index 29148bd..9bf2780 100644 --- a/Source/Contents/CameraFrame.cpp +++ b/Source/Contents/Camera/CameraFrame.cpp @@ -1,5 +1,5 @@ -#include "Contents/CameraFrame.h" -#include "Contents/TerrainHeight.h" +#include "Contents/Camera/CameraFrame.h" +#include "Contents/Ground/TerrainHeight.h" #include "Render/Renderer.h" #include @@ -23,8 +23,7 @@ void CameraFrame::Build(const CameraState& camera, const TerrainHeight& terrain) const float distance = -camera.distance; this->eye[1] = ((orbit.values[4] * 0.0f + orbit.values[1] * 0.0f) + distance * orbit.values[7]) + orbit.values[10]; this->eye[2] = ((orbit.values[5] * 0.0f + orbit.values[2] * 0.0f) + distance * orbit.values[8]) + orbit.values[11]; - this->eye[0] = (((orbit.values[3] * 0.0f + orbit.values[0] * 0.0f) + distance * orbit.values[6]) + orbit.values[9]) + - camera.target[0]; + this->eye[0] = (((orbit.values[3] * 0.0f + orbit.values[0] * 0.0f) + distance * orbit.values[6]) + orbit.values[9]) + camera.target[0]; this->eye[1] = camera.target[1] + this->eye[1]; this->eye[2] = camera.target[2] + this->eye[2]; const float height = terrain.Height(this->eye[0], this->eye[2]); @@ -47,17 +46,8 @@ void CameraFrame::Refresh(const CameraState& camera, const TerrainHeight& terrai // OFFSET: 0x00ADBF60 // FUNCTION: fn_17927 void UpdateCameraFrame( - CameraState& camera, - CameraShake& shake, - int& frameLatch, - const float* desiredTarget, - const ServiceOptions& options, - const float& rendererScale, - const float& projectionScale, - const float& baseDistance, - CameraProjectionOutputs& outputs, - const TerrainHeight& terrain, - CameraFrame& frame, + CameraState& camera, CameraShake& shake, int& frameLatch, const float* desiredTarget, const ServiceOptions& options, const float& rendererScale, + const float& projectionScale, const float& baseDistance, CameraProjectionOutputs& outputs, const TerrainHeight& terrain, CameraFrame& frame, CRenderer& renderer ) { camera.desiredTarget[0] = desiredTarget[0]; diff --git a/Source/Contents/CameraFrame.h b/Source/Contents/Camera/CameraFrame.h similarity index 50% rename from Source/Contents/CameraFrame.h rename to Source/Contents/Camera/CameraFrame.h index 537d234..b467cf5 100644 --- a/Source/Contents/CameraFrame.h +++ b/Source/Contents/Camera/CameraFrame.h @@ -1,14 +1,12 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CAMERAFRAME_H -#define RAGNAROK_SOURCE_CONTENTS_CAMERAFRAME_H +#ifndef RAGNAROK_SOURCE_CONTENTS_CAMERA_CAMERAFRAME_H +#define RAGNAROK_SOURCE_CONTENTS_CAMERA_CAMERAFRAME_H -#include "Contents/CameraState.h" -#include "Utility/AffineMatrix.h" +#include "Contents/Camera/CameraState.h" +#include "Utility/Math/AffineMatrix.h" struct TerrainHeight; class CRenderer; -// CView camera outputs +0x80..+0xF7. up is established by reset, not rewritten -// on each frame. These matrices feed projection, picking and frustum collection. struct CameraFrame { float eye[3]; float up[3]; @@ -24,17 +22,8 @@ struct CameraFrame { void ResetCamera(CameraState& camera, CameraFrame& frame); void UpdateCameraFrame( - CameraState& camera, - CameraShake& shake, - int& frameLatch, - const float* desiredTarget, - const ServiceOptions& options, - const float& rendererScale, - const float& projectionScale, - const float& baseDistance, - CameraProjectionOutputs& outputs, - const TerrainHeight& terrain, - CameraFrame& frame, + CameraState& camera, CameraShake& shake, int& frameLatch, const float* desiredTarget, const ServiceOptions& options, const float& rendererScale, + const float& projectionScale, const float& baseDistance, CameraProjectionOutputs& outputs, const TerrainHeight& terrain, CameraFrame& frame, CRenderer& renderer ); diff --git a/Source/Contents/CameraQueries.cpp b/Source/Contents/Camera/CameraQueries.cpp similarity index 74% rename from Source/Contents/CameraQueries.cpp rename to Source/Contents/Camera/CameraQueries.cpp index a964f76..b7cc198 100644 --- a/Source/Contents/CameraQueries.cpp +++ b/Source/Contents/Camera/CameraQueries.cpp @@ -1,5 +1,5 @@ -#include "Contents/CameraFrame.h" -#include "Contents/TerrainHeight.h" +#include "Contents/Camera/CameraFrame.h" +#include "Contents/Ground/TerrainHeight.h" #include #include @@ -17,6 +17,7 @@ void CameraFrame::Forward(const CameraState& camera, float* output) const { const float y = camera.target[1] - this->eye[1]; const float x = camera.target[0] - this->eye[0]; const float z = camera.target[2] - this->eye[2]; + output[1] = y; output[0] = x; output[2] = z; @@ -29,24 +30,16 @@ void CameraFrame::Forward(const CameraState& camera, float* output) const { // OFFSET: 0x00ADBB60 // FUNCTION: fn_17925 -void CameraFrame::AlternateView( - const CameraState& camera, - float yaw, - const TerrainHeight& terrain, - AffineMatrix& output -) const { +void CameraFrame::AlternateView(const CameraState& camera, float yaw, const TerrainHeight& terrain, AffineMatrix& output) const { constexpr float pi = 3.141592f; AffineMatrix orbit; orbit.SetXRotation((camera.pitch / 180.0f) * pi); orbit.RotateY((yaw / 180.0f) * pi); const float distance = -camera.distance; float eye[3]; - eye[0] = (((orbit.values[3] * 0.0f + orbit.values[0] * 0.0f) + distance * orbit.values[6]) + orbit.values[9]) + - camera.target[0]; - eye[1] = (((orbit.values[4] * 0.0f + orbit.values[1] * 0.0f) + distance * orbit.values[7]) + orbit.values[10]) + - camera.target[1]; - eye[2] = (((orbit.values[5] * 0.0f + orbit.values[2] * 0.0f) + distance * orbit.values[8]) + orbit.values[11]) + - camera.target[2]; + eye[0] = (((orbit.values[3] * 0.0f + orbit.values[0] * 0.0f) + distance * orbit.values[6]) + orbit.values[9]) + camera.target[0]; + eye[1] = (((orbit.values[4] * 0.0f + orbit.values[1] * 0.0f) + distance * orbit.values[7]) + orbit.values[10]) + camera.target[1]; + eye[2] = (((orbit.values[5] * 0.0f + orbit.values[2] * 0.0f) + distance * orbit.values[8]) + orbit.values[11]) + camera.target[2]; const float height = terrain.Height(eye[0], eye[2]); if (eye[1] > height) { diff --git a/Source/Contents/CameraShake.cpp b/Source/Contents/Camera/CameraShake.cpp similarity index 82% rename from Source/Contents/CameraShake.cpp rename to Source/Contents/Camera/CameraShake.cpp index d309caf..0b98b09 100644 --- a/Source/Contents/CameraShake.cpp +++ b/Source/Contents/Camera/CameraShake.cpp @@ -1,13 +1,10 @@ -#include "Contents/CameraState.h" -#include "Utility/AffineMatrix.h" +#include "Contents/Camera/CameraState.h" +#include "Utility/Math/AffineMatrix.h" +#include "Utility/Math/ScalarConversion.h" -#include #include -#include #include -// clang-format off -#include -// clang-format on +#include namespace { float Jitter(float divisor) { @@ -51,6 +48,7 @@ void CameraShake::Apply(CameraState& camera, int& frameLatch) { camera.distance = camera.desiredDistance; this->enabled = 0; camera.pitch = camera.desiredPitch; + return; } @@ -59,16 +57,16 @@ void CameraShake::Apply(CameraState& camera, int& frameLatch) { } frameLatch = 0; - // Function-static amplitudes are shared by every CView and initialized - // independently at their first reached phase, not when a shake is started. + static float horizontal = this->horizontal; const float horizontalX = Jitter(10.0f) + horizontal; - const int yawX = _mm_cvttss_si32(_mm_set_ss(camera.yaw)); + const int yawX = TruncateToInt(camera.yaw); const float x = static_cast(static_cast(ClientCosine(yawX)) * horizontalX); camera.target[0] = x + camera.target[0]; const float horizontalZ = Jitter(10.0f) + horizontal; - const int yawZ = _mm_cvttss_si32(_mm_set_ss(camera.yaw)); + const int yawZ = TruncateToInt(camera.yaw); const float sine = -ClientSine(yawZ); + horizontal = -horizontal; camera.target[2] = horizontalZ * sine + camera.target[2]; static float distance = this->distance; diff --git a/Source/Contents/CameraSmoothing.cpp b/Source/Contents/Camera/CameraSmoothing.cpp similarity index 87% rename from Source/Contents/CameraSmoothing.cpp rename to Source/Contents/Camera/CameraSmoothing.cpp index 1826b4e..973f24f 100644 --- a/Source/Contents/CameraSmoothing.cpp +++ b/Source/Contents/Camera/CameraSmoothing.cpp @@ -1,9 +1,7 @@ -#include "Contents/CameraState.h" -#include "Contents/ServiceOptions.h" -#include "Utility/AffineMatrix.h" - -#include -#include +#include "Contents/Camera/CameraState.h" +#include "Contents/Configuration/ServiceOptions.h" +#include "Utility/Math/AffineMatrix.h" +#include "Utility/Math/ScalarConversion.h" // OFFSET: 0x00ADC150 // FUNCTION: fn_17928 @@ -38,11 +36,7 @@ void CameraState::AddYaw(float delta) { // OFFSET: 0x00ADBCD0 // FUNCTION: fn_17926 void CameraState::Smooth( - const ServiceOptions& options, - const float& rendererScale, - const float& projectionScale, - const float& baseDistance, - CameraProjectionOutputs& output + const ServiceOptions& options, const float& rendererScale, const float& projectionScale, const float& baseDistance, CameraProjectionOutputs& output ) { while (this->desiredYaw >= 360.0f) { this->desiredYaw = this->desiredYaw - 360.0f; @@ -86,7 +80,7 @@ void CameraState::Smooth( this->target[2] = next[2]; this->target[1] = next[1]; this->target[0] = next[0]; - const int angle = _mm_cvttss_si32(_mm_set_ss(-this->pitch)); + const int angle = TruncateToInt(-this->pitch); const float sine = ClientSine(angle); const float cosine = ClientCosine(angle); const float tangent = static_cast(static_cast(sine) / cosine); diff --git a/Source/Contents/CameraState.h b/Source/Contents/Camera/CameraState.h similarity index 67% rename from Source/Contents/CameraState.h rename to Source/Contents/Camera/CameraState.h index f1003c0..c02839c 100644 --- a/Source/Contents/CameraState.h +++ b/Source/Contents/Camera/CameraState.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CAMERASTATE_H -#define RAGNAROK_SOURCE_CONTENTS_CAMERASTATE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_CAMERA_CAMERASTATE_H +#define RAGNAROK_SOURCE_CONTENTS_CAMERA_CAMERASTATE_H struct ServiceOptions; -// Established CView +0x20..+0x4F state. Reset changes only original fields. struct CameraState { float target[3]; float pitch; @@ -19,11 +18,7 @@ struct CameraState { void AddPitch(float delta); void AddYaw(float delta); void Smooth( - const ServiceOptions& options, - const float& rendererScale, - const float& projectionScale, - const float& baseDistance, - struct CameraProjectionOutputs& output + const ServiceOptions& options, const float& rendererScale, const float& projectionScale, const float& baseDistance, struct CameraProjectionOutputs& output ); }; @@ -34,7 +29,6 @@ struct CameraProjectionOutputs { float& scaleX; }; -// CView +0x04..+0x1F. Time comparison uses unsigned start+duration directly. struct CameraShake { float horizontal; float distance; diff --git a/Source/Contents/CashEmotionMgr.cpp b/Source/Contents/CashEmotionMgr.cpp index e14df19..a577d46 100644 --- a/Source/Contents/CashEmotionMgr.cpp +++ b/Source/Contents/CashEmotionMgr.cpp @@ -1,5 +1,5 @@ #include "Contents/CashEmotionMgr.h" -#include "UI/ChatSuggestions.h" +#include "UI/Chat/ChatSuggestions.h" #include #include @@ -22,8 +22,8 @@ public: // OFFSET: 0x00596430 // FUNCTION: fn_02915 CCashEmotionMgr::CCashEmotionMgr() - : m_enabled(true), unknown_0005{}, m_action(nullptr), unknown_000C(0), unknown_0010{}, m_emotionsByPack{}, - unknown_0050{}, m_packNames{}, unknown_00B0{}, m_commands{}, unknown_0198{} { + : m_enabled(true), unknown_0005{}, m_action(nullptr), unknown_000C(0), unknown_0010{}, m_emotionsByPack{}, unknown_0050{}, m_packNames{}, unknown_00B0{}, + m_commands{}, unknown_0198{} { } // OFFSET: 0x00598520 @@ -33,6 +33,7 @@ CCashEmotionMgr::~CCashEmotionMgr() { this->m_action = nullptr; } } + // OFFSET: 0x00598C70 // FUNCTION: fn_02934 void CCashEmotionMgr::Reset() { @@ -95,6 +96,7 @@ int CCashEmotionMgr::ProcessChatCommand(const char* command) { const char* key = command + 1; auto it = this->m_commands.find(key); int actionId = 0; + if (it != this->m_commands.end()) { actionId = it->second; } @@ -116,6 +118,7 @@ const char* CCashEmotionMgr::GetPackName(int packId) { if (it == this->m_packNames.end()) { return nullptr; } + return it->second.c_str(); } diff --git a/Source/Contents/CashEmotionMgr.h b/Source/Contents/CashEmotionMgr.h index 33b23cf..f0184b9 100644 --- a/Source/Contents/CashEmotionMgr.h +++ b/Source/Contents/CashEmotionMgr.h @@ -4,6 +4,7 @@ #include #include #include + struct CashEmotionData { int id; int subId; diff --git a/Source/Contents/ClientSkills.h b/Source/Contents/ClientSkills.h deleted file mode 100644 index fa98170..0000000 --- a/Source/Contents/ClientSkills.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CLIENTSKILLS_H -#define RAGNAROK_SOURCE_CONTENTS_CLIENTSKILLS_H - -#include "Contents/PlayerSkillBundle.h" - -class UIWindow; - -// Live original skill-window globals plus the authoritative window lookup. -struct SkillWindows { - UIWindow*& first; - UIWindow*& second; - WindowManagerWindows& windows; - - void Notify(); -}; - -// Borrowed client use-level vectors (+0x70, +0x710, +0x71C). The additional -// range deliberately has no upper bound in the original lookup. -struct SkillUseLevels { - const std::vector& use; - const std::vector& additional; - const std::vector& homunculus; - - int Lookup(int id) const; -}; - -// Same recovered algorithm for client+0x84 and client+0x8C. Each view borrows -// that list's specific window global and the shared second skill window. -struct CompanionSkills { - std::list& skills; - UIWindow*& window; - UIWindow*& sharedWindow; - - // Updates only the first ID match; returns true only when appending. Existing - // names, availability, prerequisites and unknown_0030 remain untouched. - bool Update(const CSkillInfo& value, unsigned char notify); - void Notify(); -}; - -// Active-effect vector, 28-byte records. -struct ActiveSkillEffect { - std::uint32_t id; - std::uint32_t unknown_0004; - std::uint32_t unknown_0008; - std::uint32_t unknown_000C; - std::uint32_t unknown_0010; - std::uint32_t unknown_0014; - std::uint32_t unknown_0018; -}; - -// Non-owning view of original client fields; not a second client singleton. -struct ClientSkills { - CPlayerSkillBundle& bundle; - const std::list& firstRange; // client+0x84 - const std::list& otherRanges; // client+0x8C - std::list& additional; // client+0x04 - const int& classMode; // client+0x8134 - const std::vector& effects; - - bool HasEffect(std::uint32_t id) const; - CSkillInfo LookupFirst(std::uint32_t id) const; - CSkillInfo LookupOther(std::uint32_t id) const; - CSkillInfo LookupAdditional(std::uint32_t id) const; - CSkillInfo Lookup(std::uint32_t id) const; - // First-match partial update; retains availability/name/unknown_000C and - // prerequisites. Append copies the full value. The original ignores unused. - bool UpdateAdditional(const CSkillInfo& value, int unused); - // Grouped skills restore the recorded previous level and always notify. - // Nongrouped skills remove the first base/extra matches; notify only when - // an extra record was removed. Pending skills and change records survive. - void Remove(std::uint32_t id, SkillWindows& windows); - - // Returns true only for a newly appended base skill. Updates grouped/extra - // state from a snapshot before the Lua query, then rereads the live input - // for base state. Existing base records notify/copy unknown_000C only for - // flag == 1; new records notify for any nonzero flag. - bool Update( - const CSkillInfo& value, - unsigned char notify, - unsigned char updateUnknown000C, - LuaScript& script, - const SkillUseLevels& levels, - SkillWindows& windows - ); -}; - -static_assert(sizeof(ActiveSkillEffect) == 28); - -#endif diff --git a/Source/Contents/GraphicsConfiguration.cpp b/Source/Contents/Configuration/GraphicsConfiguration.cpp similarity index 90% rename from Source/Contents/GraphicsConfiguration.cpp rename to Source/Contents/Configuration/GraphicsConfiguration.cpp index 945574a..ad665f4 100644 --- a/Source/Contents/GraphicsConfiguration.cpp +++ b/Source/Contents/Configuration/GraphicsConfiguration.cpp @@ -1,13 +1,12 @@ -#include "Contents/GraphicsConfiguration.h" -#include "Contents/OptionWriter.h" -#include "Contents/ScriptOptions.h" +#include "Contents/Configuration/GraphicsConfiguration.h" +#include "Contents/Configuration/OptionWriter.h" +#include "Contents/Configuration/ScriptOptions.h" #include "Render/RenderAdapter.h" #include "Script/LuaScript.h" #include #include -// INTERNAL void GraphicsConfiguration::Load(LuaScript& script, ScriptOptions& options, int& screenWidth, int& screenHeight) { const int resetPolicy = std::max(script.GlobalInteger("RenderSystemReset"), 0); const int backendPolicy = std::max(script.GlobalInteger("RenderSystemDefault"), 0); @@ -46,12 +45,10 @@ void GraphicsConfiguration::Load(LuaScript& script, ScriptOptions& options, int& } } -// INTERNAL AdapterConfiguration GraphicsConfiguration::Adapter() const { return {this->backend, this->drawGuid, this->renderGuid, this->deviceGuid, this->deviceName}; } -// INTERNAL void GraphicsConfiguration::Save(OptionWriter& output) const { output.Integer("RenderSystemReset", this->reset); output.Integer("RENDERSYSTEM", this->backend); @@ -60,7 +57,7 @@ void GraphicsConfiguration::Save(OptionWriter& output) const { output.Integer("ISFULLSCREENMODE", this->fullscreen); output.Integer("WIDTH", this->width); output.Integer("HEIGHT", this->height); - // Original saves current dimensions under OLD_* rather than retained old values. + output.Integer("OLD_WIDTH", this->width); output.Integer("OLD_HEIGHT", this->height); output.Integer("BITPERPIXEL", this->bitsPerPixel); diff --git a/Source/Contents/GraphicsConfiguration.h b/Source/Contents/Configuration/GraphicsConfiguration.h similarity index 54% rename from Source/Contents/GraphicsConfiguration.h rename to Source/Contents/Configuration/GraphicsConfiguration.h index 3177cab..51f17be 100644 --- a/Source/Contents/GraphicsConfiguration.h +++ b/Source/Contents/Configuration/GraphicsConfiguration.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_GRAPHICSCONFIGURATION_H -#define RAGNAROK_SOURCE_CONTENTS_GRAPHICSCONFIGURATION_H +#ifndef RAGNAROK_SOURCE_CONTENTS_CONFIGURATION_GRAPHICSCONFIGURATION_H +#define RAGNAROK_SOURCE_CONTENTS_CONFIGURATION_GRAPHICSCONFIGURATION_H #include @@ -8,8 +8,6 @@ struct ScriptOptions; struct AdapterConfiguration; struct OptionWriter; -// Recovered shared graphics configuration globals, grouped by their owner. -// Legacy GUID selection is populated by separate setup paths and retained by Load. struct GraphicsConfiguration { GUID drawGuid; GUID renderGuid; @@ -24,11 +22,9 @@ struct GraphicsConfiguration { GUID deviceGuid; char deviceName[32]; - // Source helper for graphics publication within the larger startup loader. - // Not a separate original entry point. void Load(LuaScript& script, ScriptOptions& options, int& screenWidth, int& screenHeight); AdapterConfiguration Adapter() const; - // Graphics portion of the larger option save routine. + void Save(OptionWriter& output) const; }; diff --git a/Source/Contents/OptionWriter.cpp b/Source/Contents/Configuration/OptionWriter.cpp similarity index 74% rename from Source/Contents/OptionWriter.cpp rename to Source/Contents/Configuration/OptionWriter.cpp index 835cc45..2b8b939 100644 --- a/Source/Contents/OptionWriter.cpp +++ b/Source/Contents/Configuration/OptionWriter.cpp @@ -1,4 +1,4 @@ -#include "Contents/OptionWriter.h" +#include "Contents/Configuration/OptionWriter.h" #include "File/File.h" #include @@ -25,8 +25,7 @@ void OptionWriter::String(const char* key, const char* value) { } char line[200]; - const int count = - _snprintf_s(line, sizeof(line), _TRUNCATE, "OptionInfoList[\"%s\"] = \"%s\"\r\n", key, escaped.c_str()); + const int count = _snprintf_s(line, sizeof(line), _TRUNCATE, "OptionInfoList[\"%s\"] = \"%s\"\r\n", key, escaped.c_str()); if (count > 0) { this->file.Write(line, count); @@ -38,9 +37,8 @@ void OptionWriter::String(const char* key, const char* value) { void OptionWriter::Guid(const char* key, const GUID& value) { char text[40]; _snprintf_s( - text, sizeof(text), _TRUNCATE, "{%08X-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", value.Data1, - value.Data2, value.Data3, value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], - value.Data4[5], value.Data4[6], value.Data4[7] + text, sizeof(text), _TRUNCATE, "{%08X-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", value.Data1, value.Data2, value.Data3, + value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7] ); char line[200]; const int count = _snprintf_s(line, sizeof(line), _TRUNCATE, "OptionInfoList[\"%s\"] = \"%s\"\r\n", key, text); diff --git a/Source/Contents/Configuration/OptionWriter.h b/Source/Contents/Configuration/OptionWriter.h new file mode 100644 index 0000000..0ae782c --- /dev/null +++ b/Source/Contents/Configuration/OptionWriter.h @@ -0,0 +1,16 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_CONFIGURATION_OPTIONWRITER_H +#define RAGNAROK_SOURCE_CONTENTS_CONFIGURATION_OPTIONWRITER_H + +#include + +class CFile; + +struct OptionWriter { + CFile& file; + + void Integer(const char* key, int value); + void String(const char* key, const char* value); + void Guid(const char* key, const GUID& value); +}; + +#endif diff --git a/Source/Contents/ScriptOptions.cpp b/Source/Contents/Configuration/ScriptOptions.cpp similarity index 95% rename from Source/Contents/ScriptOptions.cpp rename to Source/Contents/Configuration/ScriptOptions.cpp index 8d59b42..daa3170 100644 --- a/Source/Contents/ScriptOptions.cpp +++ b/Source/Contents/Configuration/ScriptOptions.cpp @@ -1,4 +1,4 @@ -#include "Contents/ScriptOptions.h" +#include "Contents/Configuration/ScriptOptions.h" #include "Script/LuaScript.h" #include "Utility/GuidParse.h" diff --git a/Source/Contents/ScriptOptions.h b/Source/Contents/Configuration/ScriptOptions.h similarity index 51% rename from Source/Contents/ScriptOptions.h rename to Source/Contents/Configuration/ScriptOptions.h index 2502e22..c2472df 100644 --- a/Source/Contents/ScriptOptions.h +++ b/Source/Contents/Configuration/ScriptOptions.h @@ -1,13 +1,11 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_SCRIPTOPTIONS_H -#define RAGNAROK_SOURCE_CONTENTS_SCRIPTOPTIONS_H +#ifndef RAGNAROK_SOURCE_CONTENTS_CONFIGURATION_SCRIPTOPTIONS_H +#define RAGNAROK_SOURCE_CONTENTS_CONFIGURATION_SCRIPTOPTIONS_H #include #include class LuaScript; -// Reads through the original settings callback l_GetOptionValue. The script -// state is borrowed from the application owner, not replaced by a second map. struct ScriptOptions { LuaScript& script; diff --git a/Source/Contents/ServiceOptions.cpp b/Source/Contents/Configuration/ServiceOptions.cpp similarity index 93% rename from Source/Contents/ServiceOptions.cpp rename to Source/Contents/Configuration/ServiceOptions.cpp index d506470..acef270 100644 --- a/Source/Contents/ServiceOptions.cpp +++ b/Source/Contents/Configuration/ServiceOptions.cpp @@ -1,4 +1,4 @@ -#include "Contents/ServiceOptions.h" +#include "Contents/Configuration/ServiceOptions.h" // OFFSET: 0x006C17A0 // FUNCTION: fn_06318 diff --git a/Source/Contents/ServiceOptions.h b/Source/Contents/Configuration/ServiceOptions.h similarity index 51% rename from Source/Contents/ServiceOptions.h rename to Source/Contents/Configuration/ServiceOptions.h index dd7f5f8..fa2a9e9 100644 --- a/Source/Contents/ServiceOptions.h +++ b/Source/Contents/Configuration/ServiceOptions.h @@ -1,13 +1,14 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_SERVICEOPTIONS_H -#define RAGNAROK_SOURCE_CONTENTS_SERVICEOPTIONS_H +#ifndef RAGNAROK_SOURCE_CONTENTS_CONFIGURATION_SERVICEOPTIONS_H +#define RAGNAROK_SOURCE_CONTENTS_CONFIGURATION_SERVICEOPTIONS_H -#include "Contents/PlayerSkillBundle.h" +#include "Contents/Skills/PlayerSkillBundle.h" #include +enum ServiceOption : int { ConfineCursor = 271 }; bool IsServiceOption(int id); -// Service-option hash table. Values retain byte width. + struct ServiceOptions { std::unordered_map& values; diff --git a/Source/Contents/EffectParticle.h b/Source/Contents/EffectParticle.h deleted file mode 100644 index c00fe4b..0000000 --- a/Source/Contents/EffectParticle.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTPARTICLE_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECTPARTICLE_H - -#include "Contents/EffectPrimitiveState.h" -#include "Contents/RenderObject.h" - -#include - -struct JobNames; -class ResourceMgr; -struct RagEffectState; - -// Recovered CEffectPrim lifetime and state over the common render base. -struct EffectParticle : CRenderObject { - EffectParticle(ResourceMgr& resources, JobNames& names); - - EffectPrimitiveState state; -}; - -// The active mode owns the returned object; the parent list borrows its state. -EffectParticle* CreateEffectParticle( - RagEffectState& parent, - const RenderObjectState& parentRender, - int type, - float x, - float y, - float z, - ResourceMgr& resources, - JobNames& names, - std::list& worldObjects -); - -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(EffectParticle) == 0xFA18); -#endif - -#endif diff --git a/Source/Contents/EffectPrimitiveColor.cpp b/Source/Contents/EffectPrimitiveColor.cpp deleted file mode 100644 index fce7cfb..0000000 --- a/Source/Contents/EffectPrimitiveColor.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "Contents/EffectPrimitiveState.h" -#include "Contents/RagEffectState.h" - -#include -#include - -namespace { - int Difference(std::uint32_t left, std::uint32_t right) { - return std::bit_cast(left - right); - } -} - -// OFFSET: 0x00BC5E00 -// FUNCTION: fn_19849 -void EffectPrimitiveState::UpdateColor() { - const auto current = std::bit_cast(this->unknown_01E0); - const bool valuesAndLimit = this->unknown_0158 != 0; - - if (valuesAndLimit || this->unknown_014C.y != 0) { - auto index = this->unknown_01D8; - const auto count = static_cast(this->unknown_0258[0].size()); - const bool outside = valuesAndLimit ? index > count - 1u : index >= count; - - if (std::bit_cast(index) < 0 || outside) { - index = 0; - this->unknown_01D8 = 0; - } - - const float key = std::bit_cast(this->unknown_0258[0][index]); - - if (static_cast(current) == key) { - const float value = std::bit_cast(this->unknown_0258[1][index]); - - if (valuesAndLimit) { - this->unknown_0324 = value; - this->unknown_02D4 = std::bit_cast(this->unknown_0258[2][index]); - } else { - this->unknown_0328 = value; - } - - this->unknown_01D8 = index + 1; - } - } - - const float lower = std::bit_cast(this->unknown_02D8); - - if ((this->flags & 0x80u) != 0) { - const bool below = - this->unknown_0328 >= 0.0f ? this->unknown_0324 < this->unknown_02D4 : lower < this->unknown_0324; - - if (!below) { - this->unknown_0328 *= -1.0f; - } - } - - if (this->unknown_015C == 0) { - const auto parentRemaining = static_cast(this->parent->lifetime) - this->parent->unknown_0178; - const int remaining = Difference(static_cast(this->lifetime), this->unknown_01E0); - - if (remaining > std::bit_cast(parentRemaining + 1u)) { - this->unknown_015C = 1; - this->flags &= ~0x80u; - this->unknown_0328 = -(this->unknown_0324 / static_cast(std::bit_cast(parentRemaining))); - } - } - - if (current == this->unknown_01F0) { - this->flags &= ~0x80u; - const int remaining = Difference(static_cast(this->lifetime), this->unknown_01E0); - this->unknown_0328 = -(this->unknown_0324 / static_cast(remaining)) * this->unknown_032C; - } - - // MAXSS/MINSS return their second operand for unordered/equal inputs. - const __m128 sum = _mm_set_ss(this->unknown_0328 + this->unknown_0324); - const __m128 bounded = _mm_min_ss(_mm_set_ss(this->unknown_02D4), _mm_max_ss(_mm_set_ss(lower), sum)); - this->unknown_0324 = _mm_cvtss_f32(bounded); - const auto alpha = static_cast(_mm_cvttss_si32(bounded)); - const auto color = - ((alpha * 256u + static_cast(this->red)) * 256u + static_cast(this->green)) * 256u + - static_cast(this->blue); - this->unknown_01C0 = std::bit_cast(color); -} diff --git a/Source/Contents/EffectPrimitiveMotion.h b/Source/Contents/EffectPrimitiveMotion.h deleted file mode 100644 index bbdd7da..0000000 --- a/Source/Contents/EffectPrimitiveMotion.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTPRIMITIVEMOTION_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECTPRIMITIVEMOTION_H - -#include "Contents/TerrainHeight.h" - -struct EffectPrimitiveState; -struct RenderObjectState; - -struct EffectMotionContext { - const RenderObjectState& parentRender; - const float& cameraPitch; - const float& cameraYaw; - const TerrainHeight& ground; -}; - -bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context); - -// Type-15 branch of CEffectPrim::Update, not the full type dispatcher. -bool UpdateEffectPrimitive15( - EffectPrimitiveState& particle, - RenderObjectState& render, - EffectMotionContext& context, - int updateTick -); - -#endif diff --git a/Source/Contents/EffectPrimitiveRendering.h b/Source/Contents/EffectPrimitiveRendering.h deleted file mode 100644 index ed774f9..0000000 --- a/Source/Contents/EffectPrimitiveRendering.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTPRIMITIVERENDERING_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECTPRIMITIVERENDERING_H - -struct EffectPrimitiveState; -struct RenderObjectState; -struct RenderProjection; -struct RenderQueues; -class RenderCommandPool; -struct EffectVisibilityContext; - -// Borrowed original renderer/camera owners. This operation does not replace -// the particle dispatcher's visibility gates or the renderer's queue drain. -struct EffectPrimitiveRenderContext { - const RenderProjection& projection; - const float* cameraMatrix; - RenderQueues& queues; - RenderCommandPool& commands; - const bool& depthAlpha; - const float& depthStart; - const float& depthEnd; -}; - -void DrawEffectPrimitive15( - EffectPrimitiveState& particle, - const RenderObjectState& render, - EffectPrimitiveRenderContext& context -); - -// Type-15 path through the particle dispatcher's parent visibility gate. -void RenderEffectPrimitive15( - EffectPrimitiveState& particle, - const RenderObjectState& render, - EffectPrimitiveRenderContext& context, - const EffectVisibilityContext& visibility -); - -#endif diff --git a/Source/Contents/EffectTypes.cpp b/Source/Contents/EffectTypes.cpp deleted file mode 100644 index 065e60b..0000000 --- a/Source/Contents/EffectTypes.cpp +++ /dev/null @@ -1,428 +0,0 @@ -#include "Contents/EffectTypes.h" - -#include - -namespace { - // Startup initializer; all 2459 entries, including gaps. - // STATIC: 0x016FDAC0 - // GLOBAL: gl_24388 - const std::unordered_map lifetimes = { - {0, 50}, {1, 50}, {2, 50}, {3, 50}, {4, 50}, {5, 50}, - {6, 100}, {7, 50}, {8, 80}, {9, 80}, {10, 100}, {11, 80}, - {12, 40}, {13, 9999}, {14, 50}, {15, 100}, {16, 40}, {17, 30}, - {18, 50}, {19, 50}, {20, 100}, {21, 100}, {22, 270}, {23, 999}, - {24, 100}, {25, 40}, {26, 160}, {27, 150}, {28, 100}, {29, 200}, - {30, 104}, {31, 160}, {32, 100}, {33, 200}, {34, 100}, {35, 100}, - {36, 100}, {37, 100}, {38, 100}, {39, 100}, {40, 999}, {41, 999}, - {42, 150}, {43, 100}, {44, 50}, {45, 100}, {46, 180}, {47, 250}, - {48, 130}, {49, 50}, {50, 50}, {51, 50}, {52, 40}, {53, 50}, - {54, 40}, {55, 40}, {56, 40}, {57, 40}, {58, 40}, {59, 40}, - {60, 200}, {61, 250}, {62, 250}, {63, 250}, {64, 999}, {65, 999}, - {66, 999}, {67, 999}, {68, 999}, {69, 9999}, {70, 999}, {71, 250}, - {72, 500}, {73, 250}, {74, 250}, {75, 999}, {76, 999}, {77, 999}, - {78, 999}, {79, 250}, {80, 250}, {81, 250}, {82, 250}, {83, 999}, - {84, 999}, {85, 999}, {86, 999}, {87, 999}, {88, 999}, {89, 9999}, - {90, 9999}, {91, 9999}, {92, 9999}, {93, 250}, {94, 250}, {95, 150}, - {96, 9999}, {97, 9999}, {98, 250}, {99, 250}, {100, 70}, {101, 9999}, - {102, 9999}, {103, 999}, {104, 999}, {105, 250}, {106, 9999}, {107, 9999}, - {108, 9999}, {111, 9999}, {109, 9999}, {110, 9999}, {112, 999}, {113, 9999}, - {114, 350}, {115, 250}, {116, 250}, {117, 100}, {118, 250}, {119, 250}, - {120, 250}, {121, 40}, {122, 250}, {123, 250}, {124, 9999}, {125, 250}, - {126, 9999}, {127, 9999}, {128, 250}, {129, 9999}, {130, 9999}, {131, 9999}, - {132, 250}, {133, 9999}, {134, 9999}, {135, 9999}, {136, 80}, {137, 350}, - {138, 8000}, {139, 9999}, {140, 250}, {141, 9999}, {142, 250}, {143, 999}, - {144, 999}, {145, 32797}, {146, 999}, {147, 999}, {148, 999}, {149, 999}, - {150, 999}, {151, 999}, {152, 100}, {153, 999}, {154, 999}, {155, 999}, - {156, 999}, {157, 999}, {158, 999}, {159, 9999}, {160, 9999}, {161, 0}, - {162, 99999999}, {163, 99999999}, {164, 999999999}, {165, 1000}, {166, 9999}, {167, 999}, - {168, 999}, {169, 9999}, {170, 999}, {171, 9999}, {172, 100}, {173, 100}, - {174, 100}, {175, 100}, {176, 100}, {177, 100}, {178, 100}, {179, 100}, - {180, 50}, {181, 9999}, {182, 9999}, {183, 9999}, {184, 0}, {185, 9999}, - {186, 9999}, {187, 9999}, {188, 9999}, {189, 9999}, {190, 9999}, {191, 9999}, - {192, 9999}, {193, 9999}, {194, 9999}, {195, 9999}, {196, 150}, {197, 9999}, - {198, 0}, {199, 9999}, {200, 99999999}, {201, 99999999}, {202, 99999999}, {203, 99999}, - {204, 100}, {205, 100}, {206, 100}, {207, 100}, {208, 100}, {209, 100}, - {210, 100}, {211, 100}, {212, 500}, {213, 9999}, {214, 9999}, {215, 500}, - {216, 200}, {217, 200}, {218, 199}, {219, 199}, {220, 199}, {221, 150}, - {222, 200}, {223, 300}, {224, 300}, {225, 300}, {226, 999}, {227, 999}, - {228, 999999}, {229, 99999999}, {230, 99999999}, {231, 999}, {232, 99999}, {233, 99999999}, - {234, 999}, {235, 999}, {236, 999}, {237, 999}, {238, 999}, {239, 29999}, - {240, 29999}, {241, 29999}, {242, 29999}, {243, 9999}, {244, 499}, {245, 499}, - {246, 499}, {247, 999}, {248, 200}, {249, 499}, {250, 9999}, {251, 150}, - {252, 200}, {253, 100}, {254, 99999999}, {255, 999}, {256, 999}, {257, 999}, - {258, 999}, {259, 999}, {260, 999}, {261, 300}, {262, 300}, {263, 300}, - {264, 300}, {265, 300}, {266, 300}, {267, 16}, {268, 300}, {269, 300}, - {270, 300}, {271, 300}, {272, 300}, {273, 300}, {274, 300}, {275, 300}, - {276, 300}, {277, 29999}, {278, 29999}, {279, 29999}, {280, 29999}, {281, 29999}, - {282, 29999}, {283, 29999}, {284, 29999}, {285, 29999}, {286, 29999}, {287, 29999}, - {288, 29999}, {289, 29999}, {290, 29999}, {291, 29999}, {292, 29999}, {293, 29999}, - {294, 29999}, {295, 999}, {296, 999}, {297, 99999999}, {298, 300}, {299, 300}, - {300, 300}, {301, 99999999}, {302, 99999}, {303, 300}, {304, 200}, {305, 90}, - {306, 90}, {307, 36000}, {308, 200}, {309, 299}, {310, 300}, {311, 300}, - {312, 100}, {313, 100}, {314, 200}, {315, 9999}, {316, 200}, {317, 9999}, - {318, 9999}, {319, 9999}, {320, 100}, {321, 99999999}, {322, 36000}, {323, 36000}, - {324, 36000}, {325, 100}, {326, 340}, {327, 340}, {328, 1000}, {329, 100}, - {330, 200}, {331, 300}, {332, 300}, {333, 99999999}, {334, 99999999}, {335, 99999999}, - {336, 200}, {337, 200}, {338, 200}, {339, 100}, {340, 3000}, {341, 9999}, - {342, 1000}, {343, 1000}, {344, 100}, {345, 99999999}, {346, 99999999}, {347, 9999}, - {348, 1000}, {349, 99999999}, {350, 99999999}, {351, 99999999}, {352, 99999999}, {353, 99999999}, - {354, 99999999}, {355, 99999999}, {356, 99999999}, {357, 99999999}, {358, 4000}, {359, 4000}, - {360, 4000}, {361, 300}, {362, 99999999}, {363, 100}, {364, 100}, {365, 300}, - {366, 200}, {367, 60}, {368, 99999}, {369, 99999}, {370, 19999}, {371, 200}, - {372, 200}, {373, 50}, {374, 29999}, {375, 99999}, {376, 200}, {377, 200}, - {378, 200}, {379, 200}, {380, 100}, {381, 99999999}, {382, 99999999}, {383, 200}, - {384, 200}, {385, 200}, {386, 250}, {387, 200}, {388, 200}, {389, 200}, - {390, 250}, {391, 150}, {392, 200}, {393, 200}, {394, 99999}, {395, 99999999}, - {396, 99999999}, {397, 99999999}, {398, 99999999}, {399, 200}, {400, 200}, {401, 200}, - {402, 200}, {403, 100}, {404, 29999}, {405, 29999}, {406, 200}, {407, 200}, - {408, 200}, {409, 300}, {410, 300}, {411, 300}, {412, 300}, {413, 50}, - {414, 50}, {415, 100}, {416, 100}, {417, 100}, {418, 99999999}, {419, 99999999}, - {420, 99999}, {421, 99999}, {422, 99999}, {423, 99999}, {424, 99999999}, {425, 100}, - {426, 14}, {427, 99999999}, {428, 200}, {429, 200}, {430, 200}, {431, 200}, - {432, 300}, {433, 300}, {434, 50}, {435, 100}, {436, 200}, {437, 3000}, - {438, 100}, {439, 300}, {440, 300}, {441, 60}, {442, 9999}, {443, 30}, - {444, 100}, {445, 500}, {446, 35}, {447, 340}, {448, 340}, {449, 60}, - {450, 999}, {451, 100}, {452, 250}, {453, 99999}, {454, 60}, {455, 1500}, - {456, 100}, {457, 100}, {458, 35}, {459, 100}, {460, 100}, {461, 100}, - {462, 200}, {463, 300}, {464, 100}, {465, 1000}, {466, 50}, {467, 300}, - {468, 300}, {469, 300}, {470, 300}, {471, 300}, {472, 300}, {473, 300}, - {474, 99999999}, {475, 99999999}, {476, 99999999}, {477, 99999999}, {478, 99999999}, {479, 99999999}, - {480, 99999999}, {481, 99999999}, {482, 99999999}, {483, 99999999}, {484, 99999999}, {485, 99999}, - {486, 99999}, {487, 200}, {488, 400}, {489, 400}, {490, 400}, {491, 100}, - {492, 100}, {493, 120}, {494, 499}, {495, 300}, {496, 200}, {497, 250}, - {498, 250}, {499, 250}, {500, 120}, {501, 100}, {502, 200}, {503, 500}, - {504, 999999}, {505, 200}, {506, 100}, {507, 100}, {508, 100}, {509, 100}, - {510, 1000}, {511, 10}, {512, 300}, {513, 3000}, {514, 300}, {515, 99999999}, - {516, 99999999}, {517, 29999}, {518, 200}, {519, 100}, {520, 499}, {521, 120}, - {522, 2000}, {523, 300}, {524, 300}, {525, 300}, {526, 300}, {527, 300}, - {528, 300}, {529, 300}, {530, 300}, {531, 300}, {532, 300}, {533, 300}, - {534, 300}, {535, 300}, {536, 300}, {537, 200}, {538, 120}, {539, 300}, - {540, 50}, {541, 300}, {542, 200}, {543, 500}, {544, 99999999}, {545, 200}, - {546, 200}, {547, 200}, {548, 60}, {549, 60}, {550, 60}, {551, 100}, - {552, 100}, {553, 200}, {554, 200}, {555, 200}, {556, 50}, {557, 99999999}, - {558, 99999999}, {559, 99999999}, {560, 99999999}, {561, 2000}, {562, 99999999}, {563, 200}, - {564, 60}, {565, 100}, {566, 100}, {567, 100}, {568, 100}, {569, 60}, - {570, 100}, {571, 100}, {572, 300}, {573, 300}, {574, 300}, {575, 300}, - {576, 100}, {577, 100}, {578, 100}, {579, 100}, {580, 100}, {581, 180}, - {582, 200}, {583, 50}, {584, 100}, {585, 100}, {586, 99999999}, {587, 100}, - {588, 100}, {589, 100}, {590, 200}, {591, 200}, {592, 99999999}, {593, 100}, - {594, 100}, {595, 100}, {596, 100}, {597, 100}, {598, 100}, {599, 200}, - {600, 200}, {601, 999999}, {602, 60}, {603, 50}, {604, 99999}, {605, 2}, - {606, 100}, {607, 100}, {608, 100}, {609, 100}, {610, 100}, {611, 100}, - {612, 100}, {613, 200}, {614, 200}, {615, 200}, {616, 200}, {617, 9999}, - {618, 300}, {619, 250}, {620, 29999}, {621, 200}, {622, 100}, {623, 300}, - {624, 200}, {625, 60}, {626, 60}, {627, 300}, {628, 200}, {629, 999999}, - {630, 100}, {631, 100}, {632, 100}, {633, 100}, {634, 23}, {635, 100}, - {636, 100}, {637, 200}, {638, 23}, {639, 23}, {640, 23}, {641, 23}, - {642, 23}, {643, 100}, {644, 100}, {645, 100}, {646, 100}, {647, 100}, - {648, 100}, {649, 100}, {650, 99999999}, {651, 99999999}, {652, 50}, {653, 50}, - {654, 50}, {655, 99999999}, {656, 40}, {657, 50}, {658, 50}, {659, 50}, - {660, 50}, {661, 50}, {662, 50}, {663, 50}, {664, 50}, {665, 200}, - {666, 100}, {667, 99999999}, {668, 28}, {669, 70}, {670, 28}, {671, 29999}, - {672, 29999}, {673, 99999999}, {674, 29999}, {675, 200}, {676, 300}, {677, 50}, - {678, 99999999}, {679, 99999999}, {680, 99999999}, {681, 36000}, {682, 100}, {683, 100}, - {684, 100}, {685, 100}, {686, 100}, {687, 99999999}, {688, 99999999}, {689, 99999999}, - {690, 99999999}, {691, 99999999}, {692, 99999999}, {693, 99999999}, {694, 99999999}, {695, 99999999}, - {696, 99999999}, {697, 99999999}, {698, 99999999}, {699, 100}, {700, 36000}, {701, 99999999}, - {702, 99999999}, {703, 99999999}, {704, 100}, {705, 100}, {706, 100}, {707, 100}, - {708, 9999}, {709, 70}, {710, 99999999}, {711, 99999999}, {712, 99999999}, {713, 99999999}, - {714, 99999999}, {715, 99999999}, {716, 360}, {717, 999}, {718, 90}, {719, 999}, - {720, 300}, {721, 100}, {722, 100}, {723, 100}, {724, 100}, {725, 250}, - {726, 300}, {727, 100}, {728, 100}, {729, 100}, {730, 100}, {731, 24}, - {732, 100}, {733, 300}, {734, 100}, {735, 999999}, {736, 999999}, {737, 999999}, - {738, 999999}, {739, 23}, {740, 23}, {741, 23}, {742, 23}, {743, 23}, - {744, 99999999}, {745, 100}, {746, 100}, {747, 100}, {748, 100}, {749, 100}, - {750, 999}, {751, 100}, {752, 9999}, {753, 300}, {754, 9999}, {755, 99999999}, - {756, 199}, {757, 99999999}, {758, 99999999}, {759, 99999999}, {760, 99999999}, {761, 99999999}, - {762, 99999999}, {763, 99999999}, {764, 99999999}, {765, 99999999}, {766, 99999999}, {767, 99999999}, - {768, 120}, {769, 200}, {770, 300}, {771, 300}, {772, 100}, {773, 300}, - {774, 499}, {775, 100}, {776, 100}, {777, 100}, {778, 250}, {779, 100}, - {780, 250}, {781, 300}, {782, 200}, {783, 29999}, {784, 29999}, {785, 300}, - {786, 100}, {787, 200}, {788, 99999999}, {789, 99999999}, {790, 99999999}, {791, 200}, - {792, 9999}, {793, 100}, {794, 300}, {795, 999}, {796, 1999}, {797, 300}, - {798, 999}, {799, 300}, {800, 75}, {801, 150}, {802, 2999}, {803, 500}, - {804, 600}, {805, 40}, {806, 100}, {807, 999}, {808, 500}, {809, 99999999}, - {810, 999}, {811, 200}, {812, 100}, {813, 100}, {814, 100}, {815, 100}, - {816, 100}, {817, 100}, {818, 100}, {819, 99999}, {820, 300}, {821, 99999999}, - {822, 29999}, {823, 99999999}, {824, 9999}, {825, 29999}, {826, 60}, {827, 29999}, - {828, 29999}, {829, 29999}, {830, 100}, {831, 100}, {832, 2000}, {833, 999999}, - {834, 200}, {835, 300}, {836, 300}, {837, 60}, {838, 99999999}, {839, 99999999}, - {840, 100}, {841, 100}, {842, 100}, {843, 100}, {844, 100}, {845, 100}, - {846, 99999999}, {847, 100}, {848, 100}, {849, 500}, {850, 100}, {851, 300}, - {852, 300}, {853, 400}, {854, 300}, {855, 300}, {856, 29999}, {857, 1000}, - {858, 300}, {859, 300}, {860, 29999}, {861, 400}, {862, 300}, {863, 300}, - {864, 100}, {865, 400}, {866, 400}, {867, 400}, {868, 400}, {869, 300}, - {870, 400}, {871, 400}, {872, 400}, {873, 400}, {874, 400}, {875, 400}, - {876, 400}, {877, 400}, {878, 400}, {879, 99999999}, {880, 99999999}, {881, 99999999}, - {882, 500}, {883, 9999}, {884, 500}, {885, 200}, {886, 300}, {887, 200}, - {888, 150}, {889, 300}, {890, 100}, {891, 100}, {892, 100}, {893, 300}, - {894, 200}, {895, 500}, {896, 500}, {897, 500}, {898, 5000}, {899, 999}, - {900, 5000}, {901, 500}, {902, 1000}, {903, 400}, {904, 300}, {905, 200}, - {906, 300}, {907, 300}, {908, 500}, {909, 500}, {910, 500}, {911, 60}, - {912, 1000}, {913, 100}, {914, 300}, {915, 200}, {916, 2000}, {917, 2000}, - {918, 2000}, {919, 1000}, {920, 40}, {921, 1000}, {922, 140}, {923, 500}, - {924, 400}, {925, 9999}, {926, 32797}, {927, 140}, {928, 200}, {929, 9999}, - {930, 300}, {931, 500}, {932, 100}, {933, 99999999}, {934, 300}, {935, 100}, - {936, 300}, {937, 300}, {938, 300}, {939, 29999}, {940, 99999999}, {941, 500}, - {942, 100}, {943, 2000}, {944, 100}, {945, 99999999}, {946, 99999999}, {947, 100}, - {948, 100}, {949, 100}, {950, 100}, {951, 100}, {952, 100}, {953, 100}, - {954, 100}, {955, 100}, {956, 100}, {957, 100}, {958, 100}, {959, 60}, - {960, 100}, {961, 100}, {962, 100}, {963, 99999}, {964, 40}, {965, 100}, - {966, 100}, {967, 100}, {968, 99999999}, {969, 200}, {970, 600}, {971, 600}, - {972, 600}, {973, 600}, {974, 99999999}, {975, 40}, {976, 99999999}, {977, 99999999}, - {978, 99999999}, {979, 99999999}, {980, 99999999}, {981, 99999999}, {982, 99999999}, {983, 99999999}, - {984, 99999999}, {985, 99999999}, {986, 99999999}, {987, 100}, {988, 100}, {989, 99999999}, - {990, 99999999}, {991, 99999999}, {992, 99999999}, {993, 99999999}, {994, 99999999}, {995, 99999999}, - {996, 99999999}, {997, 99999999}, {998, 99999999}, {999, 99999999}, {1000, 99999999}, {1001, 99999999}, - {1002, 99999999}, {1003, 99999999}, {1004, 99999999}, {1005, 99999999}, {1006, 100}, {1007, 99999999}, - {1008, 99999999}, {1009, 99999999}, {1010, 99999999}, {1011, 99999999}, {1012, 99999999}, {1013, 99999999}, - {1014, 99999999}, {1015, 100}, {1016, 90}, {1017, 100}, {1018, 100}, {1019, 200}, - {1020, 100}, {1021, 20000}, {1022, 999}, {1023, 999}, {1024, 999}, {1025, 999}, - {1026, 999}, {1027, 999}, {1028, 999}, {1029, 40}, {1030, 5000}, {1031, 999}, - {1032, 999}, {1033, 999}, {1034, 999}, {1035, 999}, {1036, 999}, {1037, 99999}, - {1038, 9999}, {1039, 999}, {1040, 9999}, {1041, 999}, {1042, 100}, {1043, 999}, - {1044, 999}, {1045, 99999999}, {1046, 999}, {1047, 999}, {1048, 9999}, {1049, 999}, - {1050, 999}, {1051, 999}, {1052, 200}, {1053, 999}, {1054, 9999}, {1055, 9999}, - {1056, 9999}, {1057, 9999}, {1058, 9999}, {1059, 350}, {1060, 9999}, {1061, 9999}, - {1062, 9999}, {1063, 9999}, {1064, 9}, {1065, 9999}, {1066, 9999}, {1067, 9999}, - {1068, 9999}, {1069, 9999}, {1070, 9999}, {1071, 9999}, {1072, 30}, {1073, 9999}, - {1074, 9999}, {1075, 9999}, {1076, 9999}, {1077, 9999}, {1078, 9999}, {1079, 999}, - {1080, 9999}, {1081, 9999}, {1082, 300}, {1083, 999}, {1084, 999}, {1085, 999}, - {1086, 999}, {1087, 999}, {1088, 2000}, {1089, 999}, {1090, 9999}, {1091, 999}, - {1092, 999}, {1093, 999}, {1094, 999}, {1095, 999}, {1096, 1096}, {1097, 1097}, - {1098, 1098}, {1099, 1099}, {1100, 1100}, {1101, 1101}, {1102, 1102}, {1103, 1103}, - {1104, 1104}, {1105, 1105}, {1106, 1106}, {1107, 1107}, {1108, 1108}, {1109, 1109}, - {1110, 9999}, {1111, 1111}, {1112, 1112}, {1113, 100}, {1114, 1114}, {1115, 99999999}, - {1116, 1116}, {1117, 1117}, {1118, 1118}, {1119, 1119}, {1120, 1120}, {1121, 1121}, - {1122, 99999999}, {1123, 1123}, {1124, 1124}, {1125, 1125}, {1126, 1126}, {1127, 1127}, - {1128, 1128}, {1129, 1129}, {1130, 1130}, {1131, 99}, {1132, 99999999}, {1133, 1133}, - {1134, 1134}, {1135, 99999999}, {1136, 1136}, {1137, 1137}, {1138, 1138}, {1139, 1139}, - {1140, 1140}, {1141, 1141}, {1142, 1142}, {1143, 100}, {1144, 100}, {1145, 99999999}, - {1146, 1146}, {1147, 99999999}, {1148, 9999999}, {1149, 99999}, {1150, 300}, {1151, 1151}, - {1152, 1152}, {1153, 1153}, {1154, 1154}, {1155, 1155}, {1156, 1156}, {1157, 1157}, - {1158, 1158}, {1159, 1159}, {1160, 1160}, {1161, 150}, {1162, 9999}, {1163, 9999}, - {1164, 99999999}, {1165, 99999999}, {1166, 99999999}, {1167, 99999999}, {1168, 99999999}, {1169, 99999999}, - {1170, 99999999}, {1171, 99999999}, {1172, 99999999}, {1173, 99999999}, {1174, 99999999}, {1175, 99999999}, - {1176, 99999999}, {1177, 99999999}, {1178, 99999999}, {1179, 99999999}, {1180, 99999999}, {1181, 99999999}, - {1182, 99999999}, {1183, 99999999}, {1184, 1184}, {1185, 99999999}, {1186, 1186}, {1187, 1187}, - {1188, 1188}, {1189, 1189}, {1190, 1190}, {1191, 1191}, {1192, 1192}, {1193, 1193}, - {1194, 1194}, {1195, 1195}, {1196, 1196}, {1197, 1197}, {1198, 1198}, {1199, 1199}, - {1200, 1200}, {1201, 1201}, {1202, 1202}, {1203, 1203}, {1204, 100}, {1205, 100}, - {1206, 200}, {1207, 200}, {1208, 200}, {1209, 100}, {1210, 200}, {1211, 1211}, - {1212, 1212}, {1213, 1213}, {1214, 1214}, {1215, 1215}, {1216, 1216}, {1217, 1217}, - {1218, 1218}, {1219, 1219}, {1220, 1220}, {1221, 1221}, {1222, 1222}, {1223, 1223}, - {1224, 50}, {1225, 1225}, {1226, 1226}, {1227, 1227}, {1228, 1228}, {1229, 1229}, - {1230, 1230}, {1231, 1231}, {1232, 1232}, {1233, 1233}, {1234, 1234}, {1235, 1235}, - {1236, 1236}, {1237, 1237}, {1238, 1238}, {1239, 1239}, {1240, 1240}, {1241, 1241}, - {1242, 1242}, {1243, 1243}, {1244, 1244}, {1245, 1245}, {1246, 1246}, {1247, 1247}, - {1248, 1248}, {1249, 1249}, {1250, 1250}, {1251, 1251}, {1252, 1252}, {1253, 1253}, - {1254, 1254}, {1255, 1255}, {1256, 1256}, {1257, 1257}, {1258, 1258}, {1259, 1259}, - {1260, 1260}, {1261, 1261}, {1262, 1262}, {1263, 1263}, {1264, 1264}, {1265, 1265}, - {1266, 1266}, {1267, 1267}, {1268, 1268}, {1269, 1269}, {1270, 1270}, {1271, 1271}, - {1272, 1272}, {1273, 1273}, {1274, 1274}, {1275, 1275}, {1276, 1276}, {1277, 1277}, - {1278, 1278}, {1279, 1279}, {1280, 1280}, {1281, 1281}, {1282, 1282}, {1283, 1283}, - {1284, 1284}, {1285, 1285}, {1286, 1286}, {1287, 1287}, {1288, 1288}, {1289, 1289}, - {1290, 1290}, {1291, 99999999}, {1292, 99999999}, {1293, 1293}, {1294, 1294}, {1295, 1295}, - {1296, 1296}, {1297, 1297}, {1298, 1298}, {1299, 1299}, {1300, 1300}, {1301, 1301}, - {1302, 1302}, {1303, 1303}, {1304, 1304}, {1305, 1305}, {1306, 1306}, {1307, 1307}, - {1308, 1308}, {1309, 1309}, {1310, 1310}, {1311, 1311}, {1312, 1312}, {1313, 1313}, - {1314, 1314}, {1315, 1315}, {1316, 1316}, {1317, 1317}, {1318, 1318}, {1319, 1319}, - {1320, 1320}, {1321, 1321}, {1322, 1322}, {1323, 1323}, {1324, 1324}, {1325, 99999999}, - {1326, 99999999}, {1327, 99999999}, {1328, 99999999}, {1329, 99999999}, {1330, 99999999}, {1331, 99999999}, - {1332, 99999999}, {1333, 99999999}, {1334, 99999999}, {1335, 99999999}, {1336, 99999999}, {1337, 99999999}, - {1338, 99999999}, {1339, 99999999}, {1340, 99999999}, {1341, 99999999}, {1342, 99999999}, {1343, 99999999}, - {1344, 99999999}, {1345, 99999999}, {1346, 99999999}, {1347, 1347}, {1348, 1348}, {1349, 1349}, - {1350, 1350}, {1351, 1351}, {1352, 1352}, {1353, 1353}, {1354, 1354}, {1355, 1355}, - {1356, 1356}, {1357, 1357}, {1358, 1358}, {1359, 1359}, {1360, 1360}, {1361, 1361}, - {1362, 1362}, {1363, 1363}, {1364, 1364}, {1365, 50}, {1366, 1366}, {1367, 1367}, - {1368, 1368}, {1369, 1369}, {1370, 1370}, {1371, 1371}, {1372, 1372}, {1373, 1373}, - {1374, 1374}, {1375, 1375}, {1376, 1376}, {1377, 99999999}, {1378, 1378}, {1379, 1379}, - {1380, 1380}, {1381, 1381}, {1382, 1382}, {1383, 1383}, {1384, 1384}, {1385, 1385}, - {1386, 1386}, {1387, 1387}, {1388, 1388}, {1389, 1389}, {1390, 1390}, {1391, 1391}, - {1392, 1392}, {1393, 1393}, {1394, 1394}, {1395, 1395}, {1396, 1396}, {1397, 1397}, - {1398, 99999999}, {1399, 75}, {1400, 1400}, {1401, 1401}, {1402, 1402}, {1403, 1403}, - {1404, 1404}, {1405, 1405}, {1406, 1406}, {1407, 1407}, {1408, 1408}, {1409, 300}, - {1410, 1410}, {1411, 1411}, {1412, 1412}, {1413, 1413}, {1414, 1414}, {1415, 1415}, - {1416, 1416}, {1417, 1417}, {1418, 1418}, {1419, 1419}, {1420, 99999999}, {1421, 1421}, - {1422, 1422}, {1423, 1423}, {1424, 1424}, {1425, 1425}, {1426, 1426}, {1427, 1427}, - {1428, 1428}, {1429, 1429}, {1430, 1430}, {1431, 1431}, {1432, 1432}, {1433, 1433}, - {1434, 1434}, {1435, 1435}, {1436, 1436}, {1437, 1437}, {1438, 1438}, {1439, 1439}, - {1440, 1440}, {1441, 1441}, {1442, 1442}, {1443, 1443}, {1444, 1444}, {1445, 1445}, - {1446, 1446}, {1447, 1447}, {1448, 1448}, {1449, 1449}, {1450, 1450}, {1451, 1451}, - {1452, 1452}, {1453, 1453}, {1454, 1454}, {1455, 1455}, {1456, 1456}, {1457, 1457}, - {1458, 1458}, {1459, 1459}, {1460, 1460}, {1461, 1461}, {1462, 1462}, {1463, 1463}, - {1464, 1464}, {1465, 1465}, {1466, 1466}, {1467, 1467}, {1468, 1468}, {1469, 1469}, - {1470, 1470}, {1471, 1471}, {1472, 1472}, {1473, 1473}, {1474, 1474}, {1475, 1475}, - {1476, 1476}, {1477, 1477}, {1478, 1478}, {1479, 1479}, {1480, 1480}, {1481, 1481}, - {1482, 1482}, {1483, 1483}, {1484, 1484}, {1485, 1485}, {1486, 1486}, {1487, 1487}, - {1488, 1488}, {1489, 1489}, {1490, 1490}, {1491, 1491}, {1492, 1492}, {1493, 1493}, - {1494, 1494}, {1495, 1495}, {1496, 1496}, {1497, 1497}, {1498, 1498}, {1499, 1499}, - {1500, 1500}, {1501, 1501}, {1502, 1502}, {1503, 1503}, {1504, 1504}, {1505, 1505}, - {1506, 1506}, {1507, 1507}, {1508, 1508}, {1509, 1509}, {1510, 1510}, {1511, 1511}, - {1512, 1512}, {1513, 1513}, {1514, 1514}, {1515, 1515}, {1516, 1516}, {1517, 1517}, - {1518, 1518}, {1519, 1519}, {1520, 1520}, {1521, 1521}, {1522, 1522}, {1523, 1523}, - {1524, 1524}, {1525, 99999999}, {1526, 1526}, {1527, 1527}, {1528, 1528}, {1529, 1529}, - {1530, 1530}, {1531, 99999999}, {1532, 1532}, {1533, 1533}, {1534, 1534}, {1535, 1535}, - {1536, 1536}, {1537, 1537}, {1538, 1538}, {1539, 1539}, {1540, 1540}, {1541, 1541}, - {1542, 1542}, {1543, 1543}, {1544, 1544}, {1545, 300}, {1546, 1546}, {1547, 1547}, - {1548, 1548}, {1549, 1549}, {1550, 1550}, {1551, 1551}, {1552, 1552}, {1553, 1553}, - {1554, 1554}, {1555, 1555}, {1556, 60}, {1557, 1557}, {1558, 1558}, {1559, 1559}, - {1560, 40}, {1561, 1561}, {1562, 1562}, {1563, 1563}, {1564, 1564}, {1565, 40}, - {1566, 1566}, {1567, 1567}, {1568, 300}, {1569, 150}, {1570, 1570}, {1571, 1571}, - {1572, 1572}, {1573, 1573}, {1574, 1574}, {1575, 300}, {1576, 1576}, {1577, 1577}, - {1578, 1578}, {1579, 1579}, {1580, 1580}, {1581, 1581}, {1582, 1582}, {1583, 1583}, - {1584, 300}, {1585, 1585}, {1586, 1586}, {1587, 1587}, {1588, 1588}, {1589, 1589}, - {1590, 1590}, {1591, 1591}, {1592, 1592}, {1593, 1593}, {1594, 200}, {1595, 1595}, - {1596, 1596}, {1597, 1597}, {1598, 1598}, {1599, 1599}, {1600, 200}, {1601, 99999999}, - {1602, 9999}, {1603, 9999}, {1604, 9999}, {1605, 9999}, {1606, 9999}, {1607, 1607}, - {1608, 1608}, {1609, 1609}, {1610, 99999999}, {1611, 1611}, {1612, 1612}, {1613, 1613}, - {1614, 1614}, {1615, 1615}, {1616, 1616}, {1617, 1617}, {1618, 1618}, {1619, 1619}, - {1620, 1620}, {1621, 1621}, {1622, 1622}, {1623, 1623}, {1624, 1624}, {1625, 1625}, - {1626, 1626}, {1627, 1627}, {1628, 1628}, {1629, 1629}, {1630, 1630}, {1631, 1631}, - {1632, 1632}, {1633, 1633}, {1634, 1634}, {1635, 1635}, {1636, 1636}, {1637, 1637}, - {1638, 1638}, {1639, 1639}, {1640, 1640}, {1641, 1641}, {1642, 1642}, {1643, 1643}, - {1644, 1644}, {1645, 1645}, {1646, 1646}, {1647, 1647}, {1648, 1648}, {1649, 1649}, - {1650, 1650}, {1651, 1651}, {1652, 1652}, {1653, 1653}, {1654, 1654}, {1655, 99999999}, - {1656, 100}, {1657, 1657}, {1658, 1658}, {1659, 1659}, {1660, 1660}, {1661, 1661}, - {1662, 1662}, {1663, 1663}, {1664, 100}, {1665, 1665}, {1666, 1666}, {1667, 1667}, - {1668, 1668}, {1669, 1669}, {1670, 1670}, {1671, 1671}, {1672, 1672}, {1673, 1673}, - {1674, 1674}, {1675, 1675}, {1676, 1676}, {1677, 60}, {1678, 1678}, {1679, 1679}, - {1680, 1680}, {1681, 1681}, {1682, 1682}, {1683, 1683}, {1684, 1684}, {1685, 1685}, - {1686, 1686}, {1687, 1687}, {1688, 1688}, {1689, 1689}, {1690, 1690}, {1691, 1691}, - {1692, 1692}, {1693, 1693}, {1694, 1694}, {1695, 1695}, {1696, 1696}, {1697, 1697}, - {1698, 1698}, {1699, 1699}, {1700, 1700}, {1701, 1701}, {1702, 1702}, {1703, 1703}, - {1704, 1704}, {1705, 1705}, {1706, 1706}, {1707, 1707}, {1708, 1708}, {1709, 40}, - {1710, 1710}, {1711, 1711}, {1712, 1712}, {1713, 1713}, {1714, 1714}, {1715, 1715}, - {1716, 1716}, {1717, 1717}, {1718, 1718}, {1719, 1719}, {1720, 1720}, {1721, 1721}, - {1722, 1722}, {1723, 1723}, {1724, 1724}, {1725, 1725}, {1726, 1726}, {1727, 1727}, - {1728, 1728}, {1729, 1729}, {1730, 1730}, {1731, 1731}, {1732, 1732}, {1733, 1733}, - {1734, 1734}, {1735, 1735}, {1736, 1736}, {1737, 1737}, {1738, 1738}, {1739, 1739}, - {1740, 1740}, {1741, 1741}, {1742, 1742}, {1743, 1743}, {1744, 1744}, {1745, 1745}, - {1746, 1746}, {1747, 1747}, {1748, 1748}, {1749, 1749}, {1750, 1750}, {1751, 1751}, - {1752, 1752}, {1753, 1753}, {1754, 1754}, {1755, 1755}, {1756, 1756}, {1757, 1757}, - {1758, 1758}, {1759, 1759}, {1760, 1760}, {1761, 1761}, {1762, 1762}, {1763, 1763}, - {1764, 1764}, {1765, 1765}, {1766, 1766}, {1767, 1767}, {1768, 1768}, {1769, 1769}, - {1770, 1770}, {1771, 1771}, {1772, 1772}, {1773, 1773}, {1774, 1774}, {1775, 1775}, - {1776, 1776}, {1777, 1777}, {1778, 1778}, {1779, 1779}, {1780, 1780}, {1781, 1781}, - {1782, 1782}, {1783, 1783}, {1784, 1784}, {1785, 1785}, {1786, 1786}, {1787, 1787}, - {1788, 1788}, {1789, 1789}, {1790, 1790}, {1791, 1791}, {1792, 1792}, {1793, 1793}, - {1794, 1794}, {1795, 1795}, {1796, 1796}, {1797, 1797}, {1798, 1798}, {1799, 1799}, - {1800, 1800}, {1801, 1801}, {1802, 1802}, {1803, 1803}, {1804, 1804}, {1805, 1805}, - {1806, 1806}, {1807, 1807}, {1808, 1808}, {1809, 1809}, {1810, 1810}, {1811, 1811}, - {1812, 1812}, {1813, 1813}, {1814, 1814}, {1815, 1815}, {1816, 1816}, {1817, 1817}, - {1818, 1818}, {1819, 1819}, {1820, 1820}, {1821, 1821}, {1822, 1822}, {1823, 1823}, - {1824, 1824}, {1825, 1825}, {1826, 1826}, {1827, 1827}, {1828, 1828}, {1829, 1829}, - {1830, 1830}, {1831, 1831}, {1832, 1832}, {1833, 1833}, {1834, 1834}, {1835, 1835}, - {1836, 1836}, {1837, 1837}, {1838, 1838}, {1839, 1839}, {1840, 1840}, {1841, 1841}, - {1842, 1842}, {1843, 1843}, {1844, 1844}, {1845, 1845}, {1846, 1846}, {1847, 1847}, - {1848, 1848}, {1849, 1849}, {1850, 1850}, {1851, 1851}, {1852, 1852}, {1853, 1853}, - {1854, 1854}, {1855, 1855}, {1856, 1856}, {1857, 1857}, {1858, 1858}, {1859, 1859}, - {1860, 1860}, {1861, 1861}, {1862, 1862}, {1863, 1863}, {1864, 1864}, {1865, 1865}, - {1866, 1866}, {1867, 1867}, {1868, 1868}, {1869, 1869}, {1870, 1870}, {1871, 1871}, - {1872, 1872}, {1873, 1873}, {1874, 1874}, {1875, 1875}, {1876, 1876}, {1877, 1877}, - {1878, 1878}, {1879, 1879}, {1880, 1880}, {1881, 1881}, {1882, 1882}, {1883, 1883}, - {1884, 1884}, {1885, 1885}, {1886, 1886}, {1887, 1887}, {1888, 1888}, {1889, 1889}, - {1890, 1890}, {1891, 1891}, {1892, 1892}, {1893, 1893}, {1894, 1894}, {1895, 1895}, - {1896, 1896}, {1897, 1897}, {1898, 1898}, {1899, 1899}, {1900, 1900}, {1901, 1901}, - {1902, 1902}, {1903, 1903}, {1904, 1904}, {1905, 1905}, {1906, 1906}, {1907, 1907}, - {1908, 1908}, {1909, 1909}, {1910, 1910}, {1911, 1911}, {1912, 1912}, {1913, 1913}, - {1914, 1914}, {1915, 1915}, {1916, 1916}, {1917, 1917}, {1918, 1918}, {1919, 1919}, - {1920, 1920}, {1921, 1921}, {1922, 1922}, {1923, 1923}, {1924, 1924}, {1925, 1925}, - {1926, 1926}, {1927, 1927}, {1928, 1928}, {1929, 1929}, {1930, 1930}, {1931, 1931}, - {1932, 1932}, {1933, 1933}, {1934, 1934}, {1935, 1935}, {1936, 1936}, {1937, 1937}, - {1938, 1938}, {1939, 1939}, {1940, 1940}, {1941, 1941}, {1942, 1942}, {1943, 1943}, - {1944, 1944}, {1945, 1945}, {1946, 1946}, {1947, 1947}, {1948, 1948}, {1949, 1949}, - {1950, 1950}, {1951, 1951}, {1952, 1952}, {1953, 1953}, {1954, 1954}, {1955, 1955}, - {1956, 1956}, {1957, 1957}, {1958, 1958}, {1959, 1959}, {1960, 1960}, {1961, 1961}, - {1962, 1962}, {1963, 1963}, {1964, 1964}, {1965, 1965}, {1966, 1966}, {1967, 1967}, - {1968, 1968}, {1969, 1969}, {1970, 1970}, {1971, 1971}, {1972, 1972}, {1973, 120}, - {1974, 1974}, {1975, 1975}, {1976, 1976}, {1977, 1977}, {1978, 1978}, {1979, 1979}, - {1980, 1980}, {1981, 1981}, {1982, 1982}, {1983, 1983}, {1984, 1984}, {1985, 1985}, - {1986, 1986}, {1987, 1987}, {1988, 1988}, {1989, 1989}, {1990, 1990}, {1991, 1991}, - {1992, 1992}, {1993, 1993}, {1994, 1994}, {1995, 1995}, {1996, 1996}, {1997, 1997}, - {1998, 1998}, {1999, 1999}, {2000, 2000}, {2001, 2001}, {2002, 2002}, {2003, 2003}, - {2004, 2004}, {2005, 2005}, {2006, 2006}, {2007, 2007}, {2008, 2008}, {2009, 2009}, - {2010, 2010}, {2011, 2011}, {2012, 2012}, {2013, 2013}, {2014, 2014}, {2015, 2015}, - {2016, 2016}, {2017, 2017}, {2018, 2018}, {2019, 2019}, {2020, 2020}, {2021, 2021}, - {2022, 2022}, {2023, 2023}, {2024, 2024}, {2025, 2025}, {2026, 60}, {2027, 60}, - {2028, 2028}, {2029, 2029}, {2030, 2030}, {2031, 2031}, {2032, 2032}, {2033, 2033}, - {2034, 2034}, {2035, 2035}, {2036, 2036}, {2037, 2037}, {2038, 2038}, {2039, 2039}, - {2040, 2040}, {2041, 2041}, {2042, 2042}, {2043, 2043}, {2044, 2044}, {2045, 2045}, - {2046, 2046}, {2047, 2047}, {2048, 2048}, {2049, 2049}, {2050, 2050}, {2051, 2051}, - {2052, 2052}, {2053, 2053}, {2054, 2054}, {2055, 2055}, {2056, 2056}, {2057, 2057}, - {2058, 2058}, {2059, 2059}, {2060, 2060}, {2061, 2061}, {2062, 2062}, {2063, 2063}, - {2064, 2064}, {2065, 2065}, {2066, 2066}, {2067, 2067}, {2068, 2068}, {2069, 2069}, - {2070, 2070}, {2071, 2071}, {2072, 2072}, {2073, 2073}, {2074, 2074}, {2075, 2075}, - {2076, 2076}, {2077, 2077}, {2078, 2078}, {2079, 2079}, {2080, 2080}, {2081, 2081}, - {2082, 2082}, {2083, 2083}, {2084, 2084}, {2085, 2085}, {2086, 2086}, {2087, 2087}, - {2088, 2088}, {2089, 2089}, {2090, 2090}, {2091, 2091}, {2092, 2092}, {2093, 2093}, - {2094, 2094}, {2095, 2095}, {2096, 2096}, {2097, 2094}, {2098, 2098}, {2099, 2099}, - {2100, 2100}, {2101, 2101}, {2102, 2102}, {2103, 2103}, {2104, 2104}, {2105, 2105}, - {2106, 2106}, {2107, 2107}, {2108, 2108}, {2109, 2109}, {2110, 2110}, {2111, 2111}, - {2112, 2095}, {2113, 2096}, {2114, 2114}, {2115, 2115}, {2116, 2116}, {2117, 2117}, - {2118, 2118}, {2119, 2119}, {2120, 2120}, {2121, 2121}, {2122, 2122}, {2123, 2123}, - {2124, 2124}, {2125, 2125}, {2126, 2126}, {2127, 2127}, {2128, 2128}, {2129, 2129}, - {2130, 2130}, {2131, 2131}, {2132, 2132}, {2133, 2133}, {2134, 2134}, {2135, 2135}, - {2136, 2136}, {2137, 2137}, {2138, 2138}, {2139, 2139}, {2140, 2140}, {2141, 2141}, - {2142, 2142}, {2143, 2143}, {2144, 2144}, {2145, 2145}, {2146, 2146}, {2147, 2147}, - {2148, 2148}, {2149, 2149}, {2150, 2150}, {2151, 2151}, {2152, 2152}, {2153, 2153}, - {2154, 2154}, {2155, 2155}, {2156, 2156}, {2157, 2157}, {2158, 2158}, {2159, 2159}, - {2160, 2160}, {2161, 2161}, {2162, 2162}, {2163, 2163}, {2164, 2164}, {2165, 2165}, - {2166, 2166}, {2167, 2167}, {2168, 2168}, {2169, 2169}, {2170, 2170}, {2171, 2171}, - {2172, 2172}, {2173, 2173}, {2174, 2174}, {2175, 2175}, {2176, 2176}, {2177, 2177}, - {2178, 2178}, {2179, 2179}, {2180, 2180}, {2181, 2181}, {2182, 2182}, {2183, 2183}, - {2184, 2184}, {2185, 2185}, {2186, 2186}, {2187, 2187}, {2188, 2188}, {2189, 2189}, - {2190, 2190}, {2191, 2191}, {2192, 2192}, {2193, 2193}, {2194, 2194}, {2195, 2195}, - {2196, 2196}, {2197, 2197}, {2198, 2198}, {2199, 2199}, {2200, 2200}, {2201, 2201}, - {2202, 2202}, {2203, 2203}, {2204, 2204}, {2205, 2205}, {2206, 2206}, {2207, 2207}, - {2208, 2208}, {2209, 2209}, {2210, 2210}, {2211, 2211}, {2212, 2212}, {2213, 2213}, - {2214, 2214}, {2215, 2215}, {2216, 2216}, {2217, 2217}, {2218, 2218}, {2219, 2219}, - {2220, 2220}, {2221, 2221}, {2222, 2222}, {2223, 2223}, {2224, 2224}, {2225, 2225}, - {2226, 2226}, {2227, 2227}, {2228, 2228}, {2229, 2229}, {2230, 2230}, {2231, 2231}, - {2232, 2232}, {2233, 2233}, {2234, 2234}, {2235, 2235}, {2236, 2236}, {2237, 2237}, - {2238, 2238}, {2239, 2239}, {2240, 2240}, {2241, 2241}, {2242, 2242}, {2243, 2243}, - {2244, 2244}, {2245, 2245}, {2246, 2246}, {2247, 2247}, {2248, 2248}, {2249, 2249}, - {2250, 2250}, {2251, 2251}, {2252, 2252}, {2253, 2253}, {2254, 2254}, {2255, 2255}, - {2256, 2256}, {2257, 2257}, {2258, 2258}, {2259, 2259}, {2260, 2260}, {2261, 2261}, - {2262, 2262}, {2263, 2263}, {2264, 2264}, {2265, 2265}, {2266, 2266}, {2267, 2267}, - {2268, 2268}, {2269, 2269}, {2270, 2270}, {2271, 2271}, {2272, 2272}, {2273, 2273}, - {2274, 2274}, {2275, 2275}, {2276, 2276}, {2277, 99999}, {2278, 99999}, {2279, 2279}, - {2280, 2280}, {2281, 2281}, {2282, 2281}, {2283, 2282}, {2284, 2283}, {2285, 2284}, - {2286, 2285}, {2287, 2286}, {2288, 100}, {2289, 100}, {2290, 100}, {2291, 100}, - {2292, 100}, {2293, 100}, {2294, 100}, {2295, 100}, {2296, 100}, {2297, 100}, - {2298, 100}, {2299, 100}, {2300, 100}, {2301, 2301}, {2302, 2302}, {2303, 2303}, - {2304, 2304}, {2305, 2305}, {2306, 2306}, {2307, 2307}, {2308, 2308}, {2309, 99999999}, - {2310, 99999999}, {2311, 2311}, {2312, 2312}, {2313, 2313}, {2314, 2314}, {2315, 2315}, - {2316, 2316}, {2317, 2317}, {2318, 2318}, {2319, 2319}, {2320, 2320}, {2321, 2321}, - {2322, 2322}, {2323, 2323}, {2324, 2324}, {2325, 2325}, {2326, 2326}, {2327, 2327}, - {2328, 2328}, {2329, 2329}, {2330, 2330}, {2331, 2331}, {2332, 2332}, {2333, 2333}, - {2334, 2334}, {2335, 2335}, {2336, 2336}, {2337, 2337}, {2338, 70}, {2339, 2339}, - {2340, 2340}, {2341, 2341}, {2342, 2342}, {2343, 2343}, {2344, 2344}, {2345, 2345}, - {2346, 99999999}, {2347, 99999999}, {2348, 2348}, {2349, 2349}, {2350, 2350}, {2351, 2351}, - {2352, 2352}, {2353, 2353}, {2354, 2354}, {2355, 2355}, {2356, 99999999}, {2357, 99999999}, - {2358, 99999999}, {2359, 99999999}, {2360, 99999999}, {2361, 99999999}, {2362, 99999999}, {2363, 99999999}, - {2364, 99999999}, {2365, 99999999}, {2366, 2366}, {2367, 40}, {2368, 100}, {2369, 40}, - {2370, 2370}, {2371, 2371}, {2372, 2372}, {2373, 300}, {2374, 99999999}, {2375, 99999999}, - {2376, 2376}, {2377, 2377}, {2378, 2378}, {2379, 2379}, {2380, 2380}, {2381, 2381}, - {2382, 2382}, {2383, 2383}, {2384, 2384}, {2385, 2385}, {2386, 2386}, {2387, 2387}, - {2388, 2388}, {2389, 2389}, {2390, 999999}, {2391, 999999}, {2392, 999999}, {2393, 999999}, - {2394, 2394}, {2395, 2395}, {2396, 2396}, {2397, 2397}, {2398, 2398}, {2399, 2399}, - {2401, 2415}, {2402, 99999999}, {2413, 99999999}, {2414, 99999999}, {2415, 99999999}, {2416, 300}, - {2417, 300}, {2418, 2418}, {2419, 2419}, {2421, 2421}, {2422, 2422}, {2423, 2423}, - {2425, 250}, {2426, 100}, {2427, 100}, {2432, 2432}, {2433, 2433}, {2434, 2434}, - {2435, 300}, {2436, 3000}, {2437, 3000}, {2438, 2438}, {2439, 300}, {2440, 99999999}, - {2441, 300}, {2442, 300}, {2443, 99999999}, {2444, 500}, {2445, 2435}, {2446, 2436}, - {2447, 40}, {2448, 40}, {2449, 2438}, {2450, 40}, {2451, 9999}, {2452, 999}, - {2453, 2000}, {2454, 40}, {2455, 499}, {2456, 9999}, {2457, 40}, {2463, 100}, - {2464, 100}, {2465, 100}, {2466, 1000}, {2468, 300}, {2469, 40}, {2470, 250}, - {2471, 29999}, {2472, 9999}, {2473, 9999}, {2474, 100}, {2477, 250}, {2478, 100}, - {2479, 999}, {2480, 499}, {2481, 200}, {2482, 99999999}, {2483, 99999999}, - }; -} - -// OFFSET: 0x00C16440 -// FUNCTION: fn_20056 -int EffectLifetime(int id) { - const auto found = lifetimes.find(id); - return found == lifetimes.end() ? 0 : found->second; -} diff --git a/Source/Contents/EffectTypes.h b/Source/Contents/EffectTypes.h deleted file mode 100644 index a84be68..0000000 --- a/Source/Contents/EffectTypes.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTTYPES_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECTTYPES_H - -int EffectLifetime(int id); - -#endif diff --git a/Source/Contents/AttachedEffect.cpp b/Source/Contents/Effects/AttachedEffect.cpp similarity index 71% rename from Source/Contents/AttachedEffect.cpp rename to Source/Contents/Effects/AttachedEffect.cpp index 1a6ad69..b0d8c1d 100644 --- a/Source/Contents/AttachedEffect.cpp +++ b/Source/Contents/Effects/AttachedEffect.cpp @@ -1,4 +1,4 @@ -#include "Contents/AttachedEffect.h" +#include "Contents/Effects/AttachedEffect.h" AttachedEffect::AttachedEffect(ResourceMgr& resources, JobNames& names) : CRenderObject(resources, names) { } diff --git a/Source/Contents/AttachedEffect.h b/Source/Contents/Effects/AttachedEffect.h similarity index 53% rename from Source/Contents/AttachedEffect.h rename to Source/Contents/Effects/AttachedEffect.h index ab5e7c2..55e2c1b 100644 --- a/Source/Contents/AttachedEffect.h +++ b/Source/Contents/Effects/AttachedEffect.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ATTACHEDEFFECT_H -#define RAGNAROK_SOURCE_CONTENTS_ATTACHEDEFFECT_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_ATTACHEDEFFECT_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_ATTACHEDEFFECT_H -#include "Contents/RagEffectState.h" -#include "Contents/RenderObject.h" +#include "Contents/Effects/RagEffectState.h" +#include "Contents/Actors/RenderObject.h" struct AttachedEffect : CRenderObject { AttachedEffect(ResourceMgr& resources, JobNames& names); diff --git a/Source/Contents/Effect.cpp b/Source/Contents/Effects/Effect.cpp similarity index 82% rename from Source/Contents/Effect.cpp rename to Source/Contents/Effects/Effect.cpp index d073042..d512038 100644 --- a/Source/Contents/Effect.cpp +++ b/Source/Contents/Effects/Effect.cpp @@ -1,10 +1,10 @@ -#include "Contents/Effect.h" +#include "Contents/Effects/Effect.h" // OFFSET: 0x00B4DAE0 // FUNCTION: fn_18979 CEffect::CEffect(int value) - : id(value), position{}, sourcePosition{}, actor(0), sourceActor(0), frame(0), unknown_002C(60), unknown_0030(1), - outsideRange(0), range(130), unknown_00B0(-1), retained(0), forceRender(0), unknown_00C4(0), unknown_00C8(0) { + : id(value), position{}, sourcePosition{}, actor(0), sourceActor(0), frame(0), unknown_002C(60), unknown_0030(1), outsideRange(0), range(130), + unknown_00B0(-1), retained(0), forceRender(0), unknown_00C4(0), unknown_00C8(0) { } // OFFSET: 0x00B4DD10 diff --git a/Source/Contents/Effect.h b/Source/Contents/Effects/Effect.h similarity index 76% rename from Source/Contents/Effect.h rename to Source/Contents/Effects/Effect.h index 2f9187e..8be5757 100644 --- a/Source/Contents/Effect.h +++ b/Source/Contents/Effects/Effect.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECT_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECT_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECT_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECT_H #include #include @@ -13,8 +13,6 @@ struct EffectEvent { std::string text; }; -// Recovered CEffect lifetime and frame-retirement virtual only. The remaining -// effect update/draw dispatcher is not supplied by this declaration. class CEffect { public: explicit CEffect(int id); @@ -46,8 +44,6 @@ public: unsigned char unknown_00C9[3]; }; -// CEffectMgr +0x18: owns effects awaiting retirement, but retains its list nodes -// throughout each Close/destructor call. Active effect maps are separate owners. struct EffectRetirement { std::list& effects; void Clear(); diff --git a/Source/Contents/EffectActor.cpp b/Source/Contents/Effects/EffectActor.cpp similarity index 63% rename from Source/Contents/EffectActor.cpp rename to Source/Contents/Effects/EffectActor.cpp index c57ec09..a0441f9 100644 --- a/Source/Contents/EffectActor.cpp +++ b/Source/Contents/Effects/EffectActor.cpp @@ -1,8 +1,7 @@ -#include "Contents/EffectActor.h" +#include "Contents/Effects/EffectActor.h" // OFFSET: 0x00CA82E0 -EffectActorState::EffectActorState() - : unknown_0138(-1), unknown_013C(0), unknown_0140(0), first(nullptr), second(nullptr) { +EffectActorState::EffectActorState() : unknown_0138(-1), unknown_013C(0), unknown_0140(0), first(nullptr), second(nullptr) { } // OFFSET: 0x00CA8C40 @@ -16,6 +15,5 @@ EffectAttachments EffectActorState::Attachments() { // OFFSET: 0x00CA82E0 EffectActor::EffectActor(ResourceMgr& resources, JobNames& names) : CRenderObject(resources, names) { - // Original full-object byte +0x130, inside the render-base tail. this->render.unknown_0130[0] = 0; } diff --git a/Source/Contents/EffectActor.h b/Source/Contents/Effects/EffectActor.h similarity index 72% rename from Source/Contents/EffectActor.h rename to Source/Contents/Effects/EffectActor.h index 42999b3..066f780 100644 --- a/Source/Contents/EffectActor.h +++ b/Source/Contents/Effects/EffectActor.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTACTOR_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECTACTOR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTACTOR_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTACTOR_H -#include "Contents/EffectAttachments.h" -#include "Contents/RenderObject.h" +#include "Contents/Effects/EffectAttachments.h" +#include "Contents/Actors/RenderObject.h" struct EffectActorState { EffectActorState(); @@ -17,7 +17,6 @@ struct EffectActorState { /* 0150 */ RagEffectState* second; }; -// Recovered CAbleToMakeEffect lifecycle, not the larger CGameActor dispatcher. struct EffectActor : CRenderObject { EffectActor(ResourceMgr& resources, JobNames& names); bool EffectVisible() const; diff --git a/Source/Contents/EffectAttachments.cpp b/Source/Contents/Effects/EffectAttachments.cpp similarity index 86% rename from Source/Contents/EffectAttachments.cpp rename to Source/Contents/Effects/EffectAttachments.cpp index c442d9f..a8bbe9d 100644 --- a/Source/Contents/EffectAttachments.cpp +++ b/Source/Contents/Effects/EffectAttachments.cpp @@ -1,6 +1,6 @@ -#include "Contents/EffectAttachments.h" -#include "Contents/EffectActor.h" -#include "Contents/RagEffectState.h" +#include "Contents/Effects/EffectAttachments.h" +#include "Contents/Effects/EffectActor.h" +#include "Contents/Effects/RagEffectState.h" // OFFSET: 0x00CADBE0 // FUNCTION: fn_21062 @@ -47,7 +47,6 @@ void EffectAttachments::Unlink(RagEffectState* effect) { } } -// Notify before clearing nodes; effects are not deleted, and callback-visible list membership survives. // OFFSET: 0x00CA8C40 void EffectAttachments::DetachAll() { for (RagEffectState* effect : this->effects) { diff --git a/Source/Contents/EffectAttachments.h b/Source/Contents/Effects/EffectAttachments.h similarity index 55% rename from Source/Contents/EffectAttachments.h rename to Source/Contents/Effects/EffectAttachments.h index 3463c71..9630ed4 100644 --- a/Source/Contents/EffectAttachments.h +++ b/Source/Contents/Effects/EffectAttachments.h @@ -1,12 +1,10 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTATTACHMENTS_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECTATTACHMENTS_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTATTACHMENTS_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTATTACHMENTS_H #include struct RagEffectState; -// Original CAbleToMakeEffect fields +0x144..+0x153. List nodes are owned; -// effect objects are borrowed from the active game-mode object owner. struct EffectAttachments { std::list& effects; RagEffectState*& first; diff --git a/Source/Contents/EffectLists.cpp b/Source/Contents/Effects/EffectLists.cpp similarity index 95% rename from Source/Contents/EffectLists.cpp rename to Source/Contents/Effects/EffectLists.cpp index 7b3b9bb..b5637a1 100644 --- a/Source/Contents/EffectLists.cpp +++ b/Source/Contents/Effects/EffectLists.cpp @@ -1,6 +1,4 @@ -#include "Contents/EffectLists.h" - -#include +#include "Contents/Effects/EffectLists.h" // OFFSET: 0x00B25750 // FUNCTION: fn_18783 @@ -34,9 +32,8 @@ CEffect* EffectLists::Find(int actor, int instance, int id) const { return nullptr; } -// INLINE void EffectLists::RemoveActive(CEffect* effect) { - const auto found = this->active.find(std::bit_cast(effect->actor)); + const auto found = this->active.find(static_cast(effect->actor)); if (found != this->active.end()) { found->second.remove(effect); diff --git a/Source/Contents/EffectLists.h b/Source/Contents/Effects/EffectLists.h similarity index 58% rename from Source/Contents/EffectLists.h rename to Source/Contents/Effects/EffectLists.h index f858bd9..8857ff0 100644 --- a/Source/Contents/EffectLists.h +++ b/Source/Contents/Effects/EffectLists.h @@ -1,14 +1,10 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTLISTS_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECTLISTS_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTLISTS_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTLISTS_H -#include "Contents/Effect.h" +#include "Contents/Effects/Effect.h" #include -// Borrowed CEffectMgr active map (+0x10), retirement list (+0x18) and -// selected effect-id index (+0x20). The index borrows active effect pointers. -// Map keys use signed actor-id ordering. Moving to retirement does not delete -// an effect: queued geometry may still borrow its storage until frame cleanup. struct EffectLists { std::map>& active; EffectRetirement& retirement; diff --git a/Source/Contents/EffectParticle.cpp b/Source/Contents/Effects/EffectParticle.cpp similarity index 61% rename from Source/Contents/EffectParticle.cpp rename to Source/Contents/Effects/EffectParticle.cpp index c2198b2..227ef69 100644 --- a/Source/Contents/EffectParticle.cpp +++ b/Source/Contents/Effects/EffectParticle.cpp @@ -1,23 +1,15 @@ -#include "Contents/EffectParticle.h" -#include "Contents/RagEffectState.h" +#include "Contents/Effects/EffectParticle.h" +#include "Contents/Effects/RagEffectState.h" // OFFSET: 0x00BAD940 // FUNCTION: fn_19761 -EffectParticle::EffectParticle(ResourceMgr& resources, JobNames& names) - : CRenderObject(resources, names), state(this->render) { +EffectParticle::EffectParticle(ResourceMgr& resources, JobNames& names) : CRenderObject(resources, names), state(this->render) { } // OFFSET: 0x00C1DE70 // FUNCTION: fn_20076 EffectParticle* CreateEffectParticle( - RagEffectState& parent, - const RenderObjectState& parentRender, - int type, - float x, - float y, - float z, - ResourceMgr& resources, - JobNames& names, + RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names, std::list& worldObjects ) { auto* particle = new EffectParticle(resources, names); @@ -25,5 +17,6 @@ EffectParticle* CreateEffectParticle( particle->state.Initialize(particle->render, parent, parentRender, type, x, y, z); parent.related.push_back(&particle->state); worldObjects.push_back(particle); + return particle; } diff --git a/Source/Contents/Effects/EffectParticle.h b/Source/Contents/Effects/EffectParticle.h new file mode 100644 index 0000000..b0113ee --- /dev/null +++ b/Source/Contents/Effects/EffectParticle.h @@ -0,0 +1,28 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTPARTICLE_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTPARTICLE_H + +#include "Contents/Effects/EffectPrimitiveState.h" +#include "Contents/Actors/RenderObject.h" + +#include + +struct JobNames; +class ResourceMgr; +struct RagEffectState; + +struct EffectParticle : CRenderObject { + EffectParticle(ResourceMgr& resources, JobNames& names); + + EffectPrimitiveState state; +}; + +EffectParticle* CreateEffectParticle( + RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names, + std::list& worldObjects +); + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(EffectParticle) == 0xFA18); +#endif + +#endif diff --git a/Source/Contents/Effects/EffectPrimitiveColor.cpp b/Source/Contents/Effects/EffectPrimitiveColor.cpp new file mode 100644 index 0000000..d7c0c76 --- /dev/null +++ b/Source/Contents/Effects/EffectPrimitiveColor.cpp @@ -0,0 +1,72 @@ +#include "Contents/Effects/EffectPrimitiveState.h" +#include "Contents/Effects/RagEffectState.h" +#include "Utility/Math/ScalarConversion.h" + +// OFFSET: 0x00BC5E00 +// FUNCTION: fn_19849 +void EffectPrimitiveState::UpdateColor() { + const int current = this->unknown_01E0; + const bool valuesAndLimit = this->unknown_0158 != 0; + + if (valuesAndLimit || this->unknown_014C.y != 0) { + auto index = this->unknown_01D8; + const auto count = static_cast(this->unknown_0258[0].size()); + const bool outside = valuesAndLimit ? static_cast(index) > count - 1u : static_cast(index) >= count; + + if (index < 0 || outside) { + index = 0; + this->unknown_01D8 = 0; + } + + const float key = this->unknown_0258[0][index]; + + if (static_cast(current) == key) { + const float value = this->unknown_0258[1][index]; + + if (valuesAndLimit) { + this->unknown_0324 = value; + this->unknown_02D4 = this->unknown_0258[2][index]; + } else { + this->unknown_0328 = value; + } + + this->unknown_01D8 = index + 1; + } + } + + const float lower = this->unknown_02D8; + + if ((this->flags & 0x80u) != 0) { + const bool below = this->unknown_0328 >= 0.0f ? this->unknown_0324 < this->unknown_02D4 : lower < this->unknown_0324; + + if (!below) { + this->unknown_0328 *= -1.0f; + } + } + + if (this->unknown_015C == 0) { + const int parentRemaining = this->parent->lifetime - this->parent->unknown_0178; + const int remaining = this->lifetime - current; + + if (remaining > parentRemaining + 1) { + this->unknown_015C = 1; + this->flags &= ~0x80u; + this->unknown_0328 = -(this->unknown_0324 / static_cast(parentRemaining)); + } + } + + if (current == this->unknown_01F0) { + this->flags &= ~0x80u; + const int remaining = this->lifetime - current; + this->unknown_0328 = -(this->unknown_0324 / static_cast(remaining)) * this->unknown_032C; + } + + const float sum = this->unknown_0328 + this->unknown_0324; + const float minimum = lower > sum ? lower : sum; + const float bounded = this->unknown_02D4 < minimum ? this->unknown_02D4 : minimum; + this->unknown_0324 = bounded; + const auto alpha = static_cast(TruncateToInt(bounded)); + const auto color = + ((alpha * 256u + static_cast(this->red)) * 256u + static_cast(this->green)) * 256u + static_cast(this->blue); + this->unknown_01C0 = color; +} diff --git a/Source/Contents/EffectPrimitiveMotion.cpp b/Source/Contents/Effects/EffectPrimitiveMotion.cpp similarity index 63% rename from Source/Contents/EffectPrimitiveMotion.cpp rename to Source/Contents/Effects/EffectPrimitiveMotion.cpp index 240bfdd..a1d9b2f 100644 --- a/Source/Contents/EffectPrimitiveMotion.cpp +++ b/Source/Contents/Effects/EffectPrimitiveMotion.cpp @@ -1,29 +1,21 @@ -#include "Contents/EffectPrimitiveMotion.h" -#include "Contents/EffectPrimitiveState.h" -#include "Contents/RagEffectState.h" -#include "Contents/RenderObjectState.h" -#include "Utility/AffineMatrix.h" +#include "Contents/Effects/EffectPrimitiveMotion.h" +#include "Contents/Effects/EffectPrimitiveState.h" +#include "Contents/Effects/RagEffectState.h" +#include "Contents/Actors/RenderObjectState.h" +#include "Utility/Math/AffineMatrix.h" +#include "Utility/Math/ScalarConversion.h" #include #include #include -#include namespace { - int Add(int left, std::uint32_t right) { - return std::bit_cast(static_cast(left) + right); - } - - int Integer(float value) { - return _mm_cvttss_si32(_mm_set_ss(value)); - } - - // Preserve every zero product and the original summation order. EffectVector3 Forward(float distance, const float* matrix) { + const EffectVector3 point{0.0f, 0.0f, distance}; return { - ((matrix[3] * 0.0f + matrix[0] * 0.0f) + distance * matrix[6]) + matrix[9], - ((matrix[4] * 0.0f + matrix[1] * 0.0f) + distance * matrix[7]) + matrix[10], - ((matrix[5] * 0.0f + matrix[2] * 0.0f) + distance * matrix[8]) + matrix[11] + ((matrix[3] * point.y + matrix[0] * point.x) + point.z * matrix[6]) + matrix[9], + ((matrix[4] * point.y + matrix[1] * point.x) + point.z * matrix[7]) + matrix[10], + ((matrix[5] * point.y + matrix[2] * point.x) + point.z * matrix[8]) + matrix[11] }; } } @@ -36,7 +28,7 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend context.parentRender.position[2] + particle.velocity.z }; - if (static_cast(particle.unknown_0200) == particle.unknown_01E0) { + if (particle.unknown_0200 == particle.unknown_01E0) { particle.unknown_0138 = 1; constexpr float sentinel = 0.0001f; @@ -53,11 +45,11 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend } if (particle.unknown_02C4 != sentinel) { - particle.unknown_035C = std::bit_cast(particle.unknown_02C4); + particle.unknown_035C = particle.unknown_02C4; } if (particle.unknown_02D0 != sentinel) { - particle.unknown_0368 = std::bit_cast(particle.unknown_02D0); + particle.unknown_0368 = particle.unknown_02D0; } if (particle.unknown_02A0 != sentinel) { @@ -89,15 +81,11 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend particle.unknown_0370.x = particle.unknown_0370.x + particle.unknown_03AC.x; particle.unknown_0370.y = particle.unknown_03AC.y + particle.unknown_0370.y; particle.unknown_0370.z = particle.unknown_03AC.z + particle.unknown_0370.z; - particle.unknown_0358 = std::bit_cast(particle.unknown_035C) + particle.unknown_0358; + particle.unknown_0358 = particle.unknown_035C + particle.unknown_0358; particle.unknown_02BC = particle.unknown_02C0 + particle.unknown_02BC; - particle.unknown_0364 = std::bit_cast(particle.unknown_0368) + particle.unknown_0364; - particle.unknown_0330 = std::bit_cast( - std::bit_cast(particle.unknown_033C) + std::bit_cast(particle.unknown_0330) - ); - particle.unknown_0334 = std::bit_cast( - std::bit_cast(particle.unknown_0340) + std::bit_cast(particle.unknown_0334) - ); + particle.unknown_0364 = particle.unknown_0368 + particle.unknown_0364; + particle.unknown_0330 = particle.unknown_033C + particle.unknown_0330; + particle.unknown_0334 = particle.unknown_0340 + particle.unknown_0334; if ((particle.flags & 0x400u) != 0) { particle.unknown_0370 = {}; @@ -126,7 +114,7 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend return false; } - particle.unknown_030C = std::bit_cast(render.angle); + particle.unknown_030C = render.angle; } render.position[0] = particle.origin.x + particle.offset.x; @@ -134,12 +122,8 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend render.position[2] = particle.offset.z + particle.origin.z; particle.unknown_0354 = particle.unknown_0358 + particle.unknown_0354; particle.unknown_0360 = particle.unknown_0364 + particle.unknown_0360; - particle.unknown_030C = std::bit_cast( - std::bit_cast(particle.unknown_030C) + std::bit_cast(particle.unknown_0330) - ); - particle.unknown_0310 = std::bit_cast( - std::bit_cast(particle.unknown_0310) + std::bit_cast(particle.unknown_0334) - ); + particle.unknown_030C = particle.unknown_030C + particle.unknown_0330; + particle.unknown_0310 = particle.unknown_0310 + particle.unknown_0334; if (!(particle.unknown_0360 <= particle.unknown_036C)) { particle.unknown_0368 = 0; @@ -151,24 +135,24 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend if ((particle.flags & 0x200u) != 0) { matrix.SetZRotation(context.cameraPitch); } else if ((particle.flags & 0x40u) != 0) { - particle.unknown_030C = std::bit_cast(context.cameraYaw + 90.0f); + particle.unknown_030C = context.cameraYaw + 90.0f; particle.unknown_0314 = context.cameraPitch; - matrix.SetXRotation(ClientRadians(Integer(std::bit_cast(particle.unknown_0310)))); - matrix.RotateZ(ClientRadians(Integer(particle.unknown_0314))); + matrix.SetXRotation(ClientRadians(TruncateToInt(particle.unknown_0310))); + matrix.RotateZ(ClientRadians(TruncateToInt(particle.unknown_0314))); } else { - matrix.SetZRotation(ClientRadians(Integer(particle.unknown_0314))); - matrix.RotateX(ClientRadians(Integer(std::bit_cast(particle.unknown_0310)))); + matrix.SetZRotation(ClientRadians(TruncateToInt(particle.unknown_0314))); + matrix.RotateX(ClientRadians(TruncateToInt(particle.unknown_0310))); } - const float angle = (particle.flags & 0x200u) != 0 ? render.angle : std::bit_cast(particle.unknown_030C); - matrix.RotateY(ClientRadians(Integer(angle))); + const float angle = (particle.flags & 0x200u) != 0 ? render.angle : particle.unknown_030C; + matrix.RotateY(ClientRadians(TruncateToInt(angle))); std::memcpy(particle.matrix2, matrix.values, sizeof(particle.matrix2)); if ((particle.flags & 2u) != 0) { const auto index = particle.unknown_01D4; particle.unknown_01D4 = index + 1u == 10u ? 0u : index + 1u; - const float offset = static_cast(std::bit_cast(index)) / 10.0f; - particle.unknown_02E4 = std::bit_cast(offset); + const float offset = static_cast(static_cast(index)) / 10.0f; + particle.unknown_02E4 = offset; particle.unknown_02E8 = offset + 1.0f; } @@ -178,18 +162,16 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend particle.parent->offset[2] = particle.offset.z + particle.velocity.z; } - if ( - (particle.flags & 4u) != 0 && render.position[1] > context.ground.Height(render.position[0], render.position[2]) - ) { + if ((particle.flags & 4u) != 0 && render.position[1] > context.ground.Height(render.position[0], render.position[2])) { particle.flags &= ~4u; - particle.unknown_01E0 = static_cast(particle.lifetime) - 25u; + particle.unknown_01E0 = particle.lifetime - 25; particle.unknown_02BC = 0; particle.parent->unknown_0170 = 1; } - const int frame = std::bit_cast(particle.unknown_01E0); + const int frame = particle.unknown_01E0; - if ((particle.flags & 0x20u) != 0 && frame % std::bit_cast(particle.unknown_01CC) == 0) { + if ((particle.flags & 0x20u) != 0 && frame % static_cast(particle.unknown_01CC) == 0) { particle.unknown_0364 *= -1.0f; } @@ -206,9 +188,9 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend } if (advance) { - particle.red = Add(particle.red, particle.unknown_0248); - particle.green = Add(particle.green, particle.unknown_024C); - particle.blue = Add(particle.blue, particle.unknown_0250); + particle.red += particle.unknown_0248; + particle.green += particle.unknown_024C; + particle.blue += particle.unknown_0250; if (gated) { particle.unknown_01FC = 0; @@ -227,12 +209,12 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend particle.UpdateColor(); - if (std::bit_cast(particle.unknown_01E0) % particle.unknown_01E8 == 0) { + if (particle.unknown_01E0 % particle.unknown_01E8 == 0) { const auto next = render.unknown_003C + 1u; render.unknown_003C = next; if (particle.unknown_0254 != 0) { - render.unknown_003C = std::bit_cast(next) % std::bit_cast(particle.textureCount); + render.unknown_003C = static_cast(next) % static_cast(particle.textureCount); } else if (next == particle.textureCount) { return false; } @@ -243,13 +225,7 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend // OFFSET: 0x00BAE7D0 // FUNCTION: fn_19769 -// Only the incremented signed frame/lifetime comparison determines expiry. -bool UpdateEffectPrimitive15( - EffectPrimitiveState& particle, - RenderObjectState& render, - EffectMotionContext& context, - int updateTick -) { +bool UpdateEffectPrimitive15(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context, int updateTick) { if (!particle.parent) { return false; } @@ -260,5 +236,5 @@ bool UpdateEffectPrimitive15( MoveEffectPrimitive(particle, render, context); ++particle.unknown_01E0; - return std::bit_cast(particle.unknown_01E0) <= particle.lifetime; + return particle.unknown_01E0 <= particle.lifetime; } diff --git a/Source/Contents/Effects/EffectPrimitiveMotion.h b/Source/Contents/Effects/EffectPrimitiveMotion.h new file mode 100644 index 0000000..fcb8cc6 --- /dev/null +++ b/Source/Contents/Effects/EffectPrimitiveMotion.h @@ -0,0 +1,20 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTPRIMITIVEMOTION_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTPRIMITIVEMOTION_H + +#include "Contents/Ground/TerrainHeight.h" + +struct EffectPrimitiveState; +struct RenderObjectState; + +struct EffectMotionContext { + const RenderObjectState& parentRender; + const float& cameraPitch; + const float& cameraYaw; + const TerrainHeight& ground; +}; + +bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context); + +bool UpdateEffectPrimitive15(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context, int updateTick); + +#endif diff --git a/Source/Contents/EffectPrimitiveRecords.cpp b/Source/Contents/Effects/EffectPrimitiveRecords.cpp similarity index 62% rename from Source/Contents/EffectPrimitiveRecords.cpp rename to Source/Contents/Effects/EffectPrimitiveRecords.cpp index 5a9167c..0cbc2f5 100644 --- a/Source/Contents/EffectPrimitiveRecords.cpp +++ b/Source/Contents/Effects/EffectPrimitiveRecords.cpp @@ -1,9 +1,8 @@ -#include "Contents/EffectPrimitiveState.h" -#include "Contents/RenderObjectState.h" +#include "Contents/Effects/EffectPrimitiveState.h" +#include "Contents/Actors/RenderObjectState.h" -#include +#include "Utility/Math/ScalarConversion.h" #include -#include // OFFSET: 0x00BAE670 // FUNCTION: fn_19768 @@ -14,17 +13,15 @@ void EffectPrimitiveState::InitializeRecords(const RenderObjectState& render) { std::memcpy(record.corners, this->corners, sizeof(record.corners)); record.unknown_003C = this->unknown_0348; record.scale = this->scale; - record.angle = std::bit_cast(this->unknown_030C); + record.angle = this->unknown_030C; std::memcpy(record.matrix, this->matrix1, sizeof(record.matrix)); record.alpha = this->unknown_0324; record.red = this->red; record.green = this->green; record.blue = this->blue; - const int alpha = _mm_cvttss_si32(_mm_set_ss(this->unknown_0324)); + const int alpha = TruncateToInt(this->unknown_0324); record.color = static_cast(this->blue) + - ((static_cast(this->green) + - ((static_cast(this->red) + (static_cast(alpha) << 8)) << 8)) - << 8); + ((static_cast(this->green) + ((static_cast(this->red) + (static_cast(alpha) << 8)) << 8)) << 8); } } diff --git a/Source/Contents/EffectPrimitiveRendering.cpp b/Source/Contents/Effects/EffectPrimitiveRendering.cpp similarity index 74% rename from Source/Contents/EffectPrimitiveRendering.cpp rename to Source/Contents/Effects/EffectPrimitiveRendering.cpp index 96cba70..b70edb2 100644 --- a/Source/Contents/EffectPrimitiveRendering.cpp +++ b/Source/Contents/Effects/EffectPrimitiveRendering.cpp @@ -1,19 +1,13 @@ -#include "Contents/EffectPrimitiveRendering.h" -#include "Contents/EffectPrimitiveState.h" -#include "Contents/EffectVisibility.h" -#include "Contents/RenderObjectState.h" -#include "Render/RenderProjection.h" -#include "Render/RenderQueues.h" - -#include +#include "Contents/Effects/EffectPrimitiveRendering.h" +#include "Contents/Effects/EffectPrimitiveState.h" +#include "Contents/Effects/EffectVisibility.h" +#include "Contents/Actors/RenderObjectState.h" +#include "Render/Projection/RenderProjection.h" +#include "Render/Primitives/RenderQueues.h" // OFFSET: 0x00BCD960 // FUNCTION: fn_19865 -void DrawEffectPrimitive15( - EffectPrimitiveState& particle, - const RenderObjectState& render, - EffectPrimitiveRenderContext& context -) { +void DrawEffectPrimitive15(EffectPrimitiveState& particle, const RenderObjectState& render, EffectPrimitiveRenderContext& context) { const float width = particle.unknown_0354; const float left = -width; float top = -particle.unknown_0360; @@ -45,7 +39,6 @@ void DrawEffectPrimitive15( const float bottomY = bottom * matrix[4] + zeroY; const float bottomZ = bottom * matrix[5] + zeroZ; - // Top and bottom rows use different ADDSS operand orders in the original. const EffectVector3 corners[4] = { {(rightX + topX) + matrix[9], (rightY + topY) + matrix[10], (rightZ + topZ) + matrix[11]}, {(leftX + topX) + matrix[9], (leftY + topY) + matrix[10], (leftZ + topZ) + matrix[11]}, @@ -55,7 +48,7 @@ void DrawEffectPrimitive15( constexpr unsigned indices[2][3] = {{0, 1, 2}, {3, 2, 1}}; constexpr float u[2][3] = {{0, 1, 0}, {1, 0, 1}}; - const float vTop = std::bit_cast(particle.unknown_02E4); + const float vTop = particle.unknown_02E4; const float vBottom = particle.unknown_02E8; const float v[2][3] = {{vTop, vTop, vBottom}, {vBottom, vBottom, vTop}}; @@ -64,14 +57,12 @@ void DrawEffectPrimitive15( for (unsigned vertexIndex = 0; vertexIndex < 3; ++vertexIndex) { const EffectVector3& corner = corners[indices[triangleIndex][vertexIndex]]; - const float position[3] = { - corner.x + render.position[0], corner.y + render.position[1], corner.z + render.position[2] - }; + const float position[3] = {corner.x + render.position[0], corner.y + render.position[1], corner.z + render.position[2]}; RenderVertex projected{0, 0, 0, 0, 0, 0xFF000000u, 0, 0}; context.projection.Project(position, context.cameraMatrix, projected); RenderVertex& vertex = triangle.vertices[vertexIndex]; vertex = projected; - vertex.diffuse = std::bit_cast(particle.unknown_01C0); + vertex.diffuse = particle.unknown_01C0; vertex.u = u[triangleIndex][vertexIndex]; vertex.v = v[triangleIndex][vertexIndex]; } @@ -84,8 +75,7 @@ void DrawEffectPrimitive15( if (triangle.Visible()) { context.queues.SubmitTriangle( - triangle, static_cast(particle.unknown_01C4), context.commands, context.depthAlpha, - context.depthStart, context.depthEnd + triangle, static_cast(particle.unknown_01C4), context.commands, context.depthAlpha, context.depthStart, context.depthEnd ); } } @@ -94,10 +84,7 @@ void DrawEffectPrimitive15( // OFFSET: 0x00BCE350 // FUNCTION: fn_19866 void RenderEffectPrimitive15( - EffectPrimitiveState& particle, - const RenderObjectState& render, - EffectPrimitiveRenderContext& context, - const EffectVisibilityContext& visibility + EffectPrimitiveState& particle, const RenderObjectState& render, EffectPrimitiveRenderContext& context, const EffectVisibilityContext& visibility ) { if (particle.parent && PartyEffectVisible(*particle.parent, visibility)) { DrawEffectPrimitive15(particle, render, context); diff --git a/Source/Contents/Effects/EffectPrimitiveRendering.h b/Source/Contents/Effects/EffectPrimitiveRendering.h new file mode 100644 index 0000000..b4fae0d --- /dev/null +++ b/Source/Contents/Effects/EffectPrimitiveRendering.h @@ -0,0 +1,27 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTPRIMITIVERENDERING_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTPRIMITIVERENDERING_H + +struct EffectPrimitiveState; +struct RenderObjectState; +struct RenderProjection; +struct RenderQueues; +class RenderCommandPool; +struct EffectVisibilityContext; + +struct EffectPrimitiveRenderContext { + const RenderProjection& projection; + const float* cameraMatrix; + RenderQueues& queues; + RenderCommandPool& commands; + const bool& depthAlpha; + const float& depthStart; + const float& depthEnd; +}; + +void DrawEffectPrimitive15(EffectPrimitiveState& particle, const RenderObjectState& render, EffectPrimitiveRenderContext& context); + +void RenderEffectPrimitive15( + EffectPrimitiveState& particle, const RenderObjectState& render, EffectPrimitiveRenderContext& context, const EffectVisibilityContext& visibility +); + +#endif diff --git a/Source/Contents/EffectPrimitiveState.cpp b/Source/Contents/Effects/EffectPrimitiveState.cpp similarity index 94% rename from Source/Contents/EffectPrimitiveState.cpp rename to Source/Contents/Effects/EffectPrimitiveState.cpp index 26358c9..fe76831 100644 --- a/Source/Contents/EffectPrimitiveState.cpp +++ b/Source/Contents/Effects/EffectPrimitiveState.cpp @@ -1,6 +1,6 @@ -#include "Contents/EffectPrimitiveState.h" -#include "Contents/RagEffectState.h" -#include "Contents/RenderObjectState.h" +#include "Contents/Effects/EffectPrimitiveState.h" +#include "Contents/Effects/RagEffectState.h" +#include "Contents/Actors/RenderObjectState.h" #include #include @@ -160,13 +160,7 @@ EffectPrimitiveState::~EffectPrimitiveState() { // OFFSET: 0x00BAE5D0 // FUNCTION: fn_19767 void EffectPrimitiveState::Initialize( - RenderObjectState& render, - RagEffectState& parent, - const RenderObjectState& parentRender, - int type, - float x, - float y, - float z + RenderObjectState& render, RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z ) { const float first = x + this->offset.x; this->parent = &parent; diff --git a/Source/Contents/EffectPrimitiveState.h b/Source/Contents/Effects/EffectPrimitiveState.h similarity index 77% rename from Source/Contents/EffectPrimitiveState.h rename to Source/Contents/Effects/EffectPrimitiveState.h index 813ad8f..8af0feb 100644 --- a/Source/Contents/EffectPrimitiveState.h +++ b/Source/Contents/Effects/EffectPrimitiveState.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTPRIMITIVESTATE_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECTPRIMITIVESTATE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTPRIMITIVESTATE_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTPRIMITIVESTATE_H -#include "Render/RenderPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" #include #include @@ -30,20 +30,10 @@ struct EffectPrimitiveRecord { std::uint32_t color; }; -// Recovered CEffectPrim state after its render base. Construction/destruction -// and parent initialization are independent of unreconstructed update/draw. struct EffectPrimitiveState { explicit EffectPrimitiveState(RenderObjectState& render); ~EffectPrimitiveState(); - void Initialize( - RenderObjectState& render, - RagEffectState& parent, - const RenderObjectState& parentRender, - int type, - float x, - float y, - float z - ); + void Initialize(RenderObjectState& render, RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z); void UpdateColor(); void InitializeRecords(const RenderObjectState& render); @@ -57,15 +47,15 @@ struct EffectPrimitiveState { /* 015C */ std::uint32_t unknown_015C; /* 0160 */ float matrix1[12]; /* 0190 */ float matrix2[12]; - /* 01C0 */ std::int32_t unknown_01C0; + /* 01C0 */ std::uint32_t unknown_01C0; /* 01C4 */ std::uint32_t unknown_01C4; /* 01C8 */ unsigned char unknown_01C8[4]; /* 01CC */ std::uint32_t unknown_01CC; /* 01D0 */ int type; /* 01D4 */ std::uint32_t unknown_01D4; - /* 01D8 */ std::uint32_t unknown_01D8; + /* 01D8 */ int unknown_01D8; /* 01DC */ std::uint32_t flags; - /* 01E0 */ std::uint32_t unknown_01E0; + /* 01E0 */ int unknown_01E0; /* 01E4 */ int lifetime; /* 01E8 */ int unknown_01E8; /* 01EC */ int unknown_01EC; @@ -82,12 +72,12 @@ struct EffectPrimitiveState { /* 023C */ int red; /* 0240 */ int green; /* 0244 */ int blue; - /* 0248 */ std::uint32_t unknown_0248; - /* 024C */ std::uint32_t unknown_024C; - /* 0250 */ std::uint32_t unknown_0250; + /* 0248 */ int unknown_0248; + /* 024C */ int unknown_024C; + /* 0250 */ int unknown_0250; /* 0254 */ unsigned char unknown_0254; /* 0255 */ unsigned char unknown_0255[3]; - /* 0258 */ std::vector unknown_0258[4]; + /* 0258 */ std::vector unknown_0258[4]; /* 0288 */ float unknown_0288; /* 028C */ std::uint32_t unknown_028C; /* 0290 */ unsigned char unknown_0290[12]; @@ -102,10 +92,10 @@ struct EffectPrimitiveState { /* 02CC */ float unknown_02CC; /* 02D0 */ float unknown_02D0; /* 02D4 */ float unknown_02D4; - /* 02D8 */ std::uint32_t unknown_02D8; + /* 02D8 */ float unknown_02D8; /* 02DC */ std::uint32_t unknown_02DC; /* 02E0 */ float unknown_02E0; - /* 02E4 */ std::uint32_t unknown_02E4; + /* 02E4 */ float unknown_02E4; /* 02E8 */ float unknown_02E8; /* 02EC */ std::uint32_t unknown_02EC; /* 02F0 */ std::uint32_t unknown_02F0; @@ -115,8 +105,8 @@ struct EffectPrimitiveState { /* 0300 */ std::uint32_t unknown_0300; /* 0304 */ std::uint32_t unknown_0304; /* 0308 */ std::uint32_t unknown_0308; - /* 030C */ std::uint32_t unknown_030C; - /* 0310 */ std::uint32_t unknown_0310; + /* 030C */ float unknown_030C; + /* 0310 */ float unknown_0310; /* 0314 */ float unknown_0314; /* 0318 */ float scale; /* 031C */ float unknown_031C; @@ -124,21 +114,21 @@ struct EffectPrimitiveState { /* 0324 */ float unknown_0324; /* 0328 */ float unknown_0328; /* 032C */ float unknown_032C; - /* 0330 */ std::uint32_t unknown_0330; - /* 0334 */ std::uint32_t unknown_0334; + /* 0330 */ float unknown_0330; + /* 0334 */ float unknown_0334; /* 0338 */ std::uint32_t unknown_0338; - /* 033C */ std::uint32_t unknown_033C; - /* 0340 */ std::uint32_t unknown_0340; + /* 033C */ float unknown_033C; + /* 0340 */ float unknown_0340; /* 0344 */ std::uint32_t unknown_0344; /* 0348 */ std::uint32_t unknown_0348; /* 034C */ float unknown_034C; /* 0350 */ float unknown_0350; /* 0354 */ float unknown_0354; /* 0358 */ float unknown_0358; - /* 035C */ std::uint32_t unknown_035C; + /* 035C */ float unknown_035C; /* 0360 */ float unknown_0360; /* 0364 */ float unknown_0364; - /* 0368 */ std::uint32_t unknown_0368; + /* 0368 */ float unknown_0368; /* 036C */ float unknown_036C; /* 0370 */ EffectVector3 unknown_0370; /* 037C */ EffectVector3 origin; diff --git a/Source/Contents/Effects/EffectTypes.cpp b/Source/Contents/Effects/EffectTypes.cpp new file mode 100644 index 0000000..38de808 --- /dev/null +++ b/Source/Contents/Effects/EffectTypes.cpp @@ -0,0 +1,325 @@ +#include "Contents/Effects/EffectTypes.h" + +#include + +namespace { + // STATIC: 0x016FDAC0 + // GLOBAL: gl_24388 + const std::unordered_map lifetimes = { + {0, 50}, {1, 50}, {2, 50}, {3, 50}, {4, 50}, {5, 50}, {6, 100}, {7, 50}, + {8, 80}, {9, 80}, {10, 100}, {11, 80}, {12, 40}, {13, 9999}, {14, 50}, {15, 100}, + {16, 40}, {17, 30}, {18, 50}, {19, 50}, {20, 100}, {21, 100}, {22, 270}, {23, 999}, + {24, 100}, {25, 40}, {26, 160}, {27, 150}, {28, 100}, {29, 200}, {30, 104}, {31, 160}, + {32, 100}, {33, 200}, {34, 100}, {35, 100}, {36, 100}, {37, 100}, {38, 100}, {39, 100}, + {40, 999}, {41, 999}, {42, 150}, {43, 100}, {44, 50}, {45, 100}, {46, 180}, {47, 250}, + {48, 130}, {49, 50}, {50, 50}, {51, 50}, {52, 40}, {53, 50}, {54, 40}, {55, 40}, + {56, 40}, {57, 40}, {58, 40}, {59, 40}, {60, 200}, {61, 250}, {62, 250}, {63, 250}, + {64, 999}, {65, 999}, {66, 999}, {67, 999}, {68, 999}, {69, 9999}, {70, 999}, {71, 250}, + {72, 500}, {73, 250}, {74, 250}, {75, 999}, {76, 999}, {77, 999}, {78, 999}, {79, 250}, + {80, 250}, {81, 250}, {82, 250}, {83, 999}, {84, 999}, {85, 999}, {86, 999}, {87, 999}, + {88, 999}, {89, 9999}, {90, 9999}, {91, 9999}, {92, 9999}, {93, 250}, {94, 250}, {95, 150}, + {96, 9999}, {97, 9999}, {98, 250}, {99, 250}, {100, 70}, {101, 9999}, {102, 9999}, {103, 999}, + {104, 999}, {105, 250}, {106, 9999}, {107, 9999}, {108, 9999}, {111, 9999}, {109, 9999}, {110, 9999}, + {112, 999}, {113, 9999}, {114, 350}, {115, 250}, {116, 250}, {117, 100}, {118, 250}, {119, 250}, + {120, 250}, {121, 40}, {122, 250}, {123, 250}, {124, 9999}, {125, 250}, {126, 9999}, {127, 9999}, + {128, 250}, {129, 9999}, {130, 9999}, {131, 9999}, {132, 250}, {133, 9999}, {134, 9999}, {135, 9999}, + {136, 80}, {137, 350}, {138, 8000}, {139, 9999}, {140, 250}, {141, 9999}, {142, 250}, {143, 999}, + {144, 999}, {145, 32797}, {146, 999}, {147, 999}, {148, 999}, {149, 999}, {150, 999}, {151, 999}, + {152, 100}, {153, 999}, {154, 999}, {155, 999}, {156, 999}, {157, 999}, {158, 999}, {159, 9999}, + {160, 9999}, {161, 0}, {162, 99999999}, {163, 99999999}, {164, 999999999}, {165, 1000}, {166, 9999}, {167, 999}, + {168, 999}, {169, 9999}, {170, 999}, {171, 9999}, {172, 100}, {173, 100}, {174, 100}, {175, 100}, + {176, 100}, {177, 100}, {178, 100}, {179, 100}, {180, 50}, {181, 9999}, {182, 9999}, {183, 9999}, + {184, 0}, {185, 9999}, {186, 9999}, {187, 9999}, {188, 9999}, {189, 9999}, {190, 9999}, {191, 9999}, + {192, 9999}, {193, 9999}, {194, 9999}, {195, 9999}, {196, 150}, {197, 9999}, {198, 0}, {199, 9999}, + {200, 99999999}, {201, 99999999}, {202, 99999999}, {203, 99999}, {204, 100}, {205, 100}, {206, 100}, {207, 100}, + {208, 100}, {209, 100}, {210, 100}, {211, 100}, {212, 500}, {213, 9999}, {214, 9999}, {215, 500}, + {216, 200}, {217, 200}, {218, 199}, {219, 199}, {220, 199}, {221, 150}, {222, 200}, {223, 300}, + {224, 300}, {225, 300}, {226, 999}, {227, 999}, {228, 999999}, {229, 99999999}, {230, 99999999}, {231, 999}, + {232, 99999}, {233, 99999999}, {234, 999}, {235, 999}, {236, 999}, {237, 999}, {238, 999}, {239, 29999}, + {240, 29999}, {241, 29999}, {242, 29999}, {243, 9999}, {244, 499}, {245, 499}, {246, 499}, {247, 999}, + {248, 200}, {249, 499}, {250, 9999}, {251, 150}, {252, 200}, {253, 100}, {254, 99999999}, {255, 999}, + {256, 999}, {257, 999}, {258, 999}, {259, 999}, {260, 999}, {261, 300}, {262, 300}, {263, 300}, + {264, 300}, {265, 300}, {266, 300}, {267, 16}, {268, 300}, {269, 300}, {270, 300}, {271, 300}, + {272, 300}, {273, 300}, {274, 300}, {275, 300}, {276, 300}, {277, 29999}, {278, 29999}, {279, 29999}, + {280, 29999}, {281, 29999}, {282, 29999}, {283, 29999}, {284, 29999}, {285, 29999}, {286, 29999}, {287, 29999}, + {288, 29999}, {289, 29999}, {290, 29999}, {291, 29999}, {292, 29999}, {293, 29999}, {294, 29999}, {295, 999}, + {296, 999}, {297, 99999999}, {298, 300}, {299, 300}, {300, 300}, {301, 99999999}, {302, 99999}, {303, 300}, + {304, 200}, {305, 90}, {306, 90}, {307, 36000}, {308, 200}, {309, 299}, {310, 300}, {311, 300}, + {312, 100}, {313, 100}, {314, 200}, {315, 9999}, {316, 200}, {317, 9999}, {318, 9999}, {319, 9999}, + {320, 100}, {321, 99999999}, {322, 36000}, {323, 36000}, {324, 36000}, {325, 100}, {326, 340}, {327, 340}, + {328, 1000}, {329, 100}, {330, 200}, {331, 300}, {332, 300}, {333, 99999999}, {334, 99999999}, {335, 99999999}, + {336, 200}, {337, 200}, {338, 200}, {339, 100}, {340, 3000}, {341, 9999}, {342, 1000}, {343, 1000}, + {344, 100}, {345, 99999999}, {346, 99999999}, {347, 9999}, {348, 1000}, {349, 99999999}, {350, 99999999}, {351, 99999999}, + {352, 99999999}, {353, 99999999}, {354, 99999999}, {355, 99999999}, {356, 99999999}, {357, 99999999}, {358, 4000}, {359, 4000}, + {360, 4000}, {361, 300}, {362, 99999999}, {363, 100}, {364, 100}, {365, 300}, {366, 200}, {367, 60}, + {368, 99999}, {369, 99999}, {370, 19999}, {371, 200}, {372, 200}, {373, 50}, {374, 29999}, {375, 99999}, + {376, 200}, {377, 200}, {378, 200}, {379, 200}, {380, 100}, {381, 99999999}, {382, 99999999}, {383, 200}, + {384, 200}, {385, 200}, {386, 250}, {387, 200}, {388, 200}, {389, 200}, {390, 250}, {391, 150}, + {392, 200}, {393, 200}, {394, 99999}, {395, 99999999}, {396, 99999999}, {397, 99999999}, {398, 99999999}, {399, 200}, + {400, 200}, {401, 200}, {402, 200}, {403, 100}, {404, 29999}, {405, 29999}, {406, 200}, {407, 200}, + {408, 200}, {409, 300}, {410, 300}, {411, 300}, {412, 300}, {413, 50}, {414, 50}, {415, 100}, + {416, 100}, {417, 100}, {418, 99999999}, {419, 99999999}, {420, 99999}, {421, 99999}, {422, 99999}, {423, 99999}, + {424, 99999999}, {425, 100}, {426, 14}, {427, 99999999}, {428, 200}, {429, 200}, {430, 200}, {431, 200}, + {432, 300}, {433, 300}, {434, 50}, {435, 100}, {436, 200}, {437, 3000}, {438, 100}, {439, 300}, + {440, 300}, {441, 60}, {442, 9999}, {443, 30}, {444, 100}, {445, 500}, {446, 35}, {447, 340}, + {448, 340}, {449, 60}, {450, 999}, {451, 100}, {452, 250}, {453, 99999}, {454, 60}, {455, 1500}, + {456, 100}, {457, 100}, {458, 35}, {459, 100}, {460, 100}, {461, 100}, {462, 200}, {463, 300}, + {464, 100}, {465, 1000}, {466, 50}, {467, 300}, {468, 300}, {469, 300}, {470, 300}, {471, 300}, + {472, 300}, {473, 300}, {474, 99999999}, {475, 99999999}, {476, 99999999}, {477, 99999999}, {478, 99999999}, {479, 99999999}, + {480, 99999999}, {481, 99999999}, {482, 99999999}, {483, 99999999}, {484, 99999999}, {485, 99999}, {486, 99999}, {487, 200}, + {488, 400}, {489, 400}, {490, 400}, {491, 100}, {492, 100}, {493, 120}, {494, 499}, {495, 300}, + {496, 200}, {497, 250}, {498, 250}, {499, 250}, {500, 120}, {501, 100}, {502, 200}, {503, 500}, + {504, 999999}, {505, 200}, {506, 100}, {507, 100}, {508, 100}, {509, 100}, {510, 1000}, {511, 10}, + {512, 300}, {513, 3000}, {514, 300}, {515, 99999999}, {516, 99999999}, {517, 29999}, {518, 200}, {519, 100}, + {520, 499}, {521, 120}, {522, 2000}, {523, 300}, {524, 300}, {525, 300}, {526, 300}, {527, 300}, + {528, 300}, {529, 300}, {530, 300}, {531, 300}, {532, 300}, {533, 300}, {534, 300}, {535, 300}, + {536, 300}, {537, 200}, {538, 120}, {539, 300}, {540, 50}, {541, 300}, {542, 200}, {543, 500}, + {544, 99999999}, {545, 200}, {546, 200}, {547, 200}, {548, 60}, {549, 60}, {550, 60}, {551, 100}, + {552, 100}, {553, 200}, {554, 200}, {555, 200}, {556, 50}, {557, 99999999}, {558, 99999999}, {559, 99999999}, + {560, 99999999}, {561, 2000}, {562, 99999999}, {563, 200}, {564, 60}, {565, 100}, {566, 100}, {567, 100}, + {568, 100}, {569, 60}, {570, 100}, {571, 100}, {572, 300}, {573, 300}, {574, 300}, {575, 300}, + {576, 100}, {577, 100}, {578, 100}, {579, 100}, {580, 100}, {581, 180}, {582, 200}, {583, 50}, + {584, 100}, {585, 100}, {586, 99999999}, {587, 100}, {588, 100}, {589, 100}, {590, 200}, {591, 200}, + {592, 99999999}, {593, 100}, {594, 100}, {595, 100}, {596, 100}, {597, 100}, {598, 100}, {599, 200}, + {600, 200}, {601, 999999}, {602, 60}, {603, 50}, {604, 99999}, {605, 2}, {606, 100}, {607, 100}, + {608, 100}, {609, 100}, {610, 100}, {611, 100}, {612, 100}, {613, 200}, {614, 200}, {615, 200}, + {616, 200}, {617, 9999}, {618, 300}, {619, 250}, {620, 29999}, {621, 200}, {622, 100}, {623, 300}, + {624, 200}, {625, 60}, {626, 60}, {627, 300}, {628, 200}, {629, 999999}, {630, 100}, {631, 100}, + {632, 100}, {633, 100}, {634, 23}, {635, 100}, {636, 100}, {637, 200}, {638, 23}, {639, 23}, + {640, 23}, {641, 23}, {642, 23}, {643, 100}, {644, 100}, {645, 100}, {646, 100}, {647, 100}, + {648, 100}, {649, 100}, {650, 99999999}, {651, 99999999}, {652, 50}, {653, 50}, {654, 50}, {655, 99999999}, + {656, 40}, {657, 50}, {658, 50}, {659, 50}, {660, 50}, {661, 50}, {662, 50}, {663, 50}, + {664, 50}, {665, 200}, {666, 100}, {667, 99999999}, {668, 28}, {669, 70}, {670, 28}, {671, 29999}, + {672, 29999}, {673, 99999999}, {674, 29999}, {675, 200}, {676, 300}, {677, 50}, {678, 99999999}, {679, 99999999}, + {680, 99999999}, {681, 36000}, {682, 100}, {683, 100}, {684, 100}, {685, 100}, {686, 100}, {687, 99999999}, + {688, 99999999}, {689, 99999999}, {690, 99999999}, {691, 99999999}, {692, 99999999}, {693, 99999999}, {694, 99999999}, {695, 99999999}, + {696, 99999999}, {697, 99999999}, {698, 99999999}, {699, 100}, {700, 36000}, {701, 99999999}, {702, 99999999}, {703, 99999999}, + {704, 100}, {705, 100}, {706, 100}, {707, 100}, {708, 9999}, {709, 70}, {710, 99999999}, {711, 99999999}, + {712, 99999999}, {713, 99999999}, {714, 99999999}, {715, 99999999}, {716, 360}, {717, 999}, {718, 90}, {719, 999}, + {720, 300}, {721, 100}, {722, 100}, {723, 100}, {724, 100}, {725, 250}, {726, 300}, {727, 100}, + {728, 100}, {729, 100}, {730, 100}, {731, 24}, {732, 100}, {733, 300}, {734, 100}, {735, 999999}, + {736, 999999}, {737, 999999}, {738, 999999}, {739, 23}, {740, 23}, {741, 23}, {742, 23}, {743, 23}, + {744, 99999999}, {745, 100}, {746, 100}, {747, 100}, {748, 100}, {749, 100}, {750, 999}, {751, 100}, + {752, 9999}, {753, 300}, {754, 9999}, {755, 99999999}, {756, 199}, {757, 99999999}, {758, 99999999}, {759, 99999999}, + {760, 99999999}, {761, 99999999}, {762, 99999999}, {763, 99999999}, {764, 99999999}, {765, 99999999}, {766, 99999999}, {767, 99999999}, + {768, 120}, {769, 200}, {770, 300}, {771, 300}, {772, 100}, {773, 300}, {774, 499}, {775, 100}, + {776, 100}, {777, 100}, {778, 250}, {779, 100}, {780, 250}, {781, 300}, {782, 200}, {783, 29999}, + {784, 29999}, {785, 300}, {786, 100}, {787, 200}, {788, 99999999}, {789, 99999999}, {790, 99999999}, {791, 200}, + {792, 9999}, {793, 100}, {794, 300}, {795, 999}, {796, 1999}, {797, 300}, {798, 999}, {799, 300}, + {800, 75}, {801, 150}, {802, 2999}, {803, 500}, {804, 600}, {805, 40}, {806, 100}, {807, 999}, + {808, 500}, {809, 99999999}, {810, 999}, {811, 200}, {812, 100}, {813, 100}, {814, 100}, {815, 100}, + {816, 100}, {817, 100}, {818, 100}, {819, 99999}, {820, 300}, {821, 99999999}, {822, 29999}, {823, 99999999}, + {824, 9999}, {825, 29999}, {826, 60}, {827, 29999}, {828, 29999}, {829, 29999}, {830, 100}, {831, 100}, + {832, 2000}, {833, 999999}, {834, 200}, {835, 300}, {836, 300}, {837, 60}, {838, 99999999}, {839, 99999999}, + {840, 100}, {841, 100}, {842, 100}, {843, 100}, {844, 100}, {845, 100}, {846, 99999999}, {847, 100}, + {848, 100}, {849, 500}, {850, 100}, {851, 300}, {852, 300}, {853, 400}, {854, 300}, {855, 300}, + {856, 29999}, {857, 1000}, {858, 300}, {859, 300}, {860, 29999}, {861, 400}, {862, 300}, {863, 300}, + {864, 100}, {865, 400}, {866, 400}, {867, 400}, {868, 400}, {869, 300}, {870, 400}, {871, 400}, + {872, 400}, {873, 400}, {874, 400}, {875, 400}, {876, 400}, {877, 400}, {878, 400}, {879, 99999999}, + {880, 99999999}, {881, 99999999}, {882, 500}, {883, 9999}, {884, 500}, {885, 200}, {886, 300}, {887, 200}, + {888, 150}, {889, 300}, {890, 100}, {891, 100}, {892, 100}, {893, 300}, {894, 200}, {895, 500}, + {896, 500}, {897, 500}, {898, 5000}, {899, 999}, {900, 5000}, {901, 500}, {902, 1000}, {903, 400}, + {904, 300}, {905, 200}, {906, 300}, {907, 300}, {908, 500}, {909, 500}, {910, 500}, {911, 60}, + {912, 1000}, {913, 100}, {914, 300}, {915, 200}, {916, 2000}, {917, 2000}, {918, 2000}, {919, 1000}, + {920, 40}, {921, 1000}, {922, 140}, {923, 500}, {924, 400}, {925, 9999}, {926, 32797}, {927, 140}, + {928, 200}, {929, 9999}, {930, 300}, {931, 500}, {932, 100}, {933, 99999999}, {934, 300}, {935, 100}, + {936, 300}, {937, 300}, {938, 300}, {939, 29999}, {940, 99999999}, {941, 500}, {942, 100}, {943, 2000}, + {944, 100}, {945, 99999999}, {946, 99999999}, {947, 100}, {948, 100}, {949, 100}, {950, 100}, {951, 100}, + {952, 100}, {953, 100}, {954, 100}, {955, 100}, {956, 100}, {957, 100}, {958, 100}, {959, 60}, + {960, 100}, {961, 100}, {962, 100}, {963, 99999}, {964, 40}, {965, 100}, {966, 100}, {967, 100}, + {968, 99999999}, {969, 200}, {970, 600}, {971, 600}, {972, 600}, {973, 600}, {974, 99999999}, {975, 40}, + {976, 99999999}, {977, 99999999}, {978, 99999999}, {979, 99999999}, {980, 99999999}, {981, 99999999}, {982, 99999999}, {983, 99999999}, + {984, 99999999}, {985, 99999999}, {986, 99999999}, {987, 100}, {988, 100}, {989, 99999999}, {990, 99999999}, {991, 99999999}, + {992, 99999999}, {993, 99999999}, {994, 99999999}, {995, 99999999}, {996, 99999999}, {997, 99999999}, {998, 99999999}, {999, 99999999}, + {1000, 99999999}, {1001, 99999999}, {1002, 99999999}, {1003, 99999999}, {1004, 99999999}, {1005, 99999999}, {1006, 100}, {1007, 99999999}, + {1008, 99999999}, {1009, 99999999}, {1010, 99999999}, {1011, 99999999}, {1012, 99999999}, {1013, 99999999}, {1014, 99999999}, {1015, 100}, + {1016, 90}, {1017, 100}, {1018, 100}, {1019, 200}, {1020, 100}, {1021, 20000}, {1022, 999}, {1023, 999}, + {1024, 999}, {1025, 999}, {1026, 999}, {1027, 999}, {1028, 999}, {1029, 40}, {1030, 5000}, {1031, 999}, + {1032, 999}, {1033, 999}, {1034, 999}, {1035, 999}, {1036, 999}, {1037, 99999}, {1038, 9999}, {1039, 999}, + {1040, 9999}, {1041, 999}, {1042, 100}, {1043, 999}, {1044, 999}, {1045, 99999999}, {1046, 999}, {1047, 999}, + {1048, 9999}, {1049, 999}, {1050, 999}, {1051, 999}, {1052, 200}, {1053, 999}, {1054, 9999}, {1055, 9999}, + {1056, 9999}, {1057, 9999}, {1058, 9999}, {1059, 350}, {1060, 9999}, {1061, 9999}, {1062, 9999}, {1063, 9999}, + {1064, 9}, {1065, 9999}, {1066, 9999}, {1067, 9999}, {1068, 9999}, {1069, 9999}, {1070, 9999}, {1071, 9999}, + {1072, 30}, {1073, 9999}, {1074, 9999}, {1075, 9999}, {1076, 9999}, {1077, 9999}, {1078, 9999}, {1079, 999}, + {1080, 9999}, {1081, 9999}, {1082, 300}, {1083, 999}, {1084, 999}, {1085, 999}, {1086, 999}, {1087, 999}, + {1088, 2000}, {1089, 999}, {1090, 9999}, {1091, 999}, {1092, 999}, {1093, 999}, {1094, 999}, {1095, 999}, + {1096, 1096}, {1097, 1097}, {1098, 1098}, {1099, 1099}, {1100, 1100}, {1101, 1101}, {1102, 1102}, {1103, 1103}, + {1104, 1104}, {1105, 1105}, {1106, 1106}, {1107, 1107}, {1108, 1108}, {1109, 1109}, {1110, 9999}, {1111, 1111}, + {1112, 1112}, {1113, 100}, {1114, 1114}, {1115, 99999999}, {1116, 1116}, {1117, 1117}, {1118, 1118}, {1119, 1119}, + {1120, 1120}, {1121, 1121}, {1122, 99999999}, {1123, 1123}, {1124, 1124}, {1125, 1125}, {1126, 1126}, {1127, 1127}, + {1128, 1128}, {1129, 1129}, {1130, 1130}, {1131, 99}, {1132, 99999999}, {1133, 1133}, {1134, 1134}, {1135, 99999999}, + {1136, 1136}, {1137, 1137}, {1138, 1138}, {1139, 1139}, {1140, 1140}, {1141, 1141}, {1142, 1142}, {1143, 100}, + {1144, 100}, {1145, 99999999}, {1146, 1146}, {1147, 99999999}, {1148, 9999999}, {1149, 99999}, {1150, 300}, {1151, 1151}, + {1152, 1152}, {1153, 1153}, {1154, 1154}, {1155, 1155}, {1156, 1156}, {1157, 1157}, {1158, 1158}, {1159, 1159}, + {1160, 1160}, {1161, 150}, {1162, 9999}, {1163, 9999}, {1164, 99999999}, {1165, 99999999}, {1166, 99999999}, {1167, 99999999}, + {1168, 99999999}, {1169, 99999999}, {1170, 99999999}, {1171, 99999999}, {1172, 99999999}, {1173, 99999999}, {1174, 99999999}, {1175, 99999999}, + {1176, 99999999}, {1177, 99999999}, {1178, 99999999}, {1179, 99999999}, {1180, 99999999}, {1181, 99999999}, {1182, 99999999}, {1183, 99999999}, + {1184, 1184}, {1185, 99999999}, {1186, 1186}, {1187, 1187}, {1188, 1188}, {1189, 1189}, {1190, 1190}, {1191, 1191}, + {1192, 1192}, {1193, 1193}, {1194, 1194}, {1195, 1195}, {1196, 1196}, {1197, 1197}, {1198, 1198}, {1199, 1199}, + {1200, 1200}, {1201, 1201}, {1202, 1202}, {1203, 1203}, {1204, 100}, {1205, 100}, {1206, 200}, {1207, 200}, + {1208, 200}, {1209, 100}, {1210, 200}, {1211, 1211}, {1212, 1212}, {1213, 1213}, {1214, 1214}, {1215, 1215}, + {1216, 1216}, {1217, 1217}, {1218, 1218}, {1219, 1219}, {1220, 1220}, {1221, 1221}, {1222, 1222}, {1223, 1223}, + {1224, 50}, {1225, 1225}, {1226, 1226}, {1227, 1227}, {1228, 1228}, {1229, 1229}, {1230, 1230}, {1231, 1231}, + {1232, 1232}, {1233, 1233}, {1234, 1234}, {1235, 1235}, {1236, 1236}, {1237, 1237}, {1238, 1238}, {1239, 1239}, + {1240, 1240}, {1241, 1241}, {1242, 1242}, {1243, 1243}, {1244, 1244}, {1245, 1245}, {1246, 1246}, {1247, 1247}, + {1248, 1248}, {1249, 1249}, {1250, 1250}, {1251, 1251}, {1252, 1252}, {1253, 1253}, {1254, 1254}, {1255, 1255}, + {1256, 1256}, {1257, 1257}, {1258, 1258}, {1259, 1259}, {1260, 1260}, {1261, 1261}, {1262, 1262}, {1263, 1263}, + {1264, 1264}, {1265, 1265}, {1266, 1266}, {1267, 1267}, {1268, 1268}, {1269, 1269}, {1270, 1270}, {1271, 1271}, + {1272, 1272}, {1273, 1273}, {1274, 1274}, {1275, 1275}, {1276, 1276}, {1277, 1277}, {1278, 1278}, {1279, 1279}, + {1280, 1280}, {1281, 1281}, {1282, 1282}, {1283, 1283}, {1284, 1284}, {1285, 1285}, {1286, 1286}, {1287, 1287}, + {1288, 1288}, {1289, 1289}, {1290, 1290}, {1291, 99999999}, {1292, 99999999}, {1293, 1293}, {1294, 1294}, {1295, 1295}, + {1296, 1296}, {1297, 1297}, {1298, 1298}, {1299, 1299}, {1300, 1300}, {1301, 1301}, {1302, 1302}, {1303, 1303}, + {1304, 1304}, {1305, 1305}, {1306, 1306}, {1307, 1307}, {1308, 1308}, {1309, 1309}, {1310, 1310}, {1311, 1311}, + {1312, 1312}, {1313, 1313}, {1314, 1314}, {1315, 1315}, {1316, 1316}, {1317, 1317}, {1318, 1318}, {1319, 1319}, + {1320, 1320}, {1321, 1321}, {1322, 1322}, {1323, 1323}, {1324, 1324}, {1325, 99999999}, {1326, 99999999}, {1327, 99999999}, + {1328, 99999999}, {1329, 99999999}, {1330, 99999999}, {1331, 99999999}, {1332, 99999999}, {1333, 99999999}, {1334, 99999999}, {1335, 99999999}, + {1336, 99999999}, {1337, 99999999}, {1338, 99999999}, {1339, 99999999}, {1340, 99999999}, {1341, 99999999}, {1342, 99999999}, {1343, 99999999}, + {1344, 99999999}, {1345, 99999999}, {1346, 99999999}, {1347, 1347}, {1348, 1348}, {1349, 1349}, {1350, 1350}, {1351, 1351}, + {1352, 1352}, {1353, 1353}, {1354, 1354}, {1355, 1355}, {1356, 1356}, {1357, 1357}, {1358, 1358}, {1359, 1359}, + {1360, 1360}, {1361, 1361}, {1362, 1362}, {1363, 1363}, {1364, 1364}, {1365, 50}, {1366, 1366}, {1367, 1367}, + {1368, 1368}, {1369, 1369}, {1370, 1370}, {1371, 1371}, {1372, 1372}, {1373, 1373}, {1374, 1374}, {1375, 1375}, + {1376, 1376}, {1377, 99999999}, {1378, 1378}, {1379, 1379}, {1380, 1380}, {1381, 1381}, {1382, 1382}, {1383, 1383}, + {1384, 1384}, {1385, 1385}, {1386, 1386}, {1387, 1387}, {1388, 1388}, {1389, 1389}, {1390, 1390}, {1391, 1391}, + {1392, 1392}, {1393, 1393}, {1394, 1394}, {1395, 1395}, {1396, 1396}, {1397, 1397}, {1398, 99999999}, {1399, 75}, + {1400, 1400}, {1401, 1401}, {1402, 1402}, {1403, 1403}, {1404, 1404}, {1405, 1405}, {1406, 1406}, {1407, 1407}, + {1408, 1408}, {1409, 300}, {1410, 1410}, {1411, 1411}, {1412, 1412}, {1413, 1413}, {1414, 1414}, {1415, 1415}, + {1416, 1416}, {1417, 1417}, {1418, 1418}, {1419, 1419}, {1420, 99999999}, {1421, 1421}, {1422, 1422}, {1423, 1423}, + {1424, 1424}, {1425, 1425}, {1426, 1426}, {1427, 1427}, {1428, 1428}, {1429, 1429}, {1430, 1430}, {1431, 1431}, + {1432, 1432}, {1433, 1433}, {1434, 1434}, {1435, 1435}, {1436, 1436}, {1437, 1437}, {1438, 1438}, {1439, 1439}, + {1440, 1440}, {1441, 1441}, {1442, 1442}, {1443, 1443}, {1444, 1444}, {1445, 1445}, {1446, 1446}, {1447, 1447}, + {1448, 1448}, {1449, 1449}, {1450, 1450}, {1451, 1451}, {1452, 1452}, {1453, 1453}, {1454, 1454}, {1455, 1455}, + {1456, 1456}, {1457, 1457}, {1458, 1458}, {1459, 1459}, {1460, 1460}, {1461, 1461}, {1462, 1462}, {1463, 1463}, + {1464, 1464}, {1465, 1465}, {1466, 1466}, {1467, 1467}, {1468, 1468}, {1469, 1469}, {1470, 1470}, {1471, 1471}, + {1472, 1472}, {1473, 1473}, {1474, 1474}, {1475, 1475}, {1476, 1476}, {1477, 1477}, {1478, 1478}, {1479, 1479}, + {1480, 1480}, {1481, 1481}, {1482, 1482}, {1483, 1483}, {1484, 1484}, {1485, 1485}, {1486, 1486}, {1487, 1487}, + {1488, 1488}, {1489, 1489}, {1490, 1490}, {1491, 1491}, {1492, 1492}, {1493, 1493}, {1494, 1494}, {1495, 1495}, + {1496, 1496}, {1497, 1497}, {1498, 1498}, {1499, 1499}, {1500, 1500}, {1501, 1501}, {1502, 1502}, {1503, 1503}, + {1504, 1504}, {1505, 1505}, {1506, 1506}, {1507, 1507}, {1508, 1508}, {1509, 1509}, {1510, 1510}, {1511, 1511}, + {1512, 1512}, {1513, 1513}, {1514, 1514}, {1515, 1515}, {1516, 1516}, {1517, 1517}, {1518, 1518}, {1519, 1519}, + {1520, 1520}, {1521, 1521}, {1522, 1522}, {1523, 1523}, {1524, 1524}, {1525, 99999999}, {1526, 1526}, {1527, 1527}, + {1528, 1528}, {1529, 1529}, {1530, 1530}, {1531, 99999999}, {1532, 1532}, {1533, 1533}, {1534, 1534}, {1535, 1535}, + {1536, 1536}, {1537, 1537}, {1538, 1538}, {1539, 1539}, {1540, 1540}, {1541, 1541}, {1542, 1542}, {1543, 1543}, + {1544, 1544}, {1545, 300}, {1546, 1546}, {1547, 1547}, {1548, 1548}, {1549, 1549}, {1550, 1550}, {1551, 1551}, + {1552, 1552}, {1553, 1553}, {1554, 1554}, {1555, 1555}, {1556, 60}, {1557, 1557}, {1558, 1558}, {1559, 1559}, + {1560, 40}, {1561, 1561}, {1562, 1562}, {1563, 1563}, {1564, 1564}, {1565, 40}, {1566, 1566}, {1567, 1567}, + {1568, 300}, {1569, 150}, {1570, 1570}, {1571, 1571}, {1572, 1572}, {1573, 1573}, {1574, 1574}, {1575, 300}, + {1576, 1576}, {1577, 1577}, {1578, 1578}, {1579, 1579}, {1580, 1580}, {1581, 1581}, {1582, 1582}, {1583, 1583}, + {1584, 300}, {1585, 1585}, {1586, 1586}, {1587, 1587}, {1588, 1588}, {1589, 1589}, {1590, 1590}, {1591, 1591}, + {1592, 1592}, {1593, 1593}, {1594, 200}, {1595, 1595}, {1596, 1596}, {1597, 1597}, {1598, 1598}, {1599, 1599}, + {1600, 200}, {1601, 99999999}, {1602, 9999}, {1603, 9999}, {1604, 9999}, {1605, 9999}, {1606, 9999}, {1607, 1607}, + {1608, 1608}, {1609, 1609}, {1610, 99999999}, {1611, 1611}, {1612, 1612}, {1613, 1613}, {1614, 1614}, {1615, 1615}, + {1616, 1616}, {1617, 1617}, {1618, 1618}, {1619, 1619}, {1620, 1620}, {1621, 1621}, {1622, 1622}, {1623, 1623}, + {1624, 1624}, {1625, 1625}, {1626, 1626}, {1627, 1627}, {1628, 1628}, {1629, 1629}, {1630, 1630}, {1631, 1631}, + {1632, 1632}, {1633, 1633}, {1634, 1634}, {1635, 1635}, {1636, 1636}, {1637, 1637}, {1638, 1638}, {1639, 1639}, + {1640, 1640}, {1641, 1641}, {1642, 1642}, {1643, 1643}, {1644, 1644}, {1645, 1645}, {1646, 1646}, {1647, 1647}, + {1648, 1648}, {1649, 1649}, {1650, 1650}, {1651, 1651}, {1652, 1652}, {1653, 1653}, {1654, 1654}, {1655, 99999999}, + {1656, 100}, {1657, 1657}, {1658, 1658}, {1659, 1659}, {1660, 1660}, {1661, 1661}, {1662, 1662}, {1663, 1663}, + {1664, 100}, {1665, 1665}, {1666, 1666}, {1667, 1667}, {1668, 1668}, {1669, 1669}, {1670, 1670}, {1671, 1671}, + {1672, 1672}, {1673, 1673}, {1674, 1674}, {1675, 1675}, {1676, 1676}, {1677, 60}, {1678, 1678}, {1679, 1679}, + {1680, 1680}, {1681, 1681}, {1682, 1682}, {1683, 1683}, {1684, 1684}, {1685, 1685}, {1686, 1686}, {1687, 1687}, + {1688, 1688}, {1689, 1689}, {1690, 1690}, {1691, 1691}, {1692, 1692}, {1693, 1693}, {1694, 1694}, {1695, 1695}, + {1696, 1696}, {1697, 1697}, {1698, 1698}, {1699, 1699}, {1700, 1700}, {1701, 1701}, {1702, 1702}, {1703, 1703}, + {1704, 1704}, {1705, 1705}, {1706, 1706}, {1707, 1707}, {1708, 1708}, {1709, 40}, {1710, 1710}, {1711, 1711}, + {1712, 1712}, {1713, 1713}, {1714, 1714}, {1715, 1715}, {1716, 1716}, {1717, 1717}, {1718, 1718}, {1719, 1719}, + {1720, 1720}, {1721, 1721}, {1722, 1722}, {1723, 1723}, {1724, 1724}, {1725, 1725}, {1726, 1726}, {1727, 1727}, + {1728, 1728}, {1729, 1729}, {1730, 1730}, {1731, 1731}, {1732, 1732}, {1733, 1733}, {1734, 1734}, {1735, 1735}, + {1736, 1736}, {1737, 1737}, {1738, 1738}, {1739, 1739}, {1740, 1740}, {1741, 1741}, {1742, 1742}, {1743, 1743}, + {1744, 1744}, {1745, 1745}, {1746, 1746}, {1747, 1747}, {1748, 1748}, {1749, 1749}, {1750, 1750}, {1751, 1751}, + {1752, 1752}, {1753, 1753}, {1754, 1754}, {1755, 1755}, {1756, 1756}, {1757, 1757}, {1758, 1758}, {1759, 1759}, + {1760, 1760}, {1761, 1761}, {1762, 1762}, {1763, 1763}, {1764, 1764}, {1765, 1765}, {1766, 1766}, {1767, 1767}, + {1768, 1768}, {1769, 1769}, {1770, 1770}, {1771, 1771}, {1772, 1772}, {1773, 1773}, {1774, 1774}, {1775, 1775}, + {1776, 1776}, {1777, 1777}, {1778, 1778}, {1779, 1779}, {1780, 1780}, {1781, 1781}, {1782, 1782}, {1783, 1783}, + {1784, 1784}, {1785, 1785}, {1786, 1786}, {1787, 1787}, {1788, 1788}, {1789, 1789}, {1790, 1790}, {1791, 1791}, + {1792, 1792}, {1793, 1793}, {1794, 1794}, {1795, 1795}, {1796, 1796}, {1797, 1797}, {1798, 1798}, {1799, 1799}, + {1800, 1800}, {1801, 1801}, {1802, 1802}, {1803, 1803}, {1804, 1804}, {1805, 1805}, {1806, 1806}, {1807, 1807}, + {1808, 1808}, {1809, 1809}, {1810, 1810}, {1811, 1811}, {1812, 1812}, {1813, 1813}, {1814, 1814}, {1815, 1815}, + {1816, 1816}, {1817, 1817}, {1818, 1818}, {1819, 1819}, {1820, 1820}, {1821, 1821}, {1822, 1822}, {1823, 1823}, + {1824, 1824}, {1825, 1825}, {1826, 1826}, {1827, 1827}, {1828, 1828}, {1829, 1829}, {1830, 1830}, {1831, 1831}, + {1832, 1832}, {1833, 1833}, {1834, 1834}, {1835, 1835}, {1836, 1836}, {1837, 1837}, {1838, 1838}, {1839, 1839}, + {1840, 1840}, {1841, 1841}, {1842, 1842}, {1843, 1843}, {1844, 1844}, {1845, 1845}, {1846, 1846}, {1847, 1847}, + {1848, 1848}, {1849, 1849}, {1850, 1850}, {1851, 1851}, {1852, 1852}, {1853, 1853}, {1854, 1854}, {1855, 1855}, + {1856, 1856}, {1857, 1857}, {1858, 1858}, {1859, 1859}, {1860, 1860}, {1861, 1861}, {1862, 1862}, {1863, 1863}, + {1864, 1864}, {1865, 1865}, {1866, 1866}, {1867, 1867}, {1868, 1868}, {1869, 1869}, {1870, 1870}, {1871, 1871}, + {1872, 1872}, {1873, 1873}, {1874, 1874}, {1875, 1875}, {1876, 1876}, {1877, 1877}, {1878, 1878}, {1879, 1879}, + {1880, 1880}, {1881, 1881}, {1882, 1882}, {1883, 1883}, {1884, 1884}, {1885, 1885}, {1886, 1886}, {1887, 1887}, + {1888, 1888}, {1889, 1889}, {1890, 1890}, {1891, 1891}, {1892, 1892}, {1893, 1893}, {1894, 1894}, {1895, 1895}, + {1896, 1896}, {1897, 1897}, {1898, 1898}, {1899, 1899}, {1900, 1900}, {1901, 1901}, {1902, 1902}, {1903, 1903}, + {1904, 1904}, {1905, 1905}, {1906, 1906}, {1907, 1907}, {1908, 1908}, {1909, 1909}, {1910, 1910}, {1911, 1911}, + {1912, 1912}, {1913, 1913}, {1914, 1914}, {1915, 1915}, {1916, 1916}, {1917, 1917}, {1918, 1918}, {1919, 1919}, + {1920, 1920}, {1921, 1921}, {1922, 1922}, {1923, 1923}, {1924, 1924}, {1925, 1925}, {1926, 1926}, {1927, 1927}, + {1928, 1928}, {1929, 1929}, {1930, 1930}, {1931, 1931}, {1932, 1932}, {1933, 1933}, {1934, 1934}, {1935, 1935}, + {1936, 1936}, {1937, 1937}, {1938, 1938}, {1939, 1939}, {1940, 1940}, {1941, 1941}, {1942, 1942}, {1943, 1943}, + {1944, 1944}, {1945, 1945}, {1946, 1946}, {1947, 1947}, {1948, 1948}, {1949, 1949}, {1950, 1950}, {1951, 1951}, + {1952, 1952}, {1953, 1953}, {1954, 1954}, {1955, 1955}, {1956, 1956}, {1957, 1957}, {1958, 1958}, {1959, 1959}, + {1960, 1960}, {1961, 1961}, {1962, 1962}, {1963, 1963}, {1964, 1964}, {1965, 1965}, {1966, 1966}, {1967, 1967}, + {1968, 1968}, {1969, 1969}, {1970, 1970}, {1971, 1971}, {1972, 1972}, {1973, 120}, {1974, 1974}, {1975, 1975}, + {1976, 1976}, {1977, 1977}, {1978, 1978}, {1979, 1979}, {1980, 1980}, {1981, 1981}, {1982, 1982}, {1983, 1983}, + {1984, 1984}, {1985, 1985}, {1986, 1986}, {1987, 1987}, {1988, 1988}, {1989, 1989}, {1990, 1990}, {1991, 1991}, + {1992, 1992}, {1993, 1993}, {1994, 1994}, {1995, 1995}, {1996, 1996}, {1997, 1997}, {1998, 1998}, {1999, 1999}, + {2000, 2000}, {2001, 2001}, {2002, 2002}, {2003, 2003}, {2004, 2004}, {2005, 2005}, {2006, 2006}, {2007, 2007}, + {2008, 2008}, {2009, 2009}, {2010, 2010}, {2011, 2011}, {2012, 2012}, {2013, 2013}, {2014, 2014}, {2015, 2015}, + {2016, 2016}, {2017, 2017}, {2018, 2018}, {2019, 2019}, {2020, 2020}, {2021, 2021}, {2022, 2022}, {2023, 2023}, + {2024, 2024}, {2025, 2025}, {2026, 60}, {2027, 60}, {2028, 2028}, {2029, 2029}, {2030, 2030}, {2031, 2031}, + {2032, 2032}, {2033, 2033}, {2034, 2034}, {2035, 2035}, {2036, 2036}, {2037, 2037}, {2038, 2038}, {2039, 2039}, + {2040, 2040}, {2041, 2041}, {2042, 2042}, {2043, 2043}, {2044, 2044}, {2045, 2045}, {2046, 2046}, {2047, 2047}, + {2048, 2048}, {2049, 2049}, {2050, 2050}, {2051, 2051}, {2052, 2052}, {2053, 2053}, {2054, 2054}, {2055, 2055}, + {2056, 2056}, {2057, 2057}, {2058, 2058}, {2059, 2059}, {2060, 2060}, {2061, 2061}, {2062, 2062}, {2063, 2063}, + {2064, 2064}, {2065, 2065}, {2066, 2066}, {2067, 2067}, {2068, 2068}, {2069, 2069}, {2070, 2070}, {2071, 2071}, + {2072, 2072}, {2073, 2073}, {2074, 2074}, {2075, 2075}, {2076, 2076}, {2077, 2077}, {2078, 2078}, {2079, 2079}, + {2080, 2080}, {2081, 2081}, {2082, 2082}, {2083, 2083}, {2084, 2084}, {2085, 2085}, {2086, 2086}, {2087, 2087}, + {2088, 2088}, {2089, 2089}, {2090, 2090}, {2091, 2091}, {2092, 2092}, {2093, 2093}, {2094, 2094}, {2095, 2095}, + {2096, 2096}, {2097, 2094}, {2098, 2098}, {2099, 2099}, {2100, 2100}, {2101, 2101}, {2102, 2102}, {2103, 2103}, + {2104, 2104}, {2105, 2105}, {2106, 2106}, {2107, 2107}, {2108, 2108}, {2109, 2109}, {2110, 2110}, {2111, 2111}, + {2112, 2095}, {2113, 2096}, {2114, 2114}, {2115, 2115}, {2116, 2116}, {2117, 2117}, {2118, 2118}, {2119, 2119}, + {2120, 2120}, {2121, 2121}, {2122, 2122}, {2123, 2123}, {2124, 2124}, {2125, 2125}, {2126, 2126}, {2127, 2127}, + {2128, 2128}, {2129, 2129}, {2130, 2130}, {2131, 2131}, {2132, 2132}, {2133, 2133}, {2134, 2134}, {2135, 2135}, + {2136, 2136}, {2137, 2137}, {2138, 2138}, {2139, 2139}, {2140, 2140}, {2141, 2141}, {2142, 2142}, {2143, 2143}, + {2144, 2144}, {2145, 2145}, {2146, 2146}, {2147, 2147}, {2148, 2148}, {2149, 2149}, {2150, 2150}, {2151, 2151}, + {2152, 2152}, {2153, 2153}, {2154, 2154}, {2155, 2155}, {2156, 2156}, {2157, 2157}, {2158, 2158}, {2159, 2159}, + {2160, 2160}, {2161, 2161}, {2162, 2162}, {2163, 2163}, {2164, 2164}, {2165, 2165}, {2166, 2166}, {2167, 2167}, + {2168, 2168}, {2169, 2169}, {2170, 2170}, {2171, 2171}, {2172, 2172}, {2173, 2173}, {2174, 2174}, {2175, 2175}, + {2176, 2176}, {2177, 2177}, {2178, 2178}, {2179, 2179}, {2180, 2180}, {2181, 2181}, {2182, 2182}, {2183, 2183}, + {2184, 2184}, {2185, 2185}, {2186, 2186}, {2187, 2187}, {2188, 2188}, {2189, 2189}, {2190, 2190}, {2191, 2191}, + {2192, 2192}, {2193, 2193}, {2194, 2194}, {2195, 2195}, {2196, 2196}, {2197, 2197}, {2198, 2198}, {2199, 2199}, + {2200, 2200}, {2201, 2201}, {2202, 2202}, {2203, 2203}, {2204, 2204}, {2205, 2205}, {2206, 2206}, {2207, 2207}, + {2208, 2208}, {2209, 2209}, {2210, 2210}, {2211, 2211}, {2212, 2212}, {2213, 2213}, {2214, 2214}, {2215, 2215}, + {2216, 2216}, {2217, 2217}, {2218, 2218}, {2219, 2219}, {2220, 2220}, {2221, 2221}, {2222, 2222}, {2223, 2223}, + {2224, 2224}, {2225, 2225}, {2226, 2226}, {2227, 2227}, {2228, 2228}, {2229, 2229}, {2230, 2230}, {2231, 2231}, + {2232, 2232}, {2233, 2233}, {2234, 2234}, {2235, 2235}, {2236, 2236}, {2237, 2237}, {2238, 2238}, {2239, 2239}, + {2240, 2240}, {2241, 2241}, {2242, 2242}, {2243, 2243}, {2244, 2244}, {2245, 2245}, {2246, 2246}, {2247, 2247}, + {2248, 2248}, {2249, 2249}, {2250, 2250}, {2251, 2251}, {2252, 2252}, {2253, 2253}, {2254, 2254}, {2255, 2255}, + {2256, 2256}, {2257, 2257}, {2258, 2258}, {2259, 2259}, {2260, 2260}, {2261, 2261}, {2262, 2262}, {2263, 2263}, + {2264, 2264}, {2265, 2265}, {2266, 2266}, {2267, 2267}, {2268, 2268}, {2269, 2269}, {2270, 2270}, {2271, 2271}, + {2272, 2272}, {2273, 2273}, {2274, 2274}, {2275, 2275}, {2276, 2276}, {2277, 99999}, {2278, 99999}, {2279, 2279}, + {2280, 2280}, {2281, 2281}, {2282, 2281}, {2283, 2282}, {2284, 2283}, {2285, 2284}, {2286, 2285}, {2287, 2286}, + {2288, 100}, {2289, 100}, {2290, 100}, {2291, 100}, {2292, 100}, {2293, 100}, {2294, 100}, {2295, 100}, + {2296, 100}, {2297, 100}, {2298, 100}, {2299, 100}, {2300, 100}, {2301, 2301}, {2302, 2302}, {2303, 2303}, + {2304, 2304}, {2305, 2305}, {2306, 2306}, {2307, 2307}, {2308, 2308}, {2309, 99999999}, {2310, 99999999}, {2311, 2311}, + {2312, 2312}, {2313, 2313}, {2314, 2314}, {2315, 2315}, {2316, 2316}, {2317, 2317}, {2318, 2318}, {2319, 2319}, + {2320, 2320}, {2321, 2321}, {2322, 2322}, {2323, 2323}, {2324, 2324}, {2325, 2325}, {2326, 2326}, {2327, 2327}, + {2328, 2328}, {2329, 2329}, {2330, 2330}, {2331, 2331}, {2332, 2332}, {2333, 2333}, {2334, 2334}, {2335, 2335}, + {2336, 2336}, {2337, 2337}, {2338, 70}, {2339, 2339}, {2340, 2340}, {2341, 2341}, {2342, 2342}, {2343, 2343}, + {2344, 2344}, {2345, 2345}, {2346, 99999999}, {2347, 99999999}, {2348, 2348}, {2349, 2349}, {2350, 2350}, {2351, 2351}, + {2352, 2352}, {2353, 2353}, {2354, 2354}, {2355, 2355}, {2356, 99999999}, {2357, 99999999}, {2358, 99999999}, {2359, 99999999}, + {2360, 99999999}, {2361, 99999999}, {2362, 99999999}, {2363, 99999999}, {2364, 99999999}, {2365, 99999999}, {2366, 2366}, {2367, 40}, + {2368, 100}, {2369, 40}, {2370, 2370}, {2371, 2371}, {2372, 2372}, {2373, 300}, {2374, 99999999}, {2375, 99999999}, + {2376, 2376}, {2377, 2377}, {2378, 2378}, {2379, 2379}, {2380, 2380}, {2381, 2381}, {2382, 2382}, {2383, 2383}, + {2384, 2384}, {2385, 2385}, {2386, 2386}, {2387, 2387}, {2388, 2388}, {2389, 2389}, {2390, 999999}, {2391, 999999}, + {2392, 999999}, {2393, 999999}, {2394, 2394}, {2395, 2395}, {2396, 2396}, {2397, 2397}, {2398, 2398}, {2399, 2399}, + {2401, 2415}, {2402, 99999999}, {2413, 99999999}, {2414, 99999999}, {2415, 99999999}, {2416, 300}, {2417, 300}, {2418, 2418}, + {2419, 2419}, {2421, 2421}, {2422, 2422}, {2423, 2423}, {2425, 250}, {2426, 100}, {2427, 100}, {2432, 2432}, + {2433, 2433}, {2434, 2434}, {2435, 300}, {2436, 3000}, {2437, 3000}, {2438, 2438}, {2439, 300}, {2440, 99999999}, + {2441, 300}, {2442, 300}, {2443, 99999999}, {2444, 500}, {2445, 2435}, {2446, 2436}, {2447, 40}, {2448, 40}, + {2449, 2438}, {2450, 40}, {2451, 9999}, {2452, 999}, {2453, 2000}, {2454, 40}, {2455, 499}, {2456, 9999}, + {2457, 40}, {2463, 100}, {2464, 100}, {2465, 100}, {2466, 1000}, {2468, 300}, {2469, 40}, {2470, 250}, + {2471, 29999}, {2472, 9999}, {2473, 9999}, {2474, 100}, {2477, 250}, {2478, 100}, {2479, 999}, {2480, 499}, + {2481, 200}, {2482, 99999999}, {2483, 99999999}, + }; +} + +// OFFSET: 0x00C16440 +// FUNCTION: fn_20056 +int EffectLifetime(int id) { + const auto found = lifetimes.find(id); + return found == lifetimes.end() ? 0 : found->second; +} diff --git a/Source/Contents/Effects/EffectTypes.h b/Source/Contents/Effects/EffectTypes.h new file mode 100644 index 0000000..d0ca0a1 --- /dev/null +++ b/Source/Contents/Effects/EffectTypes.h @@ -0,0 +1,6 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTTYPES_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTTYPES_H + +int EffectLifetime(int id); + +#endif diff --git a/Source/Contents/EffectVisibility.cpp b/Source/Contents/Effects/EffectVisibility.cpp similarity index 76% rename from Source/Contents/EffectVisibility.cpp rename to Source/Contents/Effects/EffectVisibility.cpp index 2010fab..2c63239 100644 --- a/Source/Contents/EffectVisibility.cpp +++ b/Source/Contents/Effects/EffectVisibility.cpp @@ -1,7 +1,7 @@ -#include "Contents/EffectActor.h" -#include "Contents/EffectVisibility.h" -#include "Contents/RagEffectState.h" -#include "Contents/ServiceOptions.h" +#include "Contents/Effects/EffectActor.h" +#include "Contents/Effects/EffectVisibility.h" +#include "Contents/Effects/RagEffectState.h" +#include "Contents/Configuration/ServiceOptions.h" // OFFSET: 0x00C734B0 // FUNCTION: fn_20327 @@ -28,7 +28,6 @@ bool PartyEffectVisible(const RagEffectState& effect, const EffectVisibilityCont if (context.partyVisible) { for (const MessengerMember& member : context.party) { if (member.accountId == actor->render.accountId) { - // Original membership helper stops at the first match. if (member.offline == 0) { return true; } @@ -39,6 +38,5 @@ bool PartyEffectVisible(const RagEffectState& effect, const EffectVisibilityCont } } - // Independent of the membership gate. return actor->render.visible != 0 && actor->render.enabled != 0; } diff --git a/Source/Contents/EffectVisibility.h b/Source/Contents/Effects/EffectVisibility.h similarity index 63% rename from Source/Contents/EffectVisibility.h rename to Source/Contents/Effects/EffectVisibility.h index 960b4cb..1937ade 100644 --- a/Source/Contents/EffectVisibility.h +++ b/Source/Contents/Effects/EffectVisibility.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTVISIBILITY_H -#define RAGNAROK_SOURCE_CONTENTS_EFFECTVISIBILITY_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTVISIBILITY_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_EFFECTVISIBILITY_H -#include "Contents/MessengerMember.h" +#include "Contents/Messenger/MessengerMember.h" #include @@ -15,7 +15,6 @@ struct EffectVisibilityContext { const std::list& party; }; -// Id-160 path. Other ids may consult additional actors. bool PartyEffectVisible(const RagEffectState& effect, const EffectVisibilityContext& context); #endif diff --git a/Source/Contents/PartyEffect.cpp b/Source/Contents/Effects/PartyEffect.cpp similarity index 63% rename from Source/Contents/PartyEffect.cpp rename to Source/Contents/Effects/PartyEffect.cpp index 1b314ea..a90c598 100644 --- a/Source/Contents/PartyEffect.cpp +++ b/Source/Contents/Effects/PartyEffect.cpp @@ -1,25 +1,18 @@ -#include "Contents/EffectActor.h" -#include "Contents/EffectParticle.h" -#include "Contents/PartyEffect.h" -#include "Contents/RagEffectState.h" -#include "Contents/TerrainHeight.h" -#include "Render/TextureCache.h" +#include "Contents/Effects/EffectActor.h" +#include "Contents/Effects/EffectParticle.h" +#include "Contents/Effects/PartyEffect.h" +#include "Contents/Effects/RagEffectState.h" +#include "Contents/Ground/TerrainHeight.h" +#include "Render/Textures/TextureCache.h" -#include #include #include // OFFSET: 0x00C2CF20 // FUNCTION: fn_20088 bool UpdatePartyEffect( - RagEffectState& effect, - RenderObjectState& render, - ResourceMgr& resources, - JobNames& names, - std::list& worldObjects, - TextureCache& textures, - const TerrainHeight& ground, - int updateTick + RagEffectState& effect, RenderObjectState& render, ResourceMgr& resources, JobNames& names, std::list& worldObjects, TextureCache& textures, + const TerrainHeight& ground, int updateTick ) { if (!effect.parent) { return false; @@ -55,15 +48,13 @@ bool UpdatePartyEffect( state.red = 50; state.blue = 253; state.green = 50; - const auto bytes = state.textureCount >> 30 != 0 ? std::numeric_limits::max() - : static_cast(4u * state.textureCount); - // Original array new delegates to scalar new, whose storage is CRT malloc. - // Keep new-handler/exception behavior while retaining its free-domain teardown. + const auto bytes = state.textureCount >> 30 != 0 ? std::numeric_limits::max() : static_cast(4u * state.textureCount); + state.textures = static_cast(::operator new(bytes)); state.textures[0] = textures.Load("effect\\party.tga", 0, false, true, false); } render.position[1] = ground.Height(render.position[0], render.position[2]) - 2.0f; ++effect.unknown_0178; - return std::bit_cast(effect.unknown_0178) < effect.lifetime; + return effect.unknown_0178 < effect.lifetime; } diff --git a/Source/Contents/Effects/PartyEffect.h b/Source/Contents/Effects/PartyEffect.h new file mode 100644 index 0000000..17e9a15 --- /dev/null +++ b/Source/Contents/Effects/PartyEffect.h @@ -0,0 +1,20 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_PARTYEFFECT_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_PARTYEFFECT_H + +#include + +struct RagEffectState; +struct RenderObjectState; +struct EffectParticle; +struct JobNames; +struct TerrainHeight; +class ResourceMgr; +class TextureCache; +class CRenderObject; + +bool UpdatePartyEffect( + RagEffectState& effect, RenderObjectState& render, ResourceMgr& resources, JobNames& names, std::list& worldObjects, TextureCache& textures, + const TerrainHeight& ground, int updateTick +); + +#endif diff --git a/Source/Contents/PartyMemberEffects.cpp b/Source/Contents/Effects/PartyMemberEffects.cpp similarity index 69% rename from Source/Contents/PartyMemberEffects.cpp rename to Source/Contents/Effects/PartyMemberEffects.cpp index 380815e..1e732ad 100644 --- a/Source/Contents/PartyMemberEffects.cpp +++ b/Source/Contents/Effects/PartyMemberEffects.cpp @@ -1,9 +1,9 @@ -#include "Contents/AttachedEffect.h" -#include "Contents/EffectActor.h" -#include "Contents/PartyMemberEffects.h" -#include "Contents/RagEffectInitialization.h" +#include "Contents/Effects/AttachedEffect.h" +#include "Contents/Effects/EffectActor.h" +#include "Contents/Effects/PartyMemberEffects.h" +#include "Contents/Effects/RagEffectInitialization.h" #include "Script/LuaScript.h" -#include "Utility/AffineMatrix.h" +#include "Utility/Math/AffineMatrix.h" namespace { // OFFSET: 0x00CADD60 @@ -15,16 +15,14 @@ namespace { mode.effectScript.Call("IsForceRenderEffect", "d>b", 160, &force); effect->state.forceRender = force; - // Even zero offsets pass through the original angle table and arithmetic. const float sine = ClientSine(0); const float cosine = ClientCosine(0); const float x = 0.0f * cosine - 0.0f * sine; const float z = 0.0f * cosine + 0.0f * sine; - InitializeRagEffect( - effect->state, effect->render, &actor, actor.render, 160, x, 0, z, mode.options, mode.resources - ); + InitializeRagEffect(effect->state, effect->render, &actor, actor.render, 160, x, 0, z, mode.options, mode.resources); mode.objects.push_back(effect); actor.state.effects.push_back(&effect->state); + return effect; } } @@ -38,11 +36,10 @@ bool PartyMemberEffects::Enabled() const { // OFFSET: 0x00DD70B0 // FUNCTION: fn_23283 -// First account-id match, no deduplication or new effect on the existing-roster-member return path. + void PartyMemberEffects::EnsurePartyEffect(std::uint32_t accountId) { PartyEffectMode& mode = *this->activeMode; - // Actor lookup scans the mode's actor list in order. for (EffectActor* actor : mode.actors) { if (actor->render.accountId == accountId) { if (!actor->state.Attachments().HasId(160)) { diff --git a/Source/Contents/PartyMemberEffects.h b/Source/Contents/Effects/PartyMemberEffects.h similarity index 69% rename from Source/Contents/PartyMemberEffects.h rename to Source/Contents/Effects/PartyMemberEffects.h index 307867f..512d903 100644 --- a/Source/Contents/PartyMemberEffects.h +++ b/Source/Contents/Effects/PartyMemberEffects.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_PARTYMEMBEREFFECTS_H -#define RAGNAROK_SOURCE_CONTENTS_PARTYMEMBEREFFECTS_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_PARTYMEMBEREFFECTS_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_PARTYMEMBEREFFECTS_H #include #include @@ -11,8 +11,6 @@ struct ServiceOptions; class ResourceMgr; class LuaScript; -// Borrowed original active-mode/player fields and owning mode lists. The -// enclosing mode supplies actual owners; this does not construct a fake mode. struct PartyEffectMode { const int& playerOption48; const int& playerOption54; diff --git a/Source/Contents/RagEffectInitialization.cpp b/Source/Contents/Effects/RagEffectInitialization.cpp similarity index 73% rename from Source/Contents/RagEffectInitialization.cpp rename to Source/Contents/Effects/RagEffectInitialization.cpp index ca3e9b3..32f33fe 100644 --- a/Source/Contents/RagEffectInitialization.cpp +++ b/Source/Contents/Effects/RagEffectInitialization.cpp @@ -1,6 +1,6 @@ -#include "Contents/EffectTypes.h" -#include "Contents/RagEffectInitialization.h" -#include "Contents/RagEffectState.h" +#include "Contents/Effects/EffectTypes.h" +#include "Contents/Effects/RagEffectInitialization.h" +#include "Contents/Effects/RagEffectState.h" #include "Resource/EZeffectResource.h" #include "Resource/ResourceMgr.h" @@ -10,16 +10,8 @@ // OFFSET: 0x00C1C2D0 // FUNCTION: fn_20074 void InitializeRagEffect( - RagEffectState& effect, - RenderObjectState& render, - EffectActor* parent, - const RenderObjectState& parentState, - int id, - float x, - float y, - float z, - ServiceOptions& options, - ResourceMgr& resources + RagEffectState& effect, RenderObjectState& render, EffectActor* parent, const RenderObjectState& parentState, int id, float x, float y, float z, + ServiceOptions& options, ResourceMgr& resources ) { effect.id = id; effect.parent = parent; @@ -40,7 +32,7 @@ void InitializeRagEffect( if (resource) { ++resource->references; - // Original +0x7F0 points at its resource header (+0x110). + effect.resourceData = &resource->maximumFrame; int count = resource->clipCount; diff --git a/Source/Contents/Effects/RagEffectInitialization.h b/Source/Contents/Effects/RagEffectInitialization.h new file mode 100644 index 0000000..7d28358 --- /dev/null +++ b/Source/Contents/Effects/RagEffectInitialization.h @@ -0,0 +1,17 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_RAGEFFECTINITIALIZATION_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_RAGEFFECTINITIALIZATION_H + +struct RagEffectState; +struct RenderObjectState; +struct EffectActor; +struct ServiceOptions; +class ResourceMgr; + +void InitializeRagEffect( + RagEffectState& effect, RenderObjectState& render, EffectActor* parent, const RenderObjectState& parentState, int id, float x, float y, float z, + ServiceOptions& options, ResourceMgr& resources +); + +void SelectRagEffectResource(RagEffectState& effect, ServiceOptions& options, char* name); + +#endif diff --git a/Source/Contents/RagEffectResourceSelection.cpp b/Source/Contents/Effects/RagEffectResourceSelection.cpp similarity index 99% rename from Source/Contents/RagEffectResourceSelection.cpp rename to Source/Contents/Effects/RagEffectResourceSelection.cpp index f0e6ae8..da50eed 100644 --- a/Source/Contents/RagEffectResourceSelection.cpp +++ b/Source/Contents/Effects/RagEffectResourceSelection.cpp @@ -1,6 +1,6 @@ -#include "Contents/RagEffectInitialization.h" -#include "Contents/RagEffectState.h" -#include "Contents/ServiceOptions.h" +#include "Contents/Effects/RagEffectInitialization.h" +#include "Contents/Effects/RagEffectState.h" +#include "Contents/Configuration/ServiceOptions.h" #include #include diff --git a/Source/Contents/RagEffectState.cpp b/Source/Contents/Effects/RagEffectState.cpp similarity index 58% rename from Source/Contents/RagEffectState.cpp rename to Source/Contents/Effects/RagEffectState.cpp index 5c8e4d4..e55037a 100644 --- a/Source/Contents/RagEffectState.cpp +++ b/Source/Contents/Effects/RagEffectState.cpp @@ -1,18 +1,17 @@ -#include "Contents/EffectActor.h" -#include "Contents/EffectPrimitiveState.h" -#include "Contents/RagEffectState.h" +#include "Contents/Effects/EffectActor.h" +#include "Contents/Effects/EffectPrimitiveState.h" +#include "Contents/Effects/RagEffectState.h" #include "Resource/Resource.h" #include // OFFSET: 0x00BF84B0 // FUNCTION: fn_20007 -// Render-base resources are initialized first by the enclosing object, not duplicated here. + RagEffectState::RagEffectState() - : parent(nullptr), unknown_0160(0), unknown_0164(0), id(0), unknown_016C(1), unknown_0170(0), unknown_0174(0), - unknown_0178(0), offset{}, unknown_018C{}, resource(nullptr), resourceData(nullptr), unknown_119F4(0), - unknown_11C7C(0), unknown_11C80(0), unknown_11C84(nullptr), unknown_11C88{-1, -1, -1, -1}, forceRender(0), tag(0), - unknown_11CA0(0) { + : parent(nullptr), unknown_0160(0), unknown_0164(0), id(0), unknown_016C(1), unknown_0170(0), unknown_0174(0), unknown_0178(0), offset{}, unknown_018C{}, + resource(nullptr), resourceData(nullptr), unknown_119F4(0), unknown_11C7C(0), unknown_11C80(0), unknown_11C84(nullptr), unknown_11C88{-1, -1, -1, -1}, + forceRender(0), tag(0), unknown_11CA0(0) { for (unsigned index = 0; index < 20; ++index) { auto* record = this->unknown_01AC + index * 80; const std::uint32_t zero = 0; @@ -23,8 +22,7 @@ RagEffectState::RagEffectState() } std::memset(this->unknown_11A7C, 0, sizeof(this->unknown_11A7C)); - // Original constructs the three vertices in each record, then clears the - // entire array, overriding those initial vertex colors as well. + std::memset(this->vertices, 0, sizeof(this->vertices)); } diff --git a/Source/Contents/RagEffectState.h b/Source/Contents/Effects/RagEffectState.h similarity index 79% rename from Source/Contents/RagEffectState.h rename to Source/Contents/Effects/RagEffectState.h index 4f1252e..e02c305 100644 --- a/Source/Contents/RagEffectState.h +++ b/Source/Contents/Effects/RagEffectState.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_RAGEFFECTSTATE_H -#define RAGNAROK_SOURCE_CONTENTS_RAGEFFECTSTATE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EFFECTS_RAGEFFECTSTATE_H +#define RAGNAROK_SOURCE_CONTENTS_EFFECTS_RAGEFFECTSTATE_H -#include "Contents/RenderObjectState.h" +#include "Contents/Actors/RenderObjectState.h" #include @@ -9,9 +9,6 @@ class CRes; struct EffectPrimitiveState; struct EffectActor; -// Recovered CRagEffect fields +0x138..+0x11CA7. The active mode owns effects; -// parent and related pointers are borrowed. Unknown storage is not zeroed -// unless the original constructor writes it. struct RagEffectState { RagEffectState(); ~RagEffectState(); @@ -24,7 +21,7 @@ struct RagEffectState { /* 0016C */ int unknown_016C; /* 00170 */ std::uint32_t unknown_0170; /* 00174 */ std::uint32_t unknown_0174; - /* 00178 */ std::uint32_t unknown_0178; + /* 00178 */ std::int32_t unknown_0178; /* 0017C */ int lifetime; /* 00180 */ float offset[3]; /* 0018C */ std::uint32_t unknown_018C[6]; diff --git a/Source/Contents/EmblemDownload.h b/Source/Contents/EmblemDownload.h deleted file mode 100644 index f28c5cd..0000000 --- a/Source/Contents/EmblemDownload.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMDOWNLOAD_H -#define RAGNAROK_SOURCE_CONTENTS_EMBLEMDOWNLOAD_H - -#include -#include - -class CConnection; -struct AsyncDiagnostic; - -void CompleteEmblemDownload( - AsyncDiagnostic diagnostic, - int responseCode, - std::string response, - std::uint32_t guildId, - std::uint32_t version, - CConnection& connection -); - -#endif diff --git a/Source/Contents/EmblemCache.cpp b/Source/Contents/Emblems/EmblemCache.cpp similarity index 91% rename from Source/Contents/EmblemCache.cpp rename to Source/Contents/Emblems/EmblemCache.cpp index c1cacde..8baede2 100644 --- a/Source/Contents/EmblemCache.cpp +++ b/Source/Contents/Emblems/EmblemCache.cpp @@ -1,6 +1,6 @@ -#include "Contents/EmblemCache.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "Contents/Emblems/EmblemCache.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" #include #include @@ -93,16 +93,9 @@ void EmblemCache::Store(const void* bytes, std::uint32_t size, std::uint32_t gui } } -// Packet 0x0B36 case reached by CGameMode receive dispatch. // OFFSET: 0x00D588E0 // FUNCTION: fn_21954 -void EmblemCache::Receive( - std::uint16_t state, - std::uint32_t guild, - std::uint32_t revision, - const unsigned char* bytes, - int size -) { +void EmblemCache::Receive(std::uint16_t state, std::uint32_t guild, std::uint32_t revision, const unsigned char* bytes, int size) { if (state == 0) { this->guildId = guild; this->version = revision; diff --git a/Source/Contents/EmblemCache.h b/Source/Contents/Emblems/EmblemCache.h similarity index 60% rename from Source/Contents/EmblemCache.h rename to Source/Contents/Emblems/EmblemCache.h index 599c0d7..55cae99 100644 --- a/Source/Contents/EmblemCache.h +++ b/Source/Contents/Emblems/EmblemCache.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMCACHE_H -#define RAGNAROK_SOURCE_CONTENTS_EMBLEMCACHE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMCACHE_H +#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMCACHE_H #include #include @@ -10,13 +10,11 @@ class UIWindow; class WindowManagerWindows; -// Borrowed CGuildMgr receive fields and invalid-resource set. Resource lookup, -// guild metadata, and CGuildMgr's singleton lifetime remain separate operations. struct EmblemCache { - std::uint32_t& guildId; // CGuildMgr +0x1C - std::uint32_t& version; // CGuildMgr +0x20 - std::vector& data; // CGuildMgr +0x24 - std::set& invalid; // CGuildMgr +0x14 + std::uint32_t& guildId; + std::uint32_t& version; + std::vector& data; + std::set& invalid; const std::string& accountName; const char* rootDirectory; const std::list* const& modeWindows; diff --git a/Source/Contents/EmblemDataDownloadAsyncWork.cpp b/Source/Contents/Emblems/EmblemDataDownloadAsyncWork.cpp similarity index 74% rename from Source/Contents/EmblemDataDownloadAsyncWork.cpp rename to Source/Contents/Emblems/EmblemDataDownloadAsyncWork.cpp index 33c2e01..edcf60c 100644 --- a/Source/Contents/EmblemDataDownloadAsyncWork.cpp +++ b/Source/Contents/Emblems/EmblemDataDownloadAsyncWork.cpp @@ -1,14 +1,14 @@ -#include "Contents/EmblemDataDownloadAsyncWork.h" -#include "Contents/EmblemDownload.h" -#include "Network/CURLPostHander.h" +#include "Contents/Emblems/EmblemDataDownloadAsyncWork.h" +#include "Contents/Emblems/EmblemDownload.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { - constexpr char sourceFile[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\Emblem\\CEmblemDataDownloadAsyncWork.cpp"; + constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\Emblem\\CEmblemDataDownloadAsyncWork.cpp"; AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; @@ -19,8 +19,8 @@ namespace { // OFFSET: 0x005E9C00 // FUNCTION: fn_03963 CEmblemDataDownloadAsyncWork::CEmblemDataDownloadAsyncWork() - : NAsyncWork("Emblem_Download"), m_accountId(0), m_guildId(0), m_version(0), m_responseCode(500), - m_diagnostic(Diagnostic(false, "unknwon", 29)), m_connection(nullptr) { + : NAsyncWork("Emblem_Download"), m_accountId(0), m_guildId(0), m_version(0), m_responseCode(500), m_diagnostic(Diagnostic(false, "unknwon", 29)), + m_connection(nullptr) { } // OFFSET: 0x005E9FE0 @@ -35,13 +35,7 @@ void CEmblemDataDownloadAsyncWork::Reset() { // OFFSET: 0x005EA0D0 // FUNCTION: fn_03965 void CEmblemDataDownloadAsyncWork::Bind( - std::string url, - std::uint32_t accountId, - std::string token, - std::string accountName, - std::uint32_t guildId, - std::uint32_t version, - CConnection& connection + std::string url, std::uint32_t accountId, std::string token, std::string accountName, std::uint32_t guildId, std::uint32_t version, CConnection& connection ) { this->m_group = timeGetTime(); this->m_key = 0; @@ -78,7 +72,6 @@ bool CEmblemDataDownloadAsyncWork::Execute() { AsyncDiagnostic diagnostic = Diagnostic(true, "good", 96); this->m_diagnostic.MoveFrom(diagnostic); } else { - // Original retains prior response/code on recycle after transport failure. AsyncDiagnostic diagnostic = Diagnostic(false, "fail", 105); this->m_diagnostic.MoveFrom(diagnostic); } @@ -89,7 +82,5 @@ bool CEmblemDataDownloadAsyncWork::Execute() { // OFFSET: 0x005EA360 // FUNCTION: fn_03967 void CEmblemDataDownloadAsyncWork::Complete() { - CompleteEmblemDownload( - this->m_diagnostic, this->m_responseCode, this->m_response, this->m_guildId, this->m_version, *this->m_connection - ); + CompleteEmblemDownload(this->m_diagnostic, this->m_responseCode, this->m_response, this->m_guildId, this->m_version, *this->m_connection); } diff --git a/Source/Contents/EmblemDataDownloadAsyncWork.h b/Source/Contents/Emblems/EmblemDataDownloadAsyncWork.h similarity index 62% rename from Source/Contents/EmblemDataDownloadAsyncWork.h rename to Source/Contents/Emblems/EmblemDataDownloadAsyncWork.h index 2604a72..6a77c49 100644 --- a/Source/Contents/EmblemDataDownloadAsyncWork.h +++ b/Source/Contents/Emblems/EmblemDataDownloadAsyncWork.h @@ -1,12 +1,11 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMDATADOWNLOADASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_EMBLEMDATADOWNLOADASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATADOWNLOADASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATADOWNLOADASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class CConnection; -// Original 208-byte x86 work value; host connection binding follows its fields. class CEmblemDataDownloadAsyncWork : public NAsyncWork { public: CEmblemDataDownloadAsyncWork(); @@ -15,13 +14,7 @@ public: bool Execute() override; void Complete() override; void Bind( - std::string url, - std::uint32_t accountId, - std::string token, - std::string accountName, - std::uint32_t guildId, - std::uint32_t version, - CConnection& connection + std::string url, std::uint32_t accountId, std::string token, std::string accountName, std::uint32_t guildId, std::uint32_t version, CConnection& connection ); protected: diff --git a/Source/Contents/EmblemDataMgr.cpp b/Source/Contents/Emblems/EmblemDataMgr.cpp similarity index 72% rename from Source/Contents/EmblemDataMgr.cpp rename to Source/Contents/Emblems/EmblemDataMgr.cpp index 32fb52c..84f8a51 100644 --- a/Source/Contents/EmblemDataMgr.cpp +++ b/Source/Contents/Emblems/EmblemDataMgr.cpp @@ -1,6 +1,6 @@ -#include "Contents/AccountService.h" -#include "Contents/AsyncWorkMgr.h" -#include "Contents/EmblemDataMgr.h" +#include "Contents/UserData/AccountService.h" +#include "Contents/Async/AsyncWorkMgr.h" +#include "Contents/Emblems/EmblemDataMgr.h" #include @@ -50,13 +50,7 @@ void CEmblemDataMgr::Shutdown() { // OFFSET: 0x005EB580 // FUNCTION: fn_03974 -void CEmblemDataMgr::RefreshUrls( - LuaScript& settings, - LuaScript& tables, - const char* host, - const char* port, - const char* overrideKey -) { +void CEmblemDataMgr::RefreshUrls(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey) { const std::string base = ResolveAccountServiceBase(settings, tables, host, port, overrideKey); if (!base.empty()) { @@ -68,12 +62,7 @@ void CEmblemDataMgr::RefreshUrls( // OFFSET: 0x005EB260 // FUNCTION: fn_03972 void CEmblemDataMgr::Download( - std::uint32_t guildId, - std::uint32_t version, - std::uint32_t accountId, - const std::string& accountName, - const char* token16, - CConnection& connection, + std::uint32_t guildId, std::uint32_t version, std::uint32_t accountId, const std::string& accountName, const char* token16, CConnection& connection, CAsyncWorkMgr& manager ) { const std::string token(token16, 16); @@ -83,12 +72,7 @@ void CEmblemDataMgr::Download( // OFFSET: 0x005EB410 // FUNCTION: fn_03973 bool CEmblemDataMgr::Upload( - std::uint32_t guildId, - std::string path, - std::uint32_t accountId, - const std::string& accountName, - const char* token16, - EmblemUploadContext& context, + std::uint32_t guildId, std::string path, std::uint32_t accountId, const std::string& accountName, const char* token16, EmblemUploadContext& context, CAsyncWorkMgr& manager ) { if (this->m_uploading) { @@ -98,6 +82,5 @@ bool CEmblemDataMgr::Upload( const std::string token(token16, 16); manager.UploadEmblem(this->m_uploadUrl, accountId, token, accountName, guildId, path, *this, context); - // The original tests the uploading flag but does not set it here. return true; } diff --git a/Source/Contents/EmblemDataMgr.h b/Source/Contents/Emblems/EmblemDataMgr.h similarity index 59% rename from Source/Contents/EmblemDataMgr.h rename to Source/Contents/Emblems/EmblemDataMgr.h index ddb9203..baa0c95 100644 --- a/Source/Contents/EmblemDataMgr.h +++ b/Source/Contents/Emblems/EmblemDataMgr.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMDATAMGR_H -#define RAGNAROK_SOURCE_CONTENTS_EMBLEMDATAMGR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATAMGR_H +#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATAMGR_H #include #include @@ -18,25 +18,14 @@ public: static void Shutdown(); void RefreshUrls(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey); void Download( - std::uint32_t guildId, - std::uint32_t version, - std::uint32_t accountId, - const std::string& accountName, - const char* token16, - CConnection& connection, + std::uint32_t guildId, std::uint32_t version, std::uint32_t accountId, const std::string& accountName, const char* token16, CConnection& connection, CAsyncWorkMgr& manager ); bool Upload( - std::uint32_t guildId, - std::string path, - std::uint32_t accountId, - const std::string& accountName, - const char* token16, - EmblemUploadContext& context, + std::uint32_t guildId, std::string path, std::uint32_t accountId, const std::string& accountName, const char* token16, EmblemUploadContext& context, CAsyncWorkMgr& manager ); - void - CompleteUpload(AsyncDiagnostic diagnostic, std::string response, std::uint32_t guildId, EmblemUploadContext& context); + void CompleteUpload(AsyncDiagnostic diagnostic, std::string response, std::uint32_t guildId, EmblemUploadContext& context); protected: /* 0004 */ bool m_enabled; diff --git a/Source/Contents/EmblemDataUploadAsyncWork.cpp b/Source/Contents/Emblems/EmblemDataUploadAsyncWork.cpp similarity index 82% rename from Source/Contents/EmblemDataUploadAsyncWork.cpp rename to Source/Contents/Emblems/EmblemDataUploadAsyncWork.cpp index e6ca65b..6cddf6b 100644 --- a/Source/Contents/EmblemDataUploadAsyncWork.cpp +++ b/Source/Contents/Emblems/EmblemDataUploadAsyncWork.cpp @@ -1,15 +1,15 @@ -#include "Contents/EmblemDataMgr.h" -#include "Contents/EmblemDataUploadAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/Emblems/EmblemDataMgr.h" +#include "Contents/Emblems/EmblemDataUploadAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include #include -#include +#include +#include namespace { - constexpr char sourceFile[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\Emblem\\CEmblemDataUploadAsyncWork.cpp"; + constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\Emblem\\CEmblemDataUploadAsyncWork.cpp"; AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; @@ -20,8 +20,7 @@ namespace { // OFFSET: 0x005EBF50 // FUNCTION: fn_03978 CEmblemDataUploadAsyncWork::CEmblemDataUploadAsyncWork() - : NAsyncWork("Emblem_Upload"), m_accountId(0), m_guildId(0), m_diagnostic(Diagnostic(false, "unknwon", 27)), - m_owner(nullptr), m_context(nullptr) { + : NAsyncWork("Emblem_Upload"), m_accountId(0), m_guildId(0), m_diagnostic(Diagnostic(false, "unknwon", 27)), m_owner(nullptr), m_context(nullptr) { } // OFFSET: 0x005EC350 @@ -36,13 +35,7 @@ void CEmblemDataUploadAsyncWork::Reset() { // OFFSET: 0x005EC450 // FUNCTION: fn_03980 void CEmblemDataUploadAsyncWork::Bind( - std::string url, - std::uint32_t accountId, - std::string token, - std::string accountName, - std::uint32_t guildId, - std::string path, - CEmblemDataMgr& owner, + std::string url, std::uint32_t accountId, std::string token, std::string accountName, std::uint32_t guildId, std::string path, CEmblemDataMgr& owner, EmblemUploadContext& context ) { this->m_group = timeGetTime(); diff --git a/Source/Contents/EmblemDataUploadAsyncWork.h b/Source/Contents/Emblems/EmblemDataUploadAsyncWork.h similarity index 64% rename from Source/Contents/EmblemDataUploadAsyncWork.h rename to Source/Contents/Emblems/EmblemDataUploadAsyncWork.h index 0f3a0fa..84801f8 100644 --- a/Source/Contents/EmblemDataUploadAsyncWork.h +++ b/Source/Contents/Emblems/EmblemDataUploadAsyncWork.h @@ -1,13 +1,12 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMDATAUPLOADASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_EMBLEMDATAUPLOADASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATAUPLOADASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATAUPLOADASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class CEmblemDataMgr; struct EmblemUploadContext; -// Original 224-byte x86 fields; source owner/context bindings follow them. class CEmblemDataUploadAsyncWork : public NAsyncWork { public: CEmblemDataUploadAsyncWork(); @@ -16,13 +15,7 @@ public: bool Execute() override; void Complete() override; void Bind( - std::string url, - std::uint32_t accountId, - std::string token, - std::string accountName, - std::uint32_t guildId, - std::string path, - CEmblemDataMgr& owner, + std::string url, std::uint32_t accountId, std::string token, std::string accountName, std::uint32_t guildId, std::string path, CEmblemDataMgr& owner, EmblemUploadContext& context ); diff --git a/Source/Contents/EmblemDownload.cpp b/Source/Contents/Emblems/EmblemDownload.cpp similarity index 80% rename from Source/Contents/EmblemDownload.cpp rename to Source/Contents/Emblems/EmblemDownload.cpp index bc133e9..aecada0 100644 --- a/Source/Contents/EmblemDownload.cpp +++ b/Source/Contents/Emblems/EmblemDownload.cpp @@ -1,6 +1,6 @@ -#include "Contents/EmblemDownload.h" -#include "Network/Connection.h" -#include "Utility/AsyncDiagnostic.h" +#include "Contents/Emblems/EmblemDownload.h" +#include "Network/Connection/Connection.h" +#include "Utility/Async/AsyncDiagnostic.h" #include #include @@ -30,12 +30,7 @@ namespace { // OFFSET: 0x005EB800 // FUNCTION: fn_03975 void CompleteEmblemDownload( - AsyncDiagnostic diagnostic, - int responseCode, - std::string response, - std::uint32_t guildId, - std::uint32_t version, - CConnection& connection + AsyncDiagnostic diagnostic, int responseCode, std::string response, std::uint32_t guildId, std::uint32_t version, CConnection& connection ) { if (!diagnostic.success || responseCode != 200) { return; @@ -65,8 +60,7 @@ void CompleteEmblemDownload( packet.state = 1; packet.guildId = guildId; packet.version = version; - // Original substr/copy includes bytes at remaining, not the consumed prefix. - // Avoid its unnecessary temporary string while preserving the same bytes. + std::memcpy(packet.data, response.data() + remaining, bytes); connection.Prepend(packet.bytes, &packet); } diff --git a/Source/Contents/Emblems/EmblemDownload.h b/Source/Contents/Emblems/EmblemDownload.h new file mode 100644 index 0000000..730e640 --- /dev/null +++ b/Source/Contents/Emblems/EmblemDownload.h @@ -0,0 +1,14 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDOWNLOAD_H +#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDOWNLOAD_H + +#include +#include + +class CConnection; +struct AsyncDiagnostic; + +void CompleteEmblemDownload( + AsyncDiagnostic diagnostic, int responseCode, std::string response, std::uint32_t guildId, std::uint32_t version, CConnection& connection +); + +#endif diff --git a/Source/Contents/EmblemUpload.cpp b/Source/Contents/Emblems/EmblemUpload.cpp similarity index 72% rename from Source/Contents/EmblemUpload.cpp rename to Source/Contents/Emblems/EmblemUpload.cpp index ed985f0..81da99c 100644 --- a/Source/Contents/EmblemUpload.cpp +++ b/Source/Contents/Emblems/EmblemUpload.cpp @@ -1,10 +1,10 @@ -#include "Contents/EmblemDataMgr.h" -#include "Contents/EmblemUpload.h" +#include "Contents/Emblems/EmblemDataMgr.h" +#include "Contents/Emblems/EmblemUpload.h" #include "Contents/MessageTable.h" -#include "Network/Connection.h" -#include "Network/PacketLengths.h" -#include "UI/WindowDialogs.h" -#include "Utility/AsyncDiagnostic.h" +#include "Network/Connection/Connection.h" +#include "Network/Packets/PacketLengths.h" +#include "UI/Window/WindowDialogs.h" +#include "Utility/Async/AsyncDiagnostic.h" #include #include @@ -22,12 +22,7 @@ namespace { // OFFSET: 0x005EBAD0 // FUNCTION: fn_03976 -void CEmblemDataMgr::CompleteUpload( - AsyncDiagnostic diagnostic, - std::string response, - std::uint32_t guildId, - EmblemUploadContext& context -) { +void CEmblemDataMgr::CompleteUpload(AsyncDiagnostic diagnostic, std::string response, std::uint32_t guildId, EmblemUploadContext& context) { if (!diagnostic.success) { return; } diff --git a/Source/Contents/EmblemUpload.h b/Source/Contents/Emblems/EmblemUpload.h similarity index 72% rename from Source/Contents/EmblemUpload.h rename to Source/Contents/Emblems/EmblemUpload.h index b794818..8acd6f9 100644 --- a/Source/Contents/EmblemUpload.h +++ b/Source/Contents/Emblems/EmblemUpload.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMUPLOAD_H -#define RAGNAROK_SOURCE_CONTENTS_EMBLEMUPLOAD_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMUPLOAD_H +#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMUPLOAD_H #include diff --git a/Source/Contents/GuildEmblemReqBundle.cpp b/Source/Contents/Emblems/GuildEmblemReqBundle.cpp similarity index 78% rename from Source/Contents/GuildEmblemReqBundle.cpp rename to Source/Contents/Emblems/GuildEmblemReqBundle.cpp index 4fa1b1d..bc7484a 100644 --- a/Source/Contents/GuildEmblemReqBundle.cpp +++ b/Source/Contents/Emblems/GuildEmblemReqBundle.cpp @@ -1,11 +1,9 @@ -#include "Contents/EmblemDataMgr.h" -#include "Contents/GuildEmblemReqBundle.h" +#include "Contents/Emblems/EmblemDataMgr.h" +#include "Contents/Emblems/GuildEmblemReqBundle.h" #include #include -// clang-format off -#include -// clang-format on +#include // OFFSET: 0x0065C5F0 CGuildEmblemReqBundle::CGuildEmblemReqBundle() = default; @@ -27,12 +25,7 @@ void CGuildEmblemReqBundle::Add(std::uint32_t guildId, std::uint32_t version) { // OFFSET: 0x0065CB90 // FUNCTION: fn_05155 void CGuildEmblemReqBundle::Update( - CEmblemDataMgr& emblems, - std::uint32_t accountId, - const std::string& accountName, - const char* token16, - CConnection& connection, - CAsyncWorkMgr& manager + CEmblemDataMgr& emblems, std::uint32_t accountId, const std::string& accountName, const char* token16, CConnection& connection, CAsyncWorkMgr& manager ) { while (!this->m_recent.empty()) { if (timeGetTime() < this->m_recent.front().tick + 60000u) { @@ -58,7 +51,6 @@ void CGuildEmblemReqBundle::Update( this->m_recent.push_back({request.first, request.second, timeGetTime()}); } - // At most one non-recent pending entry is consumed per update, including 0. return; } } diff --git a/Source/Contents/GuildEmblemReqBundle.h b/Source/Contents/Emblems/GuildEmblemReqBundle.h similarity index 69% rename from Source/Contents/GuildEmblemReqBundle.h rename to Source/Contents/Emblems/GuildEmblemReqBundle.h index fd931ed..fa7b020 100644 --- a/Source/Contents/GuildEmblemReqBundle.h +++ b/Source/Contents/Emblems/GuildEmblemReqBundle.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_GUILDEMBLEMREQBUNDLE_H -#define RAGNAROK_SOURCE_CONTENTS_GUILDEMBLEMREQBUNDLE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_GUILDEMBLEMREQBUNDLE_H +#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_GUILDEMBLEMREQBUNDLE_H #include #include @@ -16,12 +16,7 @@ public: virtual ~CGuildEmblemReqBundle(); void Add(std::uint32_t guildId, std::uint32_t version); void Update( - CEmblemDataMgr& emblems, - std::uint32_t accountId, - const std::string& accountName, - const char* token16, - CConnection& connection, - CAsyncWorkMgr& manager + CEmblemDataMgr& emblems, std::uint32_t accountId, const std::string& accountName, const char* token16, CConnection& connection, CAsyncWorkMgr& manager ); protected: diff --git a/Source/Contents/ForbiddenWords.cpp b/Source/Contents/ForbiddenWords.cpp index ba9e939..33eda0e 100644 --- a/Source/Contents/ForbiddenWords.cpp +++ b/Source/Contents/ForbiddenWords.cpp @@ -37,7 +37,6 @@ bool ForbiddenWords::Load(const char* name, CCommonObject& storage, ResourceByte } if (*first != '\0') { - // Original checks past leading whitespace but stores the untrimmed token. this->words.push_back(Lowercase(token, this->codePage)); } } @@ -60,15 +59,10 @@ bool ForbiddenWords::Allows(const char* text) const { const char* end = current + std::strlen(current); while (current < end) { - const auto* open = - _mbsstr(reinterpret_cast(current), reinterpret_cast("")); - const auto* close = - _mbsstr(reinterpret_cast(current), reinterpret_cast("")); + const auto* open = _mbsstr(reinterpret_cast(current), reinterpret_cast("")); + const auto* close = _mbsstr(reinterpret_cast(current), reinterpret_cast("")); - if ( - open && close && std::strlen(current) != 0 && - std::strlen(current) <= std::strlen(reinterpret_cast(open)) - ) { + if (open && close && std::strlen(current) != 0 && std::strlen(current) <= std::strlen(reinterpret_cast(open))) { const auto skip = reinterpret_cast(close) + 8 - reinterpret_cast(open); for (std::ptrdiff_t index = 0; index < skip; ++index) { @@ -99,7 +93,6 @@ bool ForbiddenWords::Contains(const char* text) const { // OFFSET: 0x00AE6050 // FUNCTION: fn_18061 void ForbiddenWords::Mask(char* text, std::string* value) const { - // Original process-wide scratch buffers; intentionally not reentrant. // STATIC: 0x016D4E60 // GLOBAL: gl_24379 static char valueBuffer[2048]; @@ -126,21 +119,15 @@ void ForbiddenWords::Mask(char* text, std::string* value) const { char* current = Lowercase(scanBuffer, this->codePage); while (std::strlen(current) != 0) { - const auto* open = - _mbsstr(reinterpret_cast(current), reinterpret_cast("")); - const auto* close = - _mbsstr(reinterpret_cast(current), reinterpret_cast("")); + const auto* open = _mbsstr(reinterpret_cast(current), reinterpret_cast("")); + const auto* close = _mbsstr(reinterpret_cast(current), reinterpret_cast("")); - if ( - open && close && std::strlen(current) != 0 && - std::strlen(current) <= std::strlen(reinterpret_cast(open)) - ) { + if (open && close && std::strlen(current) != 0 && std::strlen(current) <= std::strlen(reinterpret_cast(open))) { const auto skip = reinterpret_cast(close) + 8 - reinterpret_cast(open); char* next = current; for (std::ptrdiff_t index = 0; index < skip; ++index) { - // Reloads the same source pointer on every iteration. next = CharNextExA(this->codePage, current, 0); } @@ -159,8 +146,7 @@ void ForbiddenWords::Mask(char* text, std::string* value) const { advance = 0; const char* end = matchedWord + std::strlen(matchedWord); - for (const char* character = matchedWord; character < end; - character = CharNextExA(this->codePage, character, 0)) { + for (const char* character = matchedWord; character < end; character = CharNextExA(this->codePage, character, 0)) { ++advance; } diff --git a/Source/Contents/ForbiddenWords.h b/Source/Contents/ForbiddenWords.h index e751230..f75b7e5 100644 --- a/Source/Contents/ForbiddenWords.h +++ b/Source/Contents/ForbiddenWords.h @@ -7,8 +7,6 @@ class CCommonObject; class ResourceBytes; -// Borrowed pointer vector and charset owner. Words are -// already normalized by their resource loader; this operation does not own them. struct ForbiddenWords { std::vector& words; const unsigned short& codePage; diff --git a/Source/Contents/GroundDecals.cpp b/Source/Contents/Ground/GroundDecals.cpp similarity index 76% rename from Source/Contents/GroundDecals.cpp rename to Source/Contents/Ground/GroundDecals.cpp index 55e6fd1..cac99d4 100644 --- a/Source/Contents/GroundDecals.cpp +++ b/Source/Contents/Ground/GroundDecals.cpp @@ -1,14 +1,14 @@ -#include "Contents/GroundGeometry.h" -#include "Contents/GroundRendering.h" -#include "Render/RenderPrimitivePool.h" -#include "Render/RenderProjection.h" -#include "Render/RenderQueues.h" -#include "Render/Texture.h" -#include "Render/TextureCache.h" -#include "Resource/TerrainResource.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Contents/Ground/GroundRendering.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Projection/RenderProjection.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/World/TerrainResource.h" +#include "Utility/Math/ScalarConversion.h" #include -#include // OFFSET: 0x00AC0A90 // FUNCTION: fn_17569 @@ -32,16 +32,8 @@ bool GroundGeometry::CellRectangle(const C3dAttr& terrain, int column, int row, namespace { void DrawDecal( - const GroundGeometry& ground, - const C3dAttr& terrain, - const float* matrix, - int column, - int row, - std::uint32_t color, - CTexture& texture, - const float* uv, - float bias, - GroundRenderContext& context + const GroundGeometry& ground, const C3dAttr& terrain, const float* matrix, int column, int row, std::uint32_t color, CTexture& texture, const float* uv, + float bias, GroundRenderContext& context ) { float vertices[4][3]{}; @@ -93,14 +85,7 @@ namespace { // OFFSET: 0x00AC3380 // FUNCTION: fn_17602 void GroundGeometry::DrawCellDecal( - const C3dAttr& terrain, - const float* matrix, - int column, - int row, - std::uint32_t color, - CTexture& texture, - const float* uv, - GroundRenderContext& context + const C3dAttr& terrain, const float* matrix, int column, int row, std::uint32_t color, CTexture& texture, const float* uv, GroundRenderContext& context ) const { DrawDecal(*this, terrain, matrix, column, row, color, texture, uv, 0.10003052f, context); } @@ -108,14 +93,7 @@ void GroundGeometry::DrawCellDecal( // OFFSET: 0x00AC1720 // FUNCTION: fn_17589 void GroundGeometry::DrawGridDecal( - const C3dAttr& terrain, - const float* matrix, - int column, - int row, - std::uint32_t color, - CTexture& texture, - const float* uv, - GroundRenderContext& context + const C3dAttr& terrain, const float* matrix, int column, int row, std::uint32_t color, CTexture& texture, const float* uv, GroundRenderContext& context ) const { DrawDecal(*this, terrain, matrix, column, row, color, texture, uv, 3.0517578e-05f, context); } @@ -123,13 +101,7 @@ void GroundGeometry::DrawGridDecal( // OFFSET: 0x00AC16D0 // FUNCTION: fn_17587 void GroundGeometry::DrawGrid( - const C3dAttr& terrain, - const float* matrix, - int column, - int row, - std::uint32_t color, - TextureCache& textures, - GroundRenderContext& context + const C3dAttr& terrain, const float* matrix, int column, int row, std::uint32_t color, TextureCache& textures, GroundRenderContext& context ) const { CTexture* texture = textures.Load("grid.tga", 0, false, true, false); // STATIC: 0x01347EB0 @@ -140,15 +112,9 @@ void GroundGeometry::DrawGrid( // OFFSET: 0x00AC3610 // FUNCTION: fn_17604 void GroundGeometry::DrawTerrainOverlay( - const C3dAttr& terrain, - const float* matrix, - int column, - int row, - std::uint32_t color, - CTexture* texture, - GroundRenderContext& context + const C3dAttr& terrain, const float* matrix, int column, int row, std::uint32_t color, CTexture* texture, GroundRenderContext& context ) const { - const auto half = [](int value) { return _mm_cvttss_si32(_mm_set_ss(static_cast(value) * 0.5f)); }; + const auto half = [](int value) { return TruncateToInt(static_cast(value) * 0.5f); }; const int cellColumn = half(column); const int cellRow = half(row); const int halfWidth = half(this->width); @@ -173,10 +139,7 @@ void GroundGeometry::DrawTerrainOverlay( const float top = z - margin; const float bottom = (z + halfSize) + margin; const float vertices[4][3] = { - {left, cell->heights[0], top}, - {right, cell->heights[1], top}, - {left, cell->heights[2], bottom}, - {right, cell->heights[3], bottom} + {left, cell->heights[0], top}, {right, cell->heights[1], top}, {left, cell->heights[2], bottom}, {right, cell->heights[3], bottom} }; RenderPrimitive* primitive = context.primitives.Acquire(); diff --git a/Source/Contents/GroundGeometry.cpp b/Source/Contents/Ground/GroundGeometry.cpp similarity index 81% rename from Source/Contents/GroundGeometry.cpp rename to Source/Contents/Ground/GroundGeometry.cpp index 47f0e2b..3e28f94 100644 --- a/Source/Contents/GroundGeometry.cpp +++ b/Source/Contents/Ground/GroundGeometry.cpp @@ -1,12 +1,12 @@ -#include "Contents/GroundGeometry.h" -#include "Render/Texture.h" -#include "Render/TextureCache.h" -#include "Resource/GroundResource.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/World/GroundResource.h" +#include "Utility/Math/ScalarConversion.h" #include #include #include -#include namespace { struct CellNormals { @@ -19,8 +19,7 @@ namespace { } void Normalize(float* vector, bool yFirst) { - const float first = - yFirst ? vector[1] * vector[1] + vector[0] * vector[0] : vector[0] * vector[0] + vector[1] * vector[1]; + const float first = yFirst ? vector[1] * vector[1] + vector[0] * vector[0] : vector[0] * vector[0] + vector[1] * vector[1]; const float inverse = InverseLength(first + vector[2] * vector[2]); vector[0] = inverse * vector[0]; vector[1] = inverse * vector[1]; @@ -33,15 +32,8 @@ namespace { result[2] = result[2] + value[2]; } - std::uint32_t LitColor( - const float* normal, - bool normalize, - bool side, - const float* direction, - const float* diffuse, - const float* ambient, - const GroundQuad* source - ) { + std::uint32_t + LitColor(const float* normal, bool normalize, bool side, const float* direction, const float* diffuse, const float* ambient, const GroundQuad* source) { float vector[3] = {normal[0], normal[1], normal[2]}; if (normalize) { @@ -50,16 +42,16 @@ namespace { const float dot = side ? (direction[1] * vector[1] + vector[0] * direction[0]) + direction[2] * vector[2] : (vector[1] * direction[1] + vector[0] * direction[0]) + vector[2] * direction[2]; - const float amount = _mm_cvtss_f32(_mm_max_ss(_mm_set_ss(dot), _mm_setzero_ps())); + const float amount = dot > 0.0f ? dot : 0.0f; const std::uint32_t color = source ? source->color : 0xFFFFFFFFu; std::uint32_t result = 0xFF000000u; for (unsigned channel = 0; channel < 3; ++channel) { - const float light = - _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(amount * diffuse[channel] + ambient[channel]), _mm_set_ss(1.0f))); + const float illumination = amount * diffuse[channel] + ambient[channel]; + const float light = illumination < 1.0f ? illumination : 1.0f; const unsigned shift = 16 - channel * 8; const float scaled = static_cast((color >> shift) & 255u) * light; - const unsigned value = static_cast(_mm_cvttss_si32(_mm_set_ss(scaled))) & 255u; + const unsigned value = static_cast(TruncateToInt(scaled)) & 255u; result |= value << shift; } @@ -84,7 +76,6 @@ void GroundGeometry::ClearGeometry() { this->tiles.clear(); this->lighting.clear(); this->cells.clear(); - // Lightmaps have their own owning cleanup. } // OFFSET: 0x00AC0200 @@ -105,13 +96,7 @@ GroundSpatial GroundGeometry::Spatial() const { // OFFSET: 0x00ABDEF0 // FUNCTION: fn_17556 -void GroundGeometry::Build( - CGndRes& resource, - TextureCache& textures, - const float* lightDirection, - const float* diffuse, - const float* ambient -) { +void GroundGeometry::Build(CGndRes& resource, TextureCache& textures, const float* lightDirection, const float* diffuse, const float* ambient) { this->loaded = resource.loaded; this->Reset(resource.width, resource.height); std::vector normals(this->cells.size()); @@ -121,8 +106,7 @@ void GroundGeometry::Build( for (int row = 0; row < this->height; ++row) { for (int column = 0; column < this->width; ++column) { - const unsigned index = - static_cast(row) * static_cast(this->width) + static_cast(column); + const unsigned index = static_cast(row) * static_cast(this->width) + static_cast(column); GroundCell& cell = this->cells[index]; const unsigned char* record = resource.cells + 28u * index; std::memcpy(cell.heights, record, sizeof(cell.heights)); @@ -165,32 +149,21 @@ void GroundGeometry::Build( } else if (face == 1) { float next[4]; std::memcpy(next, resource.cells + 28u * (index + this->width), sizeof(next)); - const float values[4][3] = { - {left, cell.heights[2], bottom}, - {right, cell.heights[3], bottom}, - {left, next[0], bottom}, - {right, next[1], bottom} - }; + const float values[4][3] = {{left, cell.heights[2], bottom}, {right, cell.heights[3], bottom}, {left, next[0], bottom}, {right, next[1], bottom}}; std::memcpy(positions, values, sizeof(positions)); normals[index].values[2][2] = next[0] <= cell.heights[2] ? 1.0f : -1.0f; } else { float next[4]; std::memcpy(next, resource.cells + 28u * (index + 1), sizeof(next)); - const float values[4][3] = { - {right, cell.heights[3], bottom}, - {right, cell.heights[1], top}, - {right, next[2], bottom}, - {right, next[0], top} - }; + const float values[4][3] = {{right, cell.heights[3], bottom}, {right, cell.heights[1], top}, {right, next[2], bottom}, {right, next[0], top}}; std::memcpy(positions, values, sizeof(positions)); normals[index].values[3][0] = next[0] <= cell.heights[2] ? 1.0f : -1.0f; } - const float scaleU = - static_cast(tile.texture->Width()) / static_cast(tile.texture->TextureWidth()); - const float scaleV = - static_cast(tile.texture->Height()) / static_cast(tile.texture->TextureHeight()); + const float scaleU = static_cast(tile.texture->Width()) / static_cast(tile.texture->TextureWidth()); + const float scaleV = static_cast(tile.texture->Height()) / static_cast(tile.texture->TextureHeight()); GroundLightmap& lightmap = this->lightmaps[lightmapIndex]; + tile.lightmap = &lightmap; tile.lightmapTexture = lightmap.texture; @@ -216,6 +189,7 @@ void GroundGeometry::Build( float* second = normals[index].values[1]; const float ab = cell.heights[2] - cell.heights[0]; const float ac = cell.heights[2] - cell.heights[1]; + first[0] = ac * (this->cellSize - 0.0f) - (this->cellSize - 0.0f) * ab; first[1] = (this->cellSize - 0.0f) * 0.0f - (this->cellSize - 0.0f) * (0.0f - this->cellSize); first[2] = ab * (0.0f - this->cellSize) - ac * 0.0f; @@ -225,6 +199,7 @@ void GroundGeometry::Build( const float dz = this->cellSize - 0.0f; const float dx = this->cellSize - 0.0f; const float zero = this->cellSize - this->cellSize; + second[0] = db * zero - dx * dc; second[1] = dz * dx - zero * zero; second[2] = zero * dc - dz * db; @@ -242,13 +217,11 @@ void GroundGeometry::Build( for (int row = 0; row < this->height; ++row) { for (int column = 0; column < this->width; ++column) { - const unsigned index = - static_cast(row) * static_cast(this->width) + static_cast(column); + const unsigned index = static_cast(row) * static_cast(this->width) + static_cast(column); GroundCell& cell = this->cells[index]; const auto neighbor = [&](int x, int y) -> const GroundCell* { return x >= 0 && x < this->width && y >= 0 && y < this->height - ? &this - ->cells[static_cast(y) * static_cast(this->width) + static_cast(x)] + ? &this->cells[static_cast(y) * static_cast(this->width) + static_cast(x)] : nullptr; }; const GroundCell* north = neighbor(column, row - 1); @@ -336,9 +309,7 @@ void GroundGeometry::Build( if (cell.side2) { for (unsigned corner = 0; corner < 4; ++corner) { const GroundCell* source = (corner & 1) ? southeast : south; - const auto color = LitColor( - normals[index].values[2], false, true, lightDirection, diffuse, ambient, source ? source->top : nullptr - ); + const auto color = LitColor(normals[index].values[2], false, true, lightDirection, diffuse, ambient, source ? source->top : nullptr); cell.side2->vertices[corner][3] = std::bit_cast(color); } } @@ -346,9 +317,7 @@ void GroundGeometry::Build( if (cell.side1) { for (unsigned corner = 0; corner < 4; ++corner) { const GroundCell* source = (corner & 1) ? east : southeast; - const auto color = LitColor( - normals[index].values[3], false, true, lightDirection, diffuse, ambient, source ? source->top : nullptr - ); + const auto color = LitColor(normals[index].values[3], false, true, lightDirection, diffuse, ambient, source ? source->top : nullptr); cell.side1->vertices[corner][3] = std::bit_cast(color); } } diff --git a/Source/Contents/GroundGeometry.h b/Source/Contents/Ground/GroundGeometry.h similarity index 59% rename from Source/Contents/GroundGeometry.h rename to Source/Contents/Ground/GroundGeometry.h index fb55280..f48375f 100644 --- a/Source/Contents/GroundGeometry.h +++ b/Source/Contents/Ground/GroundGeometry.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_GROUNDGEOMETRY_H -#define RAGNAROK_SOURCE_CONTENTS_GROUNDGEOMETRY_H +#ifndef RAGNAROK_SOURCE_CONTENTS_GROUND_GROUNDGEOMETRY_H +#define RAGNAROK_SOURCE_CONTENTS_GROUND_GROUNDGEOMETRY_H -#include "Contents/GroundSpatial.h" -#include "Contents/GroundWaterState.h" +#include "Contents/Ground/GroundSpatial.h" +#include "Contents/Ground/GroundWaterState.h" #include @@ -17,21 +17,13 @@ struct GroundLightmap { std::uint32_t unknown_0028[4]; }; -// Recovered C3dGround15 geometry ownership. Device dispatch remains outside -// this owner; all tile/lightmap construction and lighting are concrete. class GroundGeometry { public: GroundGeometry(); ~GroundGeometry(); GroundGeometry(const GroundGeometry&) = delete; GroundGeometry& operator=(const GroundGeometry&) = delete; - void Build( - CGndRes& resource, - TextureCache& textures, - const float* lightDirection, - const float* diffuse, - const float* ambient - ); + void Build(CGndRes& resource, TextureCache& textures, const float* lightDirection, const float* diffuse, const float* ambient); void ClearGeometry(); void Reset(int columns, int rows); GroundSpatial Spatial() const; @@ -42,63 +34,24 @@ public: void MarkRay(const float* ray, int column, int row, float limit); bool CellRectangle(const class C3dAttr& terrain, int column, int row, float* vertices) const; void DrawCellDecal( - const class C3dAttr& terrain, - const float* matrix, - int column, - int row, - std::uint32_t color, - CTexture& texture, - const float* uv, + const class C3dAttr& terrain, const float* matrix, int column, int row, std::uint32_t color, CTexture& texture, const float* uv, GroundRenderContext& context ) const; void DrawGridDecal( - const class C3dAttr& terrain, - const float* matrix, - int column, - int row, - std::uint32_t color, - CTexture& texture, - const float* uv, + const class C3dAttr& terrain, const float* matrix, int column, int row, std::uint32_t color, CTexture& texture, const float* uv, GroundRenderContext& context ) const; void DrawGrid( - const class C3dAttr& terrain, - const float* matrix, - int column, - int row, - std::uint32_t color, - TextureCache& textures, - GroundRenderContext& context + const class C3dAttr& terrain, const float* matrix, int column, int row, std::uint32_t color, TextureCache& textures, GroundRenderContext& context ) const; void DrawTerrainOverlay( - const class C3dAttr& terrain, - const float* matrix, - int column, - int row, - std::uint32_t color, - CTexture* texture, - GroundRenderContext& context + const class C3dAttr& terrain, const float* matrix, int column, int row, std::uint32_t color, CTexture* texture, GroundRenderContext& context ) const; - void DrawWaterCell( - int column, - int row, - GroundCell& cell, - const float* matrix, - const float* ambient, - bool overrideColor, - GroundRenderContext& context - ); + void DrawWaterCell(int column, int row, GroundCell& cell, const float* matrix, const float* ambient, bool overrideColor, GroundRenderContext& context); void DrawLit(const float* matrix, const int* rectangle, bool clip, struct GroundLightingContext& context); void WorldColor(float x, float unusedY, float z, std::uint32_t* output) const; void Lighting(int column, int row, float& red, float& green, float& blue) const; - void LightmapSample( - int column, - int row, - unsigned char& alpha, - unsigned char& red, - unsigned char& green, - unsigned char& blue - ) const; + void LightmapSample(int column, int row, unsigned char& alpha, unsigned char& red, unsigned char& green, unsigned char& blue) const; bool TerrainCellCorners(const class C3dAttr& terrain, int column, int row, float* vertices) const; void InitializeLighting(const class C3dAttr& terrain); diff --git a/Source/Contents/GroundLighting.cpp b/Source/Contents/Ground/GroundLighting.cpp similarity index 74% rename from Source/Contents/GroundLighting.cpp rename to Source/Contents/Ground/GroundLighting.cpp index 3b085f5..48f3040 100644 --- a/Source/Contents/GroundLighting.cpp +++ b/Source/Contents/Ground/GroundLighting.cpp @@ -1,14 +1,14 @@ -#include "Contents/GroundGeometry.h" -#include "Contents/GroundRendering.h" -#include "Contents/ServiceOptions.h" -#include "Render/LightmappedPrimitive.h" -#include "Render/RenderPrimitivePool.h" -#include "Render/RenderProjection.h" -#include "Render/RenderQueues.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Contents/Ground/GroundRendering.h" +#include "Contents/Configuration/ServiceOptions.h" +#include "Render/Primitives/LightmappedPrimitive.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Projection/RenderProjection.h" +#include "Render/Primitives/RenderQueues.h" +#include "Utility/Math/ScalarConversion.h" #include #include -#include // OFFSET: 0x00AC1D30 // FUNCTION: fn_17592 @@ -40,7 +40,7 @@ void DrawLightmappedGround(const float* matrix, const GroundQuad& quad, bool cli for (unsigned channel = 0; channel < 3; ++channel) { const unsigned shift = 16 - channel * 8; const float value = static_cast((color >> shift) & 255u) * scales[channel]; - const unsigned byte = static_cast(_mm_cvttss_si32(_mm_set_ss(value))) & 255u; + const unsigned byte = static_cast(TruncateToInt(value)) & 255u; color = (color & ~(255u << shift)) | (byte << shift); } } @@ -48,7 +48,6 @@ void DrawLightmappedGround(const float* matrix, const GroundQuad& quad, bool cli vertices[corner].diffuse = color; } - // The option is queried a second time on the separate-pass branch. const bool enabled = context.options.Get(119) != 0; if (context.multitexture && enabled) { @@ -62,9 +61,8 @@ void DrawLightmappedGround(const float* matrix, const GroundQuad& quad, bool cli primitive->texture = quad.texture; primitive->lightmap = quad.lightmapTexture; - context.render.queues.lightmapped.Submit( - primitive, 0, context.render.depthAlpha, context.render.depthStart, context.render.depthEnd - ); + context.render.queues.lightmapped.Submit(primitive, 0, context.render.depthAlpha, context.render.depthStart, context.render.depthEnd); + return; } @@ -78,17 +76,13 @@ void DrawLightmappedGround(const float* matrix, const GroundQuad& quad, bool cli } lightmap->texture = quad.lightmapTexture; - context.render.queues.Submit( - lightmap, 0x1000, context.render.depthAlpha, context.render.depthStart, context.render.depthEnd - ); + context.render.queues.Submit(lightmap, 0x1000, context.render.depthAlpha, context.render.depthStart, context.render.depthEnd); } RenderPrimitive* primitive = context.render.primitives.Acquire(); std::memcpy(primitive->vertices, vertices, sizeof(vertices)); primitive->texture = quad.texture; - context.render.queues.Submit( - primitive, 0x800, context.render.depthAlpha, context.render.depthStart, context.render.depthEnd - ); + context.render.queues.Submit(primitive, 0x800, context.render.depthAlpha, context.render.depthStart, context.render.depthEnd); } // OFFSET: 0x00AC15A0 @@ -100,8 +94,7 @@ void GroundGeometry::DrawLit(const float* matrix, const int* rectangle, bool cli int column = rectangle[0]; while (column <= rectangle[2]) { - const unsigned index = - static_cast(column) + static_cast(row) * static_cast(this->width); + const unsigned index = static_cast(column) + static_cast(row) * static_cast(this->width); GroundCell& cell = this->cells[index]; if (cell.frame != context.render.frame) { @@ -121,9 +114,9 @@ void GroundGeometry::DrawLit(const float* matrix, const int* rectangle, bool cli } } - column = std::bit_cast(static_cast(column) + 1u); + ++column; } - row = std::bit_cast(static_cast(row) + 1u); + ++row; } } diff --git a/Source/Contents/GroundLightingInitialization.cpp b/Source/Contents/Ground/GroundLightingInitialization.cpp similarity index 64% rename from Source/Contents/GroundLightingInitialization.cpp rename to Source/Contents/Ground/GroundLightingInitialization.cpp index 7378edb..35d4e05 100644 --- a/Source/Contents/GroundLightingInitialization.cpp +++ b/Source/Contents/Ground/GroundLightingInitialization.cpp @@ -1,20 +1,13 @@ -#include "Contents/GroundGeometry.h" -#include "Resource/TerrainResource.h" - -#include -#include +#include "Contents/Ground/GroundGeometry.h" +#include "Resource/World/TerrainResource.h" // OFFSET: 0x00ABFB10 // FUNCTION: fn_17558 void GroundGeometry::InitializeLighting(const C3dAttr& terrain) { - // The original opens with a virtual slot 10 predicate (vtable 0x011591F8 -> 0x00AC1520, - // 0x00AC1520 = "mov al, 1; retn"), so its early return is unreachable for this class and - // no dispatch is modeled here. The terrain grid lives at original +0x4, before this view, - // which is why it arrives as a borrowed parameter instead of a member. // STATIC: 0x01348128; center, north, south, east, west in that order. constexpr int offsets[5][2] = {{0, 0}, {0, -1}, {0, 1}, {1, 0}, {-1, 0}}; - const int columns = std::bit_cast(2u * static_cast(this->width)); - const int rows = std::bit_cast(2u * static_cast(this->height)); + const int columns = 2 * this->width; + const int rows = 2 * this->height; for (int row = 0; row < rows; ++row) { for (int column = 0; column < columns; ++column) { @@ -32,7 +25,6 @@ void GroundGeometry::InitializeLighting(const C3dAttr& terrain) { float green = 1.0f; float blue = 1.0f; - // COMISS/JB excludes unordered averages, unlike an inverted < predicate. if (average >= minimum - 2.5f) { unsigned sums[4]{}; @@ -52,8 +44,8 @@ void GroundGeometry::InitializeLighting(const C3dAttr& terrain) { red = ((static_cast(sums[1]) / 5.0f) * 0.0078125f) + alpha; green = ((static_cast(sums[2]) / 5.0f) * 0.0078125f) + alpha; blue = ((static_cast(sums[3]) / 5.0f) * 0.0078125f) + alpha; - const float first = _mm_cvtss_f32(_mm_max_ss(_mm_set_ss(green), _mm_set_ss(red))); - const float largest = _mm_cvtss_f32(_mm_max_ss(_mm_set_ss(blue), _mm_set_ss(first))); + const float first = green > red ? green : red; + const float largest = blue > first ? blue : first; if (largest > 1.0f) { red = red / largest; @@ -63,8 +55,7 @@ void GroundGeometry::InitializeLighting(const C3dAttr& terrain) { } if (!this->lighting.empty()) { - const auto index = - static_cast(column) + 2u * static_cast(row) * static_cast(this->width); + const auto index = static_cast(column) + 2u * static_cast(row) * static_cast(this->width); this->lighting[index] = {red, green, blue}; } } diff --git a/Source/Contents/GroundLightmaps.cpp b/Source/Contents/Ground/GroundLightmaps.cpp similarity index 81% rename from Source/Contents/GroundLightmaps.cpp rename to Source/Contents/Ground/GroundLightmaps.cpp index 819ad61..63f4b79 100644 --- a/Source/Contents/GroundLightmaps.cpp +++ b/Source/Contents/Ground/GroundLightmaps.cpp @@ -1,7 +1,7 @@ -#include "Contents/GroundGeometry.h" -#include "Render/Texture.h" -#include "Render/TextureCache.h" -#include "Resource/GroundResource.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/World/GroundResource.h" #include #include @@ -36,9 +36,9 @@ void GroundGeometry::BuildLightmaps(CGndRes& resource, TextureCache& textures) { for (unsigned y = 0; y < 8; ++y) { for (unsigned x = 0; x < 8; ++x) { const unsigned pixel = y * 8 + x; - pixels[(row * 8 + y) * 256 + column * 8 + x] = - (static_cast(decoded[pixel]) << 24) | (static_cast(decoded[64 + pixel * 3]) << 16) | - (static_cast(decoded[65 + pixel * 3]) << 8) | decoded[66 + pixel * 3]; + pixels[(row * 8 + y) * 256 + column * 8 + x] = (static_cast(decoded[pixel]) << 24) | + (static_cast(decoded[64 + pixel * 3]) << 16) | + (static_cast(decoded[65 + pixel * 3]) << 8) | decoded[66 + pixel * 3]; } } @@ -47,6 +47,7 @@ void GroundGeometry::BuildLightmaps(CGndRes& resource, TextureCache& textures) { const float right = std::clamp(static_cast(8 * column + 7) / 256.0f, 0.0f, 1.0f); const float top = std::clamp(static_cast(8 * row + 1) / 256.0f, 0.0f, 1.0f); const float bottom = std::clamp(static_cast(8 * row + 7) / 256.0f, 0.0f, 1.0f); + map.uv[0][0] = left; map.uv[0][1] = top; map.uv[1][0] = right; @@ -62,8 +63,7 @@ void GroundGeometry::BuildLightmaps(CGndRes& resource, TextureCache& textures) { for (unsigned corner = 0; corner < 4; ++corner) { const unsigned pixel = samples[corner]; - map.unknown_0028[corner] = (static_cast(decoded[pixel]) << 24) | - (static_cast(decoded[64 + pixel * 3]) << 16) | + map.unknown_0028[corner] = (static_cast(decoded[pixel]) << 24) | (static_cast(decoded[64 + pixel * 3]) << 16) | (static_cast(decoded[65 + pixel * 3]) << 8) | decoded[66 + pixel * 3]; } } diff --git a/Source/Contents/GroundPicking.cpp b/Source/Contents/Ground/GroundPicking.cpp similarity index 76% rename from Source/Contents/GroundPicking.cpp rename to Source/Contents/Ground/GroundPicking.cpp index 5be773a..28ab247 100644 --- a/Source/Contents/GroundPicking.cpp +++ b/Source/Contents/Ground/GroundPicking.cpp @@ -1,6 +1,6 @@ -#include "Contents/GroundGeometry.h" -#include "Resource/TerrainResource.h" -#include "Utility/RayTriangle.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Resource/World/TerrainResource.h" +#include "Utility/Math/RayTriangle.h" #include @@ -15,8 +15,7 @@ void GroundGeometry::CellBounds(int column, int row, float& minimum, float& maxi minimum = 999999.0f; maximum = -999999.0f; - const GroundQuad* quad = - this->cells[static_cast(column) + static_cast(row) * static_cast(this->width)].top; + const GroundQuad* quad = this->cells[static_cast(column) + static_cast(row) * static_cast(this->width)].top; if (quad) { const float heights[4] = {quad->vertices[0][1], quad->vertices[1][1], quad->vertices[2][1], quad->vertices[3][1]}; @@ -50,7 +49,6 @@ bool GroundGeometry::OverlayHeights(const C3dAttr& terrain, float* vertices, int } for (unsigned corner = 0; corner < 4; ++corner) { - // Outputs may overlap the source record; do not snapshot the heights. vertices[corner * 3 + 1] = cell->heights[corner]; } @@ -64,10 +62,7 @@ bool GroundGeometry::CellVertices(const C3dAttr& terrain, float* vertices, int c return false; } - const GroundQuad* quad = - this - ->cells[static_cast(column >> 1) + static_cast(row >> 1) * static_cast(this->width)] - .top; + const GroundQuad* quad = this->cells[static_cast(column >> 1) + static_cast(row >> 1) * static_cast(this->width)].top; if (!quad) { return false; @@ -90,8 +85,7 @@ void GroundGeometry::MarkRay(const float* ray, int column, int row, float limit) return; } - GroundCell& cell = - this->cells[static_cast(column) + static_cast(row) * static_cast(this->width)]; + GroundCell& cell = this->cells[static_cast(column) + static_cast(row) * static_cast(this->width)]; GroundQuad* quads[3] = {cell.top, cell.side2, cell.side1}; for (GroundQuad* quad : quads) { @@ -113,10 +107,7 @@ void GroundGeometry::MarkRay(const float* ray, int column, int row, float limit) quad->selected = 1; } - if ( - quad->selected == 0 && IntersectRayTriangle(ray, vertices[1], vertices[3], vertices[2], u, v, distance) && - limit > distance - ) { + if (quad->selected == 0 && IntersectRayTriangle(ray, vertices[1], vertices[3], vertices[2], u, v, distance) && limit > distance) { quad->selected = 1; } } diff --git a/Source/Contents/GroundRendering.cpp b/Source/Contents/Ground/GroundRendering.cpp similarity index 85% rename from Source/Contents/GroundRendering.cpp rename to Source/Contents/Ground/GroundRendering.cpp index 6b78c1d..91fcbbd 100644 --- a/Source/Contents/GroundRendering.cpp +++ b/Source/Contents/Ground/GroundRendering.cpp @@ -1,14 +1,13 @@ -#include "Contents/GroundGeometry.h" -#include "Contents/GroundRendering.h" -#include "Render/RenderPrimitivePool.h" -#include "Render/RenderProjection.h" -#include "Render/RenderQueues.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Contents/Ground/GroundRendering.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Projection/RenderProjection.h" +#include "Render/Primitives/RenderQueues.h" #include #include namespace { - // COMISS/CMOVBE chooses the first candidate on equality and unordered inputs. float Minimum4(float a, float b, float c, float d) { const float first = !(a > b) ? a : b; const float second = !(c > d) ? c : d; @@ -20,7 +19,6 @@ namespace { const float second = !(d > c) ? c : d; return second > first ? second : first; } - } bool GroundQuadVisible(const RenderVertex* vertices, const GroundRenderContext& context) { @@ -98,8 +96,7 @@ void GroundGeometry::Draw(const float* matrix, const int* rectangle, bool clip, int column = rectangle[0]; while (column <= rectangle[2]) { - const unsigned index = - static_cast(column) + static_cast(row) * static_cast(this->width); + const unsigned index = static_cast(column) + static_cast(row) * static_cast(this->width); GroundCell& cell = this->cells[index]; if (cell.frame != context.frame) { @@ -118,9 +115,9 @@ void GroundGeometry::Draw(const float* matrix, const int* rectangle, bool clip, } } - column = std::bit_cast(static_cast(column) + 1u); + column = column + 1; } - row = std::bit_cast(static_cast(row) + 1u); + row = row + 1; } } diff --git a/Source/Contents/GroundRendering.h b/Source/Contents/Ground/GroundRendering.h similarity index 89% rename from Source/Contents/GroundRendering.h rename to Source/Contents/Ground/GroundRendering.h index 70e7a9b..857958b 100644 --- a/Source/Contents/GroundRendering.h +++ b/Source/Contents/Ground/GroundRendering.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_GROUNDRENDERING_H -#define RAGNAROK_SOURCE_CONTENTS_GROUNDRENDERING_H +#ifndef RAGNAROK_SOURCE_CONTENTS_GROUND_GROUNDRENDERING_H +#define RAGNAROK_SOURCE_CONTENTS_GROUND_GROUNDRENDERING_H #include diff --git a/Source/Contents/GroundSamples.cpp b/Source/Contents/Ground/GroundSamples.cpp similarity index 57% rename from Source/Contents/GroundSamples.cpp rename to Source/Contents/Ground/GroundSamples.cpp index da90866..bfd9fb7 100644 --- a/Source/Contents/GroundSamples.cpp +++ b/Source/Contents/Ground/GroundSamples.cpp @@ -1,7 +1,5 @@ -#include "Contents/GroundGeometry.h" -#include "Resource/TerrainResource.h" - -#include +#include "Contents/Ground/GroundGeometry.h" +#include "Resource/World/TerrainResource.h" // OFFSET: 0x00AC09B0 // FUNCTION: fn_17568 @@ -14,11 +12,11 @@ void GroundGeometry::WorldColor(float x, float, float z, std::uint32_t* output) output[1] = 255; output[0] = 255; output[2] = 255; + return; } - const GroundCell& cell = - this->cells[static_cast(column) + static_cast(row) * static_cast(this->width)]; + const GroundCell& cell = this->cells[static_cast(column) + static_cast(row) * static_cast(this->width)]; output[0] = cell.color[0]; output[1] = cell.color[1]; output[2] = cell.color[2]; @@ -31,11 +29,11 @@ void GroundGeometry::Lighting(int column, int row, float& red, float& green, flo red = 1.0f; green = 1.0f; blue = 1.0f; + return; } - const unsigned index = - static_cast(column) + 2u * static_cast(row) * static_cast(this->width); + const unsigned index = static_cast(column) + 2u * static_cast(row) * static_cast(this->width); red = this->lighting[index][0]; green = this->lighting[index][1]; blue = this->lighting[index][2]; @@ -43,21 +41,13 @@ void GroundGeometry::Lighting(int column, int row, float& red, float& green, flo // OFFSET: 0x00AC11D0 // FUNCTION: fn_17579 -void GroundGeometry::LightmapSample( - int column, - int row, - unsigned char& alpha, - unsigned char& red, - unsigned char& green, - unsigned char& blue -) const { +void GroundGeometry::LightmapSample(int column, int row, unsigned char& alpha, unsigned char& red, unsigned char& green, unsigned char& blue) const { if (column < 0 || (column >> 1) >= this->width || row < 0 || (row >> 1) >= this->height || this->cells.empty()) { alpha = red = green = blue = 255; return; } - const unsigned index = - static_cast(column >> 1) + static_cast(row >> 1) * static_cast(this->width); + const unsigned index = static_cast(column >> 1) + static_cast(row >> 1) * static_cast(this->width); if (!this->cells[index].top || !this->cells[index].top->lightmap) { alpha = red = green = blue = 255; @@ -65,10 +55,8 @@ void GroundGeometry::LightmapSample( } const unsigned sample = (static_cast(column) & 1u) + 2u * (static_cast(row) & 1u); - // Re-read the owner for each output store: outputs can alias sampled bytes. - const auto read = [&](unsigned shift) { - return static_cast(this->cells[index].top->lightmap->unknown_0028[sample] >> shift); - }; + + const auto read = [&](unsigned shift) { return static_cast(this->cells[index].top->lightmap->unknown_0028[sample] >> shift); }; alpha = read(24); red = read(16); green = read(8); @@ -78,20 +66,21 @@ void GroundGeometry::LightmapSample( // OFFSET: 0x00AC0C40 // FUNCTION: fn_17570 bool GroundGeometry::TerrainCellCorners(const C3dAttr& terrain, int column, int row, float* vertices) const { - const int columns = std::bit_cast(2u * static_cast(this->width)); - const int rows = std::bit_cast(2u * static_cast(this->height)); + const int columns = 2 * this->width; + const int rows = 2 * this->height; if (column < 0 || columns < column || row < 0 || rows < row) { return false; } const float size = this->cellSize * 0.5f; - const unsigned dx = static_cast(column) - static_cast(this->width); - const unsigned dz = static_cast(row) - static_cast(this->height); - const float left = static_cast(std::bit_cast(dx)) * size; - const float right = static_cast(std::bit_cast(dx + 1u)) * size; - const float top = static_cast(std::bit_cast(dz)) * size; - const float bottom = static_cast(std::bit_cast(dz + 1u)) * size; + const int dx = column - this->width; + const int dz = row - this->height; + const float left = static_cast(dx) * size; + const float right = static_cast(dx + 1) * size; + const float top = static_cast(dz) * size; + const float bottom = static_cast(dz + 1) * size; + vertices[1] = 0.0f; vertices[4] = 0.0f; vertices[7] = 0.0f; @@ -104,5 +93,6 @@ bool GroundGeometry::TerrainCellCorners(const C3dAttr& terrain, int column, int vertices[8] = bottom; vertices[9] = right; vertices[11] = bottom; + return this->OverlayHeights(terrain, vertices, column, row); } diff --git a/Source/Contents/GroundSpatial.cpp b/Source/Contents/Ground/GroundSpatial.cpp similarity index 62% rename from Source/Contents/GroundSpatial.cpp rename to Source/Contents/Ground/GroundSpatial.cpp index 8140130..f54a619 100644 --- a/Source/Contents/GroundSpatial.cpp +++ b/Source/Contents/Ground/GroundSpatial.cpp @@ -1,8 +1,7 @@ -#include "Contents/GroundSpatial.h" +#include "Contents/Ground/GroundSpatial.h" +#include "Utility/Math/ScalarConversion.h" -#include #include -#include // OFFSET: 0x00ABD8F0 // FUNCTION: fn_17548 @@ -23,23 +22,16 @@ GroundCell::GroundCell() : corners{}, top(nullptr), side1(nullptr), side2(nullpt // FUNCTION: fn_17562 void GroundSpatial::SpatialCell(float x, float z, int& column, int& row) const { const float first = static_cast(std::floor(static_cast(x / this->cellSize))); - column = std::bit_cast( - static_cast(_mm_cvttss_si32(_mm_set_ss(first))) + static_cast(this->width / 2) - ); + column = TruncateToInt(first) + this->width / 2; const float second = static_cast(std::floor(static_cast(z / this->cellSize))); - row = std::bit_cast( - static_cast(_mm_cvttss_si32(_mm_set_ss(second))) + static_cast(this->height / 2) - ); + row = TruncateToInt(second) + this->height / 2; } // OFFSET: 0x00AC0EA0 // FUNCTION: fn_17573 void GroundSpatial::HeightBounds(const int* rectangle, float& minimum, float& maximum) const { - if ( - rectangle[0] < 0 || rectangle[0] >= this->width || rectangle[2] < 0 || rectangle[2] >= this->width || - rectangle[1] < 0 || rectangle[1] >= this->height || rectangle[3] < 0 || rectangle[3] >= this->height || - rectangle[2] <= rectangle[0] || rectangle[3] <= rectangle[1] - ) { + if (rectangle[0] < 0 || rectangle[0] >= this->width || rectangle[2] < 0 || rectangle[2] >= this->width || rectangle[1] < 0 || rectangle[1] >= this->height || + rectangle[3] < 0 || rectangle[3] >= this->height || rectangle[2] <= rectangle[0] || rectangle[3] <= rectangle[1]) { minimum = 0.0f; maximum = 0.0f; return; @@ -53,8 +45,7 @@ void GroundSpatial::HeightBounds(const int* rectangle, float& minimum, float& ma int row = rectangle[1]; while (row <= rectangle[3]) { - const auto index = - static_cast(column) + static_cast(row) * static_cast(this->width); + const auto index = static_cast(column) + static_cast(row) * static_cast(this->width); const GroundQuad* top = this->cells[index].top; if (top) { @@ -73,9 +64,9 @@ void GroundSpatial::HeightBounds(const int* rectangle, float& minimum, float& ma } } - row = std::bit_cast(static_cast(row) + 1u); + ++row; } - column = std::bit_cast(static_cast(column) + 1u); + ++column; } } diff --git a/Source/Contents/GroundSpatial.h b/Source/Contents/Ground/GroundSpatial.h similarity index 76% rename from Source/Contents/GroundSpatial.h rename to Source/Contents/Ground/GroundSpatial.h index a7fed8f..dd6e9ee 100644 --- a/Source/Contents/GroundSpatial.h +++ b/Source/Contents/Ground/GroundSpatial.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_GROUNDSPATIAL_H -#define RAGNAROK_SOURCE_CONTENTS_GROUNDSPATIAL_H +#ifndef RAGNAROK_SOURCE_CONTENTS_GROUND_GROUNDSPATIAL_H +#define RAGNAROK_SOURCE_CONTENTS_GROUND_GROUNDSPATIAL_H #include #include @@ -7,7 +7,6 @@ class CTexture; struct GroundLightmap; -// Original C3dGround15 tile geometry; texture references are borrowed. struct GroundQuad { GroundQuad(); @@ -34,8 +33,6 @@ struct GroundCell { /* 0053 */ unsigned char unknown_0053; }; -// Original ground fields +0x08/+0x0C/+0x10 and cell vector +0x7C. -// These references borrow the ground owner; this is not a second geometry cache. struct GroundSpatial { const int& width; const int& height; diff --git a/Source/Contents/GroundWaterRendering.cpp b/Source/Contents/Ground/GroundWaterRendering.cpp similarity index 76% rename from Source/Contents/GroundWaterRendering.cpp rename to Source/Contents/Ground/GroundWaterRendering.cpp index c69cd54..5caf584 100644 --- a/Source/Contents/GroundWaterRendering.cpp +++ b/Source/Contents/Ground/GroundWaterRendering.cpp @@ -1,25 +1,19 @@ -#include "Contents/GroundGeometry.h" -#include "Contents/GroundRendering.h" -#include "Render/RenderPrimitivePool.h" -#include "Render/RenderProjection.h" -#include "Render/RenderQueues.h" -#include "Utility/AffineMatrix.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Contents/Ground/GroundRendering.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Projection/RenderProjection.h" +#include "Render/Primitives/RenderQueues.h" +#include "Utility/Math/AffineMatrix.h" +#include "Utility/Math/ScalarConversion.h" #include #include #include -#include // OFFSET: 0x00AC2B80 // FUNCTION: fn_17594 void GroundGeometry::DrawWaterCell( - int column, - int row, - GroundCell& cell, - const float* matrix, - const float* ambient, - bool overrideColor, - GroundRenderContext& context + int column, int row, GroundCell& cell, const float* matrix, const float* ambient, bool overrideColor, GroundRenderContext& context ) { const float level = this->water.Level(this->width, this->height, column, row); unsigned partition = 0; @@ -36,15 +30,15 @@ void GroundGeometry::DrawWaterCell( float last = level; if (surface.height != 0.0f) { - const auto sum = static_cast(column) + static_cast(row); - const auto wave = [&](unsigned coordinate) { - const float angle = static_cast(std::bit_cast(coordinate)) * surface.pitch + surface.phase; - const int degrees = _mm_cvttss_si32(_mm_set_ss(angle)); + const int sum = column + row; + const auto wave = [&](int coordinate) { + const float angle = static_cast(coordinate) * surface.pitch + surface.phase; + const int degrees = TruncateToInt(angle); return ClientSine(degrees) * surface.height + level; }; middle = wave(sum); - first = wave(sum - 1u); - last = wave(sum + 1u); + first = wave(sum - 1); + last = wave(sum + 1); } bool above = false; @@ -87,7 +81,7 @@ void GroundGeometry::DrawWaterCell( for (unsigned channel = 0; channel < 3; ++channel) { const float scaled = ambient[channel] * 255.0f; - color |= (static_cast(_mm_cvttss_si32(_mm_set_ss(scaled))) & 255u) << (16 - 8 * channel); + color |= (static_cast(TruncateToInt(scaled)) & 255u) << (16 - 8 * channel); } } diff --git a/Source/Contents/GroundWaterState.cpp b/Source/Contents/Ground/GroundWaterState.cpp similarity index 62% rename from Source/Contents/GroundWaterState.cpp rename to Source/Contents/Ground/GroundWaterState.cpp index 1526c67..ec95b32 100644 --- a/Source/Contents/GroundWaterState.cpp +++ b/Source/Contents/Ground/GroundWaterState.cpp @@ -1,17 +1,14 @@ -#include "Contents/GroundWaterState.h" -#include "Render/TextureCache.h" -#include "Resource/GroundResource.h" +#include "Contents/Ground/GroundWaterState.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/World/GroundResource.h" +#include "Utility/Math/ScalarConversion.h" #include -#include #include -#include -#include // OFFSET: 0x00ABD640 // FUNCTION: fn_17546 -GroundWaterState::GroundWaterState() - : level(0.0f), animation(3), pitch(50), phase(2), type(0), height(1.0f), columns(1), rows(1), partitioned(false) { +GroundWaterState::GroundWaterState() : level(0.0f), animation(3), pitch(50), phase(2), type(0), height(1.0f), columns(1), rows(1), partitioned(false) { } // OFFSET: 0x00AC3320 @@ -33,23 +30,23 @@ bool GroundWaterState::Import(const CGndRes& resource, TextureCache& textures) { this->rows = resource.waterHeight; this->levels = resource.waterHeights; this->surfaces.resize(resource.water.size()); - static_assert(sizeof(GroundWaterSurface) == sizeof(GroundWater)); - if (!resource.water.empty()) { - std::memcpy(this->surfaces.data(), resource.water.data(), resource.water.size() * sizeof(GroundWater)); + for (std::size_t index = 0; index < resource.water.size(); ++index) { + const GroundWaterParameters& parameters = resource.water[index].parameters; + this->surfaces[index] = {parameters.level, parameters.type, parameters.height, parameters.speed, parameters.pitch, parameters.animation, 0, 0.0f, + nullptr}; } - this->animation = std::bit_cast(resource.waterDefault[5]); - this->pitch = _mm_cvttss_si32(_mm_set_ss(std::bit_cast(resource.waterDefault[4]))); - this->phase = _mm_cvttss_si32(_mm_set_ss(std::bit_cast(resource.waterDefault[3]))) % 360; - this->type = std::bit_cast(resource.waterDefault[1]); - this->height = std::bit_cast(resource.waterDefault[2]); + this->animation = resource.waterDefault.animation; + this->pitch = TruncateToInt(resource.waterDefault.pitch); + this->phase = TruncateToInt(resource.waterDefault.speed) % 360; + this->type = resource.waterDefault.type; + this->height = resource.waterDefault.height; } else { this->surfaces.push_back( - {this->level, this->type, this->height, static_cast(this->phase), static_cast(this->pitch), - this->animation, 0, 0.0f, nullptr} + {this->level, this->type, this->height, static_cast(this->phase), static_cast(this->pitch), this->animation, 0, 0.0f, nullptr} ); - this->levels.push_back(std::bit_cast(this->level)); + this->levels.push_back(this->level); } this->Update(textures); @@ -65,7 +62,8 @@ float GroundWaterState::Level(int width, int height, int column, int row) const const int x = std::min(column / cellWidth, this->columns - 1); const int z = std::min(row / cellHeight, this->rows - 1); const unsigned index = static_cast(x) + static_cast(z) * static_cast(this->columns); - return index < this->levels.size() ? std::bit_cast(this->levels[index]) : 0.0f; + + return index < this->levels.size() ? this->levels[index] : 0.0f; } // OFFSET: 0x00AC1430 @@ -76,8 +74,8 @@ void GroundWaterState::Update(TextureCache& textures) { char name[32]{}; for (GroundWaterSurface& surface : this->surfaces) { - surface.frame = std::bit_cast(static_cast(surface.frame) + 1u); - const int end = std::bit_cast(static_cast(surface.animation) << 5); + ++surface.frame; + const int end = surface.animation * 32; if (end <= surface.frame) { surface.frame = 0; diff --git a/Source/Contents/GroundWaterState.h b/Source/Contents/Ground/GroundWaterState.h similarity index 75% rename from Source/Contents/GroundWaterState.h rename to Source/Contents/Ground/GroundWaterState.h index ec8dd69..64c5786 100644 --- a/Source/Contents/GroundWaterState.h +++ b/Source/Contents/Ground/GroundWaterState.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_GROUNDWATERSTATE_H -#define RAGNAROK_SOURCE_CONTENTS_GROUNDWATERSTATE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_GROUND_GROUNDWATERSTATE_H +#define RAGNAROK_SOURCE_CONTENTS_GROUND_GROUNDWATERSTATE_H #include #include @@ -20,8 +20,6 @@ struct GroundWaterSurface { CTexture* texture; }; -// C3dGround fields +0x38..+0x4F and C3dGround15 +0x88..+0xA8. -// Surface texture pointers borrow the name-keyed cache, not owned atlases. struct GroundWaterState { GroundWaterState(); void Set(float level, int type, int animation, int pitch, int phase, float height); @@ -37,7 +35,7 @@ struct GroundWaterState { float height; int columns; int rows; - std::vector levels; + std::vector levels; std::vector surfaces; bool partitioned; }; diff --git a/Source/Contents/TerrainCoordinates.cpp b/Source/Contents/Ground/TerrainCoordinates.cpp similarity index 67% rename from Source/Contents/TerrainCoordinates.cpp rename to Source/Contents/Ground/TerrainCoordinates.cpp index 8a5f3df..69ee303 100644 --- a/Source/Contents/TerrainCoordinates.cpp +++ b/Source/Contents/Ground/TerrainCoordinates.cpp @@ -1,18 +1,13 @@ -#include "Contents/TerrainHeight.h" +#include "Contents/Ground/TerrainHeight.h" +#include "Utility/Math/ScalarConversion.h" -#include #include -#include // OFFSET: 0x00AC8150 // FUNCTION: fn_17666 void TerrainHeight::CellOrigin(int column, int row, float& x, float& z) const { - const auto dx = static_cast(column) - static_cast(this->width / 2); - const auto first = dx * static_cast(this->cellSize); - x = static_cast(std::bit_cast(first)); - const auto dz = static_cast(row) - static_cast(this->height / 2); - const auto second = dz * static_cast(this->cellSize); - z = static_cast(std::bit_cast(second)); + x = static_cast((column - this->width / 2) * this->cellSize); + z = static_cast((row - this->height / 2) * this->cellSize); } // OFFSET: 0x00CD36E0 @@ -21,8 +16,7 @@ void TerrainHeight::CellCenter(int column, int row, float& x, float& z) const { const float size = static_cast(this->cellSize); const float offset = (size * 8.0f) * 0.0625f; x = ((static_cast(column) - static_cast(this->width) * 0.5f) * size) + offset; - z = - ((static_cast(row) - static_cast(this->height) * 0.5f) * static_cast(this->cellSize)) + offset; + z = ((static_cast(row) - static_cast(this->height) * 0.5f) * static_cast(this->cellSize)) + offset; } // OFFSET: 0x00CD5230 @@ -31,10 +25,10 @@ void TerrainHeight::WorldCell(float x, float z, int& column, int& row) const { const float size = static_cast(this->cellSize); const float first = static_cast(this->width / 2) + x / size; const float flooredX = static_cast(std::floor(static_cast(first))); - column = _mm_cvttss_si32(_mm_set_ss(flooredX)); + column = TruncateToInt(flooredX); const float second = static_cast(this->height / 2) + z / size; const float flooredZ = static_cast(std::floor(static_cast(second))); - row = _mm_cvttss_si32(_mm_set_ss(flooredZ)); + row = TruncateToInt(flooredZ); } // OFFSET: 0x00CD50A0 @@ -45,17 +39,17 @@ void TerrainHeight::WorldSubcell(float x, float z, int& column, int& row, int& s const float gridX = static_cast(this->width / 2) + localX; const float flooredX = static_cast(std::floor(static_cast(gridX))); const float localZ = z / size; - column = _mm_cvttss_si32(_mm_set_ss(flooredX)); + column = TruncateToInt(flooredX); const float gridZ = static_cast(this->height / 2) + localZ; const float flooredZ = static_cast(std::floor(static_cast(gridZ))); - row = _mm_cvttss_si32(_mm_set_ss(flooredZ)); + row = TruncateToInt(flooredZ); const float fractionX = (static_cast(this->width / 2) + localX) - static_cast(column); const float sixteenthsX = static_cast(std::floor(static_cast(fractionX * 16.0f))); - subColumn = _mm_cvttss_si32(_mm_set_ss(sixteenthsX)) % 16; + subColumn = TruncateToInt(sixteenthsX) % 16; const float fractionZ = (static_cast(this->height / 2) + localZ) - static_cast(row); const float sixteenthsZ = static_cast(std::floor(static_cast(fractionZ * 16.0f))); - subRow = _mm_cvttss_si32(_mm_set_ss(sixteenthsZ)) % 16; + subRow = TruncateToInt(sixteenthsZ) % 16; } // OFFSET: 0x00A8C790 @@ -63,11 +57,10 @@ void TerrainHeight::WorldSubcell(float x, float z, int& column, int& row, int& s void TerrainHeight::SpatialCell(float x, float z, int& column, int& row) const { const int halfRows = 2 * (this->height / 4); const float first = static_cast(std::floor(static_cast(x / static_cast(this->cellSize)))); - const int firstCell = _mm_cvttss_si32(_mm_set_ss(first)); - column = std::bit_cast(static_cast(firstCell) + static_cast(2 * (this->width / 4))); + const int firstCell = TruncateToInt(first); + column = firstCell + 2 * (this->width / 4); const float second = static_cast(std::floor(static_cast(z / static_cast(this->cellSize)))); - row = - std::bit_cast(static_cast(_mm_cvttss_si32(_mm_set_ss(second))) + static_cast(halfRows)); + row = TruncateToInt(second) + halfRows; } // OFFSET: 0x00748E90 @@ -84,7 +77,6 @@ void TerrainHeight::HeightBounds(const int* rectangle, float& minimum, float& ma const TerrainHeightCell* cell = this->CellAt(column, row); if (cell) { - // Maximum writes precede minimum reads, including aliased outputs. for (float value : cell->heights) { if (value > maximum) { maximum = value; @@ -98,9 +90,9 @@ void TerrainHeight::HeightBounds(const int* rectangle, float& minimum, float& ma } } - row = std::bit_cast(static_cast(row) + 1u); + ++row; } - column = std::bit_cast(static_cast(column) + 1u); + ++column; } } diff --git a/Source/Contents/TerrainHeight.cpp b/Source/Contents/Ground/TerrainHeight.cpp similarity index 56% rename from Source/Contents/TerrainHeight.cpp rename to Source/Contents/Ground/TerrainHeight.cpp index 6ffec75..faee797 100644 --- a/Source/Contents/TerrainHeight.cpp +++ b/Source/Contents/Ground/TerrainHeight.cpp @@ -1,6 +1,6 @@ -#include "Contents/TerrainHeight.h" +#include "Contents/Ground/TerrainHeight.h" -#include +#include "Utility/Math/ScalarConversion.h" // OFFSET: 0x00748D80 // FUNCTION: fn_07838 @@ -8,20 +8,14 @@ float TerrainHeight::Height(float x, float z) const { const float size = static_cast(this->cellSize); const float gridX = (static_cast(this->width) * size) * 0.5f + x; const float gridZ = (static_cast(this->height) * size) * 0.5f + z; - const int column = _mm_cvttss_si32(_mm_set_ss(gridX / size)); - const int row = _mm_cvttss_si32(_mm_set_ss(gridZ / size)); + const int column = TruncateToInt(gridX / size); + const int row = TruncateToInt(gridZ / size); if (column < 0 || column >= this->width || row < 0 || row >= this->height) { return 0.0f; } - // The original checks the computed address, not the array base. Preserve - // that distinction; a null base with a nonzero index is not a valid map. - const auto index = - static_cast(column) + static_cast(row) * static_cast(this->width); - const auto address = - reinterpret_cast(this->cells) + static_cast(index) * sizeof(TerrainHeightCell); - const auto* cell = reinterpret_cast(address); + const TerrainHeightCell* cell = this->cells + column + row * this->width; if (!cell) { return 0.0f; @@ -31,6 +25,7 @@ float TerrainHeight::Height(float x, float z) const { const float first = ((cell->heights[2] - cell->heights[0]) * localZ) / size + cell->heights[0]; const float second = ((cell->heights[3] - cell->heights[1]) * localZ) / size + cell->heights[1]; const float localX = gridX - static_cast(column) * size; + return (localX * (second - first)) / size + first; } @@ -41,11 +36,7 @@ const TerrainHeightCell* TerrainHeight::CellAt(int column, int row) const { return nullptr; } - const auto index = - static_cast(column) + static_cast(row) * static_cast(this->width); - return reinterpret_cast( - reinterpret_cast(this->cells) + static_cast(index) * sizeof(TerrainHeightCell) - ); + return this->cells + column + row * this->width; } // OFFSET: 0x007492A0 diff --git a/Source/Contents/TerrainHeight.h b/Source/Contents/Ground/TerrainHeight.h similarity index 72% rename from Source/Contents/TerrainHeight.h rename to Source/Contents/Ground/TerrainHeight.h index 5a1d29a..8149db1 100644 --- a/Source/Contents/TerrainHeight.h +++ b/Source/Contents/Ground/TerrainHeight.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_TERRAINHEIGHT_H -#define RAGNAROK_SOURCE_CONTENTS_TERRAINHEIGHT_H +#ifndef RAGNAROK_SOURCE_CONTENTS_GROUND_TERRAINHEIGHT_H +#define RAGNAROK_SOURCE_CONTENTS_GROUND_TERRAINHEIGHT_H #include @@ -8,8 +8,6 @@ struct TerrainHeightCell { std::uint32_t type; }; -// Borrowed C3dAttr fields +0x110..+0x11C, reached through the active mode. -// The query neither allocates nor changes cells. struct TerrainHeight { const int& width; const int& height; @@ -23,8 +21,7 @@ struct TerrainHeight { void CellOrigin(int column, int row, float& x, float& z) const; void CellCenter(int column, int row, float& x, float& z) const; void WorldCell(float x, float z, int& column, int& row) const; - // Writes column, row, then signed sixteenth-cell remainders in that order. - // Outputs may alias: each fractional coordinate reloads the stored cell. + void WorldSubcell(float x, float z, int& column, int& row, int& subColumn, int& subRow) const; void SpatialCell(float x, float z, int& column, int& row) const; void HeightBounds(const int* rectangle, float& minimum, float& maximum) const; diff --git a/Source/Contents/Ground/TerrainPicking.cpp b/Source/Contents/Ground/TerrainPicking.cpp new file mode 100644 index 0000000..c779899 --- /dev/null +++ b/Source/Contents/Ground/TerrainPicking.cpp @@ -0,0 +1,38 @@ +#include "Contents/Ground/TerrainHeight.h" +#include "Utility/Math/RayTriangle.h" + +// OFFSET: 0x00749300 +// FUNCTION: fn_07842 +float TerrainHeight::RayDistance(const float* ray, int column, int row) const { + const TerrainHeightCell* cell = this->CellAt(column, row); + + if (!cell) { + return 0.0f; + } + + const float size = static_cast(this->cellSize); + const int x = column - this->width / 2; + const int z = row - this->height / 2; + const float left = static_cast(x) * size; + const float right = static_cast(x + 1) * size; + const float top = static_cast(z) * size; + const float bottom = static_cast(z + 1) * size; + const float first[3] = {left, cell->heights[0], top}; + const float second[3] = {right, cell->heights[1], top}; + const float third[3] = {left, cell->heights[2], bottom}; + const float fourth[3] = {right, cell->heights[3], bottom}; + float nearest = 999999.0f; + float u; + float v; + float distance; + + if (IntersectRayTriangle(ray, first, second, third, u, v, distance)) { + nearest = distance < nearest ? distance : nearest; + } + + if (IntersectRayTriangle(ray, second, fourth, third, u, v, distance)) { + nearest = distance < nearest ? distance : nearest; + } + + return nearest; +} diff --git a/Source/Contents/Ground/TerrainPlane.cpp b/Source/Contents/Ground/TerrainPlane.cpp new file mode 100644 index 0000000..f216ba2 --- /dev/null +++ b/Source/Contents/Ground/TerrainPlane.cpp @@ -0,0 +1,40 @@ +#include "Contents/Ground/TerrainHeight.h" +#include "Utility/Math/ScalarConversion.h" + +// OFFSET: 0x00749040 +// FUNCTION: fn_07840 +float TerrainHeight::PlaneHeight(float x, float z) const { + const float size = static_cast(this->cellSize); + const int columns = this->width; + const int rows = this->height; + const int column = TruncateToInt(((static_cast(columns) * size) * 0.5f + x) / size); + const int row = TruncateToInt(((static_cast(rows) * size) * 0.5f + z) / size); + const TerrainHeightCell* cell = this->CellAt(column, row); + + if (!cell) { + return 0.0f; + } + + const int dx = column - columns / 2; + const int dz = row - rows / 2; + const float left = static_cast(dx) * size; + const float right = static_cast(dx + 1) * size; + const float top = static_cast(dz) * size; + const float bottom = static_cast(dz + 1) * size; + struct Point { + float x; + float y; + float z; + }; + const Point first{left, cell->heights[0], top}; + const Point second{right, cell->heights[1], top}; + const Point third{left, cell->heights[2], bottom}; + const float normalX = ((third.z - first.z) * second.y + (second.z - third.z) * first.y) + (first.z - second.z) * third.y; + const float normalZ = ((third.y - first.y) * second.x + (second.y - third.y) * first.x) + (first.y - second.y) * third.x; + const float constant = (((first.z * third.y - third.z * first.y) * second.x + (third.z * second.y - second.z * third.y) * first.x) + + (second.z * first.y - first.z * second.y) * third.x) * + -1.0f; + const float normalY = ((second.x - third.x) * first.z + (third.x - first.x) * second.z) + (first.x - second.x) * third.z; + + return ((normalX * x + normalZ * z) + constant) * -1.0f / normalY; +} diff --git a/Source/Contents/EmotionHotkeys.cpp b/Source/Contents/Hotkeys/EmotionHotkeys.cpp similarity index 88% rename from Source/Contents/EmotionHotkeys.cpp rename to Source/Contents/Hotkeys/EmotionHotkeys.cpp index 80bb870..9ee893e 100644 --- a/Source/Contents/EmotionHotkeys.cpp +++ b/Source/Contents/Hotkeys/EmotionHotkeys.cpp @@ -1,4 +1,4 @@ -#include "Contents/EmotionHotkeys.h" +#include "Contents/Hotkeys/EmotionHotkeys.h" #include "Contents/MessageTable.h" #include "File/File.h" #include "File/ShortcutFilename.h" @@ -14,9 +14,8 @@ void EmotionHotkeys::Load(Json::Value& data) { Json::Value values = data["EmotionHotkey"]; this->saved.clear(); this->saved.resize(10); + for (Json::UInt i = 0; i < values.size(); ++i) { - // Original requires current's ten slots initialized by the actual default/ - // saved-script load path; do not invent those defaults here. this->current[i] = FromUtf8(values[i].asString(), g_textCodePage); this->saved[i] = FromUtf8(values[i].asString(), g_textCodePage); } @@ -31,8 +30,10 @@ bool EmotionHotkeys::HasChanges() const { return true; } } + return false; } + return true; } @@ -42,18 +43,22 @@ void EmotionHotkeys::Save(std::uint32_t accountId, CRenderSystemBase* renderSyst if (this->current.empty()) { return; } + std::string output = "tbl = \r\n{\r\n"; + for (const std::string& entry : this->current) { output += "\t[=["; output += entry; output += "]=],\r\n"; } + output += "}\r\n"; const char* directory = "savedata\\shortcutlist"; if (_access_s(directory, 0) != 0) { _mkdir(directory); } + CFile file; const std::string path = std::string(directory) + "\\" + ShortcutFilename(accountId) + ".lua"; if (file.OpenWrite(path.c_str(), renderSystem)) { @@ -64,21 +69,19 @@ void EmotionHotkeys::Save(std::uint32_t accountId, CRenderSystemBase* renderSyst // OFFSET: 0x00E3D4D0 // FUNCTION: fn_24191 -bool EmotionHotkeys::LoadDefaults( - std::uint32_t accountId, - bool languagePrefix, - int serviceType, - std::uint16_t language -) { +bool EmotionHotkeys::LoadDefaults(std::uint32_t accountId, bool languagePrefix, int serviceType, std::uint16_t language) { this->current.clear(); + for (int id : {544, 545, 546, 547, 549, 550, 551, 552, 553, 554}) { this->current.emplace_back(LookupMessage(id, languagePrefix, serviceType, language)); } + CLuaInstance script; const std::string path = "savedata\\shortcutlist\\" + ShortcutFilename(accountId) + ".lua"; if (!script.LoadFile(path, false) || script.ReadStrings(this->current, "tbl") != 0) { return false; } + return this->current.size() == 10; } @@ -86,8 +89,10 @@ bool EmotionHotkeys::LoadDefaults( // FUNCTION: fn_03469 void EmotionHotkeys::Export(Json::Value& data) const { Json::Value values; + for (unsigned index = 0; index < 10; ++index) { values.append(ToUtf8(this->current[index], g_textCodePage)); } + data["EmotionHotkey"] = values; } diff --git a/Source/Contents/EmotionHotkeys.h b/Source/Contents/Hotkeys/EmotionHotkeys.h similarity index 70% rename from Source/Contents/EmotionHotkeys.h rename to Source/Contents/Hotkeys/EmotionHotkeys.h index 291486a..79e8bb8 100644 --- a/Source/Contents/EmotionHotkeys.h +++ b/Source/Contents/Hotkeys/EmotionHotkeys.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_EMOTIONHOTKEYS_H -#define RAGNAROK_SOURCE_CONTENTS_EMOTIONHOTKEYS_H +#ifndef RAGNAROK_SOURCE_CONTENTS_HOTKEYS_EMOTIONHOTKEYS_H +#define RAGNAROK_SOURCE_CONTENTS_HOTKEYS_EMOTIONHOTKEYS_H #include #include @@ -8,8 +8,6 @@ class CRenderSystemBase; -// Recovered contiguous subobject of the original client state, not a second -// global owner: current at owner+0xFF8, saved at owner+0x1004 on x86. struct EmotionHotkeys { std::vector current; std::vector saved; diff --git a/Source/Contents/HotkeyInfo.cpp b/Source/Contents/Hotkeys/HotkeyInfo.cpp similarity index 96% rename from Source/Contents/HotkeyInfo.cpp rename to Source/Contents/Hotkeys/HotkeyInfo.cpp index 8190729..e6548c1 100644 --- a/Source/Contents/HotkeyInfo.cpp +++ b/Source/Contents/Hotkeys/HotkeyInfo.cpp @@ -1,4 +1,4 @@ -#include "Contents/HotkeyInfo.h" +#include "Contents/Hotkeys/HotkeyInfo.h" #include "Script/LuaScript.h" #include @@ -18,10 +18,12 @@ HotkeyInfo GetHotkeyInfo(LuaScript& script, int tab, int index) { HotkeyInfo value; const char* text = nullptr; const char* description = nullptr; + if (script.Call("GetHotKey", "dd>ddss", tab + 1, index, &value.key1, &value.key2, &text, &description)) { value.text = text; value.description = description; } + return value; } @@ -43,6 +45,7 @@ std::string SkillTooltip(const char* hotkey, const char* name, int level, int sp } else { format = ap != 0 ? "%s %s Use Lv %d (Sp : %d, Ap : %d)" : "%s %s Use Lv %d (Sp : %d)"; } + _snprintf_s(text, sizeof(text), _TRUNCATE, format, hotkey, name, level, sp, ap); return text; } diff --git a/Source/Contents/HotkeyInfo.h b/Source/Contents/Hotkeys/HotkeyInfo.h similarity index 73% rename from Source/Contents/HotkeyInfo.h rename to Source/Contents/Hotkeys/HotkeyInfo.h index 9f204ba..43c75d9 100644 --- a/Source/Contents/HotkeyInfo.h +++ b/Source/Contents/Hotkeys/HotkeyInfo.h @@ -1,10 +1,10 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_HOTKEYINFO_H -#define RAGNAROK_SOURCE_CONTENTS_HOTKEYINFO_H +#ifndef RAGNAROK_SOURCE_CONTENTS_HOTKEYS_HOTKEYINFO_H +#define RAGNAROK_SOURCE_CONTENTS_HOTKEYS_HOTKEYINFO_H #include + class LuaScript; -// Original56-byte hotkey display value, two keys and two owned strings. struct HotkeyInfo { int key1; int key2; diff --git a/Source/Contents/UserHotkeyMgr.cpp b/Source/Contents/Hotkeys/UserHotkeyMgr.cpp similarity index 92% rename from Source/Contents/UserHotkeyMgr.cpp rename to Source/Contents/Hotkeys/UserHotkeyMgr.cpp index fdbd24b..9c1c06f 100644 --- a/Source/Contents/UserHotkeyMgr.cpp +++ b/Source/Contents/Hotkeys/UserHotkeyMgr.cpp @@ -1,4 +1,4 @@ -#include "Contents/UserHotkeyMgr.h" +#include "Contents/Hotkeys/UserHotkeyMgr.h" #include "Network/TextEncoding.h" #include @@ -32,12 +32,15 @@ namespace { if (script.Call("GetOriginalHotKeyListSize", "d>d", tab + 1, &count)) { if (tab == 1) { int hidden = 0; + for (int index = 30; index < count; ++index) { hidden += HiddenInterfaceIndex(index); } + return count - hidden; } } + return count; } @@ -49,6 +52,7 @@ namespace { index += HiddenInterfaceIndex(candidate); } } + int count = 0; script.Call("GetOriginalHotKeyListSize", "d>d", tab + 1, &count); return index >= count ? -1 : index; @@ -73,15 +77,18 @@ bool CUserHotkeyMgr::Initialize() { if (g_userHotkeyMgr) { return false; } + g_userHotkeyMgr = new (std::nothrow) CUserHotkeyMgr; if (!g_userHotkeyMgr) { return false; } + if (!g_userHotkeyMgr->m_enabled) { delete g_userHotkeyMgr; g_userHotkeyMgr = nullptr; return false; } + return true; } @@ -124,16 +131,20 @@ void CUserHotkeyMgr::LoadV2(LuaScript& script, Json::Value& data) { // FUNCTION: fn_04061 void CUserHotkeyMgr::Capture(LuaScript& script) { this->m_original.clear(); + for (int tab : {0, 3, 1, 2}) { const int count = HotkeyCount(script, tab); + for (int row = 0; row < count; ++row) { const int index = HotkeyIndex(script, tab, row); if (index == -1) { continue; } + int key1, key2; const char* keyText = nullptr; const char* description = nullptr; + if (script.Call("GetUserHotKeyInfo", "dd>ddss", tab + 1, index, &key1, &key2, &keyText, &description)) { std::string text = description; if (!text.empty()) { @@ -149,27 +160,25 @@ void CUserHotkeyMgr::Capture(LuaScript& script) { bool CUserHotkeyMgr::HasUserAssignments(LuaScript& script) const { for (int tab : {0, 3, 1, 2}) { const int count = HotkeyCount(script, tab); + for (int row = 0; row < count; ++row) { const int index = HotkeyIndex(script, tab, row); if (index == -1) { continue; } + int key1 = 0, key2 = 0; const char* keyText = nullptr; const char* description = nullptr; - if ( - script.Call("GetUserHotKeyInfo", "dd>ddss", tab + 1, index, &key1, &key2, &keyText, &description) && - std::string(description).size() - ) { - if ( - script.Call("GetOriginalHotKeyInfo", "dd>ddss", tab + 1, index, &key1, &key2, &keyText, &description) && - std::string(description).size() - ) { + + if (script.Call("GetUserHotKeyInfo", "dd>ddss", tab + 1, index, &key1, &key2, &keyText, &description) && std::string(description).size()) { + if (script.Call("GetOriginalHotKeyInfo", "dd>ddss", tab + 1, index, &key1, &key2, &keyText, &description) && std::string(description).size()) { return true; } } } } + return false; } @@ -185,16 +194,19 @@ void CUserHotkeyMgr::Export(LuaScript& script, Json::Value& data) { this->Capture(script); const std::list snapshot = this->m_original; Json::Value tabs[4]; + for (const Hotkey& hotkey : snapshot) { Json::Value value; value["index"] = hotkey.index; value["key1"] = hotkey.key1; value["key2"] = hotkey.key2; value["desc"] = ToUtf8(hotkey.description, g_textCodePage); + if (hotkey.tab >= 0 && hotkey.tab < 4) { tabs[hotkey.tab].append(value); } } + Json::Value version2; version2["SkillBar_1Tab"] = tabs[0]; version2["SkillBar_2Tab"] = tabs[3]; diff --git a/Source/Contents/UserHotkeyMgr.h b/Source/Contents/Hotkeys/UserHotkeyMgr.h similarity index 85% rename from Source/Contents/UserHotkeyMgr.h rename to Source/Contents/Hotkeys/UserHotkeyMgr.h index 9977bc9..9ede92b 100644 --- a/Source/Contents/UserHotkeyMgr.h +++ b/Source/Contents/Hotkeys/UserHotkeyMgr.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_USERHOTKEYMGR_H -#define RAGNAROK_SOURCE_CONTENTS_USERHOTKEYMGR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_HOTKEYS_USERHOTKEYMGR_H +#define RAGNAROK_SOURCE_CONTENTS_HOTKEYS_USERHOTKEYMGR_H -#include "Contents/UserHotkeyScript.h" +#include "Contents/Hotkeys/UserHotkeyScript.h" #include #include diff --git a/Source/Contents/UserHotkeyScript.cpp b/Source/Contents/Hotkeys/UserHotkeyScript.cpp similarity index 96% rename from Source/Contents/UserHotkeyScript.cpp rename to Source/Contents/Hotkeys/UserHotkeyScript.cpp index 2287576..bccbf91 100644 --- a/Source/Contents/UserHotkeyScript.cpp +++ b/Source/Contents/Hotkeys/UserHotkeyScript.cpp @@ -1,4 +1,4 @@ -#include "Contents/UserHotkeyScript.h" +#include "Contents/Hotkeys/UserHotkeyScript.h" #include "Network/TextEncoding.h" // STATIC: 0x01738010 @@ -39,6 +39,7 @@ void __stdcall ChangeUserHotkey(int tab, int index, int key1, int key2, const st // FUNCTION: fn_03473 void __stdcall LoadUserHotkeyTab(Json::Value& values, int tab) { Json::Value entries = values; + for (auto item = entries.begin(); item != entries.end(); ++item) { Json::Value& value = *item; if (value.isObject()) { @@ -46,6 +47,7 @@ void __stdcall LoadUserHotkeyTab(Json::Value& values, int tab) { int key1 = value.get("key1", "-1").asInt(); int key2 = value.get("key2", "-1").asInt(); std::string description = FromUtf8(value.get("desc", "").asString(), g_textCodePage); + if (index != -1 || description.empty()) { ChangeUserHotkey(tab, index, key1, key2, description); } diff --git a/Source/Contents/UserHotkeyScript.h b/Source/Contents/Hotkeys/UserHotkeyScript.h similarity index 75% rename from Source/Contents/UserHotkeyScript.h rename to Source/Contents/Hotkeys/UserHotkeyScript.h index cf10e58..ae263b9 100644 --- a/Source/Contents/UserHotkeyScript.h +++ b/Source/Contents/Hotkeys/UserHotkeyScript.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_USERHOTKEYSCRIPT_H -#define RAGNAROK_SOURCE_CONTENTS_USERHOTKEYSCRIPT_H +#ifndef RAGNAROK_SOURCE_CONTENTS_HOTKEYS_USERHOTKEYSCRIPT_H +#define RAGNAROK_SOURCE_CONTENTS_HOTKEYS_USERHOTKEYSCRIPT_H #include "Script/LuaScript.h" @@ -11,7 +11,6 @@ void SaveUserHotkeys(); void __stdcall ChangeUserHotkey(int tab, int index, int key1, int key2, const std::string& description); void __stdcall LoadUserHotkeyTab(Json::Value& values, int tab); -// Compatibility inline overloads for callers passing LuaScript reference inline void ClearUserHotkeys(LuaScript&) { ClearUserHotkeys(); } @@ -28,4 +27,4 @@ inline void LoadUserHotkeyTab(LuaScript&, Json::Value& values, int tab) { LoadUserHotkeyTab(values, tab); } -#endif // RAGNAROK_SOURCE_CONTENTS_USERHOTKEYSCRIPT_H +#endif diff --git a/Source/Contents/InstantVar.h b/Source/Contents/InstantVar.h index 4f1b11a..69f7175 100644 --- a/Source/Contents/InstantVar.h +++ b/Source/Contents/InstantVar.h @@ -4,8 +4,6 @@ #include #include -// RTTI CInstantVar. Embedded by CRenderObject at +0x118 -// and client at +0x7FA8. Initialization is inlined in their constructors. class CInstantVar { public: CInstantVar() = default; @@ -15,8 +13,6 @@ public: void Clear(); private: - // Original signed-key ordered tree, 32-byte x86 nodes containing an aligned - // 64-bit mapped value. A missing read does not insert a zero-valued node. std::map m_values; }; diff --git a/Source/Contents/ItemDescription.cpp b/Source/Contents/Items/ItemDescription.cpp similarity index 91% rename from Source/Contents/ItemDescription.cpp rename to Source/Contents/Items/ItemDescription.cpp index aff506e..427800a 100644 --- a/Source/Contents/ItemDescription.cpp +++ b/Source/Contents/Items/ItemDescription.cpp @@ -1,5 +1,5 @@ -#include "Contents/ItemDescription.h" -#include "Contents/ItemInfo.h" +#include "Contents/Items/ItemDescription.h" +#include "Contents/Items/ItemInfo.h" #include #include @@ -8,9 +8,10 @@ // OFFSET: 0x006D3540 // FUNCTION: fn_06540 ITEM_DESC::ITEM_DESC() - : identifiedName(nullptr), identifiedResource(nullptr), unidentifiedName(nullptr), unidentifiedResource(nullptr), - unknown_002C(0), slots(0), unknown_0040(0) { + : identifiedName(nullptr), identifiedResource(nullptr), unidentifiedName(nullptr), unidentifiedResource(nullptr), unknown_002C(0), slots(0), + unknown_0040(0) { } + // OFFSET: 0x006D3610 // FUNCTION: fn_06541 // OFFSET: 0x006D3680 @@ -23,6 +24,7 @@ ITEM_DESC& ITEM_DESC::operator=(const ITEM_DESC& other) { if (this == &other) { return *this; } + this->identifiedName = other.identifiedName; this->identifiedResource = other.identifiedResource; this->identifiedDescription = other.identifiedDescription; @@ -33,6 +35,7 @@ ITEM_DESC& ITEM_DESC::operator=(const ITEM_DESC& other) { this->slots = other.slots; this->unknown_0034 = other.unknown_0034; this->unknown_0040 = other.unknown_0040; + return *this; } @@ -72,13 +75,15 @@ const std::vector& ItemDescriptions::Description(const ItemInfo& it int ItemDescriptions::Name(const ItemInfo& item, char* output, int& capacity, unsigned char consume) { const char* name = this->Find(std::atoi(item.itemId.c_str())).identifiedName; const int error = strncpy_s(output, capacity, name ? name : " ", _TRUNCATE); - // Original checks literal80, not the modern CRT's STRUNCATE constant. + if (error != 0 && error != 80) { return 0; } + const int length = output ? static_cast(strnlen(output, capacity)) : 0; if (consume != 0) { capacity -= length; } + return length; } diff --git a/Source/Contents/ItemDescription.h b/Source/Contents/Items/ItemDescription.h similarity index 78% rename from Source/Contents/ItemDescription.h rename to Source/Contents/Items/ItemDescription.h index 3770068..8fbdcfd 100644 --- a/Source/Contents/ItemDescription.h +++ b/Source/Contents/Items/ItemDescription.h @@ -1,13 +1,11 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMDESCRIPTION_H -#define RAGNAROK_SOURCE_CONTENTS_ITEMDESCRIPTION_H +#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMDESCRIPTION_H +#define RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMDESCRIPTION_H #include #include struct ItemInfo; -// ITEM_DESC. Text/resource pointers borrow -// storage from the original table loader; vectors own only their pointer arrays. class ITEM_DESC { public: ITEM_DESC(); @@ -26,7 +24,6 @@ public: /* 0040 */ int unknown_0040; }; -// Non-owning view of table; loading remains its owner's job. struct ItemDescriptions { std::map& values; ITEM_DESC& Find(int id); diff --git a/Source/Contents/ItemInfo.cpp b/Source/Contents/Items/ItemInfo.cpp similarity index 95% rename from Source/Contents/ItemInfo.cpp rename to Source/Contents/Items/ItemInfo.cpp index bf10bbb..b18050e 100644 --- a/Source/Contents/ItemInfo.cpp +++ b/Source/Contents/Items/ItemInfo.cpp @@ -1,4 +1,4 @@ -#include "Contents/ItemInfo.h" +#include "Contents/Items/ItemInfo.h" #include #include @@ -8,6 +8,7 @@ ItemInfo::ItemInfo() { this->Reset(); } + // OFFSET: 0x006D4750 // FUNCTION: fn_06561 ItemInfo::ItemInfo(int) { @@ -70,7 +71,7 @@ ItemInfo& ItemInfo::operator=(const ItemInfo& other) { this->unknown_0090 = other.unknown_0090; this->unknown_0098 = other.unknown_0098; std::memcpy(this->unknown_009C, other.unknown_009C, sizeof(this->unknown_009C)); - // Unlike copy construction, assignment leaves +0xB8 onward untouched. + return *this; } @@ -96,7 +97,8 @@ std::uint32_t ItemInfo::Assign(const RawItemData& item) { if (item.optionCount <= 5) { count = item.optionCount; } - this->unknown_0098 = static_cast(count); + + this->unknown_0098 = count; if (count > 0) { std::memcpy(this->unknown_009C, item.options, static_cast(count) * 5); @@ -132,7 +134,6 @@ void ItemInfo::Reset() { this->unknown_0090 = 0; this->unknown_0098 = 0; std::memset(this->unknown_009C, 0, sizeof(this->unknown_009C)); - // Original leaves+0xB8 onward untouched, as well as ABI padding gaps. } // OFFSET: 0x00DDD4E0 @@ -143,6 +144,7 @@ ItemInfo LookupClientItem(const std::list& values, int id, unsigned ch return value; } } + return ItemInfo(0); } @@ -154,5 +156,6 @@ ItemInfo LookupClientItemByIdentity(const std::list& values, std::uint return value; } } + return ItemInfo(0); } diff --git a/Source/Contents/ItemInfo.h b/Source/Contents/Items/ItemInfo.h similarity index 83% rename from Source/Contents/ItemInfo.h rename to Source/Contents/Items/ItemInfo.h index 37feb92..adb88fc 100644 --- a/Source/Contents/ItemInfo.h +++ b/Source/Contents/Items/ItemInfo.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMINFO_H -#define RAGNAROK_SOURCE_CONTENTS_ITEMINFO_H +#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMINFO_H +#define RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMINFO_H #include #include #include -// Original item packet payload layout (188 bytes) received from server. struct RawItemData { /* 0000 */ std::uint32_t unknown_0000; /* 0004 */ std::uint32_t unknown_0004; @@ -36,8 +35,6 @@ struct RawItemData { static_assert(sizeof(RawItemData) == 188); #endif -// Reconstructed name for original248-byte nonpolymorphic item value. -// Unknown bytes remain explicit; two strings own their storage. struct alignas(8) ItemInfo { ItemInfo(); explicit ItemInfo(int unused); @@ -54,17 +51,17 @@ struct alignas(8) ItemInfo { /* 0044 */ std::string unknown_0044; /* 005C */ unsigned char identified; /* 005D */ unsigned char unknown_005D; - /* 0060 */ std::uint32_t unknown_0060; + /* 0060 */ std::int32_t unknown_0060; /* 0064 */ std::uint16_t unknown_0064; /* 0066 */ unsigned char unknown_0066; /* 0068 */ std::uint32_t unknown_0068; /* 006C */ std::uint16_t unknown_006C; - /* 0070 */ std::uint32_t unknown_0070; + /* 0070 */ std::int32_t unknown_0070; /* 0074 */ unsigned char unknown_0074[4]; /* 0078 */ std::uint32_t unknown_0078[4]; /* 0088 */ std::int16_t unknown_0088; /* 0090 */ std::uint64_t unknown_0090; - /* 0098 */ std::uint32_t unknown_0098; + /* 0098 */ std::int32_t unknown_0098; /* 009C */ unsigned char unknown_009C[25]; /* 00B8 */ std::uint32_t unknown_00B8[2]; /* 00C0 */ unsigned char unknown_00C0; @@ -72,7 +69,6 @@ struct alignas(8) ItemInfo { /* 00D9 */ unsigned char unknown_00D9[24]; }; -// View of original client list+0x1710. The caller owns the actual inventory. ItemInfo LookupClientItem(const std::list& values, int id, unsigned char requireIdentified); ItemInfo LookupClientItemByIdentity(const std::list& values, std::uint32_t id); diff --git a/Source/Contents/ItemLink.cpp b/Source/Contents/Items/ItemLink.cpp similarity index 91% rename from Source/Contents/ItemLink.cpp rename to Source/Contents/Items/ItemLink.cpp index 3003699..6ae14ee 100644 --- a/Source/Contents/ItemLink.cpp +++ b/Source/Contents/Items/ItemLink.cpp @@ -1,8 +1,7 @@ -#include "Contents/ItemDescription.h" -#include "Contents/ItemInfo.h" -#include "Contents/ItemLink.h" +#include "Contents/Items/ItemDescription.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/Items/ItemLink.h" -#include #include #include #include @@ -30,7 +29,7 @@ namespace { result += static_cast(digit - digits) * place; } - return std::bit_cast(result); + return static_cast(result); } // OFFSET: 0x00893AE0 @@ -168,7 +167,7 @@ bool ItemFromLinkFields(const std::vector& fields, ItemInfo& item, return false; } - item.unknown_0000[2] = std::bit_cast(fields[0]); + item.unknown_0000[2] = static_cast(fields[0]); char id[16]; std::sprintf(id, "%d", fields[2]); item.itemId = id; @@ -177,9 +176,9 @@ bool ItemFromLinkFields(const std::vector& fields, ItemInfo& item, item.unknown_0000[0] = 4; } - item.unknown_0060 = std::bit_cast(fields[3]); - item.unknown_0070 = std::bit_cast(fields[4]); - item.unknown_0088 = std::bit_cast(static_cast(fields[5])); + item.unknown_0060 = fields[3]; + item.unknown_0070 = fields[4]; + item.unknown_0088 = static_cast(fields[5]); int cardCount = 0; if (fields.size() > 6) { @@ -196,7 +195,7 @@ bool ItemFromLinkFields(const std::vector& fields, ItemInfo& item, if (optionIndex < fields.size()) { const int count = fields[optionIndex]; - item.unknown_0098 = std::bit_cast(count); + item.unknown_0098 = count; for (int index = 0; index < count; ++index) { if (index < 5) { diff --git a/Source/Contents/ItemLink.h b/Source/Contents/Items/ItemLink.h similarity index 68% rename from Source/Contents/ItemLink.h rename to Source/Contents/Items/ItemLink.h index 3bef6c7..3a1df9a 100644 --- a/Source/Contents/ItemLink.h +++ b/Source/Contents/Items/ItemLink.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMLINK_H -#define RAGNAROK_SOURCE_CONTENTS_ITEMLINK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMLINK_H +#define RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMLINK_H #include #include @@ -8,7 +8,6 @@ struct ItemDescriptions; struct ItemInfo; -// Decoder retains a 260-word work array, including untouched prior entries. void DecodeItemLinkFields(const std::string& text, std::vector& fields); bool ItemFromLinkFields(const std::vector& fields, ItemInfo& item, ItemDescriptions& descriptions); int ItemLinkMessageId(const std::string& text); diff --git a/Source/Contents/ItemNaming.cpp b/Source/Contents/Items/ItemNaming.cpp similarity index 98% rename from Source/Contents/ItemNaming.cpp rename to Source/Contents/Items/ItemNaming.cpp index e7b15d3..fe50671 100644 --- a/Source/Contents/ItemNaming.cpp +++ b/Source/Contents/Items/ItemNaming.cpp @@ -1,9 +1,8 @@ -#include "Contents/ItemInfo.h" -#include "Contents/ItemNaming.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/Items/ItemNaming.h" #include "Contents/MessageTable.h" #include "Contents/PlayerNameDictionary.h" -#include #include #include #include @@ -28,9 +27,11 @@ namespace { return false; } } + void CardIds(const ItemInfo& item, int (&ids)[4]) { std::memcpy(ids, item.unknown_001C, sizeof(ids)); } + int Copy(char* output, int capacity, const char* text) { const int error = strncpy_s(output, capacity, text ? text : " ", _TRUNCATE); return error == 0 || error == 80 ? (output ? static_cast(strnlen(output, capacity)) : 0) : 0; @@ -48,9 +49,11 @@ bool ItemNaming::HasCards(const ItemInfo& item) const { CardIds(item, ids); const bool first = this->cards.contains(ids[0]); const unsigned id = static_cast(std::atoi(item.itemId.c_str())); + if (id - 9001u <= 498 || id - 10000u <= 999 || ids[0] == 254 || ids[0] == 255 || !Equipment(item)) { return first; } + return first || this->cards.contains(ids[1]) || this->cards.contains(ids[2]) || this->cards.contains(ids[3]); } @@ -62,9 +65,11 @@ int ItemNaming::Grade(const ItemInfo& item, char* output, int& capacity, unsigne if (bytes <= 0) { return 0; } + if (consume) { capacity -= bytes; } + return bytes; } @@ -74,13 +79,16 @@ int ItemNaming::Creator(const ItemInfo& item, char* output, int& capacity, unsig int ids[4]; CardIds(item, ids); std::string name = this->players.Lookup(static_cast(ids[2]) + (static_cast(ids[3]) << 16)); + if (name.empty()) { name = this->Message(581); } + const int bytes = Copy(output, capacity, name.c_str()); if (consume) { capacity -= bytes; } + return bytes; } @@ -91,21 +99,26 @@ int ItemNaming::Prefixes(const ItemInfo& item, char* output, int& capacity, unsi CardIds(item, ids); int remaining = capacity; char* cursor = output; + for (int index = 0; index < 4; ++index) { if (ids[index] <= 0) { continue; } + const auto card = this->cards.find(ids[index]); if (card == this->cards.end() || !card->second.prefix || !*card->second.prefix) { continue; } + int count = 1; + for (int next = index + 1; next < 4; ++next) { if (ids[next] == ids[index]) { ids[next] = 0; ++count; } } + if (count >= 2) { const int bytes = _snprintf_s(cursor, remaining, _TRUNCATE, "%s ", this->Message(444 + count)); if (bytes > 0) { @@ -113,16 +126,19 @@ int ItemNaming::Prefixes(const ItemInfo& item, char* output, int& capacity, unsi remaining -= bytes; } } + const int bytes = _snprintf_s(cursor, remaining, _TRUNCATE, "%s ", card->second.prefix); if (bytes > 0) { cursor += bytes; remaining -= bytes; } } + const int bytes = static_cast(cursor - output); if (consume) { capacity -= bytes; } + return bytes; } @@ -133,26 +149,32 @@ int ItemNaming::Suffixes(const ItemInfo& item, char* output, int& capacity, unsi CardIds(item, ids); int remaining = capacity; char* cursor = output; + for (int index = 0; index < 4; ++index) { if (ids[index] <= 0) { continue; } + const auto card = this->cards.find(ids[index]); if (card == this->cards.end() || !card->second.suffix || !*card->second.suffix) { continue; } + int count = 1; + for (int next = index + 1; next < 4; ++next) { if (ids[next] == ids[index]) { ids[next] = 0; ++count; } } + int bytes = _snprintf_s(cursor, remaining, _TRUNCATE, " %s", card->second.suffix); if (bytes > 0) { cursor += bytes; remaining -= bytes; } + if (count >= 2) { bytes = _snprintf_s(cursor, remaining, _TRUNCATE, " %s", this->Message(444 + count)); if (bytes > 0) { @@ -161,10 +183,12 @@ int ItemNaming::Suffixes(const ItemInfo& item, char* output, int& capacity, unsi } } } + const int bytes = static_cast(cursor - output); if (consume) { capacity -= bytes; } + return bytes; } @@ -175,13 +199,16 @@ int ItemNaming::Slots(const ItemInfo& item, char* output, int& capacity, unsigne if (slots == 0) { return 0; } + const int bytes = _snprintf_s(output, capacity, _TRUNCATE, " [%d]", slots); if (bytes <= 0) { return 0; } + if (consume) { capacity -= bytes; } + return bytes; } @@ -199,10 +226,12 @@ std::string ItemNaming::DisplayName(const ItemInfo& item, unsigned char detailed }; const int id = std::atoi(item.itemId.c_str()); ITEM_DESC& descriptor = this->descriptions.Find(id); + if (item.identified != 1) { append(Copy(text, capacity, descriptor.unidentifiedName)); return result; } + int cards[4]; CardIds(item, cards); if ((static_cast(id) - 9001u <= 498 || static_cast(id) - 10000u <= 999) && cards[3] == 1) { @@ -210,11 +239,13 @@ std::string ItemNaming::DisplayName(const ItemInfo& item, unsigned char detailed append(Copy(text, capacity, descriptor.identifiedName)); return result; } + const auto refine = [&]() { - const int value = std::bit_cast(item.unknown_0060); + const int value = item.unknown_0060; if (value > 0) { append(_snprintf_s(text, sizeof(text), _TRUNCATE, "+%d ", value)); } + if (item.unknown_0088 > 0) { append(this->Grade(item, text, capacity, 0)); } @@ -223,6 +254,7 @@ std::string ItemNaming::DisplayName(const ItemInfo& item, unsigned char detailed const auto element = [&]() { const unsigned value = item.unknown_001C[4]; int message = 0; + switch (value) { case 0: message = id == 2634 || id == 2635 ? 2976 : 450; @@ -240,12 +272,14 @@ std::string ItemNaming::DisplayName(const ItemInfo& item, unsigned char detailed message = 453; break; } + if (message) { append(Copy(text, capacity, this->Message(message))); } }; const auto star = [&]() { int message = 0; + switch (item.unknown_001C[5]) { case 5: message = 459; @@ -257,10 +291,12 @@ std::string ItemNaming::DisplayName(const ItemInfo& item, unsigned char detailed message = 461; break; } + if (message) { append(Copy(text, capacity, this->Message(message))); } }; + if (cards[0] == 254 && cards[1] == 0) { refine(); if (this->service != 12 && this->service != 14) { @@ -272,25 +308,31 @@ std::string ItemNaming::DisplayName(const ItemInfo& item, unsigned char detailed element(); append(this->Creator(item, text, capacity, 0)); } + return result; } + if (!Equipment(item) && detailed == 0) { name(); return result; } + refine(); if (this->HasCards(item)) { append(this->Prefixes(item, text, capacity, 0)); name(); append(this->Suffixes(item, text, capacity, 0)); append(this->Slots(item, text, capacity, 0)); + return result; } + if (cards[0] != 254 && cards[0] != 255) { name(); append(this->Slots(item, text, capacity, 0)); return result; } + if (this->service == 12) { name(); element(); @@ -307,5 +349,6 @@ std::string ItemNaming::DisplayName(const ItemInfo& item, unsigned char detailed element(); name(); } + return result; } diff --git a/Source/Contents/ItemNaming.h b/Source/Contents/Items/ItemNaming.h similarity index 83% rename from Source/Contents/ItemNaming.h rename to Source/Contents/Items/ItemNaming.h index b85473b..244815c 100644 --- a/Source/Contents/ItemNaming.h +++ b/Source/Contents/Items/ItemNaming.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMNAMING_H -#define RAGNAROK_SOURCE_CONTENTS_ITEMNAMING_H +#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMNAMING_H +#define RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMNAMING_H -#include "Contents/ItemDescription.h" +#include "Contents/Items/ItemDescription.h" #include #include @@ -15,7 +15,6 @@ struct ItemCardName { const char* suffix; }; -// Borrowed original descriptor/card tables, creator dictionary and locale. struct ItemNaming { ItemDescriptions& descriptions; const std::map& cards; diff --git a/Source/Contents/ItemResources.cpp b/Source/Contents/Items/ItemResources.cpp similarity index 90% rename from Source/Contents/ItemResources.cpp rename to Source/Contents/Items/ItemResources.cpp index c4f5d79..df21eac 100644 --- a/Source/Contents/ItemResources.cpp +++ b/Source/Contents/Items/ItemResources.cpp @@ -1,5 +1,5 @@ -#include "Contents/ItemDescription.h" -#include "Contents/ItemResources.h" +#include "Contents/Items/ItemDescription.h" +#include "Contents/Items/ItemResources.h" #include "Resource/ResourceMgr.h" #include @@ -13,6 +13,7 @@ const char* ItemDragResource(ItemDescriptions& descriptions, const char* id, int const ITEM_DESC& value = descriptions.Find(std::atoi(id)); const char* name = identified != 0 ? value.identifiedResource : value.unidentifiedResource; resource += name ? name : "\xBB\xE7\xB0\xFA"; + return resource.c_str(); } @@ -22,8 +23,10 @@ const char* SkillDragResource(ResourceMgr& resources, const char* name) { static std::string resource; resource = "\xBE\xC6\xC0\xCC\xC5\xDB\\"; resource += name; + if (!resources.Exists((resource + ".act").c_str())) { resource = "\xBE\xC6\xC0\xCC\xC5\xDB\\am_berserkpitcher"; } + return resource.c_str(); } diff --git a/Source/Contents/ItemResources.h b/Source/Contents/Items/ItemResources.h similarity index 66% rename from Source/Contents/ItemResources.h rename to Source/Contents/Items/ItemResources.h index 554fe2b..6aab4ed 100644 --- a/Source/Contents/ItemResources.h +++ b/Source/Contents/Items/ItemResources.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMRESOURCES_H -#define RAGNAROK_SOURCE_CONTENTS_ITEMRESOURCES_H +#ifndef RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMRESOURCES_H +#define RAGNAROK_SOURCE_CONTENTS_ITEMS_ITEMRESOURCES_H class ResourceMgr; struct ItemDescriptions; diff --git a/Source/Contents/JobInheritance.h b/Source/Contents/JobInheritance.h deleted file mode 100644 index 0b72db4..0000000 --- a/Source/Contents/JobInheritance.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_JOBINHERITANCE_H -#define RAGNAROK_SOURCE_CONTENTS_JOBINHERITANCE_H - -class LuaScript; -class CPlayerSkillBundle; - -// Borrowed client script owner, not a separate job table. -struct JobInheritance { - LuaScript& script; - - int Lookup(int job); - - // Query GetInheritJob(job) before changing the bundle. A failed query or -1 - // retains it; other counts clear groups, extra skills and level changes. - // Visit positive indices in descending order. Resolve each job through the - // live Lua tables, then call InitSkillTreeView(job, group); callback failure - // does not stop later indices. Other bundle collections remain untouched. - void InitializeSkillTree(CPlayerSkillBundle& bundle, int job); -}; - -#endif diff --git a/Source/Contents/JobInheritance.cpp b/Source/Contents/Jobs/JobInheritance.cpp similarity index 85% rename from Source/Contents/JobInheritance.cpp rename to Source/Contents/Jobs/JobInheritance.cpp index b57aa0e..2e1c126 100644 --- a/Source/Contents/JobInheritance.cpp +++ b/Source/Contents/Jobs/JobInheritance.cpp @@ -1,5 +1,5 @@ -#include "Contents/JobInheritance.h" -#include "Contents/PlayerSkillBundle.h" +#include "Contents/Jobs/JobInheritance.h" +#include "Contents/Skills/PlayerSkillBundle.h" #include "Script/LuaScript.h" #include @@ -83,14 +83,9 @@ void JobInheritance::InitializeSkillTree(CPlayerSkillBundle& bundle, int job) { for (int index = count; index > 0; --index) { const int inherited = this->Lookup(index); int group = 1; - if ( - inherited == 0 || this->Lookup(static_cast(static_cast(index) + 1u)) == 0 || - inherited == 4218 || inherited == 4220 - ) { + if (inherited == 0 || this->Lookup(index + 1) == 0 || inherited == 4218 || inherited == 4220) { group = 0; - } else if ( - IsTreeGroupTwo(inherited) || inherited == 4239 || inherited == 4240 || inherited == 4241 || inherited == 4242 - ) { + } else if (IsTreeGroupTwo(inherited) || inherited == 4239 || inherited == 4240 || inherited == 4241 || inherited == 4242) { group = 2; } else if (IsTreeGroupThree(inherited)) { group = 3; diff --git a/Source/Contents/Jobs/JobInheritance.h b/Source/Contents/Jobs/JobInheritance.h new file mode 100644 index 0000000..ad20291 --- /dev/null +++ b/Source/Contents/Jobs/JobInheritance.h @@ -0,0 +1,15 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_JOBS_JOBINHERITANCE_H +#define RAGNAROK_SOURCE_CONTENTS_JOBS_JOBINHERITANCE_H + +class LuaScript; +class CPlayerSkillBundle; + +struct JobInheritance { + LuaScript& script; + + int Lookup(int job); + + void InitializeSkillTree(CPlayerSkillBundle& bundle, int job); +}; + +#endif diff --git a/Source/Contents/JobNameInitialization.cpp b/Source/Contents/Jobs/JobNameInitialization.cpp similarity index 78% rename from Source/Contents/JobNameInitialization.cpp rename to Source/Contents/Jobs/JobNameInitialization.cpp index d70d614..5cb47db 100644 --- a/Source/Contents/JobNameInitialization.cpp +++ b/Source/Contents/Jobs/JobNameInitialization.cpp @@ -1,4 +1,4 @@ -#include "Contents/JobNames.h" +#include "Contents/Jobs/JobNames.h" #include "Script/LuaScript.h" // OFFSET: 0x00DE67E0 @@ -27,7 +27,6 @@ void JobNames::Initialize(JobNameInitialization& context) { player(4351, 4360); const auto other = [&](int first, int last) { for (int id = first; id <= last; ++id) { - // Unlike player names, empty returned strings are retained here. context.otherScript.Call("ReqJobName", "d>s", id, &this->names[id]); } }; @@ -37,11 +36,8 @@ void JobNames::Initialize(JobNameInitialization& context) { other(10000, 19998); other(20021, 31999); - // Literal stores. Keep these bytes - // independent of the current language/code page and script table content. - const char* const homunculi[] = {"LIF", "AMISTR", "FILIR", "VANILMIRTH", "LIF2", "AMISTR2", - "FILIR2", "VANILMIRTH2", "LIF_H", "AMISTR_H", "FILIR_H", "VANILMIRTH_H", - "LIF_H2", "AMISTR_H2", "FILIR_H2", "VANILMIRTH_H2"}; + const char* const homunculi[] = {"LIF", "AMISTR", "FILIR", "VANILMIRTH", "LIF2", "AMISTR2", "FILIR2", "VANILMIRTH2", + "LIF_H", "AMISTR_H", "FILIR_H", "VANILMIRTH_H", "LIF_H2", "AMISTR_H2", "FILIR_H2", "VANILMIRTH_H2"}; for (unsigned index = 0; index < 16; ++index) { this->names[6001 + index] = homunculi[index]; diff --git a/Source/Contents/JobNames.cpp b/Source/Contents/Jobs/JobNames.cpp similarity index 99% rename from Source/Contents/JobNames.cpp rename to Source/Contents/Jobs/JobNames.cpp index 0476d0a..79df8fe 100644 --- a/Source/Contents/JobNames.cpp +++ b/Source/Contents/Jobs/JobNames.cpp @@ -1,4 +1,4 @@ -#include "Contents/JobNames.h" +#include "Contents/Jobs/JobNames.h" // OFFSET: 0x00E2FE80 // FUNCTION: fn_24165 diff --git a/Source/Contents/JobNames.h b/Source/Contents/Jobs/JobNames.h similarity index 63% rename from Source/Contents/JobNames.h rename to Source/Contents/Jobs/JobNames.h index 98e790d..8c0bd4f 100644 --- a/Source/Contents/JobNames.h +++ b/Source/Contents/Jobs/JobNames.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_JOBNAMES_H -#define RAGNAROK_SOURCE_CONTENTS_JOBNAMES_H +#ifndef RAGNAROK_SOURCE_CONTENTS_JOBS_JOBNAMES_H +#define RAGNAROK_SOURCE_CONTENTS_JOBS_JOBNAMES_H #include #include @@ -8,8 +8,6 @@ class LuaScript; -// Additional client vectors initialized by the same original entry. Existing -// elements survive resize; only newly appended skill levels receive zero. struct JobNameInitialization { LuaScript& playerScript; LuaScript& otherScript; @@ -20,8 +18,6 @@ struct JobNameInitialization { std::vector& homunculusLevels; }; -// Client-owned job-name vector and sex-specific maps. Returned strings remain -// borrowed from these tables, matching the original display-name operation. struct JobNames { std::vector& names; std::map& female; diff --git a/Source/Contents/MessageTable.cpp b/Source/Contents/MessageTable.cpp index fc6f80a..0515626 100644 --- a/Source/Contents/MessageTable.cpp +++ b/Source/Contents/MessageTable.cpp @@ -1,7 +1,7 @@ #include "Contents/MessageTable.h" #include "Network/TextEncoding.h" #include "Utility/Base64.h" -#include "Utility/LanguageCharset.h" +#include "Utility/Text/LanguageCharset.h" #include #include @@ -23,15 +23,18 @@ namespace { if (field.empty()) { return; } + std::string decoded = DecodeBase64(field); if (decoded.size() > 2) { if (decoded.front() == '"' && decoded.back() == '"') { decoded = decoded.substr(1, decoded.size() - 2); } + for (std::size_t pos = 0; (pos = decoded.find("\\\"\"", pos)) != std::string::npos; ++pos) { decoded.replace(pos, 3, "\""); } } + row.push_back(FromUtf8(decoded, g_textCodePage)); } @@ -40,6 +43,7 @@ namespace { void TransformFields(std::vector& row) { const char* escapes[] = {"\\r", "\\n", "\\t", "\\'", "\\\"", "\\\\"}; const char replacements[] = {'\r', '\n', '\t', '\'', '"', '\\'}; + for (std::string& text : row) { if (text.empty()) { text = "NO MSG"; @@ -69,14 +73,17 @@ const char* LookupMessage(int id, bool languagePrefix, int serviceType, WORD lan _snprintf_s(missing, sizeof(missing), _TRUNCATE, "NO MSG : %d", id); return missing; } + auto found = g_messageStrings.find(id); if (found == g_messageStrings.end()) { return "NO MSG"; } + const std::string& text = found->second; if (!languagePrefix || text[0] == '/' || text == "NO MSG") { return text.c_str(); } + // STATIC: 0x016D57B4 // GLOBAL: gl_24383 static std::vector cached(4698); @@ -90,6 +97,7 @@ const char* LookupMessage(int id, bool languagePrefix, int serviceType, WORD lan _snprintf_s(buffer, sizeof(buffer), _TRUNCATE, "%s%s", prefix, text.c_str()); result = buffer; } + return result.c_str(); } @@ -99,20 +107,21 @@ const char* LookupMessage(int id, bool languagePrefix, int serviceType, WORD lan // FUNCTION: fn_18372 bool ImportMessageCsv(std::string_view bytes) { g_messageStrings.clear(); - if ( - bytes.size() >= 2 && - ((static_cast(bytes[0]) == 0xFF && static_cast(bytes[1]) == 0xFE) || - (static_cast(bytes[0]) == 0xFE && static_cast(bytes[1]) == 0xFF)) - ) { + if (bytes.size() >= 2 && ((static_cast(bytes[0]) == 0xFF && static_cast(bytes[1]) == 0xFE) || + (static_cast(bytes[0]) == 0xFE && static_cast(bytes[1]) == 0xFF))) { return false; } + if (bytes.substr(0, 3) == "\xEF\xBB\xBF") { bytes.remove_prefix(3); } + std::size_t cursor = 0; + while (cursor < bytes.size()) { std::vector row; std::string field; + while (cursor < bytes.size()) { char value = bytes[cursor++]; if (value == ',' || value == '\r' || value == '\n') { @@ -121,6 +130,7 @@ bool ImportMessageCsv(std::string_view bytes) { if (value == '\n') { break; } + if (value == '\r' && cursor < bytes.size() && bytes[cursor] == '\n') { ++cursor; break; @@ -129,6 +139,7 @@ bool ImportMessageCsv(std::string_view bytes) { field.push_back(value); } } + DecodeField(field, row); TransformFields(row); if (row.size() >= 2 && !row.front().empty()) { @@ -140,5 +151,6 @@ bool ImportMessageCsv(std::string_view bytes) { } } } + return true; } diff --git a/Source/Contents/MessageTable.h b/Source/Contents/MessageTable.h index f3b2eb0..217ffd1 100644 --- a/Source/Contents/MessageTable.h +++ b/Source/Contents/MessageTable.h @@ -10,12 +10,9 @@ // GLOBAL: gl_24382 extern std::unordered_map g_messageStrings; -// Original lookup reads locale globals and font owner's LANGID at +0xB4. -// Explicit inputs retain that dependency without inventing a font owner. const char* LookupMessage(int id, bool languagePrefix, int serviceType, WORD language); void InsertMessage(int id, const char* text); -// Original file acquisition remains CFile/archive work; this consumes the exact -// acquired CSV bytes and retains row/field/import behavior. bool ImportMessageCsv(std::string_view bytes); + #endif diff --git a/Source/Contents/ClientMessenger.cpp b/Source/Contents/Messenger/ClientMessenger.cpp similarity index 96% rename from Source/Contents/ClientMessenger.cpp rename to Source/Contents/Messenger/ClientMessenger.cpp index 300a3cc..a158b78 100644 --- a/Source/Contents/ClientMessenger.cpp +++ b/Source/Contents/Messenger/ClientMessenger.cpp @@ -1,5 +1,5 @@ -#include "Contents/ClientMessenger.h" -#include "Contents/PartyMemberEffects.h" +#include "Contents/Messenger/ClientMessenger.h" +#include "Contents/Effects/PartyMemberEffects.h" // OFFSET: 0x00DDFFE0 // FUNCTION: fn_23451 @@ -55,7 +55,6 @@ void ClientMessenger::AddFriend(MessengerMember& member) { ++index; } - // Original updates every name match, then still appends a new entry. member.color = MemberColor(index); this->friends.push_back(member); } diff --git a/Source/Contents/ClientMessenger.h b/Source/Contents/Messenger/ClientMessenger.h similarity index 75% rename from Source/Contents/ClientMessenger.h rename to Source/Contents/Messenger/ClientMessenger.h index 199ef56..9b68571 100644 --- a/Source/Contents/ClientMessenger.h +++ b/Source/Contents/Messenger/ClientMessenger.h @@ -1,14 +1,12 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CLIENTMESSENGER_H -#define RAGNAROK_SOURCE_CONTENTS_CLIENTMESSENGER_H +#ifndef RAGNAROK_SOURCE_CONTENTS_MESSENGER_CLIENTMESSENGER_H +#define RAGNAROK_SOURCE_CONTENTS_MESSENGER_CLIENTMESSENGER_H -#include "Contents/MessengerMember.h" +#include "Contents/Messenger/MessengerMember.h" #include struct PartyMemberEffects; -// Non-owning source view, not a replacement client singleton. Original client -// owns party at +0x17DC and friends at +0x17E4, each an MSVC std::list value. struct ClientMessenger { std::list& party; std::list& friends; diff --git a/Source/Contents/MessengerMember.cpp b/Source/Contents/Messenger/MessengerMember.cpp similarity index 80% rename from Source/Contents/MessengerMember.cpp rename to Source/Contents/Messenger/MessengerMember.cpp index 71d5022..e64cf91 100644 --- a/Source/Contents/MessengerMember.cpp +++ b/Source/Contents/Messenger/MessengerMember.cpp @@ -1,4 +1,4 @@ -#include "Contents/MessengerMember.h" +#include "Contents/Messenger/MessengerMember.h" // OFFSET: 0x00D03DC0 // FUNCTION: fn_21550 @@ -13,9 +13,8 @@ MessengerMember::MessengerMember(int) : valid(0), dead(0) { // OFFSET: 0x00739AB0 // FUNCTION: fn_07695 MessengerMember::MessengerMember(const MessengerMember& other) - : valid(other.valid), accountId(other.accountId), characterId(other.characterId), name(other.name), map(other.map), - leader(other.leader), offline(other.offline), color(other.color), job(other.job), level(other.level), - dead(other.dead) { + : valid(other.valid), accountId(other.accountId), characterId(other.characterId), name(other.name), map(other.map), leader(other.leader), + offline(other.offline), color(other.color), job(other.job), level(other.level), dead(other.dead) { } // OFFSET: 0x00DC6FA0 @@ -32,6 +31,7 @@ MessengerMember& MessengerMember::operator=(const MessengerMember& other) { this->job = other.job; this->level = other.level; this->dead = other.dead; + return *this; } diff --git a/Source/Contents/MessengerMember.h b/Source/Contents/Messenger/MessengerMember.h similarity index 69% rename from Source/Contents/MessengerMember.h rename to Source/Contents/Messenger/MessengerMember.h index a971965..b423240 100644 --- a/Source/Contents/MessengerMember.h +++ b/Source/Contents/Messenger/MessengerMember.h @@ -1,12 +1,9 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_MESSENGERMEMBER_H -#define RAGNAROK_SOURCE_CONTENTS_MESSENGERMEMBER_H +#ifndef RAGNAROK_SOURCE_CONTENTS_MESSENGER_MESSENGERMEMBER_H +#define RAGNAROK_SOURCE_CONTENTS_MESSENGER_MESSENGERMEMBER_H #include #include -// Reconstructed name for the shared 80-byte friend/party value. The original -// constructors initialize only valid, the strings and dead; other scalars -// remain unspecified until their packet/client owner writes them. struct MessengerMember { MessengerMember(); explicit MessengerMember(int unused); diff --git a/Source/Contents/WhisperBlockMgr.cpp b/Source/Contents/Messenger/WhisperBlockMgr.cpp similarity index 97% rename from Source/Contents/WhisperBlockMgr.cpp rename to Source/Contents/Messenger/WhisperBlockMgr.cpp index d07d3a9..8a665ee 100644 --- a/Source/Contents/WhisperBlockMgr.cpp +++ b/Source/Contents/Messenger/WhisperBlockMgr.cpp @@ -1,4 +1,4 @@ -#include "Contents/WhisperBlockMgr.h" +#include "Contents/Messenger/WhisperBlockMgr.h" #include "Network/TextEncoding.h" #include @@ -22,15 +22,18 @@ bool CWhisperBlockMgr::Initialize() { if (g_whisperBlockMgr) { return false; } + g_whisperBlockMgr = new (std::nothrow) CWhisperBlockMgr; if (!g_whisperBlockMgr) { return false; } + if (!g_whisperBlockMgr->m_enabled) { delete g_whisperBlockMgr; g_whisperBlockMgr = nullptr; return false; } + return true; } @@ -49,6 +52,7 @@ void CWhisperBlockMgr::Clear() { if (this->m_tracking) { ++this->m_changes; } + this->m_names.clear(); } @@ -58,6 +62,7 @@ void CWhisperBlockMgr::Add(std::string name) { if (this->m_tracking) { ++this->m_changes; } + this->m_names.emplace(name.c_str()); } @@ -73,6 +78,7 @@ void CWhisperBlockMgr::Remove(std::string name) { if (this->m_tracking) { ++this->m_changes; } + this->m_names.erase(std::string(name.c_str())); } diff --git a/Source/Contents/WhisperBlockMgr.h b/Source/Contents/Messenger/WhisperBlockMgr.h similarity index 80% rename from Source/Contents/WhisperBlockMgr.h rename to Source/Contents/Messenger/WhisperBlockMgr.h index 07b23f8..d53961d 100644 --- a/Source/Contents/WhisperBlockMgr.h +++ b/Source/Contents/Messenger/WhisperBlockMgr.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WHISPERBLOCKMGR_H -#define RAGNAROK_SOURCE_CONTENTS_WHISPERBLOCKMGR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_MESSENGER_WHISPERBLOCKMGR_H +#define RAGNAROK_SOURCE_CONTENTS_MESSENGER_WHISPERBLOCKMGR_H #include #include @@ -21,7 +21,7 @@ public: protected: friend class CAccountLinkedUserDataMgr; - // Original +4 is the compiler's polymorphic alignment gap, not a proven field. + /* 0008 */ bool m_enabled; /* 0009 */ bool m_tracking; /* 0010 */ std::uint64_t m_changes; diff --git a/Source/Contents/ModelAnimation.h b/Source/Contents/ModelAnimation.h deleted file mode 100644 index 180925e..0000000 --- a/Source/Contents/ModelAnimation.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_MODELANIMATION_H -#define RAGNAROK_SOURCE_CONTENTS_MODELANIMATION_H - -#include "Resource/ModelResource.h" -#include "Utility/AffineMatrix.h" - -#include - -// Outputs deliberately retain the original per-track write contracts. Legacy -// multi-key samplers leave output unchanged at/after their final key. -void SampleLegacyPosition(std::span keys, int frame, AffineMatrix& output); -void SampleLegacyRotation(std::span keys, int frame, AffineMatrix& output); -void SampleLegacyScale(std::span keys, int frame, AffineMatrix& output); -void SampleModelScale(std::span keys, float frame, AffineMatrix& output); -void SampleModelPosition( - std::span keys, - float frame, - const AffineMatrix& base, - AffineMatrix& output -); -void SampleModelRotation( - std::span keys, - float frame, - const AffineMatrix& base, - AffineMatrix& output -); -void QuaternionMatrix(const ModelRotationKey& key, AffineMatrix& output); -void InterpolateModelRotation( - float amount, - const ModelRotationKey& first, - const ModelRotationKey& second, - int spins, - ModelRotationKey& output -); - -#endif diff --git a/Source/Contents/ModelActor.cpp b/Source/Contents/Models/ModelActor.cpp similarity index 94% rename from Source/Contents/ModelActor.cpp rename to Source/Contents/Models/ModelActor.cpp index 52db59e..72e8736 100644 --- a/Source/Contents/ModelActor.cpp +++ b/Source/Contents/Models/ModelActor.cpp @@ -1,6 +1,5 @@ -#include "Contents/ModelActor.h" +#include "Contents/Models/ModelActor.h" -#include #include #include @@ -12,9 +11,8 @@ namespace { // OFFSET: 0x00AB59A0 C3dActor::C3dActor() - : position{}, rotation{}, scale{1, 1, 1}, offset{}, dirty(1), oriented{}, corners{}, minimum{}, maximum{}, - enabled(1), renderFrame(0), occlusionEnabled(0), occluded(0), alpha(255), commandMode(0), color(0xFFFFFFFFu), - playback(2), speed(0), shade(0) { + : position{}, rotation{}, scale{1, 1, 1}, offset{}, dirty(1), oriented{}, corners{}, minimum{}, maximum{}, enabled(1), renderFrame(0), occlusionEnabled(0), + occluded(0), alpha(255), commandMode(0), color(0xFFFFFFFFu), playback(2), speed(0), shade(0) { } // OFFSET: 0x00AB6420 @@ -68,8 +66,8 @@ void C3dActorV2::Assign(const C3dModelRes& resource) { this->shade = resource.shade; this->framesPerSecond = modern.framesPerSecond; const float inverse = 1.0f / modern.framesPerSecond; - const int milliseconds = std::bit_cast(1000u * static_cast(modern.animationLength)); - this->duration = static_cast(static_cast(milliseconds) * inverse); + const int milliseconds = 1000 * modern.animationLength; + this->duration = static_cast(milliseconds) * inverse; for (const std::string& name : resource.rootNames) { auto* root = new C3dNodeV2; @@ -119,6 +117,7 @@ void C3dActorV1::Prepare(ModelLightingContext& context) { const float* previousPosition = context.position; const std::uint32_t* previousColor = context.color; const int* previousShade = context.shade; + context.position = this->position; context.color = &this->color; context.shade = &this->shade; @@ -138,6 +137,7 @@ void C3dActorV2::Prepare(ModelLightingContext& context) { const float* previousPosition = context.position; const std::uint32_t* previousColor = context.color; const int* previousShade = context.shade; + context.position = this->position; context.color = &this->color; context.shade = &this->shade; diff --git a/Source/Contents/ModelActor.h b/Source/Contents/Models/ModelActor.h similarity index 90% rename from Source/Contents/ModelActor.h rename to Source/Contents/Models/ModelActor.h index ecd253a..e4173e6 100644 --- a/Source/Contents/ModelActor.h +++ b/Source/Contents/Models/ModelActor.h @@ -1,11 +1,9 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_MODELACTOR_H -#define RAGNAROK_SOURCE_CONTENTS_MODELACTOR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_MODELS_MODELACTOR_H +#define RAGNAROK_SOURCE_CONTENTS_MODELS_MODELACTOR_H -#include "Contents/ModelNode.h" -#include "Contents/ModelSpatial.h" +#include "Contents/Models/ModelNode.h" +#include "Contents/Models/ModelSpatial.h" -// RTTI C3dActor, C3dActorV1 and C3dActorV2. These are model actors, not -// CGameObject sprite actors. Runtime nodes borrow this owner and its resources. class C3dActor { public: C3dActor(); diff --git a/Source/Contents/ModelActorBounds.cpp b/Source/Contents/Models/ModelActorBounds.cpp similarity index 90% rename from Source/Contents/ModelActorBounds.cpp rename to Source/Contents/Models/ModelActorBounds.cpp index f88ae66..8b2107a 100644 --- a/Source/Contents/ModelActorBounds.cpp +++ b/Source/Contents/Models/ModelActorBounds.cpp @@ -1,12 +1,11 @@ -#include "Contents/ModelActor.h" +#include "Contents/Models/ModelActor.h" -#include #include #include namespace { float Absolute(float value) { - return std::bit_cast(std::bit_cast(value) & 0x7FFFFFFFu); + return std::fabs(value); } float Radians(float degrees) { @@ -65,8 +64,7 @@ void C3dActor::FinishBounds(const float* bounds, bool modern) { for (unsigned corner = 0; corner < 8; ++corner) { const float point[3] = { - bounds[(corner & 1u) ? 3 : 0], bounds[(corner == 2 || corner == 3 || corner == 6 || corner == 7) ? 4 : 1], - bounds[corner >= 4 ? 5 : 2] + bounds[(corner & 1u) ? 3 : 0], bounds[(corner == 2 || corner == 3 || corner == 6 || corner == 7) ? 4 : 1], bounds[corner >= 4 ? 5 : 2] }; for (unsigned axis = 0; axis < 3; ++axis) { @@ -101,8 +99,7 @@ void C3dActor::FinishBounds(const float* bounds, bool modern) { direction[0] = axes.values[axis * 3]; direction[1] = axes.values[axis * 3 + 1]; direction[2] = axes.values[axis * 3 + 2]; - const float inverse = - InverseLength((direction[0] * direction[0] + direction[1] * direction[1]) + direction[2] * direction[2]); + const float inverse = InverseLength((direction[0] * direction[0] + direction[1] * direction[1]) + direction[2] * direction[2]); direction[0] = inverse * direction[0]; direction[1] = inverse * direction[1]; direction[2] = inverse * direction[2]; @@ -124,8 +121,7 @@ void C3dActor::FinishBounds(const float* bounds, bool modern) { for (unsigned corner = 0; corner < 8; ++corner) { const float point[3] = { (corner == 1 || corner == 2 || corner == 5 || corner == 6) ? volume->size[0] : -volume->size[0], - (corner == 2 || corner == 3 || corner == 6 || corner == 7) ? volume->size[1] : -volume->size[1], - corner >= 4 ? volume->size[2] : -volume->size[2] + (corner == 2 || corner == 3 || corner == 6 || corner == 7) ? volume->size[1] : -volume->size[1], corner >= 4 ? volume->size[2] : -volume->size[2] }; for (unsigned axis = 0; axis < 3; ++axis) { diff --git a/Source/Contents/ModelAnimation.cpp b/Source/Contents/Models/ModelAnimation.cpp similarity index 76% rename from Source/Contents/ModelAnimation.cpp rename to Source/Contents/Models/ModelAnimation.cpp index 2dd6726..01f4893 100644 --- a/Source/Contents/ModelAnimation.cpp +++ b/Source/Contents/Models/ModelAnimation.cpp @@ -1,16 +1,11 @@ -#include "Contents/ModelAnimation.h" +#include "Contents/Models/ModelAnimation.h" -#include #include namespace { - int Difference(int a, int b) { - return std::bit_cast(static_cast(a) - static_cast(b)); - } - // OFFSET: 0x00554340 // FUNCTION: fn_02022 - // This is not a general quaternion decomposition: the original uses only the trace formula. + ModelRotationKey MatrixQuaternion(const AffineMatrix& matrix) { ModelRotationKey result{0, {0, 0, 0, 1}}; const float trace = ((matrix.values[0] + 1.0f) + matrix.values[4]) + matrix.values[8]; @@ -21,6 +16,7 @@ namespace { result.rotation[0] = (matrix.values[7] - matrix.values[5]) / divisor; result.rotation[1] = (matrix.values[2] - matrix.values[6]) / divisor; result.rotation[2] = (matrix.values[3] - matrix.values[1]) / divisor; + return result; } } @@ -43,12 +39,10 @@ void SampleLegacyPosition(std::span keys, int frame, Aff const auto& a = keys[next - 1]; const auto& b = keys[next]; - const float amount = - static_cast(Difference(frame, a.frame)) / static_cast(Difference(b.frame, a.frame)); + const float amount = static_cast((frame - a.frame)) / static_cast((b.frame - a.frame)); const float previous = static_cast(1.0 - static_cast(amount)); output.SetTranslation( - previous * a.position[0] + amount * b.position[0], previous * a.position[1] + amount * b.position[1], - previous * a.position[2] + amount * b.position[2] + previous * a.position[0] + amount * b.position[0], previous * a.position[1] + amount * b.position[1], previous * a.position[2] + amount * b.position[2] ); } } @@ -82,8 +76,7 @@ void SampleLegacyRotation(std::span keys, int frame, Aff return; } - const float amount = - static_cast(Difference(frame, a.frame)) / static_cast(Difference(b.frame, a.frame)); + const float amount = static_cast((frame - a.frame)) / static_cast((b.frame - a.frame)); ModelRotationKey result; InterpolateModelRotation(amount, a, b, 0, result); QuaternionMatrix(result, output); @@ -124,28 +117,21 @@ void SampleModelScale(std::span keys, float frame, Affin const ModelRotationKey first = next ? keys[next - 1] : ModelRotationKey{0, {1, 1, 1, 1}}; const auto& second = keys[next]; - const float amount = second.frame != first.frame ? (frame - static_cast(first.frame)) / - static_cast(Difference(second.frame, first.frame)) - : 0.0f; + const float amount = second.frame != first.frame ? (frame - static_cast(first.frame)) / static_cast((second.frame - first.frame)) : 0.0f; output.SetScale( - (1.0f - amount) * first.rotation[0] + second.rotation[0] * amount, - (1.0f - amount) * first.rotation[1] + second.rotation[1] * amount, + (1.0f - amount) * first.rotation[0] + second.rotation[0] * amount, (1.0f - amount) * first.rotation[1] + second.rotation[1] * amount, first.rotation[2] * (1.0f - amount) + second.rotation[2] * amount ); } // OFFSET: 0x005404A0 // FUNCTION: fn_01722 -void SampleModelPosition( - std::span keys, - float frame, - const AffineMatrix& base, - AffineMatrix& output -) { +void SampleModelPosition(std::span keys, float frame, const AffineMatrix& base, AffineMatrix& output) { if (keys.empty()) { output.values[9] = base.values[9]; output.values[10] = base.values[10]; output.values[11] = base.values[11]; + return; } @@ -154,6 +140,7 @@ void SampleModelPosition( output.values[9] = key.rotation[0]; output.values[10] = key.rotation[1]; output.values[11] = key.rotation[2]; + return; } @@ -163,12 +150,11 @@ void SampleModelPosition( ++next; } - const ModelRotationKey first = - next ? keys[next - 1] : ModelRotationKey{0, {base.values[9], base.values[10], base.values[11], 0}}; + const ModelRotationKey first = next ? keys[next - 1] : ModelRotationKey{0, {base.values[9], base.values[10], base.values[11], 0}}; const auto& second = keys[next]; - const float amount = - (frame - static_cast(first.frame)) / static_cast(Difference(second.frame, first.frame)); + const float amount = (frame - static_cast(first.frame)) / static_cast((second.frame - first.frame)); const float previous = 1.0f - amount; + output.values[9] = first.rotation[0] * previous + second.rotation[0] * amount; output.values[10] = first.rotation[1] * previous + second.rotation[1] * amount; output.values[11] = first.rotation[2] * previous + second.rotation[2] * amount; @@ -176,12 +162,7 @@ void SampleModelPosition( // OFFSET: 0x005407A0 // FUNCTION: fn_01724 -void SampleModelRotation( - std::span keys, - float frame, - const AffineMatrix& base, - AffineMatrix& output -) { +void SampleModelRotation(std::span keys, float frame, const AffineMatrix& base, AffineMatrix& output) { AffineMatrix rotation; if (keys.empty()) { @@ -197,14 +178,10 @@ void SampleModelRotation( } } - ModelRotationKey a = - next < keys.size() ? (next ? keys[next - 1] : MatrixQuaternion(base)) : ModelRotationKey{0, {0, 0, 0, 1}}; + ModelRotationKey a = next < keys.size() ? (next ? keys[next - 1] : MatrixQuaternion(base)) : ModelRotationKey{0, {0, 0, 0, 1}}; ModelRotationKey b = next < keys.size() ? keys[next] : ModelRotationKey{0, {0, 0, 0, 1}}; - const float amount = b.frame != a.frame - ? (frame - static_cast(a.frame)) / static_cast(Difference(b.frame, a.frame)) - : 0.0f; - float dot = ((b.rotation[0] * a.rotation[0] + b.rotation[1] * a.rotation[1]) + b.rotation[2] * a.rotation[2]) + - b.rotation[3] * a.rotation[3]; + const float amount = b.frame != a.frame ? (frame - static_cast(a.frame)) / static_cast((b.frame - a.frame)) : 0.0f; + float dot = ((b.rotation[0] * a.rotation[0] + b.rotation[1] * a.rotation[1]) + b.rotation[2] * a.rotation[2]) + b.rotation[3] * a.rotation[3]; if (dot < 0.0f) { for (float& value : a.rotation) { diff --git a/Source/Contents/Models/ModelAnimation.h b/Source/Contents/Models/ModelAnimation.h new file mode 100644 index 0000000..28904dc --- /dev/null +++ b/Source/Contents/Models/ModelAnimation.h @@ -0,0 +1,18 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_MODELS_MODELANIMATION_H +#define RAGNAROK_SOURCE_CONTENTS_MODELS_MODELANIMATION_H + +#include "Resource/Models/ModelResource.h" +#include "Utility/Math/AffineMatrix.h" + +#include + +void SampleLegacyPosition(std::span keys, int frame, AffineMatrix& output); +void SampleLegacyRotation(std::span keys, int frame, AffineMatrix& output); +void SampleLegacyScale(std::span keys, int frame, AffineMatrix& output); +void SampleModelScale(std::span keys, float frame, AffineMatrix& output); +void SampleModelPosition(std::span keys, float frame, const AffineMatrix& base, AffineMatrix& output); +void SampleModelRotation(std::span keys, float frame, const AffineMatrix& base, AffineMatrix& output); +void QuaternionMatrix(const ModelRotationKey& key, AffineMatrix& output); +void InterpolateModelRotation(float amount, const ModelRotationKey& first, const ModelRotationKey& second, int spins, ModelRotationKey& output); + +#endif diff --git a/Source/Contents/ModelLighting.cpp b/Source/Contents/Models/ModelLighting.cpp similarity index 80% rename from Source/Contents/ModelLighting.cpp rename to Source/Contents/Models/ModelLighting.cpp index 96adbc4..720453f 100644 --- a/Source/Contents/ModelLighting.cpp +++ b/Source/Contents/Models/ModelLighting.cpp @@ -1,15 +1,14 @@ -#include "Contents/GroundGeometry.h" -#include "Contents/ModelNode.h" -#include "Render/Texture.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Contents/Models/ModelNode.h" +#include "Render/Textures/Texture.h" -#include +#include "Utility/Math/ScalarConversion.h" #include #include -#include namespace { unsigned Byte(float value) { - return static_cast(_mm_cvttss_si32(_mm_set_ss(value))) & 255u; + return static_cast(TruncateToInt(value)) & 255u; } float InverseLength(float squared) { @@ -22,8 +21,7 @@ namespace { const float y = ((normal[0] * matrix[1] + normal[1] * matrix[4]) + normal[2] * matrix[7]) + 0.0f; const float z = ((normal[0] * matrix[2] + normal[1] * matrix[5]) + normal[2] * matrix[8]) + 0.0f; const float inverse = InverseLength((y * y + x * x) + z * z); - const float dot = ((y * inverse) * context.direction[1] + (x * inverse) * context.direction[0]) + - (z * inverse) * context.direction[2]; + const float dot = ((y * inverse) * context.direction[1] + (x * inverse) * context.direction[0]) + (z * inverse) * context.direction[2]; const float amount = dot > 0.0f ? dot : 0.0f; for (unsigned component = 0; component < 3; ++component) { @@ -81,19 +79,16 @@ void C3dNode::SampleGroundColors(const float* matrix, const float* position, con for (unsigned corner = 0; corner < 3; ++corner) { const auto& vertex = this->mesh->vertices[face.vertices[corner]]; - const float x = - (((vertex[0] * matrix[0] + vertex[1] * matrix[3]) + vertex[2] * matrix[6]) + matrix[9]) + position[0]; - const float y = - (((vertex[0] * matrix[1] + vertex[1] * matrix[4]) + vertex[2] * matrix[7]) + matrix[10]) + position[1]; - const float z = - (((vertex[0] * matrix[2] + vertex[1] * matrix[5]) + vertex[2] * matrix[8]) + matrix[11]) + position[2]; + const float x = (((vertex[0] * matrix[0] + vertex[1] * matrix[3]) + vertex[2] * matrix[6]) + matrix[9]) + position[0]; + const float y = (((vertex[0] * matrix[1] + vertex[1] * matrix[4]) + vertex[2] * matrix[7]) + matrix[10]) + position[1]; + const float z = (((vertex[0] * matrix[2] + vertex[1] * matrix[5]) + vertex[2] * matrix[8]) + matrix[11]) + position[2]; std::uint32_t sampled[3]; ground.WorldColor(x, y, z, sampled); for (unsigned component = 0; component < 3; ++component) { const unsigned shift = 16u - component * 8u; const unsigned base = (this->faceState[index].colors[corner] >> shift) & 255u; - const int value = std::bit_cast(sampled[component] + base); + const int value = static_cast(sampled[component]) + base; this->faceValues[index * 9u + corner * 3u + component] = value > 255 ? 255 : value; } } @@ -126,7 +121,7 @@ void C3dNode::Prepare(const float* matrix, ModelLightingContext& context) { Light(this->mesh->vertexNormals[index * 3u + corner].data(), combined.values, context, light); } - const bool shaded = this->mesh->textureVertices[face.textureVertices[corner]][0] != 0; + const bool shaded = this->mesh->textureVertices[face.textureVertices[corner]].shaded != 0; color = LitColor(*context.color, this->alpha, shaded, light); } } @@ -137,11 +132,9 @@ void C3dNode::Prepare(const float* matrix, ModelLightingContext& context) { while (index < this->mesh->faces.size()) { const unsigned texture = this->mesh->faces[index].texture; CTexture* image = this->textures[texture % this->textures.size()]; - // Image dimensions are unsigned; original converts through double first. - const float u = static_cast(static_cast(image->CTexture::Width())) / - static_cast(static_cast(image->TextureWidth())); - const float v = static_cast(static_cast(image->CTexture::Height())) / - static_cast(static_cast(image->TextureHeight())); + + const float u = static_cast(static_cast(image->CTexture::Width())) / static_cast(static_cast(image->TextureWidth())); + const float v = static_cast(static_cast(image->CTexture::Height())) / static_cast(static_cast(image->TextureHeight())); do { const ModelFace& face = this->mesh->faces[index]; @@ -157,8 +150,8 @@ void C3dNode::Prepare(const float* matrix, ModelLightingContext& context) { state.uv[corner][1] = v; } else { const auto& uv = this->mesh->textureVertices[face.textureVertices[corner]]; - state.uv[corner][1] = v * std::bit_cast(uv[2]); - state.uv[corner][0] = u * std::bit_cast(uv[1]); + state.uv[corner][1] = v * uv.v; + state.uv[corner][0] = u * uv.u; } } diff --git a/Source/Contents/ModelMovies.cpp b/Source/Contents/Models/ModelMovies.cpp similarity index 79% rename from Source/Contents/ModelMovies.cpp rename to Source/Contents/Models/ModelMovies.cpp index 9a52afd..3c3c322 100644 --- a/Source/Contents/ModelMovies.cpp +++ b/Source/Contents/Models/ModelMovies.cpp @@ -1,5 +1,5 @@ -#include "Contents/BinkMovies.h" -#include "Resource/ModelResource.h" +#include "Contents/Movies/BinkMovies.h" +#include "Resource/Models/ModelResource.h" // OFFSET: 0x0075CDF0 // FUNCTION: fn_08028 diff --git a/Source/Contents/ModelNode.cpp b/Source/Contents/Models/ModelNode.cpp similarity index 92% rename from Source/Contents/ModelNode.cpp rename to Source/Contents/Models/ModelNode.cpp index 5cc188c..ca1f428 100644 --- a/Source/Contents/ModelNode.cpp +++ b/Source/Contents/Models/ModelNode.cpp @@ -1,8 +1,7 @@ -#include "Contents/ModelNode.h" +#include "Contents/Models/ModelNode.h" +#include "Utility/Math/ScalarConversion.h" -#include #include -#include // OFFSET: 0x00AB5CE0 // FUNCTION: fn_17464 @@ -12,7 +11,6 @@ C3dNode::C3dNode() : model(nullptr), parent(nullptr), mesh(nullptr), alpha(1.0f) // OFFSET: 0x00AB66A0 // FUNCTION: fn_17471 C3dNode::~C3dNode() { - // Delete while every list node still exists, as in the original base cleanup. for (C3dNode* child : this->children) { delete child; } @@ -59,9 +57,7 @@ void C3dNodeV1::Initialize(const ModelNode& resource) { if (this->rotationKeys.empty()) { const float halfAngle = resource.angle * 0.5f; const float sine = ClientSin(halfAngle); - this->rotationKeys.push_back( - {0, {sine * resource.axis[0], sine * resource.axis[1], sine * resource.axis[2], ClientCos(halfAngle)}} - ); + this->rotationKeys.push_back({0, {sine * resource.axis[0], sine * resource.axis[1], sine * resource.axis[2], ClientCos(halfAngle)}}); } this->positionKeys = resource.legacyPositionKeys; @@ -122,7 +118,7 @@ void C3dNodeV2::Initialize(const ModelNode& resource) { // OFFSET: 0x00AB9120 // FUNCTION: fn_17507 void C3dNodeV1::Animate(double frame) { - const int selected = _mm_cvttsd_si32(_mm_set_sd(frame)); + const int selected = TruncateToInt(frame); AffineMatrix position; AffineMatrix scale; AffineMatrix rotation; diff --git a/Source/Contents/ModelNode.h b/Source/Contents/Models/ModelNode.h similarity index 67% rename from Source/Contents/ModelNode.h rename to Source/Contents/Models/ModelNode.h index 946ff49..08c7070 100644 --- a/Source/Contents/ModelNode.h +++ b/Source/Contents/Models/ModelNode.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_MODELNODE_H -#define RAGNAROK_SOURCE_CONTENTS_MODELNODE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_MODELS_MODELNODE_H +#define RAGNAROK_SOURCE_CONTENTS_MODELS_MODELNODE_H -#include "Contents/ModelAnimation.h" -#include "Contents/ModelRendering.h" +#include "Contents/Models/ModelAnimation.h" +#include "Contents/Models/ModelRendering.h" #include @@ -12,12 +12,8 @@ struct ModelTextureTransform { float values[5] = {0, 0, 1, 1, 0}; }; -using ModelTextureChannels = std::map>>; void SampleModelTexture(const ModelTextureChannels& channels, float frame, ModelTextureTransform& output); -// Runtime C3dNode hierarchy. Meshes/textures and the owning model are borrowed; -// children are owned here. Resource nodes are copied at initialization, not kept -// as alternate live animation state. Rendering remains a separate node operation. class C3dNode { public: C3dNode(); @@ -27,13 +23,7 @@ public: virtual void Initialize(const ModelNode& resource); virtual void Animate(double frame); - virtual void Draw( - const float* matrix, - unsigned char reversed, - bool clip, - unsigned char commandMode, - ModelRenderContext& context - ) = 0; + virtual void Draw(const float* matrix, unsigned char reversed, bool clip, unsigned char commandMode, ModelRenderContext& context) = 0; C3dNode* Find(const char* name); void OverrideColors(); void Prepare(const float* matrix, ModelLightingContext& context); @@ -59,13 +49,7 @@ public: ~C3dNodeV1() override; void Initialize(const ModelNode& resource) override; void Animate(double frame) override; - void Draw( - const float* matrix, - unsigned char reversed, - bool clip, - unsigned char commandMode, - ModelRenderContext& context - ) override; + void Draw(const float* matrix, unsigned char reversed, bool clip, unsigned char commandMode, ModelRenderContext& context) override; std::vector scaleKeys; std::vector rotationKeys; @@ -78,13 +62,7 @@ public: ~C3dNodeV2() override; void Initialize(const ModelNode& resource) override; void Animate(double frame) override; - void Draw( - const float* matrix, - unsigned char reversed, - bool clip, - unsigned char commandMode, - ModelRenderContext& context - ) override; + void Draw(const float* matrix, unsigned char reversed, bool clip, unsigned char commandMode, ModelRenderContext& context) override; AffineMatrix resourceTransform; AffineMatrix localTransform; diff --git a/Source/Contents/ModelNodeBounds.cpp b/Source/Contents/Models/ModelNodeBounds.cpp similarity index 61% rename from Source/Contents/ModelNodeBounds.cpp rename to Source/Contents/Models/ModelNodeBounds.cpp index 562aa66..84007f0 100644 --- a/Source/Contents/ModelNodeBounds.cpp +++ b/Source/Contents/Models/ModelNodeBounds.cpp @@ -1,4 +1,4 @@ -#include "Contents/ModelNode.h" +#include "Contents/Models/ModelNode.h" #include @@ -11,15 +11,9 @@ void C3dNode::AccumulateBounds(float* bounds, const float* matrix) { combined.Compose(this->transform, parentMatrix); for (const auto& vertex : this->mesh->vertices) { - const float x = - ((vertex[0] * combined.values[0] + vertex[1] * combined.values[3]) + vertex[2] * combined.values[6]) + - combined.values[9]; - const float y = - ((vertex[1] * combined.values[4] + vertex[0] * combined.values[1]) + vertex[2] * combined.values[7]) + - combined.values[10]; - const float z = - ((vertex[0] * combined.values[2] + vertex[1] * combined.values[5]) + vertex[2] * combined.values[8]) + - combined.values[11]; + const float x = ((vertex[0] * combined.values[0] + vertex[1] * combined.values[3]) + vertex[2] * combined.values[6]) + combined.values[9]; + const float y = ((vertex[1] * combined.values[4] + vertex[0] * combined.values[1]) + vertex[2] * combined.values[7]) + combined.values[10]; + const float z = ((vertex[0] * combined.values[2] + vertex[1] * combined.values[5]) + vertex[2] * combined.values[8]) + combined.values[11]; if (bounds[0] > x) { bounds[0] = x; diff --git a/Source/Contents/ModelOcclusion.cpp b/Source/Contents/Models/ModelOcclusion.cpp similarity index 92% rename from Source/Contents/ModelOcclusion.cpp rename to Source/Contents/Models/ModelOcclusion.cpp index 36b9f93..8d2c2bd 100644 --- a/Source/Contents/ModelOcclusion.cpp +++ b/Source/Contents/Models/ModelOcclusion.cpp @@ -1,10 +1,10 @@ -#include "Contents/ModelActor.h" +#include "Contents/Models/ModelActor.h" -#include +#include namespace { float Absolute(float value) { - return std::bit_cast(std::bit_cast(value) & 0x7FFFFFFFu); + return std::fabs(value); } bool Intersects(const float* ray, const OrientedBounds& bounds) { @@ -28,6 +28,7 @@ namespace { const float second = (distance - radius) * inverse; const float lower = first <= second ? first : second; const float upper = first <= second ? second : first; + near = lower > near ? lower : near; far = upper < far ? upper : far; diff --git a/Source/Contents/ModelPlayback.cpp b/Source/Contents/Models/ModelPlayback.cpp similarity index 57% rename from Source/Contents/ModelPlayback.cpp rename to Source/Contents/Models/ModelPlayback.cpp index 46ecf37..6fcaf4b 100644 --- a/Source/Contents/ModelPlayback.cpp +++ b/Source/Contents/Models/ModelPlayback.cpp @@ -1,26 +1,9 @@ -#include "Contents/ModelActor.h" +#include "Contents/Models/ModelActor.h" +#include "Utility/Math/ScalarConversion.h" -#include -#include #include namespace { - unsigned UnsignedFrame(float value) { - const unsigned bits = std::bit_cast(value); - const unsigned magnitude = (bits & 0x7FFFFFFFu) << 1; - - if (bits & 0x80000000u) { - return magnitude >= 0x7F000000u ? 0xFFFFFFFFu : static_cast(_mm_cvttss_si32(_mm_set_ss(value))); - } - - if (magnitude >= 0x9F000000u) { - return 0xFFFFFFFFu; - } - - return magnitude >= 0x9E000000u ? (magnitude << 7) | 0x80000000u - : static_cast(_mm_cvttss_si32(_mm_set_ss(value))); - } - unsigned UnsignedFrame(double value) { if (!(value < 0x1p32) || value <= -1.0) { return 0xFFFFFFFFu; @@ -43,10 +26,10 @@ void C3dActorV1::Update() { return; } - this->frame = _mm_cvttss_si32(_mm_set_ss(this->speed * 100.0f + static_cast(this->frame))); + this->frame = TruncateToInt(this->speed * 100.0f + static_cast(this->frame)); if (this->frame >= this->animationLength) { - this->frame = this->playback == 1 ? std::bit_cast(static_cast(this->animationLength) - 1u) : 0; + this->frame = this->playback == 1 ? this->animationLength - 1 : 0; } this->Animate(static_cast(this->frame)); diff --git a/Source/Contents/ModelQuaternion.cpp b/Source/Contents/Models/ModelQuaternion.cpp similarity index 88% rename from Source/Contents/ModelQuaternion.cpp rename to Source/Contents/Models/ModelQuaternion.cpp index 5572bc0..a5c82bc 100644 --- a/Source/Contents/ModelQuaternion.cpp +++ b/Source/Contents/Models/ModelQuaternion.cpp @@ -1,4 +1,4 @@ -#include "Contents/ModelAnimation.h" +#include "Contents/Models/ModelAnimation.h" #include #include @@ -12,6 +12,7 @@ void QuaternionMatrix(const ModelRotationKey& key, AffineMatrix& output) { const float y = key.rotation[1]; const float z = key.rotation[2]; const float w = key.rotation[3]; + const float xx = x * (x + x); const float wx = w * (x + x); const float xy = x * (y + y); @@ -21,6 +22,7 @@ void QuaternionMatrix(const ModelRotationKey& key, AffineMatrix& output) { const float wy = w * (y + y); const float zz = z * (z + z); const float wz = w * (z + z); + output.values[9] = output.values[10] = output.values[11] = 0.0f; output.values[0] = 1.0f - (zz + yy); output.values[1] = xy + wz; @@ -35,15 +37,8 @@ void QuaternionMatrix(const ModelRotationKey& key, AffineMatrix& output) { // OFFSET: 0x00541B30 // FUNCTION: fn_01736 -void InterpolateModelRotation( - float amount, - const ModelRotationKey& first, - const ModelRotationKey& second, - int spins, - ModelRotationKey& output -) { - const float dot = ((second.rotation[1] * first.rotation[1] + second.rotation[0] * first.rotation[0]) + - first.rotation[2] * second.rotation[2]) + +void InterpolateModelRotation(float amount, const ModelRotationKey& first, const ModelRotationKey& second, int spins, ModelRotationKey& output) { + const float dot = ((second.rotation[1] * first.rotation[1] + second.rotation[0] * first.rotation[0]) + first.rotation[2] * second.rotation[2]) + first.rotation[3] * second.rotation[3]; const bool flip = dot < 0.0f; const float magnitude = flip ? -dot : dot; @@ -55,6 +50,7 @@ void InterpolateModelRotation( const float angle = static_cast(std::acos(static_cast(magnitude))); const float denominator = ClientSin(angle); const float phase = (static_cast(spins) * 3.141592f + angle) * amount; + firstWeight = ClientSin(angle - phase) / denominator; secondWeight = ClientSin(phase) / denominator; } else { diff --git a/Source/Contents/ModelRendering.cpp b/Source/Contents/Models/ModelRendering.cpp similarity index 69% rename from Source/Contents/ModelRendering.cpp rename to Source/Contents/Models/ModelRendering.cpp index f24a63c..e574ead 100644 --- a/Source/Contents/ModelRendering.cpp +++ b/Source/Contents/Models/ModelRendering.cpp @@ -1,34 +1,23 @@ -#include "Contents/ModelActor.h" -#include "Contents/ModelNode.h" -#include "Contents/ModelRendering.h" -#include "Render/RenderCommandPool.h" -#include "Render/RenderProjection.h" -#include "Render/RenderQueues.h" -#include "Render/RenderVertexPool.h" -#include "Render/Texture.h" +#include "Contents/Models/ModelActor.h" +#include "Contents/Models/ModelNode.h" +#include "Contents/Models/ModelRendering.h" +#include "Render/Primitives/RenderCommandPool.h" +#include "Render/Projection/RenderProjection.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/Primitives/RenderVertexPool.h" +#include "Render/Textures/Texture.h" -#include +#include "Utility/Math/ScalarConversion.h" #include -#include ModelRenderContext::ModelRenderContext( - const RenderProjection& projection, - RenderCommandPool& commands, - RenderVertexPool& vertices, - RenderQueues& queues, - const int& width, - const int& height, - const bool& depthAlpha, - const float& depthStart, - const float& depthEnd, - const bool& overrideColor, - const bool& integerColor, - const float* overrideScale, + const RenderProjection& projection, RenderCommandPool& commands, RenderVertexPool& vertices, RenderQueues& queues, const int& width, const int& height, + const bool& depthAlpha, const float& depthStart, const float& depthEnd, const bool& overrideColor, const bool& integerColor, const float* overrideScale, const float* colorScale ) - : projection(projection), commands(commands), vertices(vertices), queues(queues), width(width), height(height), - depthAlpha(depthAlpha), depthStart(depthStart), depthEnd(depthEnd), overrideColor(overrideColor), - integerColor(integerColor), overrideScale(overrideScale), colorScale(colorScale) { + : projection(projection), commands(commands), vertices(vertices), queues(queues), width(width), height(height), depthAlpha(depthAlpha), + depthStart(depthStart), depthEnd(depthEnd), overrideColor(overrideColor), integerColor(integerColor), overrideScale(overrideScale), + colorScale(colorScale) { for (auto& vertex : this->legacyProjected) { vertex.specular = 0xFF000000u; } @@ -38,12 +27,7 @@ ModelRenderContext::ModelRenderContext( } } -bool ModelTriangleVisible( - const RenderVertex* a, - const RenderVertex* b, - const RenderVertex* c, - const ModelRenderContext& context -) { +bool ModelTriangleVisible(const RenderVertex* a, const RenderVertex* b, const RenderVertex* c, const ModelRenderContext& context) { const float firstMinimumX = a->x > b->x ? b->x : a->x; const float minimumX = firstMinimumX > c->x ? c->x : firstMinimumX; @@ -73,28 +57,19 @@ bool ModelTriangleVisible( namespace { unsigned Byte(float value) { - return static_cast(_mm_cvttss_si32(_mm_set_ss(value))) & 255u; + return static_cast(TruncateToInt(value)) & 255u; } std::uint32_t Color(std::uint32_t source, unsigned char alpha, const float* scale) { const unsigned red = Byte(static_cast((source >> 16) & 255u) * scale[0]); const unsigned green = Byte(static_cast((source >> 8) & 255u) * scale[1]); const unsigned blue = Byte(static_cast(source & 255u) * scale[2]); + return (static_cast(alpha) << 24) | (red << 16) | (green << 8) | blue; } } -// Shared source form of the two recovered node Draw bodies. Their winding and -// two-sided predicates differ and are intentionally selected at the call site. -void DrawModelNode( - C3dNode& node, - const float* matrix, - unsigned char reversed, - bool clip, - unsigned char commandMode, - ModelRenderContext& context, - bool modern -) { +void DrawModelNode(C3dNode& node, const float* matrix, unsigned char reversed, bool clip, unsigned char commandMode, ModelRenderContext& context, bool modern) { AffineMatrix camera; std::memcpy(camera.values, matrix, sizeof(camera.values)); AffineMatrix combined; @@ -114,8 +89,7 @@ void DrawModelNode( while (index < node.mesh->faces.size()) { const unsigned texture = node.mesh->faces[index].texture; RenderVertex* first = output; - // Modern original retains 0 or 32 here: a transformed UV sets bit 0x20 - // in the group's queue flags, even if the color override is independent. + std::uint16_t flags = 0; do { @@ -127,8 +101,7 @@ void DrawModelNode( const float left = (b.y - a.y) * (c.x - a.x); const float right = (c.y - a.y) * (b.x - a.x); const bool winding = modern ? right > left : left > right; - const bool accepted = - modern ? (winding ? reversed == 0 : reversed == 1) : (winding ? reversed == 0 : reversed != 0); + const bool accepted = modern ? (winding ? reversed == 0 : reversed == 1) : (winding ? reversed == 0 : reversed != 0); visible = visible && (accepted || (modern ? face.twoSided == 1 : face.twoSided != 0)); if (visible) { @@ -162,10 +135,8 @@ void DrawModelNode( output[corner].diffuse = (state.colors[corner] & 0x00FFFFFFu) | 0x80000000u; } else if (context.integerColor) { const int* values = node.faceValues.data() + index * 9u + corner * 3u; - output[corner].diffuse = (static_cast(alpha) << 24) | - (Byte(static_cast(values[0]) * colorScale[0]) << 16) | - (Byte(static_cast(values[1]) * colorScale[1]) << 8) | - Byte(static_cast(values[2]) * colorScale[2]); + output[corner].diffuse = (static_cast(alpha) << 24) | (Byte(static_cast(values[0]) * colorScale[0]) << 16) | + (Byte(static_cast(values[1]) * colorScale[1]) << 8) | Byte(static_cast(values[2]) * colorScale[2]); } else { output[corner].diffuse = Color(state.colors[corner], alpha, colorScale); } @@ -182,10 +153,9 @@ void DrawModelNode( command->vertices = first; command->vertexCount = static_cast(output - first); command->texture = node.textures[texture % node.textures.size()]; - command->unknown_0014 = - static_cast((command->unknown_0014 & 0x00FFu) | (static_cast(commandMode) << 8)); + command->unknown_0014 = static_cast((command->unknown_0014 & 0x00FFu) | (static_cast(commandMode) << 8)); - if (alpha != 255 || command->texture->Format() == 1) { + if (alpha != 255 || command->texture->Format() == TextureFormat::A4R4G4B4) { flags |= 1; } @@ -202,24 +172,12 @@ void DrawModelNode( // OFFSET: 0x00AB7D40 // FUNCTION: fn_17499 -void C3dNodeV1::Draw( - const float* matrix, - unsigned char reversed, - bool clip, - unsigned char commandMode, - ModelRenderContext& context -) { +void C3dNodeV1::Draw(const float* matrix, unsigned char reversed, bool clip, unsigned char commandMode, ModelRenderContext& context) { DrawModelNode(*this, matrix, reversed, clip, commandMode, context, false); } // OFFSET: 0x00AB84B0 // FUNCTION: fn_17500 -void C3dNodeV2::Draw( - const float* matrix, - unsigned char reversed, - bool clip, - unsigned char commandMode, - ModelRenderContext& context -) { +void C3dNodeV2::Draw(const float* matrix, unsigned char reversed, bool clip, unsigned char commandMode, ModelRenderContext& context) { DrawModelNode(*this, matrix, reversed, clip, commandMode, context, true); } diff --git a/Source/Contents/ModelRendering.h b/Source/Contents/Models/ModelRendering.h similarity index 51% rename from Source/Contents/ModelRendering.h rename to Source/Contents/Models/ModelRendering.h index f6df94e..1a0b569 100644 --- a/Source/Contents/ModelRendering.h +++ b/Source/Contents/Models/ModelRendering.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_MODELRENDERING_H -#define RAGNAROK_SOURCE_CONTENTS_MODELRENDERING_H +#ifndef RAGNAROK_SOURCE_CONTENTS_MODELS_MODELRENDERING_H +#define RAGNAROK_SOURCE_CONTENTS_MODELS_MODELRENDERING_H -#include "Render/RenderPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" #include @@ -12,7 +12,6 @@ class RenderVertexPool; class C3dNode; struct ModelTextureTransform; -// Runtime face data is colors then three UV pairs, not nine numeric positions. struct ModelFaceState { std::uint32_t colors[3]; float uv[3][2]; @@ -26,7 +25,7 @@ struct ModelLightingContext { const float* ambient; const int* shade; const class GroundGeometry& ground; - // Shared color scratch; unknown shade values retain it. + std::array colors{}; }; @@ -44,44 +43,20 @@ struct ModelRenderContext { const bool& integerColor; const float* overrideScale; const float* colorScale; - // Distinct original static scratch arrays, initialized once to 30000 vertices. - // Projection changes only x/y/z/rhw; the other fields retain their values. + std::array legacyProjected{}; std::array modernProjected{}; ModelRenderContext( - const RenderProjection& projection, - RenderCommandPool& commands, - RenderVertexPool& vertices, - RenderQueues& queues, - const int& width, - const int& height, - const bool& depthAlpha, - const float& depthStart, - const float& depthEnd, - const bool& overrideColor, - const bool& integerColor, - const float* overrideScale, + const RenderProjection& projection, RenderCommandPool& commands, RenderVertexPool& vertices, RenderQueues& queues, const int& width, const int& height, + const bool& depthAlpha, const float& depthStart, const float& depthEnd, const bool& overrideColor, const bool& integerColor, const float* overrideScale, const float* colorScale ); }; -bool ModelTriangleVisible( - const RenderVertex* a, - const RenderVertex* b, - const RenderVertex* c, - const ModelRenderContext& context -); +bool ModelTriangleVisible(const RenderVertex* a, const RenderVertex* b, const RenderVertex* c, const ModelRenderContext& context); void TransformModelUV(float& u, float& v, const ModelTextureTransform& transform); -void DrawModelNode( - C3dNode& node, - const float* matrix, - unsigned char reversed, - bool clip, - unsigned char commandMode, - ModelRenderContext& context, - bool modern -); +void DrawModelNode(C3dNode& node, const float* matrix, unsigned char reversed, bool clip, unsigned char commandMode, ModelRenderContext& context, bool modern); static_assert(sizeof(ModelFaceState) == 36); diff --git a/Source/Contents/ModelSpatial.cpp b/Source/Contents/Models/ModelSpatial.cpp similarity index 71% rename from Source/Contents/ModelSpatial.cpp rename to Source/Contents/Models/ModelSpatial.cpp index 1f95d7c..afc7ff8 100644 --- a/Source/Contents/ModelSpatial.cpp +++ b/Source/Contents/Models/ModelSpatial.cpp @@ -1,10 +1,10 @@ -#include "Contents/ModelSpatial.h" +#include "Contents/Models/ModelSpatial.h" -#include +#include namespace { float Absolute(float value) { - return std::bit_cast(std::bit_cast(value) & 0x7FFFFFFFu); + return std::fabs(value); } } @@ -12,12 +12,9 @@ namespace { // FUNCTION: fn_17702 bool OrientedBounds::Intersects(const float* bounds) const { constexpr double tolerance = 0.000001; - const float extents[3] = { - (bounds[3] - bounds[0]) * 0.5f, (bounds[4] - bounds[1]) * 0.5f, (bounds[5] - bounds[2]) * 0.5f - }; + const float extents[3] = {(bounds[3] - bounds[0]) * 0.5f, (bounds[4] - bounds[1]) * 0.5f, (bounds[5] - bounds[2]) * 0.5f}; const float delta[3] = { - this->center[0] - (bounds[0] + bounds[3]) * 0.5f, this->center[1] - (bounds[1] + bounds[4]) * 0.5f, - this->center[2] - (bounds[2] + bounds[5]) * 0.5f + this->center[0] - (bounds[0] + bounds[3]) * 0.5f, this->center[1] - (bounds[1] + bounds[4]) * 0.5f, this->center[2] - (bounds[2] + bounds[5]) * 0.5f }; float projected[3]; float absolute[3][3]; @@ -30,32 +27,23 @@ bool OrientedBounds::Intersects(const float* bounds) const { absolute[axis][component] = Absolute(direction[component]); } - const float radius = - (absolute[axis][1] * extents[1] + absolute[axis][0] * extents[0]) + absolute[axis][2] * extents[2]; + const float radius = (absolute[axis][1] * extents[1] + absolute[axis][0] * extents[0]) + absolute[axis][2] * extents[2]; - if ( - static_cast(Absolute(projected[axis])) - (static_cast(radius) + this->halfSize[axis]) > tolerance - ) { + if (static_cast(Absolute(projected[axis])) - (static_cast(radius) + this->halfSize[axis]) > tolerance) { return false; } } for (unsigned component = 0; component < 3; ++component) { - const float radius = (this->halfSize[1] * absolute[1][component] + this->halfSize[0] * absolute[0][component]) + - this->halfSize[2] * absolute[2][component]; + const float radius = (this->halfSize[1] * absolute[1][component] + this->halfSize[0] * absolute[0][component]) + this->halfSize[2] * absolute[2][component]; - if ( - static_cast(Absolute(delta[component])) - (static_cast(radius) + extents[component]) > tolerance - ) { + if (static_cast(Absolute(delta[component])) - (static_cast(radius) + extents[component]) > tolerance) { return false; } } - // Preserve the original nine cross-axis tests and the float-pair sums - // promoted to double before the final radius addition/subtraction. const auto separated = [&](float distance, float first, float second) { - return static_cast(Absolute(distance)) - (static_cast(first) + static_cast(second)) > - tolerance; + return static_cast(Absolute(distance)) - (static_cast(first) + static_cast(second)) > tolerance; }; for (unsigned component = 0; component < 3; ++component) { diff --git a/Source/Contents/ModelSpatial.h b/Source/Contents/Models/ModelSpatial.h similarity index 51% rename from Source/Contents/ModelSpatial.h rename to Source/Contents/Models/ModelSpatial.h index 52c65b7..e39c4a8 100644 --- a/Source/Contents/ModelSpatial.h +++ b/Source/Contents/Models/ModelSpatial.h @@ -1,7 +1,6 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_MODELSPATIAL_H -#define RAGNAROK_SOURCE_CONTENTS_MODELSPATIAL_H +#ifndef RAGNAROK_SOURCE_CONTENTS_MODELS_MODELSPATIAL_H +#define RAGNAROK_SOURCE_CONTENTS_MODELS_MODELSPATIAL_H -// Model's oriented box at +0x98: half extents, center, then three local axes. struct OrientedBounds { float halfSize[3]; float center[3]; diff --git a/Source/Contents/ModelTextureAnimation.cpp b/Source/Contents/Models/ModelTextureAnimation.cpp similarity index 51% rename from Source/Contents/ModelTextureAnimation.cpp rename to Source/Contents/Models/ModelTextureAnimation.cpp index c45fb78..e044a3c 100644 --- a/Source/Contents/ModelTextureAnimation.cpp +++ b/Source/Contents/Models/ModelTextureAnimation.cpp @@ -1,6 +1,4 @@ -#include "Contents/ModelNode.h" - -#include +#include "Contents/Models/ModelNode.h" // OFFSET: 0x00540EA0 // FUNCTION: fn_01727 @@ -13,24 +11,24 @@ void SampleModelTexture(const ModelTextureChannels& channels, float frame, Model } const auto& keys = found->second; - const int last = std::bit_cast(keys.back()[0]); + const int last = keys.back().frame; if (frame >= static_cast(last)) { - output.values[channel] = std::bit_cast(keys.back()[1]); + output.values[channel] = keys.back().value; continue; } unsigned next = 1; - while (next < keys.size() && !(static_cast(std::bit_cast(keys[next][0])) > frame)) { + while (next < keys.size() && !(static_cast(keys[next].frame) > frame)) { ++next; } - const int previous = std::bit_cast(keys[next - 1][0]); - const int difference = std::bit_cast(keys[next][0] - keys[next - 1][0]); + const int previous = keys[next - 1].frame; + const int difference = keys[next].frame - keys[next - 1].frame; const float amount = (frame - static_cast(previous)) / static_cast(difference); - const float first = (1.0f - amount) * std::bit_cast(keys[next - 1][1]); - const float second = amount * std::bit_cast(keys[next][1]); + const float first = (1.0f - amount) * keys[next - 1].value; + const float second = amount * keys[next].value; output.values[channel] = first + second; } } diff --git a/Source/Contents/ModelTextureUV.cpp b/Source/Contents/Models/ModelTextureUV.cpp similarity index 81% rename from Source/Contents/ModelTextureUV.cpp rename to Source/Contents/Models/ModelTextureUV.cpp index 1245454..b3f99b9 100644 --- a/Source/Contents/ModelTextureUV.cpp +++ b/Source/Contents/Models/ModelTextureUV.cpp @@ -1,10 +1,6 @@ -#include "Contents/ModelNode.h" +#include "Contents/Models/ModelNode.h" namespace { - float Product(float first, float second) { - return first * second; - } - float Rotated(float sine, float delta, float cosineProduct, bool subtract) { const double product = static_cast(sine) * delta; return static_cast(subtract ? cosineProduct - product : product + cosineProduct); @@ -14,15 +10,16 @@ namespace { // ORIGINAL_SITE: 0x00AB8856 in fn_17500 (fragment) void TransformModelUV(float& u, float& v, const ModelTextureTransform& transform) { const float cosineU = ClientCos(transform.values[4]); - const float productU = Product(cosineU, u - 0.5f); + const float productU = cosineU * (u - 0.5f); const float sineU = ClientSin(transform.values[4]); const float rotatedU = Rotated(sineU, v - 0.5f, productU, true); const float resultU = (rotatedU * transform.values[2] + 0.5f) + transform.values[0]; const float cosineV = ClientCos(transform.values[4]); - const float productV = Product(cosineV, v - 0.5f); + const float productV = cosineV * (v - 0.5f); const float sineV = ClientSin(transform.values[4]); const float rotatedV = Rotated(sineV, u - 0.5f, productV, false); const float resultV = (rotatedV * transform.values[3] + 0.5f) + transform.values[1]; + u = resultU; v = resultV; } diff --git a/Source/Contents/BinkMovie.cpp b/Source/Contents/Movies/BinkMovie.cpp similarity index 89% rename from Source/Contents/BinkMovie.cpp rename to Source/Contents/Movies/BinkMovie.cpp index 14c4bb2..44e396b 100644 --- a/Source/Contents/BinkMovie.cpp +++ b/Source/Contents/Movies/BinkMovie.cpp @@ -1,7 +1,7 @@ -#include "Client/ErrorDialog.h" -#include "Contents/BinkMovie.h" -#include "Render/Texture.h" -#include "Resource/BitmapResource.h" +#include "Client/Application/ErrorDialog.h" +#include "Contents/Movies/BinkMovie.h" +#include "Render/Textures/Texture.h" +#include "Resource/Bitmap/BitmapResource.h" // OFFSET: 0x007AF6D0 // FUNCTION: fn_09154 @@ -40,7 +40,7 @@ bool BinkMovie::Open(const char* name, int loop, bool memory) { const auto* bytes = static_cast(context.file.Data()); this->m_bytes.assign(bytes, bytes + context.file.Size()); context.file.Close(); - // Original pushes this immediate value, not the contents at that address. + this->m_handle = context.runtime.open(this->m_bytes.data(), 0x04104000u); } else { this->m_handle = context.runtime.open(name, 0x00104000u); @@ -104,6 +104,7 @@ bool BinkMovie::CopyTo(CTexture* texture) { this->m_context->runtime.copyToBuffer(this->m_handle, locked.pixels, locked.pitch, locked.height, 0, 0, 5); texture->Unlock(); const RECT rectangle{0, 0, static_cast(locked.width), static_cast(locked.height)}; - texture->Update(static_cast(reinterpret_cast(&rectangle))); + texture->Update(&rectangle); + return true; } diff --git a/Source/Contents/BinkMovie.h b/Source/Contents/Movies/BinkMovie.h similarity index 76% rename from Source/Contents/BinkMovie.h rename to Source/Contents/Movies/BinkMovie.h index 793d9ff..e78a50f 100644 --- a/Source/Contents/BinkMovie.h +++ b/Source/Contents/Movies/BinkMovie.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_BINKMOVIE_H -#define RAGNAROK_SOURCE_CONTENTS_BINKMOVIE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_MOVIES_BINKMOVIE_H +#define RAGNAROK_SOURCE_CONTENTS_MOVIES_BINKMOVIE_H #include "Resource/BinkRuntime.h" @@ -15,8 +15,6 @@ struct BinkMovieContext { CRenderSystemBase*& renderSystem; }; -// Reconstructed name for 20-byte decoder wrapper. -// Owned input snapshots replace the original retained CFile read allocation. class BinkMovie { public: explicit BinkMovie(BinkMovieContext& context); diff --git a/Source/Contents/BinkMovies.cpp b/Source/Contents/Movies/BinkMovies.cpp similarity index 82% rename from Source/Contents/BinkMovies.cpp rename to Source/Contents/Movies/BinkMovies.cpp index c63b1a8..a938761 100644 --- a/Source/Contents/BinkMovies.cpp +++ b/Source/Contents/Movies/BinkMovies.cpp @@ -1,15 +1,13 @@ -#include "Contents/BinkMovies.h" -#include "Render/TextureCache.h" +#include "Contents/Movies/BinkMovies.h" +#include "Render/Textures/TextureCache.h" +#include "Utility/Math/ScalarConversion.h" #include -#include #include -#include // OFFSET: 0x007B00F0 // FUNCTION: fn_09165 -NamedBinkMovie::NamedBinkMovie(BinkMovieContext& context) - : decoder(std::make_unique(context)), radius(150.0f) { +NamedBinkMovie::NamedBinkMovie(BinkMovieContext& context) : decoder(std::make_unique(context)), radius(150.0f) { } // OFFSET: 0x007AFF80 @@ -43,6 +41,7 @@ NamedBinkMovie* BinkMovies::Get(std::string name, int loop) { movie->name = name; NamedBinkMovie* result = movie.get(); this->m_movies.push_back(std::move(movie)); + return result; } @@ -76,15 +75,15 @@ void BinkMovies::Update(TextureCache& textures, const float* playerPosition, int const float y = position.y - playerPosition[1]; const float z = position.z - playerPosition[2]; const float distance = std::sqrt((y * y + x * x) + z * z); - nearest = _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(distance), _mm_set_ss(nearest))); + nearest = distance < nearest ? distance : nearest; } int attenuation = 0; if (movie->radius > nearest) { const float scaled = (static_cast(volume) / movie->radius) * (movie->radius - nearest); - const int level = _mm_cvttss_si32(_mm_set_ss(scaled)); - attenuation = std::bit_cast(static_cast(level) << 8); + const unsigned level = static_cast(TruncateToInt(scaled)); + attenuation = static_cast(level * 256u); } this->m_context->runtime.setVolume(movie->decoder->Handle(), 0, attenuation); diff --git a/Source/Contents/BinkMovies.h b/Source/Contents/Movies/BinkMovies.h similarity index 65% rename from Source/Contents/BinkMovies.h rename to Source/Contents/Movies/BinkMovies.h index 329723d..9bc2a53 100644 --- a/Source/Contents/BinkMovies.h +++ b/Source/Contents/Movies/BinkMovies.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_BINKMOVIES_H -#define RAGNAROK_SOURCE_CONTENTS_BINKMOVIES_H +#ifndef RAGNAROK_SOURCE_CONTENTS_MOVIES_BINKMOVIES_H +#define RAGNAROK_SOURCE_CONTENTS_MOVIES_BINKMOVIES_H -#include "Contents/BinkMovie.h" +#include "Contents/Movies/BinkMovie.h" #include #include @@ -15,8 +15,6 @@ struct MoviePosition { float z; }; -// 40-byte named movie value, with borrowed spatial -// sound sources. Decoder and source-list storage belong to this record. struct NamedBinkMovie { explicit NamedBinkMovie(BinkMovieContext& context); ~NamedBinkMovie(); @@ -26,8 +24,6 @@ struct NamedBinkMovie { std::list positions; }; -// Original list owner at active game-mode player-manager +0xE0. Source-only -// context pointer replaces no application state or decoder behavior. class BinkMovies { public: explicit BinkMovies(BinkMovieContext& context); diff --git a/Source/Contents/NormalItemSlots.h b/Source/Contents/NormalItemSlots.h deleted file mode 100644 index ff6fe4f..0000000 --- a/Source/Contents/NormalItemSlots.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_NORMALITEMSLOTS_H -#define RAGNAROK_SOURCE_CONTENTS_NORMALITEMSLOTS_H - -#include -#include -namespace Json { - class Value; -} - -// Original client record at +0x6AC: 9 records, stride7. Only itemId is -// serialized by this operation; unknown bytes are not discarded globally. -#pragma pack(push, 1) -struct NormalItemSlot { - std::uint8_t unknown_0000; - std::uint32_t itemId; - std::uint16_t unknown_0005; -}; -#pragma pack(pop) -static_assert(sizeof(NormalItemSlot) == 7); -static_assert(offsetof(NormalItemSlot, itemId) == 1); - -// Window-state globals. -struct NormalItemSlotWindow { - int x; - int y; - int width; - int height; - int show; - void Reset(); - bool IsValid(int screenWidth, int screenHeight, bool active) const; -}; - -// Original caller supplies slots, window globals and client active flag+0x812D. -void ExportNormalItemSlots( - Json::Value& data, - const NormalItemSlot* slots, - const NormalItemSlotWindow& window, - bool active -); - -#endif diff --git a/Source/Contents/OptionWriter.h b/Source/Contents/OptionWriter.h deleted file mode 100644 index 07b4364..0000000 --- a/Source/Contents/OptionWriter.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_OPTIONWRITER_H -#define RAGNAROK_SOURCE_CONTENTS_OPTIONWRITER_H - -#include - -class CFile; - -// Borrowed original output-file owner. These routines preserve CRLF and the -// application's distinct integer/string/GUID formatting policies. -struct OptionWriter { - CFile& file; - - void Integer(const char* key, int value); - void String(const char* key, const char* value); - void Guid(const char* key, const GUID& value); -}; - -#endif diff --git a/Source/Contents/AdvenPartyInfo.cpp b/Source/Contents/Party/AdvenPartyInfo.cpp similarity index 76% rename from Source/Contents/AdvenPartyInfo.cpp rename to Source/Contents/Party/AdvenPartyInfo.cpp index 1e20b98..71363be 100644 --- a/Source/Contents/AdvenPartyInfo.cpp +++ b/Source/Contents/Party/AdvenPartyInfo.cpp @@ -1,10 +1,9 @@ -#include "Contents/AdvenPartyInfo.h" +#include "Contents/Party/AdvenPartyInfo.h" // OFFSET: 0x005CA660 // FUNCTION: fn_03647 CAdvenPartyInfo::CAdvenPartyInfo() - : tanker(false), healer(false), dealer(false), assist(false), minimumLevel(0), maximumLevel(999), type(0), - accountId(0), characterId(0) { + : tanker(false), healer(false), dealer(false), assist(false), minimumLevel(0), maximumLevel(999), type(0), accountId(0), characterId(0) { } // OFFSET: 0x005CA5B0 diff --git a/Source/Contents/AdvenPartyInfo.h b/Source/Contents/Party/AdvenPartyInfo.h similarity index 81% rename from Source/Contents/AdvenPartyInfo.h rename to Source/Contents/Party/AdvenPartyInfo.h index 8e88d27..1f31fe0 100644 --- a/Source/Contents/AdvenPartyInfo.h +++ b/Source/Contents/Party/AdvenPartyInfo.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ADVENPARTYINFO_H -#define RAGNAROK_SOURCE_CONTENTS_ADVENPARTYINFO_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_ADVENPARTYINFO_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_ADVENPARTYINFO_H #include #include @@ -9,7 +9,6 @@ namespace Json { class Value; } -// RTTI CAdvenPartyInfo; vector stride is 76 on x86. class CAdvenPartyInfo { public: CAdvenPartyInfo(); diff --git a/Source/Contents/AdventurerAgencyMgr.cpp b/Source/Contents/Party/AdventurerAgencyMgr.cpp similarity index 81% rename from Source/Contents/AdventurerAgencyMgr.cpp rename to Source/Contents/Party/AdventurerAgencyMgr.cpp index 6e56cf0..ecfceb9 100644 --- a/Source/Contents/AdventurerAgencyMgr.cpp +++ b/Source/Contents/Party/AdventurerAgencyMgr.cpp @@ -1,22 +1,15 @@ -#include "Contents/AccountService.h" -#include "Contents/AdventurerAgencyMgr.h" +#include "Contents/UserData/AccountService.h" +#include "Contents/Party/AdventurerAgencyMgr.h" -#include #include #include -// Original __dtoui3 saturates invalid/out-of-range inputs on its SSE path. -// The application calls asDouble, not Json::Value::asUInt, before conversion. std::uint32_t CAdventurerAgencyMgr::Id(double value) { if (!(value < 4294967296.0) || value <= -1.0) { return 0xFFFFFFFFu; } - if (value < 2147483648.0) { - return static_cast(_mm_cvttsd_si32(_mm_set_sd(value))); - } - - return static_cast(_mm_cvttsd_si32(_mm_set_sd(value - 2147483648.0))) | 0x80000000u; + return static_cast(value); } // STATIC: 0x01389848 @@ -73,14 +66,8 @@ const std::vector& CAdventurerAgencyMgr::Entries() const { // OFFSET: 0x005CAA50 // FUNCTION: fn_03655 -std::string CAdventurerAgencyMgr::ServiceUrl( - int operation, - LuaScript& settings, - LuaScript& tables, - const char* host, - const char* port, - const char* overrideKey -) const { +std::string +CAdventurerAgencyMgr::ServiceUrl(int operation, LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey) const { std::string url = ResolveAccountServiceBase(settings, tables, host, port, overrideKey); if (url.empty()) { diff --git a/Source/Contents/AdventurerAgencyMgr.h b/Source/Contents/Party/AdventurerAgencyMgr.h similarity index 75% rename from Source/Contents/AdventurerAgencyMgr.h rename to Source/Contents/Party/AdventurerAgencyMgr.h index 3492adf..0b44e4c 100644 --- a/Source/Contents/AdventurerAgencyMgr.h +++ b/Source/Contents/Party/AdventurerAgencyMgr.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ADVENTURERAGENCYMGR_H -#define RAGNAROK_SOURCE_CONTENTS_ADVENTURERAGENCYMGR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_ADVENTURERAGENCYMGR_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_ADVENTURERAGENCYMGR_H -#include "Contents/AdvenPartyInfo.h" +#include "Contents/Party/AdvenPartyInfo.h" struct AsyncDiagnostic; struct StopRecruitingContext; @@ -11,7 +11,6 @@ struct AgencyRequestContext; class WindowManagerWindows; class LuaScript; -// RTTI CAdventurerAgencyMgr, original x86 size 28. class CAdventurerAgencyMgr { public: CAdventurerAgencyMgr(); @@ -20,18 +19,12 @@ public: static void Shutdown(); void LoadList(const Json::Value& value); const std::vector& Entries() const; - void RequestChangeMaster( - std::uint32_t targetAccountId, - std::uint32_t targetCharacterId, - std::string targetName, - AgencyRequestContext& context - ); + void RequestChangeMaster(std::uint32_t targetAccountId, std::uint32_t targetCharacterId, std::string targetName, AgencyRequestContext& context); void RequestMyParty(AgencyRequestContext& context); void RequestList(int page, AgencyRequestContext& context); void RequestInfo(std::uint32_t queryAccountId, AgencyRequestContext& context, PartyInfoContext& completion); void RequestSearch(const CAdvenPartyInfo& filter, int page, AgencyRequestContext& context); - void - RequestRegistration(const CAdvenPartyInfo& info, AgencyRequestContext& context, RegisterPartyContext& completion); + void RequestRegistration(const CAdvenPartyInfo& info, AgencyRequestContext& context, RegisterPartyContext& completion); void RequestStop(std::uint32_t masterAccountId, AgencyRequestContext& context, StopRecruitingContext& completion); void RequestStop(AgencyRequestContext& context, StopRecruitingContext& completion); void CompleteChangeMaster(AsyncDiagnostic diagnostic, std::string response, WindowManagerWindows& windows); @@ -40,14 +33,7 @@ public: void CompletePartyInfo(AsyncDiagnostic diagnostic, std::string response, PartyInfoContext& context); void CompleteRegistration(AsyncDiagnostic diagnostic, std::string response, RegisterPartyContext& context); void CompleteStopRecruiting(AsyncDiagnostic diagnostic, std::string response, StopRecruitingContext& context); - std::string ServiceUrl( - int operation, - LuaScript& settings, - LuaScript& tables, - const char* host, - const char* port, - const char* overrideKey - ) const; + std::string ServiceUrl(int operation, LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey) const; /* 0004 */ bool enabled; /* 0005 */ bool registered; diff --git a/Source/Contents/AgencyRequestContext.h b/Source/Contents/Party/AgencyRequestContext.h similarity index 63% rename from Source/Contents/AgencyRequestContext.h rename to Source/Contents/Party/AgencyRequestContext.h index b44d1af..439ed7a 100644 --- a/Source/Contents/AgencyRequestContext.h +++ b/Source/Contents/Party/AgencyRequestContext.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_AGENCYREQUESTCONTEXT_H -#define RAGNAROK_SOURCE_CONTENTS_AGENCYREQUESTCONTEXT_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_AGENCYREQUESTCONTEXT_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_AGENCYREQUESTCONTEXT_H #include #include @@ -8,8 +8,6 @@ class CAsyncWorkMgr; class LuaScript; class WindowManagerWindows; -// Original client identity, world, 16-byte token and service configuration. -// Borrows existing owners; does not duplicate registration or pending state. struct AgencyRequestContext { CAsyncWorkMgr& work; LuaScript& settings; diff --git a/Source/Contents/AgencyRequests.cpp b/Source/Contents/Party/AgencyRequests.cpp similarity index 54% rename from Source/Contents/AgencyRequests.cpp rename to Source/Contents/Party/AgencyRequests.cpp index e95ca93..2242a18 100644 --- a/Source/Contents/AgencyRequests.cpp +++ b/Source/Contents/Party/AgencyRequests.cpp @@ -1,24 +1,19 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/AgencyRequestContext.h" -#include "Contents/AsyncWorkMgr.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/AgencyRequestContext.h" +#include "Contents/Async/AsyncWorkMgr.h" // OFFSET: 0x005CB3B0 // FUNCTION: fn_03657 void CAdventurerAgencyMgr::RequestChangeMaster( - std::uint32_t targetAccountId, - std::uint32_t targetCharacterId, - std::string targetName, - AgencyRequestContext& context + std::uint32_t targetAccountId, std::uint32_t targetCharacterId, std::string targetName, AgencyRequestContext& context ) { const std::uint32_t account = context.accountId; const std::uint32_t character = context.characterId; const std::string token(context.token16, 16); - const std::string url = - this->ServiceUrl(6, context.settings, context.tables, context.host, context.port, context.overrideKey); + const std::string url = this->ServiceUrl(6, context.settings, context.tables, context.host, context.port, context.overrideKey); const std::string world(context.world.c_str()); context.work.ChangePartyMaster( - account, character, std::string(context.characterName.c_str()), targetAccountId, targetCharacterId, targetName, - world, url, token, context.windows + account, character, std::string(context.characterName.c_str()), targetAccountId, targetCharacterId, targetName, world, url, token, context.windows ); ++this->pending; } @@ -29,8 +24,7 @@ void CAdventurerAgencyMgr::RequestMyParty(AgencyRequestContext& context) { const std::uint32_t account = context.accountId; const std::uint32_t character = context.characterId; const std::string token(context.token16, 16); - const std::string url = - this->ServiceUrl(5, context.settings, context.tables, context.host, context.port, context.overrideKey); + const std::string url = this->ServiceUrl(5, context.settings, context.tables, context.host, context.port, context.overrideKey); context.work.LoadMyParty(account, character, std::string(context.world.c_str()), url, token, context.windows); ++this->pending; } @@ -42,48 +36,31 @@ void CAdventurerAgencyMgr::RequestList(int page, AgencyRequestContext& context) const std::uint32_t character = context.characterId; CAdvenPartyInfo filter; const std::string token(context.token16, 16); - const std::string url = - this->ServiceUrl(1, context.settings, context.tables, context.host, context.port, context.overrideKey); - context.work.LoadPartyList( - account, character, std::string(context.world.c_str()), url, token, 0, filter, page, context.windows - ); + const std::string url = this->ServiceUrl(1, context.settings, context.tables, context.host, context.port, context.overrideKey); + context.work.LoadPartyList(account, character, std::string(context.world.c_str()), url, token, 0, filter, page, context.windows); ++this->pending; } // OFFSET: 0x005CC290 // FUNCTION: fn_03663 -void CAdventurerAgencyMgr::RequestInfo( - std::uint32_t queryAccountId, - AgencyRequestContext& context, - PartyInfoContext& completion -) { +void CAdventurerAgencyMgr::RequestInfo(std::uint32_t queryAccountId, AgencyRequestContext& context, PartyInfoContext& completion) { const std::uint32_t account = context.accountId; const std::uint32_t character = context.characterId; const std::string token(context.token16, 16); - const std::string url = - this->ServiceUrl(7, context.settings, context.tables, context.host, context.port, context.overrideKey); - context.work.LoadPartyInfo( - account, character, std::string(context.world.c_str()), url, token, queryAccountId, completion - ); + const std::string url = this->ServiceUrl(7, context.settings, context.tables, context.host, context.port, context.overrideKey); + context.work.LoadPartyInfo(account, character, std::string(context.world.c_str()), url, token, queryAccountId, completion); ++this->pending; } // OFFSET: 0x005CCC00 // FUNCTION: fn_03665 -void CAdventurerAgencyMgr::RequestRegistration( - const CAdvenPartyInfo& info, - AgencyRequestContext& context, - RegisterPartyContext& completion -) { +void CAdventurerAgencyMgr::RequestRegistration(const CAdvenPartyInfo& info, AgencyRequestContext& context, RegisterPartyContext& completion) { const std::uint32_t account = context.accountId; const std::uint32_t character = context.characterId; const CAdvenPartyInfo registration(info); const std::string token(context.token16, 16); - const std::string url = - this->ServiceUrl(0, context.settings, context.tables, context.host, context.port, context.overrideKey); - context.work.RegisterParty( - account, character, std::string(context.world.c_str()), url, token, registration, completion - ); + const std::string url = this->ServiceUrl(0, context.settings, context.tables, context.host, context.port, context.overrideKey); + context.work.RegisterParty(account, character, std::string(context.world.c_str()), url, token, registration, completion); ++this->pending; } @@ -94,26 +71,18 @@ void CAdventurerAgencyMgr::RequestSearch(const CAdvenPartyInfo& filter, int page const std::uint32_t character = context.characterId; const CAdvenPartyInfo search(filter); const std::string token(context.token16, 16); - const std::string url = - this->ServiceUrl(3, context.settings, context.tables, context.host, context.port, context.overrideKey); - context.work.LoadPartyList( - account, character, std::string(context.world.c_str()), url, token, 1, search, page, context.windows - ); + const std::string url = this->ServiceUrl(3, context.settings, context.tables, context.host, context.port, context.overrideKey); + context.work.LoadPartyList(account, character, std::string(context.world.c_str()), url, token, 1, search, page, context.windows); ++this->pending; } // OFFSET: 0x005CD340 // FUNCTION: fn_03669 -void CAdventurerAgencyMgr::RequestStop( - std::uint32_t masterAccountId, - AgencyRequestContext& context, - StopRecruitingContext& completion -) { +void CAdventurerAgencyMgr::RequestStop(std::uint32_t masterAccountId, AgencyRequestContext& context, StopRecruitingContext& completion) { this->unknown_0008 = masterAccountId; const std::uint32_t account = context.accountId; const std::string token(context.token16, 16); - const std::string url = - this->ServiceUrl(4, context.settings, context.tables, context.host, context.port, context.overrideKey); + const std::string url = this->ServiceUrl(4, context.settings, context.tables, context.host, context.port, context.overrideKey); context.work.StopRecruiting(account, std::string(context.world.c_str()), url, token, masterAccountId, completion); ++this->pending; } @@ -128,8 +97,7 @@ void CAdventurerAgencyMgr::RequestStop(AgencyRequestContext& context, StopRecrui this->unknown_0008 = context.accountId; const std::uint32_t account = context.accountId; const std::string token(context.token16, 16); - const std::string url = - this->ServiceUrl(4, context.settings, context.tables, context.host, context.port, context.overrideKey); + const std::string url = this->ServiceUrl(4, context.settings, context.tables, context.host, context.port, context.overrideKey); context.work.StopRecruiting(account, std::string(context.world.c_str()), url, token, account, completion); ++this->pending; } diff --git a/Source/Contents/ChangePartyMasterAsyncWork.cpp b/Source/Contents/Party/ChangePartyMasterAsyncWork.cpp similarity index 68% rename from Source/Contents/ChangePartyMasterAsyncWork.cpp rename to Source/Contents/Party/ChangePartyMasterAsyncWork.cpp index a8c909b..43daae4 100644 --- a/Source/Contents/ChangePartyMasterAsyncWork.cpp +++ b/Source/Contents/Party/ChangePartyMasterAsyncWork.cpp @@ -1,15 +1,14 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/ChangePartyMasterAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/ChangePartyMasterAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" -#include #include -#include +#include +#include namespace { - constexpr char sourceFile[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CChangePartyMasterAsyncWork.cpp"; + constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CChangePartyMasterAsyncWork.cpp"; AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; @@ -20,8 +19,7 @@ namespace { // OFFSET: 0x005CD7B0 // FUNCTION: fn_03677 CChangePartyMasterAsyncWork::CChangePartyMasterAsyncWork() - : NAsyncWork("Change_PartyMaster"), m_accountId(0), m_characterId(0), - m_diagnostic(Diagnostic(false, "unknwon", 27)), m_windows(nullptr) { + : NAsyncWork("Change_PartyMaster"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", 27)), m_windows(nullptr) { } // OFFSET: 0x005CDC30 @@ -36,16 +34,8 @@ void CChangePartyMasterAsyncWork::Reset() { // OFFSET: 0x005CDDA0 // FUNCTION: fn_03680 void CChangePartyMasterAsyncWork::Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string characterName, - std::uint32_t targetAccountId, - std::uint32_t targetCharacterId, - std::string targetName, - std::string worldName, - std::string url, - std::string token, - WindowManagerWindows& windows + std::uint32_t accountId, std::uint32_t characterId, std::string characterName, std::uint32_t targetAccountId, std::uint32_t targetCharacterId, + std::string targetName, std::string worldName, std::string url, std::string token, WindowManagerWindows& windows ) { this->m_group = timeGetTime(); this->m_accountId = accountId; @@ -70,14 +60,10 @@ bool CChangePartyMasterAsyncWork::Execute() { char character[64] = {}; char targetAccount[64] = {}; char targetCharacter[64] = {}; - _snprintf_s(account, sizeof(account), _TRUNCATE, "%d", std::bit_cast(this->m_accountId)); - _snprintf_s(character, sizeof(character), _TRUNCATE, "%d", std::bit_cast(this->m_characterId)); - _snprintf_s( - targetAccount, sizeof(targetAccount), _TRUNCATE, "%d", std::bit_cast(this->m_targetAccountId) - ); - _snprintf_s( - targetCharacter, sizeof(targetCharacter), _TRUNCATE, "%d", std::bit_cast(this->m_targetCharacterId) - ); + _snprintf_s(account, sizeof(account), _TRUNCATE, "%d", static_cast(this->m_accountId)); + _snprintf_s(character, sizeof(character), _TRUNCATE, "%d", static_cast(this->m_characterId)); + _snprintf_s(targetAccount, sizeof(targetAccount), _TRUNCATE, "%d", static_cast(this->m_targetAccountId)); + _snprintf_s(targetCharacter, sizeof(targetCharacter), _TRUNCATE, "%d", static_cast(this->m_targetCharacterId)); std::string world = ToUtf8(this->m_worldName); std::string name = ToUtf8(this->m_characterName); std::string targetName = ToUtf8(this->m_targetName); diff --git a/Source/Contents/ChangePartyMasterAsyncWork.h b/Source/Contents/Party/ChangePartyMasterAsyncWork.h similarity index 57% rename from Source/Contents/ChangePartyMasterAsyncWork.h rename to Source/Contents/Party/ChangePartyMasterAsyncWork.h index 57a8c78..647aba1 100644 --- a/Source/Contents/ChangePartyMasterAsyncWork.h +++ b/Source/Contents/Party/ChangePartyMasterAsyncWork.h @@ -1,13 +1,11 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CHANGEPARTYMASTERASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_CHANGEPARTYMASTERASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_CHANGEPARTYMASTERASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_CHANGEPARTYMASTERASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class WindowManagerWindows; -// RTTI CChangePartyMasterAsyncWork, original x86 size 256. Window lookup is -// a source-only dependency; completion uses the original agency singleton. class CChangePartyMasterAsyncWork : public NAsyncWork { public: CChangePartyMasterAsyncWork(); @@ -16,16 +14,8 @@ public: bool Execute() override; void Complete() override; void Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string characterName, - std::uint32_t targetAccountId, - std::uint32_t targetCharacterId, - std::string targetName, - std::string worldName, - std::string url, - std::string token, - WindowManagerWindows& windows + std::uint32_t accountId, std::uint32_t characterId, std::string characterName, std::uint32_t targetAccountId, std::uint32_t targetCharacterId, + std::string targetName, std::string worldName, std::string url, std::string token, WindowManagerWindows& windows ); protected: diff --git a/Source/Contents/ChangePartyMasterCompletion.cpp b/Source/Contents/Party/ChangePartyMasterCompletion.cpp similarity index 62% rename from Source/Contents/ChangePartyMasterCompletion.cpp rename to Source/Contents/Party/ChangePartyMasterCompletion.cpp index 137ed48..b5d5534 100644 --- a/Source/Contents/ChangePartyMasterCompletion.cpp +++ b/Source/Contents/Party/ChangePartyMasterCompletion.cpp @@ -1,18 +1,14 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" -#include "Utility/AsyncDiagnostic.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" +#include "Utility/Async/AsyncDiagnostic.h" #include #include // OFFSET: 0x005CB520 // FUNCTION: fn_03658 -void CAdventurerAgencyMgr::CompleteChangeMaster( - AsyncDiagnostic diagnostic, - std::string response, - WindowManagerWindows& windows -) { +void CAdventurerAgencyMgr::CompleteChangeMaster(AsyncDiagnostic diagnostic, std::string response, WindowManagerWindows& windows) { --this->pending; if (!diagnostic.success) { diff --git a/Source/Contents/LoadMyPartyAsyncWork.cpp b/Source/Contents/Party/LoadMyPartyAsyncWork.cpp similarity index 80% rename from Source/Contents/LoadMyPartyAsyncWork.cpp rename to Source/Contents/Party/LoadMyPartyAsyncWork.cpp index acd1a69..dbf89bc 100644 --- a/Source/Contents/LoadMyPartyAsyncWork.cpp +++ b/Source/Contents/Party/LoadMyPartyAsyncWork.cpp @@ -1,14 +1,14 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/LoadMyPartyAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/LoadMyPartyAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { - constexpr char sourceFile[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CLoadMyPartyAsyncWork.cpp"; + constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CLoadMyPartyAsyncWork.cpp"; AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; @@ -19,8 +19,7 @@ namespace { // OFFSET: 0x005CF1B0 // FUNCTION: fn_03685 CLoadMyPartyAsyncWork::CLoadMyPartyAsyncWork() - : NAsyncWork("MyParty_Load"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", 28)), - m_windows(nullptr) { + : NAsyncWork("MyParty_Load"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", 28)), m_windows(nullptr) { } // OFFSET: 0x005CF580 @@ -35,12 +34,7 @@ void CLoadMyPartyAsyncWork::Reset() { // OFFSET: 0x005CF670 // FUNCTION: fn_03687 void CLoadMyPartyAsyncWork::Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - WindowManagerWindows& windows + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, WindowManagerWindows& windows ) { this->m_group = timeGetTime(); this->m_accountId = accountId; diff --git a/Source/Contents/LoadMyPartyAsyncWork.h b/Source/Contents/Party/LoadMyPartyAsyncWork.h similarity index 56% rename from Source/Contents/LoadMyPartyAsyncWork.h rename to Source/Contents/Party/LoadMyPartyAsyncWork.h index 75c128e..79b738a 100644 --- a/Source/Contents/LoadMyPartyAsyncWork.h +++ b/Source/Contents/Party/LoadMyPartyAsyncWork.h @@ -1,13 +1,11 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_LOADMYPARTYASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_LOADMYPARTYASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_LOADMYPARTYASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_LOADMYPARTYASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class WindowManagerWindows; -// RTTI CLoadMyPartyAsyncWork, original x86 size 200. -// The borrowed window-manager binding is source-only, not original work state. class CLoadMyPartyAsyncWork : public NAsyncWork { public: CLoadMyPartyAsyncWork(); @@ -15,14 +13,7 @@ public: void Reset() override; bool Execute() override; void Complete() override; - void Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - WindowManagerWindows& windows - ); + void Bind(std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, WindowManagerWindows& windows); protected: /* 0028 */ std::uint32_t m_accountId; diff --git a/Source/Contents/LoadPartyInfoAsyncWork.cpp b/Source/Contents/Party/LoadPartyInfoAsyncWork.cpp similarity index 81% rename from Source/Contents/LoadPartyInfoAsyncWork.cpp rename to Source/Contents/Party/LoadPartyInfoAsyncWork.cpp index d994bbf..0e9eafe 100644 --- a/Source/Contents/LoadPartyInfoAsyncWork.cpp +++ b/Source/Contents/Party/LoadPartyInfoAsyncWork.cpp @@ -1,14 +1,14 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/LoadPartyInfoAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/LoadPartyInfoAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { - constexpr char sourceFile[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CLoadPartyInfoAsyncWork.cpp"; + constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CLoadPartyInfoAsyncWork.cpp"; AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; @@ -19,8 +19,7 @@ namespace { // OFFSET: 0x005D0470 // FUNCTION: fn_03692 CLoadPartyInfoAsyncWork::CLoadPartyInfoAsyncWork() - : NAsyncWork("PartyInfo_Load"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", 25)), - m_context(nullptr) { + : NAsyncWork("PartyInfo_Load"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", 25)), m_context(nullptr) { } // OFFSET: 0x005D0840 @@ -35,12 +34,7 @@ void CLoadPartyInfoAsyncWork::Reset() { // OFFSET: 0x005D0930 // FUNCTION: fn_03694 void CLoadPartyInfoAsyncWork::Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - std::uint32_t queryAccountId, + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, std::uint32_t queryAccountId, PartyInfoContext& context ) { this->m_group = timeGetTime(); diff --git a/Source/Contents/LoadPartyInfoAsyncWork.h b/Source/Contents/Party/LoadPartyInfoAsyncWork.h similarity index 73% rename from Source/Contents/LoadPartyInfoAsyncWork.h rename to Source/Contents/Party/LoadPartyInfoAsyncWork.h index c4aba8f..f023fee 100644 --- a/Source/Contents/LoadPartyInfoAsyncWork.h +++ b/Source/Contents/Party/LoadPartyInfoAsyncWork.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_LOADPARTYINFOASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_LOADPARTYINFOASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_LOADPARTYINFOASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_LOADPARTYINFOASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class WindowManagerWindows; class ResourceMessages; @@ -21,7 +21,6 @@ struct PartyInfoContext { const unsigned short& language; }; -// RTTI CLoadPartyInfoAsyncWork, original x86 allocation 208. class alignas(8) CLoadPartyInfoAsyncWork : public NAsyncWork { public: CLoadPartyInfoAsyncWork(); @@ -30,12 +29,7 @@ public: bool Execute() override; void Complete() override; void Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - std::uint32_t queryAccountId, + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, std::uint32_t queryAccountId, PartyInfoContext& context ); @@ -54,4 +48,5 @@ protected: #if defined(_WIN32) && !defined(_WIN64) static_assert(sizeof(CLoadPartyInfoAsyncWork) == 208); #endif + #endif diff --git a/Source/Contents/LoadPartyListAsyncWork.cpp b/Source/Contents/Party/LoadPartyListAsyncWork.cpp similarity index 84% rename from Source/Contents/LoadPartyListAsyncWork.cpp rename to Source/Contents/Party/LoadPartyListAsyncWork.cpp index ce0c7ac..29d55cd 100644 --- a/Source/Contents/LoadPartyListAsyncWork.cpp +++ b/Source/Contents/Party/LoadPartyListAsyncWork.cpp @@ -1,14 +1,14 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/LoadPartyListAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/LoadPartyListAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { - constexpr char sourceFile[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CLoadPartyLIstAsyncWork.cpp"; + constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CLoadPartyLIstAsyncWork.cpp"; AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; @@ -19,8 +19,7 @@ namespace { // OFFSET: 0x005D1640 // FUNCTION: fn_03698 CLoadPartyListAsyncWork::CLoadPartyListAsyncWork() - : NAsyncWork("PartyList_Load"), m_accountId(0), m_characterId(0), m_page(0), - m_diagnostic(Diagnostic(false, "unknwon", 25)), m_windows(nullptr) { + : NAsyncWork("PartyList_Load"), m_accountId(0), m_characterId(0), m_page(0), m_diagnostic(Diagnostic(false, "unknwon", 25)), m_windows(nullptr) { } // OFFSET: 0x005D1AB0 @@ -35,14 +34,7 @@ void CLoadPartyListAsyncWork::Reset() { // OFFSET: 0x005D1BD0 // FUNCTION: fn_03700 void CLoadPartyListAsyncWork::Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - CAdvenPartyInfo filter, - int search, - int page, + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, CAdvenPartyInfo filter, int search, int page, WindowManagerWindows& windows ) { this->m_group = timeGetTime(); @@ -121,7 +113,6 @@ bool CLoadPartyListAsyncWork::Execute() { this->m_diagnostic.MoveFrom(diagnostic); } - // Transport failure preserves the diagnostic written by Bind. return false; } diff --git a/Source/Contents/LoadPartyListAsyncWork.h b/Source/Contents/Party/LoadPartyListAsyncWork.h similarity index 58% rename from Source/Contents/LoadPartyListAsyncWork.h rename to Source/Contents/Party/LoadPartyListAsyncWork.h index d64e9d0..6f5e912 100644 --- a/Source/Contents/LoadPartyListAsyncWork.h +++ b/Source/Contents/Party/LoadPartyListAsyncWork.h @@ -1,14 +1,12 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_LOADPARTYLISTASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_LOADPARTYLISTASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_LOADPARTYLISTASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_LOADPARTYLISTASYNCWORK_H -#include "Contents/AdvenPartyInfo.h" -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Contents/Party/AdvenPartyInfo.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class WindowManagerWindows; -// RTTI CLoadPartyListAsyncWork, original x86 size 284. Window-manager binding -// is source-only; the completion target is the original agency singleton. class CLoadPartyListAsyncWork : public NAsyncWork { public: CLoadPartyListAsyncWork(); @@ -17,14 +15,7 @@ public: bool Execute() override; void Complete() override; void Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - CAdvenPartyInfo filter, - int search, - int page, + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, CAdvenPartyInfo filter, int search, int page, WindowManagerWindows& windows ); diff --git a/Source/Contents/MyPartyCompletion.cpp b/Source/Contents/Party/MyPartyCompletion.cpp similarity index 79% rename from Source/Contents/MyPartyCompletion.cpp rename to Source/Contents/Party/MyPartyCompletion.cpp index 1877a39..cb229ef 100644 --- a/Source/Contents/MyPartyCompletion.cpp +++ b/Source/Contents/Party/MyPartyCompletion.cpp @@ -1,18 +1,14 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "UI/UIAdvenPartyBoardWnd.h" -#include "UI/WindowManagerWindows.h" -#include "Utility/AsyncDiagnostic.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "UI/Party/UIAdvenPartyBoardWnd.h" +#include "UI/Window/WindowManagerWindows.h" +#include "Utility/Async/AsyncDiagnostic.h" #include #include // OFFSET: 0x005CB810 // FUNCTION: fn_03660 -void CAdventurerAgencyMgr::CompleteMyParty( - AsyncDiagnostic diagnostic, - std::string response, - WindowManagerWindows& windows -) { +void CAdventurerAgencyMgr::CompleteMyParty(AsyncDiagnostic diagnostic, std::string response, WindowManagerWindows& windows) { --this->pending; if (!diagnostic.success) { @@ -61,6 +57,5 @@ void CAdventurerAgencyMgr::CompleteMyParty( board->SetOwnParty(info); } - // The board update precedes this store in the original, including reentry. this->registered = true; } diff --git a/Source/Contents/PartyInfoCompletion.cpp b/Source/Contents/Party/PartyInfoCompletion.cpp similarity index 72% rename from Source/Contents/PartyInfoCompletion.cpp rename to Source/Contents/Party/PartyInfoCompletion.cpp index e93fa68..3249b43 100644 --- a/Source/Contents/PartyInfoCompletion.cpp +++ b/Source/Contents/Party/PartyInfoCompletion.cpp @@ -1,23 +1,19 @@ -#include "Client/ModeEvents.h" -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/LoadPartyInfoAsyncWork.h" +#include "Client/Mode/ModeEvents.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/LoadPartyInfoAsyncWork.h" #include "Contents/MessageTable.h" #include "Resource/ResourceFailures.h" -#include "UI/UIAdvenPartyBoardWnd.h" -#include "UI/UIApplyForPartyWnd.h" -#include "UI/WindowManagerWindows.h" -#include "UI/WindowOrdering.h" +#include "UI/Party/UIAdvenPartyBoardWnd.h" +#include "UI/Party/UIApplyForPartyWnd.h" +#include "UI/Window/WindowManagerWindows.h" +#include "UI/Window/WindowOrdering.h" #include #include // OFFSET: 0x005CC3A0 // FUNCTION: fn_03664 -void CAdventurerAgencyMgr::CompletePartyInfo( - AsyncDiagnostic diagnostic, - std::string response, - PartyInfoContext& context -) { +void CAdventurerAgencyMgr::CompletePartyInfo(AsyncDiagnostic diagnostic, std::string response, PartyInfoContext& context) { --this->pending; if (!diagnostic.success) { @@ -36,9 +32,7 @@ void CAdventurerAgencyMgr::CompletePartyInfo( return; } - const auto notify = [&](int id) { - context.messages.Message(LookupMessage(id, context.languagePrefix, context.service, context.language), 0xFF); - }; + const auto notify = [&](int id) { context.messages.Message(LookupMessage(id, context.languagePrefix, context.service, context.language), 0xFF); }; auto entry = root["data"].begin(); if (entry == root["data"].end()) { @@ -84,9 +78,7 @@ void CAdventurerAgencyMgr::CompletePartyInfo( } else if (context.partyCount > 0) { notify(79); } else { - context.mode->SendModeMessage( - 265, reinterpret_cast(&info.accountId), reinterpret_cast(&info.characterId), 0, 0 - ); + context.mode->SendModeMessage(265, reinterpret_cast(&info.accountId), reinterpret_cast(&info.characterId), 0, 0); context.windows.CloseWindow(345); } } diff --git a/Source/Contents/PartyInvitation.cpp b/Source/Contents/Party/PartyInvitation.cpp similarity index 86% rename from Source/Contents/PartyInvitation.cpp rename to Source/Contents/Party/PartyInvitation.cpp index 1143b0e..e2a9b3c 100644 --- a/Source/Contents/PartyInvitation.cpp +++ b/Source/Contents/Party/PartyInvitation.cpp @@ -1,7 +1,7 @@ #include "Contents/ForbiddenWords.h" -#include "Contents/PartyInvitation.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "Contents/Party/PartyInvitation.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" #include #include diff --git a/Source/Contents/PartyInvitation.h b/Source/Contents/Party/PartyInvitation.h similarity index 71% rename from Source/Contents/PartyInvitation.h rename to Source/Contents/Party/PartyInvitation.h index 8e2365e..98ff79d 100644 --- a/Source/Contents/PartyInvitation.h +++ b/Source/Contents/Party/PartyInvitation.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_PARTYINVITATION_H -#define RAGNAROK_SOURCE_CONTENTS_PARTYINVITATION_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_PARTYINVITATION_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_PARTYINVITATION_H #include diff --git a/Source/Contents/PartyJoinResult.cpp b/Source/Contents/Party/PartyJoinResult.cpp similarity index 81% rename from Source/Contents/PartyJoinResult.cpp rename to Source/Contents/Party/PartyJoinResult.cpp index 657c326..71a37ba 100644 --- a/Source/Contents/PartyJoinResult.cpp +++ b/Source/Contents/Party/PartyJoinResult.cpp @@ -1,9 +1,9 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/AgencyRequestContext.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/AgencyRequestContext.h" #include "Contents/MessageTable.h" -#include "Contents/PartyJoinResult.h" -#include "Contents/StopRecruitingAsyncWork.h" -#include "UI/WindowNotifications.h" +#include "Contents/Party/PartyJoinResult.h" +#include "Contents/Party/StopRecruitingAsyncWork.h" +#include "UI/Window/WindowNotifications.h" #include #include @@ -15,9 +15,7 @@ void ReceivePartyJoinResult(const void* packet, PartyJoinResultContext& context) context.notifications.Notify(3, nullptr, 0); std::uint32_t status; std::memcpy(&status, bytes + 54, sizeof(status)); - const auto message = [&](int id) { - return LookupMessage(id, context.stop.languagePrefix, context.stop.service, context.stop.language); - }; + const auto message = [&](int id) { return LookupMessage(id, context.stop.languagePrefix, context.stop.service, context.stop.language); }; const auto notify = [&](int id) { context.notifications.Notify(1, message(id), 0xFF); }; const auto format = [&](int id, unsigned offset, unsigned color) { char text[500] = {}; diff --git a/Source/Contents/PartyJoinResult.h b/Source/Contents/Party/PartyJoinResult.h similarity index 75% rename from Source/Contents/PartyJoinResult.h rename to Source/Contents/Party/PartyJoinResult.h index 4d637a8..7a7d0ea 100644 --- a/Source/Contents/PartyJoinResult.h +++ b/Source/Contents/Party/PartyJoinResult.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_PARTYJOINRESULT_H -#define RAGNAROK_SOURCE_CONTENTS_PARTYJOINRESULT_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_PARTYJOINRESULT_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_PARTYJOINRESULT_H struct AgencyRequestContext; struct StopRecruitingContext; diff --git a/Source/Contents/PartyListCompletion.cpp b/Source/Contents/Party/PartyListCompletion.cpp similarity index 69% rename from Source/Contents/PartyListCompletion.cpp rename to Source/Contents/Party/PartyListCompletion.cpp index 00d98b1..eda6a9a 100644 --- a/Source/Contents/PartyListCompletion.cpp +++ b/Source/Contents/Party/PartyListCompletion.cpp @@ -1,18 +1,14 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "UI/UIAdvenPartyBoardWnd.h" -#include "UI/WindowManagerWindows.h" -#include "Utility/AsyncDiagnostic.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "UI/Party/UIAdvenPartyBoardWnd.h" +#include "UI/Window/WindowManagerWindows.h" +#include "Utility/Async/AsyncDiagnostic.h" #include #include // OFFSET: 0x005CC000 // FUNCTION: fn_03662 -void CAdventurerAgencyMgr::CompleteList( - AsyncDiagnostic diagnostic, - std::string response, - WindowManagerWindows& windows -) { +void CAdventurerAgencyMgr::CompleteList(AsyncDiagnostic diagnostic, std::string response, WindowManagerWindows& windows) { --this->pending; if (!diagnostic.success) { diff --git a/Source/Contents/PartyRegistrationCompletion.cpp b/Source/Contents/Party/PartyRegistrationCompletion.cpp similarity index 74% rename from Source/Contents/PartyRegistrationCompletion.cpp rename to Source/Contents/Party/PartyRegistrationCompletion.cpp index b75a787..0f4f6dd 100644 --- a/Source/Contents/PartyRegistrationCompletion.cpp +++ b/Source/Contents/Party/PartyRegistrationCompletion.cpp @@ -1,20 +1,16 @@ -#include "Contents/AdventurerAgencyMgr.h" +#include "Contents/Party/AdventurerAgencyMgr.h" #include "Contents/MessageTable.h" -#include "Contents/RegisterPartyAsyncWork.h" +#include "Contents/Party/RegisterPartyAsyncWork.h" #include "Resource/ResourceFailures.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" #include #include // OFFSET: 0x005CCD20 // FUNCTION: fn_03666 -void CAdventurerAgencyMgr::CompleteRegistration( - AsyncDiagnostic diagnostic, - std::string response, - RegisterPartyContext& context -) { +void CAdventurerAgencyMgr::CompleteRegistration(AsyncDiagnostic diagnostic, std::string response, RegisterPartyContext& context) { --this->pending; if (!diagnostic.success) { diff --git a/Source/Contents/RegisterPartyAsyncWork.cpp b/Source/Contents/Party/RegisterPartyAsyncWork.cpp similarity index 85% rename from Source/Contents/RegisterPartyAsyncWork.cpp rename to Source/Contents/Party/RegisterPartyAsyncWork.cpp index 3209fb8..0bfb606 100644 --- a/Source/Contents/RegisterPartyAsyncWork.cpp +++ b/Source/Contents/Party/RegisterPartyAsyncWork.cpp @@ -1,14 +1,14 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/RegisterPartyAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/RegisterPartyAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { - constexpr char sourceFile[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CRegisterPartyAsyncWork.cpp"; + constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CRegisterPartyAsyncWork.cpp"; AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; @@ -19,8 +19,7 @@ namespace { // OFFSET: 0x005D3600 // FUNCTION: fn_03704 CRegisterPartyAsyncWork::CRegisterPartyAsyncWork() - : NAsyncWork("Register_Party"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", 26)), - m_context(nullptr) { + : NAsyncWork("Register_Party"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", 26)), m_context(nullptr) { } // OFFSET: 0x005D3A60 @@ -35,12 +34,7 @@ void CRegisterPartyAsyncWork::Reset() { // OFFSET: 0x005D3B80 // FUNCTION: fn_03706 void CRegisterPartyAsyncWork::Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - const CAdvenPartyInfo& info, + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, const CAdvenPartyInfo& info, RegisterPartyContext& context ) { this->m_group = timeGetTime(); diff --git a/Source/Contents/RegisterPartyAsyncWork.h b/Source/Contents/Party/RegisterPartyAsyncWork.h similarity index 62% rename from Source/Contents/RegisterPartyAsyncWork.h rename to Source/Contents/Party/RegisterPartyAsyncWork.h index c2f6c86..5c34a57 100644 --- a/Source/Contents/RegisterPartyAsyncWork.h +++ b/Source/Contents/Party/RegisterPartyAsyncWork.h @@ -1,14 +1,13 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_REGISTERPARTYASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_REGISTERPARTYASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_REGISTERPARTYASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_REGISTERPARTYASYNCWORK_H -#include "Contents/AdvenPartyInfo.h" -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Contents/Party/AdvenPartyInfo.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class WindowManagerWindows; class ResourceMessages; -// Borrowed client name/locale and manager operations used by the original work. struct RegisterPartyContext { WindowManagerWindows& windows; ResourceMessages& messages; @@ -18,8 +17,6 @@ struct RegisterPartyContext { const unsigned short& language; }; -// RTTI CRegisterPartyAsyncWork, original allocation 280. -// The source context pointer occupies the original alignment tail on x86. class alignas(8) CRegisterPartyAsyncWork : public NAsyncWork { public: CRegisterPartyAsyncWork(); @@ -28,12 +25,7 @@ public: bool Execute() override; void Complete() override; void Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string world, - std::string url, - std::string token, - const CAdvenPartyInfo& info, + std::uint32_t accountId, std::uint32_t characterId, std::string world, std::string url, std::string token, const CAdvenPartyInfo& info, RegisterPartyContext& context ); diff --git a/Source/Contents/StopRecruitingAsyncWork.cpp b/Source/Contents/Party/StopRecruitingAsyncWork.cpp similarity index 80% rename from Source/Contents/StopRecruitingAsyncWork.cpp rename to Source/Contents/Party/StopRecruitingAsyncWork.cpp index 256bb19..7dd5983 100644 --- a/Source/Contents/StopRecruitingAsyncWork.cpp +++ b/Source/Contents/Party/StopRecruitingAsyncWork.cpp @@ -1,14 +1,14 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/StopRecruitingAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/StopRecruitingAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { - constexpr char sourceFile[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CStopRecruitingAsyncWork.cpp"; + constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AdventurerAgency\\CStopRecruitingAsyncWork.cpp"; AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; @@ -19,8 +19,7 @@ namespace { // OFFSET: 0x005D5D70 // FUNCTION: fn_03711 CStopRecruitingAsyncWork::CStopRecruitingAsyncWork() - : NAsyncWork("Stop_Recruiting"), m_accountId(0), m_masterAccountId(0), - m_diagnostic(Diagnostic(false, "unknwon", 28)), m_context(nullptr) { + : NAsyncWork("Stop_Recruiting"), m_accountId(0), m_masterAccountId(0), m_diagnostic(Diagnostic(false, "unknwon", 28)), m_context(nullptr) { } // OFFSET: 0x005D6140 @@ -35,12 +34,7 @@ void CStopRecruitingAsyncWork::Reset() { // OFFSET: 0x005D6230 // FUNCTION: fn_03713 void CStopRecruitingAsyncWork::Bind( - std::uint32_t accountId, - std::string world, - std::string url, - std::string token, - std::uint32_t masterAccountId, - StopRecruitingContext& context + std::uint32_t accountId, std::string world, std::string url, std::string token, std::uint32_t masterAccountId, StopRecruitingContext& context ) { this->m_group = timeGetTime(); this->m_accountId = accountId; diff --git a/Source/Contents/StopRecruitingAsyncWork.h b/Source/Contents/Party/StopRecruitingAsyncWork.h similarity index 62% rename from Source/Contents/StopRecruitingAsyncWork.h rename to Source/Contents/Party/StopRecruitingAsyncWork.h index 8216996..496fcc2 100644 --- a/Source/Contents/StopRecruitingAsyncWork.h +++ b/Source/Contents/Party/StopRecruitingAsyncWork.h @@ -1,14 +1,12 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_STOPRECRUITINGASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_STOPRECRUITINGASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_STOPRECRUITINGASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_STOPRECRUITINGASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class WindowManagerWindows; class ResourceMessages; -// Borrowed client identity/locale and manager message routing used by -// This view does not own agency state or submit work. struct StopRecruitingContext { WindowManagerWindows& windows; ResourceMessages& messages; @@ -18,7 +16,6 @@ struct StopRecruitingContext { const unsigned short& language; }; -// RTTI CStopRecruitingAsyncWork, original x86 size 200. class CStopRecruitingAsyncWork : public NAsyncWork { public: CStopRecruitingAsyncWork(); @@ -26,14 +23,7 @@ public: void Reset() override; bool Execute() override; void Complete() override; - void Bind( - std::uint32_t accountId, - std::string world, - std::string url, - std::string token, - std::uint32_t masterAccountId, - StopRecruitingContext& context - ); + void Bind(std::uint32_t accountId, std::string world, std::string url, std::string token, std::uint32_t masterAccountId, StopRecruitingContext& context); protected: /* 0028 */ std::uint32_t m_accountId; diff --git a/Source/Contents/StopRecruitingCompletion.cpp b/Source/Contents/Party/StopRecruitingCompletion.cpp similarity index 75% rename from Source/Contents/StopRecruitingCompletion.cpp rename to Source/Contents/Party/StopRecruitingCompletion.cpp index b675eec..10324eb 100644 --- a/Source/Contents/StopRecruitingCompletion.cpp +++ b/Source/Contents/Party/StopRecruitingCompletion.cpp @@ -1,21 +1,17 @@ -#include "Contents/AdventurerAgencyMgr.h" +#include "Contents/Party/AdventurerAgencyMgr.h" #include "Contents/MessageTable.h" -#include "Contents/StopRecruitingAsyncWork.h" +#include "Contents/Party/StopRecruitingAsyncWork.h" #include "Resource/ResourceFailures.h" -#include "UI/UIAdvenPartyBoardWnd.h" -#include "UI/UIBasicButton.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Party/UIAdvenPartyBoardWnd.h" +#include "UI/Buttons/UIBasicButton.h" +#include "UI/Window/WindowManagerWindows.h" #include #include // OFFSET: 0x005CD0A0 // FUNCTION: fn_03668 -void CAdventurerAgencyMgr::CompleteStopRecruiting( - AsyncDiagnostic diagnostic, - std::string response, - StopRecruitingContext& context -) { +void CAdventurerAgencyMgr::CompleteStopRecruiting(AsyncDiagnostic diagnostic, std::string response, StopRecruitingContext& context) { --this->pending; const auto notify = [&](int id, unsigned color) { context.messages.Message(LookupMessage(id, context.languagePrefix, context.service, context.language), color); diff --git a/Source/Contents/PartyEffect.h b/Source/Contents/PartyEffect.h deleted file mode 100644 index d4163d4..0000000 --- a/Source/Contents/PartyEffect.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_PARTYEFFECT_H -#define RAGNAROK_SOURCE_CONTENTS_PARTYEFFECT_H - -#include - -struct RagEffectState; -struct RenderObjectState; -struct EffectParticle; -struct JobNames; -struct TerrainHeight; -class ResourceMgr; -class TextureCache; -class CRenderObject; - -// Id-160 path through the parent/tick gates, body and shared frame tail. -bool UpdatePartyEffect( - RagEffectState& effect, - RenderObjectState& render, - ResourceMgr& resources, - JobNames& names, - std::list& worldObjects, - TextureCache& textures, - const TerrainHeight& ground, - int updateTick -); - -#endif diff --git a/Source/Contents/PlayerNameDictionary.cpp b/Source/Contents/PlayerNameDictionary.cpp index 3ded937..e0b190f 100644 --- a/Source/Contents/PlayerNameDictionary.cpp +++ b/Source/Contents/PlayerNameDictionary.cpp @@ -1,15 +1,17 @@ #include "Contents/MessageTable.h" #include "Contents/PlayerNameDictionary.h" -#include "Network/Connection.h" +#include "Network/Connection/Connection.h" #include #include -#include +#include +#include // OFFSET: 0x0060AE30 // FUNCTION: fn_04259 CPlayerNameDictionary::CPlayerNameDictionary(PlayerNameContext& context) : m_enabled(true), m_context(&context) { } + // OFFSET: 0x0060A9D0 // OFFSET: 0x0060AAE0 CPlayerNameDictionary::~CPlayerNameDictionary() = default; @@ -23,9 +25,11 @@ std::string CPlayerNameDictionary::Lookup(std::uint32_t id) { if (entry != this->m_names.end()) { return entry->second.name; } + if (std::find(this->m_pending.begin(), this->m_pending.end(), id) == this->m_pending.end()) { this->m_pending.push_back(id); } + return LookupMessage(581, this->m_context->languagePrefix, this->m_context->service, this->m_context->language); } @@ -33,9 +37,7 @@ std::string CPlayerNameDictionary::Lookup(std::uint32_t id) { // FUNCTION: fn_04258 void CPlayerNameDictionary::Set(std::uint32_t id, std::string name) { this->m_names.insert_or_assign(id, Entry{std::move(name), timeGetTime()}); - const auto request = std::find_if(this->m_requests.begin(), this->m_requests.end(), [&](const Request& value) { - return value.id == id; - }); + const auto request = std::find_if(this->m_requests.begin(), this->m_requests.end(), [&](const Request& value) { return value.id == id; }); if (request != this->m_requests.end()) { this->m_requests.erase(request); } @@ -62,19 +64,21 @@ void CPlayerNameDictionary::Update() { if (timeGetTime() < this->m_requests.front().tick + 10000u) { break; } + this->m_requests.pop_front(); } + while (!this->m_pending.empty()) { const std::uint32_t id = this->m_pending.front(); const auto cached = this->m_names.find(id); const bool fresh = cached != this->m_names.end() && !(cached->second.tick + 600000u < timeGetTime()); - const auto outstanding = std::find_if( - this->m_requests.begin(), this->m_requests.end(), [&](const Request& request) { return request.id == id; } - ); + const auto outstanding = std::find_if(this->m_requests.begin(), this->m_requests.end(), [&](const Request& request) { return request.id == id; }); this->m_pending.pop_front(); + if (fresh || outstanding != this->m_requests.end()) { continue; } + if (id != 0) { unsigned char packet[6]; const std::uint16_t header = 873; @@ -83,6 +87,7 @@ void CPlayerNameDictionary::Update() { this->m_context->connection.Send(sizeof(packet), packet); this->m_requests.push_back({id, timeGetTime()}); } + return; } } diff --git a/Source/Contents/PlayerNameDictionary.h b/Source/Contents/PlayerNameDictionary.h index e42b41b..f0f51be 100644 --- a/Source/Contents/PlayerNameDictionary.h +++ b/Source/Contents/PlayerNameDictionary.h @@ -16,8 +16,6 @@ struct PlayerNameContext { const WORD& language; }; -// RTTI CPlayerNameDictionary. Original56-byte owned map and two deques; -// reconstructed source adds one explicit context pointer. class CPlayerNameDictionary { public: explicit CPlayerNameDictionary(PlayerNameContext& context); diff --git a/Source/Contents/RagEffectInitialization.h b/Source/Contents/RagEffectInitialization.h deleted file mode 100644 index 12a7664..0000000 --- a/Source/Contents/RagEffectInitialization.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_RAGEFFECTINITIALIZATION_H -#define RAGNAROK_SOURCE_CONTENTS_RAGEFFECTINITIALIZATION_H - -struct RagEffectState; -struct RenderObjectState; -struct EffectActor; -struct ServiceOptions; -class ResourceMgr; - -// Whole CRagEffect initialization entry, independent of its still-unrecovered -// update/render virtuals. Parent state borrows the actual render-base owner. -void InitializeRagEffect( - RagEffectState& effect, - RenderObjectState& render, - EffectActor* parent, - const RenderObjectState& parentState, - int id, - float x, - float y, - float z, - ServiceOptions& options, - ResourceMgr& resources -); - -// Resource selection inlined in the same entry. Returns the exact STR name -// and writes only the per-effect fields changed by the selected case. -void SelectRagEffectResource(RagEffectState& effect, ServiceOptions& options, char* name); - -#endif diff --git a/Source/Contents/RenderObject.h b/Source/Contents/RenderObject.h deleted file mode 100644 index 87a1ffe..0000000 --- a/Source/Contents/RenderObject.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_RENDEROBJECT_H -#define RAGNAROK_SOURCE_CONTENTS_RENDEROBJECT_H - -#include "Contents/GameObject.h" -#include "Contents/RenderObjectState.h" - -// Recovered CRenderObject lifecycle. Unrecovered virtual operations are not -// replaced here; explicit recovered operations remain on their real owners. -class CRenderObject : public CGameObject { -public: - CRenderObject(ResourceMgr& resources, JobNames& names); - ~CRenderObject() override; - bool Update() override; - void SendObjectMessage( - CGameObject* sender, - int message, - int a, - int b, - int c, - int d, - int e, - int f, - int g, - int h, - int i, - int j, - int k, - int l, - int m - ) override; - - // Vtable slot 5. The base keeps no state; derived actors use the projected - // bounds and forward the screen point to SetScreenPosition. - virtual void SetScreenBounds(const float* bounds, float x, float y); - - // Vtable slot 6. Stores the truncated projected screen point. - virtual void SetScreenPosition(float x, float y); - - RenderObjectState render; -}; - -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(CRenderObject) == 0x138); -#endif - -#endif diff --git a/Source/Contents/ShowRankingScheduler.cpp b/Source/Contents/ShowRankingScheduler.cpp index 3fdc7e4..4466b61 100644 --- a/Source/Contents/ShowRankingScheduler.cpp +++ b/Source/Contents/ShowRankingScheduler.cpp @@ -15,5 +15,6 @@ const void* CShowRankingScheduler::SetData(const void* data) { std::memset(this->rankingData, 0, sizeof(this->rankingData)); errno = EINVAL; _invalid_parameter_noinfo(); + return nullptr; } diff --git a/Source/Contents/SkillLevelConfig.h b/Source/Contents/SkillLevelConfig.h deleted file mode 100644 index b32778b..0000000 --- a/Source/Contents/SkillLevelConfig.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLLEVELCONFIG_H -#define RAGNAROK_SOURCE_CONTENTS_SKILLLEVELCONFIG_H - -#include - -// Original storage belongs to CPlayerSkillBundle's vector at +0x64 and the -// client's homunculus vector at +0x71C. These operations do not allocate or -// invent their enclosing owners; the caller supplies established storage. -void LoadUseSkillLevels(Json::Value& data, int* levels); -void LoadHomunculusSkillLevels(Json::Value& data, int* levels); - -#endif diff --git a/Source/Contents/SkillTreeScript.h b/Source/Contents/SkillTreeScript.h deleted file mode 100644 index a688a35..0000000 --- a/Source/Contents/SkillTreeScript.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLTREESCRIPT_H -#define RAGNAROK_SOURCE_CONTENTS_SKILLTREESCRIPT_H - -struct lua_State; -class CPlayerSkillBundle; - -// Source-side binding for the two recovered callbacks, not the full original -// LuaScript initializer. The bundle must outlive this state's callbacks. -// Skill names remain borrowed from Lua strings, as in the reference. -// Registers c_AddSkillList and c_AddNeedSkillList only. Both return the existing -// top Lua argument (one result, no push), preserve numeric truncation and -1 -// filters, and associate prerequisites with the first available grouped match. -void RegisterSkillTreeCallbacks(lua_State* state, CPlayerSkillBundle& bundle); - -#endif diff --git a/Source/Contents/AutomaticSkills.cpp b/Source/Contents/Skills/AutomaticSkills.cpp similarity index 89% rename from Source/Contents/AutomaticSkills.cpp rename to Source/Contents/Skills/AutomaticSkills.cpp index e40ebce..04125a3 100644 --- a/Source/Contents/AutomaticSkills.cpp +++ b/Source/Contents/Skills/AutomaticSkills.cpp @@ -1,6 +1,5 @@ -#include "Contents/AutomaticSkills.h" +#include "Contents/Skills/AutomaticSkills.h" -#include #include namespace { @@ -16,8 +15,9 @@ namespace { return -1; } } + void Cancel(CConnection& connection, std::int16_t id) { - const std::uint16_t packet[2] = {2833, std::bit_cast(id)}; + const std::uint16_t packet[2] = {2833, static_cast(id)}; connection.Send(sizeof(packet), packet); } } @@ -58,6 +58,7 @@ int AutomaticSkills::CancelOption(std::int16_t id) { // FUNCTION: fn_09150 void AutomaticSkills::DisableAll() { this->m_context->activeKey = 0; + for (int id : this->m_ids) { const auto skill = static_cast(id); const int option = ActiveOption(skill); @@ -79,6 +80,7 @@ void AutomaticSkills::Use(std::int16_t id, std::int16_t level, std::uint32_t tar std::memcpy(packet + 6, &target, 4); this->m_context->connection.Send(sizeof(packet), packet); const int cancel = AutomaticSkills::CancelOption(id); + if (this->m_context->options.Get(cancel) != 0) { Cancel(this->m_context->connection, id); this->m_context->options.Set(cancel, 0, 0); @@ -92,8 +94,6 @@ void AutomaticSkills::Use(std::int16_t id, std::int16_t level, std::uint32_t tar // FUNCTION: fn_21406 void AutomaticSkills::Complete(int id) { if (this->Contains(id)) { - this->m_context->options.Set( - AutomaticSkills::CancelOption(std::bit_cast(static_cast(id))), 0, 0 - ); + this->m_context->options.Set(AutomaticSkills::CancelOption(static_cast(id)), 0, 0); } } diff --git a/Source/Contents/AutomaticSkills.h b/Source/Contents/Skills/AutomaticSkills.h similarity index 80% rename from Source/Contents/AutomaticSkills.h rename to Source/Contents/Skills/AutomaticSkills.h index c7d4af2..584252c 100644 --- a/Source/Contents/AutomaticSkills.h +++ b/Source/Contents/Skills/AutomaticSkills.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_AUTOMATICSKILLS_H -#define RAGNAROK_SOURCE_CONTENTS_AUTOMATICSKILLS_H +#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLS_AUTOMATICSKILLS_H +#define RAGNAROK_SOURCE_CONTENTS_SKILLS_AUTOMATICSKILLS_H -#include "Network/Connection.h" +#include "Network/Connection/Connection.h" #include #include @@ -13,7 +13,6 @@ struct AutomaticSkillContext { const int& currentKey; }; -// Context borrows the actual option/socket/key owners. class AutomaticSkills { public: explicit AutomaticSkills(AutomaticSkillContext& context); diff --git a/Source/Contents/ClientSkills.cpp b/Source/Contents/Skills/ClientSkills.cpp similarity index 90% rename from Source/Contents/ClientSkills.cpp rename to Source/Contents/Skills/ClientSkills.cpp index a9bf117..adcd3f9 100644 --- a/Source/Contents/ClientSkills.cpp +++ b/Source/Contents/Skills/ClientSkills.cpp @@ -1,9 +1,8 @@ -#include "Contents/ClientSkills.h" +#include "Contents/Skills/ClientSkills.h" #include "Script/LuaScript.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" -#include #include namespace { @@ -13,6 +12,7 @@ namespace { return value; } } + return CSkillInfo(-1); } } @@ -25,6 +25,7 @@ bool ClientSkills::HasEffect(std::uint32_t id) const { return true; } } + return false; } @@ -33,11 +34,13 @@ bool ClientSkills::HasEffect(std::uint32_t id) const { CSkillInfo ClientSkills::LookupFirst(std::uint32_t id) const { return Find(this->firstRange, id); } + // OFFSET: 0x00E09A10 // FUNCTION: fn_23787 CSkillInfo ClientSkills::LookupOther(std::uint32_t id) const { return Find(this->otherRanges, id); } + // OFFSET: 0x00E095B0 // FUNCTION: fn_23780 CSkillInfo ClientSkills::LookupAdditional(std::uint32_t id) const { @@ -50,12 +53,15 @@ CSkillInfo ClientSkills::Lookup(std::uint32_t id) const { if (id - 8000u <= 60) { return this->LookupFirst(id); } + if (id - 8200u <= 41 || id - 8400u <= 57) { return this->LookupOther(id); } + if (id - 10000u <= 19) { return this->LookupAdditional(id); } + return this->bundle.Lookup(id, this->classMode, this->HasEffect(1717), this->HasEffect(1716)); } @@ -80,7 +86,7 @@ void SkillWindows::Notify() { void ClientSkills::Remove(std::uint32_t id, SkillWindows& windows) { if (CSkillInfo* skill = this->bundle.FindGrouped(id)) { int previous; - if (this->bundle.PreviousLevel(std::bit_cast(id), previous)) { + if (this->bundle.PreviousLevel(static_cast(id), previous)) { skill->level = previous; } @@ -115,27 +121,24 @@ int SkillUseLevels::Lookup(int id) const { // OFFSET: 0x00E07540 bool ClientSkills::Update( - const CSkillInfo& value, - unsigned char notify, - unsigned char updateUnknown000C, - LuaScript& script, - const SkillUseLevels& levels, - SkillWindows& windows + const CSkillInfo& value, unsigned char notify, unsigned char updateUnknown000C, LuaScript& script, const SkillUseLevels& levels, SkillWindows& windows ) { { - // Keep the original snapshot: Lua/window callbacks may mutate the input. CSkillInfo snapshot(value); const auto update = [](CSkillInfo& target, const CSkillInfo& source, bool copy000C, bool copy0030) { target.level = source.level; std::memcpy(&target.unknown_0014, &source.unknown_0014, sizeof(target.unknown_0014)); std::memcpy(&target.unknown_001C, &source.unknown_001C, sizeof(target.unknown_001C)); std::memcpy(&target.unknown_0018, &source.unknown_0018, sizeof(target.unknown_0018)); + if (copy000C) { std::memcpy(&target.unknown_000C, &source.unknown_000C, sizeof(target.unknown_000C)); } + if (copy0030) { target.unknown_0030 = source.unknown_0030; } + target.unknown_0034 = source.unknown_0034; }; @@ -153,10 +156,10 @@ bool ClientSkills::Update( } if (grouped || snapshot.available) { - if (CSkillInfo::UsesLevel(script, std::bit_cast(snapshot.id)) && snapshot.level != 0) { - const int saved = levels.Lookup(std::bit_cast(snapshot.id)); + if (CSkillInfo::UsesLevel(script, static_cast(snapshot.id)) && snapshot.level != 0) { + const int saved = levels.Lookup(static_cast(snapshot.id)); if (saved <= 0 || saved > snapshot.level) { - this->bundle.SetUnknownValue(std::bit_cast(snapshot.id), snapshot.level); + this->bundle.SetUnknownValue(static_cast(snapshot.id), snapshot.level); } } } @@ -167,14 +170,17 @@ bool ClientSkills::Update( std::memcpy(&existing->unknown_0014, &value.unknown_0014, sizeof(existing->unknown_0014)); std::memcpy(&existing->unknown_001C, &value.unknown_001C, sizeof(existing->unknown_001C)); std::memcpy(&existing->unknown_0018, &value.unknown_0018, sizeof(existing->unknown_0018)); + if (updateUnknown000C == 1) { std::memcpy(&existing->unknown_000C, &value.unknown_000C, sizeof(existing->unknown_000C)); } + existing->unknown_0030 = value.unknown_0030; existing->unknown_0034 = value.unknown_0034; if (notify == 1) { windows.Notify(); } + return false; } @@ -182,6 +188,7 @@ bool ClientSkills::Update( if (notify != 0) { windows.Notify(); } + return true; } @@ -216,6 +223,7 @@ bool CompanionSkills::Update(const CSkillInfo& value, unsigned char notify) { if (notify) { this->Notify(); } + return false; } } @@ -224,6 +232,7 @@ bool CompanionSkills::Update(const CSkillInfo& value, unsigned char notify) { if (notify) { this->Notify(); } + return true; } @@ -237,6 +246,7 @@ bool ClientSkills::UpdateAdditional(const CSkillInfo& value, int) { std::memcpy(&skill.unknown_001C, &value.unknown_001C, sizeof(skill.unknown_001C)); std::memcpy(&skill.unknown_0018, &value.unknown_0018, sizeof(skill.unknown_0018)); skill.unknown_0034 = value.unknown_0034; + return false; } } diff --git a/Source/Contents/Skills/ClientSkills.h b/Source/Contents/Skills/ClientSkills.h new file mode 100644 index 0000000..cd4a5cc --- /dev/null +++ b/Source/Contents/Skills/ClientSkills.h @@ -0,0 +1,68 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLS_CLIENTSKILLS_H +#define RAGNAROK_SOURCE_CONTENTS_SKILLS_CLIENTSKILLS_H + +#include "Contents/Skills/PlayerSkillBundle.h" + +class UIWindow; + +struct SkillWindows { + UIWindow*& first; + UIWindow*& second; + WindowManagerWindows& windows; + + void Notify(); +}; + +struct SkillUseLevels { + const std::vector& use; + const std::vector& additional; + const std::vector& homunculus; + + int Lookup(int id) const; +}; + +struct CompanionSkills { + std::list& skills; + UIWindow*& window; + UIWindow*& sharedWindow; + + bool Update(const CSkillInfo& value, unsigned char notify); + void Notify(); +}; + +struct ActiveSkillEffect { + std::uint32_t id; + std::uint32_t unknown_0004; + std::uint32_t unknown_0008; + std::uint32_t unknown_000C; + std::uint32_t unknown_0010; + std::uint32_t unknown_0014; + std::uint32_t unknown_0018; +}; + +struct ClientSkills { + CPlayerSkillBundle& bundle; + const std::list& firstRange; + const std::list& otherRanges; + std::list& additional; + const int& classMode; + const std::vector& effects; + + bool HasEffect(std::uint32_t id) const; + CSkillInfo LookupFirst(std::uint32_t id) const; + CSkillInfo LookupOther(std::uint32_t id) const; + CSkillInfo LookupAdditional(std::uint32_t id) const; + CSkillInfo Lookup(std::uint32_t id) const; + + bool UpdateAdditional(const CSkillInfo& value, int unused); + + void Remove(std::uint32_t id, SkillWindows& windows); + + bool Update( + const CSkillInfo& value, unsigned char notify, unsigned char updateUnknown000C, LuaScript& script, const SkillUseLevels& levels, SkillWindows& windows + ); +}; + +static_assert(sizeof(ActiveSkillEffect) == 28); + +#endif diff --git a/Source/Contents/PlayerSkillBundle.cpp b/Source/Contents/Skills/PlayerSkillBundle.cpp similarity index 94% rename from Source/Contents/PlayerSkillBundle.cpp rename to Source/Contents/Skills/PlayerSkillBundle.cpp index e27a881..e8299c5 100644 --- a/Source/Contents/PlayerSkillBundle.cpp +++ b/Source/Contents/Skills/PlayerSkillBundle.cpp @@ -1,16 +1,16 @@ -#include "Contents/PlayerSkillBundle.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "Contents/Skills/PlayerSkillBundle.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" #include -#include std::size_t SkillIdHash::operator()(std::uint32_t id) const { - // Original MSVC hash over the four little-endian key bytes. std::uint32_t hash = 0x811C9DC5u; + for (unsigned shift = 0; shift < 32; shift += 8) { hash = (hash ^ ((id >> shift) & 255)) * 16777619u; } + return hash; } @@ -18,6 +18,7 @@ std::size_t SkillIdHash::operator()(std::uint32_t id) const { // FUNCTION: fn_08260 CPlayerSkillBundle::lcEXCInfo::lcEXCInfo() { } + // OFFSET: 0x00770E90 CPlayerSkillBundle::lcEXCInfo::~lcEXCInfo() = default; @@ -25,6 +26,7 @@ CPlayerSkillBundle::lcEXCInfo::~lcEXCInfo() = default; // FUNCTION: fn_08253 CPlayerSkillBundle::CPlayerSkillBundle() : index(8) { } + // OFFSET: 0x00770830 // FUNCTION: fn_08258 // OFFSET: 0x00770D40 @@ -60,6 +62,7 @@ CSkillInfo* CPlayerSkillBundle::Find(std::uint32_t id) { return &value; } } + return nullptr; } @@ -69,6 +72,7 @@ std::uint32_t CPlayerSkillBundle::ResolveSkillId(std::uint32_t id, int classMode if (classMode != 1 || (id != 6578 && id != 6579)) { return id; } + const auto valid = [&](std::uint32_t key) { const auto entry = this->index.find(key); return entry != this->index.end() && entry->second->IsValid(); @@ -76,9 +80,11 @@ std::uint32_t CPlayerSkillBundle::ResolveSkillId(std::uint32_t id, int classMode if (effect1717 && valid(6580)) { return 6580; } + if (effect1716 && valid(6579)) { return 6579; } + return id; } @@ -88,10 +94,12 @@ CSkillInfo CPlayerSkillBundle::Lookup(std::uint32_t id, int classMode, bool effe if (this->skills.empty()) { return CSkillInfo(-1); } + const auto entry = this->index.find(this->ResolveSkillId(id, classMode, effect1717, effect1716)); if (entry != this->index.end() && entry->second->IsValid()) { return *entry->second; } + CSkillInfo* value = this->Find(id); return value ? *value : CSkillInfo(-1); } @@ -103,6 +111,7 @@ bool CPlayerSkillBundle::FindIndexed(std::uint32_t id, CSkillInfo*& output) { if (entry == this->index.end()) { return false; } + output = entry->second; return true; } @@ -117,9 +126,11 @@ bool CPlayerSkillBundle::UpdatePending(const CSkillInfo& value) { entry.unknown_0014 = value.unknown_0014; entry.unknown_0018 = value.unknown_0018; entry.unknown_0034 = value.unknown_0034; + return false; } } + this->pending.push_back(value); return true; } @@ -132,6 +143,7 @@ CSkillInfo CPlayerSkillBundle::Pending(std::uint32_t id) { return value; } } + return CSkillInfo(-1); } @@ -143,6 +155,7 @@ CSkillInfo* CPlayerSkillBundle::FindExtra(std::uint32_t id) { return &value; } } + return nullptr; } @@ -160,6 +173,7 @@ void CPlayerSkillBundle::AddExtra(const CSkillInfo& value, WindowManagerWindows& if (UIWindow* window = windows.LookupWindow(37)) { window->SendMsg(nullptr, 161, 0, 0, 0, 0); } + this->extra.push_back(value); } @@ -170,6 +184,7 @@ bool CPlayerSkillBundle::RemoveExtra(std::uint32_t id, WindowManagerWindows& win if (entry->id != id) { continue; } + this->extra.erase(entry); const auto item = std::find(this->extraIds.begin(), this->extraIds.end(), id); if (item != this->extraIds.end()) { @@ -178,8 +193,10 @@ bool CPlayerSkillBundle::RemoveExtra(std::uint32_t id, WindowManagerWindows& win window->SendMsg(nullptr, 161, 0, 0, 0, 0); } } + return true; } + return false; } @@ -187,6 +204,7 @@ bool CPlayerSkillBundle::RemoveExtra(std::uint32_t id, WindowManagerWindows& win // FUNCTION: fn_08278 void CPlayerSkillBundle::NumberExtra() { unsigned number = 0; + for (CSkillInfo& value : this->extra) { value.unknown_0024 = number++; } @@ -214,13 +232,13 @@ CSkillInfo* CPlayerSkillBundle::FindGrouped(std::uint32_t id) { } } } + return nullptr; } // OFFSET: 0x00771DA0 // FUNCTION: fn_08291 std::list& CPlayerSkillBundle::Group(int group) { - // Original has one function-local, mutable empty list shared by all bundles. static std::list missing; const auto entry = this->groups.find(group); return entry == this->groups.end() ? missing : entry->second; @@ -244,7 +262,7 @@ int CPlayerSkillBundle::GroupedLevel(std::uint32_t id) { // FUNCTION: fn_08284 bool CPlayerSkillBundle::HasHigherLevel(std::uint32_t id) { const CSkillInfo* value = this->FindGrouped(id); - return value && value->level > std::bit_cast(value->unknown_0030); + return value && value->level > value->unknown_0030; } // OFFSET: 0x00770F20 @@ -253,14 +271,16 @@ void CPlayerSkillBundle::RecordLevelChange(const CSkillInfo& value) { if (value.level == 0) { return; } + CSkillInfo* previous = this->FindGrouped(value.id); if (!previous || previous->level >= value.level) { return; } - lcEXCInfo& entry = this->levelChanges[std::bit_cast(value.id)]; + + lcEXCInfo& entry = this->levelChanges[static_cast(value.id)]; entry.previous = previous->level; entry.target = value.level; - this->changed[std::bit_cast(value.id)] = true; + this->changed[static_cast(value.id)] = true; } // OFFSET: 0x00771250 @@ -274,7 +294,7 @@ bool CPlayerSkillBundle::PreviousLevel(int id, int& output) const { // OFFSET: 0x00771FC0 // FUNCTION: fn_08295 void CPlayerSkillBundle::ApplyLevelChange(CSkillInfo& value) { - const int id = std::bit_cast(value.id); + const int id = static_cast(value.id); const auto entry = this->levelChanges.find(id); if (entry != this->levelChanges.end()) { lcEXCInfo& change = entry->second; @@ -285,11 +305,13 @@ void CPlayerSkillBundle::ApplyLevelChange(CSkillInfo& value) { value.level = change.target; } } + for (int removed : this->removals) { if (this->levelChanges.erase(removed)) { this->changed.erase(removed); } } + this->removals.clear(); } diff --git a/Source/Contents/PlayerSkillBundle.h b/Source/Contents/Skills/PlayerSkillBundle.h similarity index 90% rename from Source/Contents/PlayerSkillBundle.h rename to Source/Contents/Skills/PlayerSkillBundle.h index 200728a..509dc9a 100644 --- a/Source/Contents/PlayerSkillBundle.h +++ b/Source/Contents/Skills/PlayerSkillBundle.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_PLAYERSKILLBUNDLE_H -#define RAGNAROK_SOURCE_CONTENTS_PLAYERSKILLBUNDLE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLS_PLAYERSKILLBUNDLE_H +#define RAGNAROK_SOURCE_CONTENTS_SKILLS_PLAYERSKILLBUNDLE_H -#include "Contents/SkillInfo.h" +#include "Contents/Skills/SkillInfo.h" #include #include @@ -14,8 +14,6 @@ struct SkillIdHash { std::size_t operator()(std::uint32_t id) const; }; -// RTTI CPlayerSkillBundle. Borrowed hash values point -// into the stable nodes of skills; all other collections own their values. class CPlayerSkillBundle { public: struct lcEXCInfo { diff --git a/Source/Contents/SkillInfo.cpp b/Source/Contents/Skills/SkillInfo.cpp similarity index 76% rename from Source/Contents/SkillInfo.cpp rename to Source/Contents/Skills/SkillInfo.cpp index 1c06095..871716d 100644 --- a/Source/Contents/SkillInfo.cpp +++ b/Source/Contents/Skills/SkillInfo.cpp @@ -1,20 +1,17 @@ -#include "Contents/NormalItemSlots.h" -#include "Contents/SkillInfo.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "Contents/Skills/SkillInfo.h" #include "Script/LuaScript.h" -#include #include // OFFSET: 0x00773480 // FUNCTION: fn_08311 -CSkillInfo::CSkillInfo() - : available(1), id(0), level(0), name(nullptr), unknown_0028(0), unknown_0030(0), unknown_0034(0) { +CSkillInfo::CSkillInfo() : available(1), id(0), level(0), name(nullptr), unknown_0028(0), unknown_0030(0), unknown_0034(0) { } // OFFSET: 0x00773400 // FUNCTION: fn_08310 -CSkillInfo::CSkillInfo(int) - : available(0), id(0), level(0), name("Unknown-Skill"), unknown_0028(0), unknown_0030(0), unknown_0034(0) { +CSkillInfo::CSkillInfo(int) : available(0), id(0), level(0), name("Unknown-Skill"), unknown_0028(0), unknown_0030(0), unknown_0034(0) { } // OFFSET: 0x0076FD70 @@ -30,9 +27,9 @@ CSkillInfo& CSkillInfo::operator=(const CSkillInfo& other) { if (this == &other) { return *this; } + this->id = other.id; - // Preserve the unknown member representations, including fields left - // untouched by the constructors, without evaluating indeterminate integers. + std::memcpy(&this->unknown_000C, &other.unknown_000C, sizeof(this->unknown_000C)); this->level = other.level; std::memcpy(&this->unknown_0014, &other.unknown_0014, sizeof(this->unknown_0014)); @@ -45,6 +42,7 @@ CSkillInfo& CSkillInfo::operator=(const CSkillInfo& other) { this->unknown_0030 = other.unknown_0030; this->unknown_0034 = other.unknown_0034; this->entries = other.entries; + return *this; } @@ -64,7 +62,8 @@ bool CSkillInfo::MatchesShortcut(const NormalItemSlot* slot) const { if (!slot || !this->IsValid()) { return false; } - const auto requested = std::bit_cast(slot->unknown_0005); + + const auto requested = slot->unknown_0005; return requested != 0 && (this->id != slot->itemId || this->level >= requested); } @@ -72,7 +71,7 @@ bool CSkillInfo::MatchesShortcut(const NormalItemSlot* slot) const { // FUNCTION: fn_08313 int CSkillInfo::UseApAmount(LuaScript& script, int skillLevel) const { int amount = 0; - script.Call("GetLevelUseApAmount", "dd>d", std::bit_cast(this->id), skillLevel, &amount); + script.Call("GetLevelUseApAmount", "dd>d", static_cast(this->id), skillLevel, &amount); return amount; } @@ -80,14 +79,14 @@ int CSkillInfo::UseApAmount(LuaScript& script, int skillLevel) const { // FUNCTION: fn_08314 int CSkillInfo::UseSpAmount(LuaScript& script, int skillLevel) const { int amount = 0; - script.Call("GetLevelUseSpAmount", "dd>d", std::bit_cast(this->id), skillLevel, &amount); + script.Call("GetLevelUseSpAmount", "dd>d", static_cast(this->id), skillLevel, &amount); return amount; } // OFFSET: 0x007736F0 // FUNCTION: fn_08315 const char* CSkillInfo::DisplayName(LuaScript& script) const { - return CSkillInfo::DisplayName(script, std::bit_cast(this->id)); + return CSkillInfo::DisplayName(script, static_cast(this->id)); } // OFFSET: 0x00773920 @@ -98,6 +97,7 @@ const char* CSkillInfo::DisplayName(LuaScript& script, int skillId) { } else if (skillId == 5043) { skillId = 5036; } + const char* result = nullptr; return script.Call("GetSkillName", "d>s", skillId, &result) ? result : "Unknown-Skill"; } @@ -105,7 +105,7 @@ const char* CSkillInfo::DisplayName(LuaScript& script, int skillId) { // OFFSET: 0x007737C0 // FUNCTION: fn_08316 const char* CSkillInfo::IdName(LuaScript& script) const { - return CSkillInfo::IdName(script, std::bit_cast(this->id)); + return CSkillInfo::IdName(script, static_cast(this->id)); } // OFFSET: 0x00773870 diff --git a/Source/Contents/SkillInfo.h b/Source/Contents/Skills/SkillInfo.h similarity index 85% rename from Source/Contents/SkillInfo.h rename to Source/Contents/Skills/SkillInfo.h index 74631b9..e0d41e5 100644 --- a/Source/Contents/SkillInfo.h +++ b/Source/Contents/Skills/SkillInfo.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLINFO_H -#define RAGNAROK_SOURCE_CONTENTS_SKILLINFO_H +#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLS_SKILLINFO_H +#define RAGNAROK_SOURCE_CONTENTS_SKILLS_SKILLINFO_H #include #include @@ -11,8 +11,6 @@ struct SkillInfoEntry { std::uint32_t unknown_0004; }; -// RTTI CSkillInfo, 68-byte x86 value. Unresolved members -// retain their original offsets rather than guessed domain meanings. class CSkillInfo { public: CSkillInfo(); @@ -41,7 +39,7 @@ public: /* 0024 */ std::uint32_t unknown_0024; /* 0028 */ std::uint32_t unknown_0028; /* 002C */ std::uint32_t unknown_002C; - /* 0030 */ std::uint16_t unknown_0030; + /* 0030 */ std::int16_t unknown_0030; /* 0034 */ std::uint32_t unknown_0034; /* 0038 */ std::vector entries; }; diff --git a/Source/Contents/SkillLevelConfig.cpp b/Source/Contents/Skills/SkillLevelConfig.cpp similarity index 86% rename from Source/Contents/SkillLevelConfig.cpp rename to Source/Contents/Skills/SkillLevelConfig.cpp index bb3dfb9..2a2e6fc 100644 --- a/Source/Contents/SkillLevelConfig.cpp +++ b/Source/Contents/Skills/SkillLevelConfig.cpp @@ -1,4 +1,4 @@ -#include "Contents/SkillLevelConfig.h" +#include "Contents/Skills/SkillLevelConfig.h" #include @@ -30,8 +30,7 @@ void LoadHomunculusSkillLevels(Json::Value& data, int* levels) { if (value.isObject()) { int id = value.get("HomunSKID", 0).asInt(); int level = value.get("HomunSKLv", 0).asInt(); - // Original subtracts in 32 bits, then signed-compares against -1; - // there is no upper bound check on the caller's storage. + std::uint32_t index = static_cast(id) - 8000; if (static_cast(index) > -1) { levels[index] = level; diff --git a/Source/Contents/Skills/SkillLevelConfig.h b/Source/Contents/Skills/SkillLevelConfig.h new file mode 100644 index 0000000..b19fc45 --- /dev/null +++ b/Source/Contents/Skills/SkillLevelConfig.h @@ -0,0 +1,9 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLS_SKILLLEVELCONFIG_H +#define RAGNAROK_SOURCE_CONTENTS_SKILLS_SKILLLEVELCONFIG_H + +#include + +void LoadUseSkillLevels(Json::Value& data, int* levels); +void LoadHomunculusSkillLevels(Json::Value& data, int* levels); + +#endif diff --git a/Source/Contents/SkillLevelRegistry.cpp b/Source/Contents/Skills/SkillLevelRegistry.cpp similarity index 82% rename from Source/Contents/SkillLevelRegistry.cpp rename to Source/Contents/Skills/SkillLevelRegistry.cpp index b613e26..5d4147b 100644 --- a/Source/Contents/SkillLevelRegistry.cpp +++ b/Source/Contents/Skills/SkillLevelRegistry.cpp @@ -1,5 +1,5 @@ -#include "Contents/SkillInfo.h" -#include "Contents/SkillLevelRegistry.h" +#include "Contents/Skills/SkillInfo.h" +#include "Contents/Skills/SkillLevelRegistry.h" #include "Script/LuaScript.h" #include @@ -34,10 +34,7 @@ void SkillLevelRegistry::Load() { const char* skill = CSkillInfo::IdName(this->script, id); std::sprintf(name, "%s%d", skill, character); - if ( - RegQueryValueExA(handle, name, nullptr, &type, reinterpret_cast(&value), &size) != ERROR_SUCCESS || - !CSkillInfo::UsesLevel(this->script, id) - ) { + if (RegQueryValueExA(handle, name, nullptr, &type, reinterpret_cast(&value), &size) != ERROR_SUCCESS || !CSkillInfo::UsesLevel(this->script, id)) { return 0; } diff --git a/Source/Contents/SkillLevelRegistry.h b/Source/Contents/Skills/SkillLevelRegistry.h similarity index 62% rename from Source/Contents/SkillLevelRegistry.h rename to Source/Contents/Skills/SkillLevelRegistry.h index 97aec2a..2e2ef93 100644 --- a/Source/Contents/SkillLevelRegistry.h +++ b/Source/Contents/Skills/SkillLevelRegistry.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLLEVELREGISTRY_H -#define RAGNAROK_SOURCE_CONTENTS_SKILLLEVELREGISTRY_H +#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLS_SKILLLEVELREGISTRY_H +#define RAGNAROK_SOURCE_CONTENTS_SKILLS_SKILLLEVELREGISTRY_H class LuaScript; diff --git a/Source/Contents/SkillTreeScript.cpp b/Source/Contents/Skills/SkillTreeScript.cpp similarity index 93% rename from Source/Contents/SkillTreeScript.cpp rename to Source/Contents/Skills/SkillTreeScript.cpp index 8c6dbbb..45ad9fd 100644 --- a/Source/Contents/SkillTreeScript.cpp +++ b/Source/Contents/Skills/SkillTreeScript.cpp @@ -1,5 +1,5 @@ -#include "Contents/PlayerSkillBundle.h" -#include "Contents/SkillTreeScript.h" +#include "Contents/Skills/PlayerSkillBundle.h" +#include "Contents/Skills/SkillTreeScript.h" extern "C" { #include @@ -38,7 +38,6 @@ namespace { Bundle(state).AddGrouped(static_cast(group), skill); } - // The original returns one existing stack value, without pushing a result. return 1; } diff --git a/Source/Contents/Skills/SkillTreeScript.h b/Source/Contents/Skills/SkillTreeScript.h new file mode 100644 index 0000000..55a56a2 --- /dev/null +++ b/Source/Contents/Skills/SkillTreeScript.h @@ -0,0 +1,9 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_SKILLS_SKILLTREESCRIPT_H +#define RAGNAROK_SOURCE_CONTENTS_SKILLS_SKILLTREESCRIPT_H + +struct lua_State; +class CPlayerSkillBundle; + +void RegisterSkillTreeCallbacks(lua_State* state, CPlayerSkillBundle& bundle); + +#endif diff --git a/Source/Contents/SkinInfo.cpp b/Source/Contents/SkinInfo.cpp index 92d533c..ddeb635 100644 --- a/Source/Contents/SkinInfo.cpp +++ b/Source/Contents/SkinInfo.cpp @@ -25,7 +25,6 @@ const char* SkinInfo::Name() const { // FUNCTION: fn_09687 const char* SkinInfo::Prefix() const { if (this->selected == -1) { - // Default string is twelve zero bytes. return ""; } @@ -68,6 +67,6 @@ void SkinInfo::Prepare() { const std::string input = std::string("skin/") + this->names[this->selected]; const std::string output = std::string("_tmpskin_/") + this->names[this->selected]; _spawnl(_P_WAIT, "runzip.exe", "runzip.exe", "-n", input.c_str(), "-d", output.c_str(), nullptr); - // Original marks preparation even when the process launch/extraction fails. + this->prepared[this->selected] = 1; } diff --git a/Source/Contents/SkinInfo.h b/Source/Contents/SkinInfo.h index c0f1121..bbaaec1 100644 --- a/Source/Contents/SkinInfo.h +++ b/Source/Contents/SkinInfo.h @@ -4,8 +4,6 @@ #include #include -// Borrowed fields of original skin owner off_1334630. Names/prefixes and -// archive/prepared flags are kept on their real configuration owner. struct SkinInfo { int& selected; const std::vector& names; diff --git a/Source/Contents/SoundConfiguration.cpp b/Source/Contents/Sound/SoundConfiguration.cpp similarity index 71% rename from Source/Contents/SoundConfiguration.cpp rename to Source/Contents/Sound/SoundConfiguration.cpp index 8f4718b..ed44154 100644 --- a/Source/Contents/SoundConfiguration.cpp +++ b/Source/Contents/Sound/SoundConfiguration.cpp @@ -1,8 +1,8 @@ -#include "Contents/SoundConfiguration.h" +#include "Contents/Sound/SoundConfiguration.h" // OFFSET: 0x00E59030 // FUNCTION: fn_24366 -// Sound portion of the setup registry loader. + void SoundConfiguration::LoadRegistry(const char* baseKey) { HKEY key; @@ -10,8 +10,6 @@ void SoundConfiguration::LoadRegistry(const char* baseKey) { return; } - // The original reuses type/size outputs across all five DWORD queries; - // failures are ignored except NUMSAMPLETYPE's explicit fallback to 2. DWORD type = REG_DWORD; DWORD size = sizeof(int); RegQueryValueExA(key, "SOUNDMODE", nullptr, &type, reinterpret_cast(&this->mode), &size); @@ -19,10 +17,7 @@ void SoundConfiguration::LoadRegistry(const char* baseKey) { RegQueryValueExA(key, "DIGITALRATETYPE", nullptr, &type, reinterpret_cast(&this->digitalRateType), &size); RegQueryValueExA(key, "DIGITALBITSTYPE", nullptr, &type, reinterpret_cast(&this->digitalBitsType), &size); - if ( - RegQueryValueExA(key, "NUMSAMPLETYPE", nullptr, &type, reinterpret_cast(&this->numSampleType), &size) != - ERROR_SUCCESS - ) { + if (RegQueryValueExA(key, "NUMSAMPLETYPE", nullptr, &type, reinterpret_cast(&this->numSampleType), &size) != ERROR_SUCCESS) { this->numSampleType = 2; } diff --git a/Source/Contents/SoundConfiguration.h b/Source/Contents/Sound/SoundConfiguration.h similarity index 58% rename from Source/Contents/SoundConfiguration.h rename to Source/Contents/Sound/SoundConfiguration.h index 7d2ab1a..3ecca23 100644 --- a/Source/Contents/SoundConfiguration.h +++ b/Source/Contents/Sound/SoundConfiguration.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_SOUNDCONFIGURATION_H -#define RAGNAROK_SOURCE_CONTENTS_SOUNDCONFIGURATION_H +#ifndef RAGNAROK_SOURCE_CONTENTS_SOUND_SOUNDCONFIGURATION_H +#define RAGNAROK_SOURCE_CONTENTS_SOUND_SOUNDCONFIGURATION_H #include -// Shared sound configuration. Populated by the setup registry loader. struct SoundConfiguration { /* 0173A924 */ int mode = 0; /* 0173A928 */ int speakerType = 0; @@ -13,7 +12,6 @@ struct SoundConfiguration { /* 0173A938 */ int preference15 = 0; /* 0173A93C */ char providerName[1024] = {}; - // Sound portion of the larger setup loader. baseKey is the application's shared setup key. void LoadRegistry(const char* baseKey); }; diff --git a/Source/Contents/SoundMgr.cpp b/Source/Contents/Sound/SoundMgr.cpp similarity index 86% rename from Source/Contents/SoundMgr.cpp rename to Source/Contents/Sound/SoundMgr.cpp index 07d1cef..7300db1 100644 --- a/Source/Contents/SoundMgr.cpp +++ b/Source/Contents/Sound/SoundMgr.cpp @@ -1,15 +1,14 @@ -#include "Contents/ServiceOptions.h" -#include "Contents/SoundConfiguration.h" -#include "Contents/SoundMgr.h" +#include "Contents/Configuration/ServiceOptions.h" +#include "Contents/Sound/SoundConfiguration.h" +#include "Contents/Sound/SoundMgr.h" #include "Resource/ResourceMgr.h" -#include "Resource/WaveResource.h" -#include "Utility/AffineMatrix.h" +#include "Resource/Audio/WaveResource.h" +#include "Utility/Math/AffineMatrix.h" +#include "Utility/Math/ScalarConversion.h" -#include #include #include #include -#include #include #include @@ -18,7 +17,6 @@ CSoundMgr* g_soundMgr = nullptr; namespace { - // OFFSET: 0x00401090 // FUNCTION: fn_45443 void ShutdownMilesAtExit() { @@ -56,9 +54,7 @@ void CSoundMgr::FadeIn() { this->fadeThread = INVALID_HANDLE_VALUE; } - this->fadeThread = reinterpret_cast( - _beginthreadex(nullptr, 0, &CSoundMgr::FadeThread, reinterpret_cast(1), 0, &this->threadId) - ); + this->fadeThread = reinterpret_cast(_beginthreadex(nullptr, 0, &CSoundMgr::FadeThread, reinterpret_cast(1), 0, &this->threadId)); } // OFFSET: 0x00638EF0 @@ -75,8 +71,7 @@ void CSoundMgr::FadeOut() { this->fadeThread = INVALID_HANDLE_VALUE; } - this->fadeThread = - reinterpret_cast(_beginthreadex(nullptr, 0, &CSoundMgr::FadeThread, nullptr, 0, &this->threadId)); + this->fadeThread = reinterpret_cast(_beginthreadex(nullptr, 0, &CSoundMgr::FadeThread, nullptr, 0, &this->threadId)); } // OFFSET: 0x00638F60 @@ -127,8 +122,7 @@ bool CSoundMgr::Initialize() { MilesRuntime& miles = MilesRuntime::Get(); miles.setRedistDirectory(".\\"); - // Get() must precede registration: this callback runs before the host - // binding's destructor unloads Mss32.dll. Every Initialize registers it. + std::atexit(&ShutdownMilesAtExit); miles.startup(); @@ -170,8 +164,6 @@ bool CSoundMgr::Initialize() { strcpy_s(configuration.providerName, sizeof(configuration.providerName), "Miles Fast 2D Positional Audio"); - // The original has 64 slots but no enumeration bound. Do not turn its - // first matching-provider search into a capped or fallback-provider policy. int index = 0; while (miles.enumerate3DProviders(&this->enumerator, &this->providers[index], &this->providerNames[index])) { @@ -336,8 +328,6 @@ unsigned __stdcall CSoundMgr::FadeThread(void* direction) { CSoundMgr* sound = g_soundMgr; const int volume = CSoundMgr::Volume(sound); - // The fade-in path really dereferences the singleton after the - // null-safe volume read. There is no destructor join/null recovery. if (sound->targetVolume <= volume) { break; } @@ -413,17 +403,9 @@ void CSoundMgr::Pause(CSoundMgr* sound, int paused) { // OFFSET: 0x00639B50 // FUNCTION: fn_45424 -bool CSoundMgr::PlayData3D( - const void* data, - const float& x, - const float& y, - const float& z, - int maximumDistance, - int minimumDistance, - float scale -) { +bool CSoundMgr::PlayData3D(const void* data, const float& x, const float& y, const float& z, int maximumDistance, int minimumDistance, float scale) { const float scaledVolume = static_cast(this->volume3D) * scale; - const int volume = _mm_cvttss_si32(_mm_set_ss(scaledVolume)); + const int volume = TruncateToInt(scaledVolume); if (!this->provider) { return this->PlayData2D(data, x, y, z, 250, 40, 1.0f); @@ -448,10 +430,9 @@ bool CSoundMgr::PlayData3D( miles.set3DPosition(this->samples3D[i], x, y, z); miles.set3DOrientation(this->samples3D[i], -x, -y, -z, 0.0f, 1.0f, 0.0f); miles.set3DSampleVolume(this->samples3D[i], volume); - miles.set3DSampleDistances( - this->samples3D[i], static_cast(maximumDistance), static_cast(minimumDistance) - ); + miles.set3DSampleDistances(this->samples3D[i], static_cast(maximumDistance), static_cast(minimumDistance)); miles.start3DSample(this->samples3D[i]); + return true; } @@ -472,17 +453,7 @@ void CSoundMgr::SetDefaultName(std::string name) { // OFFSET: 0x00639DF0 // FUNCTION: fn_04762 -bool CSoundMgr::PlayData2D( - const void* data, - const float& x, - const float& y, - const float& z, - int maximumDistance, - int minimumDistance, - float scale -) { - // Distance calculation uses fsqrt with a float spill, called twice. Retain both - // roots and each SSE-width intermediate rather than collapsing to length. +bool CSoundMgr::PlayData2D(const void* data, const float& x, const float& y, const float& z, int maximumDistance, int minimumDistance, float scale) { const float zSquared = z * z; const float xSquared = x * x; const float horizontalSquared = xSquared + zSquared; @@ -499,16 +470,14 @@ bool CSoundMgr::PlayData2D( int volume = this->sampleVolume; const float minimum = static_cast(minimumDistance); - // COMISS minimum,distance / JAE skips attenuation for ordered >= only. - // In particular an unordered distance still enters the cvttss2si path. if (!(minimum >= distance)) { const float numerator = static_cast(volume) * minimum; const float attenuatedVolume = numerator / distance; - volume = _mm_cvttss_si32(_mm_set_ss(attenuatedVolume)); + volume = TruncateToInt(attenuatedVolume); } const float scaledVolume = static_cast(volume) * scale; - volume = _mm_cvttss_si32(_mm_set_ss(scaledVolume)); + volume = TruncateToInt(scaledVolume); for (int i = 0; i < this->sampleCount; ++i) { if (!this->samples[i]) { @@ -525,6 +494,7 @@ bool CSoundMgr::PlayData2D( miles.setSampleFile(this->samples[i], data, 0); miles.setSampleVolume(this->samples[i], volume); miles.startSample(this->samples[i]); + return true; } @@ -570,7 +540,6 @@ void CSoundMgr::PlayStream(const char* name, int loopCount, bool fade) { const std::string copiedName(name); } - // The original calls these even if openStream returned null. miles.setStreamVolume(this->stream, this->streamVolume); miles.setStreamLoopCount(this->stream, loopCount); miles.startStream(this->stream); @@ -578,23 +547,13 @@ void CSoundMgr::PlayStream(const char* name, int loopCount, bool fade) { // OFFSET: 0x0063A130 // FUNCTION: fn_04764 -void CSoundMgr::PlayWave( - const char* name, - float x, - float y, - float z, - int maximumDistance, - int minimumDistance, - float scale, - int unused -) { +void CSoundMgr::PlayWave(const char* name, float x, float y, float z, int maximumDistance, int minimumDistance, float scale, int unused) { const unsigned char enabled = this->m_context->serviceOptions.Get(11); if (this->m_context->configuration.mode == 0 || !enabled) { return; } - // Exact legacy-codepage filename. Rejects every other name when unknown is nonzero. static constexpr char permittedName[] = "\xB9\xF6\xC6\xB0\xBC\xD2\xB8\xAE.wav"; if (this->unknown != 0 && std::strcmp(name, permittedName) != 0) { @@ -610,7 +569,6 @@ void CSoundMgr::PlayWave( if (this->m_context->configuration.mode == 1) { this->PlayData2D(wave->data, x, y, z, maximumDistance, minimumDistance, scale); } else if (this->m_context->configuration.mode == 2) { - // Inlined PlayData3D body, including the fixed 250/40/1 fallback when no 3D provider was selected. this->PlayData3D(wave->data, x, y, z, maximumDistance, minimumDistance, scale); } } @@ -664,7 +622,7 @@ void CSoundMgr::SetListenerYaw(float yaw) { } const float angle = 180.0f - yaw; - const int degrees = _mm_cvttss_si32(_mm_set_ss(angle)); + const int degrees = TruncateToInt(angle); const float sine = ClientSine(degrees); const float cosine = ClientCosine(degrees); MilesRuntime::Get().set3DOrientation(this->listener, sine, 0.0f, -cosine, 0.0f, 1.0f, 0.0f); diff --git a/Source/Contents/SoundMgr.h b/Source/Contents/Sound/SoundMgr.h similarity index 76% rename from Source/Contents/SoundMgr.h rename to Source/Contents/Sound/SoundMgr.h index fb35bda..43939ba 100644 --- a/Source/Contents/SoundMgr.h +++ b/Source/Contents/Sound/SoundMgr.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_SOUNDMGR_H -#define RAGNAROK_SOURCE_CONTENTS_SOUNDMGR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_SOUND_SOUNDMGR_H +#define RAGNAROK_SOURCE_CONTENTS_SOUND_SOUNDMGR_H -#include "Resource/MilesRuntime.h" +#include "Resource/Audio/MilesRuntime.h" #include #include @@ -18,14 +18,6 @@ struct SoundMgrContext { ResourceMgr& resources; }; -// RTTI CSoundMgr. Original size is 0x41C; -// only the borrowed source context is appended. The original fade worker -// accesses g_soundMgr without synchronization. Destruction neither joins the -// worker nor closes its handle; preserve that lifetime/race contract here. -// Keep the context and shared configuration alive through Destroy(). Native -// Miles 6.1a requires Mss32.dll; mode 2 discovers its .m3d provider in the redist -// directory ".\\". File decoding additionally uses the supplied ASI codecs. -// Application WinMain/game-mode callers remain separate from this owner. class CSoundMgr { public: explicit CSoundMgr(SoundMgrContext& context); @@ -42,44 +34,17 @@ public: void Shutdown(); void EndSamples(); - // Original entries explicitly accept a null owner in ECX. Static pointer - // interfaces preserve that behavior without undefined null-this calls. static int Volume(const CSoundMgr* sound); static void Pause(CSoundMgr* sound, int paused); static void SetVolume(CSoundMgr* sound, int volume); bool IsComplete() const; bool IsStopped() const; - bool PlayData3D( - const void* data, - const float& x, - const float& y, - const float& z, - int maximumDistance, - int minimumDistance, - float scale - ); + bool PlayData3D(const void* data, const float& x, const float& y, const float& z, int maximumDistance, int minimumDistance, float scale); void SetDefaultName(std::string name); - bool PlayData2D( - const void* data, - const float& x, - const float& y, - const float& z, - int maximumDistance, - int minimumDistance, - float scale - ); + bool PlayData2D(const void* data, const float& x, const float& y, const float& z, int maximumDistance, int minimumDistance, float scale); void PlayStream(const char* name, int loopCount, bool fade); - void PlayWave( - const char* name, - float x, - float y, - float z, - int maximumDistance, - int minimumDistance, - float scale, - int unused - ); + void PlayWave(const char* name, float x, float y, float z, int maximumDistance, int minimumDistance, float scale, int unused); void RestartSecondary(); void SetSampleVolume(int volume); void Set3DVolume(int volume); @@ -129,7 +94,6 @@ private: /* 041C */ SoundMgrContext* m_context; }; -// Global sound manager instance. extern CSoundMgr* g_soundMgr; #if defined(_WIN32) && !defined(_WIN64) diff --git a/Source/Contents/SpriteDrawingPolicy.h b/Source/Contents/SpriteDrawingPolicy.h deleted file mode 100644 index 7e78451..0000000 --- a/Source/Contents/SpriteDrawingPolicy.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_SPRITEDRAWINGPOLICY_H -#define RAGNAROK_SOURCE_CONTENTS_SPRITEDRAWINGPOLICY_H - -class LuaScript; - -// Borrowed sprite-compositor fields. Arguments retain the original script -// order: +0xBC, +0x18, +0x10, +0x40, +0x44. No result is cached here. -struct SpriteDrawingPolicy { - LuaScript& script; - const unsigned char& newDrawOnTop; - int& argument00BC; - const int& argument0018; - const int& argument0010; - const int& argument0040; - const int& argument0044; - bool& helmRobe; - - // Only mode byte 1 selects _New_DrawOnTop; other values use DrawOnTop. - // The original initializes the result true and ignores the call status. - bool DrawOnTop() const; - // Publishes +0xBC before querying the actual TB_Layer_Priority table. - // A failed call retains the prior +0xC0 helm-robe flag. - bool SetRobe(int robe); -}; - -#endif diff --git a/Source/Contents/MCStoreInfoBackup.cpp b/Source/Contents/Store/MCStoreInfoBackup.cpp similarity index 64% rename from Source/Contents/MCStoreInfoBackup.cpp rename to Source/Contents/Store/MCStoreInfoBackup.cpp index f554800..296db12 100644 --- a/Source/Contents/MCStoreInfoBackup.cpp +++ b/Source/Contents/Store/MCStoreInfoBackup.cpp @@ -1,12 +1,11 @@ -#include "Contents/AccountService.h" -#include "Contents/AsyncWorkMgr.h" -#include "Contents/MCStoreInfoBackup.h" +#include "Contents/UserData/AccountService.h" +#include "Contents/Async/AsyncWorkMgr.h" +#include "Contents/Store/MCStoreInfoBackup.h" #include "Contents/MessageTable.h" -#include "Contents/StoreBackupData.h" -#include "Utility/AsyncDiagnostic.h" +#include "Contents/Store/StoreBackupData.h" +#include "Utility/Async/AsyncDiagnostic.h" #include -#include #include #include #include @@ -31,35 +30,25 @@ void CMCStoreInfoBackup::Clear() { // OFFSET: 0x00606BB0 // FUNCTION: fn_04234 -int CMCStoreInfoBackup::Restore( - unsigned char wholeItem, - int maximum, - std::list& inventory, - std::list& storeItems -) { +int CMCStoreInfoBackup::Restore(unsigned char wholeItem, int maximum, std::list& inventory, std::list& storeItems) { auto saved = this->items.begin(); int examined = 0; while (saved != this->items.end() && examined < maximum) { - // Inventory match, including the strict <5 count. const auto found = std::find_if(inventory.begin(), inventory.end(), [&](const ItemInfo& item) { - if ( - item.itemId != saved->itemId || - std::memcmp(item.unknown_001C, saved->unknown_001C, sizeof(item.unknown_001C)) != 0 || - item.identified != saved->identified || item.unknown_0060 != saved->unknown_0060 || - item.unknown_0088 != saved->unknown_0088 || item.unknown_0098 != saved->unknown_0098 - ) { + if (item.itemId != saved->itemId || std::memcmp(item.unknown_001C, saved->unknown_001C, sizeof(item.unknown_001C)) != 0 || + item.identified != saved->identified || item.unknown_0060 != saved->unknown_0060 || item.unknown_0088 != saved->unknown_0088 || + item.unknown_0098 != saved->unknown_0098) { return false; } - const int count = std::bit_cast(item.unknown_0098); + const int count = item.unknown_0098; if (count >= 5) { return false; } - return count <= 0 || - std::memcmp(item.unknown_009C, saved->unknown_009C, static_cast(count) * 5) == 0; + return count <= 0 || std::memcmp(item.unknown_009C, saved->unknown_009C, static_cast(count) * 5) == 0; }); if (found == inventory.end()) { @@ -72,25 +61,19 @@ int CMCStoreInfoBackup::Restore( } if (item.unknown_0000[0] != 0) { - // Adds/merges the selected inventory value, then subtracts quantity or removes the complete identity. - const auto offered = std::find_if(storeItems.begin(), storeItems.end(), [&](const ItemInfo& value) { - return value.unknown_0000[1] == item.unknown_0000[1]; - }); + const auto offered = + std::find_if(storeItems.begin(), storeItems.end(), [&](const ItemInfo& value) { return value.unknown_0000[1] == item.unknown_0000[1]; }); if (offered == storeItems.end()) { storeItems.push_back(item); } else if (wholeItem == 0) { - offered->quantity = std::bit_cast( - static_cast(offered->quantity) + static_cast(item.quantity) - ); + offered->quantity += item.quantity; } if (wholeItem != 0) { inventory.erase(found); } else { - found->quantity = std::bit_cast( - static_cast(found->quantity) - static_cast(item.quantity) - ); + found->quantity -= item.quantity; if (found->quantity <= 0) { inventory.erase(found); @@ -121,13 +104,7 @@ std::string CMCStoreInfoBackup::SaveUrl() const { // OFFSET: 0x006070E0 // FUNCTION: fn_04237 -void CMCStoreInfoBackup::Reset( - LuaScript& settings, - LuaScript& tables, - const char* host, - const char* port, - const char* overrideKey -) { +void CMCStoreInfoBackup::Reset(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey) { this->loaded = false; this->title.clear(); this->items.clear(); @@ -142,12 +119,7 @@ void CMCStoreInfoBackup::Reset( // OFFSET: 0x00605FA0 // FUNCTION: fn_04232 void CMCStoreInfoBackup::CompleteLoad( - AsyncDiagnostic diagnostic, - std::uint32_t, - std::uint32_t, - std::string, - std::string response, - StoreBackupContext& context + AsyncDiagnostic diagnostic, std::uint32_t, std::uint32_t, std::string, std::string response, StoreBackupContext& context ) { if (!diagnostic.success) { return; @@ -197,8 +169,7 @@ void CMCStoreInfoBackup::CompleteSave(AsyncDiagnostic diagnostic, std::string re context.ui.Notify(3, nullptr, 0); if (this->type == 0 || this->type == 1) { - const char* message = - LookupMessage(this->type == 0 ? 3685 : 3686, context.languagePrefix, context.serviceType, context.language); + const char* message = LookupMessage(this->type == 0 ? 3685 : 3686, context.languagePrefix, context.serviceType, context.language); context.ui.Notify(1, message, 0xFFFF); } } @@ -206,12 +177,7 @@ void CMCStoreInfoBackup::CompleteSave(AsyncDiagnostic diagnostic, std::string re // OFFSET: 0x00606DE0 // FUNCTION: fn_04235 void CMCStoreInfoBackup::Load( - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - const char* token16, - int type, - CAsyncWorkMgr& workManager, + std::uint32_t accountId, std::uint32_t characterId, std::string accountName, const char* token16, int type, CAsyncWorkMgr& workManager, StoreBackupContext& context ) { if (accountId == 0 || characterId == 0) { @@ -226,14 +192,8 @@ void CMCStoreInfoBackup::Load( // OFFSET: 0x00606EB0 // FUNCTION: fn_04236 void CMCStoreInfoBackup::Save( - int type, - std::uint32_t accountId, - std::uint32_t characterId, - const char* accountName, - const char* token16, - const std::list& storeItems, - CAsyncWorkMgr& workManager, - StoreBackupContext& context + int type, std::uint32_t accountId, std::uint32_t characterId, const char* accountName, const char* token16, const std::list& storeItems, + CAsyncWorkMgr& workManager, StoreBackupContext& context ) { this->type = type; Json::Value root; diff --git a/Source/Contents/MCStoreInfoBackup.h b/Source/Contents/Store/MCStoreInfoBackup.h similarity index 64% rename from Source/Contents/MCStoreInfoBackup.h rename to Source/Contents/Store/MCStoreInfoBackup.h index 8781d83..d192a82 100644 --- a/Source/Contents/MCStoreInfoBackup.h +++ b/Source/Contents/Store/MCStoreInfoBackup.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_MCSTOREINFOBACKUP_H -#define RAGNAROK_SOURCE_CONTENTS_MCSTOREINFOBACKUP_H +#ifndef RAGNAROK_SOURCE_CONTENTS_STORE_MCSTOREINFOBACKUP_H +#define RAGNAROK_SOURCE_CONTENTS_STORE_MCSTOREINFOBACKUP_H -#include "Contents/ItemInfo.h" -#include "UI/WindowNotifications.h" +#include "Contents/Items/ItemInfo.h" +#include "UI/Window/WindowNotifications.h" #include @@ -35,32 +35,16 @@ public: std::string SaveUrl() const; void Reset(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey); void CompleteLoad( - AsyncDiagnostic diagnostic, - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string response, - StoreBackupContext& context + AsyncDiagnostic diagnostic, std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string response, StoreBackupContext& context ); void CompleteSave(AsyncDiagnostic diagnostic, std::string response, StoreBackupContext& context); void Load( - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - const char* token16, - int type, - CAsyncWorkMgr& workManager, + std::uint32_t accountId, std::uint32_t characterId, std::string accountName, const char* token16, int type, CAsyncWorkMgr& workManager, StoreBackupContext& context ); void Save( - int type, - std::uint32_t accountId, - std::uint32_t characterId, - const char* accountName, - const char* token16, - const std::list& storeItems, - CAsyncWorkMgr& workManager, - StoreBackupContext& context + int type, std::uint32_t accountId, std::uint32_t characterId, const char* accountName, const char* token16, const std::list& storeItems, + CAsyncWorkMgr& workManager, StoreBackupContext& context ); /* 0004 */ bool enabled; diff --git a/Source/Contents/MCStoreInfoBackupAsyncWork.cpp b/Source/Contents/Store/MCStoreInfoBackupAsyncWork.cpp similarity index 76% rename from Source/Contents/MCStoreInfoBackupAsyncWork.cpp rename to Source/Contents/Store/MCStoreInfoBackupAsyncWork.cpp index 0b7e09c..cf1abc5 100644 --- a/Source/Contents/MCStoreInfoBackupAsyncWork.cpp +++ b/Source/Contents/Store/MCStoreInfoBackupAsyncWork.cpp @@ -1,18 +1,17 @@ -#include "Contents/MCStoreInfoBackup.h" -#include "Contents/MCStoreInfoBackupAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/Store/MCStoreInfoBackup.h" +#include "Contents/Store/MCStoreInfoBackupAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { - constexpr char loadSource[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\MCStoreBackUpData\\CMCStoreInfoBackupLoadAsyncWork." - "cpp"; - constexpr char saveSource[] = - "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\MCStoreBackUpData\\CMCStoreInfoBackupSaveAsyncWork." - "cpp"; + constexpr char loadSource[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\MCStoreBackUpData\\CMCStoreInfoBackupLoadAsyncWork." + "cpp"; + constexpr char saveSource[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\MCStoreBackUpData\\CMCStoreInfoBackupSaveAsyncWork." + "cpp"; AsyncDiagnostic Diagnostic(bool success, const char* text, const char* file, std::uint32_t line) { std::string message = text; @@ -23,8 +22,8 @@ namespace { // OFFSET: 0x00607B10 // FUNCTION: fn_04241 CMCStoreInfoBackupLoadAsyncWork::CMCStoreInfoBackupLoadAsyncWork() - : NAsyncWork("MerchantStoreInformation_Load"), m_accountId(0), m_characterId(0), - m_diagnostic(Diagnostic(false, "unknwon", loadSource, 28)), m_type(0), m_owner(nullptr), m_context(nullptr) { + : NAsyncWork("MerchantStoreInformation_Load"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", loadSource, 28)), m_type(0), + m_owner(nullptr), m_context(nullptr) { } // OFFSET: 0x00607EF0 @@ -39,13 +38,7 @@ void CMCStoreInfoBackupLoadAsyncWork::Reset() { // OFFSET: 0x00607FE0 // FUNCTION: fn_04243 void CMCStoreInfoBackupLoadAsyncWork::Bind( - std::string url, - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string token, - int type, - CMCStoreInfoBackup& owner, + std::string url, std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string token, int type, CMCStoreInfoBackup& owner, StoreBackupContext& context ) { this->m_group = timeGetTime(); @@ -91,16 +84,14 @@ bool CMCStoreInfoBackupLoadAsyncWork::Execute() { // OFFSET: 0x00608280 // FUNCTION: fn_04245 void CMCStoreInfoBackupLoadAsyncWork::Complete() { - this->m_owner->CompleteLoad( - this->m_diagnostic, this->m_accountId, this->m_characterId, this->m_accountName, this->m_response, *this->m_context - ); + this->m_owner->CompleteLoad(this->m_diagnostic, this->m_accountId, this->m_characterId, this->m_accountName, this->m_response, *this->m_context); } // OFFSET: 0x00608D60 // FUNCTION: fn_04247 CMCStoreInfoBackupSaveAsyncWork::CMCStoreInfoBackupSaveAsyncWork() - : NAsyncWork("MerchantStoreInformation_Save"), m_accountId(0), m_characterId(0), - m_diagnostic(Diagnostic(false, "unknwon", saveSource, 30)), m_type(0), m_owner(nullptr), m_context(nullptr) { + : NAsyncWork("MerchantStoreInformation_Save"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", saveSource, 30)), m_type(0), + m_owner(nullptr), m_context(nullptr) { } // OFFSET: 0x00609170 @@ -115,15 +106,8 @@ void CMCStoreInfoBackupSaveAsyncWork::Reset() { // OFFSET: 0x00609270 // FUNCTION: fn_04249 void CMCStoreInfoBackupSaveAsyncWork::Bind( - std::string url, - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string token, - std::string data, - int type, - CMCStoreInfoBackup& owner, - StoreBackupContext& context + std::string url, std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string token, std::string data, int type, + CMCStoreInfoBackup& owner, StoreBackupContext& context ) { this->m_group = timeGetTime(); this->m_accountId = accountId; @@ -161,6 +145,7 @@ bool CMCStoreInfoBackupSaveAsyncWork::Execute() { AsyncDiagnostic diagnostic = Diagnostic(success, success ? "good" : "fail", saveSource, success ? 122 : 112); this->m_diagnostic.MoveFrom(diagnostic); this->m_response = handler.Response(); + return false; } diff --git a/Source/Contents/MCStoreInfoBackupAsyncWork.h b/Source/Contents/Store/MCStoreInfoBackupAsyncWork.h similarity index 67% rename from Source/Contents/MCStoreInfoBackupAsyncWork.h rename to Source/Contents/Store/MCStoreInfoBackupAsyncWork.h index 116cd06..ea783d3 100644 --- a/Source/Contents/MCStoreInfoBackupAsyncWork.h +++ b/Source/Contents/Store/MCStoreInfoBackupAsyncWork.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_MCSTOREINFOBACKUPASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_MCSTOREINFOBACKUPASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_STORE_MCSTOREINFOBACKUPASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_STORE_MCSTOREINFOBACKUPASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class CMCStoreInfoBackup; struct StoreBackupContext; @@ -15,13 +15,7 @@ public: bool Execute() override; void Complete() override; void Bind( - std::string url, - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string token, - int type, - CMCStoreInfoBackup& owner, + std::string url, std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string token, int type, CMCStoreInfoBackup& owner, StoreBackupContext& context ); @@ -34,7 +28,7 @@ protected: /* 0078 */ std::string m_response; /* 0090 */ AsyncDiagnostic m_diagnostic; /* 00C8 */ int m_type; - // Host bindings for the original global owner and UI state. + CMCStoreInfoBackup* m_owner; StoreBackupContext* m_context; }; @@ -47,15 +41,8 @@ public: bool Execute() override; void Complete() override; void Bind( - std::string url, - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string token, - std::string data, - int type, - CMCStoreInfoBackup& owner, - StoreBackupContext& context + std::string url, std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string token, std::string data, int type, + CMCStoreInfoBackup& owner, StoreBackupContext& context ); protected: @@ -68,7 +55,7 @@ protected: /* 0090 */ AsyncDiagnostic m_diagnostic; /* 00C8 */ std::string m_response; /* 00E0 */ int m_type; - // Host bindings; original x86 work objects end before these fields. + CMCStoreInfoBackup* m_owner; StoreBackupContext* m_context; }; diff --git a/Source/Contents/StoreBackupData.cpp b/Source/Contents/Store/StoreBackupData.cpp similarity index 82% rename from Source/Contents/StoreBackupData.cpp rename to Source/Contents/Store/StoreBackupData.cpp index c963663..2781ff6 100644 --- a/Source/Contents/StoreBackupData.cpp +++ b/Source/Contents/Store/StoreBackupData.cpp @@ -1,7 +1,6 @@ -#include "Contents/StoreBackupData.h" +#include "Contents/Store/StoreBackupData.h" #include "Network/TextEncoding.h" -#include #include #include #include @@ -25,8 +24,8 @@ void StoreBackupData::Import(Json::Value& data) { item.itemId = std::to_string(value.get("ID", 0).asInt()); item.quantity = value.get("Count", 0).asInt(); item.identified = value.get("Identified", 0).asBool(); - item.unknown_0060 = static_cast(value.get("RefiningLevel", 0).asInt()); - item.unknown_0088 = std::bit_cast(static_cast(value.get("GradeLevel", 0).asInt())); + item.unknown_0060 = value.get("RefiningLevel", 0).asInt(); + item.unknown_0088 = static_cast(value.get("GradeLevel", 0).asInt()); const char* slotKeys[] = {"Slot_1", "Slot_2", "Slot_3", "Slot_4"}; @@ -35,7 +34,7 @@ void StoreBackupData::Import(Json::Value& data) { std::memcpy(item.unknown_001C + 4 * index, &slot, sizeof(slot)); } - item.unknown_0098 = static_cast(value.get("RandomOptionCount", 0).asInt()); + item.unknown_0098 = value.get("RandomOptionCount", 0).asInt(); Json::Value& options = value["RandomOptionList"]; unsigned index = 0; @@ -44,7 +43,7 @@ void StoreBackupData::Import(Json::Value& data) { const auto amount = static_cast((*option).get("Value", 0).asInt()); const auto parameter = static_cast((*option).get("Parm1", 0).asInt()); auto* record = reinterpret_cast(&item) + offsetof(ItemInfo, unknown_009C) + index * 5; - // Original accepts six records, spilling the sixth into +0xB5..+0xB9. + std::memcpy(record, &id, sizeof(id)); std::memcpy(record + 2, &amount, sizeof(amount)); record[4] = parameter; @@ -66,7 +65,7 @@ void StoreBackupData::Export(Json::Value& data, const std::list& store value["ID"] = std::atoi(item.itemId.c_str()); value["Count"] = item.quantity; value["Identified"] = item.identified != 0; - value["RefiningLevel"] = std::bit_cast(item.unknown_0060); + value["RefiningLevel"] = item.unknown_0060; value["GradeLevel"] = item.unknown_0088; const char* slotKeys[] = {"Slot_1", "Slot_2", "Slot_3", "Slot_4"}; @@ -76,7 +75,7 @@ void StoreBackupData::Export(Json::Value& data, const std::list& store value[slotKeys[index]] = slot; } - const int count = std::bit_cast(item.unknown_0098); + const int count = item.unknown_0098; value["RandomOptionCount"] = count; Json::Value options; @@ -93,7 +92,7 @@ void StoreBackupData::Export(Json::Value& data, const std::list& store } value["RandomOptionList"] = options; - value["Price"] = std::bit_cast(item.unknown_0014[0]); + value["Price"] = static_cast(item.unknown_0014[0]); values.append(value); } diff --git a/Source/Contents/Store/StoreBackupData.h b/Source/Contents/Store/StoreBackupData.h new file mode 100644 index 0000000..a883691 --- /dev/null +++ b/Source/Contents/Store/StoreBackupData.h @@ -0,0 +1,21 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_STORE_STOREBACKUPDATA_H +#define RAGNAROK_SOURCE_CONTENTS_STORE_STOREBACKUPDATA_H + +#include "Contents/Items/ItemInfo.h" + +#include +#include + +namespace Json { + class Value; +} + +struct StoreBackupData { + std::string& title; + std::vector& items; + + void Import(Json::Value& data); + void Export(Json::Value& data, const std::list& storeItems) const; +}; + +#endif diff --git a/Source/Contents/StoreBackupData.h b/Source/Contents/StoreBackupData.h deleted file mode 100644 index dd02dc1..0000000 --- a/Source/Contents/StoreBackupData.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_STOREBACKUPDATA_H -#define RAGNAROK_SOURCE_CONTENTS_STOREBACKUPDATA_H - -#include "Contents/ItemInfo.h" - -#include -#include - -namespace Json { - class Value; -} - -// The title and vector belong to CMCStoreInfoBackup (+0x3C and +0x58). -// Serialization only; applying restored items to an open shop remains UI work. -struct StoreBackupData { - std::string& title; - std::vector& items; - - void Import(Json::Value& data); - void Export(Json::Value& data, const std::list& storeItems) const; -}; - -#endif diff --git a/Source/Contents/TerrainPicking.cpp b/Source/Contents/TerrainPicking.cpp deleted file mode 100644 index 5829993..0000000 --- a/Source/Contents/TerrainPicking.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "Contents/TerrainHeight.h" -#include "Utility/RayTriangle.h" - -#include -#include - -// OFFSET: 0x00749300 -// FUNCTION: fn_07842 -float TerrainHeight::RayDistance(const float* ray, int column, int row) const { - const TerrainHeightCell* cell = this->CellAt(column, row); - - if (!cell) { - return 0.0f; - } - - const float size = static_cast(this->cellSize); - const auto x = static_cast(column) - static_cast(this->width / 2); - const auto z = static_cast(row) - static_cast(this->height / 2); - const float left = static_cast(std::bit_cast(x)) * size; - const float right = static_cast(std::bit_cast(x + 1u)) * size; - const float top = static_cast(std::bit_cast(z)) * size; - const float bottom = static_cast(std::bit_cast(z + 1u)) * size; - const float first[3] = {left, cell->heights[0], top}; - const float second[3] = {right, cell->heights[1], top}; - const float third[3] = {left, cell->heights[2], bottom}; - const float fourth[3] = {right, cell->heights[3], bottom}; - float nearest = 999999.0f; - float u; - float v; - float distance; - - if (IntersectRayTriangle(ray, first, second, third, u, v, distance)) { - nearest = _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(distance), _mm_set_ss(nearest))); - } - - if (IntersectRayTriangle(ray, second, fourth, third, u, v, distance)) { - nearest = _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(distance), _mm_set_ss(nearest))); - } - - return nearest; -} diff --git a/Source/Contents/TerrainPlane.cpp b/Source/Contents/TerrainPlane.cpp deleted file mode 100644 index d3f20cd..0000000 --- a/Source/Contents/TerrainPlane.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "Contents/TerrainHeight.h" - -#include -#include - -// OFFSET: 0x00749040 -// FUNCTION: fn_07840 -float TerrainHeight::PlaneHeight(float x, float z) const { - const float size = static_cast(this->cellSize); - const int columns = this->width; - const int rows = this->height; - const int column = _mm_cvttss_si32(_mm_set_ss(((static_cast(columns) * size) * 0.5f + x) / size)); - const int row = _mm_cvttss_si32(_mm_set_ss(((static_cast(rows) * size) * 0.5f + z) / size)); - const TerrainHeightCell* cell = this->CellAt(column, row); - - if (!cell) { - return 0.0f; - } - - const auto dx = static_cast(column) - static_cast(columns / 2); - const auto dz = static_cast(row) - static_cast(rows / 2); - const float left = static_cast(std::bit_cast(dx)) * size; - const float right = static_cast(std::bit_cast(dx + 1u)) * size; - const float top = static_cast(std::bit_cast(dz)) * size; - const float bottom = static_cast(std::bit_cast(dz + 1u)) * size; - const float first = cell->heights[0]; - const float second = cell->heights[1]; - const float third = cell->heights[2]; - - // Keep cancelling terms and both negative multiplications: they are - // observable for nonfinite values and rounded scalar intermediates. - const float xTerm = (((bottom - top) * second + (top - bottom) * first) + (top - top) * third) * x; - const float zTerm = (((third - first) * right + (second - third) * left) + (first - second) * left) * z; - const float constant = (((top * third - bottom * first) * right + (bottom * second - top * third) * left) + - (top * first - top * second) * left) * - -1.0f; - const float numerator = ((xTerm + zTerm) + constant) * -1.0f; - const float denominator = ((right - left) * top + (left - left) * top) + (left - right) * bottom; - return numerator / denominator; -} diff --git a/Source/Contents/TipBoxTitles.cpp b/Source/Contents/TipBoxTitles.cpp index d77506a..1e0d625 100644 --- a/Source/Contents/TipBoxTitles.cpp +++ b/Source/Contents/TipBoxTitles.cpp @@ -20,8 +20,6 @@ namespace { current = CharNextExA(codePage, current, 0); } - - // Original intentionally does not append the final partial segment. } } diff --git a/Source/Contents/TipBoxTitles.h b/Source/Contents/TipBoxTitles.h index 2f78cb4..b66400b 100644 --- a/Source/Contents/TipBoxTitles.h +++ b/Source/Contents/TipBoxTitles.h @@ -6,7 +6,6 @@ #include #include -// Original CTipBoxMgr map value. Unidentified scalar fields stay explicit. struct TipBoxEntry { TipBoxEntry(); std::string title; @@ -19,7 +18,6 @@ struct TipBoxEntry { std::int32_t unknown_004C[3]; }; -// Borrow actual CTipBoxMgr table+16, missing value+188 and upper bound+280. struct TipBoxTitles { const std::map& entries; const TipBoxEntry& missing; diff --git a/Source/Contents/AccountConfigLoad.h b/Source/Contents/UserData/AccountConfigLoad.h similarity index 65% rename from Source/Contents/AccountConfigLoad.h rename to Source/Contents/UserData/AccountConfigLoad.h index 21785c4..358193a 100644 --- a/Source/Contents/AccountConfigLoad.h +++ b/Source/Contents/UserData/AccountConfigLoad.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ACCOUNTCONFIGLOAD_H -#define RAGNAROK_SOURCE_CONTENTS_ACCOUNTCONFIGLOAD_H +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTCONFIGLOAD_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTCONFIGLOAD_H #include @@ -7,7 +7,6 @@ struct EmotionHotkeys; class LuaScript; class CRenderSystemBase; -// Original client/script/locale state, borrowed through queued completion. struct AccountConfigLoad { EmotionHotkeys& emotions; LuaScript& script; diff --git a/Source/Contents/AccountLinkedUserDataLoadAsyncWork.cpp b/Source/Contents/UserData/AccountLinkedUserDataLoadAsyncWork.cpp similarity index 75% rename from Source/Contents/AccountLinkedUserDataLoadAsyncWork.cpp rename to Source/Contents/UserData/AccountLinkedUserDataLoadAsyncWork.cpp index b23e41f..cd3df28 100644 --- a/Source/Contents/AccountLinkedUserDataLoadAsyncWork.cpp +++ b/Source/Contents/UserData/AccountLinkedUserDataLoadAsyncWork.cpp @@ -1,11 +1,12 @@ -#include "Contents/AccountConfigLoad.h" -#include "Contents/AccountLinkedUserDataLoadAsyncWork.h" -#include "Contents/AccountLinkedUserDataMgr.h" -#include "Network/CURLPostHander.h" +#include "Contents/UserData/AccountConfigLoad.h" +#include "Contents/UserData/AccountLinkedUserDataLoadAsyncWork.h" +#include "Contents/UserData/AccountLinkedUserDataMgr.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { constexpr char sourceFile[] = "C:" @@ -21,11 +22,9 @@ namespace { // OFFSET: 0x005B9E50 // FUNCTION: fn_03440 CAccountLinkedUserDataLoadAsyncWork::CAccountLinkedUserDataLoadAsyncWork() - : NAsyncWork("AccountLinkedUserData_Load"), m_accountId(0), m_diagnostic(Diagnostic(false, "unknwon", 26)), - m_context(nullptr) { + : NAsyncWork("AccountLinkedUserData_Load"), m_accountId(0), m_diagnostic(Diagnostic(false, "unknwon", 26)), m_context(nullptr) { } -// Deleting entry. // OFFSET: 0x005BA410 // FUNCTION: fn_03442 CAccountLinkedUserDataLoadAsyncWork::~CAccountLinkedUserDataLoadAsyncWork() = default; @@ -37,12 +36,7 @@ void CAccountLinkedUserDataLoadAsyncWork::Reset() { // OFFSET: 0x005BA5D0 // FUNCTION: fn_03445 -void CAccountLinkedUserDataLoadAsyncWork::Bind( - std::uint32_t accountId, - std::string accountName, - std::string url, - AccountConfigLoad& context -) { +void CAccountLinkedUserDataLoadAsyncWork::Bind(std::uint32_t accountId, std::string accountName, std::string url, AccountConfigLoad& context) { this->m_group = timeGetTime(); this->m_accountId = accountId; this->m_key = 0; @@ -67,7 +61,6 @@ bool CAccountLinkedUserDataLoadAsyncWork::Execute() { handler.AddField("WorldName", name, 4); if (handler.Perform() == 0) { - // Unlike character load, account load passes UTF-8 JSON through unchanged. this->m_response = handler.Response(); AsyncDiagnostic diagnostic = Diagnostic(true, "good", 92); this->m_diagnostic.MoveFrom(diagnostic); @@ -80,7 +73,7 @@ bool CAccountLinkedUserDataLoadAsyncWork::Execute() { // FUNCTION: fn_03447 void CAccountLinkedUserDataLoadAsyncWork::Complete() { g_accountLinkedUserDataMgr->CompleteLoad( - this->m_diagnostic, this->m_accountId, this->m_accountName, this->m_response, this->m_context->emotions, - this->m_context->script, this->m_context->persistenceAccountId, this->m_context->renderSystem + this->m_diagnostic, this->m_accountId, this->m_accountName, this->m_response, this->m_context->emotions, this->m_context->script, + this->m_context->persistenceAccountId, this->m_context->renderSystem ); } diff --git a/Source/Contents/AccountLinkedUserDataLoadAsyncWork.h b/Source/Contents/UserData/AccountLinkedUserDataLoadAsyncWork.h similarity index 67% rename from Source/Contents/AccountLinkedUserDataLoadAsyncWork.h rename to Source/Contents/UserData/AccountLinkedUserDataLoadAsyncWork.h index c486456..ede71d2 100644 --- a/Source/Contents/AccountLinkedUserDataLoadAsyncWork.h +++ b/Source/Contents/UserData/AccountLinkedUserDataLoadAsyncWork.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ACCOUNTLINKEDUSERDATALOADASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_ACCOUNTLINKEDUSERDATALOADASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTLINKEDUSERDATALOADASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTLINKEDUSERDATALOADASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" struct AccountConfigLoad; @@ -22,8 +22,6 @@ protected: /* 005C */ std::string m_response; /* 0074 */ AsyncDiagnostic m_diagnostic; - // Host binding replaces original completion's global owner reads. Original - // allocation is 176 bytes; this pointer occupies the x86 alignment tail. AccountConfigLoad* m_context; }; diff --git a/Source/Contents/AccountLinkedUserDataMgr.cpp b/Source/Contents/UserData/AccountLinkedUserDataMgr.cpp similarity index 69% rename from Source/Contents/AccountLinkedUserDataMgr.cpp rename to Source/Contents/UserData/AccountLinkedUserDataMgr.cpp index 55edaf0..7440fec 100644 --- a/Source/Contents/AccountLinkedUserDataMgr.cpp +++ b/Source/Contents/UserData/AccountLinkedUserDataMgr.cpp @@ -1,12 +1,12 @@ -#include "Contents/AccountConfigLoad.h" -#include "Contents/AccountLinkedUserDataMgr.h" -#include "Contents/AccountService.h" -#include "Contents/AccountUserData.h" -#include "Contents/AsyncWorkMgr.h" -#include "Contents/EmotionHotkeys.h" -#include "Contents/UserHotkeyMgr.h" -#include "Contents/WhisperBlockMgr.h" -#include "Utility/AsyncDiagnostic.h" +#include "Contents/UserData/AccountConfigLoad.h" +#include "Contents/UserData/AccountLinkedUserDataMgr.h" +#include "Contents/UserData/AccountService.h" +#include "Contents/UserData/AccountUserData.h" +#include "Contents/Async/AsyncWorkMgr.h" +#include "Contents/Hotkeys/EmotionHotkeys.h" +#include "Contents/Hotkeys/UserHotkeyMgr.h" +#include "Contents/Messenger/WhisperBlockMgr.h" +#include "Utility/Async/AsyncDiagnostic.h" #include #include @@ -18,8 +18,7 @@ CAccountLinkedUserDataMgr* g_accountLinkedUserDataMgr; // OFFSET: 0x005BBF50 // FUNCTION: fn_03459 -CAccountLinkedUserDataMgr::CAccountLinkedUserDataMgr() - : m_enabled(true), m_accountId(0), m_accountName("unknown"), m_loaded(false), unknown_0028(0) { +CAccountLinkedUserDataMgr::CAccountLinkedUserDataMgr() : m_enabled(true), m_accountId(0), m_accountName("unknown"), m_loaded(false), unknown_0028(0) { } // OFFSET: 0x005BBDB0 @@ -32,15 +31,18 @@ bool CAccountLinkedUserDataMgr::Initialize() { if (g_accountLinkedUserDataMgr) { return false; } + g_accountLinkedUserDataMgr = new (std::nothrow) CAccountLinkedUserDataMgr; if (!g_accountLinkedUserDataMgr) { return false; } + if (!g_accountLinkedUserDataMgr->m_enabled) { delete g_accountLinkedUserDataMgr; g_accountLinkedUserDataMgr = nullptr; return false; } + return true; } @@ -68,14 +70,8 @@ std::string CAccountLinkedUserDataMgr::SaveUrl() const { // OFFSET: 0x005BC520 // FUNCTION: fn_03465 void CAccountLinkedUserDataMgr::CompleteLoad( - AsyncDiagnostic diagnostic, - std::uint32_t accountId, - std::string accountName, - std::string response, - EmotionHotkeys& emotions, - LuaScript& script, - std::uint32_t persistenceAccountId, - CRenderSystemBase* renderSystem + AsyncDiagnostic diagnostic, std::uint32_t accountId, std::string accountName, std::string response, EmotionHotkeys& emotions, LuaScript& script, + std::uint32_t persistenceAccountId, CRenderSystemBase* renderSystem ) { if (diagnostic.success && this->m_accountId == 0) { Json::Value root; @@ -87,6 +83,7 @@ void CAccountLinkedUserDataMgr::CompleteLoad( emotions.Load(root["data"]); g_userHotkeyMgr->LoadV2(script, root["data"]); } + if (type == 1 || type == 2) { g_whisperBlockMgr->m_tracking = true; g_userHotkeyMgr->m_loaded = true; @@ -101,13 +98,7 @@ void CAccountLinkedUserDataMgr::CompleteLoad( // OFFSET: 0x005BCB10 // FUNCTION: fn_03467 -void CAccountLinkedUserDataMgr::RefreshUrls( - LuaScript& settings, - LuaScript& tables, - const char* host, - const char* port, - const char* overrideKey -) { +void CAccountLinkedUserDataMgr::RefreshUrls(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey) { const std::string base = ResolveAccountServiceBase(settings, tables, host, port, overrideKey); if (!base.empty()) { this->m_saveUrl = base + "/userconfig/save"; @@ -117,13 +108,7 @@ void CAccountLinkedUserDataMgr::RefreshUrls( // OFFSET: 0x005BD170 // FUNCTION: fn_03470 -void CAccountLinkedUserDataMgr::Reset( - EmotionHotkeys& emotions, - LuaScript& script, - const char* host, - const char* port, - const char* overrideKey -) { +void CAccountLinkedUserDataMgr::Reset(EmotionHotkeys& emotions, LuaScript& script, const char* host, const char* port, const char* overrideKey) { this->m_accountId = 0; this->m_accountName = "unknown"; this->m_loaded = false; @@ -142,17 +127,14 @@ void CAccountLinkedUserDataMgr::CompleteSave() { // OFFSET: 0x005BCE50 // FUNCTION: fn_03469 void CAccountLinkedUserDataMgr::Save( - EmotionHotkeys& emotions, - LuaScript& script, - std::uint32_t persistenceAccountId, - CRenderSystemBase* renderSystem, - const char* token16, + EmotionHotkeys& emotions, LuaScript& script, std::uint32_t persistenceAccountId, CRenderSystemBase* renderSystem, const char* token16, CAsyncWorkMgr& workManager ) { emotions.Save(persistenceAccountId, renderSystem); if (!this->m_loaded) { return; } + Json::Value root; Json::Value data; if (static_cast(g_whisperBlockMgr->m_changes) > 0) { @@ -160,34 +142,28 @@ void CAccountLinkedUserDataMgr::Save( g_whisperBlockMgr->Export(values); data["WhisperBlockList"] = values; } + if (emotions.HasChanges()) { emotions.Export(data); } + if (g_userHotkeyMgr->HasChanges(script)) { g_userHotkeyMgr->Export(script, data); } + if (!data.isNull()) { root["data"] = data; Json::StyledWriter writer; const std::string response = writer.write(root); - workManager.SaveAccount( - this->m_accountId, this->m_accountName, this->SaveUrl(), std::string(token16, 16), response - ); + workManager.SaveAccount(this->m_accountId, this->m_accountName, this->SaveUrl(), std::string(token16, 16), response); ++this->unknown_0028; } } // OFFSET: 0x005BCD80 // FUNCTION: fn_03468 -void CAccountLinkedUserDataMgr::Load( - std::uint32_t accountId, - std::string accountName, - CAsyncWorkMgr& workManager, - AccountConfigLoad& context -) { - context.emotions.LoadDefaults( - context.persistenceAccountId, context.languagePrefix, context.serviceType, context.language - ); +void CAccountLinkedUserDataMgr::Load(std::uint32_t accountId, std::string accountName, CAsyncWorkMgr& workManager, AccountConfigLoad& context) { + context.emotions.LoadDefaults(context.persistenceAccountId, context.languagePrefix, context.serviceType, context.language); if (this->m_accountId == accountId && this->m_accountName == accountName) { return; diff --git a/Source/Contents/AccountLinkedUserDataMgr.h b/Source/Contents/UserData/AccountLinkedUserDataMgr.h similarity index 66% rename from Source/Contents/AccountLinkedUserDataMgr.h rename to Source/Contents/UserData/AccountLinkedUserDataMgr.h index 4082a85..5a1f5cb 100644 --- a/Source/Contents/AccountLinkedUserDataMgr.h +++ b/Source/Contents/UserData/AccountLinkedUserDataMgr.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ACCOUNTLINKEDUSERDATAMGR_H -#define RAGNAROK_SOURCE_CONTENTS_ACCOUNTLINKEDUSERDATAMGR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTLINKEDUSERDATAMGR_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTLINKEDUSERDATAMGR_H #include #include @@ -20,27 +20,16 @@ public: std::string SaveUrl() const; std::string LoadUrl() const; void RefreshUrls(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey); - // Explicit original client-state/script/render-owner dependencies; these - // parameters do not establish a replacement application-global lifecycle. + void CompleteLoad( - AsyncDiagnostic diagnostic, - std::uint32_t accountId, - std::string accountName, - std::string response, - EmotionHotkeys& emotions, - LuaScript& script, - std::uint32_t persistenceAccountId, - CRenderSystemBase* renderSystem + AsyncDiagnostic diagnostic, std::uint32_t accountId, std::string accountName, std::string response, EmotionHotkeys& emotions, LuaScript& script, + std::uint32_t persistenceAccountId, CRenderSystemBase* renderSystem ); void Load(std::uint32_t accountId, std::string accountName, CAsyncWorkMgr& workManager, AccountConfigLoad& context); void Reset(EmotionHotkeys& emotions, LuaScript& script, const char* host, const char* port, const char* overrideKey); void CompleteSave(); void Save( - EmotionHotkeys& emotions, - LuaScript& script, - std::uint32_t persistenceAccountId, - CRenderSystemBase* renderSystem, - const char* token16, + EmotionHotkeys& emotions, LuaScript& script, std::uint32_t persistenceAccountId, CRenderSystemBase* renderSystem, const char* token16, CAsyncWorkMgr& workManager ); diff --git a/Source/Contents/AccountLinkedUserDataSaveAsyncWork.cpp b/Source/Contents/UserData/AccountLinkedUserDataSaveAsyncWork.cpp similarity index 83% rename from Source/Contents/AccountLinkedUserDataSaveAsyncWork.cpp rename to Source/Contents/UserData/AccountLinkedUserDataSaveAsyncWork.cpp index 2e58906..40bdd11 100644 --- a/Source/Contents/AccountLinkedUserDataSaveAsyncWork.cpp +++ b/Source/Contents/UserData/AccountLinkedUserDataSaveAsyncWork.cpp @@ -1,16 +1,17 @@ -#include "Contents/AccountLinkedUserDataMgr.h" -#include "Contents/AccountLinkedUserDataSaveAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/UserData/AccountLinkedUserDataMgr.h" +#include "Contents/UserData/AccountLinkedUserDataSaveAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { - // Original diagnostic provenance, not the reconstructed host file path. constexpr char sourceFile[] = "C:" "\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\AccountLinkedUserData\\CAcco" "untLinkedUserDataSaveAsyncWork.cpp"; + AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; return AsyncDiagnostic(&success, &message, sourceFile, &line); @@ -23,7 +24,6 @@ CAccountLinkedUserDataSaveAsyncWork::CAccountLinkedUserDataSaveAsyncWork() : NAsyncWork("AccountLinkedUserData_Save"), m_accountId(0), m_diagnostic(Diagnostic(false, "unknwon", 26)) { } -// Deleting entry. // OFFSET: 0x005BDE60 // FUNCTION: fn_03479 CAccountLinkedUserDataSaveAsyncWork::~CAccountLinkedUserDataSaveAsyncWork() = default; @@ -35,13 +35,7 @@ void CAccountLinkedUserDataSaveAsyncWork::Reset() { // OFFSET: 0x005BDF50 // FUNCTION: fn_03480 -void CAccountLinkedUserDataSaveAsyncWork::Bind( - std::uint32_t accountId, - std::string accountName, - std::string url, - std::string token, - std::string data -) { +void CAccountLinkedUserDataSaveAsyncWork::Bind(std::uint32_t accountId, std::string accountName, std::string url, std::string token, std::string data) { this->m_group = timeGetTime(); this->m_key = 0; this->m_accountId = accountId; @@ -67,6 +61,7 @@ bool CAccountLinkedUserDataSaveAsyncWork::Execute() { const bool success = handler.Perform() == 0; AsyncDiagnostic diagnostic = Diagnostic(success, success ? "good" : "fail", success ? 106 : 102); this->m_diagnostic.MoveFrom(diagnostic); + return false; } diff --git a/Source/Contents/AccountLinkedUserDataSaveAsyncWork.h b/Source/Contents/UserData/AccountLinkedUserDataSaveAsyncWork.h similarity index 71% rename from Source/Contents/AccountLinkedUserDataSaveAsyncWork.h rename to Source/Contents/UserData/AccountLinkedUserDataSaveAsyncWork.h index f7a8c05..b70da6c 100644 --- a/Source/Contents/AccountLinkedUserDataSaveAsyncWork.h +++ b/Source/Contents/UserData/AccountLinkedUserDataSaveAsyncWork.h @@ -1,10 +1,9 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_ACCOUNTLINKEDUSERDATASAVEASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_ACCOUNTLINKEDUSERDATASAVEASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTLINKEDUSERDATASAVEASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTLINKEDUSERDATASAVEASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" -// Original pool/deleting entries allocate/free 200 bytes; no extra tail field. class alignas(8) CAccountLinkedUserDataSaveAsyncWork : public NAsyncWork { public: CAccountLinkedUserDataSaveAsyncWork(); diff --git a/Source/Contents/AccountService.cpp b/Source/Contents/UserData/AccountService.cpp similarity index 54% rename from Source/Contents/AccountService.cpp rename to Source/Contents/UserData/AccountService.cpp index a94ba1f..6073a7f 100644 --- a/Source/Contents/AccountService.cpp +++ b/Source/Contents/UserData/AccountService.cpp @@ -1,28 +1,23 @@ -#include "Contents/AccountService.h" +#include "Contents/UserData/AccountService.h" #include "Script/LuaScript.h" // OFFSET: 0x00DDBB60 // FUNCTION: fn_23360 -std::string ResolveAccountServiceBase( - LuaScript& settings, - LuaScript& tables, - const char* host, - const char* port, - const char* overrideKey -) { +std::string ResolveAccountServiceBase(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey) { std::string address = settings.GlobalString("AssistAddr"); if (!address.empty()) { return address; } + std::string key = std::string(host) + ":" + port; if (overrideKey && *overrideKey) { key = overrideKey; } + const char* resolved = nullptr; - if ( - tables.Call("GetTableStringValueForC", "ss>s", "AssistAddrTbl", key.c_str(), &resolved) && resolved && *resolved - ) { + if (tables.Call("GetTableStringValueForC", "ss>s", "AssistAddrTbl", key.c_str(), &resolved) && resolved && *resolved) { return resolved; } + return {}; } diff --git a/Source/Contents/UserData/AccountService.h b/Source/Contents/UserData/AccountService.h new file mode 100644 index 0000000..596f2ec --- /dev/null +++ b/Source/Contents/UserData/AccountService.h @@ -0,0 +1,10 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTSERVICE_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTSERVICE_H + +#include + +class LuaScript; + +std::string ResolveAccountServiceBase(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey); + +#endif diff --git a/Source/Contents/AccountUserData.cpp b/Source/Contents/UserData/AccountUserData.cpp similarity index 77% rename from Source/Contents/AccountUserData.cpp rename to Source/Contents/UserData/AccountUserData.cpp index 9dbfecb..61c931e 100644 --- a/Source/Contents/AccountUserData.cpp +++ b/Source/Contents/UserData/AccountUserData.cpp @@ -1,11 +1,12 @@ -#include "Contents/AccountUserData.h" -#include "Contents/WhisperBlockMgr.h" +#include "Contents/UserData/AccountUserData.h" +#include "Contents/Messenger/WhisperBlockMgr.h" #include "Network/TextEncoding.h" // OFFSET: 0x005BC950 // FUNCTION: fn_03466 void LoadWhisperBlockList(Json::Value& data) { Json::Value names = data["WhisperBlockList"]; + for (Json::UInt i = 0; i < names.size(); ++i) { std::string name = FromUtf8(names[i].asString(), g_textCodePage); g_whisperBlockMgr->Add(name); diff --git a/Source/Contents/UserData/AccountUserData.h b/Source/Contents/UserData/AccountUserData.h new file mode 100644 index 0000000..39de1df --- /dev/null +++ b/Source/Contents/UserData/AccountUserData.h @@ -0,0 +1,8 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTUSERDATA_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_ACCOUNTUSERDATA_H + +#include + +void LoadWhisperBlockList(Json::Value& data); + +#endif diff --git a/Source/Contents/CharacterConfigLoad.cpp b/Source/Contents/UserData/CharacterConfigLoad.cpp similarity index 63% rename from Source/Contents/CharacterConfigLoad.cpp rename to Source/Contents/UserData/CharacterConfigLoad.cpp index e37109e..132b74a 100644 --- a/Source/Contents/CharacterConfigLoad.cpp +++ b/Source/Contents/UserData/CharacterConfigLoad.cpp @@ -1,12 +1,12 @@ #include "Client/ClientOptions.h" -#include "Contents/AsyncWorkMgr.h" -#include "Contents/CharacterConfigLoad.h" -#include "Contents/CharacterLinkedUserDataMgr.h" -#include "Contents/ServiceOptions.h" -#include "Contents/SkillLevelConfig.h" -#include "Contents/SkillLevelRegistry.h" -#include "UI/NormalItemSlotLoad.h" -#include "Utility/AsyncDiagnostic.h" +#include "Contents/Async/AsyncWorkMgr.h" +#include "Contents/UserData/CharacterConfigLoad.h" +#include "Contents/UserData/CharacterLinkedUserDataMgr.h" +#include "Contents/Configuration/ServiceOptions.h" +#include "Contents/Skills/SkillLevelConfig.h" +#include "Contents/Skills/SkillLevelRegistry.h" +#include "UI/Shortcuts/NormalItemSlotLoad.h" +#include "Utility/Async/AsyncDiagnostic.h" #include #include @@ -14,12 +14,7 @@ // OFFSET: 0x005E6090 // FUNCTION: fn_03927 void CCharacterLinkedUserDataMgr::CompleteLoad( - AsyncDiagnostic diagnostic, - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string response, - CharacterConfigLoad& context + AsyncDiagnostic diagnostic, std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string response, CharacterConfigLoad& context ) { if (!diagnostic.success) { return; @@ -51,13 +46,10 @@ void CCharacterLinkedUserDataMgr::CompleteLoad( const Json::Value sorting = data["SortPrivateTab"]; context.sortPrivate = sorting.isNull() ? false : sorting.asBool(); - LoadNormalItemSlots( - data, context.items, context.saved, context.itemSlotActive, context.windows, context.visibility - ); + LoadNormalItemSlots(data, context.items, context.saved, context.itemSlotActive, context.windows, context.visibility); this->m_loaded = true; } - // Every successfully parsed response updates identity, even an unknown Type. this->m_accountId = accountId; this->m_characterId = characterId; this->m_accountName = accountName; @@ -66,12 +58,7 @@ void CCharacterLinkedUserDataMgr::CompleteLoad( // OFFSET: 0x005E6E20 // FUNCTION: fn_03932 void CCharacterLinkedUserDataMgr::Load( - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - const char* token16, - CAsyncWorkMgr& workManager, - CharacterConfigLoad& context + std::uint32_t accountId, std::uint32_t characterId, std::string accountName, const char* token16, CAsyncWorkMgr& workManager, CharacterConfigLoad& context ) { if (accountId == 0 || characterId == 0) { return; diff --git a/Source/Contents/CharacterConfigLoad.h b/Source/Contents/UserData/CharacterConfigLoad.h similarity index 80% rename from Source/Contents/CharacterConfigLoad.h rename to Source/Contents/UserData/CharacterConfigLoad.h index a0e1ca4..eba4e7d 100644 --- a/Source/Contents/CharacterConfigLoad.h +++ b/Source/Contents/UserData/CharacterConfigLoad.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CHARACTERCONFIGLOAD_H -#define RAGNAROK_SOURCE_CONTENTS_CHARACTERCONFIGLOAD_H +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERCONFIGLOAD_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERCONFIGLOAD_H struct NormalItemSlot; struct NormalItemSlotWindow; diff --git a/Source/Contents/CharacterConfigSave.cpp b/Source/Contents/UserData/CharacterConfigSave.cpp similarity index 80% rename from Source/Contents/CharacterConfigSave.cpp rename to Source/Contents/UserData/CharacterConfigSave.cpp index 81ce090..5fc2bf6 100644 --- a/Source/Contents/CharacterConfigSave.cpp +++ b/Source/Contents/UserData/CharacterConfigSave.cpp @@ -1,12 +1,11 @@ #include "Client/ClientOptions.h" -#include "Contents/AsyncWorkMgr.h" -#include "Contents/CharacterConfigSave.h" -#include "Contents/CharacterLinkedUserDataMgr.h" -#include "Contents/NormalItemSlots.h" -#include "Contents/PlayerSkillBundle.h" -#include "Contents/ServiceOptions.h" +#include "Contents/Async/AsyncWorkMgr.h" +#include "Contents/UserData/CharacterConfigSave.h" +#include "Contents/UserData/CharacterLinkedUserDataMgr.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "Contents/Skills/PlayerSkillBundle.h" +#include "Contents/Configuration/ServiceOptions.h" -#include #include #include @@ -42,9 +41,9 @@ void CCharacterLinkedUserDataMgr::Save(CharacterConfigSave& context, const char* if (context.options.Get(7) != 0) { Json::Value values; - // Map group order then each list's order. + context.skills.ForEachGrouped([&](CSkillInfo* skill) { - const int id = std::bit_cast(skill->id); + const int id = static_cast(skill->id); const int level = context.UseLevel(id); if (level != 0) { @@ -63,9 +62,9 @@ void CCharacterLinkedUserDataMgr::Save(CharacterConfigSave& context, const char* Json::Value values; for (const CSkillInfo& skill : context.homunculusSkills) { - const int id = std::bit_cast(skill.id); + const int id = static_cast(skill.id); const auto index = skill.id - 8000u; - const int level = std::bit_cast(index) < 0 ? 0 : context.homunculusLevels[index]; + const int level = static_cast(index) < 0 ? 0 : context.homunculusLevels[index]; if (level != 0) { Json::Value value; diff --git a/Source/Contents/CharacterConfigSave.h b/Source/Contents/UserData/CharacterConfigSave.h similarity index 72% rename from Source/Contents/CharacterConfigSave.h rename to Source/Contents/UserData/CharacterConfigSave.h index 63e449e..51cf2af 100644 --- a/Source/Contents/CharacterConfigSave.h +++ b/Source/Contents/UserData/CharacterConfigSave.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CHARACTERCONFIGSAVE_H -#define RAGNAROK_SOURCE_CONTENTS_CHARACTERCONFIGSAVE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERCONFIGSAVE_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERCONFIGSAVE_H -#include "Contents/SkillInfo.h" +#include "Contents/Skills/SkillInfo.h" #include @@ -11,7 +11,6 @@ struct ServiceOptions; struct NormalItemSlot; struct NormalItemSlotWindow; -// Borrows original client collections and persistence state, not a second owner. struct CharacterConfigSave { CPlayerSkillBundle& skills; const std::list& homunculusSkills; diff --git a/Source/Contents/CharacterLinkedUserDataLoadAsyncWork.cpp b/Source/Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.cpp similarity index 85% rename from Source/Contents/CharacterLinkedUserDataLoadAsyncWork.cpp rename to Source/Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.cpp index af6c3f8..abff3ee 100644 --- a/Source/Contents/CharacterLinkedUserDataLoadAsyncWork.cpp +++ b/Source/Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.cpp @@ -1,10 +1,11 @@ -#include "Contents/CharacterLinkedUserDataLoadAsyncWork.h" -#include "Contents/CharacterLinkedUserDataMgr.h" -#include "Network/CURLPostHander.h" +#include "Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.h" +#include "Contents/UserData/CharacterLinkedUserDataMgr.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { constexpr char sourceFile[] = "C:" @@ -20,8 +21,7 @@ namespace { // OFFSET: 0x005E4A50 // FUNCTION: fn_03916 CCharacterLinkedUserDataLoadAsyncWork::CCharacterLinkedUserDataLoadAsyncWork() - : NAsyncWork("CharacterLinkedUserData_Load"), m_accountId(0), m_characterId(0), - m_diagnostic(Diagnostic(false, "unknwon", 29)), m_context(nullptr) { + : NAsyncWork("CharacterLinkedUserData_Load"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", 29)), m_context(nullptr) { } // OFFSET: 0x005E4E20 @@ -36,12 +36,7 @@ void CCharacterLinkedUserDataLoadAsyncWork::Reset() { // OFFSET: 0x005E4F10 // FUNCTION: fn_03918 void CCharacterLinkedUserDataLoadAsyncWork::Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string url, - std::string token, - CharacterConfigLoad& context + std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string url, std::string token, CharacterConfigLoad& context ) { this->m_group = timeGetTime(); this->m_accountId = accountId; diff --git a/Source/Contents/CharacterLinkedUserDataLoadAsyncWork.h b/Source/Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.h similarity index 57% rename from Source/Contents/CharacterLinkedUserDataLoadAsyncWork.h rename to Source/Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.h index e6bd21c..8cc81d1 100644 --- a/Source/Contents/CharacterLinkedUserDataLoadAsyncWork.h +++ b/Source/Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CHARACTERLINKEDUSERDATALOADASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_CHARACTERLINKEDUSERDATALOADASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERLINKEDUSERDATALOADASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERLINKEDUSERDATALOADASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" struct CharacterConfigLoad; @@ -13,14 +13,7 @@ public: void Reset() override; bool Execute() override; void Complete() override; - void Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string url, - std::string token, - CharacterConfigLoad& context - ); + void Bind(std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string url, std::string token, CharacterConfigLoad& context); protected: /* 0028 */ std::uint32_t m_accountId; @@ -31,8 +24,6 @@ protected: /* 0078 */ std::string m_response; /* 0090 */ AsyncDiagnostic m_diagnostic; - // Host binding for original global owner state; outlives queued completion. - // Not part of the original 200-byte x86 object. CharacterConfigLoad* m_context; }; diff --git a/Source/Contents/CharacterLinkedUserDataMgr.cpp b/Source/Contents/UserData/CharacterLinkedUserDataMgr.cpp similarity index 84% rename from Source/Contents/CharacterLinkedUserDataMgr.cpp rename to Source/Contents/UserData/CharacterLinkedUserDataMgr.cpp index bdf8c47..b954d71 100644 --- a/Source/Contents/CharacterLinkedUserDataMgr.cpp +++ b/Source/Contents/UserData/CharacterLinkedUserDataMgr.cpp @@ -1,5 +1,5 @@ -#include "Contents/AccountService.h" -#include "Contents/CharacterLinkedUserDataMgr.h" +#include "Contents/UserData/AccountService.h" +#include "Contents/UserData/CharacterLinkedUserDataMgr.h" #include @@ -23,15 +23,18 @@ bool CCharacterLinkedUserDataMgr::Initialize() { if (g_characterLinkedUserDataMgr) { return false; } + g_characterLinkedUserDataMgr = new (std::nothrow) CCharacterLinkedUserDataMgr; if (!g_characterLinkedUserDataMgr) { return false; } + if (!g_characterLinkedUserDataMgr->m_enabled) { delete g_characterLinkedUserDataMgr; g_characterLinkedUserDataMgr = nullptr; return false; } + return true; } @@ -64,12 +67,7 @@ void CCharacterLinkedUserDataMgr::CompleteSave() { // OFFSET: 0x005E6BB0 // FUNCTION: fn_03931 -void CCharacterLinkedUserDataMgr::RefreshUrls( - LuaScript& script, - const char* host, - const char* port, - const char* overrideKey -) { +void CCharacterLinkedUserDataMgr::RefreshUrls(LuaScript& script, const char* host, const char* port, const char* overrideKey) { const std::string base = ResolveAccountServiceBase(script, script, host, port, overrideKey); if (!base.empty()) { this->m_saveUrl = base + "/charconfig/save"; @@ -79,12 +77,7 @@ void CCharacterLinkedUserDataMgr::RefreshUrls( // OFFSET: 0x005E73B0 // FUNCTION: fn_03934 -void CCharacterLinkedUserDataMgr::Reset( - LuaScript& script, - const char* host, - const char* port, - const char* overrideKey -) { +void CCharacterLinkedUserDataMgr::Reset(LuaScript& script, const char* host, const char* port, const char* overrideKey) { this->m_accountId = 0; this->m_characterId = 0; this->m_accountName = "unknown"; diff --git a/Source/Contents/CharacterLinkedUserDataMgr.h b/Source/Contents/UserData/CharacterLinkedUserDataMgr.h similarity index 72% rename from Source/Contents/CharacterLinkedUserDataMgr.h rename to Source/Contents/UserData/CharacterLinkedUserDataMgr.h index f5258ca..ae9af9d 100644 --- a/Source/Contents/CharacterLinkedUserDataMgr.h +++ b/Source/Contents/UserData/CharacterLinkedUserDataMgr.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CHARACTERLINKEDUSERDATAMGR_H -#define RAGNAROK_SOURCE_CONTENTS_CHARACTERLINKEDUSERDATAMGR_H +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERLINKEDUSERDATAMGR_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERLINKEDUSERDATAMGR_H #include #include @@ -20,20 +20,10 @@ public: std::string SaveUrl() const; void CompleteSave(); void CompleteLoad( - AsyncDiagnostic diagnostic, - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string response, - CharacterConfigLoad& context + AsyncDiagnostic diagnostic, std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string response, CharacterConfigLoad& context ); void Load( - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - const char* token16, - CAsyncWorkMgr& workManager, - CharacterConfigLoad& context + std::uint32_t accountId, std::uint32_t characterId, std::string accountName, const char* token16, CAsyncWorkMgr& workManager, CharacterConfigLoad& context ); void Save(CharacterConfigSave& context, const char* token16, CAsyncWorkMgr& workManager); void RefreshUrls(LuaScript& script, const char* host, const char* port, const char* overrideKey); diff --git a/Source/Contents/CharacterLinkedUserDataSaveAsyncWork.cpp b/Source/Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.cpp similarity index 85% rename from Source/Contents/CharacterLinkedUserDataSaveAsyncWork.cpp rename to Source/Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.cpp index d9ad6a6..9324d88 100644 --- a/Source/Contents/CharacterLinkedUserDataSaveAsyncWork.cpp +++ b/Source/Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.cpp @@ -1,15 +1,17 @@ -#include "Contents/CharacterLinkedUserDataMgr.h" -#include "Contents/CharacterLinkedUserDataSaveAsyncWork.h" -#include "Network/CURLPostHander.h" +#include "Contents/UserData/CharacterLinkedUserDataMgr.h" +#include "Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.h" +#include "Network/Http/CURLPostHander.h" #include "Network/TextEncoding.h" #include -#include +#include +#include namespace { constexpr char sourceFile[] = "C:" "\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\CharacterLinkedUserData\\CCh" "aracterLinkedUserDataSaveAsyncWork.cpp"; + AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) { std::string message = text; return AsyncDiagnostic(&success, &message, sourceFile, &line); @@ -19,8 +21,7 @@ namespace { // OFFSET: 0x005E7C10 // FUNCTION: fn_03944 CCharacterLinkedUserDataSaveAsyncWork::CCharacterLinkedUserDataSaveAsyncWork() - : NAsyncWork("CharacterLinkedUserData_Save"), m_accountId(0), m_characterId(0), - m_diagnostic(Diagnostic(false, "unknwon", 28)) { + : NAsyncWork("CharacterLinkedUserData_Save"), m_accountId(0), m_characterId(0), m_diagnostic(Diagnostic(false, "unknwon", 28)) { } // OFFSET: 0x005E7FE0 @@ -35,12 +36,7 @@ void CCharacterLinkedUserDataSaveAsyncWork::Reset() { // OFFSET: 0x005E80D0 // FUNCTION: fn_03946 void CCharacterLinkedUserDataSaveAsyncWork::Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string url, - std::string token, - std::string data + std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string url, std::string token, std::string data ) { this->m_group = timeGetTime(); this->m_key = 0; @@ -72,6 +68,7 @@ bool CCharacterLinkedUserDataSaveAsyncWork::Execute() { const bool success = handler.Perform() == 0; AsyncDiagnostic diagnostic = Diagnostic(success, success ? "good" : "fail", success ? 102 : 98); this->m_diagnostic.MoveFrom(diagnostic); + return false; } diff --git a/Source/Contents/CharacterLinkedUserDataSaveAsyncWork.h b/Source/Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.h similarity index 62% rename from Source/Contents/CharacterLinkedUserDataSaveAsyncWork.h rename to Source/Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.h index 12493a1..c2a555b 100644 --- a/Source/Contents/CharacterLinkedUserDataSaveAsyncWork.h +++ b/Source/Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_CHARACTERLINKEDUSERDATASAVEASYNCWORK_H -#define RAGNAROK_SOURCE_CONTENTS_CHARACTERLINKEDUSERDATASAVEASYNCWORK_H +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERLINKEDUSERDATASAVEASYNCWORK_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_CHARACTERLINKEDUSERDATASAVEASYNCWORK_H -#include "Utility/AsyncDiagnostic.h" -#include "Utility/NAsyncWork.h" +#include "Utility/Async/AsyncDiagnostic.h" +#include "Utility/Async/NAsyncWork.h" class CCharacterLinkedUserDataSaveAsyncWork : public NAsyncWork { public: @@ -11,14 +11,7 @@ public: void Reset() override; bool Execute() override; void Complete() override; - void Bind( - std::uint32_t accountId, - std::uint32_t characterId, - std::string accountName, - std::string url, - std::string token, - std::string data - ); + void Bind(std::uint32_t accountId, std::uint32_t characterId, std::string accountName, std::string url, std::string token, std::string data); protected: /* 0028 */ std::uint32_t m_accountId; diff --git a/Source/Contents/NormalItemSlots.cpp b/Source/Contents/UserData/NormalItemSlots.cpp similarity index 62% rename from Source/Contents/NormalItemSlots.cpp rename to Source/Contents/UserData/NormalItemSlots.cpp index 65246a4..5f57c4f 100644 --- a/Source/Contents/NormalItemSlots.cpp +++ b/Source/Contents/UserData/NormalItemSlots.cpp @@ -1,6 +1,5 @@ -#include "Contents/NormalItemSlots.h" +#include "Contents/UserData/NormalItemSlots.h" -#include #include // OFFSET: 0x009A6C20 @@ -16,33 +15,27 @@ void NormalItemSlotWindow::Reset() { // OFFSET: 0x009A6000 // FUNCTION: fn_13667 bool NormalItemSlotWindow::IsValid(int screenWidth, int screenHeight, bool active) const { - if ( - this->width != 290 || this->height < 43 || this->height > 175 || (this->height - 10) % 33 != 0 || - (this->height == 175 && !active) - ) { + if (this->width != 290 || this->height < 43 || this->height > 175 || (this->height - 10) % 33 != 0 || (this->height == 175 && !active)) { return false; } - const int maxX = std::bit_cast(static_cast(screenWidth) - 290u); - const int maxY = - std::bit_cast(static_cast(screenHeight) - static_cast(this->height)); + + const int maxX = screenWidth - 290; + const int maxY = screenHeight - this->height; return this->x >= 0 && this->x <= maxX && this->y >= 0 && this->y <= maxY; } // OFFSET: 0x005E75A0 // FUNCTION: fn_03935 -void ExportNormalItemSlots( - Json::Value& data, - const NormalItemSlot* slots, - const NormalItemSlotWindow& window, - bool active -) { +void ExportNormalItemSlots(Json::Value& data, const NormalItemSlot* slots, const NormalItemSlotWindow& window, bool active) { Json::Value values; + for (int index = 0; index < 9; ++index) { Json::Value value; value["ItemID"] = Json::UInt(slots[index].itemId); value["SlotNum"] = index; values.append(value); } + Json::Value info; info["SlotX"] = window.x; info["SlotY"] = window.y; diff --git a/Source/Contents/UserData/NormalItemSlots.h b/Source/Contents/UserData/NormalItemSlots.h new file mode 100644 index 0000000..4c8826b --- /dev/null +++ b/Source/Contents/UserData/NormalItemSlots.h @@ -0,0 +1,33 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_USERDATA_NORMALITEMSLOTS_H +#define RAGNAROK_SOURCE_CONTENTS_USERDATA_NORMALITEMSLOTS_H + +#include +#include + +namespace Json { + class Value; +} + +#pragma pack(push, 1) +struct NormalItemSlot { + std::uint8_t unknown_0000; + std::uint32_t itemId; + std::int16_t unknown_0005; +}; +#pragma pack(pop) +static_assert(sizeof(NormalItemSlot) == 7); +static_assert(offsetof(NormalItemSlot, itemId) == 1); + +struct NormalItemSlotWindow { + int x; + int y; + int width; + int height; + int show; + void Reset(); + bool IsValid(int screenWidth, int screenHeight, bool active) const; +}; + +void ExportNormalItemSlots(Json::Value& data, const NormalItemSlot* slots, const NormalItemSlotWindow& window, bool active); + +#endif diff --git a/Source/Contents/WorldActors.cpp b/Source/Contents/World/WorldActors.cpp similarity index 93% rename from Source/Contents/WorldActors.cpp rename to Source/Contents/World/WorldActors.cpp index ddaa286..e32ae1d 100644 --- a/Source/Contents/WorldActors.cpp +++ b/Source/Contents/World/WorldActors.cpp @@ -1,5 +1,5 @@ -#include "Contents/RenderObject.h" -#include "Contents/WorldActors.h" +#include "Contents/Actors/RenderObject.h" +#include "Contents/World/WorldActors.h" // OFFSET: 0x00AC8260 // FUNCTION: fn_17668 @@ -28,6 +28,7 @@ bool WorldActors::TargetPosition(const float* origin, std::uint32_t accountId, f output[0] = target->render.position[0]; output[1] = target->render.position[1]; output[2] = target->render.position[2]; + return true; } @@ -39,8 +40,10 @@ bool WorldActors::TargetPosition(const float* origin, std::uint32_t accountId, f const float reflectedX = x - deltaX; const float deltaY = this->localPlayer->render.position[1] - y; const float reflectedZ = z - deltaZ; + output[0] = reflectedX; output[1] = y - deltaY; output[2] = reflectedZ; + return false; } diff --git a/Source/Contents/World/WorldActors.h b/Source/Contents/World/WorldActors.h new file mode 100644 index 0000000..996012c --- /dev/null +++ b/Source/Contents/World/WorldActors.h @@ -0,0 +1,19 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDACTORS_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDACTORS_H + +#include +#include + +class CRenderObject; + +struct WorldActors { + const std::list& actors; + CRenderObject* const& localPlayer; + const std::uint32_t& localAccountId; + + CRenderObject* Find(std::uint32_t accountId) const; + + bool TargetPosition(const float* origin, std::uint32_t accountId, float* output) const; +}; + +#endif diff --git a/Source/Contents/WorldEnvironment.cpp b/Source/Contents/World/WorldEnvironment.cpp similarity index 78% rename from Source/Contents/WorldEnvironment.cpp rename to Source/Contents/World/WorldEnvironment.cpp index ecd27fb..6c5ea15 100644 --- a/Source/Contents/WorldEnvironment.cpp +++ b/Source/Contents/World/WorldEnvironment.cpp @@ -1,15 +1,11 @@ -#include "Contents/WorldEnvironment.h" +#include "Contents/World/WorldEnvironment.h" #include "Render/Renderer.h" -#include "Resource/WorldResource.h" +#include "Resource/World/WorldResource.h" // OFFSET: 0x00AC94C0 // FUNCTION: fn_17684 void PublishWorldEnvironment( - const C3dWorldRes& resource, - int* modeBounds, - WorldSpatialTree*& serialized, - WorldEnvironmentLighting& lighting, - unsigned char& rendererFlag, + const C3dWorldRes& resource, int* modeBounds, WorldSpatialTree*& serialized, WorldEnvironmentLighting& lighting, unsigned char& rendererFlag, CRenderer& renderer ) { serialized = resource.spatial; @@ -17,6 +13,7 @@ void PublishWorldEnvironment( modeBounds[1] = resource.bounds[3]; modeBounds[2] = resource.bounds[0]; modeBounds[3] = resource.bounds[1]; + lighting.direction[0] = resource.lightDirection[0]; lighting.direction[1] = resource.lightDirection[1]; lighting.direction[2] = resource.lightDirection[2]; @@ -26,6 +23,7 @@ void PublishWorldEnvironment( lighting.ambient[0] = resource.ambient[0]; lighting.ambient[1] = resource.ambient[1]; lighting.ambient[2] = resource.ambient[2]; + rendererFlag = resource.flag; renderer.SetLighting(lighting.direction, lighting.diffuse, lighting.ambient); } diff --git a/Source/Contents/World/WorldEnvironment.h b/Source/Contents/World/WorldEnvironment.h new file mode 100644 index 0000000..1dd3dcf --- /dev/null +++ b/Source/Contents/World/WorldEnvironment.h @@ -0,0 +1,19 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDENVIRONMENT_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDENVIRONMENT_H + +class C3dWorldRes; +struct WorldSpatialTree; +class CRenderer; + +struct WorldEnvironmentLighting { + float direction[3]; + float diffuse[3]; + float ambient[3]; +}; + +void PublishWorldEnvironment( + const C3dWorldRes& resource, int* modeBounds, WorldSpatialTree*& serialized, WorldEnvironmentLighting& lighting, unsigned char& rendererFlag, + CRenderer& renderer +); + +#endif diff --git a/Source/Contents/WorldGroundImport.cpp b/Source/Contents/World/WorldGroundImport.cpp similarity index 57% rename from Source/Contents/WorldGroundImport.cpp rename to Source/Contents/World/WorldGroundImport.cpp index e42a5ed..c6d1c7a 100644 --- a/Source/Contents/WorldGroundImport.cpp +++ b/Source/Contents/World/WorldGroundImport.cpp @@ -1,25 +1,15 @@ -#include "Client/ErrorDialog.h" -#include "Contents/GroundGeometry.h" -#include "Contents/WorldGroundImport.h" -#include "Resource/GroundResource.h" +#include "Client/Application/ErrorDialog.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Contents/World/WorldGroundImport.h" +#include "Resource/World/GroundResource.h" #include "Resource/ResourceMgr.h" -#include "Resource/TerrainResource.h" -#include "Resource/WorldResource.h" - -#include -#include +#include "Resource/World/TerrainResource.h" +#include "Resource/World/WorldResource.h" +#include "Utility/Math/ScalarConversion.h" bool ImportWorldGround( - const C3dWorldRes& world, - ResourceMgr& resources, - TextureCache& textures, - CRenderSystemBase* renderSystem, - C3dAttr*& terrain, - GroundGeometry*& ground, - int& nearbyRange, - const float* lightDirection, - const float* diffuse, - const float* ambient + const C3dWorldRes& world, ResourceMgr& resources, TextureCache& textures, CRenderSystemBase* renderSystem, C3dAttr*& terrain, GroundGeometry*& ground, + int& nearbyRange, const float* lightDirection, const float* diffuse, const float* ambient ) { if (world.terrainName.empty()) { ShowErrorDialog(renderSystem, "attr ", 0); @@ -34,7 +24,7 @@ bool ImportWorldGround( } terrain->cellSize = 5; - nearbyRange = std::bit_cast(static_cast(nearbyRange) * static_cast(terrain->cellSize)); + nearbyRange *= terrain->cellSize; if (world.groundName.empty()) { ShowErrorDialog(renderSystem, "gnd ", 0); @@ -55,10 +45,11 @@ bool ImportWorldGround( ground = new GroundGeometry; ground->Build(*resource, textures, lightDirection, diffuse, ambient); - const int pitch = _mm_cvttss_si32(_mm_set_ss(world.waveSpeed)); - const int phase = _mm_cvttss_si32(_mm_set_ss(world.wavePitch)); + const int pitch = TruncateToInt(world.waveSpeed); + const int phase = TruncateToInt(world.wavePitch); ground->water.Set(world.waterLevel, world.waterType, world.waterAnimation, pitch, phase, world.waveHeight); ground->water.Import(*resource, textures); resources.Remove(resource); + return true; } diff --git a/Source/Contents/World/WorldGroundImport.h b/Source/Contents/World/WorldGroundImport.h new file mode 100644 index 0000000..0f69676 --- /dev/null +++ b/Source/Contents/World/WorldGroundImport.h @@ -0,0 +1,16 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDGROUNDIMPORT_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDGROUNDIMPORT_H + +class C3dWorldRes; +class C3dAttr; +class GroundGeometry; +class ResourceMgr; +class TextureCache; +class CRenderSystemBase; + +bool ImportWorldGround( + const C3dWorldRes& world, ResourceMgr& resources, TextureCache& textures, CRenderSystemBase* renderSystem, C3dAttr*& terrain, GroundGeometry*& ground, + int& nearbyRange, const float* lightDirection, const float* diffuse, const float* ambient +); + +#endif diff --git a/Source/Contents/WorldModelLoading.cpp b/Source/Contents/World/WorldModelLoading.cpp similarity index 79% rename from Source/Contents/WorldModelLoading.cpp rename to Source/Contents/World/WorldModelLoading.cpp index a8036ce..f938806 100644 --- a/Source/Contents/WorldModelLoading.cpp +++ b/Source/Contents/World/WorldModelLoading.cpp @@ -1,10 +1,10 @@ -#include "Contents/ModelActor.h" -#include "Contents/TerrainHeight.h" -#include "Contents/WorldModelLoading.h" -#include "Contents/WorldModelPlacement.h" -#include "Contents/WorldSpatialInitialization.h" +#include "Contents/Models/ModelActor.h" +#include "Contents/Ground/TerrainHeight.h" +#include "Contents/World/WorldModelLoading.h" +#include "Contents/World/WorldModelPlacement.h" +#include "Contents/World/WorldSpatialInitialization.h" #include "Resource/ResourceMgr.h" -#include "Resource/WorldResource.h" +#include "Resource/World/WorldResource.h" #include #include @@ -29,15 +29,7 @@ namespace { } } -void WorldModelLoading::Schedule( - const WorldModelRecord& placement, - const TerrainHeight& terrain, - int column, - int row, - float* center -) { - // Distance-selection block in world import. CellCenter - // writes only X/Z; the shared center's existing Y participates in distance. +void WorldModelLoading::Schedule(const WorldModelRecord& placement, const TerrainHeight& terrain, int column, int row, float* center) { terrain.CellCenter(column, row, center[0], center[2]); const float y = placement.position[1] - center[1]; const float x = placement.position[0] - center[0]; @@ -65,7 +57,6 @@ DWORD WINAPI WorldModelLoading::ThreadEntry(void* context) { } void WorldModelLoading::Start() { - // CreateThread/fallback block in world import. this->thread = CreateThread(nullptr, 0, &WorldModelLoading::ThreadEntry, this, 0, nullptr); if (!this->thread) { @@ -101,8 +92,6 @@ void WorldModelLoading::Run() { } void WorldModelLoading::Publish(WorldSpatialTree& root) { - // Read only the stable pointer range. The worker owns vector-end mutation; - // its release increment publishes the slots covered by the pending snapshot. C3dActor* const* data = this->models.data(); PublishWorldModels(root, data, this->published, this->pending); } diff --git a/Source/Contents/WorldModelLoading.h b/Source/Contents/World/WorldModelLoading.h similarity index 69% rename from Source/Contents/WorldModelLoading.h rename to Source/Contents/World/WorldModelLoading.h index b82d5f6..c8a8127 100644 --- a/Source/Contents/WorldModelLoading.h +++ b/Source/Contents/World/WorldModelLoading.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDMODELLOADING_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDMODELLOADING_H +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDMODELLOADING_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDMODELLOADING_H #include #include @@ -17,9 +17,6 @@ struct DeferredWorldModel { const WorldModelRecord* placement; }; -// Borrowed CWorld model vector/published/pending fields and the original shared -// deferred list/thread handle. Import reserves space for all placements before -// launching; placements, dependencies and vector storage must survive Finish. struct WorldModelLoading { ResourceMgr& resources; BinkMovies& movies; diff --git a/Source/Contents/WorldModelPlacement.cpp b/Source/Contents/World/WorldModelPlacement.cpp similarity index 76% rename from Source/Contents/WorldModelPlacement.cpp rename to Source/Contents/World/WorldModelPlacement.cpp index 716ce6a..d90a17f 100644 --- a/Source/Contents/WorldModelPlacement.cpp +++ b/Source/Contents/World/WorldModelPlacement.cpp @@ -1,6 +1,6 @@ -#include "Contents/ModelActor.h" -#include "Contents/WorldModelPlacement.h" -#include "Resource/WorldResource.h" +#include "Contents/Models/ModelActor.h" +#include "Contents/World/WorldModelPlacement.h" +#include "Resource/World/WorldResource.h" #include @@ -8,13 +8,8 @@ // FUNCTION: fn_17684 // OFFSET: 0x00AC8BF0 // FUNCTION: fn_17680 -// Movie registration precedes node suitability. -C3dActor* CreatePlacedWorldModel( - const WorldModelRecord& placement, - C3dModelRes& resource, - BinkMovies& movies, - ModelLightingContext& lighting -) { + +C3dActor* CreatePlacedWorldModel(const WorldModelRecord& placement, C3dModelRes& resource, BinkMovies& movies, ModelLightingContext& lighting) { resource.RegisterMovies(movies, placement.position); if (!resource.FindNode(placement.node) && resource.nodes.empty()) { @@ -43,5 +38,6 @@ C3dActor* CreatePlacedWorldModel( actor->Assign(resource); actor->occlusionEnabled = 0; actor->Prepare(lighting); + return actor; } diff --git a/Source/Contents/World/WorldModelPlacement.h b/Source/Contents/World/WorldModelPlacement.h new file mode 100644 index 0000000..b8c880b --- /dev/null +++ b/Source/Contents/World/WorldModelPlacement.h @@ -0,0 +1,12 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDMODELPLACEMENT_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDMODELPLACEMENT_H + +class C3dActor; +class C3dModelRes; +class BinkMovies; +struct WorldModelRecord; +struct ModelLightingContext; + +C3dActor* CreatePlacedWorldModel(const WorldModelRecord& placement, C3dModelRes& resource, BinkMovies& movies, ModelLightingContext& lighting); + +#endif diff --git a/Source/Contents/WorldModelView.cpp b/Source/Contents/World/WorldModelView.cpp similarity index 59% rename from Source/Contents/WorldModelView.cpp rename to Source/Contents/World/WorldModelView.cpp index aabacee..cb57854 100644 --- a/Source/Contents/WorldModelView.cpp +++ b/Source/Contents/World/WorldModelView.cpp @@ -1,14 +1,14 @@ -#include "Contents/GroundGeometry.h" -#include "Contents/GroundRendering.h" -#include "Contents/ModelActor.h" -#include "Contents/WorldModelView.h" -#include "Contents/WorldSpatialTree.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Contents/Ground/GroundRendering.h" +#include "Contents/Models/ModelActor.h" +#include "Contents/World/WorldModelView.h" +#include "Contents/World/WorldSpatialTree.h" -#include +#include namespace { float Absolute(float value) { - return std::bit_cast(std::bit_cast(value) & 0x7FFFFFFFu); + return std::fabs(value); } void IncludeRectangle(const int* rectangle, int* output) { @@ -37,11 +37,8 @@ int ModelViewPlanes::ClassifyAxisAligned(const WorldSpatialTree& bounds) const { for (unsigned plane = 0; plane < 6; ++plane) { const float* normal = this->normals[plane]; - const float radius = (Absolute(normal[0] * bounds.halfSize[0]) + Absolute(normal[1] * bounds.halfSize[1])) + - Absolute(normal[2] * bounds.halfSize[2]); - const float distance = - ((normal[0] * bounds.center[0] + normal[1] * bounds.center[1]) + normal[2] * bounds.center[2]) + - this->planes[plane][3]; + const float radius = (Absolute(normal[0] * bounds.halfSize[0]) + Absolute(normal[1] * bounds.halfSize[1])) + Absolute(normal[2] * bounds.halfSize[2]); + const float distance = ((normal[0] * bounds.center[0] + normal[1] * bounds.center[1]) + normal[2] * bounds.center[2]) + this->planes[plane][3]; if (!(distance > radius)) { const float negative = -radius; @@ -64,22 +61,11 @@ int ModelViewPlanes::ClassifyOriented(const OrientedBounds& bounds) const { for (unsigned plane = 0; plane < 6; ++plane) { const float* normal = this->normals[plane]; - const float second = Absolute( - ((normal[0] * bounds.axes[1][0] + normal[1] * bounds.axes[1][1]) + normal[2] * bounds.axes[1][2]) * - bounds.halfSize[1] - ); - const float first = Absolute( - ((normal[0] * bounds.axes[0][0] + normal[1] * bounds.axes[0][1]) + normal[2] * bounds.axes[0][2]) * - bounds.halfSize[0] - ); - const float third = Absolute( - ((normal[0] * bounds.axes[2][0] + normal[1] * bounds.axes[2][1]) + normal[2] * bounds.axes[2][2]) * - bounds.halfSize[2] - ); + const float second = Absolute(((normal[0] * bounds.axes[1][0] + normal[1] * bounds.axes[1][1]) + normal[2] * bounds.axes[1][2]) * bounds.halfSize[1]); + const float first = Absolute(((normal[0] * bounds.axes[0][0] + normal[1] * bounds.axes[0][1]) + normal[2] * bounds.axes[0][2]) * bounds.halfSize[0]); + const float third = Absolute(((normal[0] * bounds.axes[2][0] + normal[1] * bounds.axes[2][1]) + normal[2] * bounds.axes[2][2]) * bounds.halfSize[2]); const float radius = (second + first) + third; - const float distance = - ((normal[0] * bounds.center[0] + normal[1] * bounds.center[1]) + normal[2] * bounds.center[2]) + - this->planes[plane][3]; + const float distance = ((normal[0] * bounds.center[0] + normal[1] * bounds.center[1]) + normal[2] * bounds.center[2]) + this->planes[plane][3]; if (!(distance > radius)) { const float negative = -radius; @@ -104,16 +90,12 @@ int ClassifyModelView(const OrientedBounds& bounds, const ModelViewPlanes& plane const float x = planes.planes[plane][0]; const float y = planes.normals[plane][1]; const float z = planes.normals[plane][2]; - const float second = - Absolute(((bounds.axes[1][0] * x + bounds.axes[1][1] * y) + bounds.axes[1][2] * z) * bounds.halfSize[1]); - const float first = - Absolute(((bounds.axes[0][0] * x + bounds.axes[0][1] * y) + bounds.axes[0][2] * z) * bounds.halfSize[0]); - const float third = - Absolute(((bounds.axes[2][0] * x + bounds.axes[2][1] * y) + bounds.axes[2][2] * z) * bounds.halfSize[2]); + const float second = Absolute(((bounds.axes[1][0] * x + bounds.axes[1][1] * y) + bounds.axes[1][2] * z) * bounds.halfSize[1]); + const float first = Absolute(((bounds.axes[0][0] * x + bounds.axes[0][1] * y) + bounds.axes[0][2] * z) * bounds.halfSize[0]); + const float third = Absolute(((bounds.axes[2][0] * x + bounds.axes[2][1] * y) + bounds.axes[2][2] * z) * bounds.halfSize[2]); const float radius = (second + first) + third; - const float distance = ((bounds.center[0] * x + bounds.center[1] * planes.planes[plane][1]) + - bounds.center[2] * planes.planes[plane][2]) + - planes.planes[plane][3]; + const float distance = + ((bounds.center[0] * x + bounds.center[1] * planes.planes[plane][1]) + bounds.center[2] * planes.planes[plane][2]) + planes.planes[plane][3]; if (!(distance > radius)) { const float negative = -radius; @@ -130,16 +112,8 @@ int ClassifyModelView(const OrientedBounds& bounds, const ModelViewPlanes& plane } void DrawWorldModelLeaves( - std::list& clipped, - std::list& inside, - const ModelViewPlanes& planes, - const float* matrix, - unsigned frame, - int updates, - GroundGeometry& ground, - ModelRenderContext& models, - GroundLightingContext& lighting, - int* visibleRectangle + std::list& clipped, std::list& inside, const ModelViewPlanes& planes, const float* matrix, unsigned frame, int updates, + GroundGeometry& ground, ModelRenderContext& models, GroundLightingContext& lighting, int* visibleRectangle ) { visibleRectangle[0] = visibleRectangle[1] = 999; visibleRectangle[2] = visibleRectangle[3] = 0; diff --git a/Source/Contents/World/WorldModelView.h b/Source/Contents/World/WorldModelView.h new file mode 100644 index 0000000..282c836 --- /dev/null +++ b/Source/Contents/World/WorldModelView.h @@ -0,0 +1,39 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDMODELVIEW_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDMODELVIEW_H + +#include + +struct OrientedBounds; +struct WorldSpatialTree; +struct ModelRenderContext; +struct GroundLightingContext; +class GroundGeometry; + +struct ModelViewPlanes { + float planes[6][4]; + float normals[6][3]; + + int ClassifyAxisAligned(const WorldSpatialTree& bounds) const; + int ClassifyOriented(const OrientedBounds& bounds) const; +}; + +struct WorldViewSpatial { + WorldViewSpatial(); + ~WorldViewSpatial(); + + std::list inside; + std::list clipped; + ModelViewPlanes planes; + + void Collect(float horizontal, float vertical, const float* matrix, WorldSpatialTree& root); + void CollectNode(WorldSpatialTree& node, int depth, bool fullyInside); +}; + +int ClassifyModelView(const OrientedBounds& bounds, const ModelViewPlanes& planes); + +void DrawWorldModelLeaves( + std::list& clipped, std::list& inside, const ModelViewPlanes& planes, const float* matrix, unsigned frame, int updates, + GroundGeometry& ground, ModelRenderContext& models, GroundLightingContext& lighting, int* visibleRectangle +); + +#endif diff --git a/Source/Contents/WorldObjects.cpp b/Source/Contents/World/WorldObjects.cpp similarity index 74% rename from Source/Contents/WorldObjects.cpp rename to Source/Contents/World/WorldObjects.cpp index 74ea509..08c8281 100644 --- a/Source/Contents/WorldObjects.cpp +++ b/Source/Contents/World/WorldObjects.cpp @@ -1,5 +1,5 @@ -#include "Contents/RenderObject.h" -#include "Contents/WorldObjects.h" +#include "Contents/Actors/RenderObject.h" +#include "Contents/World/WorldObjects.h" // OFFSET: 0x00ACA4E0 // FUNCTION: fn_17692 @@ -15,7 +15,7 @@ void WorldObjects::Remove(CRenderObject* object) { // OFFSET: 0x00ACA320 // FUNCTION: fn_17691 -// The continuation clears borrowed actor/item indexes, movement state and other world collections. + void WorldObjects::Clear() { auto entry = this->objects.begin(); diff --git a/Source/Contents/World/WorldObjects.h b/Source/Contents/World/WorldObjects.h new file mode 100644 index 0000000..335eabf --- /dev/null +++ b/Source/Contents/World/WorldObjects.h @@ -0,0 +1,15 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDOBJECTS_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDOBJECTS_H + +#include + +class CRenderObject; + +struct WorldObjects { + std::list& objects; + + void Remove(CRenderObject* object); + void Clear(); +}; + +#endif diff --git a/Source/Contents/WorldOcclusion.cpp b/Source/Contents/World/WorldOcclusion.cpp similarity index 53% rename from Source/Contents/WorldOcclusion.cpp rename to Source/Contents/World/WorldOcclusion.cpp index adb3d4c..994567e 100644 --- a/Source/Contents/WorldOcclusion.cpp +++ b/Source/Contents/World/WorldOcclusion.cpp @@ -1,24 +1,16 @@ -#include "Contents/GroundGeometry.h" -#include "Contents/ModelActor.h" -#include "Contents/WorldOcclusion.h" -#include "Contents/WorldRayQuery.h" -#include "Contents/WorldSpatialTree.h" -#include "Render/RenderProjection.h" +#include "Contents/Ground/GroundGeometry.h" +#include "Contents/Models/ModelActor.h" +#include "Contents/World/WorldOcclusion.h" +#include "Contents/World/WorldRayQuery.h" +#include "Contents/World/WorldSpatialTree.h" +#include "Render/Projection/RenderProjection.h" -#include +#include "Utility/Math/ScalarConversion.h" #include -#include // OFFSET: 0x00CD5AD0 // FUNCTION: fn_21286 -void MarkWorldOcclusionRay( - const float* ray, - float actorLimit, - float groundLimit, - WorldSpatialTree& root, - GroundGeometry& ground, - bool markGround -) { +void MarkWorldOcclusionRay(const float* ray, float actorLimit, float groundLimit, WorldSpatialTree& root, GroundGeometry& ground, bool markGround) { float actorRay[7]; std::memcpy(actorRay, ray, 6 * sizeof(float)); actorRay[6] = actorLimit; @@ -40,30 +32,21 @@ void MarkWorldOcclusionRay( while (column <= node->groundCells[2]) { ground.MarkRay(ray, column, row, groundLimit); - column = std::bit_cast(static_cast(column) + 1u); + ++column; } - row = std::bit_cast(static_cast(row) + 1u); + ++row; } } } } void MarkScreenWorldOcclusion( - const RenderProjection& projection, - int screenX, - int screenY, - float rendererScale, - const float* origin, - const float* cameraMatrix, - float playerHeight, - float cameraHeight, - WorldSpatialTree& root, - GroundGeometry& ground, - bool markGround + const RenderProjection& projection, int screenX, int screenY, float rendererScale, const float* origin, const float* cameraMatrix, float playerHeight, + float cameraHeight, WorldSpatialTree& root, GroundGeometry& ground, bool markGround ) { const float shifted = static_cast(screenY) - rendererScale * 23.0f; - const int y = _mm_cvttss_si32(_mm_set_ss(shifted)); + const int y = TruncateToInt(shifted); float ray[6]{}; projection.Ray(screenX, y, origin, cameraMatrix, ray); const float limit = (playerHeight + cameraHeight) - 16.0f; diff --git a/Source/Contents/World/WorldOcclusion.h b/Source/Contents/World/WorldOcclusion.h new file mode 100644 index 0000000..c5d3b4d --- /dev/null +++ b/Source/Contents/World/WorldOcclusion.h @@ -0,0 +1,15 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDOCCLUSION_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDOCCLUSION_H + +struct WorldSpatialTree; +class GroundGeometry; +struct RenderProjection; + +void MarkWorldOcclusionRay(const float* ray, float actorLimit, float groundLimit, WorldSpatialTree& root, GroundGeometry& ground, bool markGround); + +void MarkScreenWorldOcclusion( + const RenderProjection& projection, int screenX, int screenY, float rendererScale, const float* origin, const float* cameraMatrix, float playerHeight, + float cameraHeight, WorldSpatialTree& root, GroundGeometry& ground, bool markGround +); + +#endif diff --git a/Source/Contents/WorldProximity.cpp b/Source/Contents/World/WorldProximity.cpp similarity index 67% rename from Source/Contents/WorldProximity.cpp rename to Source/Contents/World/WorldProximity.cpp index 195ac81..ee6ecfb 100644 --- a/Source/Contents/WorldProximity.cpp +++ b/Source/Contents/World/WorldProximity.cpp @@ -1,17 +1,13 @@ -#include "Contents/WorldProximity.h" -#include "Network/Connection.h" -#include "Network/PacketLengths.h" +#include "Contents/World/WorldProximity.h" +#include "Network/Connection/Connection.h" +#include "Network/Packets/PacketLengths.h" #include // OFFSET: 0x00AC93C0 // FUNCTION: fn_17683 void UpdateWorldProximityNotification( - unsigned char& notified, - std::function nearby, - CConnection& connection, - const PacketLengths& lengths, - const std::uint32_t& accountId + unsigned char& notified, std::function nearby, CConnection& connection, const PacketLengths& lengths, const std::uint32_t& accountId ) { if (notified == 1) { if (!nearby()) { diff --git a/Source/Contents/World/WorldProximity.h b/Source/Contents/World/WorldProximity.h new file mode 100644 index 0000000..5f85263 --- /dev/null +++ b/Source/Contents/World/WorldProximity.h @@ -0,0 +1,14 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDPROXIMITY_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDPROXIMITY_H + +#include +#include + +class CConnection; +struct PacketLengths; + +void UpdateWorldProximityNotification( + unsigned char& notified, std::function nearby, CConnection& connection, const PacketLengths& lengths, const std::uint32_t& accountId +); + +#endif diff --git a/Source/Contents/WorldRayQuery.cpp b/Source/Contents/World/WorldRayQuery.cpp similarity index 75% rename from Source/Contents/WorldRayQuery.cpp rename to Source/Contents/World/WorldRayQuery.cpp index 01f9073..14c3e20 100644 --- a/Source/Contents/WorldRayQuery.cpp +++ b/Source/Contents/World/WorldRayQuery.cpp @@ -1,15 +1,12 @@ -#include "Contents/WorldRayQuery.h" -#include "Contents/WorldSpatialTree.h" +#include "Contents/World/WorldRayQuery.h" +#include "Contents/World/WorldSpatialTree.h" -#include -#include +#include // OFFSET: 0x00AC7C50 // FUNCTION: fn_17661 bool WorldRayQuery::Intersects(const float* bounds) const { - const float centers[3] = { - (bounds[3] + bounds[0]) * 0.5f, (bounds[4] + bounds[1]) * 0.5f, (bounds[5] + bounds[2]) * 0.5f - }; + const float centers[3] = {(bounds[3] + bounds[0]) * 0.5f, (bounds[4] + bounds[1]) * 0.5f, (bounds[5] + bounds[2]) * 0.5f}; const float extents[3] = {bounds[3] - centers[0], bounds[4] - centers[1], bounds[5] - centers[2]}; const float offsets[3] = {centers[0] - this->origin[0], centers[1] - this->origin[1], centers[2] - this->origin[2]}; float entry = -999999.0f; @@ -19,9 +16,8 @@ bool WorldRayQuery::Intersects(const float* bounds) const { for (unsigned axis = 0; axis < 3; ++axis) { const float direction = this->direction[axis]; - const float magnitude = std::bit_cast(std::bit_cast(direction) & 0x7FFFFFFFu); + const float magnitude = std::fabs(direction); - // COMISS/JBE takes the parallel path for unordered directions too. if (!(magnitude > epsilon)) { const float extent = extents[axis] * parallelScale; @@ -35,9 +31,9 @@ bool WorldRayQuery::Intersects(const float* bounds) const { const bool orderedDescending = first > second; const float near = orderedDescending ? second : first; const float far = orderedDescending ? first : second; - // Operand order matters for unordered values and signed zero. - entry = _mm_cvtss_f32(_mm_max_ss(_mm_set_ss(near), _mm_set_ss(entry))); - exit = _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(far), _mm_set_ss(exit))); + + entry = near > entry ? near : entry; + exit = far < exit ? far : exit; if (entry > exit || exit < 0.0f) { return false; @@ -45,7 +41,6 @@ bool WorldRayQuery::Intersects(const float* bounds) const { } } - // Inside-origin queries use the exit distance, not a clamped zero entry. return !((entry > 0.0f ? entry : exit) > this->limit); } diff --git a/Source/Contents/WorldRayQuery.h b/Source/Contents/World/WorldRayQuery.h similarity index 71% rename from Source/Contents/WorldRayQuery.h rename to Source/Contents/World/WorldRayQuery.h index b2e039d..088300a 100644 --- a/Source/Contents/WorldRayQuery.h +++ b/Source/Contents/World/WorldRayQuery.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDRAYQUERY_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDRAYQUERY_H +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDRAYQUERY_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDRAYQUERY_H #include struct WorldSpatialTree; -// Original query list followed by origin, direction and picking limit. struct WorldRayQuery { std::list nodes; float origin[3]; diff --git a/Source/Contents/WorldSpatialInitialization.cpp b/Source/Contents/World/WorldSpatialInitialization.cpp similarity index 62% rename from Source/Contents/WorldSpatialInitialization.cpp rename to Source/Contents/World/WorldSpatialInitialization.cpp index eaceff8..c8db328 100644 --- a/Source/Contents/WorldSpatialInitialization.cpp +++ b/Source/Contents/World/WorldSpatialInitialization.cpp @@ -1,34 +1,23 @@ -#include "Contents/GroundSpatial.h" -#include "Contents/ModelActor.h" -#include "Contents/WorldSpatialInitialization.h" -#include "Contents/WorldSpatialTree.h" -#include "Resource/TerrainResource.h" +#include "Contents/Ground/GroundSpatial.h" +#include "Contents/Models/ModelActor.h" +#include "Contents/World/WorldSpatialInitialization.h" +#include "Contents/World/WorldSpatialTree.h" +#include "Resource/World/TerrainResource.h" #include -#include // OFFSET: 0x00AC79C0 // FUNCTION: fn_17660 void InitializeWorldSpatial( - WorldSpatialTree& root, - GroundSpatial& ground, - C3dAttr& terrain, - std::span models, - const WorldSpatialTree* serialized + WorldSpatialTree& root, GroundSpatial& ground, C3dAttr& terrain, std::span models, const WorldSpatialTree* serialized ) { root.ClearChildren(); const int halfWidth = ground.width / 2; const int halfHeight = ground.height / 2; root.minimum[0] = static_cast(ground.width / -2) * ground.cellSize; - root.maximum[0] = - static_cast(std::bit_cast(static_cast(ground.width) - static_cast(halfWidth))) * - ground.cellSize - - 1.0f; + root.maximum[0] = static_cast(ground.width - halfWidth) * ground.cellSize - 1.0f; root.minimum[2] = static_cast(ground.height / -2) * ground.cellSize; - root.maximum[2] = - static_cast(std::bit_cast(static_cast(ground.height) - static_cast(halfHeight))) * - ground.cellSize - - 1.0f; + root.maximum[2] = static_cast(ground.height - halfHeight) * ground.cellSize - 1.0f; root.halfSize[0] = 0; root.halfSize[2] = 0; root.Subdivide(0); @@ -65,7 +54,7 @@ void PublishWorldModels(WorldSpatialTree& root, C3dActor* const* models, int& pu return; } - const int end = std::bit_cast(static_cast(published) + static_cast(ready)); + const int end = published + ready; while (published < end) { C3dActor& model = *models[published]; @@ -77,6 +66,6 @@ void PublishWorldModels(WorldSpatialTree& root, C3dActor* const* models, int& pu } count.fetch_sub(1, std::memory_order_seq_cst); - published = std::bit_cast(static_cast(published) + 1u); + ++published; } } diff --git a/Source/Contents/World/WorldSpatialInitialization.h b/Source/Contents/World/WorldSpatialInitialization.h new file mode 100644 index 0000000..4b703e1 --- /dev/null +++ b/Source/Contents/World/WorldSpatialInitialization.h @@ -0,0 +1,17 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDSPATIALINITIALIZATION_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDSPATIALINITIALIZATION_H + +#include + +struct WorldSpatialTree; +struct GroundSpatial; +class C3dAttr; +class C3dActor; + +void InitializeWorldSpatial( + WorldSpatialTree& root, GroundSpatial& ground, C3dAttr& terrain, std::span models, const WorldSpatialTree* serialized +); + +void PublishWorldModels(WorldSpatialTree& root, C3dActor* const* models, int& published, int& pending); + +#endif diff --git a/Source/Contents/WorldSpatialTree.cpp b/Source/Contents/World/WorldSpatialTree.cpp similarity index 92% rename from Source/Contents/WorldSpatialTree.cpp rename to Source/Contents/World/WorldSpatialTree.cpp index 8ae96fd..cc44166 100644 --- a/Source/Contents/WorldSpatialTree.cpp +++ b/Source/Contents/World/WorldSpatialTree.cpp @@ -1,15 +1,12 @@ -#include "Contents/GroundSpatial.h" -#include "Contents/ModelActor.h" -#include "Contents/WorldSpatialTree.h" +#include "Contents/Ground/GroundSpatial.h" +#include "Contents/Models/ModelActor.h" +#include "Contents/World/WorldSpatialTree.h" #include "Resource/ResourceByteReader.h" -#include "Resource/TerrainResource.h" - -#include +#include "Resource/World/TerrainResource.h" // OFFSET: 0x00AC66F0 // FUNCTION: fn_17652 -WorldSpatialTree::WorldSpatialTree() - : parent(nullptr), children{}, minimum{}, maximum{}, center{}, halfSize{}, dirty(1) { +WorldSpatialTree::WorldSpatialTree() : parent(nullptr), children{}, minimum{}, maximum{}, center{}, halfSize{}, dirty(1) { } // OFFSET: 0x00AC71E0 @@ -132,6 +129,7 @@ void WorldSpatialTree::BindGround(GroundSpatial& resource, int depth) { // FUNCTION: fn_17662 void WorldSpatialTree::CopyBounds(int depth, const WorldSpatialTree& source) { this->dirty = 0; + for (unsigned index = 0; index < 3; ++index) { this->maximum[index] = source.maximum[index]; } @@ -176,8 +174,8 @@ void WorldSpatialTree::RefreshBounds(int depth) { float terrainMaximum; this->ground->HeightBounds(this->groundCells, groundMinimum, groundMaximum); this->terrain->Grid().HeightBounds(this->terrainCells, terrainMinimum, terrainMaximum); - this->maximum[1] = _mm_cvtss_f32(_mm_max_ss(_mm_set_ss(terrainMaximum), _mm_set_ss(groundMaximum))); - this->minimum[1] = _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(terrainMinimum), _mm_set_ss(groundMinimum))); + this->maximum[1] = terrainMaximum > groundMaximum ? terrainMaximum : groundMaximum; + this->minimum[1] = terrainMinimum < groundMinimum ? terrainMinimum : groundMinimum; auto object = this->objects.begin(); @@ -197,7 +195,6 @@ void WorldSpatialTree::RefreshBounds(int depth) { ++object; } - // The original does not advance past a null entry. } WorldSpatialTree* node = this; diff --git a/Source/Contents/WorldSpatialTree.h b/Source/Contents/World/WorldSpatialTree.h similarity index 88% rename from Source/Contents/WorldSpatialTree.h rename to Source/Contents/World/WorldSpatialTree.h index bcdcbb3..c1b2cf0 100644 --- a/Source/Contents/WorldSpatialTree.h +++ b/Source/Contents/World/WorldSpatialTree.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDSPATIALTREE_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDSPATIALTREE_H +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDSPATIALTREE_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDSPATIALTREE_H #include #include @@ -9,7 +9,6 @@ class C3dAttr; struct GroundSpatial; class C3dActor; -// Original CWorld quadtree node, shared with retained RSW spatial data. struct WorldSpatialTree { WorldSpatialTree(); ~WorldSpatialTree(); diff --git a/Source/Contents/WorldTerrainPicking.cpp b/Source/Contents/World/WorldTerrainPicking.cpp similarity index 61% rename from Source/Contents/WorldTerrainPicking.cpp rename to Source/Contents/World/WorldTerrainPicking.cpp index f6c0ce1..a5574e0 100644 --- a/Source/Contents/WorldTerrainPicking.cpp +++ b/Source/Contents/World/WorldTerrainPicking.cpp @@ -1,10 +1,8 @@ -#include "Contents/WorldRayQuery.h" -#include "Contents/WorldSpatialTree.h" -#include "Contents/WorldTerrainPicking.h" -#include "Render/RenderProjection.h" -#include "Resource/TerrainResource.h" - -#include +#include "Contents/World/WorldRayQuery.h" +#include "Contents/World/WorldSpatialTree.h" +#include "Contents/World/WorldTerrainPicking.h" +#include "Render/Projection/RenderProjection.h" +#include "Resource/World/TerrainResource.h" // OFFSET: 0x00CD4060 // FUNCTION: fn_21274 @@ -23,17 +21,16 @@ bool PickTerrainRay(const float* ray, WorldSpatialTree& root, int& column, int& while (candidateColumn <= node->terrainCells[2]) { const float distance = terrain->Grid().RayDistance(ray, candidateColumn, candidateRow); - // COMISS nearest,distance / JBE retains ties and unordered misses. if (nearest > distance) { nearest = distance; column = candidateColumn; row = candidateRow; } - candidateColumn = std::bit_cast(static_cast(candidateColumn) + 1u); + candidateColumn = candidateColumn + 1; } - candidateRow = std::bit_cast(static_cast(candidateRow) + 1u); + candidateRow = candidateRow + 1; } } @@ -43,14 +40,7 @@ bool PickTerrainRay(const float* ray, WorldSpatialTree& root, int& column, int& // OFFSET: 0x00CD4060 // FUNCTION: fn_21274 bool PickScreenTerrain( - const RenderProjection& projection, - int x, - int y, - const float* origin, - const float* cameraMatrix, - WorldSpatialTree& root, - int& column, - int& row + const RenderProjection& projection, int x, int y, const float* origin, const float* cameraMatrix, WorldSpatialTree& root, int& column, int& row ) { float ray[6]{}; projection.Ray(x, y, origin, cameraMatrix, ray); diff --git a/Source/Contents/World/WorldTerrainPicking.h b/Source/Contents/World/WorldTerrainPicking.h new file mode 100644 index 0000000..50c6045 --- /dev/null +++ b/Source/Contents/World/WorldTerrainPicking.h @@ -0,0 +1,13 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDTERRAINPICKING_H +#define RAGNAROK_SOURCE_CONTENTS_WORLD_WORLDTERRAINPICKING_H + +struct WorldSpatialTree; +struct RenderProjection; + +bool PickTerrainRay(const float* ray, WorldSpatialTree& root, int& column, int& row); + +bool PickScreenTerrain( + const RenderProjection& projection, int x, int y, const float* origin, const float* cameraMatrix, WorldSpatialTree& root, int& column, int& row +); + +#endif diff --git a/Source/Contents/WorldViewSpatial.cpp b/Source/Contents/World/WorldViewSpatial.cpp similarity index 96% rename from Source/Contents/WorldViewSpatial.cpp rename to Source/Contents/World/WorldViewSpatial.cpp index cc85597..fb6f774 100644 --- a/Source/Contents/WorldViewSpatial.cpp +++ b/Source/Contents/World/WorldViewSpatial.cpp @@ -1,5 +1,5 @@ -#include "Contents/WorldModelView.h" -#include "Contents/WorldSpatialTree.h" +#include "Contents/World/WorldModelView.h" +#include "Contents/World/WorldSpatialTree.h" #include diff --git a/Source/Contents/WorldActors.h b/Source/Contents/WorldActors.h deleted file mode 100644 index 5e6685e..0000000 --- a/Source/Contents/WorldActors.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDACTORS_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDACTORS_H - -#include -#include - -class CRenderObject; - -// Borrowed CWorld actor list at +0x10, local actor at +0x2C, and client account -// ID. The list and local actor remain owned by the world; the local actor and -// list entries are nonnull, and the first matching account ID wins. -struct WorldActors { - const std::list& actors; - CRenderObject* const& localPlayer; - const std::uint32_t& localAccountId; - - CRenderObject* Find(std::uint32_t accountId) const; - - // Returns the local/matching actor position, or false with the position - // reflected away from the local player through origin when no actor exists. - // Successful copies are sequential; fallback inputs are read before output. - bool TargetPosition(const float* origin, std::uint32_t accountId, float* output) const; -}; - -#endif diff --git a/Source/Contents/WorldEnvironment.h b/Source/Contents/WorldEnvironment.h deleted file mode 100644 index 231e493..0000000 --- a/Source/Contents/WorldEnvironment.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDENVIRONMENT_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDENVIRONMENT_H - -class C3dWorldRes; -struct WorldSpatialTree; -class CRenderer; - -// Shared import-light globals, distinct from the -// resource loader's diffuse/ambient globals. -struct WorldEnvironmentLighting { - float direction[3]; - float diffuse[3]; - float ambient[3]; -}; - -// Borrowed mode +0x58..+0x67 bounds, CWorld +0xD4 serialized tree and renderer -// +0x48 byte. World resource ownership remains with ResourceMgr. -void PublishWorldEnvironment( - const C3dWorldRes& resource, - int* modeBounds, - WorldSpatialTree*& serialized, - WorldEnvironmentLighting& lighting, - unsigned char& rendererFlag, - CRenderer& renderer -); - -#endif diff --git a/Source/Contents/WorldGroundImport.h b/Source/Contents/WorldGroundImport.h deleted file mode 100644 index 184241e..0000000 --- a/Source/Contents/WorldGroundImport.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDGROUNDIMPORT_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDGROUNDIMPORT_H - -class C3dWorldRes; -class C3dAttr; -class GroundGeometry; -class ResourceMgr; -class TextureCache; -class CRenderSystemBase; - -// Terrain/ground block of world import. The world owns ground; -// terrain remains borrowed from ResourceMgr. Earlier world/lighting publication -// and subsequent model/effect import are separate operations. -bool ImportWorldGround( - const C3dWorldRes& world, - ResourceMgr& resources, - TextureCache& textures, - CRenderSystemBase* renderSystem, - C3dAttr*& terrain, - GroundGeometry*& ground, - int& nearbyRange, - const float* lightDirection, - const float* diffuse, - const float* ambient -); - -#endif diff --git a/Source/Contents/WorldModelPlacement.h b/Source/Contents/WorldModelPlacement.h deleted file mode 100644 index 2e6ef24..0000000 --- a/Source/Contents/WorldModelPlacement.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDMODELPLACEMENT_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDMODELPLACEMENT_H - -class C3dActor; -class C3dModelRes; -class BinkMovies; -struct WorldModelRecord; -struct ModelLightingContext; - -// Model creation block shared by immediate and worker world import. Returned -// actor ownership transfers to the caller; resource/mesh lifetime remains with -// the resource manager. Distance scheduling and world startup are separate. -C3dActor* CreatePlacedWorldModel( - const WorldModelRecord& placement, - C3dModelRes& resource, - BinkMovies& movies, - ModelLightingContext& lighting -); - -#endif diff --git a/Source/Contents/WorldModelView.h b/Source/Contents/WorldModelView.h deleted file mode 100644 index 4b53aa4..0000000 --- a/Source/Contents/WorldModelView.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDMODELVIEW_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDMODELVIEW_H - -#include - -struct OrientedBounds; -struct WorldSpatialTree; -struct ModelRenderContext; -struct GroundLightingContext; -class GroundGeometry; - -// Original CView plane coefficients and its separate normal cache are read -// independently. Do not assume the two arrays are identical or normalize them. -struct ModelViewPlanes { - float planes[6][4]; - float normals[6][3]; - - int ClassifyAxisAligned(const WorldSpatialTree& bounds) const; - int ClassifyOriented(const OrientedBounds& bounds) const; -}; - -// Appended leaf lists at original CView +0xF8/+0x100. Collection does not clear -// previous results; the completed draw phase owns that release point. -struct WorldViewSpatial { - WorldViewSpatial(); - ~WorldViewSpatial(); - - std::list inside; - std::list clipped; - ModelViewPlanes planes; - - void Collect(float horizontal, float vertical, const float* matrix, WorldSpatialTree& root); - void CollectNode(WorldSpatialTree& node, int depth, bool fullyInside); -}; - -int ClassifyModelView(const OrientedBounds& bounds, const ModelViewPlanes& planes); - -// Model/ground portion of CView Draw. Leaf lists have already -// been classified by the view's spatial traversal; other world objects and -// overlay passes remain separate from this concrete slice. -void DrawWorldModelLeaves( - std::list& clipped, - std::list& inside, - const ModelViewPlanes& planes, - const float* matrix, - unsigned frame, - int updates, - GroundGeometry& ground, - ModelRenderContext& models, - GroundLightingContext& lighting, - int* visibleRectangle -); - -#endif diff --git a/Source/Contents/WorldObjects.h b/Source/Contents/WorldObjects.h deleted file mode 100644 index 9375f24..0000000 --- a/Source/Contents/WorldObjects.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDOBJECTS_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDOBJECTS_H - -#include - -class CRenderObject; - -// Borrowed CWorld owning list at +0x08. Actor/spatial indexes are separate -// owners and must be updated by their original caller, not by this operation. -struct WorldObjects { - std::list& objects; - - void Remove(CRenderObject* object); - void Clear(); -}; - -#endif diff --git a/Source/Contents/WorldOcclusion.h b/Source/Contents/WorldOcclusion.h deleted file mode 100644 index fa91fd6..0000000 --- a/Source/Contents/WorldOcclusion.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDOCCLUSION_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDOCCLUSION_H - -struct WorldSpatialTree; -class GroundGeometry; -struct RenderProjection; - -// Recovered traversal within CGameMode. Spatial query keeps its -// original fixed limit; actor and ground rejection limits are independent. -void MarkWorldOcclusionRay( - const float* ray, - float actorLimit, - float groundLimit, - WorldSpatialTree& root, - GroundGeometry& ground, - bool markGround -); - -// Caller has established world/player/renderer prerequisites. Player screen Y -// is shifted by renderer +0x1C times 23, then truncated before ray construction. -void MarkScreenWorldOcclusion( - const RenderProjection& projection, - int screenX, - int screenY, - float rendererScale, - const float* origin, - const float* cameraMatrix, - float playerHeight, - float cameraHeight, - WorldSpatialTree& root, - GroundGeometry& ground, - bool markGround -); - -#endif diff --git a/Source/Contents/WorldProximity.h b/Source/Contents/WorldProximity.h deleted file mode 100644 index 6531a63..0000000 --- a/Source/Contents/WorldProximity.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDPROXIMITY_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDPROXIMITY_H - -#include -#include - -class CConnection; -struct PacketLengths; - -// CWorld's byte at +0xF4 suppresses repeated proximity notifications. Exactly -// 1 means notified; other byte values take the inactive branch. The predicate -// is owned by this call and runs before the account ID is read or state changes. -// An empty predicate throws std::bad_function_call without changing the byte. -void UpdateWorldProximityNotification( - unsigned char& notified, - std::function nearby, - CConnection& connection, - const PacketLengths& lengths, - const std::uint32_t& accountId -); - -#endif diff --git a/Source/Contents/WorldSpatialInitialization.h b/Source/Contents/WorldSpatialInitialization.h deleted file mode 100644 index 033d135..0000000 --- a/Source/Contents/WorldSpatialInitialization.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDSPATIALINITIALIZATION_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDSPATIALINITIALIZATION_H - -#include - -struct WorldSpatialTree; -struct GroundSpatial; -class C3dAttr; -class C3dActor; - -// CWorld spatial assembly. Ground references must outlive -// the tree; rebuilding deletes children but retains the root's object vector. -void InitializeWorldSpatial( - WorldSpatialTree& root, - GroundSpatial& ground, - C3dAttr& terrain, - std::span models, - const WorldSpatialTree* serialized -); - -// Publication block in CWorld update. The worker publishes actor -// pointers before incrementing pending; this pass consumes one count snapshot. -// Model storage must remain stable while the worker and this pass access it. -void PublishWorldModels(WorldSpatialTree& root, C3dActor* const* models, int& published, int& pending); - -#endif diff --git a/Source/Contents/WorldTerrainPicking.h b/Source/Contents/WorldTerrainPicking.h deleted file mode 100644 index ce61112..0000000 --- a/Source/Contents/WorldTerrainPicking.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef RAGNAROK_SOURCE_CONTENTS_WORLDTERRAINPICKING_H -#define RAGNAROK_SOURCE_CONTENTS_WORLDTERRAINPICKING_H - -struct WorldSpatialTree; -struct RenderProjection; - -// Recovered terrain scan after camera ray construction. -bool PickTerrainRay(const float* ray, WorldSpatialTree& root, int& column, int& row); - -// Explicit original renderer, camera and cursor inputs to CGameMode picking. -bool PickScreenTerrain( - const RenderProjection& projection, - int x, - int y, - const float* origin, - const float* cameraMatrix, - WorldSpatialTree& root, - int& column, - int& row -); - -#endif diff --git a/Source/File/CommonObject.cpp b/Source/File/CommonObject.cpp index 5e2d3d0..b81d7fc 100644 --- a/Source/File/CommonObject.cpp +++ b/Source/File/CommonObject.cpp @@ -1,5 +1,5 @@ #include "File/CommonObject.h" -#include "Resource/BitmapResource.h" +#include "Resource/Bitmap/BitmapResource.h" #include #include @@ -31,17 +31,13 @@ bool CCommonObject::LoadTokens(std::vector& tokens, const char* name, int tokens.reserve(4096); } - // ResourceBytes supplies the original resolved, archive-aware read boundary. - // No loose-file fallback is hidden in this table parser. if (!file.Open(name)) { file.Close(); return false; } const auto bytes = static_cast(file.Size()); - std::unique_ptr buffer( - static_cast(std::malloc(static_cast(bytes) + 1)), &std::free - ); + std::unique_ptr buffer(static_cast(std::malloc(static_cast(bytes) + 1)), &std::free); if (!buffer) { file.Close(); diff --git a/Source/File/CommonObject.h b/Source/File/CommonObject.h index 9ebff34..3599b49 100644 --- a/Source/File/CommonObject.h +++ b/Source/File/CommonObject.h @@ -5,8 +5,6 @@ class ResourceBytes; -// RTTI CCommonObject. Token pointers borrow the -// retained file allocations until Clear/destruction, not the input file view. class CCommonObject { public: CCommonObject() = default; diff --git a/Source/File/File.cpp b/Source/File/File.cpp index 291529b..6d3dfbb 100644 --- a/Source/File/File.cpp +++ b/Source/File/File.cpp @@ -1,4 +1,4 @@ -#include "Client/ErrorDialog.h" +#include "Client/Application/ErrorDialog.h" #include "File/File.h" #include @@ -17,16 +17,16 @@ CFile::~CFile() { // FUNCTION: fn_02597 bool CFile::OpenWrite(const char* path, CRenderSystemBase* renderSystem) { this->m_path = path; - this->m_handle = CreateFileA( - path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr - ); + this->m_handle = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (this->m_handle == INVALID_HANDLE_VALUE) { ShowErrorDialog(renderSystem, this->m_path.c_str(), 0); return false; } + LARGE_INTEGER size; GetFileSizeEx(this->m_handle, &size); this->m_size = size.LowPart; + return true; } @@ -65,7 +65,7 @@ bool CFile::Peek(void* data, std::uint32_t bytes) { } LARGE_INTEGER distance; - // The reference zero-extends the negated low DWORD, not sign-extension. + distance.QuadPart = static_cast(0u - bytes); SetFilePointerEx(this->m_handle, distance, nullptr, FILE_CURRENT); return true; @@ -86,6 +86,7 @@ bool CFile::Seek(std::uint32_t distance, DWORD origin) { LARGE_INTEGER offset; offset.QuadPart = distance; SetFilePointerEx(this->m_handle, offset, nullptr, origin); + return true; } @@ -118,7 +119,6 @@ bool CFile::Seek(std::uint32_t distance, DWORD origin) { void CFile::Close() { if (this->m_handle == INVALID_HANDLE_VALUE) { if (this->m_data) { - // Release helper. VirtualFree(this->m_data, 0, MEM_RELEASE); this->m_data = nullptr; } diff --git a/Source/File/File.h b/Source/File/File.h index 8abe834..d12eb94 100644 --- a/Source/File/File.h +++ b/Source/File/File.h @@ -11,20 +11,11 @@ class CFile { public: CFile(); virtual ~CFile(); - // Recovered write branch only; not a replacement for original general Open, - // whose archive read/extraction dependency remains unresolved. + bool OpenWrite(const char* path, CRenderSystemBase* renderSystem); bool Open(const char* path) { this->m_path = path; - this->m_handle = CreateFileA( - path, - GENERIC_READ, - FILE_SHARE_READ, - nullptr, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - nullptr - ); + this->m_handle = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (this->m_handle == INVALID_HANDLE_VALUE) { return false; } diff --git a/Source/File/MapName.h b/Source/File/MapName.h index f6e6323..42316f7 100644 --- a/Source/File/MapName.h +++ b/Source/File/MapName.h @@ -3,11 +3,6 @@ #include -// Removes three bytes starting four bytes before the final '@', if that '@' -// has at least four preceding bytes, then formats at most 15 bytes plus NUL. -// Returned storage belongs to the original GetCurrentThread pseudo-handle map. -// The pseudo-handle is shared across threads: later calls overwrite the same -// buffer. This is deliberately not thread-local storage and is not synchronized. const char* ScriptMapName(std::string name); #endif diff --git a/Source/File/ResourcePath.cpp b/Source/File/ResourcePath.cpp index b591f30..1507eb9 100644 --- a/Source/File/ResourcePath.cpp +++ b/Source/File/ResourcePath.cpp @@ -13,9 +13,11 @@ std::string MakeResourcePath(std::string filename) { } std::size_t duplicate; + while ((duplicate = path.find("//")) != std::string::npos) { path.replace(duplicate, 2, "/", 1); } + return path; } @@ -29,8 +31,7 @@ bool ResourceExists(const char* filename, int looseOnly) { // OFFSET: 0x00AE9EE0 // FUNCTION: fn_18113 void* ReadLooseResource(const char* filename, std::uint32_t* size) { - HANDLE file = - CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + HANDLE file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (file == INVALID_HANDLE_VALUE) { return nullptr; } @@ -50,6 +51,5 @@ void* ReadLooseResource(const char* filename, std::uint32_t* size) { ReadFile(file, data, *size, &read, nullptr); CloseHandle(file); - // The original's non-.ebm post-read hook is an established empty routine. return data; } diff --git a/Source/File/ResourcePath.h b/Source/File/ResourcePath.h index 4e99268..bac43c1 100644 --- a/Source/File/ResourcePath.h +++ b/Source/File/ResourcePath.h @@ -4,14 +4,9 @@ #include #include -// Reconstructed names for the original resource path and existence helpers. std::string MakeResourcePath(std::string filename); bool ResourceExists(const char* filename, int looseOnly); -// Full loose-file reader used after archive lookup. size must be non-null. -// Publishes the low file-size DWORD after opening, even when allocation fails; -// a successful allocation is returned regardless of ReadFile's status/count. -// Caller owns the returned region and releases it with VirtualFree/MEM_RELEASE. void* ReadLooseResource(const char* filename, std::uint32_t* size); #endif diff --git a/Source/File/ShortcutFilename.cpp b/Source/File/ShortcutFilename.cpp index cb0cc46..1a4bcab 100644 --- a/Source/File/ShortcutFilename.cpp +++ b/Source/File/ShortcutFilename.cpp @@ -5,15 +5,18 @@ std::string ShortcutFilename(std::uint32_t identifier) { std::string result; constexpr char digits[] = "3867012495"; + for (std::uint32_t divisor = 1000000000; divisor; divisor /= 10) { if (!result.empty() && divisor == 100) { result.push_back('-'); } + unsigned digit = identifier / divisor; identifier %= divisor; if (digit || !result.empty()) { result.push_back(digits[digit]); } } + return result; } diff --git a/Source/File/ShortcutFilename.h b/Source/File/ShortcutFilename.h index 71365fe..20420fa 100644 --- a/Source/File/ShortcutFilename.h +++ b/Source/File/ShortcutFilename.h @@ -4,7 +4,6 @@ #include #include -// Reconstructed semantic name for the original numeric filename transformation. std::string ShortcutFilename(std::uint32_t identifier); #endif diff --git a/Source/Network/Connection.cpp b/Source/Network/Connection/Connection.cpp similarity index 90% rename from Source/Network/Connection.cpp rename to Source/Network/Connection/Connection.cpp index 6bd450d..a1137cb 100644 --- a/Source/Network/Connection.cpp +++ b/Source/Network/Connection/Connection.cpp @@ -1,18 +1,18 @@ -#include "Client/ErrorDialog.h" -#include "Network/Connection.h" -#include "Network/ConnectionRuntime.h" -#include "Network/PacketLengths.h" +#include "Client/Application/ErrorDialog.h" +#include "Network/Connection/Connection.h" +#include "Network/Connection/ConnectionRuntime.h" +#include "Network/Packets/PacketLengths.h" #include #include #include -#include +#include +#include #include // OFFSET: 0x00C7C110 // FUNCTION: fn_20382 -CConnection::CConnection(ConnectionContext& context) - : m_socket(INVALID_SOCKET), m_deferred(0), m_sendDeadline(0), m_context(&context) { +CConnection::CConnection(ConnectionContext& context) : m_socket(INVALID_SOCKET), m_deferred(0), m_sendDeadline(0), m_context(&context) { this->m_input.Reset(0xA000); this->m_output.Reset(0xA000); this->m_pending.Reset(0xA000); @@ -23,10 +23,12 @@ CConnection::CConnection(ConnectionContext& context) // OFFSET: 0x00C7C2F0 // FUNCTION: fn_20385 CConnection::~CConnection() = default; + // OFFSET: 0x00C7C1C0 // FUNCTION: fn_20383 CRagConnection::CRagConnection(ConnectionContext& context) : CConnection(context), unknown_006C(0) { } + // OFFSET: 0x00C7C370 // FUNCTION: fn_20386 CRagConnection::~CRagConnection() = default; @@ -35,57 +37,68 @@ CRagConnection::~CRagConnection() = default; // FUNCTION: fn_20389 bool CConnection::Connect(const ConnectionEndpoint& endpoint) { this->m_deferred = 0; + while (this->m_pending.Available() != 0) { const int bytes = this->m_pending.Available(); this->m_output.Append(bytes, this->m_pending.Data()); this->m_pending.Consume(bytes); this->Flush(); } + this->m_input.Reset(0xA000); this->m_output.Reset(0xA000); this->m_pending.Reset(0xA000); this->m_socket = socket(AF_INET, SOCK_STREAM, 0); + if (this->m_socket == INVALID_SOCKET) { return false; } + const int noDelay = 1; setsockopt(this->m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&noDelay), sizeof(noDelay)); u_long nonblocking = 1; + if (ioctlsocket(this->m_socket, FIONBIO, &nonblocking) == SOCKET_ERROR) { ShowErrorDialog(this->m_context->renderSystem, "Failed to setup select mode", 0); return false; } + std::memset(&this->m_address, 0, sizeof(this->m_address)); std::string address = endpoint.address; const std::string overrideAddress = endpoint.overrideAddress; const std::size_t colon = overrideAddress.rfind(':'); + if (!overrideAddress.empty() && colon != std::string::npos) { const std::string host = overrideAddress.substr(0, colon); if (hostent* resolved = gethostbyname(host.c_str())) { - address = inet_ntoa(*reinterpret_cast(resolved->h_addr_list[0])); + in_addr resolvedAddress; + std::memcpy(&resolvedAddress, resolved->h_addr_list[0], sizeof(resolvedAddress)); + address = inet_ntoa(resolvedAddress); } } + this->m_address.sin_addr.s_addr = inet_addr(address.c_str()); this->m_address.sin_family = AF_INET; int port = endpoint.port; + if (!overrideAddress.empty() && colon != std::string::npos) { port = std::atoi(overrideAddress.c_str() + colon + 1); } + this->m_address.sin_port = htons(static_cast(port)); ConnectionAddressCache& cache = this->m_context->addressCache; if (cache.session != this->m_context->session || cache.address == 0) { cache.address = this->m_address.sin_addr.s_addr; cache.session = this->m_context->session; } + this->m_address.sin_addr.s_addr = cache.address; - if ( - connect(this->m_socket, reinterpret_cast(&this->m_address), sizeof(this->m_address)) != - SOCKET_ERROR || - WSAGetLastError() == WSAEWOULDBLOCK - ) { + if (connect(this->m_socket, reinterpret_cast(&this->m_address), sizeof(this->m_address)) != SOCKET_ERROR || + WSAGetLastError() == WSAEWOULDBLOCK) { this->m_status = 0; return true; } + this->Close(); return false; } @@ -99,6 +112,7 @@ void CConnection::Close() { this->m_output.Reset(0xA000); this->m_pending.Reset(0xA000); } + this->m_status = 0; this->m_context->options.Set(5, 0, 0); } @@ -111,9 +125,11 @@ bool CConnection::Receive() { FD_ZERO(&readable); FD_SET(this->m_socket, &readable); timeval timeout{}; + if (select(0, &readable, nullptr, nullptr, &timeout) <= 0) { return true; } + char data[2048]; const int bytes = g_connectionReceive(this->m_socket, data, sizeof(data), 0); if (bytes == SOCKET_ERROR) { @@ -125,6 +141,7 @@ bool CConnection::Receive() { this->m_input.Append(bytes, data); continue; } + this->Close(); return false; } @@ -137,15 +154,18 @@ bool CConnection::Flush() { if (this->m_output.Available() == 0) { return true; } + fd_set writable; FD_ZERO(&writable); FD_SET(this->m_socket, &writable); timeval timeout{}; const int ready = select(0, nullptr, &writable, nullptr, &timeout); + if (ready != SOCKET_ERROR) { if (ready <= 0) { return true; } + const int sent = g_connectionSend(this->m_socket, this->m_output.Data(), this->m_output.Available(), 0); if (sent != SOCKET_ERROR) { this->m_output.Consume(sent); @@ -158,6 +178,7 @@ bool CConnection::Flush() { } } } + return true; } @@ -166,6 +187,7 @@ bool CConnection::Flush() { bool CConnection::Update() { return this->m_socket == INVALID_SOCKET || (this->Receive() && this->Flush()); } + // OFFSET: 0x00C7CC60 // FUNCTION: fn_20400 void CConnection::UpdateStatus() { @@ -173,6 +195,7 @@ void CConnection::UpdateStatus() { this->m_status = !this->Receive() || !this->Flush(); } } + // OFFSET: 0x00C7CA10 // FUNCTION: fn_20394 int CConnection::Status() const { @@ -186,6 +209,7 @@ void CConnection::Send(int bytes, const void* data) { if (this->m_socket == INVALID_SOCKET) { return; } + this->m_output.Append(bytes, data); this->Flush(); } @@ -196,6 +220,7 @@ int CConnection::Read(void* output, int bytes, unsigned char exact) { if (exact != 0) { return this->m_input.Read(bytes, output) ? bytes : 0; } + const int available = std::min(bytes, this->m_input.Available()); this->m_input.Read(available, output); return available; @@ -208,6 +233,7 @@ bool CConnection::ReadPacket(void* output, unsigned short* bytes, const PacketLe if (!this->m_input.Peek(2, &id)) { return false; } + unsigned short size; if (lengths.Lookup(id).kind == 1) { size = static_cast(lengths.FixedLength(id)); @@ -216,26 +242,33 @@ bool CConnection::ReadPacket(void* output, unsigned short* bytes, const PacketLe if (!this->m_input.Peek(4, &header)) { return false; } + size = static_cast(header >> 16); } + if (!this->m_input.Read(size, output)) { return false; } + if (bytes) { *bytes = size; } + return true; } + // OFFSET: 0x00C7CEC0 // FUNCTION: fn_20406 void CConnection::Prepend(int bytes, const void* data) { this->m_input.Prepend(bytes, data); } + // OFFSET: 0x00C7CDB0 // FUNCTION: fn_20403 void CConnection::ResetDeferred() { this->m_pending.Reset(0xA000); } + // OFFSET: 0x00C7CDC0 // FUNCTION: fn_20404 void CConnection::ResetBuffers() { @@ -243,6 +276,7 @@ void CConnection::ResetBuffers() { this->m_output.Reset(0xA000); this->m_pending.Reset(0xA000); } + // OFFSET: 0x00C7CED0 // FUNCTION: fn_20407 void CConnection::SetDeferred(unsigned char value) { @@ -250,6 +284,7 @@ void CConnection::SetDeferred(unsigned char value) { if (value != 0) { return; } + while (this->m_pending.Available() != 0) { const int bytes = this->m_pending.Available(); this->m_output.Append(bytes, this->m_pending.Data()); @@ -261,8 +296,6 @@ void CConnection::SetDeferred(unsigned char value) { // OFFSET: 0x00C7D7D0 // FUNCTION: fn_20409 CRagConnection& GetRagConnection(ConnectionContext& context) { - // The original guard initializes one process-wide object, not one per - // context. The first context and its borrowed owners must outlive all uses. // STATIC: 0x016FDC98 // GLOBAL: gl_24490 static CRagConnection connection(context); diff --git a/Source/Network/Connection.h b/Source/Network/Connection/Connection.h similarity index 71% rename from Source/Network/Connection.h rename to Source/Network/Connection/Connection.h index 316a7b7..6cb1986 100644 --- a/Source/Network/Connection.h +++ b/Source/Network/Connection/Connection.h @@ -1,24 +1,20 @@ -#ifndef RAGNAROK_SOURCE_NETWORK_CONNECTION_H -#define RAGNAROK_SOURCE_NETWORK_CONNECTION_H +#ifndef RAGNAROK_SOURCE_NETWORK_CONNECTION_CONNECTION_H +#define RAGNAROK_SOURCE_NETWORK_CONNECTION_CONNECTION_H #include "Client/ClientOptions.h" -#include "Network/ConnectionBuffer.h" +#include "Network/Connection/ConnectionBuffer.h" #include class CRenderSystemBase; struct PacketLengths; -// Source view of original endpoint strings at+0/+20 and port at+16. -// The original trailing string's reservation is not established here. struct ConnectionEndpoint { const char* address; int port; const char* overrideAddress; }; -// Original patched connect cache is shared across connections, keyed by the -// Client session field. Caller supplies the actual owner values. struct ConnectionAddressCache { unsigned address = 0; unsigned session = 0xFFFFFFFFu; @@ -50,7 +46,6 @@ public: void ResetBuffers(); void SetDeferred(unsigned char value); - // Source views of original direct owner fields, not an alternate socket API. SOCKET NativeSocket() const { return this->m_socket; } @@ -73,7 +68,6 @@ protected: ConnectionContext* m_context; }; -// Original derived vtable changes only the deleting destructor entry. class CRagConnection : public CConnection { public: explicit CRagConnection(ConnectionContext& context); @@ -83,9 +77,6 @@ private: /* 006C */ unsigned char unknown_006C; }; -// Lazily constructs the original process-wide connection. Later calls retain -// the first context; callers must keep that context and its owners alive. -// Destruction releases buffers without implicitly closing the socket. CRagConnection& GetRagConnection(ConnectionContext& context); #if defined(_WIN32) && !defined(_WIN64) diff --git a/Source/Network/ConnectionBuffer.cpp b/Source/Network/Connection/ConnectionBuffer.cpp similarity index 77% rename from Source/Network/ConnectionBuffer.cpp rename to Source/Network/Connection/ConnectionBuffer.cpp index e6c939f..fb7f582 100644 --- a/Source/Network/ConnectionBuffer.cpp +++ b/Source/Network/Connection/ConnectionBuffer.cpp @@ -1,19 +1,13 @@ -#include "Network/ConnectionBuffer.h" +#include "Network/Connection/ConnectionBuffer.h" #include -#include #include -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } -} - // OFFSET: 0x00C7EF60 // FUNCTION: fn_20418 ConnectionBuffer::ConnectionBuffer() : m_data(nullptr) { } + // OFFSET: 0x00C7EFC0 // FUNCTION: fn_20419 ConnectionBuffer::~ConnectionBuffer() = default; @@ -37,28 +31,27 @@ int ConnectionBuffer::Available() const { // FUNCTION: fn_20423 void ConnectionBuffer::Append(int bytes, const void* source) { const int size = static_cast(this->m_storage.size()); - if (Add(this->m_write, bytes) > size) { - const int required = Add(this->Available(), bytes); + if ((this->m_write + bytes) > size) { + const int required = (this->Available() + bytes); if (required > size) { - // Original vector resize, not reserve: newly appended storage is zeroed. this->m_storage.resize(static_cast(required) * 2u); this->m_data = this->m_storage.data(); } - // Both original thunks import vcruntime140 memcpy. Its x86 implementation - // supports this overlapping left shift; use defined equivalent host code. + std::memmove(this->m_data, this->m_data + this->m_read, this->Available()); this->m_write = this->Available(); this->m_read = 0; } + std::memcpy(this->m_data + this->m_write, source, bytes); - this->m_write = Add(this->m_write, bytes); + this->m_write = (this->m_write + bytes); } // OFFSET: 0x00C7F160 // FUNCTION: fn_20424 void ConnectionBuffer::Prepend(int bytes, const void* source) { const int available = this->Available(); - const int required = Add(bytes, available); + const int required = (bytes + available); std::vector storage(static_cast(std::max(required, static_cast(this->m_storage.size())))); std::memcpy(storage.data(), source, bytes); std::memcpy(storage.data() + bytes, this->m_data + this->m_read, available); @@ -74,8 +67,9 @@ bool ConnectionBuffer::Read(int bytes, void* destination) { if (this->Available() < bytes) { return false; } + std::memcpy(destination, this->m_data + this->m_read, bytes); - this->m_read = Add(this->m_read, bytes); + this->m_read = (this->m_read + bytes); return true; } @@ -85,6 +79,7 @@ bool ConnectionBuffer::Peek(int bytes, void* destination) const { if (this->m_write - this->m_read < bytes) { return false; } + std::memcpy(destination, this->m_data + this->m_read, bytes); return true; } @@ -95,6 +90,7 @@ bool ConnectionBuffer::Consume(int bytes) { if (this->m_write - this->m_read < bytes) { return false; } + this->m_read += bytes; return true; } diff --git a/Source/Network/ConnectionBuffer.h b/Source/Network/Connection/ConnectionBuffer.h similarity index 71% rename from Source/Network/ConnectionBuffer.h rename to Source/Network/Connection/ConnectionBuffer.h index c626f7e..d5f55f7 100644 --- a/Source/Network/ConnectionBuffer.h +++ b/Source/Network/Connection/ConnectionBuffer.h @@ -1,10 +1,8 @@ -#ifndef RAGNAROK_SOURCE_NETWORK_CONNECTIONBUFFER_H -#define RAGNAROK_SOURCE_NETWORK_CONNECTIONBUFFER_H +#ifndef RAGNAROK_SOURCE_NETWORK_CONNECTION_CONNECTIONBUFFER_H +#define RAGNAROK_SOURCE_NETWORK_CONNECTION_CONNECTIONBUFFER_H #include -// Original24-byte connection buffer: borrowed data alias, signed read/write -// offsets, owned vector. Offsets become usable only after Reset. class ConnectionBuffer { public: ConnectionBuffer(); @@ -17,7 +15,6 @@ public: bool Peek(int bytes, void* destination) const; bool Consume(int bytes); - // Source view for original direct socket access; no copied packet storage. char* Data() const { return this->m_data + this->m_read; } diff --git a/Source/Network/ConnectionRuntime.cpp b/Source/Network/Connection/ConnectionRuntime.cpp similarity index 89% rename from Source/Network/ConnectionRuntime.cpp rename to Source/Network/Connection/ConnectionRuntime.cpp index e16baac..e491000 100644 --- a/Source/Network/ConnectionRuntime.cpp +++ b/Source/Network/Connection/ConnectionRuntime.cpp @@ -1,4 +1,4 @@ -#include "Network/ConnectionRuntime.h" +#include "Network/Connection/ConnectionRuntime.h" #include @@ -18,13 +18,16 @@ bool CheckConnectionRuntime() { if (!library) { return true; } + static const char* names[] = {"connect", "closesocket", "send", "select"}; + for (const char* name : names) { if (GetProcAddress(library, name) != GetProcAddress(module, name)) { FreeLibrary(library); return false; } } + FreeLibrary(library); return true; } @@ -33,12 +36,12 @@ bool CheckConnectionRuntime() { // FUNCTION: fn_20408 bool InitializeConnections() { WSADATA data; - WSAStartup(0x101, &data); + WSAStartup(MAKEWORD(1, 1), &data); module = LoadLibraryA("ws2_32.dll"); g_connectionSend = reinterpret_cast(GetProcAddress(module, "send")); g_connectionReceive = reinterpret_cast(GetProcAddress(module, "recv")); CheckConnectionRuntime(); - // Original ignores WSAStartup/load/address/check outcomes and returns true. + return true; } diff --git a/Source/Network/ConnectionRuntime.h b/Source/Network/Connection/ConnectionRuntime.h similarity index 68% rename from Source/Network/ConnectionRuntime.h rename to Source/Network/Connection/ConnectionRuntime.h index cf5ce3f..ea09384 100644 --- a/Source/Network/ConnectionRuntime.h +++ b/Source/Network/Connection/ConnectionRuntime.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_NETWORK_CONNECTIONRUNTIME_H -#define RAGNAROK_SOURCE_NETWORK_CONNECTIONRUNTIME_H +#ifndef RAGNAROK_SOURCE_NETWORK_CONNECTION_CONNECTIONRUNTIME_H +#define RAGNAROK_SOURCE_NETWORK_CONNECTION_CONNECTIONRUNTIME_H #include -// Dynamically resolved I/O entries. extern int(WSAAPI* g_connectionSend)(SOCKET socket, const char* data, int bytes, int flags); extern int(WSAAPI* g_connectionReceive)(SOCKET socket, char* data, int bytes, int flags); diff --git a/Source/Network/CURLMgr.cpp b/Source/Network/Http/CURLMgr.cpp similarity index 91% rename from Source/Network/CURLMgr.cpp rename to Source/Network/Http/CURLMgr.cpp index 17cba82..4b01f74 100644 --- a/Source/Network/CURLMgr.cpp +++ b/Source/Network/Http/CURLMgr.cpp @@ -1,11 +1,11 @@ -#include "Network/CURLMgr.h" +#include "Network/Http/CURLMgr.h" #include // STATIC: 0x013898CC // GLOBAL: gl_24354 CCURLMgr* g_curlMgr; -// Inlined constructor portion. + // OFFSET: 0x005E9290 // FUNCTION: fn_03952 CCURLMgr::CCURLMgr() : m_enabled(false), m_module(nullptr) { @@ -30,8 +30,6 @@ CCURLMgr::CCURLMgr() : m_enabled(false), m_module(nullptr) { // OFFSET: 0x005E8F70 // FUNCTION: fn_03950 CCURLMgr::~CCURLMgr() { - // The original unconditionally invokes this pointer, including its failed - // library-load destruction path. No invented safe fallback is supplied. this->globalCleanup(); if (this->m_module) { FreeLibrary(this->m_module); @@ -45,15 +43,18 @@ bool CCURLMgr::Initialize() { if (g_curlMgr) { return false; } + g_curlMgr = new (std::nothrow) CCURLMgr; if (!g_curlMgr) { return false; } + if (!g_curlMgr->m_enabled) { delete g_curlMgr; g_curlMgr = nullptr; return false; } + return true; } diff --git a/Source/Network/CURLMgr.h b/Source/Network/Http/CURLMgr.h similarity index 83% rename from Source/Network/CURLMgr.h rename to Source/Network/Http/CURLMgr.h index 5f09f0d..8a257c4 100644 --- a/Source/Network/CURLMgr.h +++ b/Source/Network/Http/CURLMgr.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_NETWORK_CURLMGR_H -#define RAGNAROK_SOURCE_NETWORK_CURLMGR_H +#ifndef RAGNAROK_SOURCE_NETWORK_HTTP_CURLMGR_H +#define RAGNAROK_SOURCE_NETWORK_HTTP_CURLMGR_H #include -// Opaque types belong to the supplied libcurl DLL ABI, not reconstructed fields. struct curl_slist; struct curl_httppost; diff --git a/Source/Network/CURLPostHander.cpp b/Source/Network/Http/CURLPostHander.cpp similarity index 90% rename from Source/Network/CURLPostHander.cpp rename to Source/Network/Http/CURLPostHander.cpp index 0b9d656..e08853c 100644 --- a/Source/Network/CURLPostHander.cpp +++ b/Source/Network/Http/CURLPostHander.cpp @@ -1,4 +1,4 @@ -#include "Network/CURLPostHander.h" +#include "Network/Http/CURLPostHander.h" #include @@ -24,10 +24,12 @@ CCURLPostHander::~CCURLPostHander() { g_curlMgr->easyCleanup(this->m_easy); this->m_easy = nullptr; } + if (this->m_form) { g_curlMgr->formFree(this->m_form); this->m_form = nullptr; } + if (this->m_headers) { g_curlMgr->slistFreeAll(this->m_headers); this->m_headers = nullptr; @@ -37,21 +39,16 @@ CCURLPostHander::~CCURLPostHander() { // OFFSET: 0x005E9960 // FUNCTION: fn_03958 int CCURLPostHander::AddField(std::string name, std::string value, int type) { - // Original CURLFORM_COPYNAME=1, caller-selected data option, CURLFORM_END=17. return g_curlMgr->formAdd(&this->m_form, &this->m_last, 1, name.c_str(), type, value.c_str(), 17); } // OFFSET: 0x005E9AF0 // FUNCTION: fn_03961 -std::size_t __cdecl CCURLPostHander::WriteResponse( - char* data, - std::size_t size, - std::size_t count, - std::string* response -) { +std::size_t __cdecl CCURLPostHander::WriteResponse(char* data, std::size_t size, std::size_t count, std::string* response) { if (!response) { return 0; } + response->append(data, size * count); return size * count; } @@ -62,6 +59,7 @@ int CCURLPostHander::Perform() { if (!this->m_easy) { return 2; } + g_curlMgr->easySetopt(this->m_easy, 10002, this->m_url.c_str()); g_curlMgr->easySetopt(this->m_easy, 10023, this->m_headers); g_curlMgr->easySetopt(this->m_easy, 47, 1L); @@ -70,6 +68,7 @@ int CCURLPostHander::Perform() { g_curlMgr->easySetopt(this->m_easy, 10001, &this->m_response); g_curlMgr->easySetopt(this->m_easy, 13, 3L); g_curlMgr->easySetopt(this->m_easy, 78, 3L); + return g_curlMgr->easyPerform(this->m_easy); } diff --git a/Source/Network/CURLPostHander.h b/Source/Network/Http/CURLPostHander.h similarity index 81% rename from Source/Network/CURLPostHander.h rename to Source/Network/Http/CURLPostHander.h index 2a2559c..a70f567 100644 --- a/Source/Network/CURLPostHander.h +++ b/Source/Network/Http/CURLPostHander.h @@ -1,12 +1,11 @@ -#ifndef RAGNAROK_SOURCE_NETWORK_CURLPOSTHANDER_H -#define RAGNAROK_SOURCE_NETWORK_CURLPOSTHANDER_H +#ifndef RAGNAROK_SOURCE_NETWORK_HTTP_CURLPOSTHANDER_H +#define RAGNAROK_SOURCE_NETWORK_HTTP_CURLPOSTHANDER_H -#include "Network/CURLMgr.h" +#include "Network/Http/CURLMgr.h" #include #include -// Original RTTI spelling is Hander, not Handler. class CCURLPostHander { public: explicit CCURLPostHander(std::string url); diff --git a/Source/Network/PacketLengths.cpp b/Source/Network/Packets/PacketLengths.cpp similarity index 93% rename from Source/Network/PacketLengths.cpp rename to Source/Network/Packets/PacketLengths.cpp index b01d230..308efc6 100644 --- a/Source/Network/PacketLengths.cpp +++ b/Source/Network/Packets/PacketLengths.cpp @@ -1,4 +1,4 @@ -#include "Network/PacketLengths.h" +#include "Network/Packets/PacketLengths.h" #include @@ -9,12 +9,15 @@ PacketLengthResult PacketLengths::Lookup(int id) const { if (entry == this->values.end()) { return {-1, 4}; } + if (entry->second.length == -1) { return {0, entry->second.variable}; } + if (entry->second.length < 0) { return {-1, 4}; } + return {1, entry->second.length}; } @@ -24,9 +27,11 @@ int PacketLengths::FixedLength(int id) const { if (id == 703) { return 12; } + if (id == 704) { return 4; } + return std::max(this->Lookup(id).length, 2); } @@ -40,7 +45,7 @@ namespace { // STATIC: 0x00B02294 // GLOBAL: gl_00808 constexpr PacketRegistration registrations[] = { -#include "Network/PacketRegistrations.inc" +#include "Network/Packets/PacketRegistrations.inc" }; } diff --git a/Source/Network/PacketLengths.h b/Source/Network/Packets/PacketLengths.h similarity index 75% rename from Source/Network/PacketLengths.h rename to Source/Network/Packets/PacketLengths.h index f16a541..f26bd1e 100644 --- a/Source/Network/PacketLengths.h +++ b/Source/Network/Packets/PacketLengths.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_NETWORK_PACKETLENGTHS_H -#define RAGNAROK_SOURCE_NETWORK_PACKETLENGTHS_H +#ifndef RAGNAROK_SOURCE_NETWORK_PACKETS_PACKETLENGTHS_H +#define RAGNAROK_SOURCE_NETWORK_PACKETS_PACKETLENGTHS_H #include @@ -14,7 +14,6 @@ struct PacketLengthResult { int length; }; -// Source view of packet metadata map. struct PacketLengths { const std::map& values; PacketLengthResult Lookup(int id) const; diff --git a/Source/Network/PacketRegistrations.inc b/Source/Network/Packets/PacketRegistrations.inc similarity index 95% rename from Source/Network/PacketRegistrations.inc rename to Source/Network/Packets/PacketRegistrations.inc index 31d7557..3071980 100644 --- a/Source/Network/PacketRegistrations.inc +++ b/Source/Network/Packets/PacketRegistrations.inc @@ -1,1744 +1,1744 @@ - {0, 7, 7, 1079}, - {0, 10, 10, 1080}, - {0, 5, 5, 863}, - {0, 6, 6, 864}, - {0, 10, 10, 2944}, - {0, 5, 5, 865}, - {0, 6, 6, 866}, - {0, 6, 6, 867}, - {0, 8, 8, 868}, - {0, 8, 8, 869}, - {0, 10, 10, 870}, - {0, 31, 31, 871}, - {0, 6, 6, 872}, - {0, 6, 6, 873}, - {0, 14, 14, 2108}, - {0, 2, 2, 2104}, - {0, 15, -1, 2101}, - {0, 12, -1, 2073}, - {0, 6, 6, 2071}, - {0, 2, 2, 2069}, - {0, 89, -1, 2065}, - {0, 18, 18, 2050}, - {0, 8, 8, 2028}, - {0, 12, -1, 2020}, - {0, 23, 23, 1078}, - {0, 23, 23, 9900}, - {0, 27, 27, 3001}, - {0, 26, 26, 708}, - {0, 4, 4, 641}, - {0, 26, 26, 514}, - {0, 5, 5, 557}, - {0, 36, 36, 571}, - {0, 1000, 1000, 3103}, - {0, 2, 2, 2138}, - {0, 2, 2, 2139}, - {0, 2, 2, 2140}, - {0, 2, 2, 2141}, - {0, 2, 2, 2142}, - {0, 2, 2, 2143}, - {0, 2, 2, 2144}, - {0, 2, 2, 2145}, - {0, 2, 2, 2146}, - {0, 2, 2, 2147}, - {0, 2, 2, 2148}, - {0, 2, 2, 2149}, - {0, 2, 2, 2150}, - {0, 2, 2, 2151}, - {0, 2, 2, 2152}, - {0, 2, 2, 2153}, - {0, 2, 2, 2154}, - {0, 2, 2, 2155}, - {0, 2, 2, 2156}, - {0, 2, 2, 2157}, - {0, 2, 2, 2158}, - {0, 2, 2, 2159}, - {0, 2, 2, 2160}, - {0, 2, 2, 2161}, - {0, 2, 2, 2162}, - {0, 2, 2, 2163}, - {0, 2, 2, 2164}, - {0, 2, 2, 2165}, - {0, 2, 2, 2166}, - {0, 2, 2, 2167}, - {0, 2, 2, 2168}, - {0, 2, 2, 2169}, - {0, 2, 2, 2170}, - {0, 2, 2, 2171}, - {0, 2, 2, 2172}, - {0, 2, 2, 2173}, - {0, 2, 2, 2174}, - {0, 2, 2, 2175}, - {0, 2, 2, 2176}, - {0, 2, 2, 2177}, - {0, 2, 2, 2178}, - {0, 2, 2, 2179}, - {0, 2, 2, 2327}, - {0, 2, 2, 2328}, - {0, 2, 2, 2329}, - {0, 2, 2, 2330}, - {0, 2, 2, 2331}, - {0, 2, 2, 2332}, - {0, 2, 2, 2333}, - {0, 2, 2, 2334}, - {0, 2, 2, 2335}, - {0, 2, 2, 2336}, - {0, 2, 2, 2337}, - {0, 2, 2, 2338}, - {0, 2, 2, 2339}, - {0, 2, 2, 2340}, - {0, 2, 2, 2341}, - {0, 2, 2, 2342}, - {0, 2, 2, 2343}, - {0, 2, 2, 2344}, - {0, 2, 2, 2345}, - {0, 2, 2, 2346}, - {0, 2, 2, 2347}, - {0, 2, 2, 2348}, - {0, 2, 2, 2349}, - {0, 2, 2, 2350}, - {0, 2, 2, 2351}, - {0, 2, 2, 2352}, - {0, 2, 2, 2353}, - {0, 2, 2, 2354}, - {0, 2, 2, 2355}, - {0, 2, 2, 2356}, - {0, 2, 2, 2357}, - {0, 2, 2, 2358}, - {0, 2, 2, 2359}, - {0, 2, 2, 2360}, - {0, 2, 2, 2361}, - {0, 2, 2, 2362}, - {0, 2, 2, 2363}, - {0, 2, 2, 2364}, - {0, 2, 2, 2365}, - {0, 2, 2, 2366}, - {0, 2, 2, 2367}, - {0, 2, 2, 2368}, - {0, 2, 2, 2180}, - {0, 2, 2, 2181}, - {0, 2, 2, 2182}, - {0, 2, 2, 2183}, - {0, 2, 2, 2184}, - {0, 2, 2, 2185}, - {0, 2, 2, 2186}, - {0, 2, 2, 2187}, - {0, 2, 2, 2188}, - {0, 2, 2, 2189}, - {0, 2, 2, 2190}, - {0, 2, 2, 2191}, - {0, 2, 2, 2192}, - {0, 2, 2, 2193}, - {0, 2, 2, 2194}, - {0, 2, 2, 2195}, - {0, 2, 2, 2196}, - {0, 2, 2, 2197}, - {0, 2, 2, 2198}, - {0, 2, 2, 2199}, - {0, 2, 2, 2200}, - {0, 2, 2, 2201}, - {0, 2, 2, 2202}, - {0, 2, 2, 2203}, - {0, 2, 2, 2204}, - {0, 2, 2, 2205}, - {0, 2, 2, 2206}, - {0, 2, 2, 2207}, - {0, 2, 2, 2208}, - {0, 2, 2, 2209}, - {0, 2, 2, 2210}, - {0, 2, 2, 2211}, - {0, 2, 2, 2212}, - {0, 2, 2, 2213}, - {0, 2, 2, 2214}, - {0, 2, 2, 2215}, - {0, 2, 2, 2216}, - {0, 2, 2, 2217}, - {0, 2, 2, 2218}, - {0, 2, 2, 2219}, - {0, 2, 2, 2220}, - {0, 2, 2, 2221}, - {0, 2, 2, 2369}, - {0, 2, 2, 2370}, - {0, 2, 2, 2371}, - {0, 2, 2, 2372}, - {0, 2, 2, 2373}, - {0, 2, 2, 2374}, - {0, 2, 2, 2375}, - {0, 2, 2, 2376}, - {0, 2, 2, 2377}, - {0, 2, 2, 2378}, - {0, 2, 2, 2379}, - {0, 2, 2, 2380}, - {0, 2, 2, 2381}, - {0, 2, 2, 2382}, - {0, 2, 2, 2383}, - {0, 2, 2, 2384}, - {0, 2, 2, 2385}, - {0, 2, 2, 2386}, - {0, 2, 2, 2387}, - {0, 2, 2, 2388}, - {0, 2, 2, 2389}, - {0, 2, 2, 2390}, - {0, 2, 2, 2391}, - {0, 2, 2, 2392}, - {0, 2, 2, 2393}, - {0, 2, 2, 2394}, - {0, 2, 2, 2395}, - {0, 2, 2, 2396}, - {0, 2, 2, 2397}, - {0, 2, 2, 2398}, - {0, 2, 2, 2399}, - {0, 2, 2, 2400}, - {0, 2, 2, 2401}, - {0, 2, 2, 2402}, - {0, 2, 2, 2403}, - {0, 2, 2, 2404}, - {0, 2, 2, 2405}, - {0, 2, 2, 2406}, - {0, 2, 2, 2407}, - {0, 2, 2, 2408}, - {0, 2, 2, 2409}, - {0, 2, 2, 2410}, - {0, 1000, 1000, 3103}, - {0, 6, 6, 391}, - {0, 3, 3, 129}, - {0, 4, 4, 454}, - {1, 2, 2, 455}, - {0, 55, 55, 100}, - {0, 47, -1, 105}, - {0, 23, 23, 106}, - {0, 2, 2, 475}, - {0, 4, -1, 476}, - {0, 47, 47, 477}, - {0, 48, 48, 506}, - {0, 18, 18, 516}, - {0, 4, -1, 497}, - {0, 26, 26, 512}, - {0, 2, 2, 446}, - {0, 3, 3, 447}, - {0, 17, 17, 101}, - {0, 3, 3, 102}, - {0, 37, 37, 103}, - {0, 31, 31, 2416}, - {0, 4, -1, 525}, - {0, 24, -1, 107}, - {0, 3, 3, 108}, - {0, 157, 157, 109}, - {0, 3, 3, 110}, - {0, 28, 28, 113}, - {0, 46, 46, 104}, - {0, 56, 56, 507}, - {0, 2, 2, 111}, - {0, 3, 3, 112}, - {0, 3, 3, 714}, - {0, 34, 34, 155}, - {0, 2, 2, 130}, - {0, 9, 9, 167}, - {0, 23, 23, 400}, - {0, 4, -1, 243}, - {0, 11, 11, 137}, - {0, 2, 2, 125}, - {0, 7, 7, 144}, - {0, 4, -1, 153}, - {0, 4, -1, 412}, - {0, 10, 10, 133}, - {0, 6, 6, 204}, - {0, 2, 2, 206}, - {0, 11, 11, 245}, - {0, 17, 17, 278}, - {0, 20, 20, 159}, - {0, 6, 6, 169}, - {0, 4, 4, 171}, - {0, 7, 7, 184}, - {0, 6, 6, 185}, - {0, 3, 3, 178}, - {0, 2, 2, 186}, - {0, 5, 5, 187}, - {0, 3, 3, 191}, - {0, 2, 2, 193}, - {0, 7, 7, 197}, - {0, 4, -1, 200}, - {0, 4, -1, 201}, - {0, 28, -1, 150}, - {0, 27, 27, 207}, - {0, 3, 3, 208}, - {0, 2, 2, 211}, - {0, 15, -1, 213}, - {0, 14, 14, 217}, - {0, 15, -1, 222}, - {0, 30, 30, 224}, - {0, 26, 26, 226}, - {0, 2, 2, 227}, - {0, 6, 6, 228}, - {0, 3, 3, 230}, - {0, 8, 8, 232}, - {0, 2, 2, 235}, - {0, 2, 2, 237}, - {0, 2, 2, 239}, - {0, 19, 19, 148}, - {0, 17, 17, 247}, - {0, 2, 2, 403}, - {0, 26, 26, 249}, - {0, 28, 28, 488}, - {0, 6, 6, 252}, - {0, 10, 10, 255}, - {0, 6, 6, 258}, - {0, 2, 2, 256}, - {0, 30, 30, 259}, - {0, 4, -1, 264}, - {0, 4, 4, 274}, - {0, 22, 22, 114}, - {0, 25, 25, 275}, - {0, 2, 2, 280}, - {0, 20, 20, 283}, - {0, 2, 2, 285}, - {0, 8, 8, 294}, - {0, 8, 8, 295}, - {0, 8, 8, 296}, - {0, 8, 8, 297}, - {0, 2, 2, 298}, - {0, 2, 2, 302}, - {0, 84, -1, 303}, - {0, 85, -1, 434}, - {0, 8, -1, 308}, - {0, 6, 6, 304}, - {0, 3, 3, 312}, - {0, 26, 26, 319}, - {0, 22, 22, 320}, - {0, 10, 10, 323}, - {0, 6, 6, 326}, - {0, 4, 4, 376}, - {0, 4, 4, 378}, - {0, 6, 6, 380}, - {0, 25, 25, 509}, - {0, 4, 4, 394}, - {0, 18, 18, 398}, - {0, 46, 46, 126}, - {0, 4, 4, 407}, - {0, 8, 8, 408}, - {0, 6, 6, 430}, - {0, 8, 8, 603}, - {0, 4, 4, 431}, - {1, 6, 6, 441}, - {1, 30, 30, 461}, - {0, 6, 6, 462}, - {1, 28, 28, 463}, - {1, 8, 8, 464}, - {1, 8, 8, 481}, - {1, 14, 14, 465}, - {1, 10, 10, 466}, - {0, 14, 14, 140}, - {1, 30, 30, 149}, - {1, 102, 102, 405}, - {0, 14, 14, 162}, - {0, 6, 6, 373}, - {0, 106, 106, 374}, - {1, 53, 53, 121}, - {0, 6, 6, 413}, - {1, 4, -1, 332}, - {0, 2, 2, 333}, - {1, 6, 6, 334}, - {0, 6, 6, 335}, - {1, 110, 110, 336}, - {1, 114, 114, 438}, - {0, 6, 6, 337}, - {1, 12, -1, 338}, - {0, 4, -1, 339}, - {1, 4, -1, 340}, - {1, 4, -1, 358}, - {0, 4, -1, 341}, - {1, 4, -1, 342}, - {0, 6, 6, 343}, - {0, 54, 54, 345}, - {1, 66, 66, 346}, - {0, 54, 54, 347}, - {1, 90, 90, 348}, - {0, 42, 42, 349}, - {1, 6, 6, 350}, - {1, 42, 42, 351}, - {1, 4, -1, 352}, - {0, 4, -1, 353}, - {1, 6, -1, 354}, - {1, 4, -1, 355}, - {1, 4, -1, 356}, - {0, 30, 30, 357}, - {1, 3, 3, 359}, - {0, 14, 14, 360}, - {1, 3, 3, 361}, - {1, 30, 30, 362}, - {0, 10, 10, 363}, - {0, 9, 9, 329}, - {1, 6, 6, 330}, - {1, 27, 27, 331}, - {0, 186, 186, 366}, - {1, 182, 182, 367}, - {0, 4, -1, 382}, - {1, 4, -1, 383}, - {1, 43, 43, 364}, - {1, 47, 47, 759}, - {1, 36, -1, 760}, - {1, 8, -1, 761}, - {0, 7, -1, 762}, - {1, 32, -1, 763}, - {1, 44, -1, 764}, - {1, 14, 14, 365}, - {1, 20, 20, 498}, - {0, 14, 14, 368}, - {1, 30, 30, 369}, - {0, 10, 10, 370}, - {1, 3, 3, 371}, - {1, 4, -1, 372}, - {0, 6, 6, 384}, - {1, 3, 3, 385}, - {1, 106, 106, 386}, - {0, 10, 10, 387}, - {1, 10, 10, 388}, - {1, 34, 34, 389}, - {1, 2, 2, 414}, - {0, 6, 6, 415}, - {1, 3, 3, 416}, - {0, 3, 3, 417}, - {1, 37, 37, 418}, - {1, 7, 7, 419}, - {1, 11, 11, 420}, - {0, 26, 26, 421}, - {1, 4, -1, 422}, - {0, 4, 4, 423}, - {0, 4, 4, 424}, - {0, 6, 6, 425}, - {1, 10, 10, 426}, - {0, 3, 3, 458}, - {1, 11, 11, 432}, - {1, 7, 7, 433}, - {0, 26, 26, 442}, - {0, 26, 26, 443}, - {0, 26, 26, 444}, - {0, 26, 26, 445}, - {0, 2, 2, 448}, - {1, 14, 14, 449}, - {1, 10, 10, 450}, - {1, 35, 35, 467}, - {0, 8, -1, 469}, - {1, 6, 6, 468}, - {0, 6, 6, 479}, - {1, 10, 10, 499}, - {1, 14, 14, 644}, - {1, 10, 10, 511}, - {0, 2, 2, 493}, - {0, 2, 2, 487}, - {0, 6, 6, 439}, - {0, 14, 14, 503}, - {0, 14, 14, 483}, - {0, 9, 9, 459}, - {0, 6, 6, 505}, - {0, 6, 6, 485}, - {1, 4, -1, 513}, - {0, 10, 10, 515}, - {1, 26, 26, 517}, - {1, 35, 35, 518}, - {1, 34, 34, 519}, - {0, 14, 14, 520}, - {1, 36, 36, 521}, - {1, 10, 10, 522}, - {1, 32, 32, 526}, - {0, 26, 26, 530}, - {0, 26, 26, 531}, - {1, 42, 42, 532}, - {1, 6, 6, 533}, - {1, 6, 6, 534}, - {0, 2, 2, 535}, - {0, 2, 2, 536}, - {0, 2, 2, 549}, - {1, 282, 282, 537}, - {1, 282, 282, 538}, - {1, 282, 282, 550}, - {1, 284, 284, 642}, - {1, 10, 10, 539}, - {1, 10, 10, 540}, - {1, 10, 10, 548}, - {1, 12, 12, 640}, - {1, 6, 6, 645}, - {0, 4, 4, 646}, - {0, 6, 6, 541}, - {0, 6, 6, 542}, - {1, 66, 66, 543}, - {0, 6, 6, 546}, - {1, 4, -1, 545}, - {1, 10, 10, 544}, - {1, 10, 10, 547}, - {1, 11, 11, 115}, - {0, 3, 3, 116}, - {1, 11, -1, 117}, - {1, 9, 9, 118}, - {1, 5, 5, 119}, - {1, 55, 55, 120}, - {1, 58, 58, 122}, - {1, 60, 60, 123}, - {1, 44, 44, 124}, - {1, 6, 6, 127}, - {1, 7, 7, 128}, - {1, 2, 2, 131}, - {1, 2, 2, 132}, - {1, 16, 16, 134}, - {1, 12, 12, 135}, - {1, 16, 16, 3000}, - {1, 10, 10, 136}, - {1, 10, 10, 2253}, - {1, 29, 29, 138}, - {1, 23, 23, 139}, - {1, 8, -1, 141}, - {1, 4, -1, 142}, - {1, 22, 22, 145}, - {1, 28, 28, 146}, - {1, 2, 2, 147}, - {1, 32, -1, 151}, - {1, 3, 3, 152}, - {1, 4, -1, 154}, - {1, 9, 9, 156}, - {1, 19, 19, 157}, - {1, 19, 19, 158}, - {1, 33, 33, 160}, - {1, 6, 6, 161}, - {1, 4, -1, 163}, - {1, 4, -1, 164}, - {1, 4, -1, 165}, - {1, 4, -1, 166}, - {1, 7, 7, 168}, - {1, 9, 9, 170}, - {1, 7, 7, 172}, - {1, 4, -1, 174}, - {1, 6, 6, 175}, - {1, 8, 8, 176}, - {1, 8, 8, 177}, - {0, 3, 3, 179}, - {1, 8, -1, 180}, - {1, 6, 6, 181}, - {1, 6, 6, 182}, - {1, 8, -1, 183}, - {1, 8, -1, 3100}, - {1, 6, 6, 188}, - {1, 44, 44, 189}, - {1, 5, 5, 190}, - {1, 7, 7, 192}, - {1, 6, 6, 194}, - {1, 8, 8, 195}, - {1, 6, 6, 196}, - {1, 4, -1, 198}, - {1, 4, -1, 199}, - {1, 3, 3, 202}, - {1, 3, 3, 203}, - {1, 3, 3, 205}, - {1, 4, 4, 209}, - {1, 4, 4, 210}, - {1, 4, -1, 212}, - {1, 3, 3, 214}, - {1, 17, -1, 215}, - {1, 6, 6, 216}, - {1, 3, 3, 218}, - {1, 8, -1, 219}, - {1, 28, 28, 220}, - {1, 29, 29, 221}, - {1, 17, -1, 223}, - {1, 30, 30, 225}, - {1, 26, 26, 229}, - {1, 3, 3, 231}, - {1, 29, 29, 233}, - {1, 5, 5, 234}, - {1, 3, 3, 236}, - {1, 2, 2, 238}, - {1, 3, 3, 240}, - {1, 2, 2, 241}, - {1, 6, 6, 242}, - {1, 31, 31, 244}, - {1, 8, 8, 246}, - {1, 2, 2, 248}, - {1, 3, 3, 250}, - {1, 28, -1, 251}, - {1, 27, 27, 253}, - {1, 30, 30, 254}, - {1, 6, 6, 257}, - {1, 79, 79, 260}, - {1, 31, 31, 261}, - {1, 10, 10, 262}, - {1, 10, 10, 263}, - {1, 8, -1, 265}, - {1, 6, 6, 266}, - {1, 6, 6, 267}, - {1, 6, 6, 268}, - {1, 2, 2, 269}, - {1, 11, 11, 270}, - {1, 4, -1, 271}, - {1, 8, -1, 689}, - {1, 8, -1, 690}, - {1, 6, -1, 693}, - {1, 14, 14, 272}, - {1, 39, 39, 273}, - {1, 31, 31, 276}, - {1, 35, 35, 277}, - {1, 18, 18, 279}, - {1, 13, 13, 281}, - {1, 15, 15, 553}, - {1, 15, 15, 282}, - {1, 68, 68, 284}, - {1, 3, 3, 286}, - {1, 16, 16, 287}, - {1, 6, 6, 288}, - {1, 14, 14, 289}, - {1, 4, -1, 290}, - {1, 4, -1, 291}, - {1, 31, 31, 292}, - {1, 8, 8, 293}, - {1, 2, 2, 299}, - {1, 3, 3, 300}, - {1, 4, 4, 301}, - {1, 86, 86, 305}, - {1, 6, 6, 306}, - {1, 8, -1, 307}, - {1, 7, 7, 309}, - {1, 8, -1, 310}, - {1, 6, 6, 311}, - {1, 16, 16, 313}, - {1, 4, 4, 314}, - {1, 4, 4, 315}, - {1, 4, 4, 316}, - {1, 6, 6, 317}, - {1, 24, 24, 318}, - {1, 14, 14, 321}, - {1, 6, 6, 322}, - {1, 23, 23, 324}, - {1, 19, 19, 325}, - {1, 39, 39, 327}, - {1, 8, 8, 328}, - {1, 4, -1, 375}, - {1, 5, 5, 377}, - {1, 4, -1, 379}, - {1, 7, 7, 381}, - {1, 8, 8, 392}, - {1, 4, 4, 393}, - {0, 4, 4, 395}, - {1, 29, 29, 396}, - {1, 4, -1, 397}, - {1, 8, 8, 399}, - {1, 27, 27, 401}, - {1, 24, 24, 402}, - {1, 30, 30, 404}, - {1, 9, 9, 406}, - {1, 18, 18, 650}, - {1, 4, 4, 409}, - {1, 14, 14, 410}, - {1, 10, 10, 411}, - {1, 12, 12, 427}, - {1, 6, 6, 428}, - {1, 4, -1, 429}, - {1, 4, -1, 602}, - {1, 67, 67, 435}, - {1, 12, 12, 436}, - {0, 18, 18, 437}, - {1, 3, 3, 440}, - {1, 16, -1, 451}, - {1, 32, 32, 452}, - {1, 32, 32, 453}, - {1, 15, 15, 456}, - {1, 97, 97, 457}, - {1, 9, 9, 460}, - {1, 4, 4, 470}, - {1, 15, 15, 471}, - {1, 58, 58, 472}, - {1, 62, 62, 554}, - {1, 57, 57, 473}, - {1, 61, 61, 555}, - {1, 64, 64, 474}, - {1, 69, 69, 556}, - {1, 33, 33, 478}, - {1, 30, 30, 480}, - {1, 34, 34, 482}, - {1, 2, 2, 484}, - {1, 26, 26, 486}, - {1, 81, 81, 489}, - {1, 6, 6, 490}, - {1, 10, 10, 491}, - {1, 26, 26, 492}, - {1, 4, -1, 494}, - {1, 4, -1, 495}, - {1, 4, -1, 496}, - {1, 32, 32, 500}, - {1, 9, 9, 501}, - {1, 34, 34, 502}, - {1, 3, 3, 595}, - {0, 3, 3, 596}, - {1, 2, 2, 504}, - {1, 4, -1, 508}, - {1, 5, 5, 510}, - {0, 18, 18, 551}, - {0, 18, 18, 552}, - {0, 9, 9, 562}, - {0, 11, 11, 563}, - {0, 6, 6, 564}, - {1, 12, 12, 560}, - {1, 73, 73, 558}, - {0, 62, 62, 637}, - {1, 4, -1, 565}, - {1, 11, 11, 569}, - {1, 7, 7, 559}, - {0, 26, 26, 561}, - {0, 2, 2, 567}, - {1, 282, 282, 568}, - {1, 10, 10, 566}, - {0, 4, 4, 570}, - {0, 6, 6, 572}, - {0, 6, 6, 573}, - {0, 8, 8, 574}, - {0, 2, 2, 575}, - {1, 8, -1, 576}, - {0, 6, 6, 577}, - {1, 109, -1, 578}, - {0, 6, 6, 579}, - {1, 8, 8, 599}, - {0, 6, 6, 580}, - {1, 3, 3, 581}, - {0, 4, 4, 582}, - {0, 8, 8, 583}, - {0, 68, -1, 584}, - {1, 3, 3, 585}, - {1, 70, 70, 586}, - {0, 4, 4, 587}, - {0, 8, 8, 588}, - {0, 12, 12, 589}, - {0, 6, 6, 590}, - {0, 10, 10, 591}, - {1, 3, 3, 592}, - {0, 34, 34, 593}, - {1, 12, -1, 594}, - {1, 5, 5, 597}, - {1, 5, 5, 598}, - {0, 2, 2, 600}, - {0, 3, 3, 601}, - {0, 4, 4, 604}, - {1, 6, 6, 605}, - {0, 4, 4, 606}, - {1, 6, 6, 607}, - {1, 6, 6, 608}, - {0, 11, 11, 609}, - {0, 11, 11, 610}, - {0, 11, 11, 611}, - {0, 20, 20, 612}, - {0, 20, 20, 613}, - {0, 30, 30, 614}, - {0, 4, 4, 615}, - {0, 4, 4, 616}, - {0, 4, 4, 617}, - {0, 4, 4, 618}, - {0, 4, 4, 619}, - {0, 4, 4, 620}, - {0, 4, 4, 621}, - {0, 2, 2, 623}, - {0, 2, 2, 624}, - {0, 40, 40, 625}, - {0, 44, 44, 626}, - {0, 30, 30, 627}, - {1, 8, 8, 628}, - {0, 37, 37, 629}, - {0, 51, -1, 630}, - {0, 84, 84, 631}, - {0, 2, 2, 632}, - {0, 2, 2, 633}, - {1, 4, -1, 634}, - {0, 14, 14, 635}, - {0, 60, 60, 636}, - {0, 6, -1, 638}, - {0, 8, 8, 639}, - {1, 6, 6, 643}, - {1, 12, -1, 647}, - {0, 10, -1, 648}, - {1, 12, 12, 649}, - {1, 12, -1, 1092}, - {0, 12, 12, 1093}, - {0, 4, -1, 651}, - {0, 46, 46, 652}, - {0, 34, 34, 653}, - {0, 4, 4, 654}, - {0, 6, 6, 655}, - {0, 4, 4, 656}, - {1, 4, 4, 657}, - {0, 2, 2, 658}, - {1, 70, 70, 659}, - {1, 10, 10, 660}, - {1, 4, -1, 661}, - {1, 4, -1, 662}, - {1, 4, -1, 663}, - {1, 10, 10, 664}, - {1, 8, 8, 665}, - {1, 37, 37, 666}, - {1, 80, 80, 667}, - {0, 66, 66, 668}, - {1, 4, -1, 669}, - {1, 11, 11, 670}, - {0, 3, 3, 671}, - {1, 8, 8, 674}, - {0, 8, 8, 677}, - {0, 10, -1, 678}, - {0, 10, -1, 679}, - {0, 4, 4, 682}, - {0, 36, 36, 683}, - {0, 6, 6, 684}, - {0, 8, 8, 685}, - {0, 85, 85, 688}, - {1, 32, 32, 696}, - {1, 8, 8, 699}, - {1, 191, 191, 697}, - {0, 11, 11, 698}, - {0, 6, 6, 700}, - {1, 107, 107, 691}, - {1, 6, 6, 692}, - {0, 7, 7, 694}, - {1, 7, 7, 695}, - {1, 12, -1, 705}, - {1, 6, -1, 706}, - {1, 30, 30, 709}, - {0, 3, 3, 712}, - {1, 3, 3, 713}, - {1, 30, 30, 710}, - {0, 7, 7, 711}, - {1, 65, 65, 715}, - {1, 4, 4, 716}, - {1, 71, 71, 717}, - {1, 10, 10, 718}, - {0, 6, 6, 719}, - {1, 2, 2, 725}, - {1, 4, -1, 720}, - {1, 4, -1, 721}, - {1, 4, -1, 722}, - {1, 4, 4, 723}, - {1, 39, 39, 724}, - {0, 6, 6, 726}, - {1, 43, -1, 727}, - {0, 10, 10, 728}, - {1, 10, 10, 729}, - {1, 3, 3, 730}, - {0, 4, -1, 731}, - {1, 32, -1, 732}, - {1, 32, 32, 733}, - {1, 6, 6, 734}, - {1, 36, 36, 735}, - {1, 34, 34, 736}, - {1, 33, 33, 737}, - {0, 20, 20, 738}, - {0, 22, 22, 739}, - {0, 11, 11, 740}, - {0, 9, 9, 741}, - {0, 6, 6, 742}, - {1, 6, -1, 743}, - {1, 4, -1, 744}, - {1, 4, -1, 745}, - {1, 4, -1, 746}, - {1, 13, 13, 747}, - {1, 71, 71, 748}, - {1, 63, 63, 749}, - {1, 64, 64, 750}, - {1, 8, 8, 751}, - {1, 10, 10, 752}, - {0, 2, 2, 753}, - {1, 2, 2, 754}, - {0, 2, 2, 860}, - {0, 20, -1, 861}, - {0, 2, 2, 862}, - {0, 18, 18, 989}, - {0, 18, 18, 990}, - {0, 8, 8, 1081}, - {1, 8, 8, 1085}, - {1, 4, -1, 1086}, - {1, 25, 25, 1087}, - {1, 10, 10, 1088}, - {1, 4, 4, 1089}, - {1, 8, -1, 1090}, - {0, 8, 8, 1091}, - {1, 14, 14, 1094}, - {0, 4, -1, 1096}, - {0, 4, 4, 1097}, - {0, 6, 6, 1098}, - {0, 2, 2, 1099}, - {0, 2, 2, 1095}, - {0, 8, 8, 2007}, - {1, 8, 8, 2008}, - {1, 268, 268, 2009}, - {0, 6, 6, 2010}, - {1, 8, 8, 2011}, - {0, 6, 6, 2012}, - {1, 54, 54, 2013}, - {0, 30, 30, 2014}, - {0, 54, 54, 2015}, - {0, 58, 58, 2016}, - {1, 15, 15, 2017}, - {1, 8, 8, 2018}, - {1, 6, 6, 2019}, - {1, 8, 8, 2022}, - {0, 4, 4, 2021}, - {0, 4, -1, 2024}, - {0, 32, 32, 2023}, - {0, 5, 5, 2025}, - {0, 2, 2, 2026}, - {1, 8, -1, 2027}, - {1, 10, 10, 2029}, - {0, 6, 6, 2030}, - {1, 8, 8, 2031}, - {0, 6, 6, 2032}, - {1, 18, 18, 2033}, - {1, 8, 8, 2034}, - {1, 6, 6, 2035}, - {0, 3, 3, 2036}, - {0, 6, 6, 2037}, - {1, 14, 14, 2038}, - {1, 73, -1, 2039}, - {1, 66, -1, 2040}, - {1, 67, -1, 2041}, - {1, 8, 8, 2042}, - {1, 25, 25, 2043}, - {1, 10, 10, 2044}, - {1, 9, -1, 2045}, - {1, 26, 26, 2046}, - {1, 32, -1, 3127}, - {1, 32, -1, 3128}, - {1, 56, -1, 3129}, - {1, 41, -1, 3130}, - {1, 12, -1, 2048}, - {0, 12, -1, 2049}, - {1, 4, 4, 2051}, - {0, 14, 14, 2052}, - {1, 5, -1, 2053}, - {0, 2, 2, 2054}, - {1, 4, 4, 2055}, - {0, 14, 14, 2056}, - {1, 50, 50, 2057}, - {1, 18, 18, 2058}, - {1, 6, 6, 2059}, - {0, 2, 2, 2060}, - {1, 3, 3, 2061}, - {1, 14, 14, 2062}, - {1, 30, 30, 2063}, - {1, 3, 3, 2064}, - {1, 8, 8, 2066}, - {1, 12, -1, 2067}, - {1, 86, 86, 2068}, - {1, 6, 6, 2070}, - {1, 16, -1, 2072}, - {1, 4, 4, 2074}, - {1, 8, 8, 2084}, - {1, 12, 12, 2075}, - {1, 10, 10, 2076}, - {1, 22, 22, 2077}, - {1, 8, 8, 2078}, - {1, 9, -1, 2079}, - {0, 11, 11, 2080}, - {0, 2, 2, 2081}, - {0, 9, 9, 2082}, - {0, 4, -1, 2083}, - {0, 92, -1, 2085}, - {0, 156, -1, 3112}, - {0, 7, -1, 2102}, - {0, 3, 3, 2103}, - {1, 66, 66, 2105}, - {0, 5, 5, 2106}, - {0, 2, 2, 2107}, - {0, 6, 6, 2109}, - {0, 26, 26, 2110}, - {0, 4, -1, 2112}, - {0, 4, 4, 2113}, - {0, 6, 6, 2087}, - {0, 14, 14, 2088}, - {0, 12, 12, 2089}, - {0, 10, 10, 2090}, - {0, 6, 6, 2091}, - {0, 10, 10, 2092}, - {0, 6, 6, 2114}, - {0, 6, 6, 2115}, - {0, 2, 2, 2116}, - {0, 10, 10, 2117}, - {0, 4, 4, 2118}, - {0, 6, -1, 2119}, - {0, 10, -1, 2120}, - {0, 16, 16, 2121}, - {0, 2, 2, 2122}, - {1, 21, 21, 2123}, - {0, 10, 10, 2124}, - {0, 10, 10, 2125}, - {0, 5, 5, 2126}, - {0, 6, 6, 2127}, - {0, 7, 7, 2128}, - {0, 6, 6, 2133}, - {0, 4, -1, 2129}, - {0, 2, 2, 2130}, - {0, 4, -1, 2131}, - {0, 4, -1, 2132}, - {1, 75, -1, 2134}, - {1, 69, -1, 2135}, - {1, 68, -1, 2136}, - {1, 45, -1, 2137}, - {0, 4, -1, 2225}, - {0, 29, -1, 2093}, - {0, 6, -1, 2226}, - {0, 10, 10, 2223}, - {0, 17, 17, 2224}, - {0, 8, -1, 2227}, - {0, 2, 2, 2228}, - {0, 6, 6, 2229}, - {0, 3, 3, 2230}, - {0, 68, -1, 755}, - {0, 3, 3, 756}, - {0, 7, 7, 757}, - {0, 7, 7, 758}, - {0, 10, 10, 2232}, - {0, 12, 12, 2233}, - {0, 10, 10, 2234}, - {0, 8, 8, 2235}, - {0, 10, 10, 2236}, - {0, 8, 8, 2237}, - {0, 14, 14, 2238}, - {0, 8, 8, 2239}, - {0, 10, 10, 2243}, - {0, 8, 8, 2244}, - {0, 6, 6, 2245}, - {0, 4, 4, 2246}, - {0, 10, -1, 2240}, - {0, 2, 2, 2241}, - {0, 2, 2, 2242}, - {1, 19, -1, 2247}, - {1, 34, 34, 2248}, - {0, 2, 2, 2249}, - {0, 8, -1, 2250}, - {0, 10, -1, 2251}, - {0, 16, -1, 2427}, - {0, 109, 109, 2252}, - {0, 2, 2, 2254}, - {0, 10, 10, 2255}, - {1, 9, 9, 2256}, - {1, 7, 7, 2257}, - {1, 10, 10, 2258}, - {0, 10, 10, 2259}, - {0, 8, 8, 2260}, - {0, 8, -1, 2261}, - {0, 6, 6, 2262}, - {1, 28, 28, 2263}, - {1, 27, 27, 2264}, - {1, 30, 30, 2265}, - {1, 26, 26, 2266}, - {1, 27, 27, 2267}, - {1, 26, 26, 2268}, - {1, 27, 27, 2269}, - {1, 27, 27, 2270}, - {1, 50, 50, 2271}, - {1, 51, 51, 2272}, - {1, 51, 51, 2273}, - {0, 27, 27, 2274}, - {0, 157, 157, 2275}, - {0, 6, 6, 2276}, - {0, 30, 30, 2300}, - {0, 6, 6, 2301}, - {1, 4, -1, 2302}, - {1, 24, 24, 2303}, - {1, 4, -1, 2304}, - {1, 4, -1, 2305}, - {1, 4, -1, 2306}, - {1, 4, -1, 2307}, - {1, 4, -1, 2308}, - {1, 4, -1, 2309}, - {1, 45, -1, 2310}, - {0, 5, 5, 2311}, - {1, 5, 5, 2312}, - {1, 26, 26, 2314}, - {1, 10, -1, 2317}, - {0, 2, 2, 2318}, - {1, 10, 10, 2320}, - {1, 30, 30, 2321}, - {1, 10, 10, 2322}, - {1, 30, 30, 2323}, - {1, 84, -1, 2324}, - {1, 77, -1, 2319}, - {1, 78, -1, 2325}, - {1, 26, 26, 2326}, - {1, 4, 4, 2411}, - {1, 6, 6, 2412}, - {1, 4, -1, 2413}, - {1, 4, -1, 2414}, - {1, 7, 7, 2415}, - {1, 6, 6, 2417}, - {1, 9, -1, 2418}, - {1, 7, 7, 2419}, - {1, 2, 2, 2420}, - {1, 28, -1, 2421}, - {1, 28, -1, 2422}, - {1, 14, 14, 2423}, - {0, 6, 6, 2424}, - {0, 50, 50, 2425}, - {1, 8, -1, 2426}, - {0, 4, 4, 2428}, - {1, 288, 288, 2429}, - {1, 12, 12, 2430}, - {1, 8, -1, 2431}, - {1, 7, 7, 2432}, - {0, 12, -1, 2433}, - {0, 7, 7, 2434}, - {1, 29, 29, 2435}, - {1, 28, 28, 2436}, - {1, 4, -1, 2437}, - {0, 10, 10, 2438}, - {0, 41, -1, 2439}, - {0, 6, 6, 2440}, - {0, 2, 2, 2441}, - {0, 74, -1, 2442}, - {0, 4, -1, 2445}, - {0, 28, -1, 2446}, - {0, 2, 2, 2443}, - {0, 4, 4, 2444}, - {0, 8, -1, 2447}, - {1, 41, 41, 2448}, - {1, 4, -1, 2449}, - {1, 4, -1, 2450}, - {1, 4, -1, 2451}, - {1, 4, -1, 2452}, - {1, 28, -1, 2453}, - {1, 28, -1, 2454}, - {1, 45, -1, 2455}, - {1, 8, 8, 2456}, - {1, 11, 11, 2457}, - {1, 9, 9, 2458}, - {1, 8, 8, 2459}, - {0, 6, 6, 2460}, - {0, 4, -1, 2461}, - {0, 12, 12, 2462}, - {1, 22, -1, 2463}, - {0, 6, 6, 2464}, - {0, 2, 2, 2465}, - {0, 6, 6, 2466}, - {0, 8, -1, 2467}, - {0, 18, 18, 2468}, - {0, 7, 7, 2469}, - {0, 6, 6, 2475}, - {0, 12, 12, 2470}, - {0, 10, 10, 2471}, - {0, 16, 16, 2472}, - {0, 10, 10, 2473}, - {0, 16, 16, 2474}, - {0, 8, -1, 2476}, - {0, 12, 12, 2477}, - {0, 19, 19, 2478}, - {0, 4, 4, 2479}, - {0, 10, 10, 2480}, - {0, 4, 4, 2481}, - {0, 10, 10, 2482}, - {0, 6, 6, 2483}, - {0, 6, 6, 2484}, - {0, 2, 2, 2485}, - {0, 6, 6, 2486}, - {0, 4, 4, 2487}, - {0, 6, 6, 2488}, - {0, 4, 4, 2489}, - {0, 2, 2, 2490}, - {0, 6, 6, 2491}, - {0, 6, 6, 2492}, - {0, 2, 2, 2493}, - {0, 2, 2, 2494}, - {0, 4, 4, 2495}, - {0, 10, 10, 2497}, - {0, 4, -1, 2498}, - {0, 10, 10, 2499}, - {0, 10, 10, 2500}, - {0, 1042, 1042, 2501}, - {0, 16, -1, 2502}, - {0, 18, 18, 2503}, - {0, 13, -1, 2504}, - {0, 4, -1, 2505}, - {1, 23, -1, 2506}, - {1, 27, -1, 3016}, - {1, 17, 17, 2507}, - {0, 4, -1, 2508}, - {1, 8, 8, 2509}, - {1, 102, 102, 2510}, - {0, 4, -1, 2511}, - {0, 4, -1, 2512}, - {1, 14, 14, 2513}, - {0, 28, -1, 2514}, - {0, 28, -1, 2515}, - {0, 2, 2, 2516}, - {1, 4, -1, 2517}, - {1, 4, -1, 2518}, - {1, 2, 2, 2520}, - {1, 5, -1, 2519}, - {0, 4, 4, 2521}, - {0, 8, -1, 2522}, - {1, 88, -1, 2523}, - {1, 81, -1, 2524}, - {1, 82, -1, 2525}, - {1, 33, -1, 2526}, - {1, 7, 7, 2527}, - {0, 40, -1, 2528}, - {1, 8, 8, 2529}, - {1, 8, 8, 2530}, - {1, 8, 8, 2531}, - {1, 8, 8, 2532}, - {1, 18, 18, 2533}, - {1, 24, 24, 2534}, - {1, 3, 3, 2535}, - {1, 11, 11, 2536}, - {1, 2, 2, 2537}, - {1, 11, 11, 2542}, - {1, 11, 11, 2543}, - {1, 7, -1, 2544}, - {1, 7, -1, 2685}, - {1, 11, 11, 2549}, - {1, 11, 11, 2550}, - {1, 11, 11, 2538}, - {1, 24, -1, 2539}, - {1, 77, 77, 2551}, - {1, 64, -1, 2540}, - {1, 3, 3, 2541}, - {1, 11, 11, 2547}, - {1, 12, 12, 2548}, - {1, 11, 11, 2545}, - {1, 12, 12, 2546}, - {1, 6, 6, 2564}, - {1, 63, 63, 2565}, - {1, 6, 6, 2566}, - {1, 9, 9, 2567}, - {1, 2, 2, 2563}, - {1, 26, 26, 2568}, - {1, 27, 27, 2578}, - {1, 26, 26, 2579}, - {1, 10, 10, 2580}, - {1, 34, 34, 2641}, - {0, 2, 2, 2610}, - {1, 8, -1, 2552}, - {1, 143, 143, 2553}, - {1, 6, -1, 2554}, - {0, 8, -1, 2555}, - {1, 6, 6, 2556}, - {1, 90, -1, 2557}, - {1, 83, -1, 2558}, - {1, 84, -1, 2559}, - {1, 94, -1, 2999}, - {1, 269, 269, 2560}, - {0, 3, 3, 2561}, - {1, 4, 4, 2562}, - {1, 55, 55, 2569}, - {1, 57, 57, 2570}, - {1, 57, 57, 2571}, - {1, 66, 66, 2572}, - {1, 4, -1, 2573}, - {1, 4, -1, 2575}, - {1, 28, -1, 2576}, - {1, 28, -1, 2577}, - {1, 14, 14, 2574}, - {1, 12, 12, 2581}, - {0, 26, 26, 2582}, - {1, 6, 6, 2583}, - {1, 14, 14, 2584}, - {1, 18, 18, 2998}, - {1, 2, 2, 2585}, - {1, 25, 25, 2586}, - {1, 2, 2, 2587}, - {1, 8, -1, 2588}, - {1, 2, 2, 2589}, - {1, 3, 3, 2590}, - {1, 2, 2, 2591}, - {1, 23, 23, 2592}, - {1, 3, 3, 2593}, - {1, 7, 7, 2594}, - {1, 22, -1, 2595}, - {1, 66, 66, 2596}, - {1, 6, 6, 2597}, - {1, 7, 7, 2598}, - {1, 8, 8, 2599}, - {1, 3, 3, 2600}, - {0, 6, 6, 2601}, - {0, 6, 6, 2602}, - {0, 14, 14, 2603}, - {0, 12, 12, 2604}, - {0, 45, -1, 2605}, - {1, 6, 6, 2606}, - {1, 7, 7, 2607}, - {1, 106, 106, 2608}, - {0, 8, -1, 2609}, - {0, 36, -1, 3140}, - {0, 7, 7, 2611}, - {0, 6, 6, 2612}, - {0, 4, 4, 2613}, - {1, 7, 7, 2614}, - {1, 69, 69, 2615}, - {1, 3, 3, 2616}, - {1, 3, 3, 2664}, - {1, 7, 7, 2786}, - {1, 36, 36, 2617}, - {1, 12, 12, 2618}, - {1, 12, -1, 2619}, - {0, 18, -1, 2620}, - {0, 20, 20, 2621}, - {0, 16, -1, 2622}, - {0, 11, 11, 2623}, - {0, 11, 11, 2624}, - {0, 18, 18, 2625}, - {0, 43, 43, 2626}, - {0, 85, 85, 2627}, - {0, 28, -1, 2628}, - {0, 14, 14, 2630}, - {0, 3, 3, 2631}, - {0, 2, 2, 2632}, - {0, 16, 16, 2812}, - {0, 22, 22, 2633}, - {0, 6, 6, 2634}, - {0, 18, 18, 3139}, - {0, 22, 22, 2635}, - {0, 28, 28, 2636}, - {0, 2, 2, 2703}, - {0, 3, 3, 2704}, - {0, 6, 6, 2851}, - {0, 64, -1, 2637}, - {0, 67, -1, 2681}, - {0, 47, -1, 2913}, - {0, 63, -1, 2922}, - {0, 6, 6, 2638}, - {0, 2, 2, 2672}, - {0, 8, -1, 2639}, - {0, 4, 4, 2640}, - {0, 20, 20, 2642}, - {0, 10, 10, 2643}, - {0, 8, -1, 2644}, - {0, 2, 2, 2645}, - {0, 6, 6, 2646}, - {0, 6, 6, 2647}, - {0, 8, 8, 2648}, - {0, 8, -1, 2649}, - {0, 2, 2, 2650}, - {0, 7, 7, 2651}, - {0, 18, 18, 2652}, - {0, 6, 6, 2653}, - {0, 6, 6, 2665}, - {0, 12, 12, 2666}, - {0, 8, -1, 2667}, - {0, 7, 7, 2668}, - {0, 4, -1, 2669}, - {0, 26, 26, 2654}, - {0, 8, 8, 2655}, - {0, 3, 3, 2656}, - {1, 68, -1, 2670}, - {1, 10, -1, 2671}, - {0, 5, -1, 2673}, - {0, 61, 61, 2674}, - {0, 2, 2, 2675}, - {0, 8, 8, 2676}, - {0, 80, 80, 2678}, - {0, 15, 15, 2679}, - {0, 15, 15, 2680}, - {0, 4, -1, 2683}, - {0, 4, -1, 2684}, - {1, 5, -1, 2686}, - {1, 2, 2, 2700}, - {1, 6, 6, 2688}, - {1, 88, -1, 2687}, - {1, 17, -1, 2701}, - {1, 4, 4, 2689}, - {1, 96, -1, 2706}, - {1, 25, -1, 2705}, - {1, 3, 3, 2707}, - {1, 2, 2, 2708}, - {1, 61, 61, 2697}, - {1, 63, 63, 2821}, - {1, 6, 6, 2698}, - {1, 46, 46, 2690}, - {1, 46, 46, 2691}, - {1, 94, 94, 2692}, - {1, 82, 82, 2693}, - {1, 4, -1, 2694}, - {1, 4, -1, 2695}, - {1, 118, 118, 2939}, - {1, 4, -1, 2940}, - {1, 4, -1, 2941}, - {1, 60, 60, 2942}, - {0, 2, 2, 2696}, - {0, 2, 2, 2699}, - {0, 2, 2, 2702}, - {1, 4, 4, 2709}, - {0, 61, 61, 2710}, - {0, 8, 8, 2711}, - {0, 10, 10, 2712}, - {0, 4, 4, 2713}, - {0, 10, 10, 2714}, - {0, 4, -1, 2715}, - {0, 2, 2, 2716}, - {0, 4, 4, 2766}, - {0, 4, 4, 2717}, - {0, 2, 2, 2718}, - {0, 2, 2, 2719}, - {0, 2, 2, 2720}, - {0, 4, 4, 2721}, - {0, 7, -1, 2722}, - {0, 7, -1, 3121}, - {0, 9, 9, 2723}, - {0, 2, 2, 2724}, - {1, 4, -1, 2725}, - {1, 36, 36, 2726}, - {1, 6, 6, 2727}, - {1, 5, 5, 2728}, - {1, 4, -1, 2729}, - {1, 4, -1, 2730}, - {1, 5, -1, 2731}, - {0, 69, 69, 2732}, - {1, 14, 14, 2737}, - {0, 51, 51, 2733}, - {0, 2, 2, 2734}, - {0, 6, 6, 2735}, - {0, 6, 6, 2736}, - {0, 2, 2, 2746}, - {0, 2, 2, 2747}, - {0, 7, 7, 2738}, - {0, 19, 19, 2739}, - {0, 6, 6, 2740}, - {0, 2, 2, 2741}, - {0, 8, 8, 2742}, - {0, 4, 4, 2743}, - {0, 2, 2, 2744}, - {0, 47, 47, 2745}, - {0, 4, -1, 2748}, - {0, 10, 10, 2749}, - {0, 6, -1, 2750}, - {0, 4, -1, 2751}, - {0, 26, 26, 2752}, - {0, 26, 26, 2753}, - {0, 5, -1, 2754}, - {0, 2, 2, 2755}, - {0, 64, -1, 2756}, - {0, 156, 156, 2757}, - {0, 156, 156, 2758}, - {1, 156, 156, 2759}, - {0, 2, 2, 2760}, - {0, 47, -1, 2761}, - {0, 3, 3, 2762}, - {0, 12, 12, 2763}, - {0, 18, 18, 2764}, - {0, 23, 23, 2765}, - {0, 68, 68, 2767}, - {0, 94, 94, 3110}, - {0, 11, 11, 2768}, - {0, 8, -1, 2769}, - {0, 9, 9, 3107}, - {1, 30, 30, 2770}, - {1, 4, -1, 2771}, - {1, 4, -1, 2772}, - {0, 2, 2, 2773}, - {1, 2, 2, 2774}, - {0, 8, 8, 2775}, - {0, 8, 8, 2776}, - {1, 6, -1, 2777}, - {1, 32, 32, 2778}, - {1, 33, 33, 3131}, - {0, 8, -1, 2779}, - {1, 6, 6, 2780}, - {1, 24, 24, 2781}, - {0, 6, 6, 2782}, - {0, 58, 58, 2783}, - {0, 30, 30, 2784}, - {0, 28, 28, 2785}, - {1, 89, 89, 2788}, - {1, 28, -1, 2789}, - {0, 28, -1, 2787}, - {0, 10, 10, 2790}, - {0, 38, 38, 2791}, - {0, 2, 2, 2792}, - {0, 2, 2, 2796}, - {0, 2, 2, 2797}, - {0, 2, 2, 2798}, - {0, 13, 13, 2793}, - {0, 2, 2, 2799}, - {0, 10, 10, 2800}, - {0, 102, 102, 2801}, - {1, 40, 40, 2802}, - {1, 4, -1, 2803}, - {0, 11, 11, 2804}, - {0, 3, 3, 2805}, - {0, 88, 88, 2806}, - {0, 32, 32, 2807}, - {0, 11, 11, 2808}, - {0, 6, 6, 2809}, - {0, 58, 58, 2810}, - {1, 4, -1, 2811}, - {1, 8, -1, 2813}, - {1, 155, 155, 2828}, - {1, 6, -1, 2814}, - {1, 8, -1, 2815}, - {1, 8, 8, 2816}, - {0, 56, 56, 2817}, - {0, 26, 26, 2818}, - {0, 47, -1, 2819}, - {0, 190, 190, 2820}, - {0, 47, -1, 2823}, - {1, 5, -1, 2824}, - {1, 5, -1, 2825}, - {1, 5, -1, 2826}, - {1, 4, 4, 2827}, - {1, 10, 10, 2829}, - {1, 4, -1, 2830}, - {1, 4, -1, 2831}, - {1, 10, 10, 2832}, - {1, 4, 4, 2833}, - {-1, 2, 2, 2834}, - {0, 48, 48, 2835}, - {0, 2, 2, 2836}, - {0, 2, 2, 2838}, - {0, 2, 2, 2841}, - {1, 7, 7, 2837}, - {1, 3, 3, 2839}, - {1, 4, 4, 2840}, - {1, 29, 29, 2842}, - {1, 2, 2, 2843}, - {0, 2, 2, 2844}, - {0, 2, 2, 2845}, - {0, 14, 14, 2846}, - {1, 14, 14, 2847}, - {1, 271, 271, 2848}, - {0, 5, 5, 2850}, - {0, 13, 13, 2849}, - {1, 6, 6, 2852}, - {1, 6, 6, 2853}, - {1, 4, -1, 2855}, - {1, 3, 3, 2856}, - {1, 11, 11, 2859}, - {1, 3, 3, 2860}, - {1, 11, 11, 2861}, - {1, 4, 4, 2862}, - {1, 73, 73, 2863}, - {1, 4, -1, 2864}, - {1, 17, 17, 2865}, - {1, 4, -1, 2866}, - {1, 17, 17, 2867}, - {0, 50, 50, 2868}, - {0, 3, 3, 2869}, - {1, 14, -1, 2870}, - {1, 47, -1, 2871}, - {1, 5, -1, 2873}, - {1, 4, 4, 2876}, - {1, 12, -1, 2877}, - {1, 8, -1, 2878}, - {1, 64, 64, 2879}, - {1, 8, -1, 2880}, - {1, 70, 70, 2881}, - {1, 62, 62, 2882}, - {1, 48, 48, 2883}, - {1, 58, 58, 2884}, - {1, 58, 58, 2885}, - {0, 10, 10, 2886}, - {1, 14, 14, 2887}, - {0, 18, 18, 2888}, - {0, 4, 4, 2889}, - {0, 6, 6, 2890}, - {0, 4, 4, 2891}, - {0, 2, 2, 2892}, - {0, 6, -1, 2893}, - {0, 2, 2, 2895}, - {0, 2, 2, 2896}, - {0, 2, 2, 2897}, - {0, 2, 2, 2898}, - {0, 52, 52, 2899}, - {0, 8, 8, 2900}, - {1, 6, -1, 2894}, - {0, 4, -1, 2901}, - {1, 8, -1, 2902}, - {1, 4, -1, 2903}, - {1, 2, 2, 2904}, - {1, 4, 4, 2905}, - {1, 34, -1, 2906}, - {1, 14, 14, 2907}, - {1, 2, 2, 2908}, - {1, 10, 10, 2909}, - {1, 33, 33, 2910}, - {0, 5, -1, 2911}, - {0, 64, -1, 2912}, - {1, 17, -1, 2914}, - {1, 24, -1, 2915}, - {1, 7, -1, 2916}, - {1, 4, -1, 2917}, - {1, 26, 26, 2918}, - {1, 33, 33, 2919}, - {1, 12, 12, 2920}, - {1, 18, 18, 2921}, - {1, 14, 14, 2923}, - {1, 12, 12, 2924}, - {0, 6, 6, 2925}, - {0, 14, 14, 2926}, - {0, 177, 177, 2927}, - {0, 8, -1, 2928}, - {0, 177, 177, 2929}, - {0, 4, -1, 2930}, - {1, 8, 8, 2931}, - {0, 1026, 1026, 2932}, - {0, 1026, 1026, 2933}, - {1, 77, 77, 2934}, - {1, 4, -1, 2935}, - {1, 4, -1, 2936}, - {1, 8, -1, 2937}, - {1, 4, -1, 2938}, - {1, 10, 10, 2943}, - {1, 5, -1, 2956}, - {1, 5, -1, 2957}, - {1, 18, 18, 2958}, - {0, 6, 6, 2959}, - {0, 2, 2, 2960}, - {0, 8, 8, 2961}, - {0, 5, 5, 2962}, - {0, 12, 12, 2963}, - {0, 14, 14, 2964}, - {0, 4, -1, 2965}, - {0, 26, 26, 2966}, - {0, 27, 27, 2967}, - {0, 6, 6, 2968}, - {0, 10, 10, 2969}, - {0, 11, 11, 2970}, - {0, 12, 12, 2971}, - {0, 16, 16, 2972}, - {0, 14, 14, 2973}, - {0, 12, 12, 2974}, - {0, 10, 10, 2975}, - {0, 2, 2, 2976}, - {0, 3, 3, 2977}, - {0, 10, 10, 2978}, - {0, 10, 10, 2979}, - {1, 85, 85, 2980}, - {1, 12, 12, 2981}, - {1, 8, -1, 2982}, - {1, 8, -1, 2983}, - {1, 8, -1, 3101}, - {1, 7, 7, 2984}, - {1, 8, -1, 2985}, - {1, 22, 22, 2986}, - {1, 22, 22, 2987}, - {0, 22, 22, 2988}, - {0, 2, 2, 2989}, - {0, 6, 6, 3061}, - {0, 3, 3, 2990}, - {0, 16, 16, 2991}, - {0, 9, 9, 2992}, - {0, 3, 3, 2993}, - {0, 2, 2, 2994}, - {0, 8, -1, 2995}, - {0, 31, 31, 2996}, - {0, 10, 10, 2997}, - {1, 9, -1, 3002}, - {-1, 5, -1, 3003}, - {1, 22, 22, 3004}, - {0, 6, 6, 3005}, - {1, 6, 6, 3006}, - {1, 12, 12, 3007}, - {0, 3, 3, 3008}, - {0, 13, -1, 3009}, - {0, 10, 10, 3011}, - {0, 9, 9, 3014}, - {0, 22, -1, 3034}, - {0, 19, 19, 3035}, - {0, 18, 18, 3036}, - {0, 5, 5, 3010}, - {0, 2, 2, 3012}, - {0, 7, 7, 3013}, - {0, 6, 6, 3015}, - {1, 10, 10, 3017}, - {1, 8, -1, 3018}, - {0, 4, 4, 3019}, - {0, 9, -1, 3020}, - {0, 9, -1, 3021}, - {0, 8, 8, 3022}, - {0, 9, 9, 3023}, - {0, 8, 8, 3024}, - {0, 13, 13, 3025}, - {0, 8, 8, 3026}, - {0, 13, 13, 3027}, - {0, 2, 2, 3028}, - {0, 9, 9, 3029}, - {0, 8, 8, 3030}, - {0, 9, 9, 3031}, - {0, 14, 14, 3032}, - {0, 51, 51, 3033}, - {0, 4, -1, 3037}, - {1, 4, -1, 3038}, - {0, 3, 3, 3039}, - {0, 3, 3, 3040}, - {0, 3, 3, 3041}, - {0, 137, 137, 3042}, - {0, 34, 34, 3043}, - {0, 14, 14, 3044}, - {0, 8, 8, 3045}, - {0, 8, 8, 3046}, - {0, 4, 4, 3047}, - {0, 4, 4, 3048}, - {0, 6, 6, 3049}, - {0, 10, 10, 3050}, - {0, 7, 7, 3051}, - {0, 7, 7, 3052}, - {0, 9, 9, 3053}, - {0, 5, 5, 3054}, - {0, 8, -1, 3055}, - {0, 14, 14, 3056}, - {0, 18, 18, 3057}, - {0, 13, 13, 3058}, - {0, 4, -1, 3059}, - {0, 4, -1, 3060}, - {0, 10, -1, 3062}, - {0, 6, -1, 3063}, - {0, 6, 6, 3064}, - {0, 11, 11, 3065}, - {0, 9, 9, 3066}, - {0, 35, 35, 3067}, - {0, 6, 6, 3068}, - {0, 4, 4, 3069}, - {0, 76, -1, 3070}, - {1, 24, 24, 3071}, - {0, 6, 6, 3072}, - {0, 6, 6, 3073}, - {0, 6, 6, 3074}, - {0, 6, 6, 3075}, - {0, 8, 8, 3076}, - {0, 7, 7, 3090}, - {0, 11, 11, 3089}, - {0, 11, 11, 3091}, - {0, 14, 14, 3092}, - {0, 30, 30, 3077}, - {0, 8, 8, 3078}, - {0, 12, 12, 3079}, - {0, 6, 6, 3080}, - {0, 116, 116, 3081}, - {0, 30, 30, 3082}, - {0, 10, 10, 3102}, - {0, 12, 12, 3109}, - {0, 18, 18, 3083}, - {0, 4, 4, 3084}, - {0, 167, 167, 3085}, - {0, 689, 689, 3086}, - {0, 610, 610, 3087}, - {0, 15, 15, 3088}, - {1, 9, -1, 3093}, - {0, 9, 9, 3094}, - {1, 10, 10, 3095}, - {0, 20, 20, 3096}, - {0, 8, 8, 3097}, - {0, 20, 20, 3098}, - {0, 8, 8, 3099}, - {0, 4, -1, 3104}, - {0, 4, -1, 3105}, - {0, 12, 12, 3106}, - {0, 979, 979, 3108}, - {0, 2, 2, 3111}, - {0, 26, -1, 3113}, - {0, 3, 3, 3117}, - {0, 15, 15, 3118}, - {0, 2, 2, 3119}, - {0, 15, 15, 3120}, - {0, 7, 7, 3135}, - {0, 19, 19, 3136}, - {0, 2, 2, 3137}, - {0, 19, 19, 3138}, - {0, 4, 4, 3114}, - {0, 8, 8, 3115}, - {0, 4, 4, 3116}, - {0, 64, -1, 3122}, - {0, 8, 8, 3123}, - {0, 3, 3, 3124}, - {0, 6, 6, 3125}, - {1, 12, 12, 3126}, - {1, 6, 6, 3132}, - {0, 6, 6, 3133}, - {0, 8, 8, 3134}, + {0, 7, 7, 1079}, + {0, 10, 10, 1080}, + {0, 5, 5, 863}, + {0, 6, 6, 864}, + {0, 10, 10, 2944}, + {0, 5, 5, 865}, + {0, 6, 6, 866}, + {0, 6, 6, 867}, + {0, 8, 8, 868}, + {0, 8, 8, 869}, + {0, 10, 10, 870}, + {0, 31, 31, 871}, + {0, 6, 6, 872}, + {0, 6, 6, 873}, + {0, 14, 14, 2108}, + {0, 2, 2, 2104}, + {0, 15, -1, 2101}, + {0, 12, -1, 2073}, + {0, 6, 6, 2071}, + {0, 2, 2, 2069}, + {0, 89, -1, 2065}, + {0, 18, 18, 2050}, + {0, 8, 8, 2028}, + {0, 12, -1, 2020}, + {0, 23, 23, 1078}, + {0, 23, 23, 9900}, + {0, 27, 27, 3001}, + {0, 26, 26, 708}, + {0, 4, 4, 641}, + {0, 26, 26, 514}, + {0, 5, 5, 557}, + {0, 36, 36, 571}, + {0, 1000, 1000, 3103}, + {0, 2, 2, 2138}, + {0, 2, 2, 2139}, + {0, 2, 2, 2140}, + {0, 2, 2, 2141}, + {0, 2, 2, 2142}, + {0, 2, 2, 2143}, + {0, 2, 2, 2144}, + {0, 2, 2, 2145}, + {0, 2, 2, 2146}, + {0, 2, 2, 2147}, + {0, 2, 2, 2148}, + {0, 2, 2, 2149}, + {0, 2, 2, 2150}, + {0, 2, 2, 2151}, + {0, 2, 2, 2152}, + {0, 2, 2, 2153}, + {0, 2, 2, 2154}, + {0, 2, 2, 2155}, + {0, 2, 2, 2156}, + {0, 2, 2, 2157}, + {0, 2, 2, 2158}, + {0, 2, 2, 2159}, + {0, 2, 2, 2160}, + {0, 2, 2, 2161}, + {0, 2, 2, 2162}, + {0, 2, 2, 2163}, + {0, 2, 2, 2164}, + {0, 2, 2, 2165}, + {0, 2, 2, 2166}, + {0, 2, 2, 2167}, + {0, 2, 2, 2168}, + {0, 2, 2, 2169}, + {0, 2, 2, 2170}, + {0, 2, 2, 2171}, + {0, 2, 2, 2172}, + {0, 2, 2, 2173}, + {0, 2, 2, 2174}, + {0, 2, 2, 2175}, + {0, 2, 2, 2176}, + {0, 2, 2, 2177}, + {0, 2, 2, 2178}, + {0, 2, 2, 2179}, + {0, 2, 2, 2327}, + {0, 2, 2, 2328}, + {0, 2, 2, 2329}, + {0, 2, 2, 2330}, + {0, 2, 2, 2331}, + {0, 2, 2, 2332}, + {0, 2, 2, 2333}, + {0, 2, 2, 2334}, + {0, 2, 2, 2335}, + {0, 2, 2, 2336}, + {0, 2, 2, 2337}, + {0, 2, 2, 2338}, + {0, 2, 2, 2339}, + {0, 2, 2, 2340}, + {0, 2, 2, 2341}, + {0, 2, 2, 2342}, + {0, 2, 2, 2343}, + {0, 2, 2, 2344}, + {0, 2, 2, 2345}, + {0, 2, 2, 2346}, + {0, 2, 2, 2347}, + {0, 2, 2, 2348}, + {0, 2, 2, 2349}, + {0, 2, 2, 2350}, + {0, 2, 2, 2351}, + {0, 2, 2, 2352}, + {0, 2, 2, 2353}, + {0, 2, 2, 2354}, + {0, 2, 2, 2355}, + {0, 2, 2, 2356}, + {0, 2, 2, 2357}, + {0, 2, 2, 2358}, + {0, 2, 2, 2359}, + {0, 2, 2, 2360}, + {0, 2, 2, 2361}, + {0, 2, 2, 2362}, + {0, 2, 2, 2363}, + {0, 2, 2, 2364}, + {0, 2, 2, 2365}, + {0, 2, 2, 2366}, + {0, 2, 2, 2367}, + {0, 2, 2, 2368}, + {0, 2, 2, 2180}, + {0, 2, 2, 2181}, + {0, 2, 2, 2182}, + {0, 2, 2, 2183}, + {0, 2, 2, 2184}, + {0, 2, 2, 2185}, + {0, 2, 2, 2186}, + {0, 2, 2, 2187}, + {0, 2, 2, 2188}, + {0, 2, 2, 2189}, + {0, 2, 2, 2190}, + {0, 2, 2, 2191}, + {0, 2, 2, 2192}, + {0, 2, 2, 2193}, + {0, 2, 2, 2194}, + {0, 2, 2, 2195}, + {0, 2, 2, 2196}, + {0, 2, 2, 2197}, + {0, 2, 2, 2198}, + {0, 2, 2, 2199}, + {0, 2, 2, 2200}, + {0, 2, 2, 2201}, + {0, 2, 2, 2202}, + {0, 2, 2, 2203}, + {0, 2, 2, 2204}, + {0, 2, 2, 2205}, + {0, 2, 2, 2206}, + {0, 2, 2, 2207}, + {0, 2, 2, 2208}, + {0, 2, 2, 2209}, + {0, 2, 2, 2210}, + {0, 2, 2, 2211}, + {0, 2, 2, 2212}, + {0, 2, 2, 2213}, + {0, 2, 2, 2214}, + {0, 2, 2, 2215}, + {0, 2, 2, 2216}, + {0, 2, 2, 2217}, + {0, 2, 2, 2218}, + {0, 2, 2, 2219}, + {0, 2, 2, 2220}, + {0, 2, 2, 2221}, + {0, 2, 2, 2369}, + {0, 2, 2, 2370}, + {0, 2, 2, 2371}, + {0, 2, 2, 2372}, + {0, 2, 2, 2373}, + {0, 2, 2, 2374}, + {0, 2, 2, 2375}, + {0, 2, 2, 2376}, + {0, 2, 2, 2377}, + {0, 2, 2, 2378}, + {0, 2, 2, 2379}, + {0, 2, 2, 2380}, + {0, 2, 2, 2381}, + {0, 2, 2, 2382}, + {0, 2, 2, 2383}, + {0, 2, 2, 2384}, + {0, 2, 2, 2385}, + {0, 2, 2, 2386}, + {0, 2, 2, 2387}, + {0, 2, 2, 2388}, + {0, 2, 2, 2389}, + {0, 2, 2, 2390}, + {0, 2, 2, 2391}, + {0, 2, 2, 2392}, + {0, 2, 2, 2393}, + {0, 2, 2, 2394}, + {0, 2, 2, 2395}, + {0, 2, 2, 2396}, + {0, 2, 2, 2397}, + {0, 2, 2, 2398}, + {0, 2, 2, 2399}, + {0, 2, 2, 2400}, + {0, 2, 2, 2401}, + {0, 2, 2, 2402}, + {0, 2, 2, 2403}, + {0, 2, 2, 2404}, + {0, 2, 2, 2405}, + {0, 2, 2, 2406}, + {0, 2, 2, 2407}, + {0, 2, 2, 2408}, + {0, 2, 2, 2409}, + {0, 2, 2, 2410}, + {0, 1000, 1000, 3103}, + {0, 6, 6, 391}, + {0, 3, 3, 129}, + {0, 4, 4, 454}, + {1, 2, 2, 455}, + {0, 55, 55, 100}, + {0, 47, -1, 105}, + {0, 23, 23, 106}, + {0, 2, 2, 475}, + {0, 4, -1, 476}, + {0, 47, 47, 477}, + {0, 48, 48, 506}, + {0, 18, 18, 516}, + {0, 4, -1, 497}, + {0, 26, 26, 512}, + {0, 2, 2, 446}, + {0, 3, 3, 447}, + {0, 17, 17, 101}, + {0, 3, 3, 102}, + {0, 37, 37, 103}, + {0, 31, 31, 2416}, + {0, 4, -1, 525}, + {0, 24, -1, 107}, + {0, 3, 3, 108}, + {0, 157, 157, 109}, + {0, 3, 3, 110}, + {0, 28, 28, 113}, + {0, 46, 46, 104}, + {0, 56, 56, 507}, + {0, 2, 2, 111}, + {0, 3, 3, 112}, + {0, 3, 3, 714}, + {0, 34, 34, 155}, + {0, 2, 2, 130}, + {0, 9, 9, 167}, + {0, 23, 23, 400}, + {0, 4, -1, 243}, + {0, 11, 11, 137}, + {0, 2, 2, 125}, + {0, 7, 7, 144}, + {0, 4, -1, 153}, + {0, 4, -1, 412}, + {0, 10, 10, 133}, + {0, 6, 6, 204}, + {0, 2, 2, 206}, + {0, 11, 11, 245}, + {0, 17, 17, 278}, + {0, 20, 20, 159}, + {0, 6, 6, 169}, + {0, 4, 4, 171}, + {0, 7, 7, 184}, + {0, 6, 6, 185}, + {0, 3, 3, 178}, + {0, 2, 2, 186}, + {0, 5, 5, 187}, + {0, 3, 3, 191}, + {0, 2, 2, 193}, + {0, 7, 7, 197}, + {0, 4, -1, 200}, + {0, 4, -1, 201}, + {0, 28, -1, 150}, + {0, 27, 27, 207}, + {0, 3, 3, 208}, + {0, 2, 2, 211}, + {0, 15, -1, 213}, + {0, 14, 14, 217}, + {0, 15, -1, 222}, + {0, 30, 30, 224}, + {0, 26, 26, 226}, + {0, 2, 2, 227}, + {0, 6, 6, 228}, + {0, 3, 3, 230}, + {0, 8, 8, 232}, + {0, 2, 2, 235}, + {0, 2, 2, 237}, + {0, 2, 2, 239}, + {0, 19, 19, 148}, + {0, 17, 17, 247}, + {0, 2, 2, 403}, + {0, 26, 26, 249}, + {0, 28, 28, 488}, + {0, 6, 6, 252}, + {0, 10, 10, 255}, + {0, 6, 6, 258}, + {0, 2, 2, 256}, + {0, 30, 30, 259}, + {0, 4, -1, 264}, + {0, 4, 4, 274}, + {0, 22, 22, 114}, + {0, 25, 25, 275}, + {0, 2, 2, 280}, + {0, 20, 20, 283}, + {0, 2, 2, 285}, + {0, 8, 8, 294}, + {0, 8, 8, 295}, + {0, 8, 8, 296}, + {0, 8, 8, 297}, + {0, 2, 2, 298}, + {0, 2, 2, 302}, + {0, 84, -1, 303}, + {0, 85, -1, 434}, + {0, 8, -1, 308}, + {0, 6, 6, 304}, + {0, 3, 3, 312}, + {0, 26, 26, 319}, + {0, 22, 22, 320}, + {0, 10, 10, 323}, + {0, 6, 6, 326}, + {0, 4, 4, 376}, + {0, 4, 4, 378}, + {0, 6, 6, 380}, + {0, 25, 25, 509}, + {0, 4, 4, 394}, + {0, 18, 18, 398}, + {0, 46, 46, 126}, + {0, 4, 4, 407}, + {0, 8, 8, 408}, + {0, 6, 6, 430}, + {0, 8, 8, 603}, + {0, 4, 4, 431}, + {1, 6, 6, 441}, + {1, 30, 30, 461}, + {0, 6, 6, 462}, + {1, 28, 28, 463}, + {1, 8, 8, 464}, + {1, 8, 8, 481}, + {1, 14, 14, 465}, + {1, 10, 10, 466}, + {0, 14, 14, 140}, + {1, 30, 30, 149}, + {1, 102, 102, 405}, + {0, 14, 14, 162}, + {0, 6, 6, 373}, + {0, 106, 106, 374}, + {1, 53, 53, 121}, + {0, 6, 6, 413}, + {1, 4, -1, 332}, + {0, 2, 2, 333}, + {1, 6, 6, 334}, + {0, 6, 6, 335}, + {1, 110, 110, 336}, + {1, 114, 114, 438}, + {0, 6, 6, 337}, + {1, 12, -1, 338}, + {0, 4, -1, 339}, + {1, 4, -1, 340}, + {1, 4, -1, 358}, + {0, 4, -1, 341}, + {1, 4, -1, 342}, + {0, 6, 6, 343}, + {0, 54, 54, 345}, + {1, 66, 66, 346}, + {0, 54, 54, 347}, + {1, 90, 90, 348}, + {0, 42, 42, 349}, + {1, 6, 6, 350}, + {1, 42, 42, 351}, + {1, 4, -1, 352}, + {0, 4, -1, 353}, + {1, 6, -1, 354}, + {1, 4, -1, 355}, + {1, 4, -1, 356}, + {0, 30, 30, 357}, + {1, 3, 3, 359}, + {0, 14, 14, 360}, + {1, 3, 3, 361}, + {1, 30, 30, 362}, + {0, 10, 10, 363}, + {0, 9, 9, 329}, + {1, 6, 6, 330}, + {1, 27, 27, 331}, + {0, 186, 186, 366}, + {1, 182, 182, 367}, + {0, 4, -1, 382}, + {1, 4, -1, 383}, + {1, 43, 43, 364}, + {1, 47, 47, 759}, + {1, 36, -1, 760}, + {1, 8, -1, 761}, + {0, 7, -1, 762}, + {1, 32, -1, 763}, + {1, 44, -1, 764}, + {1, 14, 14, 365}, + {1, 20, 20, 498}, + {0, 14, 14, 368}, + {1, 30, 30, 369}, + {0, 10, 10, 370}, + {1, 3, 3, 371}, + {1, 4, -1, 372}, + {0, 6, 6, 384}, + {1, 3, 3, 385}, + {1, 106, 106, 386}, + {0, 10, 10, 387}, + {1, 10, 10, 388}, + {1, 34, 34, 389}, + {1, 2, 2, 414}, + {0, 6, 6, 415}, + {1, 3, 3, 416}, + {0, 3, 3, 417}, + {1, 37, 37, 418}, + {1, 7, 7, 419}, + {1, 11, 11, 420}, + {0, 26, 26, 421}, + {1, 4, -1, 422}, + {0, 4, 4, 423}, + {0, 4, 4, 424}, + {0, 6, 6, 425}, + {1, 10, 10, 426}, + {0, 3, 3, 458}, + {1, 11, 11, 432}, + {1, 7, 7, 433}, + {0, 26, 26, 442}, + {0, 26, 26, 443}, + {0, 26, 26, 444}, + {0, 26, 26, 445}, + {0, 2, 2, 448}, + {1, 14, 14, 449}, + {1, 10, 10, 450}, + {1, 35, 35, 467}, + {0, 8, -1, 469}, + {1, 6, 6, 468}, + {0, 6, 6, 479}, + {1, 10, 10, 499}, + {1, 14, 14, 644}, + {1, 10, 10, 511}, + {0, 2, 2, 493}, + {0, 2, 2, 487}, + {0, 6, 6, 439}, + {0, 14, 14, 503}, + {0, 14, 14, 483}, + {0, 9, 9, 459}, + {0, 6, 6, 505}, + {0, 6, 6, 485}, + {1, 4, -1, 513}, + {0, 10, 10, 515}, + {1, 26, 26, 517}, + {1, 35, 35, 518}, + {1, 34, 34, 519}, + {0, 14, 14, 520}, + {1, 36, 36, 521}, + {1, 10, 10, 522}, + {1, 32, 32, 526}, + {0, 26, 26, 530}, + {0, 26, 26, 531}, + {1, 42, 42, 532}, + {1, 6, 6, 533}, + {1, 6, 6, 534}, + {0, 2, 2, 535}, + {0, 2, 2, 536}, + {0, 2, 2, 549}, + {1, 282, 282, 537}, + {1, 282, 282, 538}, + {1, 282, 282, 550}, + {1, 284, 284, 642}, + {1, 10, 10, 539}, + {1, 10, 10, 540}, + {1, 10, 10, 548}, + {1, 12, 12, 640}, + {1, 6, 6, 645}, + {0, 4, 4, 646}, + {0, 6, 6, 541}, + {0, 6, 6, 542}, + {1, 66, 66, 543}, + {0, 6, 6, 546}, + {1, 4, -1, 545}, + {1, 10, 10, 544}, + {1, 10, 10, 547}, + {1, 11, 11, 115}, + {0, 3, 3, 116}, + {1, 11, -1, 117}, + {1, 9, 9, 118}, + {1, 5, 5, 119}, + {1, 55, 55, 120}, + {1, 58, 58, 122}, + {1, 60, 60, 123}, + {1, 44, 44, 124}, + {1, 6, 6, 127}, + {1, 7, 7, 128}, + {1, 2, 2, 131}, + {1, 2, 2, 132}, + {1, 16, 16, 134}, + {1, 12, 12, 135}, + {1, 16, 16, 3000}, + {1, 10, 10, 136}, + {1, 10, 10, 2253}, + {1, 29, 29, 138}, + {1, 23, 23, 139}, + {1, 8, -1, 141}, + {1, 4, -1, 142}, + {1, 22, 22, 145}, + {1, 28, 28, 146}, + {1, 2, 2, 147}, + {1, 32, -1, 151}, + {1, 3, 3, 152}, + {1, 4, -1, 154}, + {1, 9, 9, 156}, + {1, 19, 19, 157}, + {1, 19, 19, 158}, + {1, 33, 33, 160}, + {1, 6, 6, 161}, + {1, 4, -1, 163}, + {1, 4, -1, 164}, + {1, 4, -1, 165}, + {1, 4, -1, 166}, + {1, 7, 7, 168}, + {1, 9, 9, 170}, + {1, 7, 7, 172}, + {1, 4, -1, 174}, + {1, 6, 6, 175}, + {1, 8, 8, 176}, + {1, 8, 8, 177}, + {0, 3, 3, 179}, + {1, 8, -1, 180}, + {1, 6, 6, 181}, + {1, 6, 6, 182}, + {1, 8, -1, 183}, + {1, 8, -1, 3100}, + {1, 6, 6, 188}, + {1, 44, 44, 189}, + {1, 5, 5, 190}, + {1, 7, 7, 192}, + {1, 6, 6, 194}, + {1, 8, 8, 195}, + {1, 6, 6, 196}, + {1, 4, -1, 198}, + {1, 4, -1, 199}, + {1, 3, 3, 202}, + {1, 3, 3, 203}, + {1, 3, 3, 205}, + {1, 4, 4, 209}, + {1, 4, 4, 210}, + {1, 4, -1, 212}, + {1, 3, 3, 214}, + {1, 17, -1, 215}, + {1, 6, 6, 216}, + {1, 3, 3, 218}, + {1, 8, -1, 219}, + {1, 28, 28, 220}, + {1, 29, 29, 221}, + {1, 17, -1, 223}, + {1, 30, 30, 225}, + {1, 26, 26, 229}, + {1, 3, 3, 231}, + {1, 29, 29, 233}, + {1, 5, 5, 234}, + {1, 3, 3, 236}, + {1, 2, 2, 238}, + {1, 3, 3, 240}, + {1, 2, 2, 241}, + {1, 6, 6, 242}, + {1, 31, 31, 244}, + {1, 8, 8, 246}, + {1, 2, 2, 248}, + {1, 3, 3, 250}, + {1, 28, -1, 251}, + {1, 27, 27, 253}, + {1, 30, 30, 254}, + {1, 6, 6, 257}, + {1, 79, 79, 260}, + {1, 31, 31, 261}, + {1, 10, 10, 262}, + {1, 10, 10, 263}, + {1, 8, -1, 265}, + {1, 6, 6, 266}, + {1, 6, 6, 267}, + {1, 6, 6, 268}, + {1, 2, 2, 269}, + {1, 11, 11, 270}, + {1, 4, -1, 271}, + {1, 8, -1, 689}, + {1, 8, -1, 690}, + {1, 6, -1, 693}, + {1, 14, 14, 272}, + {1, 39, 39, 273}, + {1, 31, 31, 276}, + {1, 35, 35, 277}, + {1, 18, 18, 279}, + {1, 13, 13, 281}, + {1, 15, 15, 553}, + {1, 15, 15, 282}, + {1, 68, 68, 284}, + {1, 3, 3, 286}, + {1, 16, 16, 287}, + {1, 6, 6, 288}, + {1, 14, 14, 289}, + {1, 4, -1, 290}, + {1, 4, -1, 291}, + {1, 31, 31, 292}, + {1, 8, 8, 293}, + {1, 2, 2, 299}, + {1, 3, 3, 300}, + {1, 4, 4, 301}, + {1, 86, 86, 305}, + {1, 6, 6, 306}, + {1, 8, -1, 307}, + {1, 7, 7, 309}, + {1, 8, -1, 310}, + {1, 6, 6, 311}, + {1, 16, 16, 313}, + {1, 4, 4, 314}, + {1, 4, 4, 315}, + {1, 4, 4, 316}, + {1, 6, 6, 317}, + {1, 24, 24, 318}, + {1, 14, 14, 321}, + {1, 6, 6, 322}, + {1, 23, 23, 324}, + {1, 19, 19, 325}, + {1, 39, 39, 327}, + {1, 8, 8, 328}, + {1, 4, -1, 375}, + {1, 5, 5, 377}, + {1, 4, -1, 379}, + {1, 7, 7, 381}, + {1, 8, 8, 392}, + {1, 4, 4, 393}, + {0, 4, 4, 395}, + {1, 29, 29, 396}, + {1, 4, -1, 397}, + {1, 8, 8, 399}, + {1, 27, 27, 401}, + {1, 24, 24, 402}, + {1, 30, 30, 404}, + {1, 9, 9, 406}, + {1, 18, 18, 650}, + {1, 4, 4, 409}, + {1, 14, 14, 410}, + {1, 10, 10, 411}, + {1, 12, 12, 427}, + {1, 6, 6, 428}, + {1, 4, -1, 429}, + {1, 4, -1, 602}, + {1, 67, 67, 435}, + {1, 12, 12, 436}, + {0, 18, 18, 437}, + {1, 3, 3, 440}, + {1, 16, -1, 451}, + {1, 32, 32, 452}, + {1, 32, 32, 453}, + {1, 15, 15, 456}, + {1, 97, 97, 457}, + {1, 9, 9, 460}, + {1, 4, 4, 470}, + {1, 15, 15, 471}, + {1, 58, 58, 472}, + {1, 62, 62, 554}, + {1, 57, 57, 473}, + {1, 61, 61, 555}, + {1, 64, 64, 474}, + {1, 69, 69, 556}, + {1, 33, 33, 478}, + {1, 30, 30, 480}, + {1, 34, 34, 482}, + {1, 2, 2, 484}, + {1, 26, 26, 486}, + {1, 81, 81, 489}, + {1, 6, 6, 490}, + {1, 10, 10, 491}, + {1, 26, 26, 492}, + {1, 4, -1, 494}, + {1, 4, -1, 495}, + {1, 4, -1, 496}, + {1, 32, 32, 500}, + {1, 9, 9, 501}, + {1, 34, 34, 502}, + {1, 3, 3, 595}, + {0, 3, 3, 596}, + {1, 2, 2, 504}, + {1, 4, -1, 508}, + {1, 5, 5, 510}, + {0, 18, 18, 551}, + {0, 18, 18, 552}, + {0, 9, 9, 562}, + {0, 11, 11, 563}, + {0, 6, 6, 564}, + {1, 12, 12, 560}, + {1, 73, 73, 558}, + {0, 62, 62, 637}, + {1, 4, -1, 565}, + {1, 11, 11, 569}, + {1, 7, 7, 559}, + {0, 26, 26, 561}, + {0, 2, 2, 567}, + {1, 282, 282, 568}, + {1, 10, 10, 566}, + {0, 4, 4, 570}, + {0, 6, 6, 572}, + {0, 6, 6, 573}, + {0, 8, 8, 574}, + {0, 2, 2, 575}, + {1, 8, -1, 576}, + {0, 6, 6, 577}, + {1, 109, -1, 578}, + {0, 6, 6, 579}, + {1, 8, 8, 599}, + {0, 6, 6, 580}, + {1, 3, 3, 581}, + {0, 4, 4, 582}, + {0, 8, 8, 583}, + {0, 68, -1, 584}, + {1, 3, 3, 585}, + {1, 70, 70, 586}, + {0, 4, 4, 587}, + {0, 8, 8, 588}, + {0, 12, 12, 589}, + {0, 6, 6, 590}, + {0, 10, 10, 591}, + {1, 3, 3, 592}, + {0, 34, 34, 593}, + {1, 12, -1, 594}, + {1, 5, 5, 597}, + {1, 5, 5, 598}, + {0, 2, 2, 600}, + {0, 3, 3, 601}, + {0, 4, 4, 604}, + {1, 6, 6, 605}, + {0, 4, 4, 606}, + {1, 6, 6, 607}, + {1, 6, 6, 608}, + {0, 11, 11, 609}, + {0, 11, 11, 610}, + {0, 11, 11, 611}, + {0, 20, 20, 612}, + {0, 20, 20, 613}, + {0, 30, 30, 614}, + {0, 4, 4, 615}, + {0, 4, 4, 616}, + {0, 4, 4, 617}, + {0, 4, 4, 618}, + {0, 4, 4, 619}, + {0, 4, 4, 620}, + {0, 4, 4, 621}, + {0, 2, 2, 623}, + {0, 2, 2, 624}, + {0, 40, 40, 625}, + {0, 44, 44, 626}, + {0, 30, 30, 627}, + {1, 8, 8, 628}, + {0, 37, 37, 629}, + {0, 51, -1, 630}, + {0, 84, 84, 631}, + {0, 2, 2, 632}, + {0, 2, 2, 633}, + {1, 4, -1, 634}, + {0, 14, 14, 635}, + {0, 60, 60, 636}, + {0, 6, -1, 638}, + {0, 8, 8, 639}, + {1, 6, 6, 643}, + {1, 12, -1, 647}, + {0, 10, -1, 648}, + {1, 12, 12, 649}, + {1, 12, -1, 1092}, + {0, 12, 12, 1093}, + {0, 4, -1, 651}, + {0, 46, 46, 652}, + {0, 34, 34, 653}, + {0, 4, 4, 654}, + {0, 6, 6, 655}, + {0, 4, 4, 656}, + {1, 4, 4, 657}, + {0, 2, 2, 658}, + {1, 70, 70, 659}, + {1, 10, 10, 660}, + {1, 4, -1, 661}, + {1, 4, -1, 662}, + {1, 4, -1, 663}, + {1, 10, 10, 664}, + {1, 8, 8, 665}, + {1, 37, 37, 666}, + {1, 80, 80, 667}, + {0, 66, 66, 668}, + {1, 4, -1, 669}, + {1, 11, 11, 670}, + {0, 3, 3, 671}, + {1, 8, 8, 674}, + {0, 8, 8, 677}, + {0, 10, -1, 678}, + {0, 10, -1, 679}, + {0, 4, 4, 682}, + {0, 36, 36, 683}, + {0, 6, 6, 684}, + {0, 8, 8, 685}, + {0, 85, 85, 688}, + {1, 32, 32, 696}, + {1, 8, 8, 699}, + {1, 191, 191, 697}, + {0, 11, 11, 698}, + {0, 6, 6, 700}, + {1, 107, 107, 691}, + {1, 6, 6, 692}, + {0, 7, 7, 694}, + {1, 7, 7, 695}, + {1, 12, -1, 705}, + {1, 6, -1, 706}, + {1, 30, 30, 709}, + {0, 3, 3, 712}, + {1, 3, 3, 713}, + {1, 30, 30, 710}, + {0, 7, 7, 711}, + {1, 65, 65, 715}, + {1, 4, 4, 716}, + {1, 71, 71, 717}, + {1, 10, 10, 718}, + {0, 6, 6, 719}, + {1, 2, 2, 725}, + {1, 4, -1, 720}, + {1, 4, -1, 721}, + {1, 4, -1, 722}, + {1, 4, 4, 723}, + {1, 39, 39, 724}, + {0, 6, 6, 726}, + {1, 43, -1, 727}, + {0, 10, 10, 728}, + {1, 10, 10, 729}, + {1, 3, 3, 730}, + {0, 4, -1, 731}, + {1, 32, -1, 732}, + {1, 32, 32, 733}, + {1, 6, 6, 734}, + {1, 36, 36, 735}, + {1, 34, 34, 736}, + {1, 33, 33, 737}, + {0, 20, 20, 738}, + {0, 22, 22, 739}, + {0, 11, 11, 740}, + {0, 9, 9, 741}, + {0, 6, 6, 742}, + {1, 6, -1, 743}, + {1, 4, -1, 744}, + {1, 4, -1, 745}, + {1, 4, -1, 746}, + {1, 13, 13, 747}, + {1, 71, 71, 748}, + {1, 63, 63, 749}, + {1, 64, 64, 750}, + {1, 8, 8, 751}, + {1, 10, 10, 752}, + {0, 2, 2, 753}, + {1, 2, 2, 754}, + {0, 2, 2, 860}, + {0, 20, -1, 861}, + {0, 2, 2, 862}, + {0, 18, 18, 989}, + {0, 18, 18, 990}, + {0, 8, 8, 1081}, + {1, 8, 8, 1085}, + {1, 4, -1, 1086}, + {1, 25, 25, 1087}, + {1, 10, 10, 1088}, + {1, 4, 4, 1089}, + {1, 8, -1, 1090}, + {0, 8, 8, 1091}, + {1, 14, 14, 1094}, + {0, 4, -1, 1096}, + {0, 4, 4, 1097}, + {0, 6, 6, 1098}, + {0, 2, 2, 1099}, + {0, 2, 2, 1095}, + {0, 8, 8, 2007}, + {1, 8, 8, 2008}, + {1, 268, 268, 2009}, + {0, 6, 6, 2010}, + {1, 8, 8, 2011}, + {0, 6, 6, 2012}, + {1, 54, 54, 2013}, + {0, 30, 30, 2014}, + {0, 54, 54, 2015}, + {0, 58, 58, 2016}, + {1, 15, 15, 2017}, + {1, 8, 8, 2018}, + {1, 6, 6, 2019}, + {1, 8, 8, 2022}, + {0, 4, 4, 2021}, + {0, 4, -1, 2024}, + {0, 32, 32, 2023}, + {0, 5, 5, 2025}, + {0, 2, 2, 2026}, + {1, 8, -1, 2027}, + {1, 10, 10, 2029}, + {0, 6, 6, 2030}, + {1, 8, 8, 2031}, + {0, 6, 6, 2032}, + {1, 18, 18, 2033}, + {1, 8, 8, 2034}, + {1, 6, 6, 2035}, + {0, 3, 3, 2036}, + {0, 6, 6, 2037}, + {1, 14, 14, 2038}, + {1, 73, -1, 2039}, + {1, 66, -1, 2040}, + {1, 67, -1, 2041}, + {1, 8, 8, 2042}, + {1, 25, 25, 2043}, + {1, 10, 10, 2044}, + {1, 9, -1, 2045}, + {1, 26, 26, 2046}, + {1, 32, -1, 3127}, + {1, 32, -1, 3128}, + {1, 56, -1, 3129}, + {1, 41, -1, 3130}, + {1, 12, -1, 2048}, + {0, 12, -1, 2049}, + {1, 4, 4, 2051}, + {0, 14, 14, 2052}, + {1, 5, -1, 2053}, + {0, 2, 2, 2054}, + {1, 4, 4, 2055}, + {0, 14, 14, 2056}, + {1, 50, 50, 2057}, + {1, 18, 18, 2058}, + {1, 6, 6, 2059}, + {0, 2, 2, 2060}, + {1, 3, 3, 2061}, + {1, 14, 14, 2062}, + {1, 30, 30, 2063}, + {1, 3, 3, 2064}, + {1, 8, 8, 2066}, + {1, 12, -1, 2067}, + {1, 86, 86, 2068}, + {1, 6, 6, 2070}, + {1, 16, -1, 2072}, + {1, 4, 4, 2074}, + {1, 8, 8, 2084}, + {1, 12, 12, 2075}, + {1, 10, 10, 2076}, + {1, 22, 22, 2077}, + {1, 8, 8, 2078}, + {1, 9, -1, 2079}, + {0, 11, 11, 2080}, + {0, 2, 2, 2081}, + {0, 9, 9, 2082}, + {0, 4, -1, 2083}, + {0, 92, -1, 2085}, + {0, 156, -1, 3112}, + {0, 7, -1, 2102}, + {0, 3, 3, 2103}, + {1, 66, 66, 2105}, + {0, 5, 5, 2106}, + {0, 2, 2, 2107}, + {0, 6, 6, 2109}, + {0, 26, 26, 2110}, + {0, 4, -1, 2112}, + {0, 4, 4, 2113}, + {0, 6, 6, 2087}, + {0, 14, 14, 2088}, + {0, 12, 12, 2089}, + {0, 10, 10, 2090}, + {0, 6, 6, 2091}, + {0, 10, 10, 2092}, + {0, 6, 6, 2114}, + {0, 6, 6, 2115}, + {0, 2, 2, 2116}, + {0, 10, 10, 2117}, + {0, 4, 4, 2118}, + {0, 6, -1, 2119}, + {0, 10, -1, 2120}, + {0, 16, 16, 2121}, + {0, 2, 2, 2122}, + {1, 21, 21, 2123}, + {0, 10, 10, 2124}, + {0, 10, 10, 2125}, + {0, 5, 5, 2126}, + {0, 6, 6, 2127}, + {0, 7, 7, 2128}, + {0, 6, 6, 2133}, + {0, 4, -1, 2129}, + {0, 2, 2, 2130}, + {0, 4, -1, 2131}, + {0, 4, -1, 2132}, + {1, 75, -1, 2134}, + {1, 69, -1, 2135}, + {1, 68, -1, 2136}, + {1, 45, -1, 2137}, + {0, 4, -1, 2225}, + {0, 29, -1, 2093}, + {0, 6, -1, 2226}, + {0, 10, 10, 2223}, + {0, 17, 17, 2224}, + {0, 8, -1, 2227}, + {0, 2, 2, 2228}, + {0, 6, 6, 2229}, + {0, 3, 3, 2230}, + {0, 68, -1, 755}, + {0, 3, 3, 756}, + {0, 7, 7, 757}, + {0, 7, 7, 758}, + {0, 10, 10, 2232}, + {0, 12, 12, 2233}, + {0, 10, 10, 2234}, + {0, 8, 8, 2235}, + {0, 10, 10, 2236}, + {0, 8, 8, 2237}, + {0, 14, 14, 2238}, + {0, 8, 8, 2239}, + {0, 10, 10, 2243}, + {0, 8, 8, 2244}, + {0, 6, 6, 2245}, + {0, 4, 4, 2246}, + {0, 10, -1, 2240}, + {0, 2, 2, 2241}, + {0, 2, 2, 2242}, + {1, 19, -1, 2247}, + {1, 34, 34, 2248}, + {0, 2, 2, 2249}, + {0, 8, -1, 2250}, + {0, 10, -1, 2251}, + {0, 16, -1, 2427}, + {0, 109, 109, 2252}, + {0, 2, 2, 2254}, + {0, 10, 10, 2255}, + {1, 9, 9, 2256}, + {1, 7, 7, 2257}, + {1, 10, 10, 2258}, + {0, 10, 10, 2259}, + {0, 8, 8, 2260}, + {0, 8, -1, 2261}, + {0, 6, 6, 2262}, + {1, 28, 28, 2263}, + {1, 27, 27, 2264}, + {1, 30, 30, 2265}, + {1, 26, 26, 2266}, + {1, 27, 27, 2267}, + {1, 26, 26, 2268}, + {1, 27, 27, 2269}, + {1, 27, 27, 2270}, + {1, 50, 50, 2271}, + {1, 51, 51, 2272}, + {1, 51, 51, 2273}, + {0, 27, 27, 2274}, + {0, 157, 157, 2275}, + {0, 6, 6, 2276}, + {0, 30, 30, 2300}, + {0, 6, 6, 2301}, + {1, 4, -1, 2302}, + {1, 24, 24, 2303}, + {1, 4, -1, 2304}, + {1, 4, -1, 2305}, + {1, 4, -1, 2306}, + {1, 4, -1, 2307}, + {1, 4, -1, 2308}, + {1, 4, -1, 2309}, + {1, 45, -1, 2310}, + {0, 5, 5, 2311}, + {1, 5, 5, 2312}, + {1, 26, 26, 2314}, + {1, 10, -1, 2317}, + {0, 2, 2, 2318}, + {1, 10, 10, 2320}, + {1, 30, 30, 2321}, + {1, 10, 10, 2322}, + {1, 30, 30, 2323}, + {1, 84, -1, 2324}, + {1, 77, -1, 2319}, + {1, 78, -1, 2325}, + {1, 26, 26, 2326}, + {1, 4, 4, 2411}, + {1, 6, 6, 2412}, + {1, 4, -1, 2413}, + {1, 4, -1, 2414}, + {1, 7, 7, 2415}, + {1, 6, 6, 2417}, + {1, 9, -1, 2418}, + {1, 7, 7, 2419}, + {1, 2, 2, 2420}, + {1, 28, -1, 2421}, + {1, 28, -1, 2422}, + {1, 14, 14, 2423}, + {0, 6, 6, 2424}, + {0, 50, 50, 2425}, + {1, 8, -1, 2426}, + {0, 4, 4, 2428}, + {1, 288, 288, 2429}, + {1, 12, 12, 2430}, + {1, 8, -1, 2431}, + {1, 7, 7, 2432}, + {0, 12, -1, 2433}, + {0, 7, 7, 2434}, + {1, 29, 29, 2435}, + {1, 28, 28, 2436}, + {1, 4, -1, 2437}, + {0, 10, 10, 2438}, + {0, 41, -1, 2439}, + {0, 6, 6, 2440}, + {0, 2, 2, 2441}, + {0, 74, -1, 2442}, + {0, 4, -1, 2445}, + {0, 28, -1, 2446}, + {0, 2, 2, 2443}, + {0, 4, 4, 2444}, + {0, 8, -1, 2447}, + {1, 41, 41, 2448}, + {1, 4, -1, 2449}, + {1, 4, -1, 2450}, + {1, 4, -1, 2451}, + {1, 4, -1, 2452}, + {1, 28, -1, 2453}, + {1, 28, -1, 2454}, + {1, 45, -1, 2455}, + {1, 8, 8, 2456}, + {1, 11, 11, 2457}, + {1, 9, 9, 2458}, + {1, 8, 8, 2459}, + {0, 6, 6, 2460}, + {0, 4, -1, 2461}, + {0, 12, 12, 2462}, + {1, 22, -1, 2463}, + {0, 6, 6, 2464}, + {0, 2, 2, 2465}, + {0, 6, 6, 2466}, + {0, 8, -1, 2467}, + {0, 18, 18, 2468}, + {0, 7, 7, 2469}, + {0, 6, 6, 2475}, + {0, 12, 12, 2470}, + {0, 10, 10, 2471}, + {0, 16, 16, 2472}, + {0, 10, 10, 2473}, + {0, 16, 16, 2474}, + {0, 8, -1, 2476}, + {0, 12, 12, 2477}, + {0, 19, 19, 2478}, + {0, 4, 4, 2479}, + {0, 10, 10, 2480}, + {0, 4, 4, 2481}, + {0, 10, 10, 2482}, + {0, 6, 6, 2483}, + {0, 6, 6, 2484}, + {0, 2, 2, 2485}, + {0, 6, 6, 2486}, + {0, 4, 4, 2487}, + {0, 6, 6, 2488}, + {0, 4, 4, 2489}, + {0, 2, 2, 2490}, + {0, 6, 6, 2491}, + {0, 6, 6, 2492}, + {0, 2, 2, 2493}, + {0, 2, 2, 2494}, + {0, 4, 4, 2495}, + {0, 10, 10, 2497}, + {0, 4, -1, 2498}, + {0, 10, 10, 2499}, + {0, 10, 10, 2500}, + {0, 1042, 1042, 2501}, + {0, 16, -1, 2502}, + {0, 18, 18, 2503}, + {0, 13, -1, 2504}, + {0, 4, -1, 2505}, + {1, 23, -1, 2506}, + {1, 27, -1, 3016}, + {1, 17, 17, 2507}, + {0, 4, -1, 2508}, + {1, 8, 8, 2509}, + {1, 102, 102, 2510}, + {0, 4, -1, 2511}, + {0, 4, -1, 2512}, + {1, 14, 14, 2513}, + {0, 28, -1, 2514}, + {0, 28, -1, 2515}, + {0, 2, 2, 2516}, + {1, 4, -1, 2517}, + {1, 4, -1, 2518}, + {1, 2, 2, 2520}, + {1, 5, -1, 2519}, + {0, 4, 4, 2521}, + {0, 8, -1, 2522}, + {1, 88, -1, 2523}, + {1, 81, -1, 2524}, + {1, 82, -1, 2525}, + {1, 33, -1, 2526}, + {1, 7, 7, 2527}, + {0, 40, -1, 2528}, + {1, 8, 8, 2529}, + {1, 8, 8, 2530}, + {1, 8, 8, 2531}, + {1, 8, 8, 2532}, + {1, 18, 18, 2533}, + {1, 24, 24, 2534}, + {1, 3, 3, 2535}, + {1, 11, 11, 2536}, + {1, 2, 2, 2537}, + {1, 11, 11, 2542}, + {1, 11, 11, 2543}, + {1, 7, -1, 2544}, + {1, 7, -1, 2685}, + {1, 11, 11, 2549}, + {1, 11, 11, 2550}, + {1, 11, 11, 2538}, + {1, 24, -1, 2539}, + {1, 77, 77, 2551}, + {1, 64, -1, 2540}, + {1, 3, 3, 2541}, + {1, 11, 11, 2547}, + {1, 12, 12, 2548}, + {1, 11, 11, 2545}, + {1, 12, 12, 2546}, + {1, 6, 6, 2564}, + {1, 63, 63, 2565}, + {1, 6, 6, 2566}, + {1, 9, 9, 2567}, + {1, 2, 2, 2563}, + {1, 26, 26, 2568}, + {1, 27, 27, 2578}, + {1, 26, 26, 2579}, + {1, 10, 10, 2580}, + {1, 34, 34, 2641}, + {0, 2, 2, 2610}, + {1, 8, -1, 2552}, + {1, 143, 143, 2553}, + {1, 6, -1, 2554}, + {0, 8, -1, 2555}, + {1, 6, 6, 2556}, + {1, 90, -1, 2557}, + {1, 83, -1, 2558}, + {1, 84, -1, 2559}, + {1, 94, -1, 2999}, + {1, 269, 269, 2560}, + {0, 3, 3, 2561}, + {1, 4, 4, 2562}, + {1, 55, 55, 2569}, + {1, 57, 57, 2570}, + {1, 57, 57, 2571}, + {1, 66, 66, 2572}, + {1, 4, -1, 2573}, + {1, 4, -1, 2575}, + {1, 28, -1, 2576}, + {1, 28, -1, 2577}, + {1, 14, 14, 2574}, + {1, 12, 12, 2581}, + {0, 26, 26, 2582}, + {1, 6, 6, 2583}, + {1, 14, 14, 2584}, + {1, 18, 18, 2998}, + {1, 2, 2, 2585}, + {1, 25, 25, 2586}, + {1, 2, 2, 2587}, + {1, 8, -1, 2588}, + {1, 2, 2, 2589}, + {1, 3, 3, 2590}, + {1, 2, 2, 2591}, + {1, 23, 23, 2592}, + {1, 3, 3, 2593}, + {1, 7, 7, 2594}, + {1, 22, -1, 2595}, + {1, 66, 66, 2596}, + {1, 6, 6, 2597}, + {1, 7, 7, 2598}, + {1, 8, 8, 2599}, + {1, 3, 3, 2600}, + {0, 6, 6, 2601}, + {0, 6, 6, 2602}, + {0, 14, 14, 2603}, + {0, 12, 12, 2604}, + {0, 45, -1, 2605}, + {1, 6, 6, 2606}, + {1, 7, 7, 2607}, + {1, 106, 106, 2608}, + {0, 8, -1, 2609}, + {0, 36, -1, 3140}, + {0, 7, 7, 2611}, + {0, 6, 6, 2612}, + {0, 4, 4, 2613}, + {1, 7, 7, 2614}, + {1, 69, 69, 2615}, + {1, 3, 3, 2616}, + {1, 3, 3, 2664}, + {1, 7, 7, 2786}, + {1, 36, 36, 2617}, + {1, 12, 12, 2618}, + {1, 12, -1, 2619}, + {0, 18, -1, 2620}, + {0, 20, 20, 2621}, + {0, 16, -1, 2622}, + {0, 11, 11, 2623}, + {0, 11, 11, 2624}, + {0, 18, 18, 2625}, + {0, 43, 43, 2626}, + {0, 85, 85, 2627}, + {0, 28, -1, 2628}, + {0, 14, 14, 2630}, + {0, 3, 3, 2631}, + {0, 2, 2, 2632}, + {0, 16, 16, 2812}, + {0, 22, 22, 2633}, + {0, 6, 6, 2634}, + {0, 18, 18, 3139}, + {0, 22, 22, 2635}, + {0, 28, 28, 2636}, + {0, 2, 2, 2703}, + {0, 3, 3, 2704}, + {0, 6, 6, 2851}, + {0, 64, -1, 2637}, + {0, 67, -1, 2681}, + {0, 47, -1, 2913}, + {0, 63, -1, 2922}, + {0, 6, 6, 2638}, + {0, 2, 2, 2672}, + {0, 8, -1, 2639}, + {0, 4, 4, 2640}, + {0, 20, 20, 2642}, + {0, 10, 10, 2643}, + {0, 8, -1, 2644}, + {0, 2, 2, 2645}, + {0, 6, 6, 2646}, + {0, 6, 6, 2647}, + {0, 8, 8, 2648}, + {0, 8, -1, 2649}, + {0, 2, 2, 2650}, + {0, 7, 7, 2651}, + {0, 18, 18, 2652}, + {0, 6, 6, 2653}, + {0, 6, 6, 2665}, + {0, 12, 12, 2666}, + {0, 8, -1, 2667}, + {0, 7, 7, 2668}, + {0, 4, -1, 2669}, + {0, 26, 26, 2654}, + {0, 8, 8, 2655}, + {0, 3, 3, 2656}, + {1, 68, -1, 2670}, + {1, 10, -1, 2671}, + {0, 5, -1, 2673}, + {0, 61, 61, 2674}, + {0, 2, 2, 2675}, + {0, 8, 8, 2676}, + {0, 80, 80, 2678}, + {0, 15, 15, 2679}, + {0, 15, 15, 2680}, + {0, 4, -1, 2683}, + {0, 4, -1, 2684}, + {1, 5, -1, 2686}, + {1, 2, 2, 2700}, + {1, 6, 6, 2688}, + {1, 88, -1, 2687}, + {1, 17, -1, 2701}, + {1, 4, 4, 2689}, + {1, 96, -1, 2706}, + {1, 25, -1, 2705}, + {1, 3, 3, 2707}, + {1, 2, 2, 2708}, + {1, 61, 61, 2697}, + {1, 63, 63, 2821}, + {1, 6, 6, 2698}, + {1, 46, 46, 2690}, + {1, 46, 46, 2691}, + {1, 94, 94, 2692}, + {1, 82, 82, 2693}, + {1, 4, -1, 2694}, + {1, 4, -1, 2695}, + {1, 118, 118, 2939}, + {1, 4, -1, 2940}, + {1, 4, -1, 2941}, + {1, 60, 60, 2942}, + {0, 2, 2, 2696}, + {0, 2, 2, 2699}, + {0, 2, 2, 2702}, + {1, 4, 4, 2709}, + {0, 61, 61, 2710}, + {0, 8, 8, 2711}, + {0, 10, 10, 2712}, + {0, 4, 4, 2713}, + {0, 10, 10, 2714}, + {0, 4, -1, 2715}, + {0, 2, 2, 2716}, + {0, 4, 4, 2766}, + {0, 4, 4, 2717}, + {0, 2, 2, 2718}, + {0, 2, 2, 2719}, + {0, 2, 2, 2720}, + {0, 4, 4, 2721}, + {0, 7, -1, 2722}, + {0, 7, -1, 3121}, + {0, 9, 9, 2723}, + {0, 2, 2, 2724}, + {1, 4, -1, 2725}, + {1, 36, 36, 2726}, + {1, 6, 6, 2727}, + {1, 5, 5, 2728}, + {1, 4, -1, 2729}, + {1, 4, -1, 2730}, + {1, 5, -1, 2731}, + {0, 69, 69, 2732}, + {1, 14, 14, 2737}, + {0, 51, 51, 2733}, + {0, 2, 2, 2734}, + {0, 6, 6, 2735}, + {0, 6, 6, 2736}, + {0, 2, 2, 2746}, + {0, 2, 2, 2747}, + {0, 7, 7, 2738}, + {0, 19, 19, 2739}, + {0, 6, 6, 2740}, + {0, 2, 2, 2741}, + {0, 8, 8, 2742}, + {0, 4, 4, 2743}, + {0, 2, 2, 2744}, + {0, 47, 47, 2745}, + {0, 4, -1, 2748}, + {0, 10, 10, 2749}, + {0, 6, -1, 2750}, + {0, 4, -1, 2751}, + {0, 26, 26, 2752}, + {0, 26, 26, 2753}, + {0, 5, -1, 2754}, + {0, 2, 2, 2755}, + {0, 64, -1, 2756}, + {0, 156, 156, 2757}, + {0, 156, 156, 2758}, + {1, 156, 156, 2759}, + {0, 2, 2, 2760}, + {0, 47, -1, 2761}, + {0, 3, 3, 2762}, + {0, 12, 12, 2763}, + {0, 18, 18, 2764}, + {0, 23, 23, 2765}, + {0, 68, 68, 2767}, + {0, 94, 94, 3110}, + {0, 11, 11, 2768}, + {0, 8, -1, 2769}, + {0, 9, 9, 3107}, + {1, 30, 30, 2770}, + {1, 4, -1, 2771}, + {1, 4, -1, 2772}, + {0, 2, 2, 2773}, + {1, 2, 2, 2774}, + {0, 8, 8, 2775}, + {0, 8, 8, 2776}, + {1, 6, -1, 2777}, + {1, 32, 32, 2778}, + {1, 33, 33, 3131}, + {0, 8, -1, 2779}, + {1, 6, 6, 2780}, + {1, 24, 24, 2781}, + {0, 6, 6, 2782}, + {0, 58, 58, 2783}, + {0, 30, 30, 2784}, + {0, 28, 28, 2785}, + {1, 89, 89, 2788}, + {1, 28, -1, 2789}, + {0, 28, -1, 2787}, + {0, 10, 10, 2790}, + {0, 38, 38, 2791}, + {0, 2, 2, 2792}, + {0, 2, 2, 2796}, + {0, 2, 2, 2797}, + {0, 2, 2, 2798}, + {0, 13, 13, 2793}, + {0, 2, 2, 2799}, + {0, 10, 10, 2800}, + {0, 102, 102, 2801}, + {1, 40, 40, 2802}, + {1, 4, -1, 2803}, + {0, 11, 11, 2804}, + {0, 3, 3, 2805}, + {0, 88, 88, 2806}, + {0, 32, 32, 2807}, + {0, 11, 11, 2808}, + {0, 6, 6, 2809}, + {0, 58, 58, 2810}, + {1, 4, -1, 2811}, + {1, 8, -1, 2813}, + {1, 155, 155, 2828}, + {1, 6, -1, 2814}, + {1, 8, -1, 2815}, + {1, 8, 8, 2816}, + {0, 56, 56, 2817}, + {0, 26, 26, 2818}, + {0, 47, -1, 2819}, + {0, 190, 190, 2820}, + {0, 47, -1, 2823}, + {1, 5, -1, 2824}, + {1, 5, -1, 2825}, + {1, 5, -1, 2826}, + {1, 4, 4, 2827}, + {1, 10, 10, 2829}, + {1, 4, -1, 2830}, + {1, 4, -1, 2831}, + {1, 10, 10, 2832}, + {1, 4, 4, 2833}, + {-1, 2, 2, 2834}, + {0, 48, 48, 2835}, + {0, 2, 2, 2836}, + {0, 2, 2, 2838}, + {0, 2, 2, 2841}, + {1, 7, 7, 2837}, + {1, 3, 3, 2839}, + {1, 4, 4, 2840}, + {1, 29, 29, 2842}, + {1, 2, 2, 2843}, + {0, 2, 2, 2844}, + {0, 2, 2, 2845}, + {0, 14, 14, 2846}, + {1, 14, 14, 2847}, + {1, 271, 271, 2848}, + {0, 5, 5, 2850}, + {0, 13, 13, 2849}, + {1, 6, 6, 2852}, + {1, 6, 6, 2853}, + {1, 4, -1, 2855}, + {1, 3, 3, 2856}, + {1, 11, 11, 2859}, + {1, 3, 3, 2860}, + {1, 11, 11, 2861}, + {1, 4, 4, 2862}, + {1, 73, 73, 2863}, + {1, 4, -1, 2864}, + {1, 17, 17, 2865}, + {1, 4, -1, 2866}, + {1, 17, 17, 2867}, + {0, 50, 50, 2868}, + {0, 3, 3, 2869}, + {1, 14, -1, 2870}, + {1, 47, -1, 2871}, + {1, 5, -1, 2873}, + {1, 4, 4, 2876}, + {1, 12, -1, 2877}, + {1, 8, -1, 2878}, + {1, 64, 64, 2879}, + {1, 8, -1, 2880}, + {1, 70, 70, 2881}, + {1, 62, 62, 2882}, + {1, 48, 48, 2883}, + {1, 58, 58, 2884}, + {1, 58, 58, 2885}, + {0, 10, 10, 2886}, + {1, 14, 14, 2887}, + {0, 18, 18, 2888}, + {0, 4, 4, 2889}, + {0, 6, 6, 2890}, + {0, 4, 4, 2891}, + {0, 2, 2, 2892}, + {0, 6, -1, 2893}, + {0, 2, 2, 2895}, + {0, 2, 2, 2896}, + {0, 2, 2, 2897}, + {0, 2, 2, 2898}, + {0, 52, 52, 2899}, + {0, 8, 8, 2900}, + {1, 6, -1, 2894}, + {0, 4, -1, 2901}, + {1, 8, -1, 2902}, + {1, 4, -1, 2903}, + {1, 2, 2, 2904}, + {1, 4, 4, 2905}, + {1, 34, -1, 2906}, + {1, 14, 14, 2907}, + {1, 2, 2, 2908}, + {1, 10, 10, 2909}, + {1, 33, 33, 2910}, + {0, 5, -1, 2911}, + {0, 64, -1, 2912}, + {1, 17, -1, 2914}, + {1, 24, -1, 2915}, + {1, 7, -1, 2916}, + {1, 4, -1, 2917}, + {1, 26, 26, 2918}, + {1, 33, 33, 2919}, + {1, 12, 12, 2920}, + {1, 18, 18, 2921}, + {1, 14, 14, 2923}, + {1, 12, 12, 2924}, + {0, 6, 6, 2925}, + {0, 14, 14, 2926}, + {0, 177, 177, 2927}, + {0, 8, -1, 2928}, + {0, 177, 177, 2929}, + {0, 4, -1, 2930}, + {1, 8, 8, 2931}, + {0, 1026, 1026, 2932}, + {0, 1026, 1026, 2933}, + {1, 77, 77, 2934}, + {1, 4, -1, 2935}, + {1, 4, -1, 2936}, + {1, 8, -1, 2937}, + {1, 4, -1, 2938}, + {1, 10, 10, 2943}, + {1, 5, -1, 2956}, + {1, 5, -1, 2957}, + {1, 18, 18, 2958}, + {0, 6, 6, 2959}, + {0, 2, 2, 2960}, + {0, 8, 8, 2961}, + {0, 5, 5, 2962}, + {0, 12, 12, 2963}, + {0, 14, 14, 2964}, + {0, 4, -1, 2965}, + {0, 26, 26, 2966}, + {0, 27, 27, 2967}, + {0, 6, 6, 2968}, + {0, 10, 10, 2969}, + {0, 11, 11, 2970}, + {0, 12, 12, 2971}, + {0, 16, 16, 2972}, + {0, 14, 14, 2973}, + {0, 12, 12, 2974}, + {0, 10, 10, 2975}, + {0, 2, 2, 2976}, + {0, 3, 3, 2977}, + {0, 10, 10, 2978}, + {0, 10, 10, 2979}, + {1, 85, 85, 2980}, + {1, 12, 12, 2981}, + {1, 8, -1, 2982}, + {1, 8, -1, 2983}, + {1, 8, -1, 3101}, + {1, 7, 7, 2984}, + {1, 8, -1, 2985}, + {1, 22, 22, 2986}, + {1, 22, 22, 2987}, + {0, 22, 22, 2988}, + {0, 2, 2, 2989}, + {0, 6, 6, 3061}, + {0, 3, 3, 2990}, + {0, 16, 16, 2991}, + {0, 9, 9, 2992}, + {0, 3, 3, 2993}, + {0, 2, 2, 2994}, + {0, 8, -1, 2995}, + {0, 31, 31, 2996}, + {0, 10, 10, 2997}, + {1, 9, -1, 3002}, + {-1, 5, -1, 3003}, + {1, 22, 22, 3004}, + {0, 6, 6, 3005}, + {1, 6, 6, 3006}, + {1, 12, 12, 3007}, + {0, 3, 3, 3008}, + {0, 13, -1, 3009}, + {0, 10, 10, 3011}, + {0, 9, 9, 3014}, + {0, 22, -1, 3034}, + {0, 19, 19, 3035}, + {0, 18, 18, 3036}, + {0, 5, 5, 3010}, + {0, 2, 2, 3012}, + {0, 7, 7, 3013}, + {0, 6, 6, 3015}, + {1, 10, 10, 3017}, + {1, 8, -1, 3018}, + {0, 4, 4, 3019}, + {0, 9, -1, 3020}, + {0, 9, -1, 3021}, + {0, 8, 8, 3022}, + {0, 9, 9, 3023}, + {0, 8, 8, 3024}, + {0, 13, 13, 3025}, + {0, 8, 8, 3026}, + {0, 13, 13, 3027}, + {0, 2, 2, 3028}, + {0, 9, 9, 3029}, + {0, 8, 8, 3030}, + {0, 9, 9, 3031}, + {0, 14, 14, 3032}, + {0, 51, 51, 3033}, + {0, 4, -1, 3037}, + {1, 4, -1, 3038}, + {0, 3, 3, 3039}, + {0, 3, 3, 3040}, + {0, 3, 3, 3041}, + {0, 137, 137, 3042}, + {0, 34, 34, 3043}, + {0, 14, 14, 3044}, + {0, 8, 8, 3045}, + {0, 8, 8, 3046}, + {0, 4, 4, 3047}, + {0, 4, 4, 3048}, + {0, 6, 6, 3049}, + {0, 10, 10, 3050}, + {0, 7, 7, 3051}, + {0, 7, 7, 3052}, + {0, 9, 9, 3053}, + {0, 5, 5, 3054}, + {0, 8, -1, 3055}, + {0, 14, 14, 3056}, + {0, 18, 18, 3057}, + {0, 13, 13, 3058}, + {0, 4, -1, 3059}, + {0, 4, -1, 3060}, + {0, 10, -1, 3062}, + {0, 6, -1, 3063}, + {0, 6, 6, 3064}, + {0, 11, 11, 3065}, + {0, 9, 9, 3066}, + {0, 35, 35, 3067}, + {0, 6, 6, 3068}, + {0, 4, 4, 3069}, + {0, 76, -1, 3070}, + {1, 24, 24, 3071}, + {0, 6, 6, 3072}, + {0, 6, 6, 3073}, + {0, 6, 6, 3074}, + {0, 6, 6, 3075}, + {0, 8, 8, 3076}, + {0, 7, 7, 3090}, + {0, 11, 11, 3089}, + {0, 11, 11, 3091}, + {0, 14, 14, 3092}, + {0, 30, 30, 3077}, + {0, 8, 8, 3078}, + {0, 12, 12, 3079}, + {0, 6, 6, 3080}, + {0, 116, 116, 3081}, + {0, 30, 30, 3082}, + {0, 10, 10, 3102}, + {0, 12, 12, 3109}, + {0, 18, 18, 3083}, + {0, 4, 4, 3084}, + {0, 167, 167, 3085}, + {0, 689, 689, 3086}, + {0, 610, 610, 3087}, + {0, 15, 15, 3088}, + {1, 9, -1, 3093}, + {0, 9, 9, 3094}, + {1, 10, 10, 3095}, + {0, 20, 20, 3096}, + {0, 8, 8, 3097}, + {0, 20, 20, 3098}, + {0, 8, 8, 3099}, + {0, 4, -1, 3104}, + {0, 4, -1, 3105}, + {0, 12, 12, 3106}, + {0, 979, 979, 3108}, + {0, 2, 2, 3111}, + {0, 26, -1, 3113}, + {0, 3, 3, 3117}, + {0, 15, 15, 3118}, + {0, 2, 2, 3119}, + {0, 15, 15, 3120}, + {0, 7, 7, 3135}, + {0, 19, 19, 3136}, + {0, 2, 2, 3137}, + {0, 19, 19, 3138}, + {0, 4, 4, 3114}, + {0, 8, 8, 3115}, + {0, 4, 4, 3116}, + {0, 64, -1, 3122}, + {0, 8, 8, 3123}, + {0, 3, 3, 3124}, + {0, 6, 6, 3125}, + {1, 12, 12, 3126}, + {1, 6, 6, 3132}, + {0, 6, 6, 3133}, + {0, 8, 8, 3134}, diff --git a/Source/Network/PartyJoinPacket.cpp b/Source/Network/Packets/PartyJoinPacket.cpp similarity index 64% rename from Source/Network/PartyJoinPacket.cpp rename to Source/Network/Packets/PartyJoinPacket.cpp index efd3d1a..5a381e6 100644 --- a/Source/Network/PartyJoinPacket.cpp +++ b/Source/Network/Packets/PartyJoinPacket.cpp @@ -1,17 +1,12 @@ -#include "Network/Connection.h" -#include "Network/PacketLengths.h" -#include "Network/PartyJoinPacket.h" -#include "UI/WindowManagerWindows.h" +#include "Network/Connection/Connection.h" +#include "Network/Packets/PacketLengths.h" +#include "Network/Packets/PartyJoinPacket.h" +#include "UI/Window/WindowManagerWindows.h" #include // ORIGINAL_SITE: 0x00CF7D40 in fn_21426 (fragment) -void SendPartyJoin( - CConnection& connection, - const PacketLengths& lengths, - const std::uint32_t* accountId, - const std::uint32_t* characterId -) { +void SendPartyJoin(CConnection& connection, const PacketLengths& lengths, const std::uint32_t* accountId, const std::uint32_t* characterId) { unsigned char packet[10]; const std::uint16_t id = 0x0AE6; std::memcpy(packet, &id, sizeof(id)); @@ -21,13 +16,7 @@ void SendPartyJoin( } // ORIGINAL_SITE: 0x00CF7CE6 in fn_21426 (fragment) -void SendPartyJoinDecision( - CConnection& connection, - const PacketLengths& lengths, - std::uint32_t characterId, - bool accepted, - const std::uint32_t* accountId -) { +void SendPartyJoinDecision(CConnection& connection, const PacketLengths& lengths, std::uint32_t characterId, bool accepted, const std::uint32_t* accountId) { unsigned char packet[11]; const std::uint16_t id = 0x0AF8; std::memcpy(packet, &id, sizeof(id)); @@ -39,12 +28,7 @@ void SendPartyJoinDecision( // ORIGINAL_SITE: 0x00CF7C15 in fn_21426 (fragment) void SendPartyInvitationDecision( - CConnection& connection, - const PacketLengths& lengths, - WindowManagerWindows& windows, - std::string& pendingName, - std::uint32_t identity, - bool accepted + CConnection& connection, const PacketLengths& lengths, WindowManagerWindows& windows, std::string& pendingName, std::uint32_t identity, bool accepted ) { if (accepted) { windows.EnsureWindow(34); diff --git a/Source/Network/Packets/PartyJoinPacket.h b/Source/Network/Packets/PartyJoinPacket.h new file mode 100644 index 0000000..2088caf --- /dev/null +++ b/Source/Network/Packets/PartyJoinPacket.h @@ -0,0 +1,18 @@ +#ifndef RAGNAROK_SOURCE_NETWORK_PACKETS_PARTYJOINPACKET_H +#define RAGNAROK_SOURCE_NETWORK_PACKETS_PARTYJOINPACKET_H + +#include +#include + +class CConnection; +struct PacketLengths; +class WindowManagerWindows; + +void SendPartyJoin(CConnection& connection, const PacketLengths& lengths, const std::uint32_t* accountId, const std::uint32_t* characterId); +void SendPartyJoinDecision(CConnection& connection, const PacketLengths& lengths, std::uint32_t characterId, bool accepted, const std::uint32_t* accountId); +void ReceivePartyJoinRequest(const void* packet); +void SendPartyInvitationDecision( + CConnection& connection, const PacketLengths& lengths, WindowManagerWindows& windows, std::string& pendingName, std::uint32_t identity, bool accepted +); + +#endif diff --git a/Source/Network/PartyJoinRequest.cpp b/Source/Network/Packets/PartyJoinRequest.cpp similarity index 74% rename from Source/Network/PartyJoinRequest.cpp rename to Source/Network/Packets/PartyJoinRequest.cpp index 2d60520..65a60fe 100644 --- a/Source/Network/PartyJoinRequest.cpp +++ b/Source/Network/Packets/PartyJoinRequest.cpp @@ -1,5 +1,5 @@ -#include "Network/PartyJoinPacket.h" -#include "UI/UIRequestJoinPartyMgr.h" +#include "Network/Packets/PartyJoinPacket.h" +#include "UI/Party/UIRequestJoinPartyMgr.h" #include @@ -18,7 +18,6 @@ void ReceivePartyJoinRequest(const void* packet) { std::memcpy(&job, bytes + 34, sizeof(job)); std::memcpy(&account, bytes + 2, sizeof(account)); std::memcpy(&character, bytes + 6, sizeof(character)); - // The original loads the manager pointer straight from its global and - // dereferences it without a null check; the dispatch already registered it. + g_requestJoinPartyMgr->Add(character, account, name, job, level); } diff --git a/Source/Network/ShortcutPacket.cpp b/Source/Network/Packets/ShortcutPacket.cpp similarity index 72% rename from Source/Network/ShortcutPacket.cpp rename to Source/Network/Packets/ShortcutPacket.cpp index 3fda33d..be05a02 100644 --- a/Source/Network/ShortcutPacket.cpp +++ b/Source/Network/Packets/ShortcutPacket.cpp @@ -1,25 +1,21 @@ -#include "Contents/NormalItemSlots.h" -#include "Network/Connection.h" -#include "Network/PacketLengths.h" -#include "Network/ShortcutPacket.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "Network/Connection/Connection.h" +#include "Network/Packets/PacketLengths.h" +#include "Network/Packets/ShortcutPacket.h" #include #include // ORIGINAL_SITE: 0x00CFB806 in fn_21426 (fragment) void SendShortcutUpdate( - CConnection& connection, - const PacketLengths& lengths, - int index, - int bank, - const NormalItemSlot* bank0, - const NormalItemSlot* bank1, + CConnection& connection, const PacketLengths& lengths, int index, int bank, const NormalItemSlot* bank0, const NormalItemSlot* bank1, const NormalItemSlot* special ) { unsigned char packet[13]; const std::uint32_t header = 2849; std::memcpy(packet, &header, sizeof(header)); const NormalItemSlot* slot = nullptr; + if (index >= 36) { if (static_cast(index) - 36u <= 1) { slot = &special[index - 36]; @@ -31,9 +27,11 @@ void SendShortcutUpdate( const std::uint16_t flag = 1; std::memcpy(packet + 2, &flag, sizeof(flag)); } + if (slot) { std::memcpy(packet + 6, slot, sizeof(*slot)); } + const auto position = static_cast(index); std::memcpy(packet + 4, &position, sizeof(position)); connection.Send(lengths.FixedLength(2849), packet); diff --git a/Source/Network/Packets/ShortcutPacket.h b/Source/Network/Packets/ShortcutPacket.h new file mode 100644 index 0000000..3c659fa --- /dev/null +++ b/Source/Network/Packets/ShortcutPacket.h @@ -0,0 +1,13 @@ +#ifndef RAGNAROK_SOURCE_NETWORK_PACKETS_SHORTCUTPACKET_H +#define RAGNAROK_SOURCE_NETWORK_PACKETS_SHORTCUTPACKET_H + +struct NormalItemSlot; +class CConnection; +struct PacketLengths; + +void SendShortcutUpdate( + CConnection& connection, const PacketLengths& lengths, int index, int bank, const NormalItemSlot* bank0, const NormalItemSlot* bank1, + const NormalItemSlot* special +); + +#endif diff --git a/Source/Network/SkillUpdatePacket.cpp b/Source/Network/Packets/SkillUpdatePacket.cpp similarity index 85% rename from Source/Network/SkillUpdatePacket.cpp rename to Source/Network/Packets/SkillUpdatePacket.cpp index d562862..6f2e0e3 100644 --- a/Source/Network/SkillUpdatePacket.cpp +++ b/Source/Network/Packets/SkillUpdatePacket.cpp @@ -1,5 +1,5 @@ -#include "Network/SkillUpdatePacket.h" -#include "UI/WindowOrdering.h" +#include "Network/Packets/SkillUpdatePacket.h" +#include "UI/Window/WindowOrdering.h" #include @@ -20,11 +20,10 @@ void SkillUpdatePacket::Apply(const void* packet) { const auto opcode = Read(bytes); const auto id = Read(bytes + 2); CSkillInfo value; + switch (opcode) { case 270: - value = this->client.bundle.Lookup( - id, this->client.classMode, this->client.HasEffect(1717), this->client.HasEffect(1716) - ); + value = this->client.bundle.Lookup(id, this->client.classMode, this->client.HasEffect(1717), this->client.HasEffect(1716)); break; case 569: value = this->client.LookupFirst(id); @@ -58,13 +57,7 @@ void SkillUpdatePacket::Apply(const void* packet) { // OFFSET: 0x00D06AF0 // FUNCTION: fn_21577 void LearnedSkillReceiver::Apply( - std::uint16_t id, - std::int16_t level, - int unknown000C, - std::uint8_t unknown0018, - std::int16_t unknown0014, - std::int16_t unknown001C, - std::int16_t unknown0030 + std::uint16_t id, std::int16_t level, int unknown000C, std::uint8_t unknown0018, std::int16_t unknown0014, std::int16_t unknown001C, std::int16_t unknown0030 ) { CSkillInfo value; value.unknown_000C = unknown000C; @@ -74,7 +67,7 @@ void LearnedSkillReceiver::Apply( value.name = value.IdName(this->script); value.unknown_0014 = unknown0014; value.unknown_001C = unknown001C; - value.unknown_0030 = static_cast(unknown0030); + value.unknown_0030 = unknown0030; value.unknown_0034 = value.UseApAmount(this->script, level); this->client.bundle.RecordLevelChange(value); @@ -92,10 +85,11 @@ void AdditionalSkillPacket::Apply(const void* packet) { this->client.additional.clear(); const auto* bytes = static_cast(packet); - // Original divides a zero-extended (signed length - 6) by 37. + const auto length = static_cast(static_cast(Read(bytes + 2)) - 6); const std::uint32_t count = length / 37; const unsigned char* record = bytes + 6; + for (std::uint32_t index = 0; index < count; ++index, record += 37) { CSkillInfo value; value.level = Read(record + 6); diff --git a/Source/Network/Packets/SkillUpdatePacket.h b/Source/Network/Packets/SkillUpdatePacket.h new file mode 100644 index 0000000..afac1bf --- /dev/null +++ b/Source/Network/Packets/SkillUpdatePacket.h @@ -0,0 +1,45 @@ +#ifndef RAGNAROK_SOURCE_NETWORK_PACKETS_SKILLUPDATEPACKET_H +#define RAGNAROK_SOURCE_NETWORK_PACKETS_SKILLUPDATEPACKET_H + +#include "Contents/Skills/ClientSkills.h" + +struct WindowOrdering; + +struct SkillUpdatePacket { + int& pending; + ClientSkills& client; + CompanionSkills& first; + CompanionSkills& other; + LuaScript& script; + const SkillUseLevels& levels; + SkillWindows& windows; + + void Apply(const void* packet); +}; + +struct LearnedSkillReceiver { + ClientSkills& client; + LuaScript& script; + const SkillUseLevels& levels; + SkillWindows& windows; + int& skill336; + + void Apply( + std::uint16_t id, std::int16_t level, int unknown000C, std::uint8_t unknown0018, std::int16_t unknown0014, std::int16_t unknown001C, + std::int16_t unknown0030 + ); +}; + +struct AdditionalSkillPacket { + int& pending; + ClientSkills& client; + LuaScript& script; + int& capacity; + WindowOrdering& ordering; + int& frameLatch; + CompanionSkills& windows; + + void Apply(const void* packet); +}; + +#endif diff --git a/Source/Network/PartyJoinPacket.h b/Source/Network/PartyJoinPacket.h deleted file mode 100644 index da67965..0000000 --- a/Source/Network/PartyJoinPacket.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef RAGNAROK_SOURCE_NETWORK_PARTYJOINPACKET_H -#define RAGNAROK_SOURCE_NETWORK_PARTYJOINPACKET_H - -#include -#include - -class CConnection; -struct PacketLengths; -class WindowManagerWindows; - -void SendPartyJoin( - CConnection& connection, - const PacketLengths& lengths, - const std::uint32_t* accountId, - const std::uint32_t* characterId -); -void SendPartyJoinDecision( - CConnection& connection, - const PacketLengths& lengths, - std::uint32_t characterId, - bool accepted, - const std::uint32_t* accountId -); -void ReceivePartyJoinRequest(const void* packet); -void SendPartyInvitationDecision( - CConnection& connection, - const PacketLengths& lengths, - WindowManagerWindows& windows, - std::string& pendingName, - std::uint32_t identity, - bool accepted -); - -#endif diff --git a/Source/Network/ShortcutPacket.h b/Source/Network/ShortcutPacket.h deleted file mode 100644 index 5fd5b91..0000000 --- a/Source/Network/ShortcutPacket.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef RAGNAROK_SOURCE_NETWORK_SHORTCUTPACKET_H -#define RAGNAROK_SOURCE_NETWORK_SHORTCUTPACKET_H - -struct NormalItemSlot; -class CConnection; -struct PacketLengths; - -// Exact event313 operation; caller supplies actual bank and special-slot owners. -void SendShortcutUpdate( - CConnection& connection, - const PacketLengths& lengths, - int index, - int bank, - const NormalItemSlot* bank0, - const NormalItemSlot* bank1, - const NormalItemSlot* special -); - -#endif diff --git a/Source/Network/SkillUpdatePacket.h b/Source/Network/SkillUpdatePacket.h deleted file mode 100644 index 2659925..0000000 --- a/Source/Network/SkillUpdatePacket.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef RAGNAROK_SOURCE_NETWORK_SKILLUPDATEPACKET_H -#define RAGNAROK_SOURCE_NETWORK_SKILLUPDATEPACKET_H - -#include "Contents/ClientSkills.h" - -struct WindowOrdering; - -// Borrowed original game-mode pending flag (+0x10C) and skill owners. -struct SkillUpdatePacket { - int& pending; - ClientSkills& client; - CompanionSkills& first; - CompanionSkills& other; - LuaScript& script; - const SkillUseLevels& levels; - SkillWindows& windows; - - // Packet storage must provide the original 11-byte record. IDs/fields are - // decoded at their observed widths; unknown opcodes still clear pending and - // apply level-change bookkeeping, but do not publish a skill list update. - void Apply(const void* packet); -}; - -struct LearnedSkillReceiver { - ClientSkills& client; - LuaScript& script; - const SkillUseLevels& levels; - SkillWindows& windows; - int& skill336; // Set to 1 only for skill 336 - - // Resolve ID name, then AP amount, record a grouped level increase, publish - // the 336 latch, then update client skills. Does not reset the pending flag - // used by SkillUpdatePacket; existing base unknown_000C remains unchanged. - void Apply( - std::uint16_t id, - std::int16_t level, - int unknown000C, - std::uint8_t unknown0018, - std::int16_t unknown0014, - std::int16_t unknown001C, - std::int16_t unknown0030 - ); -}; - -struct AdditionalSkillPacket { - int& pending; - ClientSkills& client; - LuaScript& script; - int& capacity; - WindowOrdering& ordering; - int& frameLatch; - CompanionSkills& windows; // notification only: additional/shared windows - - // Six-byte header and 37-byte records; enclosing dispatcher owns extent - // validation. Name/AP callbacks run even for IDs rejected by 10000..10019. - void Apply(const void* packet); -}; - -#endif diff --git a/Source/Network/TextEncoding.cpp b/Source/Network/TextEncoding.cpp index f13668e..9e32ea4 100644 --- a/Source/Network/TextEncoding.cpp +++ b/Source/Network/TextEncoding.cpp @@ -15,20 +15,23 @@ std::string ToUtf8(std::string text) { std::string result; int wideLength = MultiByteToWideChar(g_textCodePage, 0, text.c_str(), lstrlenA(text.c_str()), nullptr, 0); BSTR wide = SysAllocStringLen(nullptr, wideLength); + if (wide) { MultiByteToWideChar(g_textCodePage, 0, text.c_str(), lstrlenA(text.c_str()), wide, wideLength); int length = WideCharToMultiByte(CP_UTF8, 0, wide, -1, nullptr, 0, nullptr, nullptr); char* converted = static_cast(_malloca(length + 1)); + if (converted) { WideCharToMultiByte(CP_UTF8, 0, wide, -1, converted, length, nullptr, nullptr); result.assign(converted, std::strlen(converted)); _freea(converted); } else { - // Original failure path reaches an unchecked null string assignment. result.assign(converted, std::strlen(converted)); } + SysFreeString(wide); } + return result; } @@ -41,14 +44,17 @@ std::string FromUtf8(std::string text) { MultiByteToWideChar(CP_UTF8, 0, text.c_str(), lstrlenA(text.c_str()) + 1, wide, wideLength); int length = WideCharToMultiByte(g_textCodePage, 0, wide, -1, nullptr, 0, nullptr, nullptr); char* converted = static_cast(_malloca(length + 1)); + if (converted) { WideCharToMultiByte(g_textCodePage, 0, wide, -1, converted, length, nullptr, nullptr); result.assign(converted, std::strlen(converted)); _freea(converted); } + if (wide) { SysFreeString(wide); } + return result; } @@ -59,28 +65,34 @@ std::string FromUtf8(const std::string& text, UINT codePage) { if (!wideLength) { return {}; } + BSTR wide = SysAllocStringLen(nullptr, wideLength); if (!wide) { return {}; } + if (!MultiByteToWideChar(CP_UTF8, 0, text.data(), static_cast(text.size()), wide, wideLength)) { SysFreeString(wide); return {}; } + int length = WideCharToMultiByte(codePage, 0, wide, -1, nullptr, 0, nullptr, nullptr); if (!length) { SysFreeString(wide); return {}; } + char* converted = static_cast(std::malloc(length)); if (!converted) { SysFreeString(wide); return {}; } + std::string result; if (WideCharToMultiByte(codePage, 0, wide, -1, converted, length, nullptr, nullptr)) { result.assign(converted); } + std::free(converted); SysFreeString(wide); return result; @@ -93,28 +105,34 @@ std::string ToUtf8(const std::string& text, UINT codePage) { if (!wideLength) { return {}; } + BSTR wide = SysAllocStringLen(nullptr, wideLength); if (!wide) { return {}; } + if (!MultiByteToWideChar(codePage, 0, text.data(), static_cast(text.size()), wide, wideLength)) { SysFreeString(wide); return {}; } + int length = WideCharToMultiByte(CP_UTF8, 0, wide, -1, nullptr, 0, nullptr, nullptr); if (!length) { SysFreeString(wide); return {}; } + char* converted = static_cast(std::malloc(length)); if (!converted) { SysFreeString(wide); return {}; } + std::string result; if (WideCharToMultiByte(CP_UTF8, 0, wide, -1, converted, length, nullptr, nullptr)) { result.assign(converted); } + std::free(converted); SysFreeString(wide); return result; diff --git a/Source/Network/TextEncoding.h b/Source/Network/TextEncoding.h index c1dbe35..85cac7b 100644 --- a/Source/Network/TextEncoding.h +++ b/Source/Network/TextEncoding.h @@ -8,12 +8,9 @@ // GLOBAL: gl_24375 extern UINT g_textCodePage; -// Reconstructed names for original Win32/BSTR conversion operations. std::string ToUtf8(std::string text); std::string FromUtf8(std::string text); -// Distinct original helper uses string length and reports conversion failures -// as empty strings, unlike the earlier global-codepage helper's odd paths. std::string FromUtf8(const std::string& text, UINT codePage); std::string ToUtf8(const std::string& text, UINT codePage); diff --git a/Source/Render/AlphaRectangle.h b/Source/Render/AlphaRectangle.h deleted file mode 100644 index ffd25be..0000000 --- a/Source/Render/AlphaRectangle.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RAGNAROK_SOURCE_RENDER_ALPHARECTANGLE_H -#define RAGNAROK_SOURCE_RENDER_ALPHARECTANGLE_H - -#include - -class RenderPrimitivePool; -class TextureCache; -struct RenderQueues; - -// Original global renderer/texture-cache dependencies are borrowed. A zero -// alpha byte returns before acquiring a pooled primitive or default texture. -void DrawAlphaRectangle( - RenderPrimitivePool& primitives, - TextureCache& textures, - RenderQueues& queues, - int x, - int y, - int width, - int height, - std::uint32_t color, - bool depthAlpha, - float depthStart, - float depthEnd -); - -#endif diff --git a/Source/Render/BitmapPixels.h b/Source/Render/BitmapPixels.h deleted file mode 100644 index 14deeb0..0000000 --- a/Source/Render/BitmapPixels.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef RAGNAROK_SOURCE_RENDER_BITMAPPIXELS_H -#define RAGNAROK_SOURCE_RENDER_BITMAPPIXELS_H - -#include "Render/SpritePixels.h" - -#include -#include - -class CSurface; -class SpriteAtlas; -class CRenderSystemBase; -class CTexture; - -// Reconstructed contiguous CDCBitmap subobject at +4..+28 on x86. Texture -// cache invalidation belongs to the enclosing CDCBitmap, not this DIB owner. -struct BitmapPixels { - /* 0000 */ std::uint32_t width; - /* 0004 */ std::uint32_t height; - /* 0008 */ HDC dc; - /* 000C */ HBITMAP bitmap; - /* 0010 */ HGDIOBJ previous; - /* 0014 */ std::uint32_t* pixels; - /* 0018 */ bool dirty; - - BitmapPixels(int width, int height); - ~BitmapPixels(); - void Grow(std::uint32_t width, std::uint32_t height); - bool GetDC(HDC* output); - void ReleaseDC(HDC dc); - void Fill(const RECT* rectangle, std::uint32_t color); - void Copy(int x, int y, int width, int height, const std::uint32_t* source, bool transparent); - void CopyFrom(int x, int y, int sourceX, int sourceY, int width, int height, const BitmapPixels& source); - void BlendFrom(std::uint32_t x, std::uint32_t y, int width, int height, const BitmapPixels& source, bool alpha); - void Brighten(int x, int y, int width, int height, int amount); - void Dim(int x, int y, int width, int height, int percent); - void CopyRegion( - int x, - int y, - int sourceLeft, - int sourceTop, - int sourceRight, - int sourceBottom, - const std::uint32_t* source, - int sourceWidth, - int sourceHeight, - bool transparent, - bool alpha - ); - void DrawSurface( - int x, - int y, - CSurface* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - bool mirrored, - int scaleX, - int scaleY, - int filter, - int format - ); - void DrawScaledSurface( - int x, - int y, - int width, - int height, - CSurface* source, - int sourceWidth, - int sourceHeight, - float scaleX, - float scaleY, - std::uint32_t color, - bool mirrored, - int offsetX, - int offsetY, - int sourceX, - int sourceY, - int format - ); - void DrawRleSprite( - int x, - int y, - std::span cells, - const SpriteRleImage* const* const* images, - const std::uint32_t* palette, - int cellCount - ); - void DrawScaledSprite( - int x, - int y, - int width, - int height, - std::span cells, - const SpriteRleImage* const* const* images, - int cellCount, - int offsetX, - int offsetY, - float scale, - const std::uint32_t* palette, - SpriteAtlas& atlas, - CRenderSystemBase& system, - int serviceType, - std::uint32_t reuseDelay - ); - void ScaleCopy( - int x, - int y, - int sourceWidth, - int sourceHeight, - int width, - int height, - const std::uint32_t* source, - int option - ); - void UploadTexture(CRenderSystemBase& system, CTexture*& texture); - -private: - void Create(int width, int height); -}; - -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(BitmapPixels) == 28); -#endif - -#endif diff --git a/Source/Render/BlendColor.cpp b/Source/Render/BlendColor.cpp index 799c89f..631a559 100644 --- a/Source/Render/BlendColor.cpp +++ b/Source/Render/BlendColor.cpp @@ -9,5 +9,6 @@ std::uint32_t BlendColor(std::uint32_t base, std::uint32_t overlay) { const unsigned red = static_cast(channel(base, 16) * inverse + channel(overlay, 16) * alpha); const unsigned green = static_cast(channel(overlay, 8) * alpha + channel(base, 8) * inverse); const unsigned blue = static_cast(channel(base, 0) * inverse + channel(overlay, 0) * alpha); + return (base & 0xFF000000u) | ((red & 255u) << 16) | ((green & 255u) << 8) | (blue & 255u); } diff --git a/Source/Render/ClientTextureSources.h b/Source/Render/ClientTextureSources.h deleted file mode 100644 index 794e64c..0000000 --- a/Source/Render/ClientTextureSources.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef RAGNAROK_SOURCE_RENDER_CLIENTTEXTURESOURCES_H -#define RAGNAROK_SOURCE_RENDER_CLIENTTEXTURESOURCES_H - -#include "Render/TextureCache.h" - -#include - -struct TextureNames; -class BinkMovies; - -// Concrete source wiring for original CGameMode/player-manager movie state -// and recovered name resolution. Movie owner is borrowed only in mode 1. -class ClientTextureSources : public TextureSources { -public: - ClientTextureSources( - TextureNames& names, - const int& modeType, - BinkMovies* const& movies, - CRenderSystemBase*& system, - IDirectDraw7* const& directDraw - ); - const char* Resolve(const char* name) override; - bool MovieSize(const char* name, int& width, int& height) override; - void CleanupTextures() override; - -private: - TextureNames& m_names; - const int& m_modeType; - BinkMovies* const& m_movies; - CRenderSystemBase*& m_system; - IDirectDraw7* const& m_directDraw; -}; - -#endif diff --git a/Source/Render/D3DX9Runtime.cpp b/Source/Render/D3DX9Runtime.cpp deleted file mode 100644 index 8fa06dc..0000000 --- a/Source/Render/D3DX9Runtime.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "Render/D3DX9Runtime.h" - -#include - -D3DX9Runtime::D3DX9Runtime() : m_module(LoadLibraryA("D3DX9_43.dll")) { - if (!this->m_module) { - throw std::system_error(GetLastError(), std::system_category(), "D3DX9_43.dll"); - } - this->filterTexture = - reinterpret_castfilterTexture)>(GetProcAddress(this->m_module, "D3DXFilterTexture")); - this->loadSurfaceFromMemory = reinterpret_castloadSurfaceFromMemory)>( - GetProcAddress(this->m_module, "D3DXLoadSurfaceFromMemory") - ); - this->loadSurfaceFromSurface = reinterpret_castloadSurfaceFromSurface)>( - GetProcAddress(this->m_module, "D3DXLoadSurfaceFromSurface") - ); - this->perspectiveFovLH = - reinterpret_castperspectiveFovLH)>(GetProcAddress(this->m_module, "D3DXMatrixPerspectiveFovLH")); - this->saveSurfaceToFileA = - reinterpret_castsaveSurfaceToFileA)>(GetProcAddress(this->m_module, "D3DXSaveSurfaceToFileA")); - if ( - !this->filterTexture || !this->loadSurfaceFromMemory || !this->loadSurfaceFromSurface || !this->perspectiveFovLH || - !this->saveSurfaceToFileA - ) { - FreeLibrary(this->m_module); - throw std::system_error(ERROR_PROC_NOT_FOUND, std::system_category(), "D3DX9_43 exports"); - } -} - -D3DX9Runtime::~D3DX9Runtime() { - FreeLibrary(this->m_module); -} diff --git a/Source/Render/DCBitmap.h b/Source/Render/DCBitmap.h deleted file mode 100644 index 9edb38a..0000000 --- a/Source/Render/DCBitmap.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef RAGNAROK_SOURCE_RENDER_DCBITMAP_H -#define RAGNAROK_SOURCE_RENDER_DCBITMAP_H - -#include "Render/BitmapPixels.h" -#include "Render/BitmapTextureCache.h" -#include "Render/DeviceContext.h" - -class CDCBitmap : public CDC { -public: - CDCBitmap(int width, int height); - ~CDCBitmap() override; - void Grow(std::uint32_t width, std::uint32_t height) override; - bool GetDC(HDC* output) override; - void ReleaseDC(HDC dc) override; - void Copy(int x, int y, int width, int height, const std::uint32_t* source, bool transparent) override; - void ScaleCopy( - int x, - int y, - int sourceWidth, - int sourceHeight, - int width, - int height, - const std::uint32_t* source, - int option - ) override; - void CopyRegion( - int x, - int y, - int sourceLeft, - int sourceTop, - int sourceRight, - int sourceBottom, - const std::uint32_t* source, - int sourceWidth, - int sourceHeight, - bool transparent, - bool alpha - ) override; - void CopyFrom(int x, int y, int sourceX, int sourceY, int width, int height, const CDCBitmap& source) override; - void BlendFrom(std::uint32_t x, std::uint32_t y, int width, int height, const CDCBitmap& source) override; - void DrawRleSprite( - int x, - int y, - std::span cells, - const SpriteRleImage* const* const* images, - const std::uint32_t* palette, - int cellCount - ) override; - void DrawSurface( - int x, - int y, - CSurface* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - bool mirrored, - int scaleX, - int scaleY, - int filter, - int format - ) override; - void Fill(const RECT* rectangle, std::uint32_t color) override; - void Draw(CRenderSystemBase& system, int x, int y, int width, int height, std::uint32_t color) override; - void DrawScaledSprite( - int x, - int y, - int width, - int height, - std::span cells, - const SpriteRleImage* const* const* images, - int cellCount, - int offsetX, - int offsetY, - float scale, - const std::uint32_t* palette, - SpriteAtlas& atlas, - CRenderSystemBase& system, - int serviceType, - std::uint32_t reuseDelay - ) override; - void DrawScaledSurface( - int x, - int y, - int width, - int height, - CSurface* source, - int sourceWidth, - int sourceHeight, - float scaleX, - float scaleY, - std::uint32_t color, - bool mirrored, - int offsetX, - int offsetY, - int sourceX, - int sourceY, - int format - ) override; - void Brighten(int x, int y, int width, int height, int amount) override; - void Dim(int x, int y, int width, int height, int percent) override; - void UploadTexture(CRenderSystemBase& system, CTexture*& texture); - void SetAlpha(bool alpha) { - this->m_cache.m_alpha = alpha; - } - -protected: - /* 0004 */ BitmapPixels m_bitmap; - /* 0020 */ BitmapTextureCache m_cache; -}; - -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(CDCBitmap) == 44); -#endif - -CDCBitmap* CreateBitmapDC(int width, int height, bool fill); - -#endif diff --git a/Source/Render/BackBufferDX7.cpp b/Source/Render/DX7/BackBufferDX7.cpp similarity index 97% rename from Source/Render/BackBufferDX7.cpp rename to Source/Render/DX7/BackBufferDX7.cpp index 6580d17..cb044ce 100644 --- a/Source/Render/BackBufferDX7.cpp +++ b/Source/Render/DX7/BackBufferDX7.cpp @@ -1,4 +1,4 @@ -#include "Render/DeviceOwnerDX7.h" +#include "Render/DX7/DeviceOwnerDX7.h" #include "Render/RendererBackBuffer.h" // OFFSET: 0x0055A080 @@ -34,6 +34,7 @@ bool RendererBackBuffer::Lock(const DeviceOwnerDX7& owner) { this->pixels = description.lpSurface; this->bitsPerPixel = description.ddpfPixelFormat.dwRGBBitCount; this->pitch = description.lPitch; + return true; } diff --git a/Source/Render/DeviceCapabilitiesDX7.cpp b/Source/Render/DX7/DeviceCapabilitiesDX7.cpp similarity index 62% rename from Source/Render/DeviceCapabilitiesDX7.cpp rename to Source/Render/DX7/DeviceCapabilitiesDX7.cpp index 6e57069..1876869 100644 --- a/Source/Render/DeviceCapabilitiesDX7.cpp +++ b/Source/Render/DX7/DeviceCapabilitiesDX7.cpp @@ -1,34 +1,30 @@ -#include "Client/ErrorDialog.h" -#include "Render/DeviceOwnerDX7.h" -#include "Render/TextureAllocationDX7.h" +#include "Client/Application/ErrorDialog.h" +#include "Render/DX7/DeviceOwnerDX7.h" +#include "Render/DX7/TextureAllocationDX7.h" +#include "Render/Textures/Texture.h" // OFFSET: 0x0054A380 // FUNCTION: fn_01896 -int DeviceOwnerDX7::RefreshRendererCapabilities( - int mipmaps, - TextureAllocationDX7& allocation, - bool& multitexture, - CRenderSystemBase* renderSystem -) { +int DeviceOwnerDX7::RefreshRendererCapabilities(int mipmaps, TextureAllocationDX7& allocation, bool& multitexture, CRenderSystemBase* renderSystem) { int format; switch (this->redMask) { case 0xF800: - format = 2; + format = TextureFormat::R5G6B5; break; case 0x7C00: - format = 3; + format = TextureFormat::X1R5G5B5; break; case 0x1F: ShowErrorDialog(renderSystem, "BGR 565 MODE. NOT SUPPORTED", 0); - format = 2; + format = TextureFormat::R5G6B5; break; default: if (this->bitDepth == 32) { - format = 4; + format = TextureFormat::A8R8G8B8; } else { ShowErrorDialog(renderSystem, "NOT SUPPORTED MODE", 0); - format = -1; + format = TextureFormat::UnknownTextureFormat; } break; } @@ -46,8 +42,7 @@ int DeviceOwnerDX7::RefreshRendererCapabilities( this->maxTextureWidth = this->caps.dwMaxTextureWidth; this->maxTextureHeight = this->caps.dwMaxTextureHeight; this->maxTextureAspectRatio = this->caps.dwMaxTextureAspectRatio; - multitexture = this->caps.wMaxSimultaneousTextures >= 2 && - (this->caps.dwTextureOpCaps & D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR) != 0; + multitexture = this->caps.wMaxSimultaneousTextures >= 2 && (this->caps.dwTextureOpCaps & D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR) != 0; allocation.Update(mipmaps, this->caps); } diff --git a/Source/Render/DeviceOwnerDX7.cpp b/Source/Render/DX7/DeviceOwnerDX7.cpp similarity index 74% rename from Source/Render/DeviceOwnerDX7.cpp rename to Source/Render/DX7/DeviceOwnerDX7.cpp index 23e6246..cce712c 100644 --- a/Source/Render/DeviceOwnerDX7.cpp +++ b/Source/Render/DX7/DeviceOwnerDX7.cpp @@ -1,4 +1,4 @@ -#include "Render/DeviceOwnerDX7.h" +#include "Render/DX7/DeviceOwnerDX7.h" #include @@ -15,6 +15,7 @@ namespace { result.dwFlags = flags; result.ddsCaps.dwCaps = caps; result.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + return result; } @@ -31,6 +32,7 @@ namespace { ClientToScreen(window, &point); result.right = point.x - monitor.left; result.bottom = point.y - monitor.top; + return result; } @@ -77,10 +79,9 @@ namespace { // OFFSET: 0x005493B0 // FUNCTION: fn_01888 DeviceOwnerDX7::DeviceOwnerDX7() - : window(nullptr), width(0), height(0), primary(nullptr), backBuffer(nullptr), renderTarget(nullptr), - depthBuffer(nullptr), draw(nullptr), direct3D(nullptr), device(nullptr), depthMemory(0), fullscreen(0), - presentationOption(0), captureSurface(nullptr), red{0, 8}, green{0, 8}, blue{0, 8}, alpha{0, 8}, bitDepth(0), - redMask(0), greenMask(0), blueMask(0), alphaMask(0), surfacesLost(false) { + : window(nullptr), width(0), height(0), primary(nullptr), backBuffer(nullptr), renderTarget(nullptr), depthBuffer(nullptr), draw(nullptr), + direct3D(nullptr), device(nullptr), depthMemory(0), fullscreen(0), presentationOption(0), captureSurface(nullptr), red{0, 8}, green{0, 8}, blue{0, 8}, + alpha{0, 8}, bitDepth(0), redMask(0), greenMask(0), blueMask(0), alphaMask(0), surfacesLost(false) { } // OFFSET: 0x005498A0 @@ -95,22 +96,17 @@ HRESULT DeviceOwnerDX7::CreateSurfaces(const DDSURFACEDESC2* mode, DWORD flags, this->width = this->source.right; this->height = this->source.bottom; this->destination = this->source; - const DWORD modeFlags = - this->width == 320 && this->height == 200 && mode->ddpfPixelFormat.dwRGBBitCount == 8 ? DDSDM_STANDARDVGAMODE : 0; + const DWORD modeFlags = this->width == 320 && this->height == 200 && mode->ddpfPixelFormat.dwRGBBitCount == 8 ? DDSDM_STANDARDVGAMODE : 0; - if ( - FAILED(this->draw->SetDisplayMode( - this->width, this->height, mode->ddpfPixelFormat.dwRGBBitCount, mode->dwRefreshRate, modeFlags - )) - ) { + if (FAILED(this->draw->SetDisplayMode(this->width, this->height, mode->ddpfPixelFormat.dwRGBBitCount, mode->dwRefreshRate, modeFlags))) { return DeviceError(9); } - description.ddsCaps.dwCaps = 0x2200; + description.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; if (buffered) { description.dwFlags |= DDSD_BACKBUFFERCOUNT; - description.ddsCaps.dwCaps = 0x2218; + description.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; description.dwBackBufferCount = 1; } @@ -133,7 +129,7 @@ HRESULT DeviceOwnerDX7::CreateSurfaces(const DDSURFACEDESC2* mode, DWORD flags, this->width = this->source.right; this->height = this->source.bottom; this->destination = ClientRectangle(this->window, monitor); - description.ddsCaps.dwCaps = buffered ? 0x200 : 0x2200; + description.ddsCaps.dwCaps = buffered ? DDSCAPS_PRIMARYSURFACE : DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; status = this->draw->CreateSurface(&description, &this->primary, nullptr); if (FAILED(status)) { @@ -159,15 +155,21 @@ HRESULT DeviceOwnerDX7::CreateSurfaces(const DDSURFACEDESC2* mode, DWORD flags, description.dwWidth = this->width; description.dwHeight = this->height; description.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - description.ddsCaps.dwCaps = 0x2040; + description.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; status = this->draw->CreateSurface(&description, &this->backBuffer, nullptr); if (FAILED(status)) { return SurfaceError(status, 10); } } else { - ClientToScreen(this->window, reinterpret_cast(&this->source.left)); - ClientToScreen(this->window, reinterpret_cast(&this->source.right)); + POINT topLeft{this->source.left, this->source.top}; + ClientToScreen(this->window, &topLeft); + this->source.left = topLeft.x; + this->source.top = topLeft.y; + POINT bottomRight{this->source.right, this->source.bottom}; + ClientToScreen(this->window, &bottomRight); + this->source.right = bottomRight.x; + this->source.bottom = bottomRight.y; } } @@ -185,27 +187,22 @@ HRESULT DeviceOwnerDX7::CreateSurfaces(const DDSURFACEDESC2* mode, DWORD flags, ChannelMask(this->alpha, this->alphaMask); this->renderTarget = buffered ? this->backBuffer : this->primary; this->renderTarget->AddRef(); - description = SurfaceDescription(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, 0x840); + description = SurfaceDescription(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY); description.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; description.dwWidth = this->width; description.dwHeight = this->height; status = this->draw->CreateSurface(&description, &this->captureSurface, nullptr); + return FAILED(status) ? E_OUTOFMEMORY : S_OK; } // OFFSET: 0x0054A000 // FUNCTION: fn_01895 -HRESULT DeviceOwnerDX7::CreateDevice( - GUID* drawIdentity, - const GUID* renderIdentity, - const DDSURFACEDESC2* mode, - DWORD flags, - const RECT& monitor -) { - this->depthMemory = std::memcmp(renderIdentity, &IID_IDirect3DHALDevice, sizeof(GUID)) == 0 || - std::memcmp(renderIdentity, &IID_IDirect3DTnLHalDevice, sizeof(GUID)) == 0 - ? DDSCAPS_VIDEOMEMORY - : DDSCAPS_SYSTEMMEMORY; +HRESULT DeviceOwnerDX7::CreateDevice(GUID* drawIdentity, const GUID* renderIdentity, const DDSURFACEDESC2* mode, DWORD flags, const RECT& monitor) { + this->depthMemory = + std::memcmp(renderIdentity, &IID_IDirect3DHALDevice, sizeof(GUID)) == 0 || std::memcmp(renderIdentity, &IID_IDirect3DTnLHalDevice, sizeof(GUID)) == 0 + ? DDSCAPS_VIDEOMEMORY + : DDSCAPS_SYSTEMMEMORY; if (FAILED(DirectDrawCreateEx(drawIdentity, reinterpret_cast(&this->draw), IID_IDirectDraw7, nullptr))) { return DeviceError(1); @@ -214,13 +211,13 @@ HRESULT DeviceOwnerDX7::CreateDevice( auto description = SurfaceDescription(0, 0); this->draw->GetDisplayMode(&description); this->desktopBitDepth = description.ddpfPixelFormat.dwRGBBitCount; - DWORD cooperative = this->fullscreen ? 19 : 8; + DWORD cooperative = this->fullscreen ? DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE : DDSCL_NORMAL; if (!(flags & 16)) { - cooperative |= 0x800; + cooperative |= DDSCL_FPUSETUP; } - if (FAILED(this->draw->SetCooperativeLevel(this->window, cooperative | 0x400))) { + if (FAILED(this->draw->SetCooperativeLevel(this->window, cooperative | DDSCL_MULTITHREADED))) { return DeviceError(2); } @@ -246,20 +243,17 @@ HRESULT DeviceOwnerDX7::CreateDevice( } this->depthFormat = {}; - this->depthFormat.dwFlags = ((flags & 8) << 11) | DDPF_ZBUFFER; + this->depthFormat.dwFlags = DDPF_ZBUFFER | ((flags & 8) ? DDPF_STENCILBUFFER : 0); this->direct3D->EnumZBufferFormats(*renderIdentity, SelectDepthFormat, &this->depthFormat); - // The original tests the descriptor size, not its depth-bit count. - if (this->depthFormat.dwSize != 32) { + if (this->depthFormat.dwSize != sizeof(this->depthFormat)) { return DeviceError(5); } this->device->GetCaps(&this->caps); if (!(this->caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR)) { - description = SurfaceDescription( - DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, this->depthMemory | DDSCAPS_ZBUFFER - ); + description = SurfaceDescription(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, this->depthMemory | DDSCAPS_ZBUFFER); description.dwWidth = this->width; description.dwHeight = this->height; description.ddpfPixelFormat = this->depthFormat; @@ -269,10 +263,7 @@ HRESULT DeviceOwnerDX7::CreateDevice( return SurfaceError(depthStatus, 5); } - if ( - FAILED(this->renderTarget->AddAttachedSurface(this->depthBuffer)) || - FAILED(this->device->SetRenderTarget(this->renderTarget, 0)) - ) { + if (FAILED(this->renderTarget->AddAttachedSurface(this->depthBuffer)) || FAILED(this->device->SetRenderTarget(this->renderTarget, 0))) { return DeviceError(5); } } @@ -342,13 +333,7 @@ HRESULT DeviceOwnerDX7::Close() { // OFFSET: 0x0054AAD0 // FUNCTION: fn_01901 HRESULT DeviceOwnerDX7::Initialize( - HWND value, - GUID* drawIdentity, - const GUID* renderIdentity, - const DDSURFACEDESC2* mode, - DWORD flags, - HWND applicationWindow, - const RECT& monitor + HWND value, GUID* drawIdentity, const GUID* renderIdentity, const DDSURFACEDESC2* mode, DWORD flags, HWND applicationWindow, const RECT& monitor ) { this->window = value; @@ -378,10 +363,16 @@ HRESULT DeviceOwnerDX7::Initialize( D3DRENDERSTATETYPE state; DWORD value; } states[] = { - {D3DRENDERSTATE_CULLMODE, 1}, {D3DRENDERSTATE_ZFUNC, 4}, {D3DRENDERSTATE_TEXTUREPERSPECTIVE, 1}, - {D3DRENDERSTATE_ALPHAFUNC, 7}, {D3DRENDERSTATE_ALPHAREF, 240}, {D3DRENDERSTATE_COLORKEYENABLE, 1}, - {D3DRENDERSTATE_ZENABLE, 1}, {D3DRENDERSTATE_ZWRITEENABLE, 1}, {D3DRENDERSTATE_SRCBLEND, 5}, - {D3DRENDERSTATE_DESTBLEND, 6} + {D3DRENDERSTATE_CULLMODE, D3DCULL_NONE}, + {D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL}, + {D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE}, + {D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATEREQUAL}, + {D3DRENDERSTATE_ALPHAREF, 240}, + {D3DRENDERSTATE_COLORKEYENABLE, TRUE}, + {D3DRENDERSTATE_ZENABLE, D3DZB_TRUE}, + {D3DRENDERSTATE_ZWRITEENABLE, TRUE}, + {D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA}, + {D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA} }; for (const auto& state : states) { @@ -392,13 +383,17 @@ HRESULT DeviceOwnerDX7::Initialize( DWORD stage; D3DTEXTURESTAGESTATETYPE state; DWORD value; - } stages[] = {{0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLOROP, 4}, {0, D3DTSS_COLORARG1, 2}, - {0, D3DTSS_COLORARG2, 0}, {0, D3DTSS_ALPHAOP, 4}, {0, D3DTSS_ALPHAARG1, 2}, - {0, D3DTSS_ALPHAARG2, 0}, {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, 2}, - {1, D3DTSS_COLOROP, 18}, {1, D3DTSS_COLORARG2, 1}, {1, D3DTSS_ALPHAOP, 1}, - {2, D3DTSS_COLOROP, 1}, {2, D3DTSS_ALPHAOP, 1}, {0, D3DTSS_MAGFILTER, 2}, - {0, D3DTSS_MINFILTER, 2}, {1, D3DTSS_MAGFILTER, 2}, {1, D3DTSS_MINFILTER, 2}, - {0, D3DTSS_ADDRESS, 3}, {1, D3DTSS_ADDRESS, 4}, {1, D3DTSS_BORDERCOLOR, 0xFF000000}}; + } stages[] = {{0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, + {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAOP, D3DTOP_MODULATE}, {0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, + {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, {1, D3DTSS_TEXCOORDINDEX, 1}, + {1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {1, D3DTSS_COLOROP, D3DTOP_MODULATEALPHA_ADDCOLOR}, + {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAOP, D3DTOP_DISABLE}, + {2, D3DTSS_COLOROP, D3DTOP_DISABLE}, {2, D3DTSS_ALPHAOP, D3DTOP_DISABLE}, + {0, D3DTSS_MAGFILTER, D3DTFG_LINEAR}, {0, D3DTSS_MINFILTER, D3DTFN_LINEAR}, + {1, D3DTSS_MAGFILTER, D3DTFG_LINEAR}, {1, D3DTSS_MINFILTER, D3DTFN_LINEAR}, + {0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP}, {1, D3DTSS_ADDRESS, D3DTADDRESS_BORDER}, + {1, D3DTSS_BORDERCOLOR, 0xFF000000}}; for (const auto& state : stages) { this->device->SetTextureStageState(state.stage, state.state, state.value); @@ -468,8 +463,14 @@ HRESULT DeviceOwnerDX7::Present(bool wait, const RECT& monitor) { } GetClientRect(this->window, &this->destination); - ClientToScreen(this->window, reinterpret_cast(&this->destination.left)); - ClientToScreen(this->window, reinterpret_cast(&this->destination.right)); + POINT topLeft{this->destination.left, this->destination.top}; + ClientToScreen(this->window, &topLeft); + this->destination.left = topLeft.x; + this->destination.top = topLeft.y; + POINT bottomRight{this->destination.right, this->destination.bottom}; + ClientToScreen(this->window, &bottomRight); + this->destination.right = bottomRight.x; + this->destination.bottom = bottomRight.y; if (wait) { this->draw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, nullptr); @@ -529,8 +530,7 @@ void DeviceOwnerDX7::AdjustTextureDimensions(std::uint32_t& width, std::uint32_t // OFFSET: 0x0054AE50 // FUNCTION: fn_01902 bool DeviceOwnerDX7::SupportsTextureDimensions(std::uint32_t width, std::uint32_t height) const { - return this->minTextureWidth <= width && width <= this->maxTextureWidth && this->minTextureHeight <= height && - height <= this->maxTextureHeight; + return this->minTextureWidth <= width && width <= this->maxTextureWidth && this->minTextureHeight <= height && height <= this->maxTextureHeight; } // OFFSET: 0x0056B890 diff --git a/Source/Render/DeviceOwnerDX7.h b/Source/Render/DX7/DeviceOwnerDX7.h similarity index 74% rename from Source/Render/DeviceOwnerDX7.h rename to Source/Render/DX7/DeviceOwnerDX7.h index 3ae535f..7fef772 100644 --- a/Source/Render/DeviceOwnerDX7.h +++ b/Source/Render/DX7/DeviceOwnerDX7.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_DEVICEOWNERDX7_H -#define RAGNAROK_SOURCE_RENDER_DEVICEOWNERDX7_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_DEVICEOWNERDX7_H +#define RAGNAROK_SOURCE_RENDER_DX7_DEVICEOWNERDX7_H #include #include @@ -17,27 +17,12 @@ struct TextureDX7Context; struct TextureAllocationDX7; class CRenderSystemBase; -// Original nonpolymorphic device owner, 588 bytes on x86. Unwritten fields remain -// unwritten until their corresponding creation/capability operation publishes them. class DeviceOwnerDX7 { public: DeviceOwnerDX7(); - HRESULT Initialize( - HWND window, - GUID* drawIdentity, - const GUID* renderIdentity, - const DDSURFACEDESC2* mode, - DWORD flags, - HWND applicationWindow, - const RECT& monitor - ); - HRESULT CreateDevice( - GUID* drawIdentity, - const GUID* renderIdentity, - const DDSURFACEDESC2* mode, - DWORD flags, - const RECT& monitor - ); + HRESULT + Initialize(HWND window, GUID* drawIdentity, const GUID* renderIdentity, const DDSURFACEDESC2* mode, DWORD flags, HWND applicationWindow, const RECT& monitor); + HRESULT CreateDevice(GUID* drawIdentity, const GUID* renderIdentity, const DDSURFACEDESC2* mode, DWORD flags, const RECT& monitor); HRESULT CreateSurfaces(const DDSURFACEDESC2* mode, DWORD flags, const RECT& monitor); HRESULT Close(); HRESULT Clear(DWORD color); @@ -54,14 +39,8 @@ public: HRESULT RestoreAllSurfaces(); void SetDialogClipper(int enabled); bool CalibrateTextureCoordinates(TextureDX7Context& context); - // Recovered capability-publication portion of the renderer factory. Host - // helper has no OFFSET: the full factory also constructs/calibrates a renderer. - int RefreshRendererCapabilities( - int mipmaps, - TextureAllocationDX7& allocation, - bool& multitexture, - CRenderSystemBase* renderSystem - ); + + int RefreshRendererCapabilities(int mipmaps, TextureAllocationDX7& allocation, bool& multitexture, CRenderSystemBase* renderSystem); std::uint16_t PackColor(int red, int green, int blue); DWORD BlueMask(); DWORD BlueExpansion(); diff --git a/Source/Render/DirectDrawEnumeration.cpp b/Source/Render/DX7/DirectDrawEnumeration.cpp similarity index 88% rename from Source/Render/DirectDrawEnumeration.cpp rename to Source/Render/DX7/DirectDrawEnumeration.cpp index 9b65073..765e204 100644 --- a/Source/Render/DirectDrawEnumeration.cpp +++ b/Source/Render/DX7/DirectDrawEnumeration.cpp @@ -1,4 +1,4 @@ -#include "Render/DirectDrawEnumeration.h" +#include "Render/DX7/DirectDrawEnumeration.h" #include #include @@ -9,8 +9,7 @@ struct DirectDrawEnumeration::AdapterContext { DirectDrawDeviceRecord record{}; }; -DirectDrawEnumeration::DirectDrawEnumeration(const GUID& selectedDraw, RECT& monitor) - : m_selectedDraw(selectedDraw), m_monitor(monitor) { +DirectDrawEnumeration::DirectDrawEnumeration(const GUID& selectedDraw, RECT& monitor) : m_selectedDraw(selectedDraw), m_monitor(monitor) { } // OFFSET: 0x007E9C00 @@ -61,9 +60,7 @@ int __cdecl DirectDrawEnumeration::CompareModes(const void* left, const void* ri HRESULT CALLBACK DirectDrawEnumeration::Mode(DDSURFACEDESC2* mode, void* context) { auto& record = static_cast(context)->record; const unsigned count = record.modeCount + 1; - const std::size_t size = count > std::numeric_limits::max() / sizeof(*mode) - ? std::numeric_limits::max() - : count * sizeof(*mode); + const std::size_t size = count > std::numeric_limits::max() / sizeof(*mode) ? std::numeric_limits::max() : count * sizeof(*mode); auto* replacement = static_cast(std::malloc(size)); if (record.modeCount) { @@ -74,6 +71,7 @@ HRESULT CALLBACK DirectDrawEnumeration::Mode(DDSURFACEDESC2* mode, void* context record.modes = replacement; record.modes[record.modeCount] = *mode; ++record.modeCount; + return DDENUMRET_OK; } @@ -86,7 +84,7 @@ HRESULT CALLBACK DirectDrawEnumeration::Device(char*, char* name, D3DDEVICEDESC7 ++owner.devicesSeen; auto& record = owner.devices[owner.deviceCount]; std::memset(&record, 0, sizeof(record)); - record.hardware = device->dwDevCaps & 0x80000; + record.hardware = device->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION; record.device = *device; record.primaryAdapter = source.primaryAdapter; record.driverCaps = source.driverCaps; @@ -103,10 +101,7 @@ HRESULT CALLBACK DirectDrawEnumeration::Device(char*, char* name, D3DDEVICEDESC7 lstrcpynA(record.description, name, 39); } - if ( - (record.drawGuid && !record.hardware) || - (owner.m_filter && FAILED(owner.m_filter(&record.driverCaps, &record.device))) - ) { + if ((record.drawGuid && !record.hardware) || (owner.m_filter && FAILED(owner.m_filter(&record.driverCaps, &record.device)))) { std::free(record.modes); return D3DENUMRET_OK; } @@ -115,8 +110,7 @@ HRESULT CALLBACK DirectDrawEnumeration::Device(char*, char* name, D3DDEVICEDESC7 const auto& mode = source.modes[index]; const DWORD bits = mode.ddpfPixelFormat.dwRGBBitCount; const DWORD supported = record.device.dwDeviceRenderBitDepth; - const bool accepted = - (bits == 32 && (supported & 0x100)) || (bits == 24 && (supported & 0x200)) || (bits == 16 && (supported & 0x400)); + const bool accepted = (bits == 32 && (supported & DDBD_32)) || (bits == 24 && (supported & DDBD_24)) || (bits == 16 && (supported & DDBD_16)); if (accepted) { record.modes[record.modeCount++] = mode; @@ -183,7 +177,7 @@ BOOL WINAPI DirectDrawEnumeration::Adapter(GUID* guid, char* description, char*, record.drawGuid = &record.drawIdentity; } - if ((record.driverCaps.dwCaps2 & 0x80000) && !record.drawGuid) { + if ((record.driverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED) && !record.drawGuid) { record.primaryAdapter = 1; } @@ -193,5 +187,6 @@ BOOL WINAPI DirectDrawEnumeration::Adapter(GUID* guid, char* description, char*, std::free(record.modes); render->Release(); draw->Release(); + return TRUE; } diff --git a/Source/Render/DirectDrawEnumeration.h b/Source/Render/DX7/DirectDrawEnumeration.h similarity index 85% rename from Source/Render/DirectDrawEnumeration.h rename to Source/Render/DX7/DirectDrawEnumeration.h index 593c74b..4d9f6a8 100644 --- a/Source/Render/DirectDrawEnumeration.h +++ b/Source/Render/DX7/DirectDrawEnumeration.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_DIRECTDRAWENUMERATION_H -#define RAGNAROK_SOURCE_RENDER_DIRECTDRAWENUMERATION_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_DIRECTDRAWENUMERATION_H +#define RAGNAROK_SOURCE_RENDER_DX7_DIRECTDRAWENUMERATION_H #include #include @@ -26,8 +26,6 @@ struct DirectDrawDeviceRecord { DWORD hasStereoMode; }; -// Original shared device table and counters. ClearModes releases mode buffers -// without resetting discovery counts or retained descriptor metadata. class DirectDrawEnumeration { public: using Filter = HRESULT(__cdecl*)(const DDCAPS*, const D3DDEVICEDESC7*); diff --git a/Source/Render/DisplayModeDX7.cpp b/Source/Render/DX7/DisplayModeDX7.cpp similarity index 89% rename from Source/Render/DisplayModeDX7.cpp rename to Source/Render/DX7/DisplayModeDX7.cpp index 8561e57..5463af5 100644 --- a/Source/Render/DisplayModeDX7.cpp +++ b/Source/Render/DX7/DisplayModeDX7.cpp @@ -1,4 +1,4 @@ -#include "Render/DirectDrawEnumeration.h" +#include "Render/DX7/DirectDrawEnumeration.h" #include "Render/DisplayMode.h" #include @@ -35,8 +35,7 @@ std::vector EnumerateDisplayModesDX7(DirectDrawEnumeration& enumera DWORDLONG mask = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); mask = VerSetConditionMask(mask, VER_MINORVERSION, VER_GREATER_EQUAL); mask = VerSetConditionMask(mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); - const bool modern = - VerifyVersionInfoW(&version, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, mask) != FALSE; + const bool modern = VerifyVersionInfoW(&version, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, mask) != FALSE; if (modern ? bits != 32 : (bits != 16 && bits != 32)) { continue; diff --git a/Source/Render/RenderAdapterDX7.cpp b/Source/Render/DX7/RenderAdapterDX7.cpp similarity index 92% rename from Source/Render/RenderAdapterDX7.cpp rename to Source/Render/DX7/RenderAdapterDX7.cpp index 1f892cd..0bb8c62 100644 --- a/Source/Render/RenderAdapterDX7.cpp +++ b/Source/Render/DX7/RenderAdapterDX7.cpp @@ -1,4 +1,4 @@ -#include "Render/DirectDrawEnumeration.h" +#include "Render/DX7/DirectDrawEnumeration.h" #include "Render/RenderAdapter.h" // OFFSET: 0x0056B8C0 diff --git a/Source/Render/RenderSystemDX7.cpp b/Source/Render/DX7/RenderSystemDX7.cpp similarity index 52% rename from Source/Render/RenderSystemDX7.cpp rename to Source/Render/DX7/RenderSystemDX7.cpp index b968a97..470dd4e 100644 --- a/Source/Render/RenderSystemDX7.cpp +++ b/Source/Render/DX7/RenderSystemDX7.cpp @@ -1,48 +1,30 @@ -#include "Render/RenderSystemDX7.h" -#include "Render/DeviceOwnerDX7.h" -#include "Render/SurfaceDX7.h" -#include "Render/TextureDX7.h" +#include "Render/DX7/RenderSystemDX7.h" +#include "Render/DX7/DeviceOwnerDX7.h" +#include "Render/DX7/SurfaceDX7.h" +#include "Render/DX7/TextureDX7.h" #include // OFFSET: 0x0056B5F0 // FUNCTION: fn_02318 CSurface* CRenderSystemDX7::CreateSurface(std::uint32_t width, std::uint32_t height) { - return new (std::nothrow) - CSurfaceDX7(*this->m_device, static_cast(width), static_cast(height)); + return new (std::nothrow) CSurfaceDX7(*this->m_device, static_cast(width), static_cast(height)); } // OFFSET: 0x0056B680 // FUNCTION: fn_02319 -CTexture* CRenderSystemDX7::CreateTexture( - std::uint32_t width, - std::uint32_t height, - std::int32_t format, - bool /*option1*/, - bool /*option2*/ -) { - return new (std::nothrow) CTextureDX7( - *reinterpret_cast(this->m_device), static_cast(width), static_cast(height), format - ); +CTexture* CRenderSystemDX7::CreateTexture(std::uint32_t width, std::uint32_t height, std::int32_t format, bool, bool) { + return new (std::nothrow) CTextureDX7(*reinterpret_cast(this->m_device), static_cast(width), static_cast(height), format); } // OFFSET: 0x0056B710 // FUNCTION: fn_02320 CSurface* CRenderSystemDX7::CreateSurfaceOrTexture(std::uint32_t width, std::uint32_t height) { if (this->m_device->SupportsTextureDimensions(width, height)) { - return new CTextureDX7( - *reinterpret_cast(this->m_device), - static_cast(width), - static_cast(height), - 0 - ); + return new CTextureDX7(*reinterpret_cast(this->m_device), static_cast(width), static_cast(height), TextureFormat::A1R5G5B5); } - return new CSurfaceWallpaperDX7( - *this->m_device, - static_cast(this->m_device->width), - static_cast(this->m_device->height) - ); + return new CSurfaceWallpaperDX7(*this->m_device, static_cast(this->m_device->width), static_cast(this->m_device->height)); } // OFFSET: 0x0056B7C0 @@ -51,6 +33,7 @@ HRESULT CRenderSystemDX7::Close() { delete this->m_defaultTexture; this->m_defaultTexture = nullptr; this->m_backBuffer.reset(); + return this->m_device->Close(); } @@ -64,8 +47,7 @@ void CRenderSystemDX7::DestroySurface(CSurface* surface) { // FUNCTION: fn_02323 void CRenderSystemDX7::UpdateOption() { if (this->m_device) { - const bool trilinear = - (this->m_device->caps.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR) != 0; + const bool trilinear = (this->m_device->caps.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR) != 0; (void)trilinear; } } diff --git a/Source/Render/RenderSystemDX7.h b/Source/Render/DX7/RenderSystemDX7.h similarity index 83% rename from Source/Render/RenderSystemDX7.h rename to Source/Render/DX7/RenderSystemDX7.h index 8c6f432..cb43256 100644 --- a/Source/Render/RenderSystemDX7.h +++ b/Source/Render/DX7/RenderSystemDX7.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERSYSTEMDX7_H -#define RAGNAROK_SOURCE_RENDER_RENDERSYSTEMDX7_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_RENDERSYSTEMDX7_H +#define RAGNAROK_SOURCE_RENDER_DX7_RENDERSYSTEMDX7_H #include "Render/RenderSystemBase.h" @@ -22,13 +22,7 @@ public: CRenderer* CreateRenderer() override; void DestroySurface(CSurface* surface) override; CSurface* CreateSurface(std::uint32_t width, std::uint32_t height) override; - CTexture* CreateTexture( - std::uint32_t width, - std::uint32_t height, - std::int32_t format, - bool option1, - bool option2 - ) override; + CTexture* CreateTexture(std::uint32_t width, std::uint32_t height, std::int32_t format, bool option1, bool option2) override; CSurface* CreateSurfaceOrTexture(std::uint32_t width, std::uint32_t height) override; CTexture* BackBufferTexture() override; std::shared_ptr BackBufferSurface() override; diff --git a/Source/Render/RenderToTextureDX7.cpp b/Source/Render/DX7/RenderToTextureDX7.cpp similarity index 64% rename from Source/Render/RenderToTextureDX7.cpp rename to Source/Render/DX7/RenderToTextureDX7.cpp index 84cc746..ce749df 100644 --- a/Source/Render/RenderToTextureDX7.cpp +++ b/Source/Render/DX7/RenderToTextureDX7.cpp @@ -1,8 +1,8 @@ -#include "Render/DeviceOwnerDX7.h" -#include "Render/RenderPrimitive.h" -#include "Render/RendererDX7Operations.h" -#include "Render/TextureBindingDX7.h" -#include "Render/TextureDX7.h" +#include "Render/DX7/DeviceOwnerDX7.h" +#include "Render/Primitives/RenderPrimitive.h" +#include "Render/DX7/RendererDX7Operations.h" +#include "Render/DX7/TextureBindingDX7.h" +#include "Render/DX7/TextureDX7.h" #include @@ -11,23 +11,16 @@ using Microsoft::WRL::ComPtr; // OFFSET: 0x00544120 // FUNCTION: fn_01813 bool CTextureDX7::CopySurface(IDirectDrawSurface7* source, const RECT* rectangle) { - return this->m_surface && SUCCEEDED(this->m_surface->Blt( - const_cast(rectangle), source, const_cast(rectangle), DDBLT_WAIT, nullptr - )); + return this->m_surface && SUCCEEDED(this->m_surface->Blt(const_cast(rectangle), source, const_cast(rectangle), DDBLT_WAIT, nullptr)); } // OFFSET: 0x00813CA0 // FUNCTION: fn_10125 bool RendererDX7Operations::RenderToTexture( - int width, - int height, - const std::list& primitives, - CTexture*& texture, - TextureDX7Context& context, - TextureBindingDX7& binding + int width, int height, const std::list& primitives, CTexture*& texture, TextureDX7Context& context, TextureBindingDX7& binding ) { if (!texture) { - texture = new CTextureDX7(context, width, height, 4); + texture = new CTextureDX7(context, width, height, TextureFormat::A8R8G8B8); if (!texture) { return false; @@ -39,7 +32,7 @@ bool RendererDX7Operations::RenderToTexture( description.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; description.dwWidth = width; description.dwHeight = height; - description.ddsCaps.dwCaps = 0x10007000; + description.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM; description.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; description.ddpfPixelFormat.dwRGBBitCount = 32; description.ddpfPixelFormat.dwRBitMask = 0xFF0000; @@ -57,16 +50,13 @@ bool RendererDX7Operations::RenderToTexture( DWORD fog = 0; auto* device = this->owner.device; - if ( - device->GetRenderTarget(previous.GetAddressOf()) != S_OK || - device->GetRenderState(D3DRENDERSTATE_ZENABLE, &depth) != S_OK || - device->GetRenderState(D3DRENDERSTATE_FOGENABLE, &fog) != S_OK - ) { + if (device->GetRenderTarget(previous.GetAddressOf()) != S_OK || device->GetRenderState(D3DRENDERSTATE_ZENABLE, &depth) != S_OK || + device->GetRenderState(D3DRENDERSTATE_FOGENABLE, &fog) != S_OK) { return false; } if (device->SetRenderTarget(target.Get(), 0) == S_OK) { - device->SetRenderState(D3DRENDERSTATE_ZENABLE, 0); + device->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); device->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0); device->Clear(0, nullptr, D3DCLEAR_TARGET, 0, 0, 0); @@ -89,7 +79,5 @@ bool RendererDX7Operations::RenderToTexture( device->SetRenderState(D3DRENDERSTATE_FOGENABLE, fog); } - // Original reports success even when target switching or BeginScene failed. - // It retains texture binding and does not generate output mipmaps here. return true; } diff --git a/Source/Render/RendererDX7Operations.cpp b/Source/Render/DX7/RendererDX7Operations.cpp similarity index 67% rename from Source/Render/RendererDX7Operations.cpp rename to Source/Render/DX7/RendererDX7Operations.cpp index 8f3b733..5235517 100644 --- a/Source/Render/RendererDX7Operations.cpp +++ b/Source/Render/DX7/RendererDX7Operations.cpp @@ -1,8 +1,8 @@ #include "Render/BlendColor.h" -#include "Render/DeviceOwnerDX7.h" -#include "Render/LightmappedPrimitive.h" -#include "Render/RenderPrimitive.h" -#include "Render/RendererDX7Operations.h" +#include "Render/DX7/DeviceOwnerDX7.h" +#include "Render/Primitives/LightmappedPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" +#include "Render/DX7/RendererDX7Operations.h" #include @@ -49,7 +49,7 @@ void RendererDX7Operations::ClearWorld(unsigned color, int mode, unsigned char w // OFFSET: 0x0055ACB0 // FUNCTION: fn_02082 void RendererDX7Operations::DrawPrimitive(RenderCommand* primitive) { - if (std::bit_cast(primitive->vertexCount) <= 0) { + if (primitive->vertexCount <= 0) { return; } @@ -57,10 +57,11 @@ void RendererDX7Operations::DrawPrimitive(RenderCommand* primitive) { if (primitive->indexCount) { this->device->DrawIndexedPrimitive( - type, 452, primitive->vertices, primitive->vertexCount, primitive->indices, primitive->indexCount, 0 + type, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1, primitive->vertices, primitive->vertexCount, primitive->indices, + primitive->indexCount, 0 ); } else { - this->device->DrawPrimitive(type, 452, primitive->vertices, primitive->vertexCount, 0); + this->device->DrawPrimitive(type, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1, primitive->vertices, primitive->vertexCount, 0); } } @@ -69,7 +70,7 @@ void RendererDX7Operations::DrawPrimitive(RenderCommand* primitive) { // OFFSET: 0x0055AD50 // FUNCTION: fn_02084 void RendererDX7Operations::DrawLightmappedPrimitive(LightmappedPrimitive* primitive) { - if (std::bit_cast(primitive->vertexCount) <= 0) { + if (primitive->vertexCount <= 0) { return; } @@ -77,9 +78,10 @@ void RendererDX7Operations::DrawLightmappedPrimitive(LightmappedPrimitive* primi if (primitive->indexCount) { this->device->DrawIndexedPrimitive( - type, 708, primitive->vertices, primitive->vertexCount, primitive->indices, primitive->indexCount, 0 + type, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2, primitive->vertices, primitive->vertexCount, primitive->indices, + primitive->indexCount, 0 ); } else { - this->device->DrawPrimitive(type, 708, primitive->vertices, primitive->vertexCount, 0); + this->device->DrawPrimitive(type, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2, primitive->vertices, primitive->vertexCount, 0); } } diff --git a/Source/Render/RendererDX7Operations.h b/Source/Render/DX7/RendererDX7Operations.h similarity index 56% rename from Source/Render/RendererDX7Operations.h rename to Source/Render/DX7/RendererDX7Operations.h index a1e41f3..b96a1e9 100644 --- a/Source/Render/RendererDX7Operations.h +++ b/Source/Render/DX7/RendererDX7Operations.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERERDX7OPERATIONS_H -#define RAGNAROK_SOURCE_RENDER_RENDERERDX7OPERATIONS_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_RENDERERDX7OPERATIONS_H +#define RAGNAROK_SOURCE_RENDER_DX7_RENDERERDX7OPERATIONS_H #include #include @@ -19,8 +19,6 @@ class IJL15Runtime; class ResourceMgr; struct TextureNames; -// Original renderer snapshots its device pointer separately from the shared -// device owner used by clear/capture/presentation operations. struct RendererDX7Operations { DeviceOwnerDX7& owner; IDirect3DDevice7* device; @@ -32,23 +30,10 @@ struct RendererDX7Operations { void DrawLightmappedPrimitive(LightmappedPrimitive* primitive); void SetTextureMode(int mode); bool RenderToTexture( - int width, - int height, - const std::list& primitives, - CTexture*& texture, - TextureDX7Context& context, - TextureBindingDX7& binding - ); - bool - SaveBitmap(const char* filename, const BitmapImage& overlay, int width, int height, RendererBackBuffer& backBuffer); - bool SaveJpeg( - const char* filename, - const BitmapImage& overlay, - int width, - int height, - RendererBackBuffer& backBuffer, - IJL15Runtime& runtime + int width, int height, const std::list& primitives, CTexture*& texture, TextureDX7Context& context, TextureBindingDX7& binding ); + bool SaveBitmap(const char* filename, const BitmapImage& overlay, int width, int height, RendererBackBuffer& backBuffer); + bool SaveJpeg(const char* filename, const BitmapImage& overlay, int width, int height, RendererBackBuffer& backBuffer, IJL15Runtime& runtime); bool SaveLogo(std::string filename, ResourceMgr& resources, TextureNames& names, IJL15Runtime& runtime); }; diff --git a/Source/Render/RendererFogDX7.cpp b/Source/Render/DX7/RendererFogDX7.cpp similarity index 91% rename from Source/Render/RendererFogDX7.cpp rename to Source/Render/DX7/RendererFogDX7.cpp index c753d57..99183e1 100644 --- a/Source/Render/RendererFogDX7.cpp +++ b/Source/Render/DX7/RendererFogDX7.cpp @@ -1,5 +1,5 @@ -#include "Client/ErrorDialog.h" -#include "Render/RendererFogDX7.h" +#include "Client/Application/ErrorDialog.h" +#include "Render/DX7/RendererFogDX7.h" #include #include @@ -47,6 +47,7 @@ HRESULT PerspectiveMatrixDX7(D3DMATRIX& matrix, float fov, float aspect, float n const float sineY = Sine(half); const float scaleY = static_cast(static_cast(cosineY) / sineY); const float depth = farPlane / difference; + matrix._12 = matrix._13 = matrix._14 = 0; matrix._21 = matrix._23 = matrix._24 = 0; matrix._31 = matrix._32 = 0; @@ -57,17 +58,13 @@ HRESULT PerspectiveMatrixDX7(D3DMATRIX& matrix, float fov, float aspect, float n matrix._11 = scaleX; matrix._22 = scaleY; matrix._43 = translation; + return S_OK; } // OFFSET: 0x0055CF10 // FUNCTION: fn_02094 -void RendererFogDX7::Set( - int value, - IDirect3DDevice7* device, - const D3DDEVICEDESC7& caps, - FogConfiguration& configuration -) { +void RendererFogDX7::Set(int value, IDirect3DDevice7* device, const D3DDEVICEDESC7& caps, FogConfiguration& configuration) { this->supported = (caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0; this->enabled = value; device->SetRenderState(D3DRENDERSTATE_FOGENABLE, value); @@ -79,11 +76,7 @@ void RendererFogDX7::Set( // OFFSET: 0x0055A500 // FUNCTION: fn_02080 void RendererFogDX7::Apply( - IDirect3DDevice7* device, - const D3DDEVICEDESC7& caps, - float aspect, - const FogConfiguration& configuration, - CRenderSystemBase* renderSystem + IDirect3DDevice7* device, const D3DDEVICEDESC7& caps, float aspect, const FogConfiguration& configuration, CRenderSystemBase* renderSystem ) { if (!this->dirty) { return; diff --git a/Source/Render/RendererFogDX7.h b/Source/Render/DX7/RendererFogDX7.h similarity index 60% rename from Source/Render/RendererFogDX7.h rename to Source/Render/DX7/RendererFogDX7.h index 621bb55..d1da41c 100644 --- a/Source/Render/RendererFogDX7.h +++ b/Source/Render/DX7/RendererFogDX7.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERERFOGDX7_H -#define RAGNAROK_SOURCE_RENDER_RENDERERFOGDX7_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_RENDERERFOGDX7_H +#define RAGNAROK_SOURCE_RENDER_DX7_RENDERERFOGDX7_H #include "Render/FogConfiguration.h" @@ -15,13 +15,7 @@ struct RendererFogDX7 { int supported; void Set(int value, IDirect3DDevice7* device, const D3DDEVICEDESC7& caps, FogConfiguration& configuration); - void Apply( - IDirect3DDevice7* device, - const D3DDEVICEDESC7& caps, - float aspect, - const FogConfiguration& configuration, - CRenderSystemBase* renderSystem - ); + void Apply(IDirect3DDevice7* device, const D3DDEVICEDESC7& caps, float aspect, const FogConfiguration& configuration, CRenderSystemBase* renderSystem); }; static_assert(sizeof(RendererFogDX7) == 12); diff --git a/Source/Render/RendererPresentationDX7.cpp b/Source/Render/DX7/RendererPresentationDX7.cpp similarity index 86% rename from Source/Render/RendererPresentationDX7.cpp rename to Source/Render/DX7/RendererPresentationDX7.cpp index b2fdb1c..8518a5f 100644 --- a/Source/Render/RendererPresentationDX7.cpp +++ b/Source/Render/DX7/RendererPresentationDX7.cpp @@ -1,12 +1,12 @@ -#include "Render/DCSurface.h" -#include "Render/DeviceOwnerDX7.h" +#include "Render/DeviceContext/DCSurface.h" +#include "Render/DX7/DeviceOwnerDX7.h" #include "Render/RendererBackBuffer.h" -#include "Render/RendererPresentationDX7.h" +#include "Render/DX7/RendererPresentationDX7.h" -#include #include #include -#include +#include +#include #include // OFFSET: 0x0055B000 @@ -67,8 +67,6 @@ void RendererPresentationDX7::DrawFPS(CRenderSystemBase* system, int width, int SetBkMode(dc, TRANSPARENT); } - // The original records font selection in its text context, then calls GDI - // TextOutA directly, bypassing the context operation that selects that font. SetTextColor(dc, 0xFFFF); const int x = width - 40; const int y = height - 14; diff --git a/Source/Render/RendererPresentationDX7.h b/Source/Render/DX7/RendererPresentationDX7.h similarity index 63% rename from Source/Render/RendererPresentationDX7.h rename to Source/Render/DX7/RendererPresentationDX7.h index c6abc52..7e914f5 100644 --- a/Source/Render/RendererPresentationDX7.h +++ b/Source/Render/DX7/RendererPresentationDX7.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERERPRESENTATIONDX7_H -#define RAGNAROK_SOURCE_RENDER_RENDERERPRESENTATIONDX7_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_RENDERERPRESENTATIONDX7_H +#define RAGNAROK_SOURCE_RENDER_DX7_RENDERERPRESENTATIONDX7_H #include #include @@ -9,8 +9,6 @@ struct RendererBackBuffer; class CSurface; class CRenderSystemBase; -// Borrowed CRenderer frame (+0x38) and legacy renderer counters -// (+0x25C/+0x260/+0x264). The published rate is a sample count, not a ratio. struct RendererPresentationDX7 { unsigned& frame; unsigned& samples; diff --git a/Source/Render/ScreenshotDX7.cpp b/Source/Render/DX7/ScreenshotDX7.cpp similarity index 81% rename from Source/Render/ScreenshotDX7.cpp rename to Source/Render/DX7/ScreenshotDX7.cpp index e7b9972..b71a444 100644 --- a/Source/Render/ScreenshotDX7.cpp +++ b/Source/Render/DX7/ScreenshotDX7.cpp @@ -1,9 +1,9 @@ -#include "Render/DeviceOwnerDX7.h" +#include "Render/DX7/DeviceOwnerDX7.h" #include "Render/RendererBackBuffer.h" -#include "Render/RendererDX7Operations.h" -#include "Resource/BitmapImage.h" -#include "Resource/BitmapResource.h" -#include "Resource/IJL15Runtime.h" +#include "Render/DX7/RendererDX7Operations.h" +#include "Resource/Bitmap/BitmapImage.h" +#include "Resource/Bitmap/BitmapResource.h" +#include "Resource/Bitmap/IJL15Runtime.h" #include "Resource/ResourceMgr.h" #include "Resource/TextureNames.h" @@ -17,10 +17,7 @@ namespace { const auto channel = [](unsigned value, const DeviceOwnerDX7::Channel& field) { return static_cast((value >> (field.expansion & 31)) << (field.shift & 31)); }; - return static_cast( - channel((color >> 16) & 255, owner.red) + channel((color >> 8) & 255, owner.green) + - channel(color & 255, owner.blue) - ); + return static_cast(channel((color >> 16) & 255, owner.red) + channel((color >> 8) & 255, owner.green) + channel(color & 255, owner.blue)); } unsigned char ExpandedChannel(unsigned value, DWORD mask, const DeviceOwnerDX7::Channel& field) { @@ -31,13 +28,7 @@ namespace { // OFFSET: 0x0055D860 // FUNCTION: fn_02109 -bool RendererDX7Operations::SaveBitmap( - const char* filename, - const BitmapImage& overlay, - int width, - int height, - RendererBackBuffer& backBuffer -) { +bool RendererDX7Operations::SaveBitmap(const char* filename, const BitmapImage& overlay, int width, int height, RendererBackBuffer& backBuffer) { if (!backBuffer.Lock(this->owner)) { return false; } @@ -45,7 +36,6 @@ bool RendererDX7Operations::SaveBitmap( std::FILE* file = std::fopen(filename, "wb"); if (!file) { - // The original leaves the render target locked when fopen fails. return false; } @@ -82,16 +72,14 @@ bool RendererDX7Operations::SaveBitmap( if (useOverlay) { color = overlay.pixels[overlayX + overlayY * overlay.width]; - useOverlay = backBuffer.bitsPerPixel == 16 ? PackedColor(this->owner, color) != transparent - : (color & 0xFFFFFF) != 0xFF00FF; + useOverlay = backBuffer.bitsPerPixel == 16 ? PackedColor(this->owner, color) != transparent : (color & 0xFFFFFF) != 0xFF00FF; } if (!useOverlay) { if (backBuffer.bitsPerPixel == 16) { std::uint16_t pixel; std::memcpy(&pixel, source + 2 * x, sizeof(pixel)); - color = (static_cast(ExpandedChannel(pixel, redMask, red)) << 16) | - (static_cast(ExpandedChannel(pixel, greenMask, green)) << 8) | + color = (static_cast(ExpandedChannel(pixel, redMask, red)) << 16) | (static_cast(ExpandedChannel(pixel, greenMask, green)) << 8) | ExpandedChannel(pixel, blueMask, blue); } else { std::memcpy(&color, source + 4 * x, sizeof(color)); @@ -103,7 +91,6 @@ bool RendererDX7Operations::SaveBitmap( row[3 * x + 2] = static_cast(color >> 16); } - // Original writes tightly packed BGR rows without BMP alignment padding. std::fwrite(row.data(), 3u * static_cast(width), 1, file); } @@ -115,12 +102,7 @@ bool RendererDX7Operations::SaveBitmap( // OFFSET: 0x0055DDF0 // FUNCTION: fn_02110 bool RendererDX7Operations::SaveJpeg( - const char* filename, - const BitmapImage& overlay, - int width, - int height, - RendererBackBuffer& backBuffer, - IJL15Runtime& runtime + const char* filename, const BitmapImage& overlay, int width, int height, RendererBackBuffer& backBuffer, IJL15Runtime& runtime ) { if (!backBuffer.Lock(this->owner)) { return false; @@ -148,16 +130,14 @@ bool RendererDX7Operations::SaveJpeg( if (useOverlay) { color = overlay.pixels[overlayX + overlayY * overlay.width]; - useOverlay = backBuffer.bitsPerPixel == 16 ? PackedColor(this->owner, color) != transparent - : (color & 0xFFFFFF) != 0xFF00FF; + useOverlay = backBuffer.bitsPerPixel == 16 ? PackedColor(this->owner, color) != transparent : (color & 0xFFFFFF) != 0xFF00FF; } if (!useOverlay) { if (backBuffer.bitsPerPixel == 16) { std::uint16_t pixel; std::memcpy(&pixel, source + 2 * x, sizeof(pixel)); - color = (static_cast(ExpandedChannel(pixel, redMask, red)) << 16) | - (static_cast(ExpandedChannel(pixel, greenMask, green)) << 8) | + color = (static_cast(ExpandedChannel(pixel, redMask, red)) << 16) | (static_cast(ExpandedChannel(pixel, greenMask, green)) << 8) | ExpandedChannel(pixel, blueMask, blue); } else { std::memcpy(&color, source + 4 * x, sizeof(color)); @@ -174,7 +154,6 @@ bool RendererDX7Operations::SaveJpeg( IJL15Properties properties{}; if (runtime.initialize(&properties) != 0) { - // Original does not free the temporary pixels on initialization failure. return false; } @@ -189,18 +168,13 @@ bool RendererDX7Operations::SaveJpeg( properties.jpegHeight = height; const int status = runtime.write(&properties, 8); std::free(pixels); - // The original omits ijlFree on both encoder success and write failure. + return status == 0; } // OFFSET: 0x0055E340 // FUNCTION: fn_02111 -bool RendererDX7Operations::SaveLogo( - std::string filename, - ResourceMgr& resources, - TextureNames& names, - IJL15Runtime& runtime -) { +bool RendererDX7Operations::SaveLogo(std::string filename, ResourceMgr& resources, TextureNames& names, IJL15Runtime& runtime) { auto* logo = static_cast(resources.Load(names.Resolve("scr_logo.bmp"))); if (!logo) { @@ -227,8 +201,7 @@ bool RendererDX7Operations::SaveLogo( for (unsigned x = 0; x < locked.dwWidth && static_cast(remaining) > 0; ++x) { const unsigned overlayX = x + static_cast(image.width) - locked.dwWidth; const unsigned overlayY = y + static_cast(image.height) - locked.dwHeight; - const bool inOverlay = x >= locked.dwWidth - static_cast(image.width) && - y >= locked.dwHeight - static_cast(image.height); + const bool inOverlay = x >= locked.dwWidth - static_cast(image.width) && y >= locked.dwHeight - static_cast(image.height); unsigned color = inOverlay ? image.pixels[overlayX + overlayY * image.width] : 0xFF00FF; if (!inOverlay || (color & 0xFFFFFF) == 0xFF00FF) { @@ -265,8 +238,7 @@ bool RendererDX7Operations::SaveLogo( properties.dibBytes = pixels; properties.dibWidth = paddedWidth; properties.dibHeight = locked.dwHeight; - properties.dibPadding = - ((3u * static_cast(paddedWidth) + 3u) & ~3u) - 3u * static_cast(paddedWidth); + properties.dibPadding = ((3u * static_cast(paddedWidth) + 3u) & ~3u) - 3u * static_cast(paddedWidth); properties.jpegFile = filename.c_str(); properties.dibChannels = 3; properties.dibColor = 2; @@ -274,7 +246,6 @@ bool RendererDX7Operations::SaveLogo( properties.jpegHeight = locked.dwHeight; const int status = runtime.write(&properties, 8); std::free(pixels); - // The bitmap stays cache-owned; the original does not remove/release it or - // invoke ijlFree after screenshot encoding. + return status == 0; } diff --git a/Source/Render/SurfaceDX7.cpp b/Source/Render/DX7/SurfaceDX7.cpp similarity index 79% rename from Source/Render/SurfaceDX7.cpp rename to Source/Render/DX7/SurfaceDX7.cpp index f0a2f6f..9751d68 100644 --- a/Source/Render/SurfaceDX7.cpp +++ b/Source/Render/DX7/SurfaceDX7.cpp @@ -1,8 +1,8 @@ -#include "Render/DeviceOwnerDX7.h" -#include "Render/SurfaceDX7.h" +#include "Render/DX7/DeviceOwnerDX7.h" +#include "Render/DX7/SurfaceDX7.h" #include -#include +#include namespace { std::uint32_t AlignDimension(int value) { @@ -18,9 +18,9 @@ namespace { description.dwHeight = height; description.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; description.ddpfPixelFormat = owner.primaryDescription.ddpfPixelFormat; - description.ddckCKSrcBlt.dwColorSpaceLowValue = - description.ddpfPixelFormat.dwRBitMask | description.ddpfPixelFormat.dwBBitMask; + description.ddckCKSrcBlt.dwColorSpaceLowValue = description.ddpfPixelFormat.dwRBitMask | description.ddpfPixelFormat.dwBBitMask; description.ddckCKSrcBlt.dwColorSpaceHighValue = description.ddckCKSrcBlt.dwColorSpaceLowValue; + return description; } @@ -29,9 +29,7 @@ namespace { } std::uint16_t Color(DeviceOwnerDX7& owner, unsigned red, unsigned green, unsigned blue) { - return static_cast( - Channel(red, owner.red) + Channel(green, owner.green) + Channel(blue, owner.blue) - ); + return static_cast(Channel(red, owner.red) + Channel(green, owner.green) + Channel(blue, owner.blue)); } } @@ -45,8 +43,7 @@ CSurfaceDX7::CSurfaceDX7(DeviceOwnerDX7& owner, int width, int height) // OFFSET: 0x00542C80 // FUNCTION: fn_01777 -CSurfaceDX7::CSurfaceDX7(DeviceOwnerDX7& owner, IDirectDrawSurface7* surface) - : m_owner(&owner), m_surface(nullptr), m_width(0), m_height(0) { +CSurfaceDX7::CSurfaceDX7(DeviceOwnerDX7& owner, IDirectDrawSurface7* surface) : m_owner(&owner), m_surface(nullptr), m_width(0), m_height(0) { if (surface) { DDSURFACEDESC2 description{}; description.dwSize = sizeof(description); @@ -104,7 +101,6 @@ SurfaceLock CSurfaceDX7::Lock() { SurfaceLock output{}; if (this->m_surface) { - // The original supplies a zeroed descriptor, including dwSize, at this site. DDSURFACEDESC2 description{}; if (SUCCEEDED(this->m_surface->Lock(nullptr, &description, DDLOCK_WAIT, nullptr))) { @@ -150,9 +146,7 @@ void CSurfaceDX7::Upload(int x, int y, int width, int height, const std::uint32_ } const unsigned stride = sourceWidth ? sourceWidth : width; - RECT rectangle{ - x, y, std::bit_cast(static_cast(x) + width), std::bit_cast(static_cast(y) + height) - }; + RECT rectangle{x, y, x + width, y + height}; DDSURFACEDESC2 description{}; description.dwSize = sizeof(description); @@ -165,22 +159,19 @@ void CSurfaceDX7::Upload(int x, int y, int width, int height, const std::uint32_ for (int row = 0; row < height; ++row) { if (description.ddpfPixelFormat.dwRGBBitCount == 16) { - auto* destination = reinterpret_cast(output); - for (int column = 0; column < width; ++column) { const auto pixel = pixels[column]; const auto value = Color(*this->m_owner, (pixel >> 16) & 255, (pixel >> 8) & 255, pixel & 255); if (value != transparent) { - destination[column] = value; + std::memcpy(output + column * sizeof(value), &value, sizeof(value)); } } } else { - auto* destination = reinterpret_cast(output); - for (int column = 0; column < width; ++column) { if ((pixels[column] & 0xFFFFFF) != 0xFF00FF) { - destination[column] = pixels[column]; + const std::uint32_t value = pixels[column]; + std::memcpy(output + column * sizeof(value), &value, sizeof(value)); } } } @@ -198,8 +189,7 @@ void CSurfaceDX7::Fill(const RECT* rectangle, std::uint32_t color) { if (this->m_surface) { DDBLTFX effects; effects.dwSize = sizeof(effects); - // Unlike Upload, this entry feeds low/high color bytes into red/blue and - // truncates the packed result to 16 bits even on a 32-bit surface. + effects.dwFillColor = Color(*this->m_owner, color & 255, (color >> 8) & 255, (color >> 16) & 255); this->m_surface->Blt(const_cast(rectangle), nullptr, nullptr, DDBLT_COLORFILL | DDBLT_WAIT, &effects); } @@ -209,24 +199,22 @@ void CSurfaceDX7::Fill(const RECT* rectangle, std::uint32_t color) { // FUNCTION: fn_01785 void CSurfaceDX7::Draw(int x, int y, int width, int height, std::uint32_t) { RECT source{0, 0, width, height}; - const auto right = std::bit_cast(static_cast(x) + width); - const auto bottom = std::bit_cast(static_cast(y) + height); + const int right = x + width; + const int bottom = y + height; - if (right > std::bit_cast(this->m_owner->width)) { - source.right = std::bit_cast(this->m_owner->width - static_cast(x)); + if (right > static_cast(this->m_owner->width)) { + source.right = this->m_owner->width - x; } - if (bottom > std::bit_cast(this->m_owner->height)) { - source.bottom = std::bit_cast(this->m_owner->height - static_cast(y)); + if (bottom > static_cast(this->m_owner->height)) { + source.bottom = this->m_owner->height - y; } - source.left = x < 0 ? std::bit_cast(0u - static_cast(x)) : 0; - source.top = y < 0 ? std::bit_cast(0u - static_cast(y)) : 0; + source.left = x < 0 ? -x : 0; + source.top = y < 0 ? -y : 0; if (source.right > source.left && source.bottom > source.top) { - this->m_owner->renderTarget->BltFast( - std::max(x, 0), std::max(y, 0), this->m_surface, &source, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT - ); + this->m_owner->renderTarget->BltFast(std::max(x, 0), std::max(y, 0), this->m_surface, &source, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); } } @@ -237,7 +225,6 @@ void CSurfaceDX7::Stretch(int, int, int width, int height) { this->m_owner->renderTarget->Blt(&destination, this->m_surface, nullptr, DDBLT_WAIT, nullptr); } - // FUNCTION: fn_01788 DWORD DeviceOwnerDX7::BlueMask() { return this->blueMask; @@ -295,8 +282,7 @@ IDirectDrawSurface7* DeviceOwnerDX7::RenderTarget() { // OFFSET: 0x00542D60 // FUNCTION: fn_01778 -CSurfaceWallpaperDX7::CSurfaceWallpaperDX7(DeviceOwnerDX7& owner, int width, int height) - : CSurfaceDX7(owner, width, height) { +CSurfaceWallpaperDX7::CSurfaceWallpaperDX7(DeviceOwnerDX7& owner, int width, int height) : CSurfaceDX7(owner, width, height) { } // OFFSET: 0x00543990 diff --git a/Source/Render/SurfaceDX7.h b/Source/Render/DX7/SurfaceDX7.h similarity index 84% rename from Source/Render/SurfaceDX7.h rename to Source/Render/DX7/SurfaceDX7.h index 3a8fc49..98fdbc5 100644 --- a/Source/Render/SurfaceDX7.h +++ b/Source/Render/DX7/SurfaceDX7.h @@ -1,14 +1,12 @@ -#ifndef RAGNAROK_SOURCE_RENDER_SURFACEDX7_H -#define RAGNAROK_SOURCE_RENDER_SURFACEDX7_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_SURFACEDX7_H +#define RAGNAROK_SOURCE_RENDER_DX7_SURFACEDX7_H -#include "Render/Surface.h" +#include "Render/Textures/Surface.h" #include class DeviceOwnerDX7; -// RTTI CSurfaceDX7. The device owner is borrowed; the native -// surface is retained independently and must be released before owner teardown. class CSurfaceDX7 : public CSurface { friend class CSurfaceWallpaperDX7; friend class DeviceOwnerDX7; diff --git a/Source/Render/TextureAllocationDX7.cpp b/Source/Render/DX7/TextureAllocationDX7.cpp similarity index 90% rename from Source/Render/TextureAllocationDX7.cpp rename to Source/Render/DX7/TextureAllocationDX7.cpp index e06bbbe..5a5e5b5 100644 --- a/Source/Render/TextureAllocationDX7.cpp +++ b/Source/Render/DX7/TextureAllocationDX7.cpp @@ -1,4 +1,4 @@ -#include "Render/TextureAllocationDX7.h" +#include "Render/DX7/TextureAllocationDX7.h" // ORIGINAL_SITE: 0x0054A930 in fn_02323 (fragment) void TextureAllocationDX7::Update(int enabled, const D3DDEVICEDESC7& caps) { diff --git a/Source/Render/TextureAllocationDX7.h b/Source/Render/DX7/TextureAllocationDX7.h similarity index 50% rename from Source/Render/TextureAllocationDX7.h rename to Source/Render/DX7/TextureAllocationDX7.h index 4498a25..8ee7cea 100644 --- a/Source/Render/TextureAllocationDX7.h +++ b/Source/Render/DX7/TextureAllocationDX7.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_RENDER_TEXTUREALLOCATIONDX7_H -#define RAGNAROK_SOURCE_RENDER_TEXTUREALLOCATIONDX7_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_TEXTUREALLOCATIONDX7_H +#define RAGNAROK_SOURCE_RENDER_DX7_TEXTUREALLOCATIONDX7_H #include -// Shared original globals, not per-texture options. struct TextureAllocationDX7 { DWORD descriptorFlags; DWORD surfaceCaps; diff --git a/Source/Render/TextureBindingDX7.cpp b/Source/Render/DX7/TextureBindingDX7.cpp similarity index 87% rename from Source/Render/TextureBindingDX7.cpp rename to Source/Render/DX7/TextureBindingDX7.cpp index 47d81c8..09831c6 100644 --- a/Source/Render/TextureBindingDX7.cpp +++ b/Source/Render/DX7/TextureBindingDX7.cpp @@ -1,5 +1,5 @@ -#include "Render/TextureBindingDX7.h" -#include "Render/TextureDX7.h" +#include "Render/DX7/TextureBindingDX7.h" +#include "Render/DX7/TextureDX7.h" // OFFSET: 0x0055F7D0 // FUNCTION: fn_02119 diff --git a/Source/Render/TextureBindingDX7.h b/Source/Render/DX7/TextureBindingDX7.h similarity index 74% rename from Source/Render/TextureBindingDX7.h rename to Source/Render/DX7/TextureBindingDX7.h index 802b721..333600d 100644 --- a/Source/Render/TextureBindingDX7.h +++ b/Source/Render/DX7/TextureBindingDX7.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_TEXTUREBINDINGDX7_H -#define RAGNAROK_SOURCE_RENDER_TEXTUREBINDINGDX7_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_TEXTUREBINDINGDX7_H +#define RAGNAROK_SOURCE_RENDER_DX7_TEXTUREBINDINGDX7_H #include #include @@ -7,8 +7,6 @@ class CTextureDX7; struct IDirect3DDevice7; -// Original renderer +0x268/+0x26C and native device +0x274. -// Cache entries borrow texture objects; native SetTexture retains its own surface reference. struct TextureBindingDX7 { /* 0000 */ unsigned char unknown_0000[0x268]{}; /* 0268 */ CTextureDX7* first = nullptr; diff --git a/Source/Render/TextureCalibrationDX7.cpp b/Source/Render/DX7/TextureCalibrationDX7.cpp similarity index 76% rename from Source/Render/TextureCalibrationDX7.cpp rename to Source/Render/DX7/TextureCalibrationDX7.cpp index bb2fbaf..57b4dab 100644 --- a/Source/Render/TextureCalibrationDX7.cpp +++ b/Source/Render/DX7/TextureCalibrationDX7.cpp @@ -1,7 +1,7 @@ -#include "Render/DeviceOwnerDX7.h" -#include "Render/RenderPrimitive.h" -#include "Render/SurfaceDX7.h" -#include "Render/TextureDX7.h" +#include "Render/DX7/DeviceOwnerDX7.h" +#include "Render/Primitives/RenderPrimitive.h" +#include "Render/DX7/SurfaceDX7.h" +#include "Render/DX7/TextureDX7.h" #include #include @@ -15,16 +15,15 @@ namespace { // OFFSET: 0x0054B040 // FUNCTION: fn_01905 bool DeviceOwnerDX7::CalibrateTextureCoordinates(TextureDX7Context& context) { - const std::uint32_t pattern[16] = {0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0}; + const std::uint32_t pattern[16] = {0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0}; CSurfaceDX7 readback(*this, this->width, this->height); - CTextureDX7 texture(context, 4, 4, 0); + CTextureDX7 texture(context, 4, 4, TextureFormat::A1R5G5B5); texture.Upload(0, 0, 4, 4, pattern, 0, 0); this->device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, 0); this->device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0); - this->device->SetRenderState(D3DRENDERSTATE_ZENABLE, 0); - this->device->SetTextureStageState(0, D3DTSS_MAGFILTER, 2); - this->device->SetTextureStageState(0, D3DTSS_MINFILTER, 2); + this->device->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); + this->device->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); + this->device->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR); this->device->SetTexture(0, texture.NativeSurface()); const unsigned columns = this->width >> 2; @@ -58,7 +57,7 @@ bool DeviceOwnerDX7::CalibrateTextureCoordinates(TextureDX7Context& context) { {x + 4, y, z, rhw, 0xFFFFFFFF, 0xFFFFFFFF, u1, v0}, {x + 4, y + 4, z, rhw, 0xFFFFFFFF, 0xFFFFFFFF, u1, v1} }; - this->device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 452, vertices, 4, 0); + this->device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1, vertices, 4, 0); } this->device->EndScene(); @@ -79,8 +78,7 @@ bool DeviceOwnerDX7::CalibrateTextureCoordinates(TextureDX7Context& context) { unsigned bright = 0; for (unsigned sample = 0; sample < 16; ++sample) { - const auto* source = static_cast(locked.lpSurface) + (y + sample / 4) * locked.lPitch + - (x + sample % 4) * pixelBytes; + const auto* source = static_cast(locked.lpSurface) + (y + sample / 4) * locked.lPitch + (x + sample % 4) * pixelBytes; unsigned pixel; if (pixelBytes == 2) { @@ -91,12 +89,9 @@ bool DeviceOwnerDX7::CalibrateTextureCoordinates(TextureDX7Context& context) { std::memcpy(&pixel, source, 4); } - // Original scoring truncates even a 32-bit read to its low WORD before - // applying the device masks. Preserve this distinct calibration contract. pixel = static_cast(pixel); - const unsigned value = Component(pixel, this->greenMask, this->green) + - Component(pixel, this->blueMask, this->blue) + - Component(pixel, this->redMask, this->red); + const unsigned value = + Component(pixel, this->greenMask, this->green) + Component(pixel, this->blueMask, this->blue) + Component(pixel, this->redMask, this->red); if (pattern[sample] == 0) { dark += value; @@ -121,7 +116,8 @@ bool DeviceOwnerDX7::CalibrateTextureCoordinates(TextureDX7Context& context) { g_textureOffsetX = static_cast(best % 256) * (1.0f / 256.0f); g_textureOffsetY = static_cast(best / 256) * (1.0f / 256.0f); - this->device->SetTextureStageState(0, D3DTSS_MAGFILTER, 2); - this->device->SetTextureStageState(0, D3DTSS_MINFILTER, 2); + this->device->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); + this->device->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR); + return true; } diff --git a/Source/Render/TextureDX7.cpp b/Source/Render/DX7/TextureDX7.cpp similarity index 65% rename from Source/Render/TextureDX7.cpp rename to Source/Render/DX7/TextureDX7.cpp index 395e1b7..62c5ce0 100644 --- a/Source/Render/TextureDX7.cpp +++ b/Source/Render/DX7/TextureDX7.cpp @@ -1,19 +1,20 @@ -#include "Client/ErrorDialog.h" -#include "Render/DeviceOwnerDX7.h" -#include "Render/SpritePixels.h" -#include "Render/TextureDX7.h" +#include "Client/Application/ErrorDialog.h" +#include "Render/DX7/DeviceOwnerDX7.h" +#include "Render/Textures/SpritePixels.h" +#include "Render/DX7/TextureDX7.h" -#include -#include +#include #include namespace { // STATIC: 0x01387270; shared across devices, initially all bytes 0xFF. - std::array formats = [] { - std::array result; - std::memset(result.data(), 0xFF, sizeof(result)); - return result; - }(); + DDPIXELFORMAT formats[5] = { + {UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX}, + {UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX}, + {UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX}, + {UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX}, + {UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX}, + }; // OFFSET: 0x00544B50 // FUNCTION: fn_01824 @@ -27,21 +28,17 @@ namespace { bool accepted = false; switch (*format) { - case 0: - accepted = (candidate->dwFlags & DDPF_ALPHAPIXELS) && candidate->dwRGBBitCount == 16 && - candidate->dwRGBAlphaBitMask == 0x8000; + case TextureFormat::A1R5G5B5: + accepted = (candidate->dwFlags & DDPF_ALPHAPIXELS) && candidate->dwRGBBitCount == 16 && candidate->dwRGBAlphaBitMask == 0x8000; break; - case 1: - accepted = (candidate->dwFlags & DDPF_ALPHAPIXELS) && candidate->dwRGBBitCount == 16 && - candidate->dwRGBAlphaBitMask == 0xF000; + case TextureFormat::A4R4G4B4: + accepted = (candidate->dwFlags & DDPF_ALPHAPIXELS) && candidate->dwRGBBitCount == 16 && candidate->dwRGBAlphaBitMask == 0xF000; break; - case 2: - accepted = - !(candidate->dwFlags & DDPF_ALPHAPIXELS) && candidate->dwRGBBitCount == 16 && candidate->dwRBitMask == 0xF800; + case TextureFormat::R5G6B5: + accepted = !(candidate->dwFlags & DDPF_ALPHAPIXELS) && candidate->dwRGBBitCount == 16 && candidate->dwRBitMask == 0xF800; break; - case 4: - accepted = (candidate->dwFlags & DDPF_ALPHAPIXELS) && candidate->dwRGBBitCount == 32 && - candidate->dwRGBAlphaBitMask == 0xFF000000; + case TextureFormat::A8R8G8B8: + accepted = (candidate->dwFlags & DDPF_ALPHAPIXELS) && candidate->dwRGBBitCount == 32 && candidate->dwRGBAlphaBitMask == 0xFF000000; break; } @@ -54,9 +51,7 @@ namespace { } RECT Rectangle(int x, int y, int width, int height) { - return { - x, y, std::bit_cast(static_cast(x) + width), std::bit_cast(static_cast(y) + height) - }; + return {x, y, x + width, y + height}; } // OFFSET: 0x0056FCE0 @@ -67,18 +62,21 @@ namespace { int remaining = 0; for (int y = 0; y < image.height; ++y) { - auto* row = reinterpret_cast(output); + auto* row = output; for (int x = 0; x < image.width; ++x) { if (remaining) { --remaining; - row[x] = 0; + const std::uint16_t value = 0; + std::memcpy(row + x * sizeof(value), &value, sizeof(value)); } else { if (*input) { - row[x] = static_cast(palette[*input]); + const std::uint16_t value = palette[*input]; + std::memcpy(row + x * sizeof(value), &value, sizeof(value)); } else { ++input; - row[x] = 0; + const std::uint16_t value = 0; + std::memcpy(row + x * sizeof(value), &value, sizeof(value)); remaining = static_cast(*input) - 1; } @@ -92,16 +90,14 @@ namespace { } // OFFSET: 0x00543B00 -CTextureDX7::CTextureDX7(TextureDX7Context& context) - : m_owner(&context.owner), m_surface(nullptr), m_context(&context) { +CTextureDX7::CTextureDX7(TextureDX7Context& context) : m_owner(&context.owner), m_surface(nullptr), m_context(&context) { this->m_width = this->m_height = this->m_textureWidth = this->m_textureHeight = 1; - this->m_format = 0; + this->m_format = TextureFormat::A1R5G5B5; } // OFFSET: 0x00543B90 // FUNCTION: fn_01808 -CTextureDX7::CTextureDX7(TextureDX7Context& context, int width, int height, int format) - : m_owner(&context.owner), m_surface(nullptr), m_context(&context) { +CTextureDX7::CTextureDX7(TextureDX7Context& context, int width, int height, int format) : m_owner(&context.owner), m_surface(nullptr), m_context(&context) { this->Create(width, height, format); this->SetImageSize(width, height); } @@ -130,25 +126,25 @@ bool CTextureDX7::Create(int width, int height, int format) { this->m_surface = nullptr; } - if (static_cast(format) >= 2 && format != 2 && format != 4) { + if (static_cast(format) >= TextureFormat::R5G6B5 && format != TextureFormat::R5G6B5 && format != TextureFormat::A8R8G8B8) { ShowErrorDialog(this->m_context->renderSystem, "Create Texture::Unsupported pixelformat", 0); } unsigned selected = format; - if (formats[selected].dwSize != 32) { + if (formats[selected].dwSize != sizeof(DDPIXELFORMAT)) { this->m_owner->device->EnumTextureFormats(SelectFormat, &selected); } - if (formats[selected].dwSize != 32) { + if (formats[selected].dwSize != sizeof(DDPIXELFORMAT)) { ShowErrorDialog(this->m_context->renderSystem, "GFC ", 0); } DDSURFACEDESC2 description{}; description.dwSize = sizeof(description); - description.dwFlags = this->m_context->allocation.descriptorFlags | 0x101007; + description.dwFlags = this->m_context->allocation.descriptorFlags | DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_TEXTURESTAGE; - if (selected == 2) { + if (selected == TextureFormat::R5G6B5) { description.dwFlags |= DDSD_CKSRCBLT; } @@ -157,8 +153,7 @@ bool CTextureDX7::Create(int width, int height, int format) { description.ddpfPixelFormat = formats[selected]; description.ddsCaps.dwCaps = this->m_context->allocation.surfaceCaps | DDSCAPS_TEXTURE; description.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE; - description.ddckCKSrcBlt.dwColorSpaceLowValue = - description.ddpfPixelFormat.dwRBitMask | description.ddpfPixelFormat.dwBBitMask; + description.ddckCKSrcBlt.dwColorSpaceLowValue = description.ddpfPixelFormat.dwRBitMask | description.ddpfPixelFormat.dwBBitMask; description.ddckCKSrcBlt.dwColorSpaceHighValue = description.ddckCKSrcBlt.dwColorSpaceLowValue; unsigned count = 1; description.dwMipMapCount = 1; @@ -189,14 +184,12 @@ SurfaceLock CTextureDX7::Lock() { DDSURFACEDESC2 description{}; if (SUCCEEDED(this->m_surface->Lock(nullptr, &description, DDLOCK_WAIT, nullptr))) { - output = { - true, - description.lpSurface, - description.lPitch, - description.dwWidth, - description.dwHeight, - static_cast(description.ddpfPixelFormat.dwRGBBitCount) - }; + output = {true, + description.lpSurface, + description.lPitch, + description.dwWidth, + description.dwHeight, + static_cast(description.ddpfPixelFormat.dwRGBBitCount)}; } } @@ -227,15 +220,7 @@ void CTextureDX7::ReleaseDC(HDC dc) { // OFFSET: 0x00544C90 // FUNCTION: fn_01826 -void CTextureDX7::Upload( - int x, - int y, - int width, - int height, - const std::uint32_t* pixels, - int option, - int sourceWidth -) { +void CTextureDX7::Upload(int x, int y, int width, int height, const std::uint32_t* pixels, int option, int sourceWidth) { this->SetImageSize(width, height); this->unknown_0008 = (this->unknown_0008 & 255) | (static_cast(option) << 8); @@ -270,9 +255,7 @@ void CTextureDX7::Upload( const RECT rectangle = Rectangle(x / stepX, y / stepY, columns, rows); - if ( - FAILED(this->m_surface->Lock(const_cast(&rectangle), &description, DDLOCK_WAIT | DDLOCK_WRITEONLY, nullptr)) - ) { + if (FAILED(this->m_surface->Lock(const_cast(&rectangle), &description, DDLOCK_WAIT | DDLOCK_WRITEONLY, nullptr))) { return; } @@ -283,42 +266,39 @@ void CTextureDX7::Upload( for (int row = 0; row < rows; ++row) { for (int column = 0; column < columns; ++column) { const std::uint32_t color = pixels[column * stepX]; - auto* words = reinterpret_cast(output); switch (this->m_format) { - case 0: { - std::uint16_t value = - ((color >> 16) & 0x8000) | ((color >> 3) & 0x1F) | ((color >> 6) & 0x3E0) | ((color >> 9) & 0x7C00); + case TextureFormat::A1R5G5B5: { + std::uint16_t value = ((color >> 16) & 0x8000) | ((color >> 3) & 0x1F) | ((color >> 6) & 0x3E0) | ((color >> 9) & 0x7C00); if (value == 0xFC1F || (transparent && !(value & 0x7FFF))) { value = 0; } - words[column] = value; + std::memcpy(output + column * sizeof(value), &value, sizeof(value)); break; } - case 1: { - std::uint16_t value = - ((color & 255) >> 4) | ((color >> 8) & 0xF0) | ((color >> 12) & 0xF00) | ((color >> 16) & 0xF000); + case TextureFormat::A4R4G4B4: { + std::uint16_t value = ((color & 255) >> 4) | ((color >> 8) & 0xF0) | ((color >> 12) & 0xF00) | ((color >> 16) & 0xF000); if ((value & 0xFFF) == 0xF0F || (transparent && !(value & 0xFFF))) { value = 0; } - words[column] = value; + std::memcpy(output + column * sizeof(value), &value, sizeof(value)); break; } - case 2: { + case TextureFormat::R5G6B5: { const std::uint16_t value = ((color >> 8) & 0xF800) | ((color >> 3) & 0x1F) | ((color >> 5) & 0x7E0); if (!transparent || value != 0xF81F) { - words[column] = value; + std::memcpy(output + column * sizeof(value), &value, sizeof(value)); } break; } - case 4: - reinterpret_cast(output)[column] = color; + case TextureFormat::A8R8G8B8: + std::memcpy(output + column * sizeof(color), &color, sizeof(color)); break; } } @@ -329,7 +309,7 @@ void CTextureDX7::Upload( this->m_surface->Unlock(nullptr); RECT update{0, 0, static_cast(this->m_textureWidth), static_cast(this->m_textureHeight)}; - this->Update(static_cast(reinterpret_cast(&update))); + this->Update(&update); } // OFFSET: 0x00544080 @@ -337,15 +317,12 @@ void CTextureDX7::Upload( void CTextureDX7::Fill(const RECT* rectangle, std::uint32_t color) { if (this->m_surface) { const auto& owner = *this->m_owner; - const auto channel = [](unsigned value, const DeviceOwnerDX7::Channel& mask) { - return (value >> (mask.expansion & 31)) << (mask.shift & 31); - }; + const auto channel = [](unsigned value, const DeviceOwnerDX7::Channel& mask) { return (value >> (mask.expansion & 31)) << (mask.shift & 31); }; DDBLTFX effects; + effects.dwSize = sizeof(effects); - effects.dwFillColor = static_cast( - channel(color & 255, owner.red) + channel((color >> 8) & 255, owner.green) + - channel((color >> 16) & 255, owner.blue) - ); + effects.dwFillColor = + static_cast(channel(color & 255, owner.red) + channel((color >> 8) & 255, owner.green) + channel((color >> 16) & 255, owner.blue)); this->m_surface->Blt(const_cast(rectangle), nullptr, nullptr, DDBLT_COLORFILL | DDBLT_WAIT, &effects); } } @@ -354,25 +331,19 @@ void CTextureDX7::Fill(const RECT* rectangle, std::uint32_t color) { // FUNCTION: fn_01817 void CTextureDX7::Draw(int x, int y, int width, int height, std::uint32_t color) { const auto& context = *this->m_context; - this->DrawTo( - context.primitives, context.queues, x, y, width, height, color, context.depthAlpha, context.depthStart, - context.depthEnd - ); + this->DrawTo(context.primitives, context.queues, x, y, width, height, color, context.depthAlpha, context.depthStart, context.depthEnd); } // OFFSET: 0x00544610 // FUNCTION: fn_01818 void CTextureDX7::Stretch(int x, int y, int width, int height) { const auto& context = *this->m_context; - this->StretchTo( - context.primitives, context.queues, x, y, width, height, context.depthAlpha, context.depthStart, context.depthEnd - ); + this->StretchTo(context.primitives, context.queues, x, y, width, height, context.depthAlpha, context.depthStart, context.depthEnd); } // OFFSET: 0x005451B0 // FUNCTION: fn_01827 -void CTextureDX7::Update(int argument) { - const auto* rectangle = reinterpret_cast(static_cast(static_cast(argument))); +void CTextureDX7::Update(const RECT* rectangle) { RECT destination = *rectangle; DDSCAPS2 caps{DDSCAPS_TEXTURE | DDSCAPS_MIPMAP}; IDirectDrawSurface7* level = this->m_surface; @@ -389,14 +360,13 @@ void CTextureDX7::Update(int argument) { } } - // The owning mip chain retains this level during the following traversal. level->Release(); } } // OFFSET: 0x005452A0 // FUNCTION: fn_01828 -void CTextureDX7::UploadSprite(int x, int y, int width, int height, const void* rawImage, int palette) { +void CTextureDX7::UploadSprite(int x, int y, int width, int height, const SpriteRleImage* image, const std::uint32_t* palette) { if (!this->m_surface) { return; } @@ -409,8 +379,8 @@ void CTextureDX7::UploadSprite(int x, int y, int width, int height, const void* return; } - if (this->m_format == 0 || this->m_format == 4) { - const unsigned bytes = this->m_format == 0 ? 2 : 4; + if (this->m_format == TextureFormat::A1R5G5B5 || this->m_format == TextureFormat::A8R8G8B8) { + const unsigned bytes = this->m_format == TextureFormat::A1R5G5B5 ? 2 : 4; auto* row = static_cast(description.lpSurface); for (int index = 0; index < height; ++index) { @@ -419,26 +389,14 @@ void CTextureDX7::UploadSprite(int x, int y, int width, int height, const void* } } - const auto* colors = - reinterpret_cast(static_cast(static_cast(palette))); - DecodeSprite(*static_cast(rawImage), colors, description.lpSurface, description.lPitch); + DecodeSprite(*image, palette, description.lpSurface, description.lPitch); this->m_surface->Unlock(nullptr); - this->Update(static_cast(reinterpret_cast(&rectangle))); + this->Update(&rectangle); } // OFFSET: 0x00544160 // FUNCTION: fn_01814 -bool CTextureDX7::CopyTexture( - CTexture* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - int x, - int y, - int width, - int height -) { +bool CTextureDX7::CopyTexture(CTexture* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, int x, int y, int width, int height) { if (!this->m_surface) { return false; } @@ -447,13 +405,11 @@ bool CTextureDX7::CopyTexture( const RECT to = Rectangle(x, y, width, height); auto* nativeSource = static_cast(source)->m_surface; - if ( - this->m_surface->Blt(const_cast(&to), nativeSource, const_cast(&from), DDBLT_WAIT, nullptr) != S_OK - ) { + if (this->m_surface->Blt(const_cast(&to), nativeSource, const_cast(&from), DDBLT_WAIT, nullptr) != S_OK) { return false; } RECT update{0, 0, static_cast(this->m_textureWidth), static_cast(this->m_textureHeight)}; - this->Update(static_cast(reinterpret_cast(&update))); + this->Update(&update); return true; } diff --git a/Source/Render/TextureDX7.h b/Source/Render/DX7/TextureDX7.h similarity index 68% rename from Source/Render/TextureDX7.h rename to Source/Render/DX7/TextureDX7.h index 2d38b21..cb6d76e 100644 --- a/Source/Render/TextureDX7.h +++ b/Source/Render/DX7/TextureDX7.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_RENDER_TEXTUREDX7_H -#define RAGNAROK_SOURCE_RENDER_TEXTUREDX7_H +#ifndef RAGNAROK_SOURCE_RENDER_DX7_TEXTUREDX7_H +#define RAGNAROK_SOURCE_RENDER_DX7_TEXTUREDX7_H -#include "Render/Texture.h" -#include "Render/TextureAllocationDX7.h" +#include "Render/Textures/Texture.h" +#include "Render/DX7/TextureAllocationDX7.h" #include @@ -34,19 +34,9 @@ public: void Fill(const RECT* rectangle, std::uint32_t color) override; void Draw(int x, int y, int width, int height, std::uint32_t color) override; void Stretch(int x, int y, int width, int height) override; - void Update(int rectangle) override; - void UploadSprite(int x, int y, int width, int height, const void* image, int palette) override; - bool CopyTexture( - CTexture* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - int x, - int y, - int width, - int height - ) override; + void Update(const RECT* rectangle) override; + void UploadSprite(int x, int y, int width, int height, const SpriteRleImage* image, const std::uint32_t* palette) override; + bool CopyTexture(CTexture* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, int x, int y, int width, int height) override; bool Create(int width, int height, int format) override; bool CopySurface(IDirectDrawSurface7* source, const RECT* rectangle); IDirectDrawSurface7* NativeSurface() const { @@ -56,8 +46,7 @@ public: protected: /* 0124 */ DeviceOwnerDX7* m_owner; /* 0128 */ IDirectDrawSurface7* m_surface; - // Host-side binding of recovered renderer/global dependencies, beyond the - // original 300-byte native prefix. Never copied into file/network structures. + TextureDX7Context* m_context; }; diff --git a/Source/Render/TextureModesDX7.cpp b/Source/Render/DX7/TextureModesDX7.cpp similarity index 87% rename from Source/Render/TextureModesDX7.cpp rename to Source/Render/DX7/TextureModesDX7.cpp index e65f56d..177a6bb 100644 --- a/Source/Render/TextureModesDX7.cpp +++ b/Source/Render/DX7/TextureModesDX7.cpp @@ -1,4 +1,4 @@ -#include "Render/RendererDX7Operations.h" +#include "Render/DX7/RendererDX7Operations.h" #include "Render/TextureStageModes.h" // OFFSET: 0x0055ED50 diff --git a/Source/Render/AlphaQueuesDX9.cpp b/Source/Render/DX9/AlphaQueuesDX9.cpp similarity index 85% rename from Source/Render/AlphaQueuesDX9.cpp rename to Source/Render/DX9/AlphaQueuesDX9.cpp index 1098d7e..1c264e4 100644 --- a/Source/Render/AlphaQueuesDX9.cpp +++ b/Source/Render/DX9/AlphaQueuesDX9.cpp @@ -1,7 +1,7 @@ -#include "Render/DeviceStateDX9.h" -#include "Render/RenderQueues.h" -#include "Render/RendererDX9Operations.h" -#include "Render/TextureDX9.h" +#include "Render/DX9/DeviceStateDX9.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/DX9/RendererDX9Operations.h" +#include "Render/DX9/TextureDX9.h" #include #include @@ -16,8 +16,7 @@ namespace { return false; } - return left.depth == right.depth && - reinterpret_cast(left.primitive) < reinterpret_cast(right.primitive); + return left.depth == right.depth && reinterpret_cast(left.primitive) < reinterpret_cast(right.primitive); } bool WritesDepth(const RenderCommand& command) { @@ -48,9 +47,7 @@ void RendererDX9Operations::DrawAlphaQueues(RenderQueues& queues, unsigned char this->state.SetRenderState(D3DRS_ZWRITEENABLE, WritesDepth(command)); } - this->state.SetTexture( - 0, command.texture ? static_cast(command.texture)->NativeTexture() : nullptr - ); + this->state.SetTexture(0, command.texture ? static_cast(command.texture)->NativeTexture() : nullptr); this->DrawPrimitive(&command); } }; diff --git a/Source/Render/BackBufferDX9.cpp b/Source/Render/DX9/BackBufferDX9.cpp similarity index 68% rename from Source/Render/BackBufferDX9.cpp rename to Source/Render/DX9/BackBufferDX9.cpp index a982dc5..187581d 100644 --- a/Source/Render/BackBufferDX9.cpp +++ b/Source/Render/DX9/BackBufferDX9.cpp @@ -1,4 +1,4 @@ -#include "Render/DeviceOwnerDX9.h" +#include "Render/DX9/DeviceOwnerDX9.h" // OFFSET: 0x005650E0 // FUNCTION: fn_02212 @@ -7,13 +7,10 @@ bool DeviceOwnerDX9::CaptureBackBuffer() { return false; } - if ( - !this->capturedBackBuffer && - FAILED(this->device->CreateOffscreenPlainSurface( - this->backBufferDescription.Width, this->backBufferDescription.Height, this->backBufferDescription.Format, - D3DPOOL_SYSTEMMEM, &this->capturedBackBuffer, nullptr - )) - ) { + if (!this->capturedBackBuffer && FAILED(this->device->CreateOffscreenPlainSurface( + this->backBufferDescription.Width, this->backBufferDescription.Height, this->backBufferDescription.Format, + D3DPOOL_SYSTEMMEM, &this->capturedBackBuffer, nullptr + ))) { return false; } diff --git a/Source/Render/DX9/D3DX9Runtime.cpp b/Source/Render/DX9/D3DX9Runtime.cpp new file mode 100644 index 0000000..e68f322 --- /dev/null +++ b/Source/Render/DX9/D3DX9Runtime.cpp @@ -0,0 +1,25 @@ +#include "Render/DX9/D3DX9Runtime.h" + +#include + +D3DX9Runtime::D3DX9Runtime() : m_module(LoadLibraryA("D3DX9_43.dll")) { + + if (!this->m_module) { + throw std::system_error(GetLastError(), std::system_category(), "D3DX9_43.dll"); + } + + this->filterTexture = reinterpret_castfilterTexture)>(GetProcAddress(this->m_module, "D3DXFilterTexture")); + this->loadSurfaceFromMemory = reinterpret_castloadSurfaceFromMemory)>(GetProcAddress(this->m_module, "D3DXLoadSurfaceFromMemory")); + this->loadSurfaceFromSurface = reinterpret_castloadSurfaceFromSurface)>(GetProcAddress(this->m_module, "D3DXLoadSurfaceFromSurface")); + this->perspectiveFovLH = reinterpret_castperspectiveFovLH)>(GetProcAddress(this->m_module, "D3DXMatrixPerspectiveFovLH")); + this->saveSurfaceToFileA = reinterpret_castsaveSurfaceToFileA)>(GetProcAddress(this->m_module, "D3DXSaveSurfaceToFileA")); + + if (!this->filterTexture || !this->loadSurfaceFromMemory || !this->loadSurfaceFromSurface || !this->perspectiveFovLH || !this->saveSurfaceToFileA) { + FreeLibrary(this->m_module); + throw std::system_error(ERROR_PROC_NOT_FOUND, std::system_category(), "D3DX9_43 exports"); + } +} + +D3DX9Runtime::~D3DX9Runtime() { + FreeLibrary(this->m_module); +} diff --git a/Source/Render/D3DX9Runtime.h b/Source/Render/DX9/D3DX9Runtime.h similarity index 51% rename from Source/Render/D3DX9Runtime.h rename to Source/Render/DX9/D3DX9Runtime.h index 3ff4a70..825baa9 100644 --- a/Source/Render/D3DX9Runtime.h +++ b/Source/Render/DX9/D3DX9Runtime.h @@ -1,10 +1,8 @@ -#ifndef RAGNAROK_SOURCE_RENDER_D3DX9RUNTIME_H -#define RAGNAROK_SOURCE_RENDER_D3DX9RUNTIME_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_D3DX9RUNTIME_H +#define RAGNAROK_SOURCE_RENDER_DX9_D3DX9RUNTIME_H #include -// Host loader for the original external D3DX9_43 DLL. No original address: -// the reference imports these APIs statically; algorithms remain in the DLL. class D3DX9Runtime { public: D3DX9Runtime(); @@ -14,26 +12,10 @@ public: HRESULT(WINAPI* filterTexture)(IDirect3DBaseTexture9*, const PALETTEENTRY*, UINT, DWORD); HRESULT(WINAPI* loadSurfaceFromMemory)( - IDirect3DSurface9*, - const PALETTEENTRY*, - const RECT*, - const void*, - D3DFORMAT, - UINT, - const PALETTEENTRY*, - const RECT*, - DWORD, - D3DCOLOR + IDirect3DSurface9*, const PALETTEENTRY*, const RECT*, const void*, D3DFORMAT, UINT, const PALETTEENTRY*, const RECT*, DWORD, D3DCOLOR ); HRESULT(WINAPI* loadSurfaceFromSurface)( - IDirect3DSurface9*, - const PALETTEENTRY*, - const RECT*, - IDirect3DSurface9*, - const PALETTEENTRY*, - const RECT*, - DWORD, - D3DCOLOR + IDirect3DSurface9*, const PALETTEENTRY*, const RECT*, IDirect3DSurface9*, const PALETTEENTRY*, const RECT*, DWORD, D3DCOLOR ); D3DMATRIX*(WINAPI* perspectiveFovLH)(D3DMATRIX*, float, float, float, float); HRESULT(WINAPI* saveSurfaceToFileA)(const char*, int, IDirect3DSurface9*, const PALETTEENTRY*, const RECT*); diff --git a/Source/Render/DeviceOwnerDX9.cpp b/Source/Render/DX9/DeviceOwnerDX9.cpp similarity index 85% rename from Source/Render/DeviceOwnerDX9.cpp rename to Source/Render/DX9/DeviceOwnerDX9.cpp index ed59fe9..f15a7fa 100644 --- a/Source/Render/DeviceOwnerDX9.cpp +++ b/Source/Render/DX9/DeviceOwnerDX9.cpp @@ -1,4 +1,4 @@ -#include "Render/DeviceOwnerDX9.h" +#include "Render/DX9/DeviceOwnerDX9.h" #include @@ -24,10 +24,7 @@ DeviceOwnerDX9::DeviceOwnerDX9() { this->window = nullptr; this->direct3D = nullptr; this->device = nullptr; - std::memset( - &this->presentation, 0, - sizeof(this->presentation) + sizeof(this->displayMode) + sizeof(this->backBufferDescription) + sizeof(this->caps) - ); + std::memset(&this->presentation, 0, sizeof(this->presentation) + sizeof(this->displayMode) + sizeof(this->backBufferDescription) + sizeof(this->caps)); this->backBuffer = nullptr; this->capturedBackBuffer = nullptr; this->dynamicTextures = false; @@ -45,10 +42,8 @@ bool DisplayModeSelectorDX9::Select(D3DSCANLINEORDERING ordering) { D3DDISPLAYMODEEX mode{}; mode.Size = sizeof(mode); - if ( - SUCCEEDED(this->owner->direct3D->EnumAdapterModesEx(this->adapter, &filter, index, &mode)) && - mode.Width == this->width && mode.Height == this->height && mode.RefreshRate >= refresh - ) { + if (SUCCEEDED(this->owner->direct3D->EnumAdapterModesEx(this->adapter, &filter, index, &mode)) && mode.Width == this->width && + mode.Height == this->height && mode.RefreshRate >= refresh) { refresh = mode.RefreshRate; this->owner->displayMode = mode; } @@ -68,6 +63,7 @@ UINT* DeviceOwnerDX9::AdjustTextureDimensions(UINT* output, UINT width, UINT hei value |= value >> 8; value |= value >> 16; ++value; + return value + (value == 0); }; @@ -134,10 +130,7 @@ HRESULT DeviceOwnerDX9::CreateDevice(UINT selectedAdapter, const DeviceOptionsDX if (!this->presentation.Windowed) { const D3DFORMAT format = D3DFMT_X8R8G8B8; DisplayModeSelectorDX9 selectMode{format, this, selectedAdapter, width, height}; - if ( - !selectMode.Select(D3DSCANLINEORDERING_PROGRESSIVE) && - !selectMode.Select(D3DSCANLINEORDERING_INTERLACED) - ) { + if (!selectMode.Select(D3DSCANLINEORDERING_PROGRESSIVE) && !selectMode.Select(D3DSCANLINEORDERING_INTERLACED)) { D3DDISPLAYMODEEX mode{}; mode.Size = sizeof(mode); D3DDISPLAYROTATION rotation = D3DDISPLAYROTATION_IDENTITY; @@ -155,8 +148,8 @@ HRESULT DeviceOwnerDX9::CreateDevice(UINT selectedAdapter, const DeviceOptionsDX } result = this->direct3D->CreateDeviceEx( - selectedAdapter, D3DDEVTYPE_HAL, this->window, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, - &this->presentation, this->presentation.Windowed ? nullptr : &this->displayMode, &this->device + selectedAdapter, D3DDEVTYPE_HAL, this->window, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, &this->presentation, + this->presentation.Windowed ? nullptr : &this->displayMode, &this->device ); if (FAILED(result)) { @@ -187,7 +180,6 @@ HRESULT DeviceOwnerDX9::AcquireBackBuffer() { result = surface->GetDesc(&this->backBufferDescription); if (FAILED(result)) { - // Original does not release the acquired local surface on this failure. return result; } @@ -218,6 +210,7 @@ HRESULT DeviceOwnerDX9::Initialize(HWND value, UINT selectedAdapter, const Devic this->state.SetInitialStates(); this->dynamicTextures = (this->caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0 && options.dynamicTextures != 0; this->ClipFullscreenCursor(); + return D3D_OK; } @@ -277,17 +270,8 @@ SurfaceDX9Context DeviceOwnerDX9::SurfaceContext() const { } TextureDX9Context DeviceOwnerDX9::TextureContext( - D3DX9Runtime& d3dx, - RenderPrimitivePool& primitives, - RenderQueues& queues, - bool depthAlpha, - float depthStart, - float depthEnd + D3DX9Runtime& d3dx, RenderPrimitivePool& primitives, RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd ) const { - return {this->direct3D, this->device, - this->adapter, this->presentation.BackBufferFormat, - this->caps, this->dynamicTextures, - &d3dx, &primitives, - &queues, depthAlpha, - depthStart, depthEnd}; + return {this->direct3D, this->device, this->adapter, this->presentation.BackBufferFormat, this->caps, this->dynamicTextures, &d3dx, &primitives, &queues, + depthAlpha, depthStart, depthEnd}; } diff --git a/Source/Render/DeviceOwnerDX9.h b/Source/Render/DX9/DeviceOwnerDX9.h similarity index 65% rename from Source/Render/DeviceOwnerDX9.h rename to Source/Render/DX9/DeviceOwnerDX9.h index 6da7e4e..5838516 100644 --- a/Source/Render/DeviceOwnerDX9.h +++ b/Source/Render/DX9/DeviceOwnerDX9.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_RENDER_DEVICEOWNERDX9_H -#define RAGNAROK_SOURCE_RENDER_DEVICEOWNERDX9_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_DEVICEOWNERDX9_H +#define RAGNAROK_SOURCE_RENDER_DX9_DEVICEOWNERDX9_H -#include "Render/DeviceStateDX9.h" -#include "Render/SurfaceDX9.h" -#include "Render/TextureDX9.h" +#include "Render/DX9/DeviceStateDX9.h" +#include "Render/DX9/SurfaceDX9.h" +#include "Render/DX9/TextureDX9.h" -// Original renderer configuration globals, supplied by their configuration owner. struct DeviceOptionsDX9 { const int& fullscreen; const int& width; @@ -13,8 +12,6 @@ struct DeviceOptionsDX9 { const int& dynamicTextures; }; -// Original 0x690-byte DX9 device owner, distinct from CRenderSystemDX9. Context -// views borrow this owner and become invalid at Close. No original-code calls. class DeviceOwnerDX9 { public: DeviceOwnerDX9(); @@ -23,8 +20,7 @@ public: HRESULT Initialize(HWND window, UINT adapter, const DeviceOptionsDX9& options); HRESULT CreateDevice(UINT adapter, const DeviceOptionsDX9& options); HRESULT AcquireBackBuffer(); - // Returns output after power-of-two rounding, caps clamping, and integer - // aspect-ratio adjustment. Zero/overflowed requests round to one. + UINT* AdjustTextureDimensions(UINT* output, UINT width, UINT height) const; HRESULT Close(); HRESULT Present(int unused); @@ -35,14 +31,8 @@ public: bool CaptureBackBuffer(); bool RestoreBackBuffer(); SurfaceDX9Context SurfaceContext() const; - TextureDX9Context TextureContext( - D3DX9Runtime& d3dx, - class RenderPrimitivePool& primitives, - RenderQueues& queues, - bool depthAlpha, - float depthStart, - float depthEnd - ) const; + TextureDX9Context + TextureContext(D3DX9Runtime& d3dx, class RenderPrimitivePool& primitives, RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd) const; /* 0000 */ HWND window; /* 0004 */ IDirect3D9Ex* direct3D; diff --git a/Source/Render/DeviceRecoveryDX9.cpp b/Source/Render/DX9/DeviceRecoveryDX9.cpp similarity index 88% rename from Source/Render/DeviceRecoveryDX9.cpp rename to Source/Render/DX9/DeviceRecoveryDX9.cpp index 5ee4811..f93f988 100644 --- a/Source/Render/DeviceRecoveryDX9.cpp +++ b/Source/Render/DX9/DeviceRecoveryDX9.cpp @@ -1,5 +1,5 @@ -#include "Client/ErrorDialog.h" -#include "Render/DeviceOwnerDX9.h" +#include "Client/Application/ErrorDialog.h" +#include "Render/DX9/DeviceOwnerDX9.h" #include "Render/Direct3DErrors.h" #include @@ -37,13 +37,13 @@ HRESULT DeviceOwnerDX9::CheckState(CRenderSystemBase* renderSystem) { return invalidDevice; } - result = - this->device->ResetEx(&this->presentation, this->presentation.Windowed == 1 ? nullptr : &this->displayMode); + result = this->device->ResetEx(&this->presentation, this->presentation.Windowed == 1 ? nullptr : &this->displayMode); } else if (FAILED(result) && lastReported != result) { const std::string message = std::string(Direct3DErrorName(result)) + " : " + Direct3DErrorDescription(result); ShowErrorDialog(renderSystem, message.c_str(), 0); lastReported = result; this->lastPresent = result; + return result; } diff --git a/Source/Render/DeviceStateDX9.cpp b/Source/Render/DX9/DeviceStateDX9.cpp similarity index 95% rename from Source/Render/DeviceStateDX9.cpp rename to Source/Render/DX9/DeviceStateDX9.cpp index 472a1e0..23237ad 100644 --- a/Source/Render/DeviceStateDX9.cpp +++ b/Source/Render/DX9/DeviceStateDX9.cpp @@ -1,4 +1,4 @@ -#include "Render/DeviceStateDX9.h" +#include "Render/DX9/DeviceStateDX9.h" #include @@ -17,12 +17,14 @@ DeviceStateDX9::DeviceStateDX9() : device(nullptr), fvf(0) { void DeviceStateDX9::Initialize(IDirect3DDevice9* value) { this->device = value; value->GetFVF(&this->fvf); + for (unsigned state = 0; state < 210; ++state) { DWORD result; if (SUCCEEDED(value->GetRenderState(static_cast(state), &result))) { this->render[state] = result; } } + for (unsigned stage = 0; stage < 2; ++stage) { for (unsigned state = 0; state < 33; ++state) { DWORD result; @@ -30,6 +32,7 @@ void DeviceStateDX9::Initialize(IDirect3DDevice9* value) { this->textureStage[stage][state] = result; } } + for (unsigned state = 0; state < 14; ++state) { DWORD result; if (SUCCEEDED(value->GetSamplerState(stage, static_cast(state), &result))) { @@ -47,10 +50,11 @@ void DeviceStateDX9::SetInitialStates() { this->SetRenderState(D3DRS_ALPHATESTENABLE, 1); this->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); this->SetRenderState(D3DRS_ALPHAREF, 240); - this->SetRenderState(D3DRS_ZENABLE, 1); + this->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); this->SetRenderState(D3DRS_ZWRITEENABLE, 1); this->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); this->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + this->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); this->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); this->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); @@ -63,6 +67,7 @@ void DeviceStateDX9::SetInitialStates() { this->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); this->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); this->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + this->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); this->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); this->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); @@ -97,13 +102,16 @@ HRESULT DeviceStateDX9::SetFVF(DWORD value) { if (!this->device) { return noDevice; } + if (this->fvf == value) { return D3D_OK; } + HRESULT result = this->device->SetFVF(value); if (SUCCEEDED(result)) { this->fvf = value; } + return result; } @@ -113,13 +121,16 @@ HRESULT DeviceStateDX9::SetRenderState(D3DRENDERSTATETYPE state, DWORD value) { if (!this->device) { return noDevice; } + if (this->render[state] == value) { return D3D_OK; } + HRESULT result = this->device->SetRenderState(state, value); if (SUCCEEDED(result)) { this->render[state] = value; } + return result; } @@ -129,16 +140,20 @@ HRESULT DeviceStateDX9::SetSamplerState(UINT stage, D3DSAMPLERSTATETYPE state, D if (!this->device) { return noDevice; } + if (stage >= 2) { return D3DERR_INVALIDCALL; } + if (this->sampler[stage][state] == value) { return D3D_OK; } + HRESULT result = this->device->SetSamplerState(stage, state, value); if (SUCCEEDED(result)) { this->sampler[stage][state] = value; } + return result; } @@ -148,16 +163,20 @@ HRESULT DeviceStateDX9::SetTexture(UINT stage, IDirect3DBaseTexture9* texture) { if (!this->device) { return noDevice; } + if (stage >= 2) { return D3DERR_INVALIDCALL; } + if (this->textures[stage] == texture) { return D3D_OK; } + HRESULT result = this->device->SetTexture(stage, texture); if (SUCCEEDED(result)) { this->textures[stage] = texture; } + return result; } @@ -167,16 +186,20 @@ HRESULT DeviceStateDX9::SetTextureStageState(UINT stage, D3DTEXTURESTAGESTATETYP if (!this->device) { return noDevice; } + if (stage >= 2) { return D3DERR_INVALIDCALL; } + if (this->textureStage[stage][state] == value) { return D3D_OK; } + HRESULT result = this->device->SetTextureStageState(stage, state, value); if (SUCCEEDED(result)) { this->textureStage[stage][state] = value; } + return result; } @@ -191,20 +214,19 @@ ScopedDeviceStateDX9::ScopedDeviceStateDX9(DeviceStateDX9& state) : m_state(&sta // OFFSET: 0x005516A0 // FUNCTION: fn_01998 ScopedDeviceStateDX9::~ScopedDeviceStateDX9() { - // Original restore loop covers render indices0..209, but not FVF/textures. for (unsigned state = 0; state < 210; ++state) { if (this->m_render[state] != this->m_state->render[state] && this->m_state->device) { this->m_state->SetRenderState(static_cast(state), this->m_render[state]); } } + for (unsigned stage = 0; stage < 2; ++stage) { for (unsigned state = 0; state < 33; ++state) { if (this->m_textureStage[stage][state] != this->m_state->textureStage[stage][state] && this->m_state->device) { - this->m_state->SetTextureStageState( - stage, static_cast(state), this->m_textureStage[stage][state] - ); + this->m_state->SetTextureStageState(stage, static_cast(state), this->m_textureStage[stage][state]); } } + for (unsigned state = 0; state < 14; ++state) { if (this->m_sampler[stage][state] != this->m_state->sampler[stage][state] && this->m_state->device) { this->m_state->SetSamplerState(stage, static_cast(state), this->m_sampler[stage][state]); diff --git a/Source/Render/DeviceStateDX9.h b/Source/Render/DX9/DeviceStateDX9.h similarity index 87% rename from Source/Render/DeviceStateDX9.h rename to Source/Render/DX9/DeviceStateDX9.h index 927bb64..c59eeec 100644 --- a/Source/Render/DeviceStateDX9.h +++ b/Source/Render/DX9/DeviceStateDX9.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_RENDER_DEVICESTATEDX9_H -#define RAGNAROK_SOURCE_RENDER_DEVICESTATEDX9_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_DEVICESTATEDX9_H +#define RAGNAROK_SOURCE_RENDER_DX9_DEVICESTATEDX9_H #include -// Contiguous original device-owner subobject+12, borrowed device/textures. struct DeviceStateDX9 { IDirect3DDevice9* device; DWORD fvf; diff --git a/Source/Render/GroundQueuesDX9.cpp b/Source/Render/DX9/GroundQueuesDX9.cpp similarity index 72% rename from Source/Render/GroundQueuesDX9.cpp rename to Source/Render/DX9/GroundQueuesDX9.cpp index d189205..12ec63a 100644 --- a/Source/Render/GroundQueuesDX9.cpp +++ b/Source/Render/DX9/GroundQueuesDX9.cpp @@ -1,8 +1,8 @@ -#include "Contents/ServiceOptions.h" -#include "Render/DeviceStateDX9.h" -#include "Render/RenderQueues.h" -#include "Render/RendererDX9Operations.h" -#include "Render/TextureDX9.h" +#include "Contents/Configuration/ServiceOptions.h" +#include "Render/DX9/DeviceStateDX9.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/DX9/RendererDX9Operations.h" +#include "Render/DX9/TextureDX9.h" #include #include @@ -20,9 +20,7 @@ namespace { std::sort(queue.begin(), queue.end(), TextureBefore); for (RenderCommand* command : queue) { - renderer.state.SetTexture( - 0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr - ); + renderer.state.SetTexture(0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr); renderer.DrawPrimitive(command); } } @@ -30,11 +28,7 @@ namespace { // OFFSET: 0x005668B0 // FUNCTION: fn_02226 -void RendererDX9Operations::DrawGroundQueues( - RenderQueues& queues, - const ServiceOptions& options, - unsigned char multitexture -) { +void RendererDX9Operations::DrawGroundQueues(RenderQueues& queues, const ServiceOptions& options, unsigned char multitexture) { ScopedDeviceStateDX9 restore(this->state); this->state.SetRenderState(D3DRS_COLORWRITEENABLE, 0xFFFFFFFFu); this->state.SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); @@ -56,13 +50,9 @@ void RendererDX9Operations::DrawGroundQueues( }); for (LightmappedPrimitive* command : queue) { - if (std::bit_cast(command->vertexCount) > 0) { - this->state.SetTexture( - 0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr - ); - this->state.SetTexture( - 1, command->lightmap ? static_cast(command->lightmap)->NativeTexture() : nullptr - ); + if (command->vertexCount > 0) { + this->state.SetTexture(0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr); + this->state.SetTexture(1, command->lightmap ? static_cast(command->lightmap)->NativeTexture() : nullptr); this->DrawLightmappedPrimitive(command); } } @@ -80,9 +70,7 @@ void RendererDX9Operations::DrawGroundQueues( std::sort(queues.queue_0174.begin(), queues.queue_0174.end(), TextureBefore); for (RenderCommand* command : queues.queue_0174) { - this->state.SetTexture( - 0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr - ); + this->state.SetTexture(0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr); this->DrawPrimitive(command); } } diff --git a/Source/Render/OpaqueQueuesDX9.cpp b/Source/Render/DX9/OpaqueQueuesDX9.cpp similarity index 71% rename from Source/Render/OpaqueQueuesDX9.cpp rename to Source/Render/DX9/OpaqueQueuesDX9.cpp index eef17ca..c343e27 100644 --- a/Source/Render/OpaqueQueuesDX9.cpp +++ b/Source/Render/DX9/OpaqueQueuesDX9.cpp @@ -1,7 +1,7 @@ -#include "Render/DeviceStateDX9.h" -#include "Render/RenderQueues.h" -#include "Render/RendererDX9Operations.h" -#include "Render/TextureDX9.h" +#include "Render/DX9/DeviceStateDX9.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/DX9/RendererDX9Operations.h" +#include "Render/DX9/TextureDX9.h" #include #include @@ -19,9 +19,7 @@ void RendererDX9Operations::DrawOpaqueQueues(RenderQueues& queues) { for (RenderCommand* command : queues.queue_015C) { if (command) { - this->state.SetTexture( - 0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr - ); + this->state.SetTexture(0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr); this->DrawPrimitive(command); } } @@ -32,9 +30,7 @@ void RendererDX9Operations::DrawOpaqueQueues(RenderQueues& queues) { for (RenderCommand* command : queues.queue_01B0) { if (command) { - this->state.SetTexture( - 0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr - ); + this->state.SetTexture(0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr); this->DrawPrimitive(command); } } diff --git a/Source/Render/QueuedDrawingDX9.cpp b/Source/Render/DX9/QueuedDrawingDX9.cpp similarity index 80% rename from Source/Render/QueuedDrawingDX9.cpp rename to Source/Render/DX9/QueuedDrawingDX9.cpp index a8165a6..8ce1221 100644 --- a/Source/Render/QueuedDrawingDX9.cpp +++ b/Source/Render/DX9/QueuedDrawingDX9.cpp @@ -1,8 +1,8 @@ -#include "Render/DeviceStateDX9.h" -#include "Render/RenderQueues.h" -#include "Render/RendererDX9Operations.h" -#include "Render/RendererFogDX9.h" -#include "Render/TextureDX9.h" +#include "Render/DX9/DeviceStateDX9.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/DX9/RendererDX9Operations.h" +#include "Render/DX9/RendererFogDX9.h" +#include "Render/DX9/TextureDX9.h" #include #include @@ -44,13 +44,9 @@ void RendererDX9Operations::DrawAuxiliaryQueue(RenderQueues& queues) { this->state.SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); for (LightmappedPrimitive* command : queue) { - if (std::bit_cast(command->vertexCount) > 0) { - this->state.SetTexture( - 0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr - ); - this->state.SetTexture( - 1, command->lightmap ? static_cast(command->lightmap)->NativeTexture() : nullptr - ); + if (command->vertexCount > 0) { + this->state.SetTexture(0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr); + this->state.SetTexture(1, command->lightmap ? static_cast(command->lightmap)->NativeTexture() : nullptr); this->DrawLightmappedPrimitive(command); } } @@ -59,22 +55,19 @@ void RendererDX9Operations::DrawAuxiliaryQueue(RenderQueues& queues) { // OFFSET: 0x00567610 // FUNCTION: fn_02229 void RendererDX9Operations::DrawQueues( - RenderQueues& queues, - const ServiceOptions& options, - unsigned char multitexture, - unsigned char twoPass, - RendererFogDX9& fog, - const float& aspect, + RenderQueues& queues, const ServiceOptions& options, unsigned char multitexture, unsigned char twoPass, RendererFogDX9& fog, const float& aspect, const FogConfiguration& configuration ) { fog.Apply(this->context, this->state, *this->context.d3dx, aspect, configuration); this->state.SetRenderState(D3DRS_ALPHATESTENABLE, 1); this->state.SetRenderState(D3DRS_ALPHAREF, 207); this->state.SetRenderState(D3DRS_ALPHABLENDENABLE, 0); - this->state.SetRenderState(D3DRS_ZENABLE, 1); + this->state.SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); this->state.SetRenderState(D3DRS_ZWRITEENABLE, 1); + this->DrawOpaqueQueues(queues); this->DrawGroundQueues(queues, options, multitexture); + this->state.SetRenderState(D3DRS_ALPHAREF, 1); this->state.SetRenderState(D3DRS_ALPHABLENDENABLE, 1); this->DrawAuxiliaryQueue(queues); @@ -101,26 +94,23 @@ void RendererDX9Operations::DrawQueues( { ScopedDeviceStateDX9 restore(this->state); - this->state.SetRenderState(D3DRS_ZENABLE, 0); + this->state.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); this->DrawDepthQueue(queues.queue_021C, true); } { ScopedDeviceStateDX9 restore(this->state); - std::sort( - queues.queue_0180.begin(), queues.queue_0180.end(), [](const DepthPrimitive& left, const DepthPrimitive& right) { - if (left.depth < right.depth) { - return true; - } - - if (right.depth < left.depth) { - return false; - } - - return left.depth == right.depth && - reinterpret_cast(left.primitive) < reinterpret_cast(right.primitive); + std::sort(queues.queue_0180.begin(), queues.queue_0180.end(), [](const DepthPrimitive& left, const DepthPrimitive& right) { + if (left.depth < right.depth) { + return true; } - ); + + if (right.depth < left.depth) { + return false; + } + + return left.depth == right.depth && reinterpret_cast(left.primitive) < reinterpret_cast(right.primitive); + }); this->state.SetRenderState(D3DRS_ALPHATESTENABLE, 1); this->state.SetRenderState(D3DRS_ZWRITEENABLE, 1); this->state.SetRenderState(D3DRS_ALPHAREF, 159); @@ -169,7 +159,7 @@ void RendererDX9Operations::DrawQueues( } } - this->state.SetRenderState(D3DRS_ZENABLE, 0); + this->state.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); { ScopedDeviceStateDX9 restore(this->state); @@ -190,11 +180,9 @@ void RendererDX9Operations::DrawQueues( for (const DepthPrimitive& entry : queues.queue_0234) { RenderCommand& command = *entry.primitive; - this->state.SetTexture( - 0, command.texture ? static_cast(command.texture)->NativeTexture() : nullptr - ); + this->state.SetTexture(0, command.texture ? static_cast(command.texture)->NativeTexture() : nullptr); this->SetTextureMode(command.unknown_0020); - // COMISS/JB selects command blend factors for unordered depths too. + const bool selected = !(entry.depth >= 0.99f); this->state.SetRenderState(D3DRS_SRCBLEND, selected ? command.unknown_0018 : D3DBLEND_SRCALPHA); this->state.SetRenderState(D3DRS_DESTBLEND, selected ? command.unknown_001C : D3DBLEND_INVSRCALPHA); diff --git a/Source/Render/RenderSystemDX9.cpp b/Source/Render/DX9/RenderSystemDX9.cpp similarity index 75% rename from Source/Render/RenderSystemDX9.cpp rename to Source/Render/DX9/RenderSystemDX9.cpp index bc0cabf..389e1c7 100644 --- a/Source/Render/RenderSystemDX9.cpp +++ b/Source/Render/DX9/RenderSystemDX9.cpp @@ -1,4 +1,4 @@ -#include "Render/RenderSystemDX9.h" +#include "Render/DX9/RenderSystemDX9.h" #include #include @@ -7,19 +7,8 @@ // FUNCTION: fn_02353 CRenderSystemDX9::CRenderSystemDX9(RenderSystemDX9Context& context) : m_device(new DeviceOwnerDX9), m_defaultTexture(nullptr), m_context(&context), - m_rendererContext{ - *this, - context.d3dx, - context.textures, - context.sources, - context.retirement, - context.options, - context.multitexture, - context.fog, - context.worldFlag, - context.overlayColor, - context.diagnostic - }, + m_rendererContext{*this, context.d3dx, context.textures, context.sources, context.retirement, context.options, context.multitexture, + context.fog, context.worldFlag, context.overlayColor, context.diagnostic}, m_textureContext{}, m_surfaceContext{} { this->RefreshContexts(); } @@ -55,9 +44,8 @@ std::int32_t CRenderSystemDX9::Backend() { } HRESULT CRenderSystemDX9::Initialize(HWND window) { - const HRESULT result = InitializeConfiguredDeviceDX9( - *this->m_device, window, this->m_context->deviceOptions, this->m_context->adapter, this->m_context->serviceUsesDX7 - ); + const HRESULT result = + InitializeConfiguredDeviceDX9(*this->m_device, window, this->m_context->deviceOptions, this->m_context->adapter, this->m_context->serviceUsesDX7); this->RefreshContexts(); return result; } @@ -69,6 +57,7 @@ HRESULT CRenderSystemDX9::Close() { this->m_defaultTexture = nullptr; delete texture; this->m_backBuffer.reset(); + return this->m_device->Close(); } @@ -95,11 +84,12 @@ std::uint32_t CRenderSystemDX9::Height() { CRenderer* CRenderSystemDX9::CreateRenderer() { auto* renderer = new CRendererDX9(*this->m_device, this->m_rendererContext); renderer->viewport.SetSize( - std::bit_cast(this->Width()), std::bit_cast(this->Height()), - this->m_context->projectionScale, this->m_context->heightScale, this->m_context->tangent, this->m_context->cotangent + std::bit_cast(this->Width()), std::bit_cast(this->Height()), this->m_context->projectionScale, this->m_context->heightScale, + this->m_context->tangent, this->m_context->cotangent ); this->m_textureContext.primitives = &renderer->primitives; this->m_textureContext.queues = &renderer->queues; + return renderer; } @@ -113,24 +103,15 @@ void CRenderSystemDX9::DestroySurface(CSurface* surface) { // FUNCTION: fn_02360 CSurface* CRenderSystemDX9::CreateSurface(std::uint32_t width, std::uint32_t height) { this->RefreshContexts(); - return new (std::nothrow) - CSurfaceDX9(this->m_surfaceContext, std::bit_cast(width), std::bit_cast(height)); + return new (std::nothrow) CSurfaceDX9(this->m_surfaceContext, std::bit_cast(width), std::bit_cast(height)); } // OFFSET: 0x0056D510 // FUNCTION: fn_02361 -CTexture* CRenderSystemDX9::CreateTexture( - std::uint32_t width, - std::uint32_t height, - std::int32_t format, - bool dynamic, - bool renderTarget -) { +CTexture* CRenderSystemDX9::CreateTexture(std::uint32_t width, std::uint32_t height, std::int32_t format, bool dynamic, bool renderTarget) { this->RefreshContexts(); - return new (std::nothrow) CTextureDX9( - this->m_textureContext, std::bit_cast(width), std::bit_cast(height), format, dynamic, - renderTarget - ); + return new (std::nothrow) + CTextureDX9(this->m_textureContext, std::bit_cast(width), std::bit_cast(height), format, dynamic, renderTarget); } // OFFSET: 0x0056D5B0 @@ -140,7 +121,7 @@ CSurface* CRenderSystemDX9::CreateSurfaceOrTexture(std::uint32_t width, std::uin return this->CreateSurface(width, height); } - return this->CreateTexture(width, height, 0, false, false); + return this->CreateTexture(width, height, TextureFormat::A1R5G5B5, false, false); } // OFFSET: 0x0056DAC0 @@ -168,8 +149,7 @@ std::shared_ptr CRenderSystemDX9::BackBufferSurface() { // OFFSET: 0x0056D740 // FUNCTION: fn_02365 void CRenderSystemDX9::UpdateOption() { - this->m_device->dynamicTextures = - (this->m_device->caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0 && this->m_context->deviceOptions.dynamicTextures != 0; + this->m_device->dynamicTextures = (this->m_device->caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0 && this->m_context->deviceOptions.dynamicTextures != 0; } // OFFSET: 0x0056D760 diff --git a/Source/Render/RenderSystemDX9.h b/Source/Render/DX9/RenderSystemDX9.h similarity index 79% rename from Source/Render/RenderSystemDX9.h rename to Source/Render/DX9/RenderSystemDX9.h index 3438531..6c27754 100644 --- a/Source/Render/RenderSystemDX9.h +++ b/Source/Render/DX9/RenderSystemDX9.h @@ -1,10 +1,10 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERSYSTEMDX9_H -#define RAGNAROK_SOURCE_RENDER_RENDERSYSTEMDX9_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_RENDERSYSTEMDX9_H +#define RAGNAROK_SOURCE_RENDER_DX9_RENDERSYSTEMDX9_H -#include "Render/DeviceOwnerDX9.h" +#include "Render/DX9/DeviceOwnerDX9.h" #include "Render/RenderAdapter.h" #include "Render/RenderSystemBase.h" -#include "Render/RendererDX9.h" +#include "Render/DX9/RendererDX9.h" struct RenderSystemDX9Context { const DeviceOptionsDX9& deviceOptions; @@ -26,8 +26,6 @@ struct RenderSystemDX9Context { float& cotangent; }; -// RTTI CRenderSystemDX9. Close is caller-controlled; -// destruction does not implicitly close the Direct3D device. class CRenderSystemDX9 : public CRenderSystemBase { public: explicit CRenderSystemDX9(RenderSystemDX9Context& context); @@ -41,13 +39,7 @@ public: CRenderer* CreateRenderer() override; void DestroySurface(CSurface* surface) override; CSurface* CreateSurface(std::uint32_t width, std::uint32_t height) override; - CTexture* CreateTexture( - std::uint32_t width, - std::uint32_t height, - std::int32_t format, - bool dynamic, - bool renderTarget - ) override; + CTexture* CreateTexture(std::uint32_t width, std::uint32_t height, std::int32_t format, bool dynamic, bool renderTarget) override; CSurface* CreateSurfaceOrTexture(std::uint32_t width, std::uint32_t height) override; CTexture* BackBufferTexture() override; std::shared_ptr BackBufferSurface() override; @@ -65,7 +57,7 @@ private: /* 0004 */ DeviceOwnerDX9* m_device; /* 0008 */ CTexture* m_defaultTexture; /* 000C */ std::shared_ptr m_backBuffer; - // Host dependency views follow the original 20-byte prefix. + RenderSystemDX9Context* m_context; RendererDX9Context m_rendererContext; TextureDX9Context m_textureContext; diff --git a/Source/Render/RendererBackBuffer.cpp b/Source/Render/DX9/RendererBackBuffer.cpp similarity index 91% rename from Source/Render/RendererBackBuffer.cpp rename to Source/Render/DX9/RendererBackBuffer.cpp index a7e094a..f88c04f 100644 --- a/Source/Render/RendererBackBuffer.cpp +++ b/Source/Render/DX9/RendererBackBuffer.cpp @@ -1,5 +1,5 @@ -#include "Render/DeviceOwnerDX9.h" -#include "Render/RendererDX9.h" +#include "Render/DX9/DeviceOwnerDX9.h" +#include "Render/DX9/RendererDX9.h" // OFFSET: 0x00567E80 // FUNCTION: fn_02232 diff --git a/Source/Render/RendererDX9.cpp b/Source/Render/DX9/RendererDX9.cpp similarity index 74% rename from Source/Render/RendererDX9.cpp rename to Source/Render/DX9/RendererDX9.cpp index b392226..00bedba 100644 --- a/Source/Render/RendererDX9.cpp +++ b/Source/Render/DX9/RendererDX9.cpp @@ -1,18 +1,15 @@ -#include "Render/DeviceOwnerDX9.h" -#include "Render/RendererDX9.h" -#include "Render/RendererFrameDX9.h" -#include "Render/TextureCache.h" -#include "Resource/BitmapResource.h" +#include "Render/DX9/DeviceOwnerDX9.h" +#include "Render/DX9/RendererDX9.h" +#include "Render/DX9/RendererFrameDX9.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/Bitmap/BitmapResource.h" #include // OFFSET: 0x00564EB0 CRendererDX9::CRendererDX9(DeviceOwnerDX9& owner, RendererDX9Context& context) - : CRenderer(context.system), device(&owner), nativeDevice(owner.device), clearColor(0), lastTick(0), frames(0), - fps(0.0f), m_context(&context), - m_textureContext( - owner.TextureContext(context.d3dx, this->primitives, this->queues, false, context.fog.start, context.fog.end) - ) { + : CRenderer(context.system), device(&owner), nativeDevice(owner.device), clearColor(0), lastTick(0), frames(0), fps(0.0f), m_context(&context), + m_textureContext(owner.TextureContext(context.d3dx, this->primitives, this->queues, false, context.fog.start, context.fog.end)) { } // OFFSET: 0x00564FE0 @@ -25,12 +22,11 @@ TextureDX9Context& CRendererDX9::TextureContext() { this->m_textureContext.depthAlpha = this->fog.supported != 0; this->m_textureContext.depthStart = this->m_context->fog.start; this->m_textureContext.depthEnd = this->m_context->fog.end; + return this->m_textureContext; } RendererDX9Operations CRendererDX9::Operations(TextureDX9Context& context) { - // The renderer snapshots its device at construction; the owner retains the - // state-cache/device lifecycle used by scoped writes and frame transitions. context.device = this->nativeDevice; return {context, this->device->state}; } @@ -62,9 +58,7 @@ void CRendererDX9::ClearDepth(int clearColor) { void CRendererDX9::ClearWorld() { auto& context = this->TextureContext(); - this->Operations(context).ClearWorld( - this->clearColor, this->fog.enabled, this->m_context->worldFlag, this->m_context->overlayColor - ); + this->Operations(context).ClearWorld(this->clearColor, this->fog.enabled, this->m_context->worldFlag, this->m_context->overlayColor); } bool CRendererDX9::Draw() { @@ -72,9 +66,9 @@ bool CRendererDX9::Draw() { auto operations = this->Operations(context); RendererFrameDX9 frame{*this->device, operations, this->commands, this->primitives, this->lightmapped, this->vertices, this->queues, this->m_context->retirement}; + return frame.Draw( - &this->m_context->system, this->m_context->options, this->m_context->multitexture, this->twoPass, this->fog, - this->viewport.aspect, this->m_context->fog + &this->m_context->system, this->m_context->options, this->m_context->multitexture, this->twoPass, this->fog, this->viewport.aspect, this->m_context->fog ); } @@ -114,12 +108,7 @@ void CRendererDX9::DrawPrimitive(RenderCommand* primitive) { this->Operations(context).DrawPrimitive(primitive); } -bool CRendererDX9::RenderToTexture( - int width, - int height, - const std::list& primitives, - CTexture*& texture -) { +bool CRendererDX9::RenderToTexture(int width, int height, const std::list& primitives, CTexture*& texture) { auto& context = this->TextureContext(); return this->Operations(context).RenderToTexture(width, height, primitives, texture); } @@ -129,15 +118,11 @@ bool CRendererDX9::SaveBitmapResource(const char* filename, int format, CBitmapR if (bitmap) { const auto& image = bitmap->image; - overlay.reset(this->m_context->textures.Upload( - image.width, image.height, image.pixels, image.alpha != 0, 0, false, false, false - )); + overlay.reset(this->m_context->textures.Upload(image.width, image.height, image.pixels, image.alpha != 0, 0, false, false, false)); } auto& context = this->TextureContext(); - return this->Operations(context).SaveScreenshot( - *this->device, &this->m_context->system, filename, format, overlay.get(), nullptr - ); + return this->Operations(context).SaveScreenshot(*this->device, &this->m_context->system, filename, format, overlay.get(), nullptr); } // OFFSET: 0x00567FC0 @@ -163,9 +148,8 @@ bool CRendererDX9::SaveLogo(std::string filename) { const char* name = this->m_context->sources.Resolve("scr_logo.bmp"); CTexture* overlay = this->m_context->textures.Load(name, 0, false, true, false); auto& context = this->TextureContext(); - return this->Operations(context).SaveScreenshot( - *this->device, &this->m_context->system, filename.c_str(), 1, overlay, nullptr - ); + + return this->Operations(context).SaveScreenshot(*this->device, &this->m_context->system, filename.c_str(), 1, overlay, nullptr); } void CRendererDX9::Submit(RenderCommand* command, std::uint16_t flags) { @@ -173,7 +157,5 @@ void CRendererDX9::Submit(RenderCommand* command, std::uint16_t flags) { } void CRendererDX9::Submit(LightmappedPrimitive* command, int queue) { - this->queues.lightmapped.Submit( - command, queue, this->fog.supported != 0, this->m_context->fog.start, this->m_context->fog.end - ); + this->queues.lightmapped.Submit(command, queue, this->fog.supported != 0, this->m_context->fog.start, this->m_context->fog.end); } diff --git a/Source/Render/RendererDX9.h b/Source/Render/DX9/RendererDX9.h similarity index 81% rename from Source/Render/RendererDX9.h rename to Source/Render/DX9/RendererDX9.h index e9c0335..c4ea54b 100644 --- a/Source/Render/RendererDX9.h +++ b/Source/Render/DX9/RendererDX9.h @@ -1,10 +1,10 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERERDX9_H -#define RAGNAROK_SOURCE_RENDER_RENDERERDX9_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_RENDERERDX9_H +#define RAGNAROK_SOURCE_RENDER_DX9_RENDERERDX9_H #include "Render/Renderer.h" -#include "Render/RendererDX9Operations.h" -#include "Render/RendererPresentation.h" -#include "Render/TextureDX9.h" +#include "Render/DX9/RendererDX9Operations.h" +#include "Render/DX9/RendererPresentation.h" +#include "Render/DX9/TextureDX9.h" class DeviceOwnerDX9; class D3DX9Runtime; @@ -13,7 +13,6 @@ class TextureSources; struct EffectRetirement; struct ServiceOptions; -// Original shared configuration/manager dependencies, not per-renderer copies. struct RendererDX9Context { CRenderSystemBase& system; D3DX9Runtime& d3dx; @@ -28,8 +27,6 @@ struct RendererDX9Context { RenderDiagnostic& diagnostic; }; -// RTTI CRendererDX9. Borrowed dependencies and a -// stable texture context follow the original 0x274-byte prefix as host fields. class CRendererDX9 : public CRenderer { public: CRendererDX9(DeviceOwnerDX9& device, RendererDX9Context& context); @@ -48,8 +45,7 @@ public: void DrawAuxiliaryPrimitive(LightmappedPrimitive* primitive) override; void DrawLightmappedPrimitive(LightmappedPrimitive* primitive) override; void DrawPrimitive(RenderCommand* primitive) override; - bool - RenderToTexture(int width, int height, const std::list& primitives, CTexture*& texture) override; + bool RenderToTexture(int width, int height, const std::list& primitives, CTexture*& texture) override; bool SaveBitmap(const char* filename, CBitmapRes* overlay) override; bool SaveJpeg(const char* filename, CBitmapRes* overlay) override; void CleanupTextures() override; diff --git a/Source/Render/RendererDX9Operations.cpp b/Source/Render/DX9/RendererDX9Operations.cpp similarity index 65% rename from Source/Render/RendererDX9Operations.cpp rename to Source/Render/DX9/RendererDX9Operations.cpp index 91ceb7e..4c16fa5 100644 --- a/Source/Render/RendererDX9Operations.cpp +++ b/Source/Render/DX9/RendererDX9Operations.cpp @@ -1,10 +1,10 @@ #include "Render/BlendColor.h" -#include "Render/DeviceStateDX9.h" -#include "Render/LightmappedPrimitive.h" -#include "Render/RenderPrimitive.h" -#include "Render/RenderQueues.h" -#include "Render/RendererDX9Operations.h" -#include "Render/TextureDX9.h" +#include "Render/DX9/DeviceStateDX9.h" +#include "Render/Primitives/LightmappedPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/DX9/RendererDX9Operations.h" +#include "Render/DX9/TextureDX9.h" #include #include @@ -32,6 +32,7 @@ void RendererDX9Operations::SetLighting(const float* direction, const float* dif light.Ambient.g = ambient[1]; light.Ambient.b = ambient[2]; light.Ambient.a = 255.0f; + this->context.device->SetLight(0, &light); this->context.device->LightEnable(0, TRUE); } @@ -39,9 +40,7 @@ void RendererDX9Operations::SetLighting(const float* direction, const float* dif // OFFSET: 0x00565150 // FUNCTION: fn_02214 void RendererDX9Operations::ClearDepth(int clearColor) { - this->context.device->Clear( - 0, nullptr, clearColor ? D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER : D3DCLEAR_ZBUFFER, 0xFF000000u, 1.0f, 0 - ); + this->context.device->Clear(0, nullptr, clearColor ? D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER : D3DCLEAR_ZBUFFER, 0xFF000000u, 1.0f, 0); } // OFFSET: 0x005651A0 @@ -57,44 +56,40 @@ void RendererDX9Operations::ClearWorld(unsigned color, int mode, unsigned char w // OFFSET: 0x00565740 // FUNCTION: fn_02218 void RendererDX9Operations::DrawPrimitive(RenderCommand* primitive) { - if (std::bit_cast(primitive->vertexCount) <= 0) { + if (primitive->vertexCount <= 0) { return; } - this->state.SetFVF(452); + + this->state.SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1); const auto type = static_cast(primitive->primitiveType); - const unsigned divisor = primitive->primitiveType == 4 ? 3 : 2; + const unsigned divisor = type == D3DPT_TRIANGLELIST ? 3 : 2; + if (primitive->indexCount) { this->context.device->DrawIndexedPrimitiveUP( - type, 0, primitive->vertexCount, primitive->indexCount / divisor, primitive->indices, D3DFMT_INDEX16, - primitive->vertices, sizeof(RenderVertex) + type, 0, primitive->vertexCount, primitive->indexCount / divisor, primitive->indices, D3DFMT_INDEX16, primitive->vertices, sizeof(RenderVertex) ); } else { - this->context.device->DrawPrimitiveUP( - type, primitive->vertexCount / divisor, primitive->vertices, sizeof(RenderVertex) - ); + this->context.device->DrawPrimitiveUP(type, primitive->vertexCount / divisor, primitive->vertices, sizeof(RenderVertex)); } } // OFFSET: 0x005657D0 // FUNCTION: fn_02219 void RendererDX9Operations::DrawLightmappedPrimitive(LightmappedPrimitive* primitive) { - if (std::bit_cast(primitive->vertexCount) <= 0) { + if (primitive->vertexCount <= 0) { return; } - this->state.SetFVF(708); + this->state.SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2); const auto type = static_cast(primitive->primitiveType); - const unsigned divisor = primitive->primitiveType == 4 ? 3 : 2; + const unsigned divisor = type == D3DPT_TRIANGLELIST ? 3 : 2; if (primitive->indexCount) { this->context.device->DrawIndexedPrimitiveUP( - type, 0, primitive->vertexCount, primitive->indexCount / divisor, primitive->indices, D3DFMT_INDEX16, - primitive->vertices, sizeof(LightmappedVertex) + type, 0, primitive->vertexCount, primitive->indexCount / divisor, primitive->indices, D3DFMT_INDEX16, primitive->vertices, sizeof(LightmappedVertex) ); } else { - this->context.device->DrawPrimitiveUP( - type, primitive->vertexCount / divisor, primitive->vertices, sizeof(LightmappedVertex) - ); + this->context.device->DrawPrimitiveUP(type, primitive->vertexCount / divisor, primitive->vertices, sizeof(LightmappedVertex)); } } @@ -106,47 +101,42 @@ void RendererDX9Operations::DrawDepthQueue(std::vector& queue, b if (left.depth < right.depth) { return true; } + if (right.depth < left.depth) { return false; } + return left.depth == right.depth && std::less{}(left.primitive, right.primitive); }); } + for (const DepthPrimitive& entry : queue) { RenderCommand* command = entry.primitive; - this->state.SetTexture( - 0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr - ); + this->state.SetTexture(0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr); this->DrawPrimitive(command); } } // OFFSET: 0x00565210 // FUNCTION: fn_02216 -bool RendererDX9Operations::RenderToTexture( - int width, - int height, - const std::list& primitives, - CTexture*& texture -) { +bool RendererDX9Operations::RenderToTexture(int width, int height, const std::list& primitives, CTexture*& texture) { IDirect3DTexture9* nativeTexture = nullptr; if (texture) { nativeTexture = static_cast(texture)->NativeTexture(); } else { - if ( - FAILED(this->context.device->CreateTexture( - width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &nativeTexture, nullptr - )) - ) { + if (FAILED(this->context.device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &nativeTexture, nullptr))) { return false; } + CTextureDX9* created = new (std::nothrow) CTextureDX9(this->context, nativeTexture); - // Original retains the native reference if allocation fails. + if (!created) { return false; } + texture = created; } + if (!nativeTexture) { return false; } @@ -154,38 +144,39 @@ bool RendererDX9Operations::RenderToTexture( IDirect3DSurface9* previous = nullptr; IDirect3DSurface9* target = nullptr; bool result = false; - if ( - SUCCEEDED(nativeTexture->GetSurfaceLevel(0, &target)) && - SUCCEEDED(this->context.device->GetRenderTarget(0, &previous)) && - SUCCEEDED(this->context.device->SetRenderTarget(0, target)) - ) { + + if (SUCCEEDED(nativeTexture->GetSurfaceLevel(0, &target)) && SUCCEEDED(this->context.device->GetRenderTarget(0, &previous)) && + SUCCEEDED(this->context.device->SetRenderTarget(0, target))) { { ScopedDeviceStateDX9 restore(this->state); - this->state.SetRenderState(D3DRS_ZENABLE, 0); + this->state.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); this->state.SetRenderState(D3DRS_FOGENABLE, 0); this->state.SetRenderState(D3DRS_ALPHAREF, 1); this->state.SetRenderState(D3DRS_ALPHATESTENABLE, 1); this->state.SetRenderState(D3DRS_ALPHABLENDENABLE, 1); this->context.device->Clear(0, nullptr, D3DCLEAR_TARGET, 0, 1.0f, 0); + if (SUCCEEDED(this->context.device->BeginScene())) { for (RenderPrimitive* primitive : primitives) { - this->state.SetTexture( - 0, primitive->texture ? static_cast(primitive->texture)->NativeTexture() : nullptr - ); + this->state.SetTexture(0, primitive->texture ? static_cast(primitive->texture)->NativeTexture() : nullptr); this->DrawPrimitive(primitive); } + this->context.device->EndScene(); } } this->context.device->SetRenderTarget(0, previous); - // Original reports target-switch success even when BeginScene failed. + result = true; } + if (target) { target->Release(); } + if (previous) { previous->Release(); } + return result; } diff --git a/Source/Render/RendererDX9Operations.h b/Source/Render/DX9/RendererDX9Operations.h similarity index 69% rename from Source/Render/RendererDX9Operations.h rename to Source/Render/DX9/RendererDX9Operations.h index ca21b6d..57de1e7 100644 --- a/Source/Render/RendererDX9Operations.h +++ b/Source/Render/DX9/RendererDX9Operations.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERERDX9OPERATIONS_H -#define RAGNAROK_SOURCE_RENDER_RENDERERDX9OPERATIONS_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_RENDERERDX9OPERATIONS_H +#define RAGNAROK_SOURCE_RENDER_DX9_RENDERERDX9OPERATIONS_H #include #include @@ -19,8 +19,6 @@ class DeviceOwnerDX9; class CRenderSystemBase; struct tagRECT; -// Recovered operations over the renderer's borrowed device-owner state. -// This is not a substitute for the full CRendererDX9 virtual interface. struct RendererDX9Operations { TextureDX9Context& context; DeviceStateDX9& state; @@ -38,23 +36,11 @@ struct RendererDX9Operations { void DrawAlphaQueues(RenderQueues& queues, unsigned char twoPass); void DrawAuxiliaryQueue(RenderQueues& queues); void DrawQueues( - RenderQueues& queues, - const ServiceOptions& options, - unsigned char multitexture, - unsigned char twoPass, - RendererFogDX9& fog, - const float& aspect, + RenderQueues& queues, const ServiceOptions& options, unsigned char multitexture, unsigned char twoPass, RendererFogDX9& fog, const float& aspect, const FogConfiguration& configuration ); bool RenderToTexture(int width, int height, const std::list& primitives, CTexture*& texture); - bool SaveScreenshot( - DeviceOwnerDX9& owner, - CRenderSystemBase* renderSystem, - const char* filename, - int format, - CTexture* overlay, - const tagRECT* rectangle - ); + bool SaveScreenshot(DeviceOwnerDX9& owner, CRenderSystemBase* renderSystem, const char* filename, int format, CTexture* overlay, const tagRECT* rectangle); }; #endif diff --git a/Source/Render/RendererFogDX9.cpp b/Source/Render/DX9/RendererFogDX9.cpp similarity index 85% rename from Source/Render/RendererFogDX9.cpp rename to Source/Render/DX9/RendererFogDX9.cpp index 8916e2d..3a7bb07 100644 --- a/Source/Render/RendererFogDX9.cpp +++ b/Source/Render/DX9/RendererFogDX9.cpp @@ -1,7 +1,7 @@ -#include "Render/D3DX9Runtime.h" -#include "Render/DeviceStateDX9.h" -#include "Render/RendererFogDX9.h" -#include "Render/TextureDX9.h" +#include "Render/DX9/D3DX9Runtime.h" +#include "Render/DX9/DeviceStateDX9.h" +#include "Render/DX9/RendererFogDX9.h" +#include "Render/DX9/TextureDX9.h" #include @@ -19,11 +19,7 @@ void RendererFogDX9::Set(int value, const D3DCAPS9& caps, FogConfiguration& conf // OFFSET: 0x005654D0 // FUNCTION: fn_02217 void RendererFogDX9::Apply( - const TextureDX9Context& context, - DeviceStateDX9& state, - D3DX9Runtime& d3dx, - const float& aspect, - const FogConfiguration& configuration + const TextureDX9Context& context, DeviceStateDX9& state, D3DX9Runtime& d3dx, const float& aspect, const FogConfiguration& configuration ) { if (this->dirty == 1) { const float inverseAspect = 1.0f / aspect; @@ -37,6 +33,7 @@ void RendererFogDX9::Apply( context.device->SetTransform(D3DTS_WORLD, &identity); context.device->SetTransform(D3DTS_PROJECTION, &projection); context.device->SetTransform(D3DTS_VIEW, &identity); + state.SetRenderState(D3DRS_FOGCOLOR, configuration.color); state.SetRenderState(D3DRS_RANGEFOGENABLE, configuration.range); state.SetRenderState(D3DRS_FOGSTART, std::bit_cast(start)); diff --git a/Source/Render/DX9/RendererFogDX9.h b/Source/Render/DX9/RendererFogDX9.h new file mode 100644 index 0000000..b19c3d6 --- /dev/null +++ b/Source/Render/DX9/RendererFogDX9.h @@ -0,0 +1,23 @@ +#ifndef RAGNAROK_SOURCE_RENDER_DX9_RENDERERFOGDX9_H +#define RAGNAROK_SOURCE_RENDER_DX9_RENDERERFOGDX9_H + +#include "Render/FogConfiguration.h" + +#include + +class D3DX9Runtime; +struct TextureDX9Context; +struct DeviceStateDX9; + +struct RendererFogDX9 { + int enabled; + int dirty; + int supported; + + void Set(int enabled, const D3DCAPS9& caps, FogConfiguration& configuration); + void Apply(const TextureDX9Context& context, DeviceStateDX9& state, D3DX9Runtime& d3dx, const float& aspect, const FogConfiguration& configuration); +}; + +static_assert(sizeof(RendererFogDX9) == 12); + +#endif diff --git a/Source/Render/DX9/RendererFrameDX9.cpp b/Source/Render/DX9/RendererFrameDX9.cpp new file mode 100644 index 0000000..a14a81e --- /dev/null +++ b/Source/Render/DX9/RendererFrameDX9.cpp @@ -0,0 +1,34 @@ +#include "Contents/Effects/Effect.h" +#include "Render/DX9/DeviceOwnerDX9.h" +#include "Render/Primitives/LightmappedPrimitive.h" +#include "Render/Primitives/RenderCommandPool.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/Primitives/RenderVertexPool.h" +#include "Render/DX9/RendererDX9Operations.h" +#include "Render/DX9/RendererFrameDX9.h" + +// OFFSET: 0x0055A360 +// FUNCTION: fn_02079 +void RendererFrameDX9::Clear() { + this->retirement.Clear(); + this->queues.Clear(); + this->commands.Rewind(); + this->primitives.Rewind(); + this->lightmapped.Rewind(); + this->vertices.Rewind(); +} + +// OFFSET: 0x00565970 +// FUNCTION: fn_02222 +bool RendererFrameDX9::Draw( + CRenderSystemBase* renderSystem, const ServiceOptions& options, unsigned char multitexture, unsigned char twoPass, RendererFogDX9& fog, const float& aspect, + const FogConfiguration& configuration +) { + this->device.Begin(renderSystem); + this->operations.DrawQueues(this->queues, options, multitexture, twoPass, fog, aspect, configuration); + this->Clear(); + this->device.End(); + + return true; +} diff --git a/Source/Render/RendererFrameDX9.h b/Source/Render/DX9/RendererFrameDX9.h similarity index 60% rename from Source/Render/RendererFrameDX9.h rename to Source/Render/DX9/RendererFrameDX9.h index 4257c0b..dff11d7 100644 --- a/Source/Render/RendererFrameDX9.h +++ b/Source/Render/DX9/RendererFrameDX9.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERERFRAMEDX9_H -#define RAGNAROK_SOURCE_RENDER_RENDERERFRAMEDX9_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_RENDERERFRAMEDX9_H +#define RAGNAROK_SOURCE_RENDER_DX9_RENDERERFRAMEDX9_H struct RendererDX9Operations; struct DeviceOwnerDX9; @@ -14,8 +14,6 @@ struct FogConfiguration; struct ServiceOptions; class CRenderSystemBase; -// Borrowed fields of the original renderer plus its shared effect-retirement -// owner. This view neither owns the device nor replaces the renderer vtable. struct RendererFrameDX9 { DeviceOwnerDX9& device; RendererDX9Operations& operations; @@ -28,12 +26,7 @@ struct RendererFrameDX9 { void Clear(); bool Draw( - CRenderSystemBase* renderSystem, - const ServiceOptions& options, - unsigned char multitexture, - unsigned char twoPass, - RendererFogDX9& fog, - const float& aspect, + CRenderSystemBase* renderSystem, const ServiceOptions& options, unsigned char multitexture, unsigned char twoPass, RendererFogDX9& fog, const float& aspect, const FogConfiguration& configuration ); }; diff --git a/Source/Render/RendererPresentation.cpp b/Source/Render/DX9/RendererPresentation.cpp similarity index 85% rename from Source/Render/RendererPresentation.cpp rename to Source/Render/DX9/RendererPresentation.cpp index 64cfd12..93dbb7c 100644 --- a/Source/Render/RendererPresentation.cpp +++ b/Source/Render/DX9/RendererPresentation.cpp @@ -1,7 +1,8 @@ -#include "Render/DeviceOwnerDX9.h" -#include "Render/RendererPresentation.h" +#include "Render/DX9/DeviceOwnerDX9.h" +#include "Render/DX9/RendererPresentation.h" -#include +#include +#include // OFFSET: 0x00565B70 // FUNCTION: fn_02223 @@ -24,5 +25,6 @@ HRESULT RendererPresentation::Present(DeviceOwnerDX9& owner, int option) { const HRESULT result = owner.Present(option); this->diagnostic.line = 164; this->diagnostic.file = source; + return result; } diff --git a/Source/Render/RendererPresentation.h b/Source/Render/DX9/RendererPresentation.h similarity index 55% rename from Source/Render/RendererPresentation.h rename to Source/Render/DX9/RendererPresentation.h index ee00f15..dbb7ef2 100644 --- a/Source/Render/RendererPresentation.h +++ b/Source/Render/DX9/RendererPresentation.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERERPRESENTATION_H -#define RAGNAROK_SOURCE_RENDER_RENDERERPRESENTATION_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_RENDERERPRESENTATION_H +#define RAGNAROK_SOURCE_RENDER_DX9_RENDERERPRESENTATION_H #include @@ -10,8 +10,6 @@ struct RenderDiagnostic { const char* file; }; -// Borrowed CRenderer +0x38 frame and DX9 +0x268..+0x273 counters. They are -// initialized by renderer construction, not reset on every presentation. struct RendererPresentation { unsigned& frame; unsigned& lastTick; diff --git a/Source/Render/ScreenshotDX9.cpp b/Source/Render/DX9/ScreenshotDX9.cpp similarity index 64% rename from Source/Render/ScreenshotDX9.cpp rename to Source/Render/DX9/ScreenshotDX9.cpp index 7ec0b72..08d5cef 100644 --- a/Source/Render/ScreenshotDX9.cpp +++ b/Source/Render/DX9/ScreenshotDX9.cpp @@ -1,7 +1,7 @@ -#include "Render/D3DX9Runtime.h" -#include "Render/DeviceOwnerDX9.h" -#include "Render/RendererDX9Operations.h" -#include "Render/UIRPData.h" +#include "Render/DX9/D3DX9Runtime.h" +#include "Render/DX9/DeviceOwnerDX9.h" +#include "Render/DX9/RendererDX9Operations.h" +#include "Render/Primitives/UIRPData.h" #include #include @@ -18,12 +18,7 @@ namespace { // OFFSET: 0x005680A0 // FUNCTION: fn_02236 bool RendererDX9Operations::SaveScreenshot( - DeviceOwnerDX9& owner, - CRenderSystemBase* renderSystem, - const char* filename, - int format, - CTexture* overlay, - const tagRECT* rectangle + DeviceOwnerDX9& owner, CRenderSystemBase* renderSystem, const char* filename, int format, CTexture* overlay, const tagRECT* rectangle ) { if (overlay) { unsigned x = rectangle ? static_cast(rectangle->right) : owner.backBufferDescription.Width; @@ -31,23 +26,18 @@ bool RendererDX9Operations::SaveScreenshot( x -= overlay->Width(); y -= overlay->Height(); ScreenshotOverlay drawing; - drawing.Draw( - *this->context.primitives, std::bit_cast(x), std::bit_cast(y), overlay, 0xFFFFFFFFu, - 0, 0, false - ); + drawing.Draw(*this->context.primitives, std::bit_cast(x), std::bit_cast(y), overlay, 0xFFFFFFFFu, 0, 0, false); if (owner.Begin(renderSystem)) { ScopedDeviceStateDX9 restore(this->state); - this->state.SetRenderState(D3DRS_ZENABLE, 0); + this->state.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); this->state.SetRenderState(D3DRS_FOGENABLE, 0); this->state.SetRenderState(D3DRS_ALPHAREF, 1); this->state.SetRenderState(D3DRS_ALPHATESTENABLE, 1); this->state.SetRenderState(D3DRS_ALPHABLENDENABLE, 1); for (RenderPrimitive* command : drawing.Primitives()) { - this->state.SetTexture( - 0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr - ); + this->state.SetTexture(0, command->texture ? static_cast(command->texture)->NativeTexture() : nullptr); this->DrawPrimitive(command); } diff --git a/Source/Render/SurfaceDX9.cpp b/Source/Render/DX9/SurfaceDX9.cpp similarity index 85% rename from Source/Render/SurfaceDX9.cpp rename to Source/Render/DX9/SurfaceDX9.cpp index 45441dd..764f75d 100644 --- a/Source/Render/SurfaceDX9.cpp +++ b/Source/Render/DX9/SurfaceDX9.cpp @@ -1,6 +1,7 @@ -#include "Render/SurfaceDX9.h" +#include "Render/DX9/SurfaceDX9.h" #include +#include namespace { // OFFSET: 0x00570970 @@ -45,9 +46,7 @@ namespace { // FUNCTION: fn_02427 CSurfaceDX9::CSurfaceDX9(SurfaceDX9Context& context, int width, int height) : m_context(&context), m_width(AlignDimension(width)), m_height(AlignDimension(height)), m_surface(nullptr) { - context.device->CreateOffscreenPlainSurface( - this->m_width, this->m_height, context.backBufferDescription.Format, D3DPOOL_DEFAULT, &this->m_surface, nullptr - ); + context.device->CreateOffscreenPlainSurface(this->m_width, this->m_height, context.backBufferDescription.Format, D3DPOOL_DEFAULT, &this->m_surface, nullptr); } // OFFSET: 0x005707D0 @@ -80,6 +79,7 @@ CSurfaceDX9::~CSurfaceDX9() { std::uint32_t CSurfaceDX9::Width() { return this->m_width; } + // OFFSET: 0x00570C60 // FUNCTION: fn_02436 std::uint32_t CSurfaceDX9::Height() { @@ -93,11 +93,11 @@ bool CSurfaceDX9::Resize(int width, int height) { this->m_surface->Release(); this->m_surface = nullptr; } + this->m_width = AlignDimension(width); this->m_height = AlignDimension(height); return SUCCEEDED(this->m_context->device->CreateOffscreenPlainSurface( - this->m_width, this->m_height, this->m_context->backBufferDescription.Format, D3DPOOL_DEFAULT, - &this->m_surface, nullptr + this->m_width, this->m_height, this->m_context->backBufferDescription.Format, D3DPOOL_DEFAULT, &this->m_surface, nullptr )) && this->m_surface; } @@ -108,10 +108,8 @@ SurfaceLock CSurfaceDX9::Lock() { SurfaceLock output{}; D3DSURFACE_DESC description; D3DLOCKED_RECT locked; - if ( - this->m_surface && SUCCEEDED(this->m_surface->GetDesc(&description)) && - SUCCEEDED(this->m_surface->LockRect(&locked, nullptr, 0)) - ) { + + if (this->m_surface && SUCCEEDED(this->m_surface->GetDesc(&description)) && SUCCEEDED(this->m_surface->LockRect(&locked, nullptr, 0))) { output.success = true; output.pixels = locked.pBits; output.pitch = locked.Pitch; @@ -119,6 +117,7 @@ SurfaceLock CSurfaceDX9::Lock() { output.height = description.Height; output.bitsPerPixel = BitsPerPixel(description.Format); } + return output; } @@ -150,19 +149,23 @@ void CSurfaceDX9::Upload(int x, int y, int width, int height, const std::uint32_ if (!this->m_surface || !width || !height) { return; } + D3DSURFACE_DESC description; if (FAILED(this->m_surface->GetDesc(&description))) { return; } + RECT rectangle{x, y, x + width, y + height}; D3DLOCKED_RECT locked; if (FAILED(this->m_surface->LockRect(&locked, &rectangle, 0))) { return; } + const int stride = sourceWidth ? sourceWidth : width; if (BitsPerPixel(description.Format) == 16) { for (int row = 0; row < height; ++row) { - auto* output = reinterpret_cast(static_cast(locked.pBits) + row * locked.Pitch); + auto* output = static_cast(locked.pBits) + row * locked.Pitch; + for (int column = 0; column < width; ++column) { const std::uint32_t color = pixels[row * stride + column]; std::uint16_t value = 0; @@ -182,18 +185,22 @@ void CSurfaceDX9::Upload(int x, int y, int width, int height, const std::uint32_ break; } } - output[column] = value; + + std::memcpy(output + column * sizeof(value), &value, sizeof(value)); } } } else if (description.Format == D3DFMT_A8R8G8B8 || description.Format == D3DFMT_X8R8G8B8) { for (int row = 0; row < height; ++row) { - auto* output = reinterpret_cast(static_cast(locked.pBits) + row * locked.Pitch); + auto* output = static_cast(locked.pBits) + row * locked.Pitch; + for (int column = 0; column < width; ++column) { const std::uint32_t color = pixels[row * stride + column]; - output[column] = (color & 0xFFFFFF) == 0xFF00FF ? 0 : color; + const std::uint32_t value = (color & 0xFFFFFF) == 0xFF00FF ? 0 : color; + std::memcpy(output + column * sizeof(value), &value, sizeof(value)); } } } + this->m_surface->UnlockRect(); } @@ -211,17 +218,17 @@ void CSurfaceDX9::Draw(int x, int y, int width, int height, std::uint32_t) { if (!this->m_surface) { return; } + D3DSURFACE_DESC description; if (FAILED(this->m_surface->GetDesc(&description))) { return; } + const RECT target{x, y, x + width, y + height}; const RECT destination = Clip(target, this->m_context->backBufferDescription); const RECT original{0, 0, destination.right - destination.left, destination.bottom - destination.top}; const RECT source = Clip(original, description); - this->m_context->device->StretchRect( - this->m_surface, &source, this->m_context->backBuffer, &destination, D3DTEXF_NONE - ); + this->m_context->device->StretchRect(this->m_surface, &source, this->m_context->backBuffer, &destination, D3DTEXF_NONE); } // OFFSET: 0x00570BA0 @@ -230,9 +237,8 @@ void CSurfaceDX9::Stretch(int x, int y, int width, int height) { if (!this->m_surface) { return; } + const RECT target{x, y, x + width, y + height}; const RECT destination = Clip(target, this->m_context->backBufferDescription); - this->m_context->device->StretchRect( - this->m_surface, nullptr, this->m_context->backBuffer, &destination, D3DTEXF_LINEAR - ); + this->m_context->device->StretchRect(this->m_surface, nullptr, this->m_context->backBuffer, &destination, D3DTEXF_LINEAR); } diff --git a/Source/Render/SurfaceDX9.h b/Source/Render/DX9/SurfaceDX9.h similarity index 81% rename from Source/Render/SurfaceDX9.h rename to Source/Render/DX9/SurfaceDX9.h index 7f71f0e..4f284a9 100644 --- a/Source/Render/SurfaceDX9.h +++ b/Source/Render/DX9/SurfaceDX9.h @@ -1,12 +1,10 @@ -#ifndef RAGNAROK_SOURCE_RENDER_SURFACEDX9_H -#define RAGNAROK_SOURCE_RENDER_SURFACEDX9_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_SURFACEDX9_H +#define RAGNAROK_SOURCE_RENDER_DX9_SURFACEDX9_H -#include "Render/Surface.h" +#include "Render/Textures/Surface.h" #include -// Explicit view of original device owner's fields+8,+1328,+1664. Borrowed -// resources; this is not a replacement device owner or initialization path. struct SurfaceDX9Context { IDirect3DDevice9* device; D3DSURFACE_DESC backBufferDescription; diff --git a/Source/Render/TextureDX9.cpp b/Source/Render/DX9/TextureDX9.cpp similarity index 72% rename from Source/Render/TextureDX9.cpp rename to Source/Render/DX9/TextureDX9.cpp index 5329068..5bfee1d 100644 --- a/Source/Render/TextureDX9.cpp +++ b/Source/Render/DX9/TextureDX9.cpp @@ -1,8 +1,8 @@ -#include "Render/D3DX9Runtime.h" -#include "Render/RenderPrimitivePool.h" -#include "Render/RenderQueues.h" -#include "Render/SpritePixels.h" -#include "Render/TextureDX9.h" +#include "Render/DX9/D3DX9Runtime.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/Textures/SpritePixels.h" +#include "Render/DX9/TextureDX9.h" #include #include @@ -28,22 +28,22 @@ namespace { value |= value >> 4; value |= value >> 8; value |= value >> 16; + return value + 1 + (value == 0xFFFFFFFFu); } } // OFFSET: 0x00572500 CTextureDX9::CTextureDX9(TextureDX9Context& context) - : m_context(&context), m_renderTargetUsage(false), m_dynamic(false), m_allowDynamic(false), m_renderTarget(false), - m_texture(nullptr), m_surface(nullptr), m_description{} { + : m_context(&context), m_renderTargetUsage(false), m_dynamic(false), m_allowDynamic(false), m_renderTarget(false), m_texture(nullptr), m_surface(nullptr), + m_description{} { this->m_textureWidth = this->m_textureHeight = this->m_width = this->m_height = 1; - this->m_format = 0; + this->m_format = TextureFormat::A1R5G5B5; } // OFFSET: 0x005725C0 // FUNCTION: fn_02475 -CTextureDX9::CTextureDX9(TextureDX9Context& context, int width, int height, int format, bool dynamic, bool renderTarget) - : CTextureDX9(context) { +CTextureDX9::CTextureDX9(TextureDX9Context& context, int width, int height, int format, bool dynamic, bool renderTarget) : CTextureDX9(context) { this->m_allowDynamic = dynamic; this->m_renderTarget = renderTarget; this->Create(width, height, format); @@ -54,35 +54,33 @@ CTextureDX9::CTextureDX9(TextureDX9Context& context, int width, int height, int // FUNCTION: fn_02476 CTextureDX9::CTextureDX9(TextureDX9Context& context, IDirect3DTexture9* texture) : CTextureDX9(context) { this->m_texture = texture; - if ( - SUCCEEDED(texture->GetSurfaceLevel(0, &this->m_surface)) && - SUCCEEDED(this->m_surface->GetDesc(&this->m_description)) - ) { + if (SUCCEEDED(texture->GetSurfaceLevel(0, &this->m_surface)) && SUCCEEDED(this->m_surface->GetDesc(&this->m_description))) { this->m_renderTargetUsage = (this->m_description.Usage & D3DUSAGE_RENDERTARGET) != 0; this->m_dynamic = (this->m_description.Usage & D3DUSAGE_DYNAMIC) != 0; this->m_textureWidth = this->m_description.Width; this->m_textureHeight = this->m_description.Height; + switch (this->m_description.Format) { case D3DFMT_A8R8G8B8: - this->m_format = 4; + this->m_format = TextureFormat::A8R8G8B8; break; case D3DFMT_R5G6B5: - this->m_format = 2; + this->m_format = TextureFormat::R5G6B5; break; case D3DFMT_X1R5G5B5: - this->m_format = 3; + this->m_format = TextureFormat::X1R5G5B5; break; case D3DFMT_A1R5G5B5: - this->m_format = 0; + this->m_format = TextureFormat::A1R5G5B5; break; case D3DFMT_A4R4G4B4: - this->m_format = 1; + this->m_format = TextureFormat::A4R4G4B4; break; default: - this->m_format = -1; + this->m_format = TextureFormat::UnknownTextureFormat; break; } - // Original sets both logical dimensions to the physical WIDTH. + this->m_width = this->m_height = this->m_description.Width; } } @@ -94,6 +92,7 @@ CTextureDX9::~CTextureDX9() { this->m_surface->Release(); this->m_surface = nullptr; } + if (this->m_texture) { this->m_texture->Release(); this->m_texture = nullptr; @@ -103,7 +102,6 @@ CTextureDX9::~CTextureDX9() { // OFFSET: 0x00572AC0 // FUNCTION: fn_02480 bool CTextureDX9::Create(int width, int height, int format) { - if (this->m_surface) { this->m_surface->Release(); this->m_surface = nullptr; @@ -115,20 +113,21 @@ bool CTextureDX9::Create(int width, int height, int format) { } D3DFORMAT nativeFormat = D3DFMT_UNKNOWN; + switch (format) { - case 0: + case TextureFormat::A1R5G5B5: nativeFormat = D3DFMT_A1R5G5B5; break; - case 1: + case TextureFormat::A4R4G4B4: nativeFormat = D3DFMT_A4R4G4B4; break; - case 2: + case TextureFormat::R5G6B5: nativeFormat = D3DFMT_R5G6B5; break; - case 3: + case TextureFormat::X1R5G5B5: nativeFormat = D3DFMT_X1R5G5B5; break; - case 4: + case TextureFormat::A8R8G8B8: nativeFormat = D3DFMT_A8R8G8B8; break; } @@ -136,10 +135,12 @@ bool CTextureDX9::Create(int width, int height, int format) { UINT w = std::min(RoundUpPowerOfTwo(width), this->m_context->caps.MaxTextureWidth); UINT h = std::min(RoundUpPowerOfTwo(height), this->m_context->caps.MaxTextureHeight); UINT ratio = this->m_context->caps.MaxTextureAspectRatio; + if (ratio) { if (w / h > ratio) { h = w / ratio; } + if (h / w > ratio) { w = h / ratio; } @@ -151,34 +152,35 @@ bool CTextureDX9::Create(int width, int height, int format) { DWORD usage = this->m_renderTarget ? 0 : D3DUSAGE_AUTOGENMIPMAP; D3DPOOL pool = D3DPOOL_MANAGED; this->m_dynamic = false; + if (this->m_allowDynamic && this->m_context->dynamicTextures) { this->m_dynamic = this->m_context->direct3D && (this->m_context->caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && this->m_context->direct3D->CheckDeviceFormat( - this->m_context->adapter, D3DDEVTYPE_HAL, this->m_context->displayFormat, D3DUSAGE_DYNAMIC, - D3DRTYPE_TEXTURE, nativeFormat + this->m_context->adapter, D3DDEVTYPE_HAL, this->m_context->displayFormat, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, nativeFormat ) == D3D_OK; pool = D3DPOOL_DEFAULT; if (this->m_dynamic) { usage = D3DUSAGE_DYNAMIC | (this->m_renderTarget ? 0 : D3DUSAGE_AUTOGENMIPMAP); } } - if ( - FAILED(this->m_context->device->CreateTexture(w, h, 1, usage, nativeFormat, pool, &this->m_texture, nullptr)) || - FAILED(this->m_texture->GetSurfaceLevel(0, &this->m_surface)) || - FAILED(this->m_surface->GetDesc(&this->m_description)) - ) { + + if (FAILED(this->m_context->device->CreateTexture(w, h, 1, usage, nativeFormat, pool, &this->m_texture, nullptr)) || + FAILED(this->m_texture->GetSurfaceLevel(0, &this->m_surface)) || FAILED(this->m_surface->GetDesc(&this->m_description))) { return false; } + if (!this->m_renderTarget) { for (UINT level = 0; level < this->m_texture->GetLevelCount(); ++level) { IDirect3DSurface9* surface = nullptr; if (FAILED(this->m_texture->GetSurfaceLevel(level, &surface))) { break; } + this->ClearSurface(surface, 0); surface->Release(); } } + return true; } @@ -201,6 +203,7 @@ SurfaceLock CTextureDX9::Lock() { output.bitsPerPixel = 16; } } + return output; } @@ -239,7 +242,7 @@ void CTextureDX9::ReleaseDC(HDC dc) { // OFFSET: 0x005737A0 // FUNCTION: fn_02492 -void CTextureDX9::Update(int) { +void CTextureDX9::Update(const RECT*) { this->Filter(); } @@ -248,11 +251,7 @@ void CTextureDX9::Update(int) { void CTextureDX9::Fill(const RECT* rectangle, std::uint32_t color) { if (this->m_surface) { const RECT pixel{0, 0, 1, 1}; - if ( - SUCCEEDED(this->m_context->d3dx->loadSurfaceFromMemory( - this->m_surface, nullptr, rectangle, &color, D3DFMT_A8R8G8B8, 4, nullptr, &pixel, 2, 0 - )) - ) { + if (SUCCEEDED(this->m_context->d3dx->loadSurfaceFromMemory(this->m_surface, nullptr, rectangle, &color, D3DFMT_A8R8G8B8, 4, nullptr, &pixel, 2, 0))) { this->Filter(); } } @@ -266,100 +265,99 @@ void CTextureDX9::ClearSurface(IDirect3DSurface9* surface, std::uint32_t color) if (FAILED(surface->GetDesc(&description)) || FAILED(surface->LockRect(&locked, nullptr, 0))) { return; } + for (UINT y = 0; y < description.Height; ++y) { auto* row = static_cast(locked.pBits) + y * locked.Pitch; if (this->m_description.Format == D3DFMT_A8R8G8B8) { - std::fill_n(reinterpret_cast(row), description.Width, color); - } else if ( - this->m_description.Format == D3DFMT_R5G6B5 || this->m_description.Format == D3DFMT_A1R5G5B5 || - this->m_description.Format == D3DFMT_A4R4G4B4 - ) { - std::fill_n( - reinterpret_cast(row), description.Width, Convert16(color, this->m_description.Format) - ); + for (UINT x = 0; x < description.Width; ++x) { + std::memcpy(row + x * sizeof(color), &color, sizeof(color)); + } + } else if (this->m_description.Format == D3DFMT_R5G6B5 || this->m_description.Format == D3DFMT_A1R5G5B5 || this->m_description.Format == D3DFMT_A4R4G4B4) { + const std::uint16_t value = Convert16(color, this->m_description.Format); + + for (UINT x = 0; x < description.Width; ++x) { + std::memcpy(row + x * sizeof(value), &value, sizeof(value)); + } } } + surface->UnlockRect(); } // OFFSET: 0x00573240 // FUNCTION: fn_02490 bool CTextureDX9::UploadSurface( - IDirect3DSurface9* surface, - int x, - int y, - int width, - int height, - const std::uint32_t* pixels, - bool blackTransparent, - int sourceWidth + IDirect3DSurface9* surface, int x, int y, int width, int height, const std::uint32_t* pixels, bool blackTransparent, int sourceWidth ) { D3DSURFACE_DESC description; if (FAILED(surface->GetDesc(&description))) { return false; } + const int stride = sourceWidth ? sourceWidth : width; int stepX = 1, stepY = 1; - int extentX = static_cast(static_cast(x) + width); - int extentY = static_cast(static_cast(y) + height); + int extentX = x + width; + int extentY = y + height; + if (static_cast(extentX) > this->m_width) { do { ++stepX; extentX /= stepX; } while (static_cast(extentX) > this->m_width); } + if (static_cast(extentY) > this->m_height) { do { ++stepY; extentY /= stepY; } while (static_cast(extentY) > this->m_height); } + const int w = width / stepX, h = height / stepY; if (!w || !h) { return false; } + const RECT rectangle{x / stepX, y / stepY, x / stepX + w, y / stepY + h}; D3DLOCKED_RECT locked; if (FAILED(surface->LockRect(&locked, &rectangle, 0))) { return false; } + for (int row = 0; row < h; ++row) { auto* output = static_cast(locked.pBits) + row * locked.Pitch; + for (int column = 0; column < w; ++column) { const std::uint32_t color = pixels[row * stepY * stride + column * stepX]; if (description.Format == D3DFMT_A8R8G8B8) { - reinterpret_cast(output)[column] = color; + std::memcpy(output + column * sizeof(color), &color, sizeof(color)); } else if (description.Format == D3DFMT_R5G6B5) { - reinterpret_cast(output)[column] = Convert16(color, description.Format); + const std::uint16_t converted = Convert16(color, description.Format); + std::memcpy(output + column * sizeof(converted), &converted, sizeof(converted)); } else if (description.Format == D3DFMT_A1R5G5B5 || description.Format == D3DFMT_A4R4G4B4) { std::uint16_t converted = Convert16(color, description.Format); const std::uint16_t rgb = description.Format == D3DFMT_A1R5G5B5 ? converted & 0x7FFF : converted & 0x0FFF; if (rgb == (description.Format == D3DFMT_A1R5G5B5 ? 0x7C1F : 0xF0F) || (blackTransparent && !rgb)) { converted = 0; } - reinterpret_cast(output)[column] = converted; + + std::memcpy(output + column * sizeof(converted), &converted, sizeof(converted)); } } } + return SUCCEEDED(surface->UnlockRect()); } // OFFSET: 0x00573600 // FUNCTION: fn_02491 -void CTextureDX9::Upload( - int x, - int y, - int width, - int height, - const std::uint32_t* pixels, - int option, - int sourceWidth -) { +void CTextureDX9::Upload(int x, int y, int width, int height, const std::uint32_t* pixels, int option, int sourceWidth) { this->SetImageSize(width, height); this->unknown_0008 = (this->unknown_0008 & 255) | (static_cast(option) << 8); if (!pixels) { return; } + IDirect3DTexture9* temporary = nullptr; IDirect3DSurface9* surface = nullptr; if (!this->m_renderTarget) { @@ -367,29 +365,31 @@ void CTextureDX9::Upload( if (surface) { surface->AddRef(); } - } else if ( - SUCCEEDED(this->m_context->device->CreateTexture( - this->m_textureWidth, this->m_textureHeight, !this->m_context->dynamicTextures, 0, this->m_description.Format, - D3DPOOL_SYSTEMMEM, &temporary, nullptr - )) && - SUCCEEDED(temporary->GetSurfaceLevel(0, &surface)) - ) { + } else if (SUCCEEDED(this->m_context->device->CreateTexture( + this->m_textureWidth, this->m_textureHeight, !this->m_context->dynamicTextures, 0, this->m_description.Format, D3DPOOL_SYSTEMMEM, &temporary, + nullptr + )) && + SUCCEEDED(temporary->GetSurfaceLevel(0, &surface))) { this->ClearSurface(surface, 0); } + if (surface) { this->UploadSurface(surface, x, y, width, height, pixels, option != 0, sourceWidth); if (this->m_renderTarget && temporary) { if (temporary->GetLevelCount() > 1) { this->m_context->d3dx->filterTexture(temporary, nullptr, UINT(-1), DWORD(-1)); } + this->m_context->device->UpdateTexture(temporary, this->m_texture); } else { this->Filter(); } } + if (surface) { surface->Release(); } + if (temporary) { temporary->Release(); } @@ -397,43 +397,51 @@ void CTextureDX9::Upload( // OFFSET: 0x005737E0 // FUNCTION: fn_02493 -void CTextureDX9::UploadSprite(int x, int y, int width, int height, const void* rawImage, int palette) { +void CTextureDX9::UploadSprite(int x, int y, int width, int height, const SpriteRleImage* rawImage, const std::uint32_t* palette) { if (!this->m_surface) { return; } + RECT rectangle{x, y, x + width, y + height}; D3DLOCKED_RECT locked; if (FAILED(this->m_surface->LockRect(&locked, &rectangle, 0))) { return; } + if (this->m_description.Format == D3DFMT_A1R5G5B5 || this->m_description.Format == D3DFMT_A8R8G8B8) { const int bytes = this->m_description.Format == D3DFMT_A1R5G5B5 ? 2 : 4; + for (int row = 0; row < height; ++row) { std::memset(static_cast(locked.pBits) + row * locked.Pitch, 0, width * bytes); } } - const auto& image = *static_cast(rawImage); - const auto* colors = - reinterpret_cast(static_cast(static_cast(palette))); + + const SpriteRleImage& image = *rawImage; const std::uint8_t* input = image.runs; int remaining = 0; + for (int row = 0; row < image.height; ++row) { - auto* output = reinterpret_cast(static_cast(locked.pBits) + row * locked.Pitch); + auto* output = static_cast(locked.pBits) + row * locked.Pitch; + for (int column = 0; column < image.width; ++column) { if (remaining) { --remaining; - output[column] = 0; + const std::uint16_t color = 0; + std::memcpy(output + column * sizeof(color), &color, sizeof(color)); } else { const unsigned value = *input++; if (value) { - output[column] = colors[value]; + const std::uint16_t color = palette[value]; + std::memcpy(output + column * sizeof(color), &color, sizeof(color)); } else { - output[column] = 0; + const std::uint16_t color = 0; + std::memcpy(output + column * sizeof(color), &color, sizeof(color)); remaining = *input++ - 1; } } } } + if (SUCCEEDED(this->m_surface->UnlockRect())) { this->Filter(); } @@ -441,26 +449,15 @@ void CTextureDX9::UploadSprite(int x, int y, int width, int height, const void* // OFFSET: 0x005729E0 // FUNCTION: fn_02479 -bool CTextureDX9::CopyTexture( - CTexture* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - int x, - int y, - int width, - int height -) { +bool CTextureDX9::CopyTexture(CTexture* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, int x, int y, int width, int height) { RECT src{sourceX, sourceY, sourceX + sourceWidth, sourceY + sourceHeight}; RECT dst{x, y, x + width, y + height}; - if ( - FAILED(this->m_context->d3dx->loadSurfaceFromSurface( - this->m_surface, nullptr, &dst, static_cast(source)->m_surface, nullptr, &src, 3, 0 - )) - ) { + if (FAILED( + this->m_context->d3dx->loadSurfaceFromSurface(this->m_surface, nullptr, &dst, static_cast(source)->m_surface, nullptr, &src, 3, 0) + )) { return false; } + this->Filter(); return true; } @@ -469,8 +466,8 @@ bool CTextureDX9::CopyTexture( // FUNCTION: fn_01817 void CTextureDX9::Draw(int x, int y, int width, int height, std::uint32_t color) { this->DrawTo( - *this->m_context->primitives, *this->m_context->queues, x, y, width, height, color, this->m_context->depthAlpha, - this->m_context->depthStart, this->m_context->depthEnd + *this->m_context->primitives, *this->m_context->queues, x, y, width, height, color, this->m_context->depthAlpha, this->m_context->depthStart, + this->m_context->depthEnd ); } @@ -478,7 +475,7 @@ void CTextureDX9::Draw(int x, int y, int width, int height, std::uint32_t color) // FUNCTION: fn_01818 void CTextureDX9::Stretch(int x, int y, int width, int height) { this->StretchTo( - *this->m_context->primitives, *this->m_context->queues, x, y, width, height, this->m_context->depthAlpha, - this->m_context->depthStart, this->m_context->depthEnd + *this->m_context->primitives, *this->m_context->queues, x, y, width, height, this->m_context->depthAlpha, this->m_context->depthStart, + this->m_context->depthEnd ); } diff --git a/Source/Render/TextureDX9.h b/Source/Render/DX9/TextureDX9.h similarity index 70% rename from Source/Render/TextureDX9.h rename to Source/Render/DX9/TextureDX9.h index 2ac9407..d2df468 100644 --- a/Source/Render/TextureDX9.h +++ b/Source/Render/DX9/TextureDX9.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_RENDER_TEXTUREDX9_H -#define RAGNAROK_SOURCE_RENDER_TEXTUREDX9_H +#ifndef RAGNAROK_SOURCE_RENDER_DX9_TEXTUREDX9_H +#define RAGNAROK_SOURCE_RENDER_DX9_TEXTUREDX9_H -#include "Render/Texture.h" +#include "Render/Textures/Texture.h" #include @@ -9,7 +9,6 @@ class D3DX9Runtime; struct RenderQueues; class RenderPrimitivePool; -// Borrowed original device/caps and renderer state, not a replacement owner. struct TextureDX9Context { IDirect3D9* direct3D; IDirect3DDevice9* device; @@ -29,7 +28,7 @@ class CTextureDX9 : public CTexture { public: explicit CTextureDX9(TextureDX9Context& context); CTextureDX9(TextureDX9Context& context, int width, int height, int format, bool dynamic, bool renderTarget); - // Original takes ownership of the supplied texture reference. + CTextureDX9(TextureDX9Context& context, IDirect3DTexture9* texture); ~CTextureDX9() override; bool Resize(int width, int height) override; @@ -41,19 +40,9 @@ public: void Fill(const RECT* rectangle, std::uint32_t color) override; void Draw(int x, int y, int width, int height, std::uint32_t color) override; void Stretch(int x, int y, int width, int height) override; - void Update(int option) override; - void UploadSprite(int x, int y, int width, int height, const void* image, int palette) override; - bool CopyTexture( - CTexture* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - int x, - int y, - int width, - int height - ) override; + void Update(const RECT* rectangle) override; + void UploadSprite(int x, int y, int width, int height, const SpriteRleImage* image, const std::uint32_t* palette) override; + bool CopyTexture(CTexture* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, int x, int y, int width, int height) override; bool Create(int width, int height, int format) override; IDirect3DTexture9* NativeTexture() const { return this->m_texture; @@ -72,16 +61,7 @@ protected: private: void Filter(); void ClearSurface(IDirect3DSurface9* surface, std::uint32_t color); - bool UploadSurface( - IDirect3DSurface9* surface, - int x, - int y, - int width, - int height, - const std::uint32_t* pixels, - bool blackTransparent, - int sourceWidth - ); + bool UploadSurface(IDirect3DSurface9* surface, int x, int y, int width, int height, const std::uint32_t* pixels, bool blackTransparent, int sourceWidth); }; #if defined(_WIN32) && !defined(_WIN64) diff --git a/Source/Render/TextureModesDX9.cpp b/Source/Render/DX9/TextureModesDX9.cpp similarity index 78% rename from Source/Render/TextureModesDX9.cpp rename to Source/Render/DX9/TextureModesDX9.cpp index fbc7206..c7f37c9 100644 --- a/Source/Render/TextureModesDX9.cpp +++ b/Source/Render/DX9/TextureModesDX9.cpp @@ -1,5 +1,5 @@ -#include "Render/DeviceStateDX9.h" -#include "Render/RendererDX9Operations.h" +#include "Render/DX9/DeviceStateDX9.h" +#include "Render/DX9/RendererDX9Operations.h" #include "Render/TextureStageModes.h" // OFFSET: 0x00568470 diff --git a/Source/Render/DepthAlpha.cpp b/Source/Render/DepthAlpha.cpp deleted file mode 100644 index 3da0d25..0000000 --- a/Source/Render/DepthAlpha.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "Render/DepthAlpha.h" -#include "Render/LightmappedPrimitive.h" -#include "Render/RenderPrimitive.h" - -#include -#include - -// OFFSET: 0x0055D190 -// FUNCTION: fn_02100 -std::uint32_t DepthAlpha(float reciprocalDepth, float start, float end) { - float value = ((1.0f / reciprocalDepth) - 10.0f) / 1490.0f; - const float range = end - start; - - if (range != 0.0f) { - value = (value - start) / range; - } - - const __m128 lower = _mm_max_ss(_mm_setzero_ps(), _mm_set_ss(value)); - const float upper = _mm_cvtss_f32(_mm_min_ss(_mm_set_ss(1.0f), lower)); - const float alpha = (1.0f - upper) * 255.0f; - const auto bits = std::bit_cast(alpha); - const auto magnitude = (bits & 0x7FFFFFFFu) << 1; - std::uint32_t converted; - - // Original __ftoui3 unsigned invalid-conversion results, not signed CVTTSS2SI. - if ((bits & 0x80000000u) == 0 && magnitude >= 0x9F000000u) { - converted = 0xFFFFFFFFu; - } else if ((bits & 0x80000000u) != 0 && magnitude >= 0x7F000000u) { - converted = 0xFFFFFFFFu; - } else { - converted = static_cast(_mm_cvttss_si32(_mm_set_ss(alpha))); - } - - return converted << 24; -} - -// OFFSET: 0x005694A0 -// FUNCTION: fn_02260 -void ApplyDepthAlpha(RenderCommand& command, float start, float end) { - if (std::bit_cast(command.vertexCount) > 0) { - for (std::uint32_t index = 0; index < command.vertexCount; ++index) { - command.vertices[index].specular = DepthAlpha(command.vertices[index].rhw, start, end); - } - } -} - -// OFFSET: 0x005694E0 -// FUNCTION: fn_02261 -void ApplyDepthAlpha(LightmappedPrimitive& command, float start, float end) { - if (std::bit_cast(command.vertexCount) > 0) { - for (std::uint32_t index = 0; index < command.vertexCount; ++index) { - command.vertices[index].specular = DepthAlpha(command.vertices[index].rhw, start, end); - } - } -} diff --git a/Source/Render/DeviceContext.h b/Source/Render/DeviceContext.h deleted file mode 100644 index b2cee3c..0000000 --- a/Source/Render/DeviceContext.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef RAGNAROK_SOURCE_RENDER_DEVICECONTEXT_H -#define RAGNAROK_SOURCE_RENDER_DEVICECONTEXT_H - -#include "Render/SpritePixels.h" - -#include - -class CSurface; -class CDCBitmap; -class CRenderSystemBase; -class SpriteAtlas; - -// CDC vtable, 17 slots. Resource/frame/device arguments below -// expose recovered original owners rather than introducing callable host VAs. -class CDC { -public: - virtual ~CDC(); - virtual void Grow(std::uint32_t width, std::uint32_t height) = 0; - virtual bool GetDC(HDC* output) = 0; - virtual void ReleaseDC(HDC dc) = 0; - virtual void Copy(int x, int y, int width, int height, const std::uint32_t* source, bool transparent) = 0; - virtual void ScaleCopy( - int x, - int y, - int sourceWidth, - int sourceHeight, - int width, - int height, - const std::uint32_t* source, - int option - ) = 0; - virtual void CopyRegion( - int x, - int y, - int sourceLeft, - int sourceTop, - int sourceRight, - int sourceBottom, - const std::uint32_t* source, - int sourceWidth, - int sourceHeight, - bool transparent, - bool alpha - ) = 0; - virtual void CopyFrom(int x, int y, int sourceX, int sourceY, int width, int height, const CDCBitmap& source) = 0; - virtual void BlendFrom(std::uint32_t x, std::uint32_t y, int width, int height, const CDCBitmap& source) = 0; - virtual void DrawRleSprite( - int x, - int y, - std::span cells, - const SpriteRleImage* const* const* images, - const std::uint32_t* palette, - int cellCount - ) = 0; - virtual void DrawSurface( - int x, - int y, - CSurface* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - bool mirrored, - int scaleX, - int scaleY, - int filter, - int format - ) = 0; - virtual void Fill(const RECT* rectangle, std::uint32_t color) = 0; - virtual void Draw(CRenderSystemBase& system, int x, int y, int width, int height, std::uint32_t color) = 0; - virtual void DrawScaledSprite( - int x, - int y, - int width, - int height, - std::span cells, - const SpriteRleImage* const* const* images, - int cellCount, - int offsetX, - int offsetY, - float scale, - const std::uint32_t* palette, - SpriteAtlas& atlas, - CRenderSystemBase& system, - int serviceType, - std::uint32_t reuseDelay - ) = 0; - virtual void DrawScaledSurface( - int x, - int y, - int width, - int height, - CSurface* source, - int sourceWidth, - int sourceHeight, - float scaleX, - float scaleY, - std::uint32_t color, - bool mirrored, - int offsetX, - int offsetY, - int sourceX, - int sourceY, - int format - ) = 0; - virtual void Brighten(int x, int y, int width, int height, int amount) = 0; - virtual void Dim(int x, int y, int width, int height, int percent) = 0; -}; - -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(CDC) == 4); -#endif - -#endif diff --git a/Source/Render/DCBitmap.cpp b/Source/Render/DeviceContext/DCBitmap.cpp similarity index 63% rename from Source/Render/DCBitmap.cpp rename to Source/Render/DeviceContext/DCBitmap.cpp index 89eced0..185a1b4 100644 --- a/Source/Render/DCBitmap.cpp +++ b/Source/Render/DeviceContext/DCBitmap.cpp @@ -1,4 +1,4 @@ -#include "Render/DCBitmap.h" +#include "Render/DeviceContext/DCBitmap.h" // OFFSET: 0x00545790 // FUNCTION: fn_01832 @@ -16,6 +16,7 @@ CDCBitmap* CreateBitmapDC(int width, int height, bool fill) { if (fill) { bitmap->Fill(nullptr, 0xFFFF00FFu); } + return bitmap; } @@ -37,6 +38,7 @@ void CDCBitmap::Grow(std::uint32_t width, std::uint32_t height) { bool CDCBitmap::GetDC(HDC* output) { return this->m_bitmap.GetDC(output); } + // OFFSET: 0x00547D30 // FUNCTION: fn_01849 void CDCBitmap::ReleaseDC(HDC dc) { @@ -51,37 +53,17 @@ void CDCBitmap::Copy(int x, int y, int width, int height, const std::uint32_t* s // OFFSET: 0x00547D80 // FUNCTION: fn_01851 -void CDCBitmap::ScaleCopy( - int x, - int y, - int sourceWidth, - int sourceHeight, - int width, - int height, - const std::uint32_t* source, - int option -) { +void CDCBitmap::ScaleCopy(int x, int y, int sourceWidth, int sourceHeight, int width, int height, const std::uint32_t* source, int option) { this->m_bitmap.ScaleCopy(x, y, sourceWidth, sourceHeight, width, height, source, option); } // OFFSET: 0x00548780 // FUNCTION: fn_01856 void CDCBitmap::CopyRegion( - int x, - int y, - int sourceLeft, - int sourceTop, - int sourceRight, - int sourceBottom, - const std::uint32_t* source, - int sourceWidth, - int sourceHeight, - bool transparent, - bool alpha + int x, int y, int sourceLeft, int sourceTop, int sourceRight, int sourceBottom, const std::uint32_t* source, int sourceWidth, int sourceHeight, + bool transparent, bool alpha ) { - this->m_bitmap.CopyRegion( - x, y, sourceLeft, sourceTop, sourceRight, sourceBottom, source, sourceWidth, sourceHeight, transparent, alpha - ); + this->m_bitmap.CopyRegion(x, y, sourceLeft, sourceTop, sourceRight, sourceBottom, source, sourceWidth, sourceHeight, transparent, alpha); } // OFFSET: 0x00547790 @@ -99,12 +81,7 @@ void CDCBitmap::BlendFrom(std::uint32_t x, std::uint32_t y, int width, int heigh // OFFSET: 0x00545E20 // FUNCTION: fn_01838 void CDCBitmap::DrawRleSprite( - int x, - int y, - std::span cells, - const SpriteRleImage* const* const* images, - const std::uint32_t* palette, - int cellCount + int x, int y, std::span cells, const SpriteRleImage* const* const* images, const std::uint32_t* palette, int cellCount ) { this->m_bitmap.DrawRleSprite(x, y, cells, images, palette, cellCount); } @@ -112,22 +89,9 @@ void CDCBitmap::DrawRleSprite( // OFFSET: 0x005460B0 // FUNCTION: fn_01839 void CDCBitmap::DrawSurface( - int x, - int y, - CSurface* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - bool mirrored, - int scaleX, - int scaleY, - int filter, - int format + int x, int y, CSurface* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, bool mirrored, int scaleX, int scaleY, int filter, int format ) { - this->m_bitmap.DrawSurface( - x, y, source, sourceX, sourceY, sourceWidth, sourceHeight, mirrored, scaleX, scaleY, filter, format - ); + this->m_bitmap.DrawSurface(x, y, source, sourceX, sourceY, sourceWidth, sourceHeight, mirrored, scaleX, scaleY, filter, format); } // OFFSET: 0x00547460 @@ -145,51 +109,20 @@ void CDCBitmap::Draw(CRenderSystemBase& system, int x, int y, int width, int hei // OFFSET: 0x00545C40 // FUNCTION: fn_01837 void CDCBitmap::DrawScaledSprite( - int x, - int y, - int width, - int height, - std::span cells, - const SpriteRleImage* const* const* images, - int cellCount, - int offsetX, - int offsetY, - float scale, - const std::uint32_t* palette, - SpriteAtlas& atlas, - CRenderSystemBase& system, - int serviceType, - std::uint32_t reuseDelay + int x, int y, int width, int height, std::span cells, const SpriteRleImage* const* const* images, int cellCount, int offsetX, + int offsetY, float scale, const std::uint32_t* palette, SpriteAtlas& atlas, CRenderSystemBase& system, int serviceType, std::uint32_t reuseDelay ) { - this->m_bitmap.DrawScaledSprite( - x, y, width, height, cells, images, cellCount, offsetX, offsetY, scale, palette, atlas, system, serviceType, - reuseDelay - ); + this->m_bitmap.DrawScaledSprite(x, y, width, height, cells, images, cellCount, offsetX, offsetY, scale, palette, atlas, system, serviceType, reuseDelay); } // OFFSET: 0x005469E0 // FUNCTION: fn_01840 void CDCBitmap::DrawScaledSurface( - int x, - int y, - int width, - int height, - CSurface* source, - int sourceWidth, - int sourceHeight, - float scaleX, - float scaleY, - std::uint32_t color, - bool mirrored, - int offsetX, - int offsetY, - int sourceX, - int sourceY, - int format + int x, int y, int width, int height, CSurface* source, int sourceWidth, int sourceHeight, float scaleX, float scaleY, std::uint32_t color, bool mirrored, + int offsetX, int offsetY, int sourceX, int sourceY, int format ) { this->m_bitmap.DrawScaledSurface( - x, y, width, height, source, sourceWidth, sourceHeight, scaleX, scaleY, color, mirrored, offsetX, offsetY, sourceX, - sourceY, format + x, y, width, height, source, sourceWidth, sourceHeight, scaleX, scaleY, color, mirrored, offsetX, offsetY, sourceX, sourceY, format ); } diff --git a/Source/Render/DeviceContext/DCBitmap.h b/Source/Render/DeviceContext/DCBitmap.h new file mode 100644 index 0000000..63bf2e6 --- /dev/null +++ b/Source/Render/DeviceContext/DCBitmap.h @@ -0,0 +1,57 @@ +#ifndef RAGNAROK_SOURCE_RENDER_DEVICECONTEXT_DCBITMAP_H +#define RAGNAROK_SOURCE_RENDER_DEVICECONTEXT_DCBITMAP_H + +#include "Render/Textures/BitmapPixels.h" +#include "Render/Textures/BitmapTextureCache.h" +#include "Render/DeviceContext/DeviceContext.h" + +class CDCBitmap : public CDC { +public: + CDCBitmap(int width, int height); + ~CDCBitmap() override; + void Grow(std::uint32_t width, std::uint32_t height) override; + bool GetDC(HDC* output) override; + void ReleaseDC(HDC dc) override; + void Copy(int x, int y, int width, int height, const std::uint32_t* source, bool transparent) override; + void ScaleCopy(int x, int y, int sourceWidth, int sourceHeight, int width, int height, const std::uint32_t* source, int option) override; + void CopyRegion( + int x, int y, int sourceLeft, int sourceTop, int sourceRight, int sourceBottom, const std::uint32_t* source, int sourceWidth, int sourceHeight, + bool transparent, bool alpha + ) override; + void CopyFrom(int x, int y, int sourceX, int sourceY, int width, int height, const CDCBitmap& source) override; + void BlendFrom(std::uint32_t x, std::uint32_t y, int width, int height, const CDCBitmap& source) override; + void DrawRleSprite( + int x, int y, std::span cells, const SpriteRleImage* const* const* images, const std::uint32_t* palette, int cellCount + ) override; + void DrawSurface( + int x, int y, CSurface* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, bool mirrored, int scaleX, int scaleY, int filter, int format + ) override; + void Fill(const RECT* rectangle, std::uint32_t color) override; + void Draw(CRenderSystemBase& system, int x, int y, int width, int height, std::uint32_t color) override; + void DrawScaledSprite( + int x, int y, int width, int height, std::span cells, const SpriteRleImage* const* const* images, int cellCount, int offsetX, + int offsetY, float scale, const std::uint32_t* palette, SpriteAtlas& atlas, CRenderSystemBase& system, int serviceType, std::uint32_t reuseDelay + ) override; + void DrawScaledSurface( + int x, int y, int width, int height, CSurface* source, int sourceWidth, int sourceHeight, float scaleX, float scaleY, std::uint32_t color, bool mirrored, + int offsetX, int offsetY, int sourceX, int sourceY, int format + ) override; + void Brighten(int x, int y, int width, int height, int amount) override; + void Dim(int x, int y, int width, int height, int percent) override; + void UploadTexture(CRenderSystemBase& system, CTexture*& texture); + void SetAlpha(bool alpha) { + this->m_cache.m_alpha = alpha; + } + +protected: + /* 0004 */ BitmapPixels m_bitmap; + /* 0020 */ BitmapTextureCache m_cache; +}; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(CDCBitmap) == 44); +#endif + +CDCBitmap* CreateBitmapDC(int width, int height, bool fill); + +#endif diff --git a/Source/Render/DCSurface.cpp b/Source/Render/DeviceContext/DCSurface.cpp similarity index 79% rename from Source/Render/DCSurface.cpp rename to Source/Render/DeviceContext/DCSurface.cpp index a490a2c..456d1bb 100644 --- a/Source/Render/DCSurface.cpp +++ b/Source/Render/DeviceContext/DCSurface.cpp @@ -1,6 +1,6 @@ -#include "Render/DCSurface.h" +#include "Render/DeviceContext/DCSurface.h" #include "Render/RenderSystemBase.h" -#include "Render/Surface.h" +#include "Render/Textures/Surface.h" #include @@ -15,15 +15,11 @@ CRenderer* RenderSystemHolder::CreateRenderer() { return this->system ? this->system->CreateRenderer() : nullptr; } - - - // FUNCTION: fn_02278 HRESULT RenderSystemHolder::Close() { - return this->system ? this->system->Close() : static_cast(0x8000000E); + return this->system ? this->system->Close() : E_ILLEGAL_METHOD_CALL; } - // FUNCTION: fn_02280 void RenderSystemHolder::UpdateOption() { if (this->system) { @@ -50,7 +46,6 @@ std::int32_t RenderSystemHolder::Backend() const { return this->system ? this->system->Backend() : -1; } - // FUNCTION: fn_02287 CTexture* RenderSystemHolder::BackBufferTexture() const { return this->system ? this->system->BackBufferTexture() : nullptr; @@ -73,10 +68,9 @@ bool RenderSystemHolder::IsWindowed() const { // FUNCTION: fn_02295 HRESULT RenderSystemHolder::TestDevice() const { - return this->system ? this->system->TestDevice() : static_cast(0x8000000E); + return this->system ? this->system->TestDevice() : E_ILLEGAL_METHOD_CALL; } - // OFFSET: 0x00548FE0 // FUNCTION: fn_01864 CDCSurface::CDCSurface(std::shared_ptr surface) : m_surface(std::move(surface)) { @@ -116,16 +110,7 @@ void CDCSurface::Copy(int x, int y, int width, int height, const std::uint32_t* // OFFSET: 0x005492F0 // FUNCTION: fn_01880 -void CDCSurface::ScaleCopy( - int x, - int y, - int sourceWidth, - int sourceHeight, - int, - int, - const std::uint32_t* source, - int option -) { +void CDCSurface::ScaleCopy(int x, int y, int sourceWidth, int sourceHeight, int, int, const std::uint32_t* source, int option) { this->m_surface->Upload(x, y, sourceWidth, sourceHeight, source, option, 0); } @@ -141,7 +126,6 @@ void CDCSurface::Draw(CRenderSystemBase&, int x, int y, int width, int height, s this->m_surface->Draw(x, y, width, height, color); } -// The following slots are ret-only bodies in the reference CDCSurface vtable. // OFFSET: 0x00549360 // FUNCTION: fn_01883 void CDCSurface::CopyRegion(int, int, int, int, int, int, const std::uint32_t*, int, int, bool, bool) { @@ -159,14 +143,7 @@ void CDCSurface::BlendFrom(std::uint32_t, std::uint32_t, int, int, const CDCBitm // OFFSET: 0x00549230 // FUNCTION: fn_01870 -void CDCSurface::DrawRleSprite( - int, - int, - std::span, - const SpriteRleImage* const* const*, - const std::uint32_t*, - int -) { +void CDCSurface::DrawRleSprite(int, int, std::span, const SpriteRleImage* const* const*, const std::uint32_t*, int) { } // OFFSET: 0x00549240 @@ -177,44 +154,14 @@ void CDCSurface::DrawSurface(int, int, CSurface*, int, int, int, int, bool, int, // OFFSET: 0x00549220 // FUNCTION: fn_01869 void CDCSurface::DrawScaledSprite( - int, - int, - int, - int, - std::span, - const SpriteRleImage* const* const*, - int, - int, - int, - float, - const std::uint32_t*, - SpriteAtlas&, - CRenderSystemBase&, - int, - std::uint32_t + int, int, int, int, std::span, const SpriteRleImage* const* const*, int, int, int, float, const std::uint32_t*, SpriteAtlas&, + CRenderSystemBase&, int, std::uint32_t ) { } // OFFSET: 0x00549250 // FUNCTION: fn_01872 -void CDCSurface::DrawScaledSurface( - int, - int, - int, - int, - CSurface*, - int, - int, - float, - float, - std::uint32_t, - bool, - int, - int, - int, - int, - int -) { +void CDCSurface::DrawScaledSurface(int, int, int, int, CSurface*, int, int, float, float, std::uint32_t, bool, int, int, int, int, int) { } // OFFSET: 0x00549370 diff --git a/Source/Render/DCSurface.h b/Source/Render/DeviceContext/DCSurface.h similarity index 59% rename from Source/Render/DCSurface.h rename to Source/Render/DeviceContext/DCSurface.h index 1e912b5..c59e50f 100644 --- a/Source/Render/DCSurface.h +++ b/Source/Render/DeviceContext/DCSurface.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_RENDER_DCSURFACE_H -#define RAGNAROK_SOURCE_RENDER_DCSURFACE_H +#ifndef RAGNAROK_SOURCE_RENDER_DEVICECONTEXT_DCSURFACE_H +#define RAGNAROK_SOURCE_RENDER_DEVICECONTEXT_DCSURFACE_H -#include "Render/DeviceContext.h" +#include "Render/DeviceContext/DeviceContext.h" #include "Render/RenderSystemBase.h" #include @@ -43,8 +43,6 @@ __declspec(noinline) inline RenderSystemHolder* GetRenderSystemHolder() { return &holder; } -// RTTI CDCSurface. Owns a shared surface reference. -// Unused virtuals are established empty original bodies, not bring-up stubs. class CDCSurface : public CDC { public: explicit CDCSurface(std::shared_ptr surface); @@ -53,89 +51,28 @@ public: bool GetDC(HDC* output) override; void ReleaseDC(HDC dc) override; void Copy(int x, int y, int width, int height, const std::uint32_t* source, bool transparent) override; - void ScaleCopy( - int x, - int y, - int sourceWidth, - int sourceHeight, - int width, - int height, - const std::uint32_t* source, - int option - ) override; + void ScaleCopy(int x, int y, int sourceWidth, int sourceHeight, int width, int height, const std::uint32_t* source, int option) override; void CopyRegion( - int x, - int y, - int sourceLeft, - int sourceTop, - int sourceRight, - int sourceBottom, - const std::uint32_t* source, - int sourceWidth, - int sourceHeight, - bool transparent, - bool alpha + int x, int y, int sourceLeft, int sourceTop, int sourceRight, int sourceBottom, const std::uint32_t* source, int sourceWidth, int sourceHeight, + bool transparent, bool alpha ) override; void CopyFrom(int x, int y, int sourceX, int sourceY, int width, int height, const CDCBitmap& source) override; void BlendFrom(std::uint32_t x, std::uint32_t y, int width, int height, const CDCBitmap& source) override; void DrawRleSprite( - int x, - int y, - std::span cells, - const SpriteRleImage* const* const* images, - const std::uint32_t* palette, - int cellCount + int x, int y, std::span cells, const SpriteRleImage* const* const* images, const std::uint32_t* palette, int cellCount ) override; void DrawSurface( - int x, - int y, - CSurface* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - bool mirrored, - int scaleX, - int scaleY, - int filter, - int format + int x, int y, CSurface* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, bool mirrored, int scaleX, int scaleY, int filter, int format ) override; void Fill(const RECT* rectangle, std::uint32_t color) override; void Draw(CRenderSystemBase& system, int x, int y, int width, int height, std::uint32_t color) override; void DrawScaledSprite( - int x, - int y, - int width, - int height, - std::span cells, - const SpriteRleImage* const* const* images, - int cellCount, - int offsetX, - int offsetY, - float scale, - const std::uint32_t* palette, - SpriteAtlas& atlas, - CRenderSystemBase& system, - int serviceType, - std::uint32_t reuseDelay + int x, int y, int width, int height, std::span cells, const SpriteRleImage* const* const* images, int cellCount, int offsetX, + int offsetY, float scale, const std::uint32_t* palette, SpriteAtlas& atlas, CRenderSystemBase& system, int serviceType, std::uint32_t reuseDelay ) override; void DrawScaledSurface( - int x, - int y, - int width, - int height, - CSurface* source, - int sourceWidth, - int sourceHeight, - float scaleX, - float scaleY, - std::uint32_t color, - bool mirrored, - int offsetX, - int offsetY, - int sourceX, - int sourceY, - int format + int x, int y, int width, int height, CSurface* source, int sourceWidth, int sourceHeight, float scaleX, float scaleY, std::uint32_t color, bool mirrored, + int offsetX, int offsetY, int sourceX, int sourceY, int format ) override; void Brighten(int x, int y, int width, int height, int amount) override; void Dim(int x, int y, int width, int height, int percent) override; diff --git a/Source/Render/DeviceContext.cpp b/Source/Render/DeviceContext/DeviceContext.cpp similarity index 70% rename from Source/Render/DeviceContext.cpp rename to Source/Render/DeviceContext/DeviceContext.cpp index 02eca26..98f2197 100644 --- a/Source/Render/DeviceContext.cpp +++ b/Source/Render/DeviceContext/DeviceContext.cpp @@ -1,4 +1,4 @@ -#include "Render/DeviceContext.h" +#include "Render/DeviceContext/DeviceContext.h" // OFFSET: 0x005459E0 // FUNCTION: fn_01834 diff --git a/Source/Render/DeviceContext/DeviceContext.h b/Source/Render/DeviceContext/DeviceContext.h new file mode 100644 index 0000000..3695e31 --- /dev/null +++ b/Source/Render/DeviceContext/DeviceContext.h @@ -0,0 +1,51 @@ +#ifndef RAGNAROK_SOURCE_RENDER_DEVICECONTEXT_DEVICECONTEXT_H +#define RAGNAROK_SOURCE_RENDER_DEVICECONTEXT_DEVICECONTEXT_H + +#include "Render/Textures/SpritePixels.h" + +#include + +class CSurface; +class CDCBitmap; +class CRenderSystemBase; +class SpriteAtlas; + +class CDC { +public: + virtual ~CDC(); + virtual void Grow(std::uint32_t width, std::uint32_t height) = 0; + virtual bool GetDC(HDC* output) = 0; + virtual void ReleaseDC(HDC dc) = 0; + virtual void Copy(int x, int y, int width, int height, const std::uint32_t* source, bool transparent) = 0; + virtual void ScaleCopy(int x, int y, int sourceWidth, int sourceHeight, int width, int height, const std::uint32_t* source, int option) = 0; + virtual void CopyRegion( + int x, int y, int sourceLeft, int sourceTop, int sourceRight, int sourceBottom, const std::uint32_t* source, int sourceWidth, int sourceHeight, + bool transparent, bool alpha + ) = 0; + virtual void CopyFrom(int x, int y, int sourceX, int sourceY, int width, int height, const CDCBitmap& source) = 0; + virtual void BlendFrom(std::uint32_t x, std::uint32_t y, int width, int height, const CDCBitmap& source) = 0; + virtual void DrawRleSprite( + int x, int y, std::span cells, const SpriteRleImage* const* const* images, const std::uint32_t* palette, int cellCount + ) = 0; + virtual void DrawSurface( + int x, int y, CSurface* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, bool mirrored, int scaleX, int scaleY, int filter, int format + ) = 0; + virtual void Fill(const RECT* rectangle, std::uint32_t color) = 0; + virtual void Draw(CRenderSystemBase& system, int x, int y, int width, int height, std::uint32_t color) = 0; + virtual void DrawScaledSprite( + int x, int y, int width, int height, std::span cells, const SpriteRleImage* const* const* images, int cellCount, int offsetX, + int offsetY, float scale, const std::uint32_t* palette, SpriteAtlas& atlas, CRenderSystemBase& system, int serviceType, std::uint32_t reuseDelay + ) = 0; + virtual void DrawScaledSurface( + int x, int y, int width, int height, CSurface* source, int sourceWidth, int sourceHeight, float scaleX, float scaleY, std::uint32_t color, bool mirrored, + int offsetX, int offsetY, int sourceX, int sourceY, int format + ) = 0; + virtual void Brighten(int x, int y, int width, int height, int amount) = 0; + virtual void Dim(int x, int y, int width, int height, int percent) = 0; +}; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(CDC) == 4); +#endif + +#endif diff --git a/Source/Render/Direct3DErrors.cpp b/Source/Render/Direct3DErrors.cpp index a8d082f..e43b71a 100644 --- a/Source/Render/Direct3DErrors.cpp +++ b/Source/Render/Direct3DErrors.cpp @@ -1,5 +1,7 @@ #include "Render/Direct3DErrors.h" +#include + namespace { struct Error { HRESULT value; @@ -7,64 +9,44 @@ namespace { const char* description; }; - // Result-name and description tables. constexpr Error errors[] = { - {static_cast(0), "D3D_OK", "OK"}, - {static_cast(141953135), "D3DOK_NOAUTOGEN", - "This is a success code. However, the autogeneration of mipmaps is not supported for this format."}, - {static_cast(141953141), "S_NOT_RESIDENT", "Resource not resident in memory."}, - {static_cast(141953142), "S_RESIDENT_IN_SHARED_MEMORY", "Resource resident in shared memory."}, - {static_cast(141953143), "S_PRESENT_MODE_CHANGED", "The desktop display mode has been changed."}, - {static_cast(141953144), "S_PRESENT_OCCLUDED", - "Client window is occluded. (minimized or other fullscreen)"}, - {static_cast(-2005532292), "D3DERR_OUTOFVIDEOMEMORY", - "Direct3D does not have enough display memory to perform the operation."}, - {static_cast(-2005532132), "D3DERR_WASSTILLDRAWING", - "The previous blit operation that is transferring information to or from this surface is incomplete."}, - {static_cast(-2005530600), "D3DERR_WRONGTEXTUREFORMAT", - "The pixel format of the texture surface is not valid."}, - {static_cast(-2005530599), "D3DERR_UNSUPPORTEDCOLOROPERATION", + {D3D_OK, "D3D_OK", "OK"}, + {D3DOK_NOAUTOGEN, "D3DOK_NOAUTOGEN", "This is a success code. However, the autogeneration of mipmaps is not supported for this format."}, + {S_NOT_RESIDENT, "S_NOT_RESIDENT", "Resource not resident in memory."}, + {S_RESIDENT_IN_SHARED_MEMORY, "S_RESIDENT_IN_SHARED_MEMORY", "Resource resident in shared memory."}, + {S_PRESENT_MODE_CHANGED, "S_PRESENT_MODE_CHANGED", "The desktop display mode has been changed."}, + {S_PRESENT_OCCLUDED, "S_PRESENT_OCCLUDED", "Client window is occluded. (minimized or other fullscreen)"}, + {D3DERR_OUTOFVIDEOMEMORY, "D3DERR_OUTOFVIDEOMEMORY", "Direct3D does not have enough display memory to perform the operation."}, + {D3DERR_WASSTILLDRAWING, "D3DERR_WASSTILLDRAWING", "The previous blit operation that is transferring information to or from this surface is incomplete."}, + {D3DERR_WRONGTEXTUREFORMAT, "D3DERR_WRONGTEXTUREFORMAT", "The pixel format of the texture surface is not valid."}, + {D3DERR_UNSUPPORTEDCOLOROPERATION, "D3DERR_UNSUPPORTEDCOLOROPERATION", "The device does not support a specified texture-blending operation for color values."}, - {static_cast(-2005530598), "D3DERR_UNSUPPORTEDCOLORARG", - "The device does not support a specified texture-blending argument for color values."}, - {static_cast(-2005530597), "D3DERR_UNSUPPORTEDALPHAOPERATION", + {D3DERR_UNSUPPORTEDCOLORARG, "D3DERR_UNSUPPORTEDCOLORARG", "The device does not support a specified texture-blending argument for color values."}, + {D3DERR_UNSUPPORTEDALPHAOPERATION, "D3DERR_UNSUPPORTEDALPHAOPERATION", "The device does not support a specified texture-blending operation for the alpha channel."}, - {static_cast(-2005530596), "D3DERR_UNSUPPORTEDALPHAARG", - "The device does not support a specified texture-blending argument for the alpha channel."}, - {static_cast(-2005530595), "D3DERR_TOOMANYOPERATIONS", - "The application is requesting more texture-filtering operations than the device supports."}, - {static_cast(-2005530594), "D3DERR_CONFLICTINGTEXTUREFILTER", - "The current texture filters cannot be used together."}, - {static_cast(-2005530593), "D3DERR_UNSUPPORTEDFACTORVALUE", - "The device does not support the specified texture factor value."}, - {static_cast(-2005530591), "D3DERR_CONFLICTINGRENDERSTATE", - "The currently set render states cannot be used together."}, - {static_cast(-2005530590), "D3DERR_UNSUPPORTEDTEXTUREFILTER", - "The device does not support the specified texture filter."}, - {static_cast(-2005530586), "D3DERR_CONFLICTINGTEXTUREPALETTE", - "The current textures cannot be used simultaneously."}, - {static_cast(-2005530585), "D3DERR_DRIVERINTERNALERROR", "Internal driver error."}, - {static_cast(-2005530522), "D3DERR_NOTFOUND", "The requested item was not found."}, - {static_cast(-2005530521), "D3DERR_MOREDATA", - "There is more data available than the specified buffer size can hold."}, - {static_cast(-2005530520), "D3DERR_DEVICELOST", - "The device has been lost but cannot be reset at this time. "}, - {static_cast(-2005530519), "D3DERR_DEVICENOTRESET", - "The device has been lost but can be reset at this time."}, - {static_cast(-2005530518), "D3DERR_NOTAVAILABLE", "Not available"}, - {static_cast(-2005530517), "D3DERR_INVALIDDEVICE", "The requested device type is not valid."}, - {static_cast(-2005530516), "D3DERR_INVALIDCALL", "The method call is invalid."}, - {static_cast(-2005530515), "D3DERR_DRIVERINVALIDCALL", "Driver invalid call"}, - {static_cast(-2005530512), "D3DERR_DEVICEREMOVED", "The hardware adapter has been removed."}, - {static_cast(-2005530508), "D3DERR_DEVICEHUNG", "Hardware adapter reset by the OS."}, - {static_cast(-2005530501), "D3DERR_UNSUPPORTEDOVERLAY", - "The device does not support overlay for the specified size or display mode."}, - {static_cast(-2005530500), "D3DERR_UNSUPPORTEDOVERLAYFORMAT", - "The device does not support overlay for the specified surface format."}, - {static_cast(-2005530499), "D3DERR_CANNOTPROTECTCONTENT", "Contect protection not available."}, - {static_cast(-2005530498), "D3DERR_UNSUPPORTEDCRYPTO", - "The specified cryptographic algorithm is not supported."}, - {static_cast(-2005530492), "D3DERR_PRESENT_STATISTICS_DISJOINT", "Presentation statistics are disjoint."}, + {D3DERR_UNSUPPORTEDALPHAARG, "D3DERR_UNSUPPORTEDALPHAARG", "The device does not support a specified texture-blending argument for the alpha channel."}, + {D3DERR_TOOMANYOPERATIONS, "D3DERR_TOOMANYOPERATIONS", "The application is requesting more texture-filtering operations than the device supports."}, + {D3DERR_CONFLICTINGTEXTUREFILTER, "D3DERR_CONFLICTINGTEXTUREFILTER", "The current texture filters cannot be used together."}, + {D3DERR_UNSUPPORTEDFACTORVALUE, "D3DERR_UNSUPPORTEDFACTORVALUE", "The device does not support the specified texture factor value."}, + {D3DERR_CONFLICTINGRENDERSTATE, "D3DERR_CONFLICTINGRENDERSTATE", "The currently set render states cannot be used together."}, + {D3DERR_UNSUPPORTEDTEXTUREFILTER, "D3DERR_UNSUPPORTEDTEXTUREFILTER", "The device does not support the specified texture filter."}, + {D3DERR_CONFLICTINGTEXTUREPALETTE, "D3DERR_CONFLICTINGTEXTUREPALETTE", "The current textures cannot be used simultaneously."}, + {D3DERR_DRIVERINTERNALERROR, "D3DERR_DRIVERINTERNALERROR", "Internal driver error."}, + {D3DERR_NOTFOUND, "D3DERR_NOTFOUND", "The requested item was not found."}, + {D3DERR_MOREDATA, "D3DERR_MOREDATA", "There is more data available than the specified buffer size can hold."}, + {D3DERR_DEVICELOST, "D3DERR_DEVICELOST", "The device has been lost but cannot be reset at this time. "}, + {D3DERR_DEVICENOTRESET, "D3DERR_DEVICENOTRESET", "The device has been lost but can be reset at this time."}, + {D3DERR_NOTAVAILABLE, "D3DERR_NOTAVAILABLE", "Not available"}, + {D3DERR_INVALIDDEVICE, "D3DERR_INVALIDDEVICE", "The requested device type is not valid."}, + {D3DERR_INVALIDCALL, "D3DERR_INVALIDCALL", "The method call is invalid."}, + {D3DERR_DRIVERINVALIDCALL, "D3DERR_DRIVERINVALIDCALL", "Driver invalid call"}, + {D3DERR_DEVICEREMOVED, "D3DERR_DEVICEREMOVED", "The hardware adapter has been removed."}, + {D3DERR_DEVICEHUNG, "D3DERR_DEVICEHUNG", "Hardware adapter reset by the OS."}, + {D3DERR_UNSUPPORTEDOVERLAY, "D3DERR_UNSUPPORTEDOVERLAY", "The device does not support overlay for the specified size or display mode."}, + {D3DERR_UNSUPPORTEDOVERLAYFORMAT, "D3DERR_UNSUPPORTEDOVERLAYFORMAT", "The device does not support overlay for the specified surface format."}, + {D3DERR_CANNOTPROTECTCONTENT, "D3DERR_CANNOTPROTECTCONTENT", "Contect protection not available."}, + {D3DERR_UNSUPPORTEDCRYPTO, "D3DERR_UNSUPPORTEDCRYPTO", "The specified cryptographic algorithm is not supported."}, + {D3DERR_PRESENT_STATISTICS_DISJOINT, "D3DERR_PRESENT_STATISTICS_DISJOINT", "Presentation statistics are disjoint."}, }; } diff --git a/Source/Render/DisplayMode.cpp b/Source/Render/DisplayMode.cpp index 8e9ebc5..98ff0e1 100644 --- a/Source/Render/DisplayMode.cpp +++ b/Source/Render/DisplayMode.cpp @@ -73,17 +73,7 @@ extern char g_deviceName[40]; // FUNCTION: fn_02297 LSTATUS SaveDisplayDeviceSettings() { HKEY key = nullptr; - LSTATUS status = RegCreateKeyExA( - HKEY_LOCAL_MACHINE, - g_subKey, - 0, - nullptr, - 0, - KEY_ALL_ACCESS, - nullptr, - &key, - nullptr - ); + LSTATUS status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, g_subKey, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &key, nullptr); if (status == ERROR_SUCCESS) { RegSetValueExA(key, "GUIDDEVICE", 0, REG_BINARY, g_guidDevice, 16); diff --git a/Source/Render/FogConfiguration.h b/Source/Render/FogConfiguration.h index bdf881a..1b37255 100644 --- a/Source/Render/FogConfiguration.h +++ b/Source/Render/FogConfiguration.h @@ -1,8 +1,6 @@ #ifndef RAGNAROK_SOURCE_RENDER_FOGCONFIGURATION_H #define RAGNAROK_SOURCE_RENDER_FOGCONFIGURATION_H -// Original shared renderer fog configuration globals, borrowed by both backends. -// Mode defaults are reset by Set, not guessed during application. struct FogConfiguration { unsigned color; unsigned vertexMode; diff --git a/Source/Render/Primitives/AlphaRectangle.h b/Source/Render/Primitives/AlphaRectangle.h new file mode 100644 index 0000000..c130810 --- /dev/null +++ b/Source/Render/Primitives/AlphaRectangle.h @@ -0,0 +1,15 @@ +#ifndef RAGNAROK_SOURCE_RENDER_PRIMITIVES_ALPHARECTANGLE_H +#define RAGNAROK_SOURCE_RENDER_PRIMITIVES_ALPHARECTANGLE_H + +#include + +class RenderPrimitivePool; +class TextureCache; +struct RenderQueues; + +void DrawAlphaRectangle( + RenderPrimitivePool& primitives, TextureCache& textures, RenderQueues& queues, int x, int y, int width, int height, std::uint32_t color, bool depthAlpha, + float depthStart, float depthEnd +); + +#endif diff --git a/Source/Render/Primitives/DepthAlpha.cpp b/Source/Render/Primitives/DepthAlpha.cpp new file mode 100644 index 0000000..ee85209 --- /dev/null +++ b/Source/Render/Primitives/DepthAlpha.cpp @@ -0,0 +1,43 @@ +#include "Render/Primitives/DepthAlpha.h" +#include "Render/Primitives/LightmappedPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" + +#include + +// OFFSET: 0x0055D190 +// FUNCTION: fn_02100 +std::uint32_t DepthAlpha(float reciprocalDepth, float start, float end) { + float value = ((1.0f / reciprocalDepth) - 10.0f) / 1490.0f; + const float range = end - start; + + if (range != 0.0f) { + value = (value - start) / range; + } + + const float lower = 0.0f > value ? 0.0f : value; + const float upper = 1.0f < lower ? 1.0f : lower; + const float alpha = (1.0f - upper) * 255.0f; + const std::uint32_t converted = std::isnan(alpha) ? UINT32_MAX : static_cast(alpha); + + return converted << 24; +} + +// OFFSET: 0x005694A0 +// FUNCTION: fn_02260 +void ApplyDepthAlpha(RenderCommand& command, float start, float end) { + if (command.vertexCount > 0) { + for (int index = 0; index < command.vertexCount; ++index) { + command.vertices[index].specular = DepthAlpha(command.vertices[index].rhw, start, end); + } + } +} + +// OFFSET: 0x005694E0 +// FUNCTION: fn_02261 +void ApplyDepthAlpha(LightmappedPrimitive& command, float start, float end) { + if (command.vertexCount > 0) { + for (int index = 0; index < command.vertexCount; ++index) { + command.vertices[index].specular = DepthAlpha(command.vertices[index].rhw, start, end); + } + } +} diff --git a/Source/Render/DepthAlpha.h b/Source/Render/Primitives/DepthAlpha.h similarity index 73% rename from Source/Render/DepthAlpha.h rename to Source/Render/Primitives/DepthAlpha.h index dfdc137..24843e0 100644 --- a/Source/Render/DepthAlpha.h +++ b/Source/Render/Primitives/DepthAlpha.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_DEPTHALPHA_H -#define RAGNAROK_SOURCE_RENDER_DEPTHALPHA_H +#ifndef RAGNAROK_SOURCE_RENDER_PRIMITIVES_DEPTHALPHA_H +#define RAGNAROK_SOURCE_RENDER_PRIMITIVES_DEPTHALPHA_H #include diff --git a/Source/Render/LightmappedPrimitive.cpp b/Source/Render/Primitives/LightmappedPrimitive.cpp similarity index 77% rename from Source/Render/LightmappedPrimitive.cpp rename to Source/Render/Primitives/LightmappedPrimitive.cpp index 53f4101..d82c7ab 100644 --- a/Source/Render/LightmappedPrimitive.cpp +++ b/Source/Render/Primitives/LightmappedPrimitive.cpp @@ -1,20 +1,20 @@ -#include "Render/DepthAlpha.h" -#include "Render/LightmappedPrimitive.h" +#include "Render/Primitives/DepthAlpha.h" +#include "Render/Primitives/LightmappedPrimitive.h" #include +#include +#include #include // OFFSET: 0x005690E0 // FUNCTION: fn_02248 LightmappedCommand::LightmappedCommand() - : vertices(nullptr), vertexCount(0), indices(nullptr), indexCount(0), texture(nullptr), lightmap(nullptr), - primitiveType(5) { + : vertices(nullptr), vertexCount(0), indices(nullptr), indexCount(0), texture(nullptr), lightmap(nullptr), primitiveType(D3DPT_TRIANGLESTRIP) { } // OFFSET: 0x00569020 // FUNCTION: fn_02246 -LightmappedPrimitive::LightmappedPrimitive() - : vertices(this->quad), vertexCount(4), indices(nullptr), indexCount(0), primitiveType(5) { +LightmappedPrimitive::LightmappedPrimitive() : vertices(this->quad), vertexCount(4), indices(nullptr), indexCount(0), primitiveType(D3DPT_TRIANGLESTRIP) { for (LightmappedVertex& vertex : this->quad) { vertex.x = 0.0f; vertex.y = 0.0f; @@ -24,7 +24,6 @@ LightmappedPrimitive::LightmappedPrimitive() vertex.specular = 0xFF000000u; vertex.u = 0.0f; vertex.v = 0.0f; - // The original leaves the second UV pair and texture pointers untouched. } } @@ -59,13 +58,7 @@ void LightmappedPrimitivePool::Rewind() { // OFFSET: 0x00559BE0 // FUNCTION: fn_02071 -void LightmappedQueues::Submit( - LightmappedPrimitive* primitive, - int queue, - bool depthAlpha, - float depthStart, - float depthEnd -) { +void LightmappedQueues::Submit(LightmappedPrimitive* primitive, int queue, bool depthAlpha, float depthStart, float depthEnd) { if (depthAlpha) { ApplyDepthAlpha(*primitive, depthStart, depthEnd); } diff --git a/Source/Render/LightmappedPrimitive.h b/Source/Render/Primitives/LightmappedPrimitive.h similarity index 79% rename from Source/Render/LightmappedPrimitive.h rename to Source/Render/Primitives/LightmappedPrimitive.h index d11b911..a0172bc 100644 --- a/Source/Render/LightmappedPrimitive.h +++ b/Source/Render/Primitives/LightmappedPrimitive.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_LIGHTMAPPEDPRIMITIVE_H -#define RAGNAROK_SOURCE_RENDER_LIGHTMAPPEDPRIMITIVE_H +#ifndef RAGNAROK_SOURCE_RENDER_PRIMITIVES_LIGHTMAPPEDPRIMITIVE_H +#define RAGNAROK_SOURCE_RENDER_PRIMITIVES_LIGHTMAPPEDPRIMITIVE_H #include #include @@ -23,7 +23,7 @@ struct LightmappedCommand { LightmappedCommand(); LightmappedVertex* vertices; - std::uint32_t vertexCount; + std::int32_t vertexCount; std::uint16_t* indices; std::uint32_t indexCount; CTexture* texture; @@ -31,13 +31,12 @@ struct LightmappedCommand { std::uint32_t primitiveType; }; - struct LightmappedPrimitive { LightmappedPrimitive(); LightmappedPrimitive(const LightmappedPrimitive& other); LightmappedVertex* vertices; - std::uint32_t vertexCount; + std::int32_t vertexCount; std::uint16_t* indices; std::uint32_t indexCount; CTexture* texture; @@ -46,7 +45,6 @@ struct LightmappedPrimitive { LightmappedVertex quad[4]; }; -// Renderer subobject +0x90: one 188-byte value per deque block. class LightmappedPrimitivePool { public: LightmappedPrimitivePool(); @@ -58,8 +56,6 @@ private: std::deque::iterator m_current; }; -// Original renderer vectors +0x1F8/+0x204 hold dual-texture command pointers, -// not the depth-keyed records used by neighboring queues. struct LightmappedQueues { std::vector first; std::vector second; diff --git a/Source/Render/RenderCommandPool.cpp b/Source/Render/Primitives/RenderCommandPool.cpp similarity index 93% rename from Source/Render/RenderCommandPool.cpp rename to Source/Render/Primitives/RenderCommandPool.cpp index ed57d48..e54f019 100644 --- a/Source/Render/RenderCommandPool.cpp +++ b/Source/Render/Primitives/RenderCommandPool.cpp @@ -1,4 +1,4 @@ -#include "Render/RenderCommandPool.h" +#include "Render/Primitives/RenderCommandPool.h" #include @@ -17,6 +17,7 @@ RenderCommand* RenderCommandPool::Acquire() { this->m_current = this->m_commands.end(); return &this->m_commands.back(); } + RenderCommand* command = &*this->m_current++; return new (command) RenderCommand; } diff --git a/Source/Render/RenderCommandPool.h b/Source/Render/Primitives/RenderCommandPool.h similarity index 60% rename from Source/Render/RenderCommandPool.h rename to Source/Render/Primitives/RenderCommandPool.h index ff1128e..1411918 100644 --- a/Source/Render/RenderCommandPool.h +++ b/Source/Render/Primitives/RenderCommandPool.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERCOMMANDPOOL_H -#define RAGNAROK_SOURCE_RENDER_RENDERCOMMANDPOOL_H +#ifndef RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERCOMMANDPOOL_H +#define RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERCOMMANDPOOL_H -#include "Render/RenderPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" #include -// Original renderer subobject+0x50; commands borrow their vertex storage. class RenderCommandPool { public: RenderCommandPool(); diff --git a/Source/Render/RenderPrimitive.cpp b/Source/Render/Primitives/RenderPrimitive.cpp similarity index 81% rename from Source/Render/RenderPrimitive.cpp rename to Source/Render/Primitives/RenderPrimitive.cpp index 75aa4b1..96c858f 100644 --- a/Source/Render/RenderPrimitive.cpp +++ b/Source/Render/Primitives/RenderPrimitive.cpp @@ -1,7 +1,8 @@ -#include "Render/RenderPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" #include "Render/Renderer.h" #include +#include #include // GLOBAL: gl_24481 @@ -17,6 +18,7 @@ RenderVertex* RenderVertex::Reset() { this->specular = 0xFF000000; this->u = 0; this->v = 0; + return this; } @@ -24,7 +26,6 @@ RenderVertex* RenderVertex::Reset() { // FUNCTION: fn_02263 bool RenderTriangle::Visible() const { for (const RenderVertex& vertex : this->vertices) { - // COMISS 0, rhw / JNB rejects <= 0, but not unordered values. if (vertex.rhw <= 0.0f) { return false; } @@ -36,8 +37,8 @@ bool RenderTriangle::Visible() const { // OFFSET: 0x00568F40 // FUNCTION: fn_02244 RenderCommand::RenderCommand() - : vertices(nullptr), vertexCount(0), texture(nullptr), indices(nullptr), indexCount(0), unknown_0014(1), - unknown_0018(0), unknown_001C(0), unknown_0020(0), primitiveType(4) { + : vertices(nullptr), vertexCount(0), texture(nullptr), indices(nullptr), indexCount(0), unknown_0014(1), unknown_0018(0), unknown_001C(0), unknown_0020(0), + primitiveType(D3DPT_TRIANGLELIST) { } // OFFSET: 0x005691D0 @@ -45,8 +46,8 @@ RenderCommand::RenderCommand() RenderPrimitive::RenderPrimitive() : RenderCommand() { this->vertices = this->quad; this->vertexCount = 4; - this->primitiveType = 5; - // Original writes only the low word at+0x14; +0x16 remains untouched. + this->primitiveType = D3DPT_TRIANGLESTRIP; + for (RenderVertex& vertex : this->quad) { vertex.x = 0; vertex.y = 0; @@ -65,7 +66,6 @@ RenderPrimitive::RenderPrimitive(const RenderPrimitive& other) : RenderPrimitive std::memcpy(this->quad, other.quad, sizeof(this->quad)); } - // OFFSET: 0x005692F0 // FUNCTION: fn_02253 RenderCommand* RenderCommand::FreeVertices() { @@ -73,8 +73,6 @@ RenderCommand* RenderCommand::FreeVertices() { ::operator delete(this->vertices); this->vertices = nullptr; } + return this; } - - - diff --git a/Source/Render/RenderPrimitive.h b/Source/Render/Primitives/RenderPrimitive.h similarity index 79% rename from Source/Render/RenderPrimitive.h rename to Source/Render/Primitives/RenderPrimitive.h index db94664..34bc483 100644 --- a/Source/Render/RenderPrimitive.h +++ b/Source/Render/Primitives/RenderPrimitive.h @@ -1,12 +1,11 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERPRIMITIVE_H -#define RAGNAROK_SOURCE_RENDER_RENDERPRIMITIVE_H +#ifndef RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERPRIMITIVE_H +#define RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERPRIMITIVE_H #include #include class CTexture; -// Reconstructed names for the original 32-byte transformed/textured vertex. struct RenderVertex { float x; float y; @@ -29,10 +28,9 @@ struct RenderTriangle { bool Visible() const; }; -// Original 40-byte command header; radial commands borrow an external vertex array. struct RenderCommand { RenderVertex* vertices; - std::uint32_t vertexCount; + std::int32_t vertexCount; CTexture* texture; std::uint16_t* indices; std::uint32_t indexCount; @@ -50,7 +48,6 @@ struct RenderCommand { void Draw(int unused); }; -// Quad command acquired from renderer's reusable pool. struct RenderPrimitive : RenderCommand { RenderVertex quad[4]; diff --git a/Source/Render/RenderPrimitivePool.cpp b/Source/Render/Primitives/RenderPrimitivePool.cpp similarity index 87% rename from Source/Render/RenderPrimitivePool.cpp rename to Source/Render/Primitives/RenderPrimitivePool.cpp index 99520c5..0aac7ff 100644 --- a/Source/Render/RenderPrimitivePool.cpp +++ b/Source/Render/Primitives/RenderPrimitivePool.cpp @@ -1,4 +1,4 @@ -#include "Render/RenderPrimitivePool.h" +#include "Render/Primitives/RenderPrimitivePool.h" #include @@ -21,8 +21,9 @@ RenderPrimitive* RenderPrimitivePool::Acquire() { this->m_current = this->m_commands.end(); return &this->m_commands.back(); } + RenderPrimitive* command = &*this->m_current++; - // Reinitialize the reused value; the original preserves bytes+0x16..0x17. + return new (command) RenderPrimitive; } diff --git a/Source/Render/RenderPrimitivePool.h b/Source/Render/Primitives/RenderPrimitivePool.h similarity index 55% rename from Source/Render/RenderPrimitivePool.h rename to Source/Render/Primitives/RenderPrimitivePool.h index 1550b87..3d7353a 100644 --- a/Source/Render/RenderPrimitivePool.h +++ b/Source/Render/Primitives/RenderPrimitivePool.h @@ -1,12 +1,10 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERPRIMITIVEPOOL_H -#define RAGNAROK_SOURCE_RENDER_RENDERPRIMITIVEPOOL_H +#ifndef RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERPRIMITIVEPOOL_H +#define RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERPRIMITIVEPOOL_H -#include "Render/RenderPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" #include -// Original contiguous renderer subobject at +0x70. std::deque<168-byte value> -// uses one value per block, matching original map/block allocation semantics. class RenderPrimitivePool { public: RenderPrimitivePool(); diff --git a/Source/Render/RenderQueues.cpp b/Source/Render/Primitives/RenderQueues.cpp similarity index 89% rename from Source/Render/RenderQueues.cpp rename to Source/Render/Primitives/RenderQueues.cpp index 186ef38..7ce3e5c 100644 --- a/Source/Render/RenderQueues.cpp +++ b/Source/Render/Primitives/RenderQueues.cpp @@ -1,6 +1,6 @@ -#include "Render/DepthAlpha.h" -#include "Render/RenderCommandPool.h" -#include "Render/RenderQueues.h" +#include "Render/Primitives/DepthAlpha.h" +#include "Render/Primitives/RenderCommandPool.h" +#include "Render/Primitives/RenderQueues.h" #include @@ -31,16 +31,11 @@ RenderQueues::RenderQueues() { // OFFSET: 0x00559CA0 // FUNCTION: fn_02073 -void RenderQueues::Submit( - RenderCommand* primitive, - std::uint16_t flags, - bool depthAlpha, - float depthStart, - float depthEnd -) { +void RenderQueues::Submit(RenderCommand* primitive, std::uint16_t flags, bool depthAlpha, float depthStart, float depthEnd) { if (depthAlpha) { ApplyDepthAlpha(*primitive, depthStart, depthEnd); } + if (flags & 1) { const auto first = [&]() { return primitive->vertices[0].rhw; }; const auto average = [&]() { @@ -93,14 +88,7 @@ void RenderQueues::Submit( // OFFSET: 0x00559F70 // FUNCTION: fn_02074 -void RenderQueues::SubmitTriangle( - RenderTriangle& triangle, - std::uint16_t flags, - RenderCommandPool& pool, - bool depthAlpha, - float depthStart, - float depthEnd -) { +void RenderQueues::SubmitTriangle(RenderTriangle& triangle, std::uint16_t flags, RenderCommandPool& pool, bool depthAlpha, float depthStart, float depthEnd) { RenderCommand* command = pool.Acquire(); command->vertices = triangle.vertices; command->vertexCount = 3; diff --git a/Source/Render/RenderQueues.h b/Source/Render/Primitives/RenderQueues.h similarity index 70% rename from Source/Render/RenderQueues.h rename to Source/Render/Primitives/RenderQueues.h index 8dc98cd..ace4712 100644 --- a/Source/Render/RenderQueues.h +++ b/Source/Render/Primitives/RenderQueues.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERQUEUES_H -#define RAGNAROK_SOURCE_RENDER_RENDERQUEUES_H +#ifndef RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERQUEUES_H +#define RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERQUEUES_H -#include "Render/LightmappedPrimitive.h" -#include "Render/RenderPrimitive.h" +#include "Render/Primitives/LightmappedPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" #include @@ -11,8 +11,6 @@ struct DepthPrimitive { RenderCommand* primitive; }; -// Recovered renderer fields +0x15C..+0x24B. Byte suffixes retain unknown -// original queue meanings; commands and their vertex storage remain borrowed. struct RenderQueues { std::vector queue_015C; std::vector queue_0168; @@ -36,14 +34,7 @@ struct RenderQueues { RenderQueues(); void Submit(RenderCommand* primitive, std::uint16_t flags, bool depthAlpha, float depthStart, float depthEnd); - void SubmitTriangle( - RenderTriangle& triangle, - std::uint16_t flags, - class RenderCommandPool& pool, - bool depthAlpha, - float depthStart, - float depthEnd - ); + void SubmitTriangle(RenderTriangle& triangle, std::uint16_t flags, class RenderCommandPool& pool, bool depthAlpha, float depthStart, float depthEnd); void Clear(); }; diff --git a/Source/Render/RenderVertexPool.cpp b/Source/Render/Primitives/RenderVertexPool.cpp similarity index 97% rename from Source/Render/RenderVertexPool.cpp rename to Source/Render/Primitives/RenderVertexPool.cpp index 84d473d..d0e6c11 100644 --- a/Source/Render/RenderVertexPool.cpp +++ b/Source/Render/Primitives/RenderVertexPool.cpp @@ -1,4 +1,4 @@ -#include "Render/RenderVertexPool.h" +#include "Render/Primitives/RenderVertexPool.h" #include @@ -36,6 +36,7 @@ RenderVertexPool::Block& RenderVertexPool::Activate(unsigned capacity) { auto block = std::make_unique(); block->reserve(capacity); this->m_active.push_front(std::move(block)); + return *this->m_active.front(); } @@ -51,6 +52,7 @@ RenderVertex* RenderVertexPool::Acquire(unsigned count) { const unsigned first = static_cast(block->size()); Append(*block, count); this->m_used += count; + return block->data() + first; } } @@ -58,6 +60,7 @@ RenderVertex* RenderVertexPool::Acquire(unsigned count) { Block& block = this->Activate(std::max(this->m_minimum, count)); Append(block, count); this->m_used += count; + return block.data(); } diff --git a/Source/Render/RenderVertexPool.h b/Source/Render/Primitives/RenderVertexPool.h similarity index 63% rename from Source/Render/RenderVertexPool.h rename to Source/Render/Primitives/RenderVertexPool.h index dfa5f91..3a8c958 100644 --- a/Source/Render/RenderVertexPool.h +++ b/Source/Render/Primitives/RenderVertexPool.h @@ -1,14 +1,12 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERVERTEXPOOL_H -#define RAGNAROK_SOURCE_RENDER_RENDERVERTEXPOOL_H +#ifndef RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERVERTEXPOOL_H +#define RAGNAROK_SOURCE_RENDER_PRIMITIVES_RENDERVERTEXPOOL_H -#include "Render/RenderPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" #include #include #include -// Renderer +0xB0. Commands borrow slices until queue draining precedes Rewind. -// Blocks never grow while active, so later acquisition cannot invalidate them. class RenderVertexPool { public: RenderVertexPool(); diff --git a/Source/Render/UIRPData.cpp b/Source/Render/Primitives/UIRPData.cpp similarity index 79% rename from Source/Render/UIRPData.cpp rename to Source/Render/Primitives/UIRPData.cpp index c5414e1..498a76b 100644 --- a/Source/Render/UIRPData.cpp +++ b/Source/Render/Primitives/UIRPData.cpp @@ -1,6 +1,6 @@ -#include "Render/RenderPrimitivePool.h" -#include "Render/Texture.h" -#include "Render/UIRPData.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Textures/Texture.h" +#include "Render/Primitives/UIRPData.h" #include #include @@ -22,19 +22,11 @@ UIRPData::~UIRPData() { // OFFSET: 0x008129D0 // FUNCTION: fn_10120 -void UIRPData::Draw( - RenderPrimitivePool& pool, - int x, - int y, - CTexture* texture, - std::uint32_t color, - int width, - int height, - bool stretched -) { +void UIRPData::Draw(RenderPrimitivePool& pool, int x, int y, CTexture* texture, std::uint32_t color, int width, int height, bool stretched) { if (!texture) { return; } + RenderPrimitive* primitive = pool.Acquire(); primitive->texture = texture; const float textureWidth = static_cast(texture->TextureWidth()); @@ -42,6 +34,7 @@ void UIRPData::Draw( const float u0 = g_textureOffsetX / textureWidth; const float v0 = g_textureOffsetY / textureHeight; float u1, v1; + if (stretched) { u1 = (static_cast(texture->Width()) + g_textureOffsetX) / textureWidth; v1 = (static_cast(texture->Height()) + g_textureOffsetY) / textureHeight; @@ -51,19 +44,21 @@ void UIRPData::Draw( if (!width) { width = texture->Width(); } + if (!height) { height = texture->Height(); } + u1 = (static_cast(std::min(width, imageWidth)) + g_textureOffsetX) / textureWidth; - // Original uses X offset on the <= branch, Y offset on the > branch. - v1 = (static_cast(std::min(height, imageHeight)) + - (height <= imageHeight ? g_textureOffsetX : g_textureOffsetY)) / - textureHeight; + + v1 = (static_cast(std::min(height, imageHeight)) + (height <= imageHeight ? g_textureOffsetX : g_textureOffsetY)) / textureHeight; } + const float right = static_cast(static_cast(static_cast(x) + width)); const float bottom = static_cast(static_cast(static_cast(y) + height)); constexpr float z = 0.000001f; constexpr float rhw = 0.999999f; + primitive->quad[0] = {static_cast(x), static_cast(y), z, rhw, color, 0xFF000000, u0, v0}; primitive->quad[1] = {right, static_cast(y), z, rhw, color, 0xFF000000, u1, v0}; primitive->quad[2] = {static_cast(x), bottom, z, rhw, color, 0xFF000000, u0, v1}; diff --git a/Source/Render/Primitives/UIRPData.h b/Source/Render/Primitives/UIRPData.h new file mode 100644 index 0000000..fbe3ea2 --- /dev/null +++ b/Source/Render/Primitives/UIRPData.h @@ -0,0 +1,26 @@ +#ifndef RAGNAROK_SOURCE_RENDER_PRIMITIVES_UIRPDATA_H +#define RAGNAROK_SOURCE_RENDER_PRIMITIVES_UIRPDATA_H + +#include "Render/Primitives/RenderPrimitive.h" + +#include + +class CTexture; +class RenderPrimitivePool; + +class UIRPData { +public: + UIRPData(); + virtual ~UIRPData(); + void Draw(RenderPrimitivePool& pool, int x, int y, CTexture* texture, std::uint32_t color, int width, int height, bool stretched); + +protected: + /* 0004 */ std::list m_primitives; + /* 000C */ CTexture* m_texture; +}; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(UIRPData) == 16); +#endif + +#endif diff --git a/Source/Render/RenderProjection.cpp b/Source/Render/Projection/RenderProjection.cpp similarity index 50% rename from Source/Render/RenderProjection.cpp rename to Source/Render/Projection/RenderProjection.cpp index 39b632e..1604576 100644 --- a/Source/Render/RenderProjection.cpp +++ b/Source/Render/Projection/RenderProjection.cpp @@ -1,28 +1,23 @@ -#include "Render/RenderPrimitive.h" -#include "Render/RenderProjection.h" +#include "Render/Primitives/RenderPrimitive.h" +#include "Render/Projection/RenderProjection.h" #include // OFFSET: 0x0055D650 // FUNCTION: fn_02106 void RenderProjection::Project(const float* position, const float* matrix, RenderVertex& output) const { - const float inverseDepth = - 1.0f / (((matrix[5] * position[1] + matrix[2] * position[0]) + matrix[8] * position[2]) + matrix[11]); + const float inverseDepth = 1.0f / (((matrix[5] * position[1] + matrix[2] * position[0]) + matrix[8] * position[2]) + matrix[11]); output.rhw = inverseDepth; // STATIC: 0x010DD22C // GLOBAL: gl_13420 constexpr float depthScale = 1.0067114f; const float depth = ((1.0f / inverseDepth - 10.0f) * depthScale) * inverseDepth; - const float x = - ((((matrix[3] * position[1] + position[0] * matrix[0]) + matrix[6] * position[2]) + matrix[9]) * inverseDepth) * - this->scaleX; + const float x = ((((matrix[3] * position[1] + position[0] * matrix[0]) + matrix[6] * position[2]) + matrix[9]) * inverseDepth) * this->scaleX; output.x = x + static_cast(this->centerX); const float centerY = static_cast(this->centerY); - const float y = - ((((matrix[4] * position[1] + matrix[1] * position[0]) + matrix[7] * position[2]) + matrix[10]) * inverseDepth) * - this->scaleY; + const float y = ((((matrix[4] * position[1] + matrix[1] * position[0]) + matrix[7] * position[2]) + matrix[10]) * inverseDepth) * this->scaleY; output.z = depth; output.y = y + centerY; } diff --git a/Source/Render/RenderProjection.h b/Source/Render/Projection/RenderProjection.h similarity index 58% rename from Source/Render/RenderProjection.h rename to Source/Render/Projection/RenderProjection.h index 23e98d1..4237b36 100644 --- a/Source/Render/RenderProjection.h +++ b/Source/Render/Projection/RenderProjection.h @@ -1,10 +1,8 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERPROJECTION_H -#define RAGNAROK_SOURCE_RENDER_RENDERPROJECTION_H +#ifndef RAGNAROK_SOURCE_RENDER_PROJECTION_RENDERPROJECTION_H +#define RAGNAROK_SOURCE_RENDER_PROJECTION_RENDERPROJECTION_H struct RenderVertex; -// Borrowed renderer projection fields +0x04/+0x08 and +0x30/+0x34. -// The camera transform is the original 12-float affine matrix. struct RenderProjection { const float& scaleX; const float& scaleY; diff --git a/Source/Render/RenderRay.cpp b/Source/Render/Projection/RenderRay.cpp similarity index 92% rename from Source/Render/RenderRay.cpp rename to Source/Render/Projection/RenderRay.cpp index aa1f1ad..d77e9cc 100644 --- a/Source/Render/RenderRay.cpp +++ b/Source/Render/Projection/RenderRay.cpp @@ -1,4 +1,4 @@ -#include "Render/RenderProjection.h" +#include "Render/Projection/RenderProjection.h" #include #include @@ -14,13 +14,13 @@ namespace { // OFFSET: 0x0055A090 // FUNCTION: fn_02076 void RenderProjection::Ray(int x, int y, const float* origin, const float* matrix, float* output) const { - // Original loads all matrix lanes before any potentially aliased output store. float transform[12]; std::memcpy(transform, matrix, sizeof(transform)); const float horizontal = static_cast(x) / static_cast(this->centerX); output[0] = origin[0]; output[1] = origin[1]; output[2] = origin[2]; + const float vertical = 1.0f - static_cast(y) / static_cast(this->centerY); const float negative = -vertical; const float dy = (static_cast(this->centerY) * negative) / this->scaleY; @@ -31,6 +31,7 @@ void RenderProjection::Ray(int x, int y, const float* origin, const float* matri output[4] = second; const float third = ((transform[5] * dy + dx * transform[2]) + transform[8]) + 0.0f; output[5] = third; + const float inverse = InverseLength((second * second + first * first) + third * third); output[3] = inverse * output[3]; const float last = inverse * output[5]; diff --git a/Source/Render/RendererViewport.cpp b/Source/Render/Projection/RendererViewport.cpp similarity index 85% rename from Source/Render/RendererViewport.cpp rename to Source/Render/Projection/RendererViewport.cpp index d3e697c..6896f41 100644 --- a/Source/Render/RendererViewport.cpp +++ b/Source/Render/Projection/RendererViewport.cpp @@ -1,22 +1,16 @@ -#include "Render/RendererViewport.h" +#include "Render/Projection/RendererViewport.h" #include #include // OFFSET: 0x0055F6A0 // FUNCTION: fn_02118 -void RendererViewport::SetSize( - int columns, - int rows, - const float& projectionScale, - float& heightScale, - float& tangent, - float& cotangent -) { +void RendererViewport::SetSize(int columns, int rows, const float& projectionScale, float& heightScale, float& tangent, float& cotangent) { this->height = rows; this->centerX = columns / 2; this->width = columns; this->centerY = rows / 2; + const float aspect = static_cast(rows) / static_cast(columns); this->aspect = aspect; const float narrow = static_cast(std::tan(0.13089966773986816)); @@ -27,6 +21,7 @@ void RendererViewport::SetSize( this->vertical = wide; this->horizontal = wide * aspect; this->scaleX = (static_cast(columns / 2) / narrow) * aspect; + this->uiScaleX = static_cast(columns) / 640.0f; const float height = (static_cast(rows) * 1.34f) / 768.0f; this->uiScaleY = static_cast(rows) / 730.0f; diff --git a/Source/Render/Projection/RendererViewport.h b/Source/Render/Projection/RendererViewport.h new file mode 100644 index 0000000..9b43306 --- /dev/null +++ b/Source/Render/Projection/RendererViewport.h @@ -0,0 +1,27 @@ +#ifndef RAGNAROK_SOURCE_RENDER_PROJECTION_RENDERERVIEWPORT_H +#define RAGNAROK_SOURCE_RENDER_PROJECTION_RENDERERVIEWPORT_H + +#include "Render/Projection/RenderProjection.h" + +struct RendererViewport { + float scaleX; + float scaleY; + float horizontal; + float vertical; + float aspect; + float uiScaleX; + float uiScaleY; + int clipCenterX; + int clipCenterY; + int width; + int height; + int centerX; + int centerY; + + void SetSize(int width, int height, const float& projectionScale, float& heightScale, float& tangent, float& cotangent); + RenderProjection Projection() const; +}; + +static_assert(sizeof(RendererViewport) == 52); + +#endif diff --git a/Source/Render/RenderAdapter.cpp b/Source/Render/RenderAdapter.cpp index e50c5c3..4e52542 100644 --- a/Source/Render/RenderAdapter.cpp +++ b/Source/Render/RenderAdapter.cpp @@ -1,4 +1,4 @@ -#include "Render/DeviceOwnerDX9.h" +#include "Render/DX9/DeviceOwnerDX9.h" #include "Render/RenderAdapter.h" #include @@ -25,13 +25,11 @@ bool RenderAdapter::Matches(const RenderAdapter& selected) const { } if (this->backend == 1) { - return std::memcmp(&this->drawGuid, &selected.drawGuid, sizeof(GUID)) == 0 && - std::memcmp(&this->renderGuid, &selected.renderGuid, sizeof(GUID)) == 0; + return std::memcmp(&this->drawGuid, &selected.drawGuid, sizeof(GUID)) == 0 && std::memcmp(&this->renderGuid, &selected.renderGuid, sizeof(GUID)) == 0; } if (this->backend == 2) { - return std::memcmp(&this->deviceGuid, &selected.deviceGuid, sizeof(GUID)) == 0 && - this->deviceName == selected.deviceName; + return std::memcmp(&this->deviceGuid, &selected.deviceGuid, sizeof(GUID)) == 0 && this->deviceName == selected.deviceName; } return false; @@ -73,9 +71,7 @@ std::vector EnumerateAdaptersDX9() { D3DADAPTER_IDENTIFIER9 identifier; if (SUCCEEDED(direct3D->GetAdapterIdentifier(ordinal, 0, &identifier))) { - adapters.push_back( - {2, ordinal, identifier.Description, {}, {}, identifier.DeviceIdentifier, identifier.DeviceName} - ); + adapters.push_back({2, ordinal, identifier.Description, {}, {}, identifier.DeviceIdentifier, identifier.DeviceName}); } } } @@ -90,16 +86,12 @@ std::vector EnumerateAdaptersDX9() { // OFFSET: 0x0056E270 // FUNCTION: fn_02375 HRESULT InitializeConfiguredDeviceDX9( - DeviceOwnerDX9& owner, - HWND window, - const DeviceOptionsDX9& options, - const AdapterConfiguration& configuration, - bool serviceUsesDX7 + DeviceOwnerDX9& owner, HWND window, const DeviceOptionsDX9& options, const AdapterConfiguration& configuration, bool serviceUsesDX7 ) { const std::vector adapters = EnumerateAdaptersDX9(); if (adapters.empty()) { - MessageBoxA(nullptr, "No compatible devices", "Error", 0); + MessageBoxA(nullptr, "No compatible devices", "Error", MB_OK); return D3DERR_NOTAVAILABLE; } diff --git a/Source/Render/RenderAdapter.h b/Source/Render/RenderAdapter.h index b43099e..00b4265 100644 --- a/Source/Render/RenderAdapter.h +++ b/Source/Render/RenderAdapter.h @@ -1,49 +1,44 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERADAPTER_H -#define RAGNAROK_SOURCE_RENDER_RENDERADAPTER_H - -#include -#include -#include - -class DeviceOwnerDX9; -class DirectDrawEnumeration; -struct DeviceOptionsDX9; - -struct RenderAdapter { - int backend; - UINT ordinal; - std::string description; - GUID drawGuid; - GUID renderGuid; - GUID deviceGuid; - std::string deviceName; - - bool Matches(const RenderAdapter& selected) const; -}; - -// Original selected backend/identity globals, borrowed from configuration. -struct AdapterConfiguration { - const int& backend; - const GUID& drawGuid; - const GUID& renderGuid; - const GUID& deviceGuid; - const char* deviceName; -}; - -RenderAdapter SelectedRenderAdapter(const AdapterConfiguration& configuration, bool serviceUsesDX7); -std::vector EnumerateRenderAdapters(int backend, DirectDrawEnumeration& legacy); -std::vector EnumerateAdaptersDX7(DirectDrawEnumeration& enumeration); -std::vector EnumerateAdaptersDX9(); -HRESULT InitializeConfiguredDeviceDX9( - DeviceOwnerDX9& owner, - HWND window, - const DeviceOptionsDX9& options, - const AdapterConfiguration& configuration, - bool serviceUsesDX7 -); - -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(RenderAdapter) == 104); -#endif - -#endif +#ifndef RAGNAROK_SOURCE_RENDER_RENDERADAPTER_H +#define RAGNAROK_SOURCE_RENDER_RENDERADAPTER_H + +#include +#include +#include + +class DeviceOwnerDX9; +class DirectDrawEnumeration; +struct DeviceOptionsDX9; + +struct RenderAdapter { + int backend; + UINT ordinal; + std::string description; + GUID drawGuid; + GUID renderGuid; + GUID deviceGuid; + std::string deviceName; + + bool Matches(const RenderAdapter& selected) const; +}; + +struct AdapterConfiguration { + const int& backend; + const GUID& drawGuid; + const GUID& renderGuid; + const GUID& deviceGuid; + const char* deviceName; +}; + +RenderAdapter SelectedRenderAdapter(const AdapterConfiguration& configuration, bool serviceUsesDX7); +std::vector EnumerateRenderAdapters(int backend, DirectDrawEnumeration& legacy); +std::vector EnumerateAdaptersDX7(DirectDrawEnumeration& enumeration); +std::vector EnumerateAdaptersDX9(); +HRESULT InitializeConfiguredDeviceDX9( + DeviceOwnerDX9& owner, HWND window, const DeviceOptionsDX9& options, const AdapterConfiguration& configuration, bool serviceUsesDX7 +); + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(RenderAdapter) == 104); +#endif + +#endif diff --git a/Source/Render/RenderBackends.cpp b/Source/Render/RenderBackends.cpp index 7fed1e8..6d5b7e6 100644 --- a/Source/Render/RenderBackends.cpp +++ b/Source/Render/RenderBackends.cpp @@ -1,14 +1,11 @@ #include "Render/RenderBackends.h" -// The original fills a by-value vector with two constant records, inserting the -// identity before the name and moving each temporary string into place. It does -// not consult the operating system, DirectDraw/Direct3D availability or any -// adapter, so both entries are always present. // OFFSET: 0x0056A2A0 // FUNCTION: fn_02289 std::vector EnumerateRenderBackends() { std::vector backends; backends.push_back({1, "DirectX 7"}); backends.push_back({2, "DirectX 9"}); + return backends; } diff --git a/Source/Render/RenderBackends.h b/Source/Render/RenderBackends.h index 42ba41a..c03a9b9 100644 --- a/Source/Render/RenderBackends.h +++ b/Source/Render/RenderBackends.h @@ -5,9 +5,6 @@ #include #include -// Setup-screen backend choice: a 32-bit identity followed by the display name. -// The original list is built from constants only; it never probes installed -// Direct3D runtimes or creates a device. struct RenderBackend { /* 0000 */ std::int32_t identity; /* 0004 */ std::string name; diff --git a/Source/Render/RenderSystemBase.h b/Source/Render/RenderSystemBase.h index ea7b7ff..b420528 100644 --- a/Source/Render/RenderSystemBase.h +++ b/Source/Render/RenderSystemBase.h @@ -9,8 +9,6 @@ class CRenderer; class CSurface; class CTexture; -// RTTI: CRenderSystemBase. Names are reconstructed. -// Backend lifecycle and resource factories are implemented by each concrete system. class CRenderSystemBase { public: // OFFSET: 0x0056B4D0 @@ -25,8 +23,7 @@ public: virtual CRenderer* CreateRenderer() = 0; virtual void DestroySurface(CSurface* surface) = 0; virtual CSurface* CreateSurface(std::uint32_t width, std::uint32_t height) = 0; - virtual CTexture* - CreateTexture(std::uint32_t width, std::uint32_t height, std::int32_t format, bool option1, bool option2) = 0; + virtual CTexture* CreateTexture(std::uint32_t width, std::uint32_t height, std::int32_t format, bool option1, bool option2) = 0; virtual CSurface* CreateSurfaceOrTexture(std::uint32_t width, std::uint32_t height) = 0; virtual CTexture* BackBufferTexture() = 0; virtual std::shared_ptr BackBufferSurface() = 0; diff --git a/Source/Render/Renderer.cpp b/Source/Render/Renderer.cpp index 623b359..ed0033c 100644 --- a/Source/Render/Renderer.cpp +++ b/Source/Render/Renderer.cpp @@ -2,8 +2,7 @@ // OFFSET: 0x00560A40 // FUNCTION: fn_02161 -CRenderer::CRenderer(CRenderSystemBase& system) - : frame(0), unknown_003C(0), unknown_0040(0), unknown_0044(0), twoPass(0), unknown_004C(0) { +CRenderer::CRenderer(CRenderSystemBase& system) : frame(0), unknown_003C(0), unknown_0040(0), unknown_0044(0), twoPass(0), unknown_004C(0) { this->atlas.Initialize(system, 50); this->fog.enabled = 0; this->fog.dirty = 1; diff --git a/Source/Render/Renderer.h b/Source/Render/Renderer.h index d9a3d37..48e2846 100644 --- a/Source/Render/Renderer.h +++ b/Source/Render/Renderer.h @@ -1,23 +1,21 @@ #ifndef RAGNAROK_SOURCE_RENDER_RENDERER_H #define RAGNAROK_SOURCE_RENDER_RENDERER_H -#include "Render/LightmappedPrimitive.h" -#include "Render/RenderCommandPool.h" -#include "Render/RenderPrimitivePool.h" -#include "Render/RenderQueues.h" -#include "Render/RenderVertexPool.h" +#include "Render/Primitives/LightmappedPrimitive.h" +#include "Render/Primitives/RenderCommandPool.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/Primitives/RenderVertexPool.h" #include "Render/RendererBackBuffer.h" -#include "Render/RendererFogDX9.h" -#include "Render/RendererViewport.h" -#include "Render/SpriteAtlas.h" +#include "Render/DX9/RendererFogDX9.h" +#include "Render/Projection/RendererViewport.h" +#include "Render/Textures/SpriteAtlas.h" #include class CRenderSystemBase; class CBitmapRes; -// RTTI CRenderer. Backend virtuals retain the -// original slot order; device-independent storage has one authoritative owner. class CRenderer { public: explicit CRenderer(CRenderSystemBase& system); @@ -36,8 +34,7 @@ public: virtual void DrawAuxiliaryPrimitive(LightmappedPrimitive* primitive) = 0; virtual void DrawLightmappedPrimitive(LightmappedPrimitive* primitive) = 0; virtual void DrawPrimitive(RenderCommand* primitive) = 0; - virtual bool - RenderToTexture(int width, int height, const std::list& primitives, CTexture*& texture) = 0; + virtual bool RenderToTexture(int width, int height, const std::list& primitives, CTexture*& texture) = 0; virtual bool SaveBitmap(const char* filename, CBitmapRes* overlay) = 0; virtual bool SaveJpeg(const char* filename, CBitmapRes* overlay) = 0; virtual void CleanupTextures() = 0; diff --git a/Source/Render/RendererBackBuffer.h b/Source/Render/RendererBackBuffer.h index ff0719d..3573b59 100644 --- a/Source/Render/RendererBackBuffer.h +++ b/Source/Render/RendererBackBuffer.h @@ -5,8 +5,6 @@ class DeviceOwnerDX7; -// Original renderer +0x250..+0x25B. Failed locking leaves every field intact; -// unlocking does not clear the last published pointer, pitch or bit depth. struct RendererBackBuffer { void* pixels; int pitch; diff --git a/Source/Render/RendererFogDX9.h b/Source/Render/RendererFogDX9.h deleted file mode 100644 index 1af20f0..0000000 --- a/Source/Render/RendererFogDX9.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERERFOGDX9_H -#define RAGNAROK_SOURCE_RENDER_RENDERERFOGDX9_H - -#include "Render/FogConfiguration.h" - -#include - -class D3DX9Runtime; -struct TextureDX9Context; -struct DeviceStateDX9; - -// CRenderer +0x150..+0x15B. dirty is tested for exact equality with one. -struct RendererFogDX9 { - int enabled; - int dirty; - int supported; - - void Set(int enabled, const D3DCAPS9& caps, FogConfiguration& configuration); - void Apply( - const TextureDX9Context& context, - DeviceStateDX9& state, - D3DX9Runtime& d3dx, - const float& aspect, - const FogConfiguration& configuration - ); -}; - -static_assert(sizeof(RendererFogDX9) == 12); - -#endif diff --git a/Source/Render/RendererFrameDX9.cpp b/Source/Render/RendererFrameDX9.cpp deleted file mode 100644 index 6d723cc..0000000 --- a/Source/Render/RendererFrameDX9.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "Contents/Effect.h" -#include "Render/DeviceOwnerDX9.h" -#include "Render/LightmappedPrimitive.h" -#include "Render/RenderCommandPool.h" -#include "Render/RenderPrimitivePool.h" -#include "Render/RenderQueues.h" -#include "Render/RenderVertexPool.h" -#include "Render/RendererDX9Operations.h" -#include "Render/RendererFrameDX9.h" - -// OFFSET: 0x0055A360 -// FUNCTION: fn_02079 -void RendererFrameDX9::Clear() { - this->retirement.Clear(); - this->queues.Clear(); - this->commands.Rewind(); - this->primitives.Rewind(); - this->lightmapped.Rewind(); - this->vertices.Rewind(); -} - -// OFFSET: 0x00565970 -// FUNCTION: fn_02222 -bool RendererFrameDX9::Draw( - CRenderSystemBase* renderSystem, - const ServiceOptions& options, - unsigned char multitexture, - unsigned char twoPass, - RendererFogDX9& fog, - const float& aspect, - const FogConfiguration& configuration -) { - // The original deliberately ignores Begin's result and always draws/clears. - this->device.Begin(renderSystem); - this->operations.DrawQueues(this->queues, options, multitexture, twoPass, fog, aspect, configuration); - this->Clear(); - this->device.End(); - return true; -} diff --git a/Source/Render/RendererViewport.h b/Source/Render/RendererViewport.h deleted file mode 100644 index e49b10b..0000000 --- a/Source/Render/RendererViewport.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef RAGNAROK_SOURCE_RENDER_RENDERERVIEWPORT_H -#define RAGNAROK_SOURCE_RENDER_RENDERERVIEWPORT_H - -#include "Render/RenderProjection.h" - -// Contiguous CRenderer fields +0x04..+0x37. Projection and clipping centers -// are distinct stored pairs even though this initialization sets them equally. -struct RendererViewport { - float scaleX; - float scaleY; - float horizontal; - float vertical; - float aspect; - float uiScaleX; - float uiScaleY; - int clipCenterX; - int clipCenterY; - int width; - int height; - int centerX; - int centerY; - - void - SetSize(int width, int height, const float& projectionScale, float& heightScale, float& tangent, float& cotangent); - RenderProjection Projection() const; -}; - -static_assert(sizeof(RendererViewport) == 52); - -#endif diff --git a/Source/Render/FontCache.cpp b/Source/Render/Text/FontCache.cpp similarity index 76% rename from Source/Render/FontCache.cpp rename to Source/Render/Text/FontCache.cpp index 7b4c86f..a4b3723 100644 --- a/Source/Render/FontCache.cpp +++ b/Source/Render/Text/FontCache.cpp @@ -1,11 +1,11 @@ -#include "Render/FontCache.h" +#include "Render/Text/FontCache.h" #include #include #include -// clang-format off + #include -// clang-format on + #include #include @@ -26,13 +26,14 @@ namespace { "Arial", "Tahoma" }; - const char* const fallback[] = {"Gulim", "Arial", "MS Gothic", "SimSun", "MingLiU", "Tahoma", - "Arial", "Verdana", "Verdana", "Arial", "Arial", "Tahoma"}; + const char* const fallback[] = {"Gulim", "Arial", "MS Gothic", "SimSun", "MingLiU", "Tahoma", "Arial", "Verdana", "Verdana", "Arial", "Arial", "Tahoma"}; + // OFFSET: 0x0054F2C0 // FUNCTION: fn_01956 int CALLBACK MatchFont(const LOGFONTA* font, const TEXTMETRICA*, DWORD, LPARAM name) { return _stricmp(reinterpret_cast(name), font->lfFaceName); } + const char* PrivatePath(unsigned char bold) { return bold == 1 ? "system\\font\\SCDream6.otf" : "system\\font\\SCDream4.otf"; } @@ -44,16 +45,18 @@ FontCache::FontCache() { Gdiplus::GdiplusStartupInput input; Gdiplus::GdiplusStartup(&this->m_gdiplus, &input, nullptr); } + // OFFSET: 0x0100F120 // FUNCTION: fn_29519 FontCache::~FontCache() { for (const FontEntry& entry : this->m_fonts) { DeleteObject(entry.font); - // Private-font cleanup. + if (entry.privateResources > 0 && entry.family == 29) { RemoveFontResourceExA(PrivatePath(entry.bold), FR_PRIVATE, nullptr); } } + this->m_fonts.clear(); Gdiplus::GdiplusShutdown(this->m_gdiplus); } @@ -64,15 +67,17 @@ void FontCache::CreateSystemFont(FontEntry& entry) { LOGFONTA description = {}; description.lfCharSet = static_cast(entry.charset); const char* face = primary[entry.family]; - // Original does not release either screen DC acquired for enumeration. + if (EnumFontFamiliesExA(GetDC(nullptr), &description, MatchFont, reinterpret_cast(face), 0) != 0) { face = fallback[entry.family]; if (EnumFontFamiliesExA(GetDC(nullptr), &description, MatchFont, reinterpret_cast(face), 0) != 0) { face = nullptr; } } + entry.font = CreateFontA( - entry.height, 0, 0, 0, entry.bold ? 700 : 400, entry.italic != 0, 0, 0, entry.charset, 0, 0, 3, 0, face + entry.height, 0, 0, 0, entry.bold ? FW_BOLD : FW_NORMAL, entry.italic != 0, 0, 0, entry.charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + NONANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, face ); } @@ -86,14 +91,16 @@ bool FontCache::CreatePrivateFont(FontEntry& entry) { if (entry.privateResources != 0) { LOGFONTA description = {}; description.lfHeight = -MulDiv(entry.height, 72, 72); - description.lfWeight = entry.bold ? 700 : 400; + description.lfWeight = entry.bold ? FW_BOLD : FW_NORMAL; description.lfItalic = entry.italic != 0; description.lfCharSet = static_cast(entry.charset); - // Original byte-to-wide conversion sign-extends each char, not ACP decode. + std::wstring wide; + for (const char* byte = path; *byte; ++byte) { wide.push_back(static_cast(*byte)); } + Gdiplus::PrivateFontCollection collection; collection.AddFontFile(wide.c_str()); Gdiplus::FontFamily family; @@ -106,6 +113,7 @@ bool FontCache::CreatePrivateFont(FontEntry& entry) { strncpy_s(description.lfFaceName, narrow, _TRUNCATE); entry.font = CreateFontIndirectA(&description); } + return entry.privateResources > 0; } @@ -113,31 +121,29 @@ bool FontCache::CreatePrivateFont(FontEntry& entry) { // FUNCTION: fn_01958 HFONT FontCache::Get(int family, int height, unsigned charset, unsigned char bold, unsigned char italic) { for (const FontEntry& entry : this->m_fonts) { - if ( - entry.family == family && entry.height == height && entry.charset == charset && entry.bold == bold && - entry.italic == italic - ) { + if (entry.family == family && entry.height == height && entry.charset == charset && entry.bold == bold && entry.italic == italic) { return entry.font; } } + FontEntry entry{family, height, charset, bold, italic, nullptr, 0}; if (family >= 20 && family <= 28) { - static const char* const faces[] = {"RixSquirrel_10.eot", "RixLoveangel_10.eot", "RixNHCgogo_10.eot", - "RixDiary_10.eot", "RixMiniHeart_10.eot", "RixFreshman_10.eot", - "RixKid_10.eot", "RixMagic_10.eot", "RixJJangu_10.eot"}; + static const char* const faces[] = {"RixSquirrel_10.eot", "RixLoveangel_10.eot", "RixNHCgogo_10.eot", "RixDiary_10.eot", "RixMiniHeart_10.eot", + "RixFreshman_10.eot", "RixKid_10.eot", "RixMagic_10.eot", "RixJJangu_10.eot"}; LOGFONTA description = {}; description.lfHeight = -MulDiv(13, 72, 72); - description.lfWeight = 400; - description.lfCharSet = 1; - description.lfOutPrecision = 6; - description.lfQuality = 2; + description.lfWeight = FW_NORMAL; + description.lfCharSet = DEFAULT_CHARSET; + description.lfOutPrecision = OUT_RASTER_PRECIS; + description.lfQuality = PROOF_QUALITY; strcpy_s(description.lfFaceName, faces[family - 20]); entry.font = CreateFontIndirectA(&description); } else if (family != 29 || !CreatePrivateFont(entry)) { CreateSystemFont(entry); } + this->m_fonts.push_back(entry); - // Original comparator deliberately ignores style flags when ordering. + std::sort(this->m_fonts.begin(), this->m_fonts.end(), [](const FontEntry& a, const FontEntry& b) { return std::tie(a.family, a.height, a.charset) < std::tie(b.family, b.height, b.charset); }); diff --git a/Source/Render/FontCache.h b/Source/Render/Text/FontCache.h similarity index 80% rename from Source/Render/FontCache.h rename to Source/Render/Text/FontCache.h index b40cc40..f0d2406 100644 --- a/Source/Render/FontCache.h +++ b/Source/Render/Text/FontCache.h @@ -1,9 +1,15 @@ -#ifndef RAGNAROK_SOURCE_RENDER_FONTCACHE_H -#define RAGNAROK_SOURCE_RENDER_FONTCACHE_H +#ifndef RAGNAROK_SOURCE_RENDER_TEXT_FONTCACHE_H +#define RAGNAROK_SOURCE_RENDER_TEXT_FONTCACHE_H +#include #include #include +namespace Gdiplus { + using std::max; + using std::min; +} + struct FontEntry { int family; int height; diff --git a/Source/Render/TextContext.cpp b/Source/Render/Text/TextContext.cpp similarity index 80% rename from Source/Render/TextContext.cpp rename to Source/Render/Text/TextContext.cpp index 721b05c..33f3bc7 100644 --- a/Source/Render/TextContext.cpp +++ b/Source/Render/Text/TextContext.cpp @@ -1,6 +1,6 @@ -#include "Render/DeviceContext.h" -#include "Render/FontCache.h" -#include "Render/TextContext.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/FontCache.h" +#include "Render/Text/TextContext.h" #include #include @@ -11,37 +11,39 @@ namespace { // STATIC: 0x01311F30 // GLOBAL: gl_21912 - constexpr unsigned charsets[20] = {129, 0, 128, 134, 136, 222, 162, 0, 0, 204, 163, 178}; - int Add(int a, int b) { - return std::bit_cast(static_cast(a) + static_cast(b)); - } + constexpr unsigned charsets[20] = {HANGUL_CHARSET, ANSI_CHARSET, SHIFTJIS_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET, THAI_CHARSET, + TURKISH_CHARSET, ANSI_CHARSET, ANSI_CHARSET, RUSSIAN_CHARSET, VIETNAMESE_CHARSET, ARABIC_CHARSET}; + unsigned Hex(unsigned char value) { if (value >= '0' && value <= '9') { return value - '0'; } + if (value >= 'a' && value <= 'f') { return value - 'a' + 10; } + return 0; } + bool ValidHex(unsigned char value) { return (value >= '0' && value <= '9') || (value >= 'a' && value <= 'f') || (value >= 'A' && value <= 'F'); } + unsigned InlineCharset(const char* marker) { - // Original validity accepts A-F, but conversion table maps uppercase to0. return 16 * Hex(static_cast(marker[1])) + Hex(static_cast(marker[2])); } } // OFFSET: 0x0054D4B0 // FUNCTION: fn_01934 -TextContext::TextContext(CDC& surface, FontCache& fonts, const TextLocale& locale) - : m_dc(nullptr), m_surface(&surface), m_fonts(&fonts), m_locale(&locale) { +TextContext::TextContext(CDC& surface, FontCache& fonts, const TextLocale& locale) : m_dc(nullptr), m_surface(&surface), m_fonts(&fonts), m_locale(&locale) { if (surface.GetDC(&this->m_dc)) { this->m_previous = GetCurrentObject(this->m_dc, OBJ_FONT); SetBkMode(this->m_dc, TRANSPARENT); } } + // OFFSET: 0x0054D7E0 // FUNCTION: fn_01939 TextContext::~TextContext() { @@ -59,9 +61,9 @@ void TextContext::SetFont(int family, int height, unsigned char bold, unsigned c case 1: if (this->m_locale->service == 6) { family = 8; - height = Add(height, 2); + height = (height + 2); } else { - height = Add(height, 3); + height = (height + 3); if (this->m_locale->service == 14) { family = 9; } else { @@ -83,38 +85,40 @@ void TextContext::SetFont(int family, int height, unsigned char bold, unsigned c break; case 5: family = 5; - height = Add(height, 3); + height = (height + 3); break; case 6: case 8: family = 7; - height = Add(height, 3); + height = (height + 3); if (this->m_locale->service == 12) { - height = Add(height, -2); + height = (height - 2); } else if (this->m_locale->service == 18) { if (*this->m_locale->serverLanguage == 31) { family = 6; } else { - height = Add(height, -2); + height = (height - 2); } } break; case 7: family = 10; - height = Add(height, 3); + height = (height + 3); break; case 12: family = 11; - height = Add(height, 3); + height = (height + 3); break; } } + this->m_family = family; this->m_height = height; this->m_charset = this->m_locale->language == 0 && family >= 20 ? charsets[0] : charsets[family]; this->m_bold = bold; this->m_italic = italic; } + // OFFSET: 0x00550170 // FUNCTION: fn_01969 void TextContext::SetColor(COLORREF color) { @@ -134,31 +138,31 @@ void TextContext::SetBackground(COLORREF color, int mode) { // FUNCTION: fn_17772 unsigned TextContext::CodePage(unsigned charset) { switch (charset) { - case 128: + case SHIFTJIS_CHARSET: return 932; - case 129: + case HANGUL_CHARSET: return 949; - case 134: + case GB2312_CHARSET: return 936; - case 136: + case CHINESEBIG5_CHARSET: return 950; - case 161: + case GREEK_CHARSET: return 1253; - case 162: + case TURKISH_CHARSET: return 1254; - case 163: + case VIETNAMESE_CHARSET: return 1258; - case 177: + case HEBREW_CHARSET: return 1255; - case 178: + case ARABIC_CHARSET: return 1256; - case 186: + case BALTIC_CHARSET: return 1257; - case 204: + case RUSSIAN_CHARSET: return 1251; - case 222: + case THAI_CHARSET: return 874; - case 238: + case EASTEUROPE_CHARSET: return 1250; default: return 1252; @@ -171,18 +175,18 @@ unsigned TextContext::Marker(const char* text, unsigned bytes, bool enabled) { if (!enabled) { return bytes; } + const unsigned limit = std::min(static_cast(std::strlen(text)), bytes); if (std::bit_cast(limit - 2) <= 0) { return bytes; } + for (unsigned i = 0; i < limit - 2; ++i) { - if ( - text[i] == '|' && ValidHex(static_cast(text[i + 1])) && - ValidHex(static_cast(text[i + 2])) - ) { + if (text[i] == '|' && ValidHex(static_cast(text[i + 1])) && ValidHex(static_cast(text[i + 2]))) { return i; } } + return bytes; } @@ -193,31 +197,39 @@ SIZE TextContext::MeasurePart(const char* text, int bytes, unsigned charset) { if (!text || bytes <= 0) { return size; } + const unsigned extent = 2u * static_cast(bytes); const unsigned allocation = extent < extent + 8 ? extent + 8 : 0; if (!allocation) { return size; } + void* memory = allocation > 0x400 ? std::malloc(allocation) : _alloca(allocation); if (!memory) { return size; } + auto* wide = reinterpret_cast(static_cast(memory) + 8); const int count = MultiByteToWideChar(CodePage(charset), 0, text, bytes, wide, static_cast(extent)); SelectObject(this->m_dc, this->m_fonts->Get(this->m_family, this->m_height, charset, this->m_bold, this->m_italic)); GetTextExtentPoint32W(this->m_dc, wide, count, &size); + if (this->m_italic == 1) { int width = 0; + for (int i = 0; i < count; ++i) { ABC abc; GetCharABCWidthsW(this->m_dc, wide[i], wide[i], &abc); - width = Add(width, Add(abc.abcA, abc.abcB)); + width = (width + (abc.abcA + abc.abcB)); } + size.cx = width; } + if (allocation > 0x400) { std::free(memory); } + return size; } @@ -227,20 +239,24 @@ void TextContext::DrawPart(int x, int y, const char* text, int bytes, unsigned c if (!text || bytes <= 0) { return; } + const unsigned extent = 2u * static_cast(bytes); const unsigned allocation = extent < extent + 8 ? extent + 8 : 0; if (!allocation) { return; } + void* memory = allocation > 0x400 ? std::malloc(allocation) : _alloca(allocation); if (!memory) { return; } + auto* wide = reinterpret_cast(static_cast(memory) + 8); - // Original conversion uses context charset, while font lookup uses argument. + const int count = MultiByteToWideChar(CodePage(this->m_charset), 0, text, bytes, wide, static_cast(extent)); SelectObject(this->m_dc, this->m_fonts->Get(this->m_family, this->m_height, charset, this->m_bold, this->m_italic)); TextOutW(this->m_dc, x, y, wide, count); + if (allocation > 0x400) { std::free(memory); } @@ -253,11 +269,13 @@ SIZE TextContext::Measure(const char* text, int bytes) { SIZE result = this->MeasurePart(text, first, this->m_charset); if (first < bytes) { SIZE second = this->MeasurePart(text + first + 3, bytes - first - 3, InlineCharset(text + first)); - result.cx = Add(result.cx, second.cx); + result.cx = (result.cx + second.cx); result.cy = std::max(result.cy, second.cy); } + return result; } + // OFFSET: 0x00550190 // FUNCTION: fn_01970 void TextContext::DrawPair(int x, int y, const char* text, int bytes) { @@ -265,9 +283,10 @@ void TextContext::DrawPair(int x, int y, const char* text, int bytes) { this->DrawPart(x, y, text, first, this->m_charset); if (first < bytes) { const SIZE size = this->MeasurePart(text, first, this->m_charset); - this->DrawPart(Add(x, size.cx), y, text + first + 3, bytes - first - 3, InlineCharset(text + first)); + this->DrawPart((x + size.cx), y, text + first + 3, bytes - first - 3, InlineCharset(text + first)); } } + // OFFSET: 0x00550220 // FUNCTION: fn_01971 void TextContext::Draw(int x, int y, const char* text, int bytes) { @@ -275,28 +294,33 @@ void TextContext::Draw(int x, int y, const char* text, int bytes) { this->DrawPair(x, y, text, bytes); return; } + const char* current = text; int scanned = 0, remaining = bytes; + while (scanned < bytes) { - scanned = Add(scanned, Marker(text + scanned, remaining, true)); + scanned = (scanned + Marker(text + scanned, remaining, true)); if (scanned >= bytes) { this->DrawPair(x, y, current, scanned); return; } + if (remaining <= 3) { return; } - const int segment = Add(Marker(text + scanned + 3, remaining - 3, true), 3); + + const int segment = (Marker(text + scanned + 3, remaining - 3, true) + 3); this->DrawPair(x, y, current, segment); const int first = Marker(current, segment, true); int width = this->MeasurePart(current, first, this->m_charset).cx; + if (first < segment) { - width = - Add(width, this->MeasurePart(current + first + 3, segment - first - 3, InlineCharset(current + first)).cx); + width = (width + this->MeasurePart(current + first + 3, segment - first - 3, InlineCharset(current + first)).cx); } + current += segment; - scanned = Add(scanned, segment); - x = Add(x, width); + scanned = (scanned + segment); + x = (x + width); remaining -= segment; } } diff --git a/Source/Render/TextContext.h b/Source/Render/Text/TextContext.h similarity index 87% rename from Source/Render/TextContext.h rename to Source/Render/Text/TextContext.h index 1068b24..dbfdd95 100644 --- a/Source/Render/TextContext.h +++ b/Source/Render/Text/TextContext.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_TEXTCONTEXT_H -#define RAGNAROK_SOURCE_RENDER_TEXTCONTEXT_H +#ifndef RAGNAROK_SOURCE_RENDER_TEXT_TEXTCONTEXT_H +#define RAGNAROK_SOURCE_RENDER_TEXT_TEXTCONTEXT_H #include #include @@ -7,7 +7,6 @@ class CDC; class FontCache; -// Original locale/service globals and server language field remain borrowed. struct TextLocale { signed char language; int service; diff --git a/Source/Render/TextureStageModes.cpp b/Source/Render/TextureStageModes.cpp index 4f607cb..9019010 100644 --- a/Source/Render/TextureStageModes.cpp +++ b/Source/Render/TextureStageModes.cpp @@ -4,133 +4,109 @@ namespace { using StageWrite = TextureStageWrite; - // Ordered writes. Missing fields retain prior state. + constexpr StageWrite mode0[] = { - {0, static_cast(11), 0}, {0, static_cast(1), 4}, - {0, static_cast(2), 2}, {0, static_cast(3), 0}, - {0, static_cast(4), 4}, {0, static_cast(5), 2}, - {0, static_cast(6), 0}, {1, static_cast(1), 1}, - {1, static_cast(4), 1}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, {0, D3DTSS_ALPHAOP, D3DTOP_MODULATE}, {0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, + {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, {1, D3DTSS_COLOROP, D3DTOP_DISABLE}, {1, D3DTSS_ALPHAOP, D3DTOP_DISABLE}, }; constexpr StageWrite mode2[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(5), 2}, {0, static_cast(4), 2}, - {1, static_cast(1), 1}, {1, static_cast(4), 1}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, {1, D3DTSS_COLOROP, D3DTOP_DISABLE}, {1, D3DTSS_ALPHAOP, D3DTOP_DISABLE}, }; constexpr StageWrite mode3[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 7}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(1), 1}, {1, static_cast(4), 1}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_ADD}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, {1, D3DTSS_COLOROP, D3DTOP_DISABLE}, {1, D3DTSS_ALPHAOP, D3DTOP_DISABLE}, }; constexpr StageWrite mode4[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 13}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(1), 1}, {1, static_cast(4), 1}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA}, + {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, + {1, D3DTSS_COLOROP, D3DTOP_DISABLE}, {1, D3DTSS_ALPHAOP, D3DTOP_DISABLE}, }; constexpr StageWrite mode5[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(11), 1}, {1, static_cast(2), 2}, - {1, static_cast(1), 4}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {1, D3DTSS_COLOROP, D3DTOP_MODULATE}, {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode6[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 18}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(11), 1}, {1, static_cast(2), 18}, - {1, static_cast(1), 4}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_COMPLEMENT}, + {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, + {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_COMPLEMENT}, + {1, D3DTSS_COLOROP, D3DTOP_MODULATE}, {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, + {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode7[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 2}, {0, static_cast(5), 2}, - {0, static_cast(4), 2}, {1, static_cast(11), 1}, - {1, static_cast(2), 34}, {1, static_cast(1), 4}, - {1, static_cast(3), 1}, {1, static_cast(5), 2}, - {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, + {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {0, D3DTSS_COLOROP, D3DTOP_SELECTARG1}, + {0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, + {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, + {1, D3DTSS_TEXCOORDINDEX, 1}, + {1, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE}, + {1, D3DTSS_COLOROP, D3DTOP_MODULATE}, + {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, + {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, + {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode8[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(5), 2}, {0, static_cast(4), 2}, - {1, static_cast(11), 1}, {1, static_cast(2), 2}, - {1, static_cast(1), 7}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {1, D3DTSS_COLOROP, D3DTOP_ADD}, {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode9[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(11), 1}, {1, static_cast(2), 2}, - {1, static_cast(1), 13}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, + {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, + {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {1, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA}, + {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode10[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(11), 1}, {1, static_cast(2), 2}, - {1, static_cast(1), 12}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, + {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, + {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA}, + {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode11[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(11), 1}, {1, static_cast(2), 2}, - {1, static_cast(1), 7}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {1, D3DTSS_COLOROP, D3DTOP_ADD}, {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode12[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(11), 1}, {1, static_cast(2), 18}, - {1, static_cast(1), 7}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, + {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_COMPLEMENT}, + {1, D3DTSS_COLOROP, D3DTOP_ADD}, {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, + {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode13[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 7}, {0, static_cast(3), 0}, - {0, static_cast(5), 2}, {0, static_cast(4), 2}, - {1, static_cast(11), 1}, {1, static_cast(2), 2}, - {1, static_cast(1), 4}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_ADD}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {1, D3DTSS_COLOROP, D3DTOP_MODULATE}, {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode14[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(11), 1}, {1, static_cast(2), 2}, - {1, static_cast(1), 5}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {1, D3DTSS_COLOROP, D3DTOP_MODULATE2X}, {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; constexpr StageWrite mode15[] = { - {0, static_cast(11), 0}, {0, static_cast(2), 2}, - {0, static_cast(1), 4}, {0, static_cast(3), 0}, - {0, static_cast(4), 3}, {0, static_cast(6), 0}, - {1, static_cast(11), 1}, {1, static_cast(2), 2}, - {1, static_cast(1), 8}, {1, static_cast(3), 1}, - {1, static_cast(5), 2}, {1, static_cast(4), 2}, + {0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE}, + {0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2}, {0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, {1, D3DTSS_TEXCOORDINDEX, 1}, {1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, + {1, D3DTSS_COLOROP, D3DTOP_ADDSIGNED}, {1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE}, {1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1}, }; } diff --git a/Source/Render/TextureStageModes.h b/Source/Render/TextureStageModes.h index 109f1de..1054c3e 100644 --- a/Source/Render/TextureStageModes.h +++ b/Source/Render/TextureStageModes.h @@ -4,8 +4,6 @@ #include #include -// Both original backends issue the same ordered partial stage transitions. -// State numbers are shared D3D7/D3D9 values; callers retain their native API type. struct TextureStageWrite { unsigned stage; unsigned state; diff --git a/Source/Render/BitmapPixels.cpp b/Source/Render/Textures/BitmapPixels.cpp similarity index 74% rename from Source/Render/BitmapPixels.cpp rename to Source/Render/Textures/BitmapPixels.cpp index 5804032..07af224 100644 --- a/Source/Render/BitmapPixels.cpp +++ b/Source/Render/Textures/BitmapPixels.cpp @@ -1,17 +1,17 @@ -#include "Render/BitmapPixels.h" +#include "Render/Textures/BitmapPixels.h" #include "Render/RenderSystemBase.h" -#include "Render/SpriteAtlas.h" -#include "Render/Surface.h" -#include "Render/Texture.h" +#include "Render/Textures/SpriteAtlas.h" +#include "Render/Textures/Surface.h" +#include "Render/Textures/Texture.h" #include #include +#include #include // OFFSET: 0x00545790 // FUNCTION: fn_01832 -BitmapPixels::BitmapPixels(int newWidth, int newHeight) - : dc(CreateCompatibleDC(nullptr)), bitmap(nullptr), previous(nullptr), pixels(nullptr) { +BitmapPixels::BitmapPixels(int newWidth, int newHeight) : dc(CreateCompatibleDC(nullptr)), bitmap(nullptr), previous(nullptr), pixels(nullptr) { this->Create(newWidth, newHeight); } @@ -26,17 +26,20 @@ BitmapPixels::~BitmapPixels() { // OFFSET: 0x00547C90 // FUNCTION: fn_01847 void BitmapPixels::UploadTexture(CRenderSystemBase& system, CTexture*& texture) { - const std::int32_t bytes = std::bit_cast(4u * this->width * this->height); + const std::int32_t bytes = 4 * static_cast(this->width) * static_cast(this->height); + for (std::int32_t offset = 0; offset < bytes; offset += 4) { reinterpret_cast(this->pixels)[offset + 3] = 255; } + if (texture) { texture->Upload(0, 0, this->width, this->height, this->pixels, 0, 0); } else { - CTexture* created = system.CreateTexture(this->width, this->height, 0, false, false); + CTexture* created = system.CreateTexture(this->width, this->height, TextureFormat::A1R5G5B5, false, false); if (created) { created->Upload(0, 0, this->width, this->height, this->pixels, 0, 0); } + texture = created; } } @@ -60,9 +63,11 @@ void BitmapPixels::Create(int newWidth, int newHeight) { info.bmiHeader.biClrUsed = 0; info.bmiHeader.biClrImportant = 0; this->bitmap = CreateDIBSection(nullptr, &info, DIB_RGB_COLORS, reinterpret_cast(&this->pixels), nullptr, 0); + if (!this->bitmap) { this->pixels = nullptr; } + this->previous = SelectObject(this->dc, this->bitmap); } @@ -95,12 +100,14 @@ void BitmapPixels::Fill(const RECT* rectangle, std::uint32_t color) { if (!this->pixels) { return; } + this->dirty = true; const std::uint32_t converted = (color & 0xFF00FF00) | ((color & 0xFF) << 16) | ((color >> 16) & 0xFF); const int left = rectangle ? rectangle->left : 0; const int top = rectangle ? rectangle->top : 0; const int right = rectangle ? rectangle->right : static_cast(this->width); const int bottom = rectangle ? rectangle->bottom : static_cast(this->height); + for (int y = top; y < bottom; ++y) { for (int x = left; x < right; ++x) { this->pixels[x + y * this->width] = converted; @@ -114,14 +121,15 @@ void BitmapPixels::Copy(int x, int y, int copyWidth, int copyHeight, const std:: if (!this->pixels || !source) { return; } + this->dirty = true; const std::int32_t count = static_cast(this->width * this->height); + for (int row = 0; row < copyHeight; ++row) { for (int column = 0; column < copyWidth; ++column) { std::uint32_t value = *source++; if (!transparent || value != 0xFFFF00FF) { - const std::uint32_t index = - static_cast(x) + column + this->width * (static_cast(y) + row); + const std::uint32_t index = static_cast(x) + column + this->width * (static_cast(y) + row); if (static_cast(index) > -1 && count > static_cast(index)) { this->pixels[index] = value; } @@ -132,30 +140,26 @@ void BitmapPixels::Copy(int x, int y, int copyWidth, int copyHeight, const std:: // OFFSET: 0x00547790 // FUNCTION: fn_01843 -void BitmapPixels::CopyFrom( - int x, - int y, - int sourceX, - int sourceY, - int copyWidth, - int copyHeight, - const BitmapPixels& source -) { +void BitmapPixels::CopyFrom(int x, int y, int sourceX, int sourceY, int copyWidth, int copyHeight, const BitmapPixels& source) { if (!this->pixels) { return; } + this->dirty = true; std::uint32_t* destination = this->pixels + x + y * this->width; const std::uint32_t* input = source.pixels + sourceX + sourceY * source.width; + for (int row = 0; row < copyHeight; ++row) { if (!destination || !input) { break; } + for (int column = 0; column < copyWidth; ++column) { if (input[column] != 0xFFFF00FF) { destination[column] = input[column]; } } + destination += this->width; input += source.width; } @@ -163,24 +167,21 @@ void BitmapPixels::CopyFrom( // OFFSET: 0x00547840 // FUNCTION: fn_01844 -void BitmapPixels::BlendFrom( - std::uint32_t x, - std::uint32_t y, - int copyWidth, - int copyHeight, - const BitmapPixels& source, - bool alpha -) { +void BitmapPixels::BlendFrom(std::uint32_t x, std::uint32_t y, int copyWidth, int copyHeight, const BitmapPixels& source, bool alpha) { if (!this->pixels || x >= this->width || y >= this->height) { return; } + if (x + copyWidth > this->width) { copyWidth = this->width - x; } + if (y + copyHeight > this->height) { copyHeight = this->height - y; } + this->dirty = true; + for (int row = 0; row < copyHeight; ++row) { for (int column = 0; column < copyWidth; ++column) { std::uint32_t& destination = this->pixels[x + column + this->width * (y + row)]; @@ -188,9 +189,11 @@ void BitmapPixels::BlendFrom( if (alpha) { const unsigned a = input >> 24; std::uint32_t output = std::max(a, destination >> 24) << 24; + for (unsigned shift : {0u, 8u, 16u}) { output |= (a * ((input >> shift) & 255) / 255 + (255 - a) * ((destination >> shift) & 255) / 255) << shift; } + destination = output; } else if (input != 0xFFFF00FF) { destination = input - 0x01000000; @@ -202,23 +205,24 @@ void BitmapPixels::BlendFrom( // OFFSET: 0x005489F0 // FUNCTION: fn_01857 void BitmapPixels::Brighten(int x, int y, int copyWidth, int copyHeight, int amount) { - if ( - x < 0 || y < 0 || this->width < static_cast(x) || this->height < static_cast(y) || - copyWidth < 1 || copyHeight < 1 - ) { + if (x < 0 || y < 0 || this->width < static_cast(x) || this->height < static_cast(y) || copyWidth < 1 || copyHeight < 1) { return; } + this->dirty = true; const unsigned right = std::min(this->width, static_cast(x) + copyWidth); const unsigned bottom = std::min(this->height, static_cast(y) + copyHeight); + for (unsigned row = y; row < bottom; ++row) { for (unsigned column = x; column < right; ++column) { std::uint32_t& pixel = this->pixels[column + row * this->width]; if (pixel != 0xFFFF00FF) { std::uint32_t value = 0xFF000000; + for (unsigned shift : {0u, 8u, 16u}) { value |= std::clamp(amount + static_cast((pixel >> shift) & 255), 0, 255) << shift; } + pixel = value; } } @@ -228,25 +232,24 @@ void BitmapPixels::Brighten(int x, int y, int copyWidth, int copyHeight, int amo // OFFSET: 0x00548650 // FUNCTION: fn_01855 void BitmapPixels::Dim(int x, int y, int copyWidth, int copyHeight, int percent) { - if ( - x < 0 || y < 0 || this->width < static_cast(x) || this->height < static_cast(y) || - copyWidth < 1 || copyHeight < 1 - ) { + if (x < 0 || y < 0 || this->width < static_cast(x) || this->height < static_cast(y) || copyWidth < 1 || copyHeight < 1) { return; } + const unsigned right = std::min(this->width, static_cast(x) + copyWidth); const unsigned bottom = std::min(this->height, static_cast(y) + copyHeight); const float factor = static_cast(100 - percent) * 0.01f; - // Original does not set dirty here. + for (unsigned row = y; row < bottom; ++row) { for (unsigned column = x; column < right; ++column) { std::uint32_t& pixel = this->pixels[column + row * this->width]; if (pixel != 0xFFFF00FF) { std::uint32_t value = 0xFF000000; + for (unsigned shift : {0u, 8u, 16u}) { - value |= static_cast(static_cast(static_cast((pixel >> shift) & 255) * factor)) - << shift; + value |= static_cast(static_cast(static_cast((pixel >> shift) & 255) * factor)) << shift; } + pixel = value; } } @@ -256,45 +259,39 @@ void BitmapPixels::Dim(int x, int y, int copyWidth, int copyHeight, int percent) // OFFSET: 0x00548780 // FUNCTION: fn_01856 void BitmapPixels::CopyRegion( - int x, - int y, - int sourceLeft, - int sourceTop, - int sourceRight, - int sourceBottom, - const std::uint32_t* source, - int sourceWidth, - int sourceHeight, - bool transparent, - bool alpha + int x, int y, int sourceLeft, int sourceTop, int sourceRight, int sourceBottom, const std::uint32_t* source, int sourceWidth, int sourceHeight, + bool transparent, bool alpha ) { if (!this->pixels || !source) { return; } + this->dirty = true; + for (int sourceY = sourceTop, destinationY = y; sourceY < sourceBottom; ++sourceY, ++destinationY) { - if ( - sourceY < 0 || sourceY >= sourceHeight || destinationY < 0 || static_cast(destinationY) >= this->height - ) { + if (sourceY < 0 || sourceY >= sourceHeight || destinationY < 0 || static_cast(destinationY) >= this->height) { continue; } + for (int sourceX = sourceLeft, destinationX = x; sourceX < sourceRight; ++sourceX, ++destinationX) { - if ( - sourceX < 0 || sourceX >= sourceWidth || destinationX < 0 || static_cast(destinationX) >= this->width - ) { + if (sourceX < 0 || sourceX >= sourceWidth || destinationX < 0 || static_cast(destinationX) >= this->width) { continue; } + const std::uint32_t input = source[sourceX + sourceY * sourceWidth]; if (transparent && input == 0xFFFF00FF) { continue; } + std::uint32_t& destination = this->pixels[destinationX + destinationY * this->width]; if (alpha) { const unsigned a = input >> 24; std::uint32_t output = std::max(a, destination >> 24) << 24; + for (unsigned shift : {0u, 8u, 16u}) { output |= (a * ((input >> shift) & 255) / 255 + (255 - a) * ((destination >> shift) & 255) / 255) << shift; } + destination = output; } else { destination = input; @@ -306,40 +303,36 @@ void BitmapPixels::CopyRegion( // OFFSET: 0x005460B0 // FUNCTION: fn_01839 void BitmapPixels::DrawSurface( - int x, - int y, - CSurface* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - bool mirrored, - int scaleX, - int scaleY, - int filter, - int format + int x, int y, CSurface* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, bool mirrored, int scaleX, int scaleY, int filter, int format ) { if (!source || !this->pixels) { return; } + SurfaceLock locked = source->Lock(); if (!locked.success) { return; } + this->dirty = true; - const auto* input = static_cast(locked.pixels); + const auto* input = static_cast(locked.pixels); const int stride = locked.pitch / 2; + for (int row = 0; row < sourceHeight; ++row) { for (int column = 0; column < sourceWidth; ++column) { const int inputX = sourceX + (mirrored ? sourceWidth - column - 1 : column); - const std::uint16_t value = input[inputX + (sourceY + row) * stride]; - if ((format == 0 && !(value & 0x8000)) || (format == 1 && !(value & 0xF000)) || (format != 0 && format != 1)) { + std::uint16_t value; + std::memcpy(&value, input + 2 * (inputX + (sourceY + row) * stride), sizeof(value)); + + if ((format == TextureFormat::A1R5G5B5 && !(value & 0x8000)) || (format == TextureFormat::A4R4G4B4 && !(value & 0xF000)) || + (format != TextureFormat::A1R5G5B5 && format != TextureFormat::A4R4G4B4)) { continue; } - unsigned red = format ? (value >> 4) & 0xF0 : (value >> 7) & 0xF8; - unsigned green = format ? value & 0xF0 : (value >> 2) & 0xF8; - unsigned blue = format ? (value & 15) << 4 : (value & 31) << 3; - // Filtering helper. + + unsigned red = format != TextureFormat::A1R5G5B5 ? (value >> 4) & 0xF0 : (value >> 7) & 0xF8; + unsigned green = format != TextureFormat::A1R5G5B5 ? value & 0xF0 : (value >> 2) & 0xF8; + unsigned blue = format != TextureFormat::A1R5G5B5 ? (value & 15) << 4 : (value & 31) << 3; + if (filter) { const unsigned average = std::max((red + green + blue) / 3, filter == 1 ? 120u : 100u); red = green = blue = average; @@ -351,35 +344,33 @@ void BitmapPixels::DrawSurface( blue = 200; } } + float alpha = 1; - if (format == 1) { + if (format == TextureFormat::A4R4G4B4) { alpha = static_cast(value >> 12) * 0.06666667f; if (alpha > 0.97f) { alpha = 1; } } + for (int dy = 0; dy < scaleY; ++dy) { const int destinationY = y + row * scaleY + dy; + for (int dx = 0; dx < scaleX; ++dx) { const int destinationX = x + column * scaleX + dx; - if ( - destinationX >= 0 && destinationY >= 0 && static_cast(destinationX) < this->width && - static_cast(destinationY) < this->height - ) { + if (destinationX >= 0 && destinationY >= 0 && static_cast(destinationX) < this->width && + static_cast(destinationY) < this->height) { std::uint32_t& destination = this->pixels[destinationX + destinationY * this->width]; - if (format == 0) { + if (format == TextureFormat::A1R5G5B5) { destination = 0xFF000000 | (red << 16) | (green << 8) | blue; } else { const float inverse = 1 - alpha; - const auto b = static_cast(static_cast( - static_cast(destination & 255) * inverse + static_cast(blue) * alpha - )); - const auto g = static_cast(static_cast( - static_cast((destination >> 8) & 255) * inverse + static_cast(green) * alpha - )); - const auto r = static_cast(static_cast( - static_cast((destination >> 16) & 255) * inverse + static_cast(red) * alpha - )); + const auto b = + static_cast(static_cast(static_cast(destination & 255) * inverse + static_cast(blue) * alpha)); + const auto g = + static_cast(static_cast(static_cast((destination >> 8) & 255) * inverse + static_cast(green) * alpha)); + const auto r = + static_cast(static_cast(static_cast((destination >> 16) & 255) * inverse + static_cast(red) * alpha)); destination = b | (g << 8) | (r << 16); } } @@ -387,42 +378,27 @@ void BitmapPixels::DrawSurface( } } } + source->Unlock(); } // OFFSET: 0x005469E0 // FUNCTION: fn_01840 void BitmapPixels::DrawScaledSurface( - int x, - int y, - int drawWidth, - int drawHeight, - CSurface* source, - int sourceWidth, - int sourceHeight, - float scaleX, - float scaleY, - std::uint32_t color, - bool mirrored, - int offsetX, - int offsetY, - int sourceX, - int sourceY, - int format + int x, int y, int drawWidth, int drawHeight, CSurface* source, int sourceWidth, int sourceHeight, float scaleX, float scaleY, std::uint32_t color, + bool mirrored, int offsetX, int offsetY, int sourceX, int sourceY, int format ) { - if ( - !source || x < 0 || this->width < static_cast(x) || y < 0 || this->height < static_cast(y) || - drawWidth < 0 || drawHeight < 0 || this->width < static_cast(x) + drawWidth || - this->height < static_cast(y) + drawHeight || !(scaleX > 0) || !(scaleY > 0) || !color - ) { + if (!source || x < 0 || this->width < static_cast(x) || y < 0 || this->height < static_cast(y) || drawWidth < 0 || drawHeight < 0 || + this->width < static_cast(x) + drawWidth || this->height < static_cast(y) + drawHeight || !(scaleX > 0) || !(scaleY > 0) || !color) { return; } + SurfaceLock locked = source->Lock(); if (!locked.success) { return; } - // Original does not set dirty in this operation. - const auto* input = static_cast(locked.pixels); + + const auto* input = static_cast(locked.pixels); const int stride = locked.pitch / 2; const int start = sourceX + sourceY * stride; const int limit = sourceHeight * stride; @@ -435,68 +411,67 @@ void BitmapPixels::DrawScaledSurface( const float inverseY = 1 / scaleY; const int scaledWidth = static_cast(static_cast(sourceWidth) * scaleX); const int scaledHeight = static_cast(static_cast(sourceHeight) * scaleY); + for (int row = 0; row < scaledHeight; ++row) { for (int column = 0; column < scaledWidth; ++column) { const int destinationX = offsetX + column; const int destinationY = offsetY + row; - // These original comparisons are inclusive, even at width/height. + if (destinationX < 0 || drawWidth < destinationX || destinationY < 0 || drawHeight < destinationY) { continue; } + const int sampleX = static_cast(static_cast(column) * inverseX); const int sampleY = static_cast(static_cast(row) * inverseY); const int index = sampleY * stride + (mirrored ? sourceWidth - sampleX - 1 : sampleX); + if (index < 0 || index >= limit) { continue; } - const std::uint16_t value = input[start + index]; - if ((format == 0 && !(value & 0x8000)) || (format == 1 && !(value & 0xF000)) || (format != 0 && format != 1)) { + + std::uint16_t value; + std::memcpy(&value, input + 2 * (start + index), sizeof(value)); + if ((format == TextureFormat::A1R5G5B5 && !(value & 0x8000)) || (format == TextureFormat::A4R4G4B4 && !(value & 0xF000)) || + (format != TextureFormat::A1R5G5B5 && format != TextureFormat::A4R4G4B4)) { continue; } - const unsigned red = format ? (value >> 4) & 0xF0 : (value >> 7) & 0xF8; - const unsigned green = format ? value & 0xF0 : (value >> 2) & 0xF8; - const unsigned blue = format ? (value & 15) << 4 : (value & 31) << 3; + + const unsigned red = format != TextureFormat::A1R5G5B5 ? (value >> 4) & 0xF0 : (value >> 7) & 0xF8; + const unsigned green = format != TextureFormat::A1R5G5B5 ? value & 0xF0 : (value >> 2) & 0xF8; + const unsigned blue = format != TextureFormat::A1R5G5B5 ? (value & 15) << 4 : (value & 31) << 3; std::uint32_t& destination = this->pixels[x + destinationX + (y + destinationY) * this->width]; - const auto b = static_cast( - static_cast(static_cast(destination & 255) * inverse + static_cast(blue) * blueScale) - ); - const auto g = static_cast(static_cast( - static_cast((destination >> 8) & 255) * inverse + static_cast(green) * greenScale - )); - const auto r = static_cast(static_cast( - static_cast((destination >> 16) & 255) * inverse + static_cast(red) * redScale - )); + const auto b = static_cast(static_cast(static_cast(destination & 255) * inverse + static_cast(blue) * blueScale)); + const auto g = + static_cast(static_cast(static_cast((destination >> 8) & 255) * inverse + static_cast(green) * greenScale)); + const auto r = + static_cast(static_cast(static_cast((destination >> 16) & 255) * inverse + static_cast(red) * redScale)); destination = 0xFF000000 | (r << 16) | (g << 8) | b; } } + source->Unlock(); } // OFFSET: 0x00545E20 // FUNCTION: fn_01838 void BitmapPixels::DrawRleSprite( - int x, - int y, - std::span cells, - const SpriteRleImage* const* const* images, - const std::uint32_t* palette, - int cellCount + int x, int y, std::span cells, const SpriteRleImage* const* const* images, const std::uint32_t* palette, int cellCount ) { const SpriteFrameCell missing{0, 0, -1, 0, 0xFFFFFFFF, 1, 1, 0, 0}; + for (int cellIndex = 0; cellIndex < cellCount; ++cellIndex) { const SpriteFrameCell& cell = static_cast(cellIndex) < cells.size() ? cells[cellIndex] : missing; if (cell.image == -1) { continue; } + const SpriteRleImage& image = *images[cell.imageType][cell.image]; const int left = x - image.width / 2; const int top = y - image.height / 2; const int destinationX = std::max(left, 0); const int destinationY = std::max(top, 0); - const int copyWidth = - static_cast(std::min(this->width, static_cast(left + image.width))) - destinationX; - const int copyHeight = - static_cast(std::min(this->height, static_cast(top + image.height))) - destinationY; + const int copyWidth = static_cast(std::min(this->width, static_cast(left + image.width))) - destinationX; + const int copyHeight = static_cast(std::min(this->height, static_cast(top + image.height))) - destinationY; const int skip = std::max(-left, 0) + image.width * std::max(-top, 0); const std::uint8_t* runs = image.runs; int remaining = 0; @@ -505,25 +480,29 @@ void BitmapPixels::DrawRleSprite( --remaining; return 0; } + unsigned value = *runs++; if (!value) { remaining = *runs++ - 1; } + return value; }; + for (int index = 0; index < skip; ++index) { next(); } + for (int row = 0; row < copyHeight; ++row) { for (int column = 0; column < copyWidth; ++column) { const unsigned index = next(); if (index) { const std::uint32_t color = palette[index]; const unsigned pixelX = destinationX + (cell.mirrored ? copyWidth - column - 1 : column); - this->pixels[pixelX + (destinationY + row) * this->width] = - ((color & 0x1F) << 3) + ((color & 0x3E0) << 6) + ((color & 0x7C00) << 9) - 0x01000000; + this->pixels[pixelX + (destinationY + row) * this->width] = ((color & 0x1F) << 3) + ((color & 0x3E0) << 6) + ((color & 0x7C00) << 9) - 0x01000000; } } + for (int index = 0; index < image.width - copyWidth; ++index) { next(); } @@ -534,39 +513,31 @@ void BitmapPixels::DrawRleSprite( // OFFSET: 0x00545C40 // FUNCTION: fn_01837 void BitmapPixels::DrawScaledSprite( - int x, - int y, - int drawWidth, - int drawHeight, - std::span cells, - const SpriteRleImage* const* const* images, - int cellCount, - int offsetX, - int offsetY, - float scale, - const std::uint32_t* palette, - SpriteAtlas& atlas, - CRenderSystemBase& system, - int serviceType, - std::uint32_t reuseDelay + int x, int y, int drawWidth, int drawHeight, std::span cells, const SpriteRleImage* const* const* images, int cellCount, int offsetX, + int offsetY, float scale, const std::uint32_t* palette, SpriteAtlas& atlas, CRenderSystemBase& system, int serviceType, std::uint32_t reuseDelay ) { if (!images) { return; } + const SpriteFrameCell missing{0, 0, -1, 0, 0xFFFFFFFF, 1, 1, 0, 0}; SpriteAtlasRecord record{}; + for (int index = 0; index < cellCount; ++index) { const SpriteFrameCell& cell = static_cast(index) < cells.size() ? cells[index] : missing; if (cell.image == -1) { continue; } + const SpriteRleImage* image = images[cell.imageType][cell.image]; if (!image) { continue; } + const float scaleX = scale * cell.scaleX; const float scaleY = scale * cell.scaleY; CSurface* surface; + if (!cell.imageType) { surface = atlas.Find(image, palette, record); if (!surface) { @@ -575,41 +546,35 @@ void BitmapPixels::DrawScaledSprite( } else { surface = static_cast(const_cast(image->unknown_0008)); } + if (!surface) { continue; } - // Stored action color is ABGR; original rebuilds ARGB from individual bytes. + const std::uint32_t color = (cell.color & 0xFF00FF00u) | ((cell.color & 255) << 16) | ((cell.color >> 16) & 255); this->DrawScaledSurface( x, y, drawWidth, drawHeight, surface, image->width, image->height, scaleX, scaleY, color, cell.mirrored != 0, static_cast(static_cast(cell.x) * scaleX + static_cast(offsetX)), - static_cast(static_cast(cell.y) * scaleY + static_cast(offsetY)), - static_cast(record.u0 * 256), static_cast(record.v0 * 256), static_cast(surface)->Format() + static_cast(static_cast(cell.y) * scaleY + static_cast(offsetY)), static_cast(record.u0 * 256), static_cast(record.v0 * 256), + static_cast(surface)->Format() ); } } // OFFSET: 0x00547D80 // FUNCTION: fn_01851 -void BitmapPixels::ScaleCopy( - int x, - int y, - int sourceWidth, - int sourceHeight, - int drawWidth, - int drawHeight, - const std::uint32_t* source, - int -) { +void BitmapPixels::ScaleCopy(int x, int y, int sourceWidth, int sourceHeight, int drawWidth, int drawHeight, const std::uint32_t* source, int) { if (!this->pixels || !source) { return; } + this->dirty = true; const float scaleX = static_cast(drawWidth) / static_cast(sourceWidth); const float scaleY = static_cast(drawHeight) / static_cast(sourceHeight); const int columns = scaleX < 1 ? sourceWidth : drawWidth; const int rows = scaleY < 1 ? sourceHeight : drawHeight; std::vector scratch(static_cast(columns) * rows); + if (scaleX == 1) { for (int row = 0; row < sourceHeight; ++row) { for (int column = 0; column < sourceWidth; ++column) { @@ -617,8 +582,8 @@ void BitmapPixels::ScaleCopy( } } } else if (scaleX < 1) { - // Original carries both sampling indices across rows, not per-row resets. int output = 0, previous = 0; + for (int row = 0; row < sourceHeight; ++row) { for (int column = 0; column < sourceWidth; ++column) { int next = static_cast(static_cast(column) * scaleX); @@ -627,6 +592,7 @@ void BitmapPixels::ScaleCopy( if (column == sourceWidth - 1 && output != drawWidth - 1) { scratch[(row + 1) * drawWidth - 1] = source[row * sourceWidth + previous]; } + previous = column; output = next; } @@ -634,48 +600,60 @@ void BitmapPixels::ScaleCopy( } } else { int output = 0; + for (int row = 0; row < sourceHeight; ++row) { for (int column = 1; column <= sourceWidth; ++column) { int next = static_cast(static_cast(column) * scaleX); + for (int index = output; index < next; ++index) { scratch[row * drawWidth + index] = source[row * sourceWidth + column - 1]; } + output = next; } } } + if (scaleY < 1) { int output = 0, previous = 0; + for (int column = 0; column < drawWidth; ++column) { if (static_cast(x + column) >= this->width) { continue; } + int sample = previous * drawWidth; + for (int row = 0; row < sourceHeight; ++row) { const int next = static_cast(static_cast(row) * scaleY); if (output != next && static_cast(y + next) <= this->height) { previous = row; this->pixels[x + column + (y + output) * this->width] = scratch[sample + column]; output = next; - // Original stores the current scan offset only after each row. + sample = row * drawWidth; } } } } else { int output = 0; + for (int column = 0; column < drawWidth; ++column) { if (static_cast(x + column) >= this->width) { continue; } + for (int row = 1; row <= sourceHeight; ++row) { int next = static_cast(static_cast(row) * scaleY); + for (int index = output; index < next; ++index) { if (static_cast(y + index) >= this->height) { break; } + this->pixels[x + column + (y + index) * this->width] = scratch[(row - 1) * drawWidth + column]; } + output = next; } } diff --git a/Source/Render/Textures/BitmapPixels.h b/Source/Render/Textures/BitmapPixels.h new file mode 100644 index 0000000..8ee45c6 --- /dev/null +++ b/Source/Render/Textures/BitmapPixels.h @@ -0,0 +1,62 @@ +#ifndef RAGNAROK_SOURCE_RENDER_TEXTURES_BITMAPPIXELS_H +#define RAGNAROK_SOURCE_RENDER_TEXTURES_BITMAPPIXELS_H + +#include "Render/Textures/SpritePixels.h" + +#include +#include + +class CSurface; +class SpriteAtlas; +class CRenderSystemBase; +class CTexture; + +struct BitmapPixels { + /* 0000 */ std::uint32_t width; + /* 0004 */ std::uint32_t height; + /* 0008 */ HDC dc; + /* 000C */ HBITMAP bitmap; + /* 0010 */ HGDIOBJ previous; + /* 0014 */ std::uint32_t* pixels; + /* 0018 */ bool dirty; + + BitmapPixels(int width, int height); + ~BitmapPixels(); + void Grow(std::uint32_t width, std::uint32_t height); + bool GetDC(HDC* output); + void ReleaseDC(HDC dc); + void Fill(const RECT* rectangle, std::uint32_t color); + void Copy(int x, int y, int width, int height, const std::uint32_t* source, bool transparent); + void CopyFrom(int x, int y, int sourceX, int sourceY, int width, int height, const BitmapPixels& source); + void BlendFrom(std::uint32_t x, std::uint32_t y, int width, int height, const BitmapPixels& source, bool alpha); + void Brighten(int x, int y, int width, int height, int amount); + void Dim(int x, int y, int width, int height, int percent); + void CopyRegion( + int x, int y, int sourceLeft, int sourceTop, int sourceRight, int sourceBottom, const std::uint32_t* source, int sourceWidth, int sourceHeight, + bool transparent, bool alpha + ); + void DrawSurface( + int x, int y, CSurface* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, bool mirrored, int scaleX, int scaleY, int filter, int format + ); + void DrawScaledSurface( + int x, int y, int width, int height, CSurface* source, int sourceWidth, int sourceHeight, float scaleX, float scaleY, std::uint32_t color, bool mirrored, + int offsetX, int offsetY, int sourceX, int sourceY, int format + ); + void + DrawRleSprite(int x, int y, std::span cells, const SpriteRleImage* const* const* images, const std::uint32_t* palette, int cellCount); + void DrawScaledSprite( + int x, int y, int width, int height, std::span cells, const SpriteRleImage* const* const* images, int cellCount, int offsetX, + int offsetY, float scale, const std::uint32_t* palette, SpriteAtlas& atlas, CRenderSystemBase& system, int serviceType, std::uint32_t reuseDelay + ); + void ScaleCopy(int x, int y, int sourceWidth, int sourceHeight, int width, int height, const std::uint32_t* source, int option); + void UploadTexture(CRenderSystemBase& system, CTexture*& texture); + +private: + void Create(int width, int height); +}; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(BitmapPixels) == 28); +#endif + +#endif diff --git a/Source/Render/BitmapTextureCache.cpp b/Source/Render/Textures/BitmapTextureCache.cpp similarity index 81% rename from Source/Render/BitmapTextureCache.cpp rename to Source/Render/Textures/BitmapTextureCache.cpp index e9298d9..6bd7dfe 100644 --- a/Source/Render/BitmapTextureCache.cpp +++ b/Source/Render/Textures/BitmapTextureCache.cpp @@ -1,7 +1,7 @@ -#include "Render/BitmapPixels.h" -#include "Render/BitmapTextureCache.h" +#include "Render/Textures/BitmapPixels.h" +#include "Render/Textures/BitmapTextureCache.h" #include "Render/RenderSystemBase.h" -#include "Render/Texture.h" +#include "Render/Textures/Texture.h" #include @@ -22,6 +22,7 @@ void BitmapTextureCache::Clear() { for (CTexture* texture : this->m_textures) { delete texture; } + this->m_textures.clear(); } @@ -31,13 +32,15 @@ void BitmapTextureCache::Update(BitmapPixels& bitmap, CRenderSystemBase& system) if (!bitmap.dirty) { return; } + if (this->m_alpha) { if (this->m_textures.empty()) { - CTexture* texture = system.CreateTexture(bitmap.width, bitmap.height, 4, false, false); + CTexture* texture = system.CreateTexture(bitmap.width, bitmap.height, TextureFormat::A8R8G8B8, false, false); if (texture) { this->m_textures.push_back(texture); } } + for (CTexture* texture : this->m_textures) { texture->Upload(0, 0, bitmap.width, bitmap.height, bitmap.pixels, 0, bitmap.width); } @@ -46,47 +49,42 @@ void BitmapTextureCache::Update(BitmapPixels& bitmap, CRenderSystemBase& system) for (unsigned y = 0; y < bitmap.height; y += 256) { for (unsigned x = 0; x < bitmap.width; x += 256) { this->m_textures.push_back( - system.CreateTexture(std::min(256u, bitmap.width - x), std::min(256u, bitmap.height - y), 0, false, false) + system.CreateTexture(std::min(256u, bitmap.width - x), std::min(256u, bitmap.height - y), TextureFormat::A1R5G5B5, false, false) ); } } } + const std::int32_t bytes = static_cast(4u * bitmap.width * bitmap.height); + for (std::int32_t offset = 0; offset < bytes; offset += 4) { reinterpret_cast(bitmap.pixels)[offset + 3] = 255; } + auto texture = this->m_textures.begin(); + for (unsigned y = 0; y < bitmap.height; y += 256) { for (unsigned x = 0; x < bitmap.width; x += 256) { - (*texture++) - ->Upload( - 0, 0, std::min(256u, bitmap.width - x), std::min(256u, bitmap.height - y), - bitmap.pixels + x + y * bitmap.width, 0, bitmap.width - ); + (*texture++)->Upload(0, 0, std::min(256u, bitmap.width - x), std::min(256u, bitmap.height - y), bitmap.pixels + x + y * bitmap.width, 0, bitmap.width); } } } + bitmap.dirty = false; } // OFFSET: 0x00547B80 // FUNCTION: fn_01846 -void BitmapTextureCache::Draw( - BitmapPixels& bitmap, - CRenderSystemBase& system, - int x, - int y, - int width, - int height, - std::uint32_t color -) { +void BitmapTextureCache::Draw(BitmapPixels& bitmap, CRenderSystemBase& system, int x, int y, int width, int height, std::uint32_t color) { if (!bitmap.pixels) { return; } + this->Update(bitmap, system); if (this->m_textures.empty()) { return; } + if (this->m_alpha) { for (CTexture* texture : this->m_textures) { texture->Draw(x, y, width, height, color); @@ -94,8 +92,10 @@ void BitmapTextureCache::Draw( } else { auto texture = this->m_textures.begin(); int remainingHeight = height; + for (int row = 0; row < height; row += 256, remainingHeight -= 256) { int remainingWidth = width; + for (int column = 0; column < width; column += 256, remainingWidth -= 256) { (*texture++)->Draw(x + column, y + row, std::min(256, remainingWidth), std::min(256, remainingHeight), color); } diff --git a/Source/Render/BitmapTextureCache.h b/Source/Render/Textures/BitmapTextureCache.h similarity index 77% rename from Source/Render/BitmapTextureCache.h rename to Source/Render/Textures/BitmapTextureCache.h index e4d1d74..f0ae6ad 100644 --- a/Source/Render/BitmapTextureCache.h +++ b/Source/Render/Textures/BitmapTextureCache.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_BITMAPTEXTURECACHE_H -#define RAGNAROK_SOURCE_RENDER_BITMAPTEXTURECACHE_H +#ifndef RAGNAROK_SOURCE_RENDER_TEXTURES_BITMAPTEXTURECACHE_H +#define RAGNAROK_SOURCE_RENDER_TEXTURES_BITMAPTEXTURECACHE_H #include #include @@ -8,7 +8,6 @@ struct BitmapPixels; class CTexture; class CRenderSystemBase; -// CDCBitmap's contiguous list/alpha subobject at +32/+40 on x86. class BitmapTextureCache { public: BitmapTextureCache(); diff --git a/Source/Render/ClientTextureSources.cpp b/Source/Render/Textures/ClientTextureSources.cpp similarity index 76% rename from Source/Render/ClientTextureSources.cpp rename to Source/Render/Textures/ClientTextureSources.cpp index 8e5b4f3..13ff91d 100644 --- a/Source/Render/ClientTextureSources.cpp +++ b/Source/Render/Textures/ClientTextureSources.cpp @@ -1,14 +1,10 @@ -#include "Contents/BinkMovies.h" -#include "Render/ClientTextureSources.h" +#include "Contents/Movies/BinkMovies.h" +#include "Render/Textures/ClientTextureSources.h" #include "Render/RenderSystemBase.h" #include "Resource/TextureNames.h" ClientTextureSources::ClientTextureSources( - TextureNames& names, - const int& modeType, - BinkMovies* const& movies, - CRenderSystemBase*& system, - IDirectDraw7* const& directDraw + TextureNames& names, const int& modeType, BinkMovies* const& movies, CRenderSystemBase*& system, IDirectDraw7* const& directDraw ) : m_names(names), m_modeType(modeType), m_movies(movies), m_system(system), m_directDraw(directDraw) { } @@ -34,7 +30,6 @@ bool ClientTextureSources::MovieSize(const char* name, int& width, int& height) } void ClientTextureSources::CleanupTextures() { - // DX7 slot compacts IDirectDraw; DX9 slot is empty. if (this->m_system && this->m_system->Backend() == 1 && this->m_directDraw) { this->m_directDraw->Compact(); } diff --git a/Source/Render/Textures/ClientTextureSources.h b/Source/Render/Textures/ClientTextureSources.h new file mode 100644 index 0000000..ba34011 --- /dev/null +++ b/Source/Render/Textures/ClientTextureSources.h @@ -0,0 +1,26 @@ +#ifndef RAGNAROK_SOURCE_RENDER_TEXTURES_CLIENTTEXTURESOURCES_H +#define RAGNAROK_SOURCE_RENDER_TEXTURES_CLIENTTEXTURESOURCES_H + +#include "Render/Textures/TextureCache.h" + +#include + +struct TextureNames; +class BinkMovies; + +class ClientTextureSources : public TextureSources { +public: + ClientTextureSources(TextureNames& names, const int& modeType, BinkMovies* const& movies, CRenderSystemBase*& system, IDirectDraw7* const& directDraw); + const char* Resolve(const char* name) override; + bool MovieSize(const char* name, int& width, int& height) override; + void CleanupTextures() override; + +private: + TextureNames& m_names; + const int& m_modeType; + BinkMovies* const& m_movies; + CRenderSystemBase*& m_system; + IDirectDraw7* const& m_directDraw; +}; + +#endif diff --git a/Source/Render/SpriteAtlas.cpp b/Source/Render/Textures/SpriteAtlas.cpp similarity index 88% rename from Source/Render/SpriteAtlas.cpp rename to Source/Render/Textures/SpriteAtlas.cpp index 12dec91..15611b8 100644 --- a/Source/Render/SpriteAtlas.cpp +++ b/Source/Render/Textures/SpriteAtlas.cpp @@ -1,26 +1,32 @@ #include "Render/RenderSystemBase.h" -#include "Render/SpriteAtlas.h" -#include "Render/Texture.h" +#include "Render/Textures/SpriteAtlas.h" +#include "Render/Textures/Texture.h" #include -#include +#include +#include namespace { // STATIC: 0x010DD520 / 0x010DD524 constexpr unsigned dimensions[5] = {32, 64, 128, 256, 512}; + unsigned Category(int dimension) { if (dimension > 256) { return 4; } + if (dimension > 128) { return 3; } + if (dimension > 64) { return 2; } + if (dimension > 32) { return 1; } + return 0; } } @@ -42,14 +48,15 @@ SpriteAtlas::~SpriteAtlas() { std::size_t SpriteAtlas::Hash::operator()(const Key& key) const { const auto hashPointer = [](std::uintptr_t pointer) { std::uint32_t hash = 0x811C9DC5; + for (unsigned i = 0; i < sizeof(pointer); ++i) { hash = (hash ^ ((pointer >> (i * 8)) & 255)) * 16777619u; } + return hash; }; const std::uint32_t first = hashPointer(reinterpret_cast(key.image)); - return first ^ - (hashPointer(reinterpret_cast(key.palette)) + (first << 6) + (first >> 2) + 0x9E3779B9u); + return first ^ (hashPointer(reinterpret_cast(key.palette)) + (first << 6) + (first >> 2) + 0x9E3779B9u); } // OFFSET: 0x0056FB00 @@ -60,11 +67,13 @@ void SpriteAtlas::Initialize(CRenderSystemBase& system, unsigned spareCount) { if (this->m_spare.capacity() < spareCount) { this->m_spare.reserve(spareCount); } + for (unsigned i = 0; i < spareCount; ++i) { - CTexture* texture = system.CreateTexture(256, 256, 0, false, false); + CTexture* texture = system.CreateTexture(256, 256, TextureFormat::A1R5G5B5, false, false); if (!texture) { break; } + texture->Retain(); this->m_spare.push_back(texture); } @@ -82,12 +91,14 @@ void SpriteAtlas::Clear() { delete texture; } } + while (head) { Node* next = head->next; delete head; head = next; } } + this->m_lookup.clear(); } @@ -98,6 +109,7 @@ void SpriteAtlas::ClearSpare() { texture->Release(); delete texture; } + this->m_spare.clear(); } @@ -108,10 +120,12 @@ CTexture* SpriteAtlas::Find(const SpriteRleImage* image, const std::uint32_t* pa if (found == this->m_lookup.end()) { return nullptr; } + SpriteAtlasRecord& record = *found->second; record.lastUsed = timeGetTime(); record.page->lastUsed = record.lastUsed; output = record; + return record.page->texture; } @@ -122,18 +136,21 @@ SpriteAtlasPage* SpriteAtlas::Allocate(CRenderSystemBase& system, unsigned categ node->next = this->m_classes[category]; this->m_classes[category] = node; SpriteAtlasPage& page = node->page; + if (width <= 256 && height <= 256 && !this->m_spare.empty()) { page.texture = this->m_spare.back(); this->m_spare.pop_back(); } else { - page.texture = system.CreateTexture(width, height, 0, false, false); + page.texture = system.CreateTexture(width, height, TextureFormat::A1R5G5B5, false, false); } + page.texture->Fill(nullptr, 0); page.cellWidth = dimensions[category / 5]; page.cellHeight = dimensions[category % 5]; const unsigned columns = width / page.cellWidth; const unsigned rows = height / page.cellHeight; page.records.resize(columns * rows); + for (unsigned y = 0; y < rows; ++y) { for (unsigned x = 0; x < columns; ++x) { SpriteAtlasRecord& record = page.records[x + y * columns]; @@ -144,24 +161,21 @@ SpriteAtlasPage* SpriteAtlas::Allocate(CRenderSystemBase& system, unsigned categ record.page = &page; } } + return &page; } // OFFSET: 0x0056F410 // FUNCTION: fn_02404 CTexture* SpriteAtlas::Insert( - CRenderSystemBase& system, - const SpriteRleImage* image, - const std::uint32_t* palette, - SpriteAtlasRecord& output, - int serviceType, - std::uint32_t reuseDelay + CRenderSystemBase& system, const SpriteRleImage* image, const std::uint32_t* palette, SpriteAtlasRecord& output, int serviceType, std::uint32_t reuseDelay ) { const std::uint32_t threshold = timeGetTime() - (reuseDelay >> 2); const unsigned width = image->width > 256 ? (image->width / 256 + 1) * 256 : 256; const unsigned height = image->height > 256 ? (image->height / 256 + 1) * 256 : 256; const unsigned category = Category(image->width) * 5 + Category(image->height); SpriteAtlasRecord* selected = nullptr; + for (Node* node = this->m_classes[category]; node && !selected; node = node->next) { for (SpriteAtlasRecord& record : node->page.records) { if (record.lastUsed < threshold) { @@ -171,34 +185,37 @@ CTexture* SpriteAtlas::Insert( } } } + if (!selected) { selected = &this->Allocate(system, category, width, height)->records[0]; } + SpriteAtlasRecord& record = *selected; record.image = image; record.palette = palette; float u1 = static_cast(record.x + image->width) / static_cast(width); float v1 = static_cast(record.y + image->height) / static_cast(height); + if (serviceType == 10) { if (image->width > 64) { u1 -= 0.005f; } + if (image->height > 64) { v1 -= 0.005f; } } + record.u1 = u1; record.v1 = v1; CTexture* texture = record.page->texture; - texture->UploadSprite( - record.x, record.y, record.page->cellWidth, record.page->cellHeight, image, - static_cast(reinterpret_cast(palette)) - ); + texture->UploadSprite(record.x, record.y, record.page->cellWidth, record.page->cellHeight, image, palette); record.lastUsed = timeGetTime(); record.page->lastUsed = record.lastUsed; this->m_lookup.emplace(Key{image, palette}, &record); record.u1 = static_cast(record.u1 - 0.5 / texture->Width()); record.v1 = static_cast(record.v1 - 0.5 / texture->Height()); output = record; + return texture; } diff --git a/Source/Render/SpriteAtlas.h b/Source/Render/Textures/SpriteAtlas.h similarity index 77% rename from Source/Render/SpriteAtlas.h rename to Source/Render/Textures/SpriteAtlas.h index 76084cc..204750c 100644 --- a/Source/Render/SpriteAtlas.h +++ b/Source/Render/Textures/SpriteAtlas.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_RENDER_SPRITEATLAS_H -#define RAGNAROK_SOURCE_RENDER_SPRITEATLAS_H +#ifndef RAGNAROK_SOURCE_RENDER_TEXTURES_SPRITEATLAS_H +#define RAGNAROK_SOURCE_RENDER_TEXTURES_SPRITEATLAS_H -#include "Render/SpritePixels.h" +#include "Render/Textures/SpritePixels.h" #include #include @@ -32,8 +32,6 @@ struct SpriteAtlasPage { std::uint32_t lastUsed; }; -// Original renderer subobject+192:25 singly-linked page classes, native -// image/palette hash map and spare textures. Context is an original caller input. class SpriteAtlas { public: SpriteAtlas(); @@ -42,12 +40,7 @@ public: void Clear(); CTexture* Find(const SpriteRleImage* image, const std::uint32_t* palette, SpriteAtlasRecord& output); CTexture* Insert( - CRenderSystemBase& system, - const SpriteRleImage* image, - const std::uint32_t* palette, - SpriteAtlasRecord& output, - int serviceType, - std::uint32_t reuseDelay + CRenderSystemBase& system, const SpriteRleImage* image, const std::uint32_t* palette, SpriteAtlasRecord& output, int serviceType, std::uint32_t reuseDelay ); private: diff --git a/Source/Render/SpritePixels.h b/Source/Render/Textures/SpritePixels.h similarity index 68% rename from Source/Render/SpritePixels.h rename to Source/Render/Textures/SpritePixels.h index acfff24..669ff22 100644 --- a/Source/Render/SpritePixels.h +++ b/Source/Render/Textures/SpritePixels.h @@ -1,10 +1,9 @@ -#ifndef RAGNAROK_SOURCE_RENDER_SPRITEPIXELS_H -#define RAGNAROK_SOURCE_RENDER_SPRITEPIXELS_H +#ifndef RAGNAROK_SOURCE_RENDER_TEXTURES_SPRITEPIXELS_H +#define RAGNAROK_SOURCE_RENDER_TEXTURES_SPRITEPIXELS_H #include #include -// 36-byte action cell used by frame accessor. struct SpriteFrameCell { std::int32_t x; std::int32_t y; @@ -18,7 +17,6 @@ struct SpriteFrameCell { }; static_assert(sizeof(SpriteFrameCell) == 36); -// Original image record: dimensions at0/2, RLE byte pointer at+12 on x86. struct SpriteRleImage { std::int16_t width; std::int16_t height; diff --git a/Source/Render/Surface.cpp b/Source/Render/Textures/Surface.cpp similarity index 60% rename from Source/Render/Surface.cpp rename to Source/Render/Textures/Surface.cpp index affd4e9..49ed5c8 100644 --- a/Source/Render/Surface.cpp +++ b/Source/Render/Textures/Surface.cpp @@ -1,4 +1,4 @@ -#include "Render/Surface.h" +#include "Render/Textures/Surface.h" // OFFSET: 0x00572370 CSurface::~CSurface() = default; diff --git a/Source/Render/Surface.h b/Source/Render/Textures/Surface.h similarity index 76% rename from Source/Render/Surface.h rename to Source/Render/Textures/Surface.h index 1b7d6da..525b0d2 100644 --- a/Source/Render/Surface.h +++ b/Source/Render/Textures/Surface.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_SURFACE_H -#define RAGNAROK_SOURCE_RENDER_SURFACE_H +#ifndef RAGNAROK_SOURCE_RENDER_TEXTURES_SURFACE_H +#define RAGNAROK_SOURCE_RENDER_TEXTURES_SURFACE_H #include #include @@ -13,7 +13,6 @@ struct SurfaceLock { int bitsPerPixel; }; -// RTTI CSurface. Pure backend contracts, not stand-ins. class CSurface { public: virtual ~CSurface(); @@ -24,8 +23,7 @@ public: virtual void Unlock() = 0; virtual bool GetDC(HDC* output) = 0; virtual void ReleaseDC(HDC dc) = 0; - virtual void - Upload(int x, int y, int width, int height, const std::uint32_t* pixels, int option, int sourceWidth) = 0; + virtual void Upload(int x, int y, int width, int height, const std::uint32_t* pixels, int option, int sourceWidth) = 0; virtual void Fill(const RECT* rectangle, std::uint32_t color) = 0; virtual void Draw(int x, int y, int width, int height, std::uint32_t color) = 0; virtual void Stretch(int x, int y, int width, int height) = 0; diff --git a/Source/Render/Texture.cpp b/Source/Render/Textures/Texture.cpp similarity index 79% rename from Source/Render/Texture.cpp rename to Source/Render/Textures/Texture.cpp index 74f3d73..d3cd688 100644 --- a/Source/Render/Texture.cpp +++ b/Source/Render/Textures/Texture.cpp @@ -1,10 +1,11 @@ -#include "Render/RenderPrimitivePool.h" -#include "Render/RenderQueues.h" -#include "Render/Texture.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/Textures/Texture.h" #include #include -#include +#include +#include // STATIC: 0x01312DE0 // GLOBAL: gl_21914 @@ -16,7 +17,7 @@ float g_textureOffsetY = 0.5f; // OFFSET: 0x005722E0 // FUNCTION: fn_02463 CTexture::CTexture() - : m_format(-1), unknown_0008(1), m_textureWidth(0), m_textureHeight(0), m_width(0), m_height(0), unknown_001C(0), + : m_format(TextureFormat::UnknownTextureFormat), unknown_0008(1), m_textureWidth(0), m_textureHeight(0), m_width(0), m_height(0), unknown_001C(0), unknown_0020(0) { this->m_name[0] = '\0'; } @@ -57,9 +58,11 @@ std::uint32_t CTexture::SetImageSize(std::uint32_t width, std::uint32_t height) while (width > this->m_textureWidth) { width >>= 1; } + while (height > this->m_textureHeight) { height >>= 1; } + this->m_height = height; this->m_width = width; return width; @@ -70,24 +73,13 @@ int CTexture::SetName(const char* name) { } namespace { - // Shared recovered vertex construction, not a separately addressed original. - void SetQuad( - RenderPrimitive* primitive, - CTexture* texture, - int x, - int y, - int width, - int height, - std::uint32_t color, - float u0, - float v0, - float u1, - float v1 - ) { + void + SetQuad(RenderPrimitive* primitive, CTexture* texture, int x, int y, int width, int height, std::uint32_t color, float u0, float v0, float u1, float v1) { constexpr float z = 0.00001f; constexpr float rhw = 0.99999f; const float right = static_cast(static_cast(static_cast(x) + width)); const float bottom = static_cast(static_cast(static_cast(y) + height)); + primitive->texture = texture; primitive->quad[0] = {static_cast(x), static_cast(y), z, rhw, color, 0xFFFFFFFF, u0, v0}; primitive->quad[1] = {right, static_cast(y), z, rhw, color, 0xFFFFFFFF, u1, v0}; @@ -99,16 +91,7 @@ namespace { // OFFSET: 0x00544410 // FUNCTION: fn_01817 void CTexture::DrawTo( - RenderPrimitivePool& pool, - RenderQueues& queues, - int x, - int y, - int width, - int height, - std::uint32_t color, - bool depthAlpha, - float depthStart, - float depthEnd + RenderPrimitivePool& pool, RenderQueues& queues, int x, int y, int width, int height, std::uint32_t color, bool depthAlpha, float depthStart, float depthEnd ) { const float u0 = g_textureOffsetX / static_cast(this->m_textureWidth); const float v0 = g_textureOffsetY / static_cast(this->m_textureHeight); @@ -122,15 +105,7 @@ void CTexture::DrawTo( // OFFSET: 0x00544610 // FUNCTION: fn_01818 void CTexture::StretchTo( - RenderPrimitivePool& pool, - RenderQueues& queues, - int x, - int y, - int width, - int height, - bool depthAlpha, - float depthStart, - float depthEnd + RenderPrimitivePool& pool, RenderQueues& queues, int x, int y, int width, int height, bool depthAlpha, float depthStart, float depthEnd ) { const float u0 = g_textureOffsetX / static_cast(this->m_textureWidth); const float v0 = g_textureOffsetY / static_cast(this->m_textureHeight); diff --git a/Source/Render/Texture.h b/Source/Render/Textures/Texture.h similarity index 56% rename from Source/Render/Texture.h rename to Source/Render/Textures/Texture.h index 9dcebac..b2a2992 100644 --- a/Source/Render/Texture.h +++ b/Source/Render/Textures/Texture.h @@ -1,68 +1,38 @@ -#ifndef RAGNAROK_SOURCE_RENDER_TEXTURE_H -#define RAGNAROK_SOURCE_RENDER_TEXTURE_H +#ifndef RAGNAROK_SOURCE_RENDER_TEXTURES_TEXTURE_H +#define RAGNAROK_SOURCE_RENDER_TEXTURES_TEXTURE_H -#include "Render/Surface.h" +#include "Render/Textures/Surface.h" class RenderPrimitivePool; struct RenderQueues; +struct SpriteRleImage; + +enum TextureFormat : std::int32_t { UnknownTextureFormat = -1, A1R5G5B5 = 0, A4R4G4B4 = 1, R5G6B5 = 2, X1R5G5B5 = 3, A8R8G8B8 = 4 }; // STATIC: 0x01312DE0 / 0x01312DE4 extern float g_textureOffsetX; extern float g_textureOffsetY; -// Actual CTexture base. Device methods remain abstract. class CTexture : public CSurface { public: CTexture(); ~CTexture() override; std::uint32_t Width() override; std::uint32_t Height() override; - virtual void Update(int option) = 0; - virtual void UploadSprite(int x, int y, int width, int height, const void* image, int palette) = 0; - virtual bool CopyTexture( - CTexture* source, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - int x, - int y, - int width, - int height - ) = 0; + virtual void Update(const RECT* rectangle) = 0; + virtual void UploadSprite(int x, int y, int width, int height, const SpriteRleImage* image, const std::uint32_t* palette) = 0; + virtual bool CopyTexture(CTexture* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, int x, int y, int width, int height) = 0; virtual bool Create(int width, int height, int format) = 0; - // Original Draw/Stretch algorithms with renderer dependencies explicit. - // They do not replace unresolved virtual backend dispatch/global ownership. void DrawTo( - RenderPrimitivePool& pool, - RenderQueues& queues, - int x, - int y, - int width, - int height, - std::uint32_t color, - bool depthAlpha, - float depthStart, - float depthEnd - ); - void StretchTo( - RenderPrimitivePool& pool, - RenderQueues& queues, - int x, - int y, - int width, - int height, - bool depthAlpha, - float depthStart, - float depthEnd + RenderPrimitivePool& pool, RenderQueues& queues, int x, int y, int width, int height, std::uint32_t color, bool depthAlpha, float depthStart, float depthEnd ); + void StretchTo(RenderPrimitivePool& pool, RenderQueues& queues, int x, int y, int width, int height, bool depthAlpha, float depthStart, float depthEnd); std::uint32_t SetImageSize(std::uint32_t width, std::uint32_t height); std::uint32_t Retain(); std::uint32_t Release(); int SetName(const char* name); - // Source accessors for original direct texture-allocation dimensions. std::uint32_t TextureWidth() const { return this->m_textureWidth; } diff --git a/Source/Render/TextureCache.cpp b/Source/Render/Textures/TextureCache.cpp similarity index 79% rename from Source/Render/TextureCache.cpp rename to Source/Render/Textures/TextureCache.cpp index f708542..6831804 100644 --- a/Source/Render/TextureCache.cpp +++ b/Source/Render/Textures/TextureCache.cpp @@ -1,26 +1,20 @@ #include "Render/RenderSystemBase.h" -#include "Render/Texture.h" -#include "Render/TextureCache.h" -#include "Resource/BitmapResource.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" #include -#include +#include +#include -// Original key comparison is unsigned-byte, case-sensitive string order. bool TextureNameLess::operator()(const char* left, const char* right) const { return std::strcmp(left, right) < 0; } // OFFSET: 0x004074F5 // FUNCTION: fn_00152 -TextureCache::TextureCache( - ResourceMgr& resources, - CRenderSystemBase*& system, - TextureSources& sources, - const int& reduction, - const unsigned& reuseDelay -) +TextureCache::TextureCache(ResourceMgr& resources, CRenderSystemBase*& system, TextureSources& sources, const int& reduction, const unsigned& reuseDelay) : m_resources(resources), m_system(system), m_sources(sources), m_reduction(reduction), m_reuseDelay(reuseDelay) { } @@ -38,20 +32,10 @@ CTexture* TextureCache::Default() { // OFFSET: 0x005715E0 // FUNCTION: fn_02449 -CTexture* TextureCache::Upload( - int width, - int height, - const std::uint32_t* pixels, - int format, - int option, - bool fullSize, - bool dynamic, - bool renderTarget -) { +CTexture* TextureCache::Upload(int width, int height, const std::uint32_t* pixels, int format, int option, bool fullSize, bool dynamic, bool renderTarget) { const int outputWidth = fullSize ? width : width / this->m_reduction; const int outputHeight = fullSize ? height : height / this->m_reduction; - CTexture* texture = - this->m_system ? this->m_system->CreateTexture(outputWidth, outputHeight, format, dynamic, renderTarget) : nullptr; + CTexture* texture = this->m_system ? this->m_system->CreateTexture(outputWidth, outputHeight, format, dynamic, renderTarget) : nullptr; if (texture) { texture->Upload(0, 0, width, height, pixels, option, 0); @@ -69,7 +53,7 @@ CTexture* TextureCache::Create(const char* name, int option, bool fullSize, bool int height; if (this->m_sources.MovieSize(name, width, height)) { - CTexture* texture = this->m_system ? this->m_system->CreateTexture(width, height, 4, false, false) : nullptr; + CTexture* texture = this->m_system ? this->m_system->CreateTexture(width, height, TextureFormat::A8R8G8B8, false, false) : nullptr; if (texture) { return texture; @@ -81,17 +65,16 @@ CTexture* TextureCache::Create(const char* name, int option, bool fullSize, bool if (bitmap) { const auto& image = bitmap->image; CTexture* texture = this->Upload( - image.width, image.height, image.pixels, image.alpha != 0 ? 1 : 0, option, fullSize, dynamic, renderTarget + image.width, image.height, image.pixels, image.alpha != 0 ? TextureFormat::A4R4G4B4 : TextureFormat::A1R5G5B5, option, fullSize, dynamic, renderTarget ); this->m_resources.Remove(bitmap); + return texture; } } - // Original explicitly creates a transparent 1x1 substitute on a missing - // bitmap/movie, rather than returning the renderer's shared default here. const int extent = 1 / this->m_reduction; - CTexture* texture = this->m_system ? this->m_system->CreateTexture(extent, extent, 0, false, false) : nullptr; + CTexture* texture = this->m_system ? this->m_system->CreateTexture(extent, extent, TextureFormat::A1R5G5B5, false, false) : nullptr; if (texture) { const std::uint32_t transparent = 0; @@ -121,6 +104,7 @@ CTexture* TextureCache::Load(const char* name, int option, bool fullSize, bool d strncpy_s(texture->m_name, sizeof(texture->m_name), name, _TRUNCATE); texture->unknown_0020 = timeGetTime(); this->m_textures.emplace(texture->m_name, texture); + return texture; } diff --git a/Source/Render/TextureCache.h b/Source/Render/Textures/TextureCache.h similarity index 55% rename from Source/Render/TextureCache.h rename to Source/Render/Textures/TextureCache.h index 4ca162a..3fd4b26 100644 --- a/Source/Render/TextureCache.h +++ b/Source/Render/Textures/TextureCache.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RENDER_TEXTURECACHE_H -#define RAGNAROK_SOURCE_RENDER_TEXTURECACHE_H +#ifndef RAGNAROK_SOURCE_RENDER_TEXTURES_TEXTURECACHE_H +#define RAGNAROK_SOURCE_RENDER_TEXTURES_TEXTURECACHE_H #include "Resource/EZeffectResource.h" @@ -8,14 +8,11 @@ class ResourceMgr; class CRenderSystemBase; -// Name override and movie lookup remain -// real owner dependencies. Movie success supplies its current frame extent; -// no decoded pixels are copied by original texture creation at this point. class TextureSources { public: virtual const char* Resolve(const char* name) = 0; virtual bool MovieSize(const char* name, int& width, int& height) = 0; - // Renderer virtual slot +0x40: DX7 compacts its device; DX9 is empty. + virtual void CleanupTextures() = 0; protected: @@ -26,31 +23,14 @@ struct TextureNameLess { bool operator()(const char* left, const char* right) const; }; -// Ordered cache. Keys borrow the texture's inline name; -// the cache owns the textures, while the backend owns the default texture. class TextureCache : public EffectTextures { public: - TextureCache( - ResourceMgr& resources, - CRenderSystemBase*& system, - TextureSources& sources, - const int& reduction, - const unsigned& reuseDelay - ); + TextureCache(ResourceMgr& resources, CRenderSystemBase*& system, TextureSources& sources, const int& reduction, const unsigned& reuseDelay); ~TextureCache(); CTexture* Load(const char* name, int option, bool fullSize, bool dynamic, bool renderTarget) override; CTexture* Default() override; CTexture* Create(const char* name, int option, bool fullSize, bool dynamic, bool renderTarget); - CTexture* Upload( - int width, - int height, - const std::uint32_t* pixels, - int format, - int option, - bool fullSize, - bool dynamic, - bool renderTarget - ); + CTexture* Upload(int width, int height, const std::uint32_t* pixels, int format, int option, bool fullSize, bool dynamic, bool renderTarget); void Remove(CTexture* texture); void Clear(); void ClearUnused(); diff --git a/Source/Render/UIRPData.h b/Source/Render/UIRPData.h deleted file mode 100644 index f3f91cc..0000000 --- a/Source/Render/UIRPData.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef RAGNAROK_SOURCE_RENDER_UIRPDATA_H -#define RAGNAROK_SOURCE_RENDER_UIRPDATA_H - -#include "Render/RenderPrimitive.h" - -#include - -class CTexture; -class RenderPrimitivePool; - -// Original UIRPData base; commands are borrowed from the renderer pool, -// m_texture is owned. The enclosing window supplies its actual renderer. -class UIRPData { -public: - UIRPData(); - virtual ~UIRPData(); - void Draw( - RenderPrimitivePool& pool, - int x, - int y, - CTexture* texture, - std::uint32_t color, - int width, - int height, - bool stretched - ); - -protected: - /* 0004 */ std::list m_primitives; - /* 000C */ CTexture* m_texture; -}; - -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(UIRPData) == 16); -#endif - -#endif diff --git a/Source/Resource/Audio/MilesRuntime.cpp b/Source/Resource/Audio/MilesRuntime.cpp new file mode 100644 index 0000000..7f87098 --- /dev/null +++ b/Source/Resource/Audio/MilesRuntime.cpp @@ -0,0 +1,82 @@ +#include "Resource/Audio/MilesRuntime.h" + +#include + +MilesRuntime& MilesRuntime::Get() { + static MilesRuntime instance; + return instance; +} + +MilesRuntime::MilesRuntime() : m_module(LoadLibraryA("Mss32.dll")) { + if (!this->m_module) { + throw std::system_error(GetLastError(), std::system_category(), "Mss32.dll"); + } + + this->startup = reinterpret_caststartup)>(GetProcAddress(this->m_module, "_AIL_startup@0")); + this->shutdown = reinterpret_castshutdown)>(GetProcAddress(this->m_module, "_AIL_shutdown@0")); + this->setRedistDirectory = reinterpret_castsetRedistDirectory)>(GetProcAddress(this->m_module, "_AIL_set_redist_directory@4")); + this->setPreference = reinterpret_castsetPreference)>(GetProcAddress(this->m_module, "_AIL_set_preference@8")); + this->openDigitalDriver = reinterpret_castopenDigitalDriver)>(GetProcAddress(this->m_module, "_AIL_open_digital_driver@16")); + this->closeDigitalDriver = reinterpret_castcloseDigitalDriver)>(GetProcAddress(this->m_module, "_AIL_close_digital_driver@4")); + this->allocateSample = reinterpret_castallocateSample)>(GetProcAddress(this->m_module, "_AIL_allocate_sample_handle@4")); + this->releaseSample = reinterpret_castreleaseSample)>(GetProcAddress(this->m_module, "_AIL_release_sample_handle@4")); + this->initSample = reinterpret_castinitSample)>(GetProcAddress(this->m_module, "_AIL_init_sample@4")); + this->setSampleFile = reinterpret_castsetSampleFile)>(GetProcAddress(this->m_module, "_AIL_set_sample_file@12")); + this->sampleStatus = reinterpret_castsampleStatus)>(GetProcAddress(this->m_module, "_AIL_sample_status@4")); + this->setSampleVolume = reinterpret_castsetSampleVolume)>(GetProcAddress(this->m_module, "_AIL_set_sample_volume@8")); + this->startSample = reinterpret_caststartSample)>(GetProcAddress(this->m_module, "_AIL_start_sample@4")); + this->endSample = reinterpret_castendSample)>(GetProcAddress(this->m_module, "_AIL_end_sample@4")); + + this->openStream = reinterpret_castopenStream)>(GetProcAddress(this->m_module, "_AIL_open_stream@12")); + this->closeStream = reinterpret_castcloseStream)>(GetProcAddress(this->m_module, "_AIL_close_stream@4")); + this->streamStatus = reinterpret_caststreamStatus)>(GetProcAddress(this->m_module, "_AIL_stream_status@4")); + this->setStreamLoopCount = reinterpret_castsetStreamLoopCount)>(GetProcAddress(this->m_module, "_AIL_set_stream_loop_count@8")); + this->streamVolume = reinterpret_caststreamVolume)>(GetProcAddress(this->m_module, "_AIL_stream_volume@4")); + this->setStreamVolume = reinterpret_castsetStreamVolume)>(GetProcAddress(this->m_module, "_AIL_set_stream_volume@8")); + this->pauseStream = reinterpret_castpauseStream)>(GetProcAddress(this->m_module, "_AIL_pause_stream@8")); + this->startStream = reinterpret_caststartStream)>(GetProcAddress(this->m_module, "_AIL_start_stream@4")); + + this->enumerate3DProviders = reinterpret_castenumerate3DProviders)>(GetProcAddress(this->m_module, "_AIL_enumerate_3D_providers@12")); + this->open3DProvider = reinterpret_castopen3DProvider)>(GetProcAddress(this->m_module, "_AIL_open_3D_provider@4")); + this->close3DProvider = reinterpret_castclose3DProvider)>(GetProcAddress(this->m_module, "_AIL_close_3D_provider@4")); + this->speakerType = reinterpret_castspeakerType)>(GetProcAddress(this->m_module, "_AIL_3D_speaker_type@4")); + this->setSpeakerType = reinterpret_castsetSpeakerType)>(GetProcAddress(this->m_module, "_AIL_set_3D_speaker_type@8")); + this->open3DListener = reinterpret_castopen3DListener)>(GetProcAddress(this->m_module, "_AIL_open_3D_listener@4")); + this->close3DListener = reinterpret_castclose3DListener)>(GetProcAddress(this->m_module, "_AIL_close_3D_listener@4")); + this->allocate3DSample = reinterpret_castallocate3DSample)>(GetProcAddress(this->m_module, "_AIL_allocate_3D_sample_handle@4")); + this->release3DSample = reinterpret_castrelease3DSample)>(GetProcAddress(this->m_module, "_AIL_release_3D_sample_handle@4")); + this->set3DSampleFile = reinterpret_castset3DSampleFile)>(GetProcAddress(this->m_module, "_AIL_set_3D_sample_file@8")); + this->sample3DStatus = reinterpret_castsample3DStatus)>(GetProcAddress(this->m_module, "_AIL_3D_sample_status@4")); + this->set3DSampleVolume = reinterpret_castset3DSampleVolume)>(GetProcAddress(this->m_module, "_AIL_set_3D_sample_volume@8")); + this->start3DSample = reinterpret_caststart3DSample)>(GetProcAddress(this->m_module, "_AIL_start_3D_sample@4")); + this->end3DSample = reinterpret_castend3DSample)>(GetProcAddress(this->m_module, "_AIL_end_3D_sample@4")); + this->roomType = reinterpret_castroomType)>(GetProcAddress(this->m_module, "_AIL_3D_room_type@4")); + this->setRoomType = reinterpret_castsetRoomType)>(GetProcAddress(this->m_module, "_AIL_set_3D_room_type@8")); + this->set3DSampleDistances = reinterpret_castset3DSampleDistances)>(GetProcAddress(this->m_module, "_AIL_set_3D_sample_distances@12")); + this->set3DSampleEffectsLevel = + reinterpret_castset3DSampleEffectsLevel)>(GetProcAddress(this->m_module, "_AIL_set_3D_sample_effects_level@8")); + this->set3DPosition = reinterpret_castset3DPosition)>(GetProcAddress(this->m_module, "_AIL_set_3D_position@16")); + this->set3DOrientation = reinterpret_castset3DOrientation)>(GetProcAddress(this->m_module, "_AIL_set_3D_orientation@28")); + + this->fileType = reinterpret_castfileType)>(GetProcAddress(this->m_module, "_AIL_file_type@8")); + this->wavInfo = reinterpret_castwavInfo)>(GetProcAddress(this->m_module, "_AIL_WAV_info@8")); + this->decompressADPCM = reinterpret_castdecompressADPCM)>(GetProcAddress(this->m_module, "_AIL_decompress_ADPCM@12")); + this->decompressASI = reinterpret_castdecompressASI)>(GetProcAddress(this->m_module, "_AIL_decompress_ASI@24")); + this->freeLocked = reinterpret_castfreeLocked)>(GetProcAddress(this->m_module, "_AIL_mem_free_lock@4")); + + if (!this->startup || !this->shutdown || !this->setRedistDirectory || !this->setPreference || !this->openDigitalDriver || !this->closeDigitalDriver || + !this->allocateSample || !this->releaseSample || !this->initSample || !this->setSampleFile || !this->sampleStatus || !this->setSampleVolume || + !this->startSample || !this->endSample || !this->openStream || !this->closeStream || !this->streamStatus || !this->setStreamLoopCount || + !this->streamVolume || !this->setStreamVolume || !this->pauseStream || !this->startStream || !this->enumerate3DProviders || !this->open3DProvider || + !this->close3DProvider || !this->speakerType || !this->setSpeakerType || !this->open3DListener || !this->close3DListener || !this->allocate3DSample || + !this->release3DSample || !this->set3DSampleFile || !this->sample3DStatus || !this->set3DSampleVolume || !this->start3DSample || !this->end3DSample || + !this->roomType || !this->setRoomType || !this->set3DSampleDistances || !this->set3DSampleEffectsLevel || !this->set3DPosition || + !this->set3DOrientation || !this->fileType || !this->wavInfo || !this->decompressADPCM || !this->decompressASI || !this->freeLocked) { + FreeLibrary(this->m_module); + throw std::system_error(ERROR_PROC_NOT_FOUND, std::system_category(), "Mss32 exports"); + } +} + +MilesRuntime::~MilesRuntime() { + FreeLibrary(this->m_module); +} diff --git a/Source/Resource/MilesRuntime.h b/Source/Resource/Audio/MilesRuntime.h similarity index 86% rename from Source/Resource/MilesRuntime.h rename to Source/Resource/Audio/MilesRuntime.h index 6a87c63..7470f5e 100644 --- a/Source/Resource/MilesRuntime.h +++ b/Source/Resource/Audio/MilesRuntime.h @@ -1,11 +1,9 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_MILESRUNTIME_H -#define RAGNAROK_SOURCE_RESOURCE_MILESRUNTIME_H +#ifndef RAGNAROK_SOURCE_RESOURCE_AUDIO_MILESRUNTIME_H +#define RAGNAROK_SOURCE_RESOURCE_AUDIO_MILESRUNTIME_H #include #include -// Miles Sound System 6.1a, supplied Mss32.dll (x86). Provider/enumeration -// handles are integers; driver, stream, sample and 3D object handles are opaque. using MilesProvider = std::uint32_t; using MilesEnumeration = std::uint32_t; @@ -21,9 +19,6 @@ struct MilesSoundInfo { const void* initial; }; -// Host import binding, not an original application class. Get() owns the DLL -// until process exit. Initialize registers shutdown after Get() constructs the -// runtime, so that callback executes before the runtime's own destruction. class MilesRuntime { public: static MilesRuntime& Get(); diff --git a/Source/Resource/WaveResource.cpp b/Source/Resource/Audio/WaveResource.cpp similarity index 84% rename from Source/Resource/WaveResource.cpp rename to Source/Resource/Audio/WaveResource.cpp index 7adfa92..d7b5f60 100644 --- a/Source/Resource/WaveResource.cpp +++ b/Source/Resource/Audio/WaveResource.cpp @@ -1,8 +1,8 @@ -#include "Client/ErrorDialog.h" -#include "Resource/BitmapResource.h" -#include "Resource/MilesRuntime.h" +#include "Client/Application/ErrorDialog.h" +#include "Resource/Bitmap/BitmapResource.h" +#include "Resource/Audio/MilesRuntime.h" #include "Resource/ResourceMgr.h" -#include "Resource/WaveResource.h" +#include "Resource/Audio/WaveResource.h" #include #include @@ -32,6 +32,7 @@ bool CWave::Load(const char* name) { const std::string message = std::string("Wave :: Cannot find File : ") + name; ShowErrorDialog(context.renderSystem, message.c_str(), 0); file.Close(); + return false; } @@ -51,6 +52,7 @@ bool CWave::Load(const char* name) { miles.wavInfo(raw, &info); miles.decompressADPCM(&info, &this->data, nullptr); std::free(raw); + return true; } @@ -58,6 +60,7 @@ bool CWave::Load(const char* name) { this->milesAllocated = 1; miles.decompressASI(raw, static_cast(size), name, &this->data, nullptr, nullptr); std::free(raw); + return true; } @@ -68,9 +71,6 @@ bool CWave::Load(const char* name) { // OFFSET: 0x00761830 // FUNCTION: fn_08068 void CWave::Unload() { - // In the original binary, this->data is freed but never reset to nullptr. - // Repeatedly calling Unload without an intervening Load retains a dangling - // pointer, preserving original memory management semantics. if (this->data != nullptr) { if (this->milesAllocated != 0) { MilesRuntime::Get().freeLocked(this->data); diff --git a/Source/Resource/WaveResource.h b/Source/Resource/Audio/WaveResource.h similarity index 60% rename from Source/Resource/WaveResource.h rename to Source/Resource/Audio/WaveResource.h index 13be3c1..a4eb914 100644 --- a/Source/Resource/WaveResource.h +++ b/Source/Resource/Audio/WaveResource.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_WAVERESOURCE_H -#define RAGNAROK_SOURCE_RESOURCE_WAVERESOURCE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_AUDIO_WAVERESOURCE_H +#define RAGNAROK_SOURCE_RESOURCE_AUDIO_WAVERESOURCE_H #include "Resource/Resource.h" @@ -13,9 +13,6 @@ struct WaveResourceContext { CRenderSystemBase*& renderSystem; }; -// RTTI CWave. Original size is 0x118; -// only the borrowed source context is appended (total 0x11C in x86). -// Destructor does NOT call Unload; ResourceMgr handles unloading. class CWave : public CRes { public: explicit CWave(WaveResourceContext& context); @@ -31,9 +28,6 @@ private: /* 0118 */ WaveResourceContext* m_context; }; -// Registration portion of the wave resource initializer. The application owns the -// prototype and its context; both must outlive the manager and loaded waves. -// ResourceBytes still requires the original archive-aware read implementation. void RegisterWaveResource(ResourceMgr& resourceMgr, CWave& prototype); #if defined(_WIN32) && !defined(_WIN64) diff --git a/Source/Resource/BinkRuntime.cpp b/Source/Resource/BinkRuntime.cpp index b0186b1..8d6fa7e 100644 --- a/Source/Resource/BinkRuntime.cpp +++ b/Source/Resource/BinkRuntime.cpp @@ -14,14 +14,11 @@ BinkRuntime::BinkRuntime() : m_module(LoadLibraryA("binkw32.dll")) { this->doFrame = reinterpret_castdoFrame)>(GetProcAddress(this->m_module, "_BinkDoFrame@4")); this->shouldSkip = reinterpret_castshouldSkip)>(GetProcAddress(this->m_module, "_BinkShouldSkip@4")); this->nextFrame = reinterpret_castnextFrame)>(GetProcAddress(this->m_module, "_BinkNextFrame@4")); - this->copyToBuffer = - reinterpret_castcopyToBuffer)>(GetProcAddress(this->m_module, "_BinkCopyToBuffer@28")); + this->copyToBuffer = reinterpret_castcopyToBuffer)>(GetProcAddress(this->m_module, "_BinkCopyToBuffer@28")); this->setVolume = reinterpret_castsetVolume)>(GetProcAddress(this->m_module, "_BinkSetVolume@12")); - if ( - !this->open || !this->close || !this->error || !this->wait || !this->doFrame || !this->shouldSkip || - !this->nextFrame || !this->copyToBuffer || !this->setVolume - ) { + if (!this->open || !this->close || !this->error || !this->wait || !this->doFrame || !this->shouldSkip || !this->nextFrame || !this->copyToBuffer || + !this->setVolume) { FreeLibrary(this->m_module); throw std::system_error(ERROR_PROC_NOT_FOUND, std::system_category(), "binkw32 exports"); } diff --git a/Source/Resource/BinkRuntime.h b/Source/Resource/BinkRuntime.h index 0d98874..048a8e1 100644 --- a/Source/Resource/BinkRuntime.h +++ b/Source/Resource/BinkRuntime.h @@ -4,8 +4,6 @@ #include #include -// Public prefix read/written by the original wrapper, not the decoder's -// complete private allocation. Supplied binkw32.dll is x86-only. struct BinkHandle { std::uint32_t width; std::uint32_t height; @@ -13,7 +11,6 @@ struct BinkHandle { std::uint32_t frame; }; -// Host loader for original imported APIs; no fabricated original entry. class BinkRuntime { public: BinkRuntime(); diff --git a/Source/Resource/BitmapImage.cpp b/Source/Resource/Bitmap/BitmapImage.cpp similarity index 94% rename from Source/Resource/BitmapImage.cpp rename to Source/Resource/Bitmap/BitmapImage.cpp index 81cbfc2..98e7309 100644 --- a/Source/Resource/BitmapImage.cpp +++ b/Source/Resource/Bitmap/BitmapImage.cpp @@ -1,4 +1,4 @@ -#include "Resource/BitmapImage.h" +#include "Resource/Bitmap/BitmapImage.h" #include #include @@ -12,18 +12,22 @@ namespace { std::memcpy(&value, data, sizeof(value)); return value; } + std::uint32_t Read32(const unsigned char* data) { std::uint32_t value; std::memcpy(&value, data, sizeof(value)); return value; } + int Signed(std::uint32_t value) { return std::bit_cast(value); } + std::size_t PixelBytes(int width, int height) { const std::uint32_t count = static_cast(width) * static_cast(height); return count > 0x3FFFFFFFu ? 0xFFFFFFFFu : count * 4u; } + std::uint32_t Color(const unsigned char* data, unsigned alpha) { return data[0] | (data[1] << 8) | (data[2] << 16) | (alpha << 24); } @@ -40,9 +44,11 @@ void BitmapImage::Clear() { if (this->pixels) { std::free(this->pixels); } + if (this->auxiliary) { std::free(this->auxiliary); } + this->width = this->height = 0; this->pixels = nullptr; this->auxiliary = nullptr; @@ -53,9 +59,8 @@ void BitmapImage::Clear() { bool BitmapImage::DecodeBitmap(const void* input, int, bool iconOnly) { this->Clear(); const auto* data = static_cast(input); - // Twelve-byte custom signature (CP949). - static constexpr unsigned char signature[] = {0xC3, 0xD1, 0xBE, 0xCB, 0xC0, 0xCC, 0xBB, - 0xA1, 0xC5, 0xE4, 0xB4, 0xCF, 0}; + + static constexpr unsigned char signature[] = {0xC3, 0xD1, 0xBE, 0xCB, 0xC0, 0xCC, 0xBB, 0xA1, 0xC5, 0xE4, 0xB4, 0xCF, 0}; unsigned char prefix[13]; std::memcpy(prefix, data, 12); prefix[12] = 0; @@ -64,10 +69,12 @@ bool BitmapImage::DecodeBitmap(const void* input, int, bool iconOnly) { unsigned char* rgb; const unsigned char* source; std::uint32_t palette[256]; + if (custom) { const std::uint32_t dimensions = (Read32(data + 12) >> 1) - 0x01929300u; const int width = dimensions >> 16; const int height = static_cast(dimensions & 0xFFFFu) - 1; + if (data[16] == 0) { bits = 24; } else if (data[16] == 1) { @@ -76,23 +83,28 @@ bool BitmapImage::DecodeBitmap(const void* input, int, bool iconOnly) { OutputDebugStringA("Only 16M or 8bit color format supported"); return false; } + if (iconOnly && (width != 24 || height != 24)) { return false; } + this->width = width; this->height = height; rgb = static_cast(std::malloc(3u * width * height)); this->pixels = static_cast(std::malloc(PixelBytes(width, height))); source = data + 17; + if (bits == 8) { unsigned count = Read32(source); source += 4; if (!count) { count = 256; } + const unsigned char* first = source; const unsigned char* second = source + 2u * count; source += 4u * count; + for (unsigned i = 0; i < count; ++i) { palette[i] = first[2 * i + 1] | (first[2 * i] << 8) | (second[2 * i + 1] << 16) | (second[2 * i] << 24); } @@ -104,11 +116,13 @@ bool BitmapImage::DecodeBitmap(const void* input, int, bool iconOnly) { source += 2u * count; std::memcpy(second, source, count); source += count; + for (std::uint32_t i = 0; i < count; ++i) { rgb[3 * i] = second[i]; rgb[3 * i + 1] = first[2 * i]; rgb[3 * i + 2] = first[2 * i + 1]; } + std::free(first); std::free(second); } @@ -116,35 +130,42 @@ bool BitmapImage::DecodeBitmap(const void* input, int, bool iconOnly) { if (Read16(data) != 0x4D42) { return false; } + bits = Read16(data + 28); if (bits != 24 && bits != 8) { OutputDebugStringA("Only 16M or 8bit color format supported"); return false; } + const int width = Signed(Read32(data + 18)); const int height = Signed(Read32(data + 22)); if (iconOnly && (width != 24 || height != 24)) { return false; } + this->width = width; this->height = height; rgb = static_cast(std::malloc(3u * width * height)); this->pixels = static_cast(std::malloc(PixelBytes(width, height))); const std::uint32_t offset = Read32(data + 10); + if (bits == 8) { const unsigned count = Read32(data + 46) ? Read32(data + 46) : 256; std::memcpy(palette, data + 54, 4u * count); - // Original checks <= palette end, not >= as a standard BMP reader would. + if (offset > 54u + 4u * count) { return false; } + source = data + offset; } else { if (offset > 54) { return false; } + source = data + offset; const std::uint32_t alignedWidth = (static_cast(width) + 3) & ~3u; + for (int y = height - 1; y >= 0; --y) { std::memcpy(rgb + 3u * y * width, source, 3u * width); source += 3u * width; @@ -154,8 +175,10 @@ bool BitmapImage::DecodeBitmap(const void* input, int, bool iconOnly) { } } } + if (bits == 8) { const std::uint32_t stride = (static_cast(this->width) + 3) & ~3u; + for (int y = this->height - 1; y >= 0; --y) { for (int x = 0; x < this->width; ++x) { const std::uint32_t value = palette[source[x]]; @@ -164,17 +187,21 @@ bool BitmapImage::DecodeBitmap(const void* input, int, bool iconOnly) { pixel[1] = static_cast(value >> 8); pixel[2] = static_cast(value >> 16); } + source += stride; } } + for (int y = 0; y < this->height; ++y) { const std::uint32_t row = static_cast(y) * this->width; - // Original converts the first pixel even for a zero/negative width. + this->pixels[row] = Color(rgb + 3u * row, 255); + for (int x = 1; x < this->width; ++x) { this->pixels[row + x] = Color(rgb + 3u * (row + x), 255); } } + std::free(rgb); this->alpha = 0; return true; @@ -187,10 +214,11 @@ bool BitmapImage::DecodeTga(const void* input, int) { if (data[1] != 0 || (data[2] != 10 && data[2] != 2)) { return false; } + const unsigned char* source = data + 18 + data[0]; this->width = Read16(data + 12); this->height = Read16(data + 14); - // Unlike DecodeBitmap, original TGA entry does not Clear before allocation. + this->pixels = static_cast(std::malloc(PixelBytes(this->width, this->height))); const bool rgba = data[16] == 32; unsigned alpha = 255; @@ -200,16 +228,20 @@ bool BitmapImage::DecodeTga(const void* input, int) { if (rgba) { alpha = *source++; } + return Color(pixel, alpha); }; + for (int y = this->height - 1; y >= 0; --y) { int x = 0; + while (x < this->width) { if (data[2] == 10) { const unsigned packet = *source++; const unsigned count = (packet & 127) + 1; if (packet & 128) { const std::uint32_t value = read(); + for (unsigned i = 0; i < count; ++i) { this->pixels[static_cast(y) * this->width + x++] = value; } @@ -223,6 +255,7 @@ bool BitmapImage::DecodeTga(const void* input, int) { } } } + this->alpha = 1; return true; } diff --git a/Source/Resource/BitmapImage.h b/Source/Resource/Bitmap/BitmapImage.h similarity index 64% rename from Source/Resource/BitmapImage.h rename to Source/Resource/Bitmap/BitmapImage.h index 9381864..cdc0dd0 100644 --- a/Source/Resource/BitmapImage.h +++ b/Source/Resource/Bitmap/BitmapImage.h @@ -1,13 +1,10 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_BITMAPIMAGE_H -#define RAGNAROK_SOURCE_RESOURCE_BITMAPIMAGE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_BITMAP_BITMAPIMAGE_H +#define RAGNAROK_SOURCE_RESOURCE_BITMAP_BITMAPIMAGE_H #include class IJL15Runtime; -// CBitmapRes contiguous fields+272..+291. Allocations use the original CRT -// malloc/free domain. Resource manager unload calls Clear explicitly; the -// original deleting destructor does not unload these buffers automatically. struct BitmapImage { /* 0110 */ int alpha; /* 0114 */ int width; diff --git a/Source/Resource/BitmapImageJpeg.cpp b/Source/Resource/Bitmap/BitmapImageJpeg.cpp similarity index 84% rename from Source/Resource/BitmapImageJpeg.cpp rename to Source/Resource/Bitmap/BitmapImageJpeg.cpp index c2510c2..c5f5791 100644 --- a/Source/Resource/BitmapImageJpeg.cpp +++ b/Source/Resource/Bitmap/BitmapImageJpeg.cpp @@ -1,5 +1,5 @@ -#include "Resource/BitmapImage.h" -#include "Resource/IJL15Runtime.h" +#include "Resource/Bitmap/BitmapImage.h" +#include "Resource/Bitmap/IJL15Runtime.h" #include @@ -10,9 +10,11 @@ bool BitmapImage::DecodeJpeg(const void* data, int bytes, IJL15Runtime& runtime) if (runtime.initialize(&properties) != 0) { return false; } + properties.jpegBytes = const_cast(static_cast(data)); properties.jpegSize = bytes; unsigned char* source; + if (runtime.read(&properties, 1) == 0) { this->width = properties.jpegWidth; this->height = properties.jpegHeight; @@ -22,33 +24,36 @@ bool BitmapImage::DecodeJpeg(const void* data, int bytes, IJL15Runtime& runtime) properties.dibWidth = this->width; properties.dibHeight = this->height; properties.dibBytes = source; - properties.dibColor = 2; // IJL_BGR + properties.dibColor = 2; properties.dibChannels = 3; properties.dibPadding = 0; + if (runtime.read(&properties, 3) != 0) { std::free(source); std::free(this->pixels); this->pixels = nullptr; - // Original returns without ijlFree on this failure branch. + return false; } } else { - // Original falls through with the object itself as the temporary buffer. - // Keep this observable malformed-input behavior, not an invented false. source = reinterpret_cast(this); } + runtime.release(&properties); + for (int y = 0; y < this->height; ++y) { const unsigned char* input = source + 3u * (static_cast(y) * this->width); if (!input) { return false; } + for (int x = 0; x < this->width; ++x, input += 3) { const unsigned blue = input[0], green = input[1], red = input[2]; this->pixels[static_cast(y) * this->width + x] = red >= 254 && green <= 3 && blue >= 254 ? 0x000A0A0Au : blue | (green << 8) | (red << 16) | 0xFF000000u; } } + std::free(source); this->alpha = 0; return true; diff --git a/Source/Resource/BitmapImagePng.cpp b/Source/Resource/Bitmap/BitmapImagePng.cpp similarity index 98% rename from Source/Resource/BitmapImagePng.cpp rename to Source/Resource/Bitmap/BitmapImagePng.cpp index 76dbb7d..5961c04 100644 --- a/Source/Resource/BitmapImagePng.cpp +++ b/Source/Resource/Bitmap/BitmapImagePng.cpp @@ -1,4 +1,4 @@ -#include "Resource/BitmapImage.h" +#include "Resource/Bitmap/BitmapImage.h" #include #include @@ -14,6 +14,7 @@ namespace { this->setg(begin, begin, begin + bytes); } }; + // OFFSET: 0x0074C9D0 // FUNCTION: fn_07879 void ReadPng(png_structp png, png_bytep output, png_size_t bytes) { @@ -31,24 +32,29 @@ bool BitmapImage::DecodePng(const void* data, int bytes, const char*) { *_errno() = 22; _invalid_parameter_noinfo(); } + if (png_sig_cmp(signature, 0, sizeof(signature))) { return false; } + png_structp png = png_create_read_struct("1.6.36", nullptr, nullptr, nullptr); png_infop info; if (!png || !(info = png_create_info_struct(png))) { png_destroy_read_struct(&png, nullptr, nullptr); return false; } + png_infop end = png_create_info_struct(png); if (!end) { png_destroy_read_struct(&png, &info, nullptr); return false; } + if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png, &info, &end); return false; } + MemoryBuffer buffer(data, bytes); std::iostream stream(&buffer); png_set_read_fn(png, &stream, ReadPng); @@ -58,32 +64,42 @@ bool BitmapImage::DecodePng(const void* data, int bytes, const char*) { const unsigned colorType = png_get_color_type(png, info); const unsigned depth = png_get_bit_depth(png, info); png_set_interlace_handling(png); + if (depth == 16) { png_set_strip_16(png); } + if (colorType == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png); } + if (colorType == PNG_COLOR_TYPE_GRAY && depth < 8) { png_set_expand_gray_1_2_4_to_8(png); } + if (png_get_valid(png, info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png); } + if (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_PALETTE) { png_set_filler(png, 255, PNG_FILLER_AFTER); } + if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png); } + png_read_update_info(png, info); auto** rows = static_cast(std::malloc(sizeof(png_bytep) * static_cast(this->height))); + for (int y = 0; y < this->height; ++y) { rows[y] = static_cast(std::malloc(png_get_rowbytes(png, info))); } + png_read_image(png, rows); const std::uint32_t count = static_cast(this->width) * static_cast(this->height); this->pixels = static_cast(std::malloc(count > 0x3FFFFFFFu ? 0xFFFFFFFFu : count * 4u)); + for (int y = 0; y < this->height; ++y) { for (int x = 0; x < this->width; ++x) { const unsigned char* pixel = rows[y] + 4u * x; @@ -91,10 +107,13 @@ bool BitmapImage::DecodePng(const void* data, int bytes, const char*) { pixel[2] | (pixel[1] << 8) | (pixel[0] << 16) | (static_cast(pixel[3]) << 24); } } + this->alpha = 1; + for (int y = 0; y < this->height; ++y) { std::free(rows[y]); } + std::free(rows); png_destroy_read_struct(&png, &info, &end); return true; diff --git a/Source/Resource/BitmapResource.cpp b/Source/Resource/Bitmap/BitmapResource.cpp similarity index 90% rename from Source/Resource/BitmapResource.cpp rename to Source/Resource/Bitmap/BitmapResource.cpp index b530933..4c3fb4d 100644 --- a/Source/Resource/BitmapResource.cpp +++ b/Source/Resource/Bitmap/BitmapResource.cpp @@ -1,6 +1,6 @@ -#include "Client/ErrorDialog.h" -#include "Resource/BitmapResource.h" -#include "Resource/IJL15Runtime.h" +#include "Client/Application/ErrorDialog.h" +#include "Resource/Bitmap/BitmapResource.h" +#include "Resource/Bitmap/IJL15Runtime.h" #include #include @@ -32,7 +32,7 @@ bool CBitmapRes::Load(const char* name) { this->m_context->file.Close(); } } - // Original CFile destructor invokes Close again after the explicit close. + this->m_context->file.Close(); return result; } @@ -50,18 +50,23 @@ bool CBitmapRes::Decode(const char* name, const void* data, int bytes, bool icon if (!extension) { return false; } + if (lstrcmpiA(extension, ".bmp") == 0) { return this->image.DecodeBitmap(data, bytes, iconOnly); } + if (lstrcmpiA(extension, ".tga") == 0) { return this->image.DecodeTga(data, bytes); } + if (lstrcmpiA(extension, ".jpg") == 0) { return this->image.DecodeJpeg(data, bytes, this->m_context->jpeg); } + if (lstrcmpiA(extension, ".png") == 0) { return this->image.DecodePng(data, bytes, name); } + ShowErrorDialog(this->m_context->renderSystem, "Unsupport fileformat!", 0); return false; } diff --git a/Source/Resource/BitmapResource.h b/Source/Resource/Bitmap/BitmapResource.h similarity index 70% rename from Source/Resource/BitmapResource.h rename to Source/Resource/Bitmap/BitmapResource.h index a7eee46..a01fde2 100644 --- a/Source/Resource/BitmapResource.h +++ b/Source/Resource/Bitmap/BitmapResource.h @@ -1,13 +1,11 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_BITMAPRESOURCE_H -#define RAGNAROK_SOURCE_RESOURCE_BITMAPRESOURCE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_BITMAP_BITMAPRESOURCE_H +#define RAGNAROK_SOURCE_RESOURCE_BITMAP_BITMAPRESOURCE_H -#include "Resource/BitmapImage.h" +#include "Resource/Bitmap/BitmapImage.h" #include "Resource/Resource.h" class IJL15Runtime; -// Exact original file-owner boundary: bytes come from CFile's archive-aware -// read path, not a fallback that silently ignores archive lookup precedence. class ResourceBytes { public: virtual bool Open(const char* name) = 0; @@ -25,7 +23,6 @@ struct BitmapResourceContext { CRenderSystemBase* renderSystem; }; -// RTTI CBitmapRes. Source-only context pointer follows all original fields. class CBitmapRes : public CRes { public: explicit CBitmapRes(BitmapResourceContext& context); diff --git a/Source/Resource/IJL15Runtime.cpp b/Source/Resource/Bitmap/IJL15Runtime.cpp similarity index 80% rename from Source/Resource/IJL15Runtime.cpp rename to Source/Resource/Bitmap/IJL15Runtime.cpp index cfacbf7..76a0151 100644 --- a/Source/Resource/IJL15Runtime.cpp +++ b/Source/Resource/Bitmap/IJL15Runtime.cpp @@ -1,24 +1,23 @@ -#include "Resource/IJL15Runtime.h" +#include "Resource/Bitmap/IJL15Runtime.h" #include -// Host integration helper, not a recovered original constructor. The reference -// imports IJL directly; this loader has no original function address. -// INTERNAL IJL15Runtime::IJL15Runtime() : m_module(LoadLibraryA("ijl15.dll")) { if (!this->m_module) { throw std::system_error(GetLastError(), std::system_category(), "ijl15.dll"); } + this->initialize = reinterpret_castinitialize)>(GetProcAddress(this->m_module, "ijlInit")); this->read = reinterpret_castread)>(GetProcAddress(this->m_module, "ijlRead")); this->write = reinterpret_castwrite)>(GetProcAddress(this->m_module, "ijlWrite")); this->release = reinterpret_castrelease)>(GetProcAddress(this->m_module, "ijlFree")); + if (!this->initialize || !this->read || !this->write || !this->release) { FreeLibrary(this->m_module); throw std::system_error(ERROR_PROC_NOT_FOUND, std::system_category(), "ijl15 exports"); } } -// INTERNAL + IJL15Runtime::~IJL15Runtime() { FreeLibrary(this->m_module); } diff --git a/Source/Resource/IJL15Runtime.h b/Source/Resource/Bitmap/IJL15Runtime.h similarity index 71% rename from Source/Resource/IJL15Runtime.h rename to Source/Resource/Bitmap/IJL15Runtime.h index 15fafec..c0b7406 100644 --- a/Source/Resource/IJL15Runtime.h +++ b/Source/Resource/Bitmap/IJL15Runtime.h @@ -1,12 +1,9 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_IJL15RUNTIME_H -#define RAGNAROK_SOURCE_RESOURCE_IJL15RUNTIME_H +#ifndef RAGNAROK_SOURCE_RESOURCE_BITMAP_IJL15RUNTIME_H +#define RAGNAROK_SOURCE_RESOURCE_BITMAP_IJL15RUNTIME_H #include #include -// Public IJL1.5 core-property ABI. Only the documented core fields used by -// Decoder-private JPEG_PROPERTIES stays opaque. -// Original zeroes0x4E68 bytes before ijlInit. Supplied runtime is x86 only. struct IJL15Properties { int useProperties; unsigned char* dibBytes; @@ -32,8 +29,6 @@ struct IJL15Properties { alignas(8) unsigned char privateProperties[19984]; }; -// Host-side DLL binding, not an original application class. Original IJL calls -// are imports; provenance belongs to their reconstructed application callers. class IJL15Runtime { public: IJL15Runtime(); diff --git a/Source/Resource/EZeffectResource.cpp b/Source/Resource/EZeffectResource.cpp index e0a1ada..367369a 100644 --- a/Source/Resource/EZeffectResource.cpp +++ b/Source/Resource/EZeffectResource.cpp @@ -1,6 +1,6 @@ -#include "Client/ErrorDialog.h" -#include "Render/Texture.h" -#include "Resource/BitmapResource.h" +#include "Client/Application/ErrorDialog.h" +#include "Render/Textures/Texture.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/EZeffectResource.h" #include "Resource/ResourceByteReader.h" @@ -52,6 +52,7 @@ bool CEZeffectRes::Load(const char* name) { const std::string message = std::string("Str::Cannot find File : ") + name; ShowErrorDialog(this->m_context->renderSystem, message.c_str(), 0); this->Unload(); + return false; } @@ -97,8 +98,6 @@ bool CEZeffectRes::Load(const char* name) { // OFFSET: 0x0074D320 // FUNCTION: fn_07891 void CEZeffectRes::Unload() { - // Original closes the retaining CFile without resetting clip slices/counts. - // Callers must not dereference them after unloading. std::vector().swap(this->m_bytes); } diff --git a/Source/Resource/EZeffectResource.h b/Source/Resource/EZeffectResource.h index 7a62a18..2fee0d7 100644 --- a/Source/Resource/EZeffectResource.h +++ b/Source/Resource/EZeffectResource.h @@ -9,8 +9,6 @@ class ResourceBytes; class CTexture; -// Renderer texture owner. Loading keeps its real cache, -// fallback and retain behavior; this resource never fabricates a texture. class EffectTextures { public: virtual CTexture* Load(const char* name, int format, bool option1, bool option2, bool option3) = 0; @@ -39,8 +37,6 @@ struct EZeffectResourceContext { CRenderSystemBase*& renderSystem; }; -// RTTI CEZeffectRes. STR version 148 retains its backing -// allocation; names and 124-byte frame records are borrowed slices, not copies. class CEZeffectRes : public CRes { public: explicit CEZeffectRes(EZeffectResourceContext& context); @@ -56,8 +52,6 @@ public: /* 0120 */ EZeffectClip clips[60]; private: - // Source replacement for the original retained CFile allocation. Required - // snapshot: ResourceBytes exposes borrowed bytes but cannot transfer storage. std::vector m_bytes; EZeffectResourceContext* m_context; }; diff --git a/Source/Resource/MilesRuntime.cpp b/Source/Resource/MilesRuntime.cpp deleted file mode 100644 index c369a65..0000000 --- a/Source/Resource/MilesRuntime.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "Resource/MilesRuntime.h" - -#include - -// Host integration helper, not a recovered original constructor. The reference -// imports Miles Sound System directly; this loader has no original function address. -MilesRuntime& MilesRuntime::Get() { - static MilesRuntime instance; - return instance; -} - -MilesRuntime::MilesRuntime() : m_module(LoadLibraryA("Mss32.dll")) { - if (!this->m_module) { - throw std::system_error(GetLastError(), std::system_category(), "Mss32.dll"); - } - - this->startup = reinterpret_caststartup)>(GetProcAddress(this->m_module, "_AIL_startup@0")); - this->shutdown = reinterpret_castshutdown)>(GetProcAddress(this->m_module, "_AIL_shutdown@0")); - this->setRedistDirectory = - reinterpret_castsetRedistDirectory)>(GetProcAddress(this->m_module, "_AIL_set_redist_directory@4")); - this->setPreference = - reinterpret_castsetPreference)>(GetProcAddress(this->m_module, "_AIL_set_preference@8")); - this->openDigitalDriver = - reinterpret_castopenDigitalDriver)>(GetProcAddress(this->m_module, "_AIL_open_digital_driver@16")); - this->closeDigitalDriver = - reinterpret_castcloseDigitalDriver)>(GetProcAddress(this->m_module, "_AIL_close_digital_driver@4")); - this->allocateSample = - reinterpret_castallocateSample)>(GetProcAddress(this->m_module, "_AIL_allocate_sample_handle@4")); - this->releaseSample = - reinterpret_castreleaseSample)>(GetProcAddress(this->m_module, "_AIL_release_sample_handle@4")); - this->initSample = reinterpret_castinitSample)>(GetProcAddress(this->m_module, "_AIL_init_sample@4")); - this->setSampleFile = - reinterpret_castsetSampleFile)>(GetProcAddress(this->m_module, "_AIL_set_sample_file@12")); - this->sampleStatus = - reinterpret_castsampleStatus)>(GetProcAddress(this->m_module, "_AIL_sample_status@4")); - this->setSampleVolume = - reinterpret_castsetSampleVolume)>(GetProcAddress(this->m_module, "_AIL_set_sample_volume@8")); - this->startSample = - reinterpret_caststartSample)>(GetProcAddress(this->m_module, "_AIL_start_sample@4")); - this->endSample = reinterpret_castendSample)>(GetProcAddress(this->m_module, "_AIL_end_sample@4")); - - this->openStream = - reinterpret_castopenStream)>(GetProcAddress(this->m_module, "_AIL_open_stream@12")); - this->closeStream = - reinterpret_castcloseStream)>(GetProcAddress(this->m_module, "_AIL_close_stream@4")); - this->streamStatus = - reinterpret_caststreamStatus)>(GetProcAddress(this->m_module, "_AIL_stream_status@4")); - this->setStreamLoopCount = reinterpret_castsetStreamLoopCount)>( - GetProcAddress(this->m_module, "_AIL_set_stream_loop_count@8") - ); - this->streamVolume = - reinterpret_caststreamVolume)>(GetProcAddress(this->m_module, "_AIL_stream_volume@4")); - this->setStreamVolume = - reinterpret_castsetStreamVolume)>(GetProcAddress(this->m_module, "_AIL_set_stream_volume@8")); - this->pauseStream = - reinterpret_castpauseStream)>(GetProcAddress(this->m_module, "_AIL_pause_stream@8")); - this->startStream = - reinterpret_caststartStream)>(GetProcAddress(this->m_module, "_AIL_start_stream@4")); - - this->enumerate3DProviders = reinterpret_castenumerate3DProviders)>( - GetProcAddress(this->m_module, "_AIL_enumerate_3D_providers@12") - ); - this->open3DProvider = - reinterpret_castopen3DProvider)>(GetProcAddress(this->m_module, "_AIL_open_3D_provider@4")); - this->close3DProvider = - reinterpret_castclose3DProvider)>(GetProcAddress(this->m_module, "_AIL_close_3D_provider@4")); - this->speakerType = - reinterpret_castspeakerType)>(GetProcAddress(this->m_module, "_AIL_3D_speaker_type@4")); - this->setSpeakerType = - reinterpret_castsetSpeakerType)>(GetProcAddress(this->m_module, "_AIL_set_3D_speaker_type@8")); - this->open3DListener = - reinterpret_castopen3DListener)>(GetProcAddress(this->m_module, "_AIL_open_3D_listener@4")); - this->close3DListener = - reinterpret_castclose3DListener)>(GetProcAddress(this->m_module, "_AIL_close_3D_listener@4")); - this->allocate3DSample = reinterpret_castallocate3DSample)>( - GetProcAddress(this->m_module, "_AIL_allocate_3D_sample_handle@4") - ); - this->release3DSample = reinterpret_castrelease3DSample)>( - GetProcAddress(this->m_module, "_AIL_release_3D_sample_handle@4") - ); - this->set3DSampleFile = - reinterpret_castset3DSampleFile)>(GetProcAddress(this->m_module, "_AIL_set_3D_sample_file@8")); - this->sample3DStatus = - reinterpret_castsample3DStatus)>(GetProcAddress(this->m_module, "_AIL_3D_sample_status@4")); - this->set3DSampleVolume = - reinterpret_castset3DSampleVolume)>(GetProcAddress(this->m_module, "_AIL_set_3D_sample_volume@8")); - this->start3DSample = - reinterpret_caststart3DSample)>(GetProcAddress(this->m_module, "_AIL_start_3D_sample@4")); - this->end3DSample = - reinterpret_castend3DSample)>(GetProcAddress(this->m_module, "_AIL_end_3D_sample@4")); - this->roomType = reinterpret_castroomType)>(GetProcAddress(this->m_module, "_AIL_3D_room_type@4")); - this->setRoomType = - reinterpret_castsetRoomType)>(GetProcAddress(this->m_module, "_AIL_set_3D_room_type@8")); - this->set3DSampleDistances = reinterpret_castset3DSampleDistances)>( - GetProcAddress(this->m_module, "_AIL_set_3D_sample_distances@12") - ); - this->set3DSampleEffectsLevel = reinterpret_castset3DSampleEffectsLevel)>( - GetProcAddress(this->m_module, "_AIL_set_3D_sample_effects_level@8") - ); - this->set3DPosition = - reinterpret_castset3DPosition)>(GetProcAddress(this->m_module, "_AIL_set_3D_position@16")); - this->set3DOrientation = - reinterpret_castset3DOrientation)>(GetProcAddress(this->m_module, "_AIL_set_3D_orientation@28")); - - this->fileType = reinterpret_castfileType)>(GetProcAddress(this->m_module, "_AIL_file_type@8")); - this->wavInfo = reinterpret_castwavInfo)>(GetProcAddress(this->m_module, "_AIL_WAV_info@8")); - this->decompressADPCM = - reinterpret_castdecompressADPCM)>(GetProcAddress(this->m_module, "_AIL_decompress_ADPCM@12")); - this->decompressASI = - reinterpret_castdecompressASI)>(GetProcAddress(this->m_module, "_AIL_decompress_ASI@24")); - this->freeLocked = - reinterpret_castfreeLocked)>(GetProcAddress(this->m_module, "_AIL_mem_free_lock@4")); - - if ( - !this->startup || !this->shutdown || !this->setRedistDirectory || !this->setPreference || - !this->openDigitalDriver || !this->closeDigitalDriver || !this->allocateSample || !this->releaseSample || - !this->initSample || !this->setSampleFile || !this->sampleStatus || !this->setSampleVolume || !this->startSample || - !this->endSample || !this->openStream || !this->closeStream || !this->streamStatus || !this->setStreamLoopCount || - !this->streamVolume || !this->setStreamVolume || !this->pauseStream || !this->startStream || - !this->enumerate3DProviders || !this->open3DProvider || !this->close3DProvider || !this->speakerType || - !this->setSpeakerType || !this->open3DListener || !this->close3DListener || !this->allocate3DSample || - !this->release3DSample || !this->set3DSampleFile || !this->sample3DStatus || !this->set3DSampleVolume || - !this->start3DSample || !this->end3DSample || !this->roomType || !this->setRoomType || - !this->set3DSampleDistances || !this->set3DSampleEffectsLevel || !this->set3DPosition || !this->set3DOrientation || - !this->fileType || !this->wavInfo || !this->decompressADPCM || !this->decompressASI || !this->freeLocked - ) { - FreeLibrary(this->m_module); - throw std::system_error(ERROR_PROC_NOT_FOUND, std::system_category(), "Mss32 exports"); - } -} - -MilesRuntime::~MilesRuntime() { - FreeLibrary(this->m_module); -} diff --git a/Source/Resource/AnimatedModelResource.cpp b/Source/Resource/Models/AnimatedModelResource.cpp similarity index 91% rename from Source/Resource/AnimatedModelResource.cpp rename to Source/Resource/Models/AnimatedModelResource.cpp index 130d2b8..7857b09 100644 --- a/Source/Resource/AnimatedModelResource.cpp +++ b/Source/Resource/Models/AnimatedModelResource.cpp @@ -1,15 +1,14 @@ -#include "Client/ErrorDialog.h" -#include "Render/Texture.h" -#include "Render/TextureCache.h" -#include "Resource/AnimatedModelResource.h" -#include "Resource/BitmapResource.h" +#include "Client/Application/ErrorDialog.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/Models/AnimatedModelResource.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceByteReader.h" #include AnimatedModelNode::AnimatedModelNode(TextureCache& textures) - : model(nullptr), parent(nullptr), unknown_0040(0), vertexCount(0), textureVertexCount(0), faceCount(0), - sharedTextureVertices(0), m_textures(textures) { + : model(nullptr), parent(nullptr), unknown_0040(0), vertexCount(0), textureVertexCount(0), faceCount(0), sharedTextureVertices(0), m_textures(textures) { } AnimatedModelNode::~AnimatedModelNode() { @@ -22,8 +21,8 @@ AnimatedModelNode::~AnimatedModelNode() { // OFFSET: 0x007521F0 // FUNCTION: fn_07956 C3dAnimModelRes::C3dAnimModelRes(ModelResourceContext& context) - : shade(2), frameCount(0), animationLength(0), speed(1.0f), unknown_0150(0), unknown_0154(0.0f), unknown_0158(0.0f), - unknown_015C(0.0f), alpha(255), m_context(&context) { + : shade(2), frameCount(0), animationLength(0), speed(1.0f), unknown_0150(0), unknown_0154(0.0f), unknown_0158(0.0f), unknown_015C(0.0f), alpha(255), + m_context(&context) { } // OFFSET: 0x00753510 @@ -48,7 +47,6 @@ void C3dAnimModelRes::Unload() { } this->nodes.clear(); - // The original retains root-name strings until object destruction. } // OFFSET: 0x00752390 diff --git a/Source/Resource/AnimatedModelResource.h b/Source/Resource/Models/AnimatedModelResource.h similarity index 87% rename from Source/Resource/AnimatedModelResource.h rename to Source/Resource/Models/AnimatedModelResource.h index b87b241..34f4f63 100644 --- a/Source/Resource/AnimatedModelResource.h +++ b/Source/Resource/Models/AnimatedModelResource.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_ANIMATEDMODELRESOURCE_H -#define RAGNAROK_SOURCE_RESOURCE_ANIMATEDMODELRESOURCE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_MODELS_ANIMATEDMODELRESOURCE_H +#define RAGNAROK_SOURCE_RESOURCE_MODELS_ANIMATEDMODELRESOURCE_H -#include "Resource/ModelResource.h" +#include "Resource/Models/ModelResource.h" struct AnimatedModelFace { std::uint32_t values[6]; @@ -9,7 +9,7 @@ struct AnimatedModelFace { struct AnimatedModelFrame { std::vector> vertices; - std::vector> textureVertices; + std::vector textureVertices; }; class C3dAnimModelRes; diff --git a/Source/Resource/ModelMesh.cpp b/Source/Resource/Models/ModelMesh.cpp similarity index 96% rename from Source/Resource/ModelMesh.cpp rename to Source/Resource/Models/ModelMesh.cpp index f4c3c43..2ffc2d0 100644 --- a/Source/Resource/ModelMesh.cpp +++ b/Source/Resource/Models/ModelMesh.cpp @@ -1,4 +1,4 @@ -#include "Resource/ModelMesh.h" +#include "Resource/Models/ModelMesh.h" #include #include @@ -8,6 +8,7 @@ namespace { const float squared = (vector[0] * vector[0] + vector[1] * vector[1]) + vector[2] * vector[2]; const float length = std::sqrt(squared); const float inverse = 1.0f / length; + vector[0] = inverse * vector[0]; vector[1] = inverse * vector[1]; vector[2] = inverse * vector[2]; @@ -37,6 +38,7 @@ void ModelMesh::CalculateNormals() { const float y2 = second[1] - third[1]; const float z2 = second[2] - third[2]; auto& normal = this->faceNormals[index]; + normal[0] = y2 * z1 - z2 * y1; normal[1] = z2 * x1 - x2 * z1; normal[2] = x2 * y1 - y2 * x1; @@ -47,7 +49,6 @@ void ModelMesh::CalculateNormals() { for (unsigned face = 0; face < this->faces.size(); ++face) { for (unsigned corner = 0; corner < 3; ++corner) { - // Repeated vertex indices deliberately add the same adjacent face again. adjacent[this->faces[face].vertices[corner]].push_back(face); } } diff --git a/Source/Resource/ModelMesh.h b/Source/Resource/Models/ModelMesh.h similarity index 67% rename from Source/Resource/ModelMesh.h rename to Source/Resource/Models/ModelMesh.h index c2ed600..4929584 100644 --- a/Source/Resource/ModelMesh.h +++ b/Source/Resource/Models/ModelMesh.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_MODELMESH_H -#define RAGNAROK_SOURCE_RESOURCE_MODELMESH_H +#ifndef RAGNAROK_SOURCE_RESOURCE_MODELS_MODELMESH_H +#define RAGNAROK_SOURCE_RESOURCE_MODELS_MODELMESH_H #include #include @@ -16,11 +16,17 @@ struct ModelFace { std::vector smoothing; }; -// Model mesh owns positions, texture vertices, faces and normal arrays. -// The original 0x1D4-byte owner also holds 32 index vectors used by other paths. +struct ModelTextureVertex { + /* 0000 */ std::uint32_t shaded; + /* 0004 */ float u; + /* 0008 */ float v; +}; + +static_assert(sizeof(ModelTextureVertex) == 12); + struct ModelMesh { std::vector> vertices; - std::vector> textureVertices; + std::vector textureVertices; std::vector faces; std::vector> faceNormals; std::vector> vertexNormals; diff --git a/Source/Resource/ModelNodeLoading.cpp b/Source/Resource/Models/ModelNodeLoading.cpp similarity index 94% rename from Source/Resource/ModelNodeLoading.cpp rename to Source/Resource/Models/ModelNodeLoading.cpp index 7e53df1..daf6d2d 100644 --- a/Source/Resource/ModelNodeLoading.cpp +++ b/Source/Resource/Models/ModelNodeLoading.cpp @@ -1,6 +1,6 @@ -#include "Render/Texture.h" -#include "Render/TextureCache.h" -#include "Resource/ModelResource.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/Models/ModelResource.h" #include "Resource/ResourceByteReader.h" #include @@ -57,7 +57,7 @@ void C3dModelResV1::ReadNode(ResourceByteReader& input, unsigned minor, const st mesh.textureVertices.resize(static_cast(textureVertexCount)); if (minor == 1) { - std::uint32_t uv[2]; + float uv[2]; for (auto& vertex : mesh.textureVertices) { input.Read(uv, sizeof(uv)); @@ -87,9 +87,7 @@ void C3dModelResV1::ReadNode(ResourceByteReader& input, unsigned minor, const st face.smoothing.push_back(group); } - std::sort(mesh.faces.begin(), mesh.faces.end(), [](const ModelFace& a, const ModelFace& b) { - return a.texture < b.texture; - }); + std::sort(mesh.faces.begin(), mesh.faces.end(), [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; }); mesh.CalculateNormals(); int rotationCount; input.Read(&rotationCount, 4); diff --git a/Source/Resource/ModelNodeLoadingV2.cpp b/Source/Resource/Models/ModelNodeLoadingV2.cpp similarity index 90% rename from Source/Resource/ModelNodeLoadingV2.cpp rename to Source/Resource/Models/ModelNodeLoadingV2.cpp index 1ad7303..75e28fb 100644 --- a/Source/Resource/ModelNodeLoadingV2.cpp +++ b/Source/Resource/Models/ModelNodeLoadingV2.cpp @@ -1,6 +1,6 @@ -#include "Render/Texture.h" -#include "Render/TextureCache.h" -#include "Resource/ModelResource.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/Models/ModelResource.h" #include "Resource/ResourceByteReader.h" #include @@ -12,6 +12,7 @@ namespace { input.Read(&bytes, 4); char name[40]{}; input.Read(name, bytes); + return name; } @@ -32,7 +33,6 @@ namespace { } } -// Node-decoding loops within modern version readers, not a separate machine entry. void C3dModelResV2::ReadNode(ResourceByteReader& input, unsigned minor, const std::vector& textureNames) { auto node = std::make_unique(this->m_context->textures); node->model = this; @@ -102,9 +102,7 @@ void C3dModelResV2::ReadNode(ResourceByteReader& input, unsigned minor, const st std::memcpy(face.smoothing.data(), record + 20, groups * 4u); } - std::sort(mesh.faces.begin(), mesh.faces.end(), [](const ModelFace& a, const ModelFace& b) { - return a.texture < b.texture; - }); + std::sort(mesh.faces.begin(), mesh.faces.end(), [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; }); mesh.CalculateNormals(); ReadKeys(input, node->scaleKeys, false); ReadKeys(input, node->rotationKeys, true); @@ -117,7 +115,7 @@ void C3dModelResV2::ReadNode(ResourceByteReader& input, unsigned minor, const st for (int index = 0; index < textureAnimations; ++index) { int texture = 0; input.Read(&texture, 4); - std::map>> channels; + ModelTextureChannels channels; int channelCount = 0; input.Read(&channelCount, 4); @@ -128,8 +126,8 @@ void C3dModelResV2::ReadNode(ResourceByteReader& input, unsigned minor, const st input.Read(&keyCount, 4); for (int key = 0; key < keyCount; ++key) { - std::array value; - input.Read(value.data(), 8); + ModelTextureKey value; + input.Read(&value, sizeof(value)); channels[id].push_back(value); } } diff --git a/Source/Resource/ModelResource.cpp b/Source/Resource/Models/ModelResource.cpp similarity index 85% rename from Source/Resource/ModelResource.cpp rename to Source/Resource/Models/ModelResource.cpp index 3cf265c..c54161e 100644 --- a/Source/Resource/ModelResource.cpp +++ b/Source/Resource/Models/ModelResource.cpp @@ -1,8 +1,8 @@ -#include "Client/ErrorDialog.h" -#include "Render/Texture.h" -#include "Render/TextureCache.h" -#include "Resource/BitmapResource.h" -#include "Resource/ModelResource.h" +#include "Client/Application/ErrorDialog.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" +#include "Resource/Bitmap/BitmapResource.h" +#include "Resource/Models/ModelResource.h" #include "Resource/ResourceByteReader.h" #include @@ -95,11 +95,11 @@ bool C3dModelResV1::Load(const char* name) { input.Read(magic, 4); if (std::strcmp(magic, "GRSM") != 0) { - constexpr char message[] = - "\xB8\xF0\xB5\xA8\xC6\xC4\xC0\xCF\xC0\xCC \xBE\xC6\xB4\xD5\xB4\xCF\xB4\xD9. \xC7\xFC\xBD\xC4\xC0\xBB " - "\xB4\xD9\xBD\xC3\xC7\xD1\xB9\xF8 \xC8\xAE\xC0\xCE\xC7\xD8\xC1\xD6\xBC\xBC\xBF\xE4."; + constexpr char message[] = "\xB8\xF0\xB5\xA8\xC6\xC4\xC0\xCF\xC0\xCC \xBE\xC6\xB4\xD5\xB4\xCF\xB4\xD9. \xC7\xFC\xBD\xC4\xC0\xBB " + "\xB4\xD9\xBD\xC3\xC7\xD1\xB9\xF8 \xC8\xAE\xC0\xCE\xC7\xD8\xC1\xD6\xBC\xBC\xBF\xE4."; ShowErrorDialog(this->m_context->renderSystem, message, 0); file.Close(); + return false; } @@ -110,11 +110,11 @@ bool C3dModelResV1::Load(const char* name) { input.Read(&minor, 1); if (major != 1 || minor > 5) { - constexpr char message[] = - "\xC1\xF6\xBF\xF8\xB5\xC7\xC1\xF6 \xBE\xCA\xB4\xC2 \xB9\xF6\xC1\xAF\xC0\xD4\xB4\xCF\xB4\xD9. " - "\xB3\xBB\xBF\xEB\xB9\xB0\xC0\xCC \xB1\xFA\xC1\xAE\xC0\xD6\xC0\xBB \xBC\xF6 \xC0\xD6\xBD\xC0\xB4\xCF\xB4\xD9"; + constexpr char message[] = "\xC1\xF6\xBF\xF8\xB5\xC7\xC1\xF6 \xBE\xCA\xB4\xC2 \xB9\xF6\xC1\xAF\xC0\xD4\xB4\xCF\xB4\xD9. " + "\xB3\xBB\xBF\xEB\xB9\xB0\xC0\xCC \xB1\xFA\xC1\xAE\xC0\xD6\xC0\xBB \xBC\xF6 \xC0\xD6\xBD\xC0\xB4\xCF\xB4\xD9"; ShowErrorDialog(this->m_context->renderSystem, message, 0); file.Close(); + return false; } @@ -188,5 +188,6 @@ bool C3dModelResV1::Load(const char* name) { this->sourceName = name; file.Close(); file.Close(); + return true; } diff --git a/Source/Resource/ModelResource.h b/Source/Resource/Models/ModelResource.h similarity index 85% rename from Source/Resource/ModelResource.h rename to Source/Resource/Models/ModelResource.h index d8002d2..3529029 100644 --- a/Source/Resource/ModelResource.h +++ b/Source/Resource/Models/ModelResource.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_MODELRESOURCE_H -#define RAGNAROK_SOURCE_RESOURCE_MODELRESOURCE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_MODELS_MODELRESOURCE_H +#define RAGNAROK_SOURCE_RESOURCE_MODELS_MODELRESOURCE_H -#include "Resource/ModelMesh.h" +#include "Resource/Models/ModelMesh.h" #include "Resource/Resource.h" #include @@ -30,6 +30,15 @@ struct ModelRotationKey { float rotation[4]; }; +struct ModelTextureKey { + /* 0000 */ int frame; + /* 0004 */ float value; +}; + +using ModelTextureChannels = std::map>; + +static_assert(sizeof(ModelTextureKey) == 8); + struct ModelVolume { float size[3]; float position[3]; @@ -39,8 +48,6 @@ struct ModelVolume { int flag; }; -// Shared node ownership recovered from C3dNodeRes, V1 and V2. Version-specific -// transforms/key arrays remain distinct; texture pointers are retained here. class ModelNode { public: explicit ModelNode(TextureCache& textures); @@ -66,7 +73,7 @@ public: std::vector rotationKeys; std::vector scaleKeys; std::vector positionKeys; - std::map>>> textureKeys; + std::map textureKeys; private: TextureCache& m_textures; @@ -78,8 +85,6 @@ struct ModelResourceContext { CRenderSystemBase*& renderSystem; }; -// RTTI C3dModelRes. Unload deletes nodes/volumes; -// the original destructor only destroys their pointer containers. class C3dModelRes : public CRes { public: explicit C3dModelRes(ModelResourceContext& context); diff --git a/Source/Resource/ModelResourceV2.cpp b/Source/Resource/Models/ModelResourceV2.cpp similarity index 84% rename from Source/Resource/ModelResourceV2.cpp rename to Source/Resource/Models/ModelResourceV2.cpp index e6665d2..ecc4eca 100644 --- a/Source/Resource/ModelResourceV2.cpp +++ b/Source/Resource/Models/ModelResourceV2.cpp @@ -1,14 +1,13 @@ -#include "Client/ErrorDialog.h" -#include "Resource/BitmapResource.h" -#include "Resource/ModelResource.h" +#include "Client/Application/ErrorDialog.h" +#include "Resource/Bitmap/BitmapResource.h" +#include "Resource/Models/ModelResource.h" #include "Resource/ResourceByteReader.h" #include // OFFSET: 0x00751ED0 // FUNCTION: fn_07953 -C3dModelResV2::C3dModelResV2(ModelResourceContext& context) - : C3dModelRes(context), framesPerSecond(0.0f), animationLength(0) { +C3dModelResV2::C3dModelResV2(ModelResourceContext& context) : C3dModelRes(context), framesPerSecond(0.0f), animationLength(0) { } // OFFSET: 0x00752190 @@ -36,11 +35,11 @@ bool C3dModelResV2::Load(const char* name) { input.Read(magic, 4); if (std::strcmp(magic, "GRSM") != 0) { - constexpr char message[] = - "\xB8\xF0\xB5\xA8\xC6\xC4\xC0\xCF\xC0\xCC \xBE\xC6\xB4\xD5\xB4\xCF\xB4\xD9. \xC7\xFC\xBD\xC4\xC0\xBB " - "\xB4\xD9\xBD\xC3\xC7\xD1\xB9\xF8 \xC8\xAE\xC0\xCE\xC7\xD8\xC1\xD6\xBC\xBC\xBF\xE4."; + constexpr char message[] = "\xB8\xF0\xB5\xA8\xC6\xC4\xC0\xCF\xC0\xCC \xBE\xC6\xB4\xD5\xB4\xCF\xB4\xD9. \xC7\xFC\xBD\xC4\xC0\xBB " + "\xB4\xD9\xBD\xC3\xC7\xD1\xB9\xF8 \xC8\xAE\xC0\xCE\xC7\xD8\xC1\xD6\xBC\xBC\xBF\xE4."; ShowErrorDialog(this->m_context->renderSystem, message, 0); file.Close(); + return false; } @@ -50,7 +49,6 @@ bool C3dModelResV2::Load(const char* name) { this->major = major; input.Read(&minor, 1); - // The original dispatches solely on minor and succeeds for unknown cases. if (minor >= 1 && minor <= 3) { this->ReadVersion(input, minor); } @@ -58,6 +56,7 @@ bool C3dModelResV2::Load(const char* name) { file.Close(); this->sourceName = name; file.Close(); + return true; } diff --git a/Source/Resource/Resource.cpp b/Source/Resource/Resource.cpp index 2e5cec7..4a41b10 100644 --- a/Source/Resource/Resource.cpp +++ b/Source/Resource/Resource.cpp @@ -1,17 +1,16 @@ -#include "Client/ErrorDialog.h" +#include "Client/Application/ErrorDialog.h" #include "Resource/Resource.h" #include #include -// clang-format off -#include -// clang-format on +#include // OFFSET: 0x00AECDE0 // FUNCTION: fn_18144 ResourceName::ResourceName(const char* name) { this->Assign(name); } + void ResourceName::Assign(const char* name) { myGPack::AssignNameKey(this->hash, this->text, name); } @@ -20,26 +19,32 @@ void ResourceName::Assign(const char* name) { // FUNCTION: fn_18165 CRes::CRes() : references(0) { } + // OFFSET: 0x007498B0 CRes::~CRes() = default; + // OFFSET: 0x00745260 // FUNCTION: fn_07756 bool CRes::Slot01(int, int, int) { return false; } + // OFFSET: 0x00745270 // FUNCTION: fn_07757 void CRes::Slot02() { } + // OFFSET: 0x00745280 // FUNCTION: fn_07758 bool CRes::IsTransient() { return false; } + // OFFSET: 0x00747540 // FUNCTION: fn_07789 void CRes::Unload() { } + // OFFSET: 0x00AEFCF0 // FUNCTION: fn_18185 void CRes::MissingFile(CRenderSystemBase* system, const char* name) { @@ -52,6 +57,7 @@ void CRes::MissingFile(CRenderSystemBase* system, const char* name) { std::uint32_t CRes::AddRef() { return ++this->references; } + // OFFSET: 0x00AF0BE0 // FUNCTION: fn_18194 void CRes::Release() { diff --git a/Source/Resource/Resource.h b/Source/Resource/Resource.h index 056035e..a44f6dd 100644 --- a/Source/Resource/Resource.h +++ b/Source/Resource/Resource.h @@ -7,8 +7,6 @@ class CRenderSystemBase; -// The resource owner's available name region is256 bytes total, unlike the -// archive entry's260-byte reservation. Same unbounded assignment algorithm. struct ResourceName { std::uint32_t hash; char text[252]; @@ -17,8 +15,6 @@ struct ResourceName { }; static_assert(sizeof(ResourceName) == 256); -// Resource factory/load -// are abstract; original unload remains a real empty base implementation. class CRes { public: CRes(); diff --git a/Source/Resource/ResourceAliases.cpp b/Source/Resource/ResourceAliases.cpp index e4c8ae1..92a2cb4 100644 --- a/Source/Resource/ResourceAliases.cpp +++ b/Source/Resource/ResourceAliases.cpp @@ -10,15 +10,16 @@ const char* ResourceAliases::Resolve(const char* name) const { if (entry != this->names.end()) { return entry->second.c_str(); } + const std::size_t marker = key.rfind('@'); if (marker != std::string::npos && marker >= 4) { - // Original removes three bytes starting FOUR bytes before the final '@'. key.erase(marker - 4, 3); entry = this->names.find(key); if (entry != this->names.end()) { return entry->second.c_str(); } } + return name; } @@ -28,5 +29,6 @@ std::string AddResourcePrefix(const char* name, const char* prefix) { if (std::strncmp(name, prefix, std::strlen(prefix)) == 0) { return name; } + return std::string(prefix) + name; } diff --git a/Source/Resource/ResourceAliases.h b/Source/Resource/ResourceAliases.h index fc774c5..cecc7c4 100644 --- a/Source/Resource/ResourceAliases.h +++ b/Source/Resource/ResourceAliases.h @@ -4,8 +4,6 @@ #include #include -// Resource manager's map at+68. Returned mapped string pointers remain borrowed -// from this map; misses retain the original input pointer, not a copied path. struct ResourceAliases { std::map names; diff --git a/Source/Resource/ResourceByteReader.h b/Source/Resource/ResourceByteReader.h index ac6b5d8..de9e4ad 100644 --- a/Source/Resource/ResourceByteReader.h +++ b/Source/Resource/ResourceByteReader.h @@ -3,9 +3,6 @@ #include -// Original CFile memory-backed Read contract over an explicit resource owner. -// Failed reads leave output and cursor unchanged; loaders retain original -// unchecked-read policy rather than inventing format validation. struct ResourceByteReader { const unsigned char* data; unsigned size; diff --git a/Source/Resource/ResourceFailures.cpp b/Source/Resource/ResourceFailures.cpp index 66e1311..6b53357 100644 --- a/Source/Resource/ResourceFailures.cpp +++ b/Source/Resource/ResourceFailures.cpp @@ -1,11 +1,12 @@ #include "Resource/ResourceFailures.h" -#include "Utility/NSyncObject.h" +#include "Utility/Threading/NSyncObject.h" #include ResourceFailures::ResourceFailures(ResourceMessages& messages) : m_messages(&messages) { InitializeCriticalSection(&this->m_lock); } + ResourceFailures::~ResourceFailures() { DeleteCriticalSection(&this->m_lock); } @@ -17,6 +18,7 @@ void ResourceFailures::Report(std::string requested, std::string resolved) { if (extension && _stricmp(extension, ".ebm") == 0) { return; } + bool report; { NSyncObject lock(&this->m_lock); diff --git a/Source/Resource/ResourceFailures.h b/Source/Resource/ResourceFailures.h index 721234e..fc7978a 100644 --- a/Source/Resource/ResourceFailures.h +++ b/Source/Resource/ResourceFailures.h @@ -13,8 +13,6 @@ protected: ~ResourceMessages() = default; }; -// Original failure owner's critical section+4 and set+28. Actual manager -// message routing is explicit; missing-resource diagnostics are not discarded. class ResourceFailures { public: explicit ResourceFailures(ResourceMessages& messages); diff --git a/Source/Resource/ResourceMgr.cpp b/Source/Resource/ResourceMgr.cpp index 5e3d0b7..fbceb47 100644 --- a/Source/Resource/ResourceMgr.cpp +++ b/Source/Resource/ResourceMgr.cpp @@ -1,12 +1,13 @@ #include "File/ResourcePath.h" #include "Resource/ResourceFailures.h" #include "Resource/ResourceMgr.h" -#include "Utility/NSyncObject.h" +#include "Utility/Threading/NSyncObject.h" #include #include #include -#include +#include +#include #include // OFFSET: 0x00AECEE0 @@ -15,6 +16,7 @@ bool ResourceNameLess::operator()(const ResourceName* left, const ResourceName* if (left->hash != right->hash) { return left->hash < right->hash; } + return std::strcmp(left->text, right->text) < 0; } @@ -23,17 +25,21 @@ bool ResourceNameLess::operator()(const ResourceName* left, const ResourceName* ResourceMgr::ResourceMgr(ResourceFailures& failures) : m_failures(&failures) { InitializeCriticalSection(&this->m_lock); } + // OFFSET: 0x00AEE070 // FUNCTION: fn_18169 ResourceMgr::~ResourceMgr() { this->m_transient.clear(); + for (auto& resources : this->m_resources) { for (auto& [name, resource] : resources) { resource->Unload(); delete resource; } + resources.clear(); } + DeleteCriticalSection(&this->m_lock); } @@ -53,10 +59,12 @@ int ResourceMgr::FindType(const char* extension) const { if (!extension) { return -1; } + const auto entry = this->m_extensions.find(extension); if (entry != this->m_extensions.end()) { return entry->second; } + char text[256]; std::sprintf(text, "ResourceError : %s is Undefined Ext \n", extension); return -1; @@ -69,6 +77,7 @@ CRes* ResourceMgr::Find(int type, const char* name) const { key.Assign(name); const auto& resources = this->m_resources[type]; const auto entry = resources.find(&key); + return entry == resources.end() ? nullptr : entry->second; } @@ -78,23 +87,28 @@ bool ResourceMgr::Exists(const char* name) { if (!name) { return false; } + char normalized[260] = {}; strncpy_s(normalized, sizeof(normalized), name, _TRUNCATE); + for (unsigned char* byte = reinterpret_cast(normalized); *byte; ++byte) { if (*byte >= 'A' && *byte <= 'Z') { *byte += 'a' - 'A'; } } + const char* dot = std::strrchr(normalized, '.'); const int type = this->FindType(dot ? dot + 1 : nullptr); if (type < 0) { return false; } + const std::string resolved = AddResourcePrefix(this->aliases.Resolve(normalized), this->m_prefixes[type]); if (CRes* existing = this->Find(type, resolved.c_str())) { existing->lastUse = timeGetTime(); return true; } + return ResourceExists(resolved.c_str(), 0); } @@ -103,45 +117,54 @@ CRes* ResourceMgr::Load(const char* name) { if (!name) { return nullptr; } + std::optional lock(std::in_place, &this->m_lock); char normalized[260] = {}; _snprintf_s(normalized, sizeof(normalized), _TRUNCATE, "%s", name); - // Exact original byte_134B750 table folds ASCII only, not locale/codepage. + for (unsigned char* byte = reinterpret_cast(normalized); *byte; ++byte) { if (*byte >= 'A' && *byte <= 'Z') { *byte += 'a' - 'A'; } } + const char* dot = std::strrchr(normalized, '.'); const int type = this->FindType(dot ? dot + 1 : nullptr); if (type < 0) { return nullptr; } + std::string resolved = AddResourcePrefix(this->aliases.Resolve(normalized), this->m_prefixes[type]); if (CRes* existing = this->Find(type, resolved.c_str())) { existing->lastUse = timeGetTime(); return existing; } + CRes* resource = this->m_prototypes[type]->Create(); if (!resource) { return nullptr; } + if (resource->Load(resolved.c_str()) != 1) { delete resource; - // Original reports only after releasing the resource lock. + lock.reset(); if (resolved.find("\\map\\") == std::string::npos) { this->m_failures->Report(name, resolved); } + return nullptr; } + resource->name.Assign(resolved.c_str()); resource->type = type; resource->lastUse = timeGetTime(); this->m_resources[type].emplace(&resource->name, resource); + if (resource->IsTransient() == 1) { this->m_transient.push_back(resource); } + return resource; } @@ -170,23 +193,28 @@ void ResourceMgr::ClearUnused(const char* extension) { if (type < 0) { return; } + auto& resources = this->m_resources[type]; + for (auto entry = resources.begin(); entry != resources.end();) { CRes* resource = entry->second; if (resource->references != 0) { ++entry; continue; } + this->EraseTransient(resource); resource->Unload(); delete resource; entry = resources.erase(entry); } } + // OFFSET: 0x00AF0AE0 // FUNCTION: fn_18193 void ResourceMgr::ClearUnused() { timeGetTime(); + for (auto& resources : this->m_resources) { for (auto entry = resources.begin(); entry != resources.end();) { CRes* resource = entry->second; @@ -194,6 +222,7 @@ void ResourceMgr::ClearUnused() { ++entry; continue; } + this->EraseTransient(resource); resource->Unload(); delete resource; diff --git a/Source/Resource/ResourceMgr.h b/Source/Resource/ResourceMgr.h index 8642172..e057186 100644 --- a/Source/Resource/ResourceMgr.h +++ b/Source/Resource/ResourceMgr.h @@ -14,8 +14,6 @@ struct ResourceNameLess { bool operator()(const ResourceName* left, const ResourceName* right) const; }; -// Real resource-manager containers, registration and synchronized load. Names -// are reconstructed; the singleton/static descriptor registration is separate. class ResourceMgr { public: explicit ResourceMgr(ResourceFailures& failures); diff --git a/Source/Resource/ResourceTransient.cpp b/Source/Resource/ResourceTransient.cpp index e7043bf..c5f52b4 100644 --- a/Source/Resource/ResourceTransient.cpp +++ b/Source/Resource/ResourceTransient.cpp @@ -4,6 +4,7 @@ // FUNCTION: fn_18186 void ResourceMgr::UpdateTransient() { const auto end = this->m_transient.end(); + for (auto it = this->m_transient.begin(); it != end; ++it) { (*it)->Slot02(); } diff --git a/Source/Resource/ActionResource.cpp b/Source/Resource/Sprites/ActionResource.cpp similarity index 88% rename from Source/Resource/ActionResource.cpp rename to Source/Resource/Sprites/ActionResource.cpp index 011c207..42e8dfe 100644 --- a/Source/Resource/ActionResource.cpp +++ b/Source/Resource/Sprites/ActionResource.cpp @@ -1,28 +1,24 @@ -#include "Client/ErrorDialog.h" -#include "Resource/ActionResource.h" -#include "Resource/BitmapResource.h" +#include "Client/Application/ErrorDialog.h" +#include "Resource/Sprites/ActionResource.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceByteReader.h" #include "Resource/ResourceMgr.h" -#include "Resource/SpriteResource.h" +#include "Resource/Sprites/SpriteResource.h" +#include "Utility/Math/ScalarConversion.h" #include -#include #include -#include namespace { - // Original uses scalar SSE conversion: truncation toward zero, with INT_MIN - // for NaN/infinity/out-of-range, not C++ undefined float-to-int conversion. int RelativeCoordinate(int position, int extent, float scale) { const int center = extent / 2 + extent % 2; - const __m128 divisor = _mm_set_ss(scale); - const __m128 offset = _mm_mul_ss(_mm_cvtsi32_ss(_mm_setzero_ps(), center), divisor); - const __m128 coordinate = _mm_sub_ss(_mm_cvtsi32_ss(_mm_setzero_ps(), position), offset); - return _mm_cvttss_si32(_mm_div_ss(coordinate, divisor)); + const float offset = static_cast(center) * scale; + const float coordinate = static_cast(position) - offset; + + return TruncateToInt(coordinate / scale); } } -// Initialization inlined in the original Create operation. // OFFSET: 0x007436B0 // FUNCTION: fn_07749 CActRes::CActRes(ActionResourceContext& context) : maximumCells(0), m_context(&context) { @@ -43,6 +39,7 @@ bool CActRes::Load(const char* name) { auto& file = context.file; struct CloseFile { ResourceBytes& file; + ~CloseFile() { file.Close(); } @@ -67,6 +64,7 @@ bool CActRes::Load(const char* name) { ShowErrorDialog(context.renderSystem, "Illegal File Format", 0); ShowErrorDialog(context.renderSystem, name, 0); file.Close(); + return false; } @@ -125,8 +123,7 @@ bool CActRes::Load(const char* name) { std::int32_t imageType; } legacy; input.Read(&legacy, sizeof(legacy)); - cell = {legacy.x, legacy.y, legacy.image, legacy.mirrored, legacy.color, - legacy.scale, legacy.scale, legacy.rotation, legacy.imageType}; + cell = {legacy.x, legacy.y, legacy.image, legacy.mirrored, legacy.color, legacy.scale, legacy.scale, legacy.rotation, legacy.imageType}; } else { input.Read(&cell, sizeof(cell)); } diff --git a/Source/Resource/ActionResource.h b/Source/Resource/Sprites/ActionResource.h similarity index 75% rename from Source/Resource/ActionResource.h rename to Source/Resource/Sprites/ActionResource.h index 46a8254..0f2f5de 100644 --- a/Source/Resource/ActionResource.h +++ b/Source/Resource/Sprites/ActionResource.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_ACTIONRESOURCE_H -#define RAGNAROK_SOURCE_RESOURCE_ACTIONRESOURCE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_SPRITES_ACTIONRESOURCE_H +#define RAGNAROK_SOURCE_RESOURCE_SPRITES_ACTIONRESOURCE_H -#include "Render/SpritePixels.h" +#include "Render/Textures/SpritePixels.h" #include "Resource/Resource.h" #include @@ -28,15 +28,12 @@ struct ActionFrame { }; struct ActionResourceContext { - // Must retain this load's bytes across recursive ResourceMgr::Load calls; - // use a distinct file owner from the sprite prototype, as original CFile does. + ResourceBytes& file; ResourceMgr& resources; CRenderSystemBase*& renderSystem; }; -// RTTI CActRes, original size 312. Frame/sound vectors -// are released by Unload; animation speeds survive until destruction/reload. class CActRes : public CRes { public: explicit CActRes(ActionResourceContext& context); diff --git a/Source/Resource/SpriteEncoding.cpp b/Source/Resource/Sprites/SpriteEncoding.cpp similarity index 90% rename from Source/Resource/SpriteEncoding.cpp rename to Source/Resource/Sprites/SpriteEncoding.cpp index 43ffea4..b19ee1f 100644 --- a/Source/Resource/SpriteEncoding.cpp +++ b/Source/Resource/Sprites/SpriteEncoding.cpp @@ -1,4 +1,4 @@ -#include "Resource/SpriteResource.h" +#include "Resource/Sprites/SpriteResource.h" #include #include @@ -77,8 +77,6 @@ void ConvertSpritePalette(std::uint32_t* output, const std::uint8_t* input, int const unsigned red = input[index * 4]; const unsigned green = input[index * 4 + 1]; const unsigned blue = input[index * 4 + 2]; - output[index] = red >= 254 && green < 4 && blue >= 254 - ? 1057u - : ((blue | 0x40000u) >> 3) | (4 * ((green & 0xF8u) | (32 * (red & 0xF8u)))); + output[index] = red >= 254 && green < 4 && blue >= 254 ? 1057u : ((blue | 0x40000u) >> 3) | (4 * ((green & 0xF8u) | (32 * (red & 0xF8u)))); } } diff --git a/Source/Resource/SpriteResource.cpp b/Source/Resource/Sprites/SpriteResource.cpp similarity index 88% rename from Source/Resource/SpriteResource.cpp rename to Source/Resource/Sprites/SpriteResource.cpp index be8fcc5..d92ed7a 100644 --- a/Source/Resource/SpriteResource.cpp +++ b/Source/Resource/Sprites/SpriteResource.cpp @@ -1,16 +1,15 @@ -#include "Client/ErrorDialog.h" +#include "Client/Application/ErrorDialog.h" #include "Render/RenderSystemBase.h" -#include "Render/Texture.h" -#include "Resource/BitmapResource.h" +#include "Render/Textures/Texture.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceByteReader.h" -#include "Resource/SpriteResource.h" +#include "Resource/Sprites/SpriteResource.h" #include #include #include #include -// Initialization inlined in the original Create operation. // OFFSET: 0x0075FE90 // FUNCTION: fn_08053 CSprRes::CSprRes(SpriteResourceContext& context) : indexedCount(0), m_context(&context) { @@ -31,6 +30,7 @@ bool CSprRes::Load(const char* name) { auto& file = context.file; struct CloseFile { ResourceBytes& file; + ~CloseFile() { file.Close(); } @@ -135,9 +135,7 @@ bool CSprRes::Load(const char* name) { auto* reduced = ReduceSprite(pixels, dimensions[0], dimensions[1], context.halfWidth, context.halfHeight); std::free(pixels); - image->runs = EncodeSpriteRuns( - reduced, dimensions[0] / (context.halfWidth + 1), dimensions[1] / (context.halfHeight + 1), encodedBytes - ); + image->runs = EncodeSpriteRuns(reduced, dimensions[0] / (context.halfWidth + 1), dimensions[1] / (context.halfHeight + 1), encodedBytes); std::free(reduced); if (context.halfWidth != 0) { @@ -161,23 +159,19 @@ bool CSprRes::Load(const char* name) { auto* image = new SpriteRleImage{}; image->width = static_cast(dimensions[0]); image->height = static_cast(dimensions[1]); - auto* pixels = static_cast( - ::operator new(static_cast(image->width * image->height) * sizeof(std::uint32_t)) - ); + auto* pixels = static_cast(::operator new(static_cast(image->width * image->height) * sizeof(std::uint32_t))); for (int y = image->height - 1; y >= 0; --y) { for (int x = 0; x < image->width; ++x) { std::uint8_t pixel[4]; input.Read(pixel, sizeof(pixel)); - pixels[y * image->width + x] = - pixel[1] | (pixel[2] << 8) | (pixel[3] << 16) | (static_cast(pixel[0]) << 24); + pixels[y * image->width + x] = pixel[1] | (pixel[2] << 8) | (pixel[3] << 16) | (static_cast(pixel[0]) << 24); } } const int width = context.halfWidth != 0 ? image->width / 2 : image->width; const int height = context.halfHeight != 0 ? image->height / 2 : image->height; - CTexture* texture = - context.renderSystem ? context.renderSystem->CreateTexture(width, height, 1, false, false) : nullptr; + CTexture* texture = context.renderSystem ? context.renderSystem->CreateTexture(width, height, TextureFormat::A4R4G4B4, false, false) : nullptr; image->unknown_0008 = texture; texture->Upload(0, 0, image->width, image->height, pixels, 0, 0); std::free(pixels); diff --git a/Source/Resource/SpriteResource.h b/Source/Resource/Sprites/SpriteResource.h similarity index 73% rename from Source/Resource/SpriteResource.h rename to Source/Resource/Sprites/SpriteResource.h index c32b1ab..dbd53d0 100644 --- a/Source/Resource/SpriteResource.h +++ b/Source/Resource/Sprites/SpriteResource.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_SPRITERESOURCE_H -#define RAGNAROK_SOURCE_RESOURCE_SPRITERESOURCE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_SPRITES_SPRITERESOURCE_H +#define RAGNAROK_SOURCE_RESOURCE_SPRITES_SPRITERESOURCE_H -#include "Render/SpritePixels.h" +#include "Render/Textures/SpritePixels.h" #include "Resource/Resource.h" #include @@ -15,8 +15,6 @@ struct SpriteResourceContext { const int& halfHeight; }; -// RTTI CSprRes, size 1324. Unload owns the -// individual images/textures; the original destructor only destroys vectors. class CSprRes : public CRes { public: explicit CSprRes(SpriteResourceContext& context); @@ -33,8 +31,6 @@ private: SpriteResourceContext* m_context; }; -// Original helpers retain their malloc-compatible allocation domain and -// 16-bit encoded length/source-index behavior. std::uint8_t* EncodeSpriteRuns(const std::uint8_t* pixels, int width, int height, std::uint16_t& bytes); std::uint8_t* ReduceSprite(const std::uint8_t* pixels, int width, int height, int halfWidth, int halfHeight); void ConvertSpritePalette(std::uint32_t* output, const std::uint8_t* input, int count); diff --git a/Source/Resource/TextureNames.cpp b/Source/Resource/TextureNames.cpp index 285dfe0..22622b2 100644 --- a/Source/Resource/TextureNames.cpp +++ b/Source/Resource/TextureNames.cpp @@ -17,8 +17,8 @@ const char* TextureNames::ServiceName(const char* name) { static char path[260]; std::strcpy(path, this->servicePrefix.c_str()); std::strcat(path, name); - const bool exists = - std::strstr(name, ".txt") || std::strstr(name, ".xml") ? ResourceExists(path, 0) : this->resources.Exists(path); + const bool exists = std::strstr(name, ".txt") || std::strstr(name, ".xml") ? ResourceExists(path, 0) : this->resources.Exists(path); + return exists ? path : name; } @@ -36,17 +36,17 @@ const char* TextureNames::Resolve(const char* name) { return name; } - // Original detects a fourteen-byte marker anywhere but removes fifteen bytes - // from the beginning, rather than removing relative to the found marker. if (this->activeMode && this->skin.Selected()) { const std::string prefix(this->skin.Prefix()); // STATIC: 0x016D58CC // GLOBAL: gl_24385 static std::string selectedPath; selectedPath = prefix; + if (original.size() > 15) { selectedPath.append(original.data() + 15, original.size() - 15); } + this->skin.Prepare(); if (this->resources.Exists(selectedPath.c_str())) { diff --git a/Source/Resource/GroundResource.cpp b/Source/Resource/World/GroundResource.cpp similarity index 83% rename from Source/Resource/GroundResource.cpp rename to Source/Resource/World/GroundResource.cpp index 0364c6b..3bd0ff6 100644 --- a/Source/Resource/GroundResource.cpp +++ b/Source/Resource/World/GroundResource.cpp @@ -1,5 +1,5 @@ -#include "Resource/BitmapResource.h" -#include "Resource/GroundResource.h" +#include "Resource/Bitmap/BitmapResource.h" +#include "Resource/World/GroundResource.h" #include "Resource/ResourceByteReader.h" #include @@ -15,8 +15,7 @@ namespace { // OFFSET: 0x0074E1C0 // FUNCTION: fn_07906 -CGndRes::CGndRes(GroundResourceContext& context) - : loaded(0), width(0), height(0), cellSize(10.0f), m_context(&context) { +CGndRes::CGndRes(GroundResourceContext& context) : loaded(0), width(0), height(0), cellSize(10.0f), m_context(&context) { } // OFFSET: 0x0074E390 @@ -98,11 +97,10 @@ bool CGndRes::Parse(ResourceByteReader& input) { // FUNCTION: fn_07912 void CGndRes::ReadWater(ResourceByteReader& input) { GroundWater record; - input.Read(record.values, sizeof(record.values)); + input.Read(&record.parameters, sizeof(record.parameters)); input.Read(&this->waterWidth, sizeof(this->waterWidth)); input.Read(&this->waterHeight, sizeof(this->waterHeight)); - const auto bits = static_cast(this->waterWidth) * static_cast(this->waterHeight); - const float count = static_cast(std::bit_cast(bits)); + const float count = static_cast(this->waterWidth * this->waterHeight); const auto reserveCount = count < 0.0f ? static_cast(-1) : static_cast(count); this->waterHeights.reserve(reserveCount); this->water.reserve(reserveCount); @@ -112,22 +110,22 @@ void CGndRes::ReadWater(ResourceByteReader& input) { } if (this->minor == 8) { - std::memcpy(this->waterDefault, record.values, sizeof(this->waterDefault)); - std::uint32_t level = 0; + this->waterDefault = record.parameters; + float level = 0.0f; - for (std::uint32_t index = 0; static_cast(std::bit_cast(index)) < count; ++index) { + for (int index = 0; static_cast(index) < count; ++index) { input.Read(&level, sizeof(level)); this->waterHeights.push_back(level); - record.values[0] = level; + record.parameters.level = level; std::memset(record.unknown_0018, 0, sizeof(record.unknown_0018)); this->water.push_back(record); } } else if (this->minor == 9) { - for (std::uint32_t index = 0; static_cast(std::bit_cast(index)) < count; ++index) { - input.Read(record.values, sizeof(record.values)); + for (int index = 0; static_cast(index) < count; ++index) { + input.Read(&record.parameters, sizeof(record.parameters)); std::memset(record.unknown_0018, 0, sizeof(record.unknown_0018)); this->water.push_back(record); - this->waterHeights.push_back(record.values[0]); + this->waterHeights.push_back(record.parameters.level); } } } @@ -156,7 +154,6 @@ void CGndRes::Lightmap(int index, unsigned char* output) const { for (unsigned channel = 0; channel < 4; ++channel) { const unsigned char* packed = this->legacyLightmapBytes + 40u * indices[channel]; - // Expands the high five bits, without low-bit fill. for (unsigned bit = 0, pixel = 0; bit < 320; bit += 5, ++pixel) { const unsigned shift = bit % 8; unsigned value = ((248u >> shift) & packed[bit / 8]) << shift; diff --git a/Source/Resource/GroundResource.h b/Source/Resource/World/GroundResource.h similarity index 71% rename from Source/Resource/GroundResource.h rename to Source/Resource/World/GroundResource.h index 4b5978a..08d23b0 100644 --- a/Source/Resource/GroundResource.h +++ b/Source/Resource/World/GroundResource.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_GROUNDRESOURCE_H -#define RAGNAROK_SOURCE_RESOURCE_GROUNDRESOURCE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_WORLD_GROUNDRESOURCE_H +#define RAGNAROK_SOURCE_RESOURCE_WORLD_GROUNDRESOURCE_H #include "Resource/Resource.h" @@ -8,17 +8,24 @@ class ResourceBytes; struct ResourceByteReader; +struct GroundWaterParameters { + /* 0000 */ float level; + /* 0004 */ int type; + /* 0008 */ float height; + /* 000C */ float speed; + /* 0010 */ float pitch; + /* 0014 */ int animation; +}; + struct GroundWater { - std::uint32_t values[6]; - std::uint32_t unknown_0018[3]; + /* 0000 */ GroundWaterParameters parameters; + /* 0018 */ std::uint32_t unknown_0018[3]; }; struct GroundResourceContext { ResourceBytes& file; }; -// RTTI CGndRes. Names and record slices borrow retained -// file bytes. Unload clears selected slices, not dimensions or water records. class CGndRes : public CRes { public: explicit CGndRes(GroundResourceContext& context); @@ -38,10 +45,10 @@ public: /* 0124 */ int textureCount; /* 0128 */ int tileCount; /* 012C */ int lightmapCount; - /* 0130 */ std::uint32_t waterDefault[6]; + /* 0130 */ GroundWaterParameters waterDefault; /* 0148 */ int waterWidth; /* 014C */ int waterHeight; - /* 0150 */ std::vector waterHeights; + /* 0150 */ std::vector waterHeights; /* 015C */ std::vector water; /* 0168 */ std::vector textureNames; /* 0174 */ const unsigned char* lightmaps; @@ -53,12 +60,12 @@ public: private: bool Parse(ResourceByteReader& input); void ReadWater(ResourceByteReader& input); - // Required snapshot: ResourceBytes cannot transfer its borrowed allocation. - // Replaces the original retaining CFile at +0x188. + std::vector m_bytes; GroundResourceContext* m_context; }; +static_assert(sizeof(GroundWaterParameters) == 24); static_assert(sizeof(GroundWater) == 36); #endif diff --git a/Source/Resource/TerrainResource.cpp b/Source/Resource/World/TerrainResource.cpp similarity index 84% rename from Source/Resource/TerrainResource.cpp rename to Source/Resource/World/TerrainResource.cpp index 42add09..bddbf04 100644 --- a/Source/Resource/TerrainResource.cpp +++ b/Source/Resource/World/TerrainResource.cpp @@ -1,7 +1,7 @@ -#include "Client/ErrorDialog.h" -#include "Resource/BitmapResource.h" +#include "Client/Application/ErrorDialog.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceByteReader.h" -#include "Resource/TerrainResource.h" +#include "Resource/World/TerrainResource.h" #include @@ -54,8 +54,7 @@ bool C3dAttr::Load(const char* name) { if (minor >= 3) { for (int row = 0; row < rows; ++row) { for (int column = 0; column < columns; ++column) { - this->m_cells[static_cast(row) * static_cast(columns) + static_cast(column)] - .type &= 0x7FFFFFFFu; + this->m_cells[static_cast(row) * static_cast(columns) + static_cast(column)].type &= 0x7FFFFFFFu; } } } @@ -65,8 +64,6 @@ bool C3dAttr::Load(const char* name) { ShowErrorDialog(this->m_context->renderSystem, "C3dAttr::Unsupported Version", 0); } - // Original closes twice on a supported version and reports success for an - // unsupported one. Neither branch normalizes cellSize or old cell bytes. file.Close(); return true; } diff --git a/Source/Resource/TerrainResource.h b/Source/Resource/World/TerrainResource.h similarity index 68% rename from Source/Resource/TerrainResource.h rename to Source/Resource/World/TerrainResource.h index eaeffef..6d8b067 100644 --- a/Source/Resource/TerrainResource.h +++ b/Source/Resource/World/TerrainResource.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_TERRAINRESOURCE_H -#define RAGNAROK_SOURCE_RESOURCE_TERRAINRESOURCE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_WORLD_TERRAINRESOURCE_H +#define RAGNAROK_SOURCE_RESOURCE_WORLD_TERRAINRESOURCE_H -#include "Contents/TerrainHeight.h" +#include "Contents/Ground/TerrainHeight.h" #include "Resource/Resource.h" #include @@ -13,8 +13,6 @@ struct TerrainResourceContext { CRenderSystemBase*& renderSystem; }; -// RTTI C3dAttr. Unload clears dimensions but -// retains cells; destruction frees storage. Context follows original fields. class C3dAttr : public CRes { public: explicit C3dAttr(TerrainResourceContext& context); @@ -29,7 +27,6 @@ public: /* 0118 */ int cellSize; private: - // The original's trivial cell constructor leaves new records unwritten. struct Cell : TerrainHeightCell { Cell() noexcept { } diff --git a/Source/Resource/WorldEnvironment.cpp b/Source/Resource/World/WorldEnvironment.cpp similarity index 92% rename from Source/Resource/WorldEnvironment.cpp rename to Source/Resource/World/WorldEnvironment.cpp index f9ae926..df66429 100644 --- a/Source/Resource/WorldEnvironment.cpp +++ b/Source/Resource/World/WorldEnvironment.cpp @@ -1,6 +1,6 @@ #include "Resource/ResourceByteReader.h" -#include "Resource/WorldResource.h" -#include "Utility/AffineMatrix.h" +#include "Resource/World/WorldResource.h" +#include "Utility/Math/AffineMatrix.h" #include @@ -56,8 +56,7 @@ void C3dWorldRes::ReadEnvironment(ResourceByteReader& input, unsigned version) { for (unsigned component = 0; component < 3; ++component) { this->lightDirection[component] = - ((matrix.values[component] * 0.0f + matrix.values[component + 3]) + matrix.values[component + 6] * 0.0f) + - matrix.values[component + 9]; + ((matrix.values[component] * 0.0f + matrix.values[component + 3]) + matrix.values[component + 6] * 0.0f) + matrix.values[component + 9]; } if (version >= 0x107u) { diff --git a/Source/Resource/WorldObjects.cpp b/Source/Resource/World/WorldObjects.cpp similarity index 93% rename from Source/Resource/WorldObjects.cpp rename to Source/Resource/World/WorldObjects.cpp index db8985c..1c7d8e6 100644 --- a/Source/Resource/WorldObjects.cpp +++ b/Source/Resource/World/WorldObjects.cpp @@ -1,12 +1,12 @@ #include "Resource/ResourceByteReader.h" -#include "Resource/WorldResource.h" +#include "Resource/World/WorldResource.h" #include #include // OFFSET: 0x00761CC0 // FUNCTION: fn_08073 -// Unknown type consumes only its type word; light records are read and discarded exactly as in the original. + void C3dWorldRes::ReadObjects(ResourceByteReader& input, unsigned version, unsigned build, char* lastName) { int count; input.Read(&count, sizeof(count)); @@ -37,7 +37,6 @@ void C3dWorldRes::ReadObjects(ResourceByteReader& input, unsigned version, unsig input.Read(&modelIndex, sizeof(modelIndex)); } - // COMISS 0,speed / JB accepts only ordered positive values. if (speed > 100.0f || !(0.0f < speed)) { speed = 1.0f; } diff --git a/Source/Resource/WorldResource.cpp b/Source/Resource/World/WorldResource.cpp similarity index 89% rename from Source/Resource/WorldResource.cpp rename to Source/Resource/World/WorldResource.cpp index 561b2de..777bb04 100644 --- a/Source/Resource/WorldResource.cpp +++ b/Source/Resource/World/WorldResource.cpp @@ -1,18 +1,17 @@ -#include "Client/ErrorDialog.h" -#include "Resource/BitmapResource.h" +#include "Client/Application/ErrorDialog.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceByteReader.h" -#include "Resource/WorldResource.h" +#include "Resource/World/WorldResource.h" #include #include // STATIC: 0x016FDA64 // GLOBAL: gl_24387 -// Diffuse, duplicate diffuse and ambient occupy consecutive original globals. + WorldLighting g_worldLighting{}; namespace { - // OFFSET: 0x00763010 // FUNCTION: fn_08075 signed char CompareWorldVersion(const int targetVersion[2], const unsigned char* const fileVersion[2]) { @@ -32,12 +31,10 @@ namespace { return 0; } - } // OFFSET: 0x00763060 -C3dWorldRes::C3dWorldRes(WorldResourceContext& context) - : spatial(nullptr), lightDirection{}, diffuse{}, ambient{}, flag(0), m_context(&context) { +C3dWorldRes::C3dWorldRes(WorldResourceContext& context) : spatial(nullptr), lightDirection{}, diffuse{}, ambient{}, flag(0), m_context(&context) { } // OFFSET: 0x00763550 @@ -83,6 +80,7 @@ bool C3dWorldRes::Load(const char* name) { auto& file = this->m_context->file; struct CloseFile { ResourceBytes& file; + ~CloseFile() { file.Close(); } @@ -112,6 +110,7 @@ bool C3dWorldRes::Load(const char* name) { char message[256]; std::snprintf(message, sizeof(message), "Unsupported Version\n current version: %d.%d < %d.%d", 2, 7, major, minor); ShowErrorDialog(this->m_context->renderSystem, message, 0); + return false; } @@ -123,7 +122,6 @@ bool C3dWorldRes::Load(const char* name) { input.Read(&build, sizeof(build)); } - // Constant false: no additional build rejection. if (major == 2 && minor >= 2) { input.Read(&this->flag, 1); } @@ -148,7 +146,7 @@ bool C3dWorldRes::Load(const char* name) { if (CompareWorldVersion(targetVersion, fileVersion) <= 0 && build >= 221) { unsigned count; input.Read(&count, sizeof(count)); - // Original memory-backed CFile::Seek clamps an overrun to file size. + const unsigned position = input.position + 4u * count; input.position = position <= input.size ? position : input.size; } @@ -165,5 +163,6 @@ bool C3dWorldRes::Load(const char* name) { std::memcpy(this->m_context->lighting.ambient, this->ambient, sizeof(this->ambient)); std::memcpy(this->m_context->lighting.diffuse, this->diffuse, sizeof(this->diffuse)); std::memcpy(this->m_context->lighting.secondaryDiffuse, this->diffuse, sizeof(this->diffuse)); + return true; } diff --git a/Source/Resource/WorldResource.h b/Source/Resource/World/WorldResource.h similarity index 88% rename from Source/Resource/WorldResource.h rename to Source/Resource/World/WorldResource.h index fa074a5..afd6448 100644 --- a/Source/Resource/WorldResource.h +++ b/Source/Resource/World/WorldResource.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_RESOURCE_WORLDRESOURCE_H -#define RAGNAROK_SOURCE_RESOURCE_WORLDRESOURCE_H +#ifndef RAGNAROK_SOURCE_RESOURCE_WORLD_WORLDRESOURCE_H +#define RAGNAROK_SOURCE_RESOURCE_WORLD_WORLDRESOURCE_H -#include "Contents/WorldSpatialTree.h" +#include "Contents/World/WorldSpatialTree.h" #include "Resource/Resource.h" #include @@ -45,7 +45,6 @@ struct WorldEffectRecord { float parameters[4]; }; -// Original lighting globals updated by successful world-resource loads. struct WorldLighting { float diffuse[3]; float secondaryDiffuse[3]; @@ -59,8 +58,6 @@ struct WorldResourceContext { WorldLighting& lighting; }; -// RTTI C3dWorldRes. Unload owns record/tree deletion; -// the original destructor releases container nodes and names separately. class C3dWorldRes : public CRes { public: explicit C3dWorldRes(WorldResourceContext& context); diff --git a/Source/Script/LuaInstance.cpp b/Source/Script/LuaInstance.cpp index 4e32d55..cf55884 100644 --- a/Source/Script/LuaInstance.cpp +++ b/Source/Script/LuaInstance.cpp @@ -38,7 +38,7 @@ bool CLuaInstance::Execute(const std::string& name) { // STATIC: 0x010D9630 // STRING: st_00223 const char* error = lua_tostring(this->m_state, -1); - MessageBoxA(nullptr, error, "Lua Error", 0); + MessageBoxA(nullptr, error, "Lua Error", MB_OK); return false; } @@ -47,7 +47,7 @@ bool CLuaInstance::Execute(const std::string& name) { // FUNCTION: fn_01129 int CLuaInstance::LuaMessageBox(lua_State* state) { const std::string text = lua_tostring(state, -1); - MessageBoxA(nullptr, text.c_str(), "CLuaInstance", 0); + MessageBoxA(nullptr, text.c_str(), "CLuaInstance", MB_OK); return 0; } @@ -57,9 +57,11 @@ bool CLuaInstance::LoadFile(const std::string& path, bool showError) { if (luaL_loadfile(this->m_state, path.c_str()) == 0 && lua_pcall(this->m_state, 0, LUA_MULTRET, 0) == 0) { return true; } + if (showError) { - MessageBoxA(nullptr, lua_tostring(this->m_state, -1), path.c_str(), 0); + MessageBoxA(nullptr, lua_tostring(this->m_state, -1), path.c_str(), MB_OK); } + return false; } @@ -82,14 +84,13 @@ bool CLuaInstance::LoadFile(const std::string& path) { file.Read(buffer, size); file.Close(); - if (luaL_loadbuffer(this->m_state, buffer, size, path.c_str()) == 0 && - lua_pcall(this->m_state, 0, 0, 0) == 0) { + if (luaL_loadbuffer(this->m_state, buffer, size, path.c_str()) == 0 && lua_pcall(this->m_state, 0, 0, 0) == 0) { std::free(buffer); return true; } const char* error = lua_tostring(this->m_state, -1); - MessageBoxA(nullptr, error, path.c_str(), 0); + MessageBoxA(nullptr, error, path.c_str(), MB_OK); lua_pop(this->m_state, 1); std::free(buffer); @@ -126,18 +127,22 @@ int CLuaInstance::ReadStrings(std::vector& values, const char* glob lua_pop(this->m_state, 1); return (type != LUA_TNIL) + 1; } + values.resize(lua_objlen(this->m_state, -1)); lua_pushnil(this->m_state); std::size_t index = 0; + while (lua_next(this->m_state, -2)) { type = lua_type(this->m_state, -1); if (type != LUA_TSTRING) { lua_pop(this->m_state, 3); return (type != LUA_TNIL) + 1; } + values[index++] = lua_tostring(this->m_state, -1); lua_pop(this->m_state, 1); } + lua_pop(this->m_state, 1); return 0; } diff --git a/Source/Script/LuaScript.cpp b/Source/Script/LuaScript.cpp index c4c7584..e62f621 100644 --- a/Source/Script/LuaScript.cpp +++ b/Source/Script/LuaScript.cpp @@ -30,8 +30,7 @@ void LuaScript::Close() { // OFFSET: 0x00AFDD60 // FUNCTION: fn_18335 bool LuaScript::Execute(const void* bytes, std::size_t size) { - return this->m_state && luaL_loadbuffer(this->m_state, static_cast(bytes), size, "buf") == 0 && - lua_pcall(this->m_state, 0, 0, 0) == 0; + return this->m_state && luaL_loadbuffer(this->m_state, static_cast(bytes), size, "buf") == 0 && lua_pcall(this->m_state, 0, 0, 0) == 0; } // OFFSET: 0x00AFD1D0 @@ -42,7 +41,7 @@ void LuaScript::Error(const char* caption, const char* format, ...) { va_start(arguments, format); _vsnprintf_s(text, sizeof(text), _TRUNCATE, format, arguments); va_end(arguments); - MessageBoxA(nullptr, text, caption, 0); + MessageBoxA(nullptr, text, caption, MB_OK); } // OFFSET: 0x00AFC9A0 @@ -51,16 +50,19 @@ bool LuaScript::Call(std::string function, const char* signature, ...) { if (!this->m_state) { return false; } + va_list arguments; va_start(arguments, signature); lua_getglobal(this->m_state, function.c_str()); int inputCount = 0; + while (*signature) { luaL_checkstack(this->m_state, 1, "too many arguments"); char option = *signature++; if (option == '>') { break; } + switch (option) { case 'b': lua_pushboolean(this->m_state, static_cast(va_arg(arguments, int))); @@ -78,8 +80,10 @@ bool LuaScript::Call(std::string function, const char* signature, ...) { this->Error(function.c_str(), "invalid option (%c)", option); break; } + ++inputCount; } + int outputCount = static_cast(std::strlen(signature)); if (lua_pcall(this->m_state, inputCount, outputCount, 0)) { std::string error = lua_tostring(this->m_state, -1); @@ -87,9 +91,11 @@ bool LuaScript::Call(std::string function, const char* signature, ...) { if (this->m_state) { lua_settop(this->m_state, 0); } + va_end(arguments); return false; } + for (int output = -outputCount; *signature; ++output) { switch (*signature++) { case 'b': @@ -109,12 +115,14 @@ bool LuaScript::Call(std::string function, const char* signature, ...) { break; } } + if (outputCount) { lua_pop(this->m_state, outputCount); if (this->m_state) { lua_settop(this->m_state, 0); } } + va_end(arguments); return true; } @@ -133,6 +141,7 @@ bool LuaScript::CallTable(std::string table, std::string function, const char* s lua_getfield(this->m_state, -1, function.c_str()); int inputCount = 0; + while (*signature) { luaL_checkstack(this->m_state, 1, "too many arguments"); @@ -169,6 +178,7 @@ bool LuaScript::CallTable(std::string table, std::string function, const char* s if (this->m_state) { lua_settop(this->m_state, 0); } + va_end(arguments); return false; } @@ -210,10 +220,12 @@ int LuaScript::GlobalInteger(const char* name) { if (!this->m_state) { return 0; } + lua_getglobal(this->m_state, name); if (!lua_isnumber(this->m_state, -1)) { return -1; } + int value = static_cast(lua_tonumber(this->m_state, -1)); lua_pop(this->m_state, 1); return value; @@ -225,10 +237,12 @@ std::string LuaScript::GlobalString(const char* name) { if (!this->m_state) { return {}; } + lua_getglobal(this->m_state, name); if (!lua_isstring(this->m_state, -1)) { return {}; } + std::string value = lua_tostring(this->m_state, -1); lua_pop(this->m_state, 1); return value; @@ -240,8 +254,9 @@ bool LuaScript::HasTable(const char* name) { if (!this->m_state) { return false; } + lua_getglobal(this->m_state, name); - // The original deliberately leaves this fetched global on the stack. + return lua_type(this->m_state, -1) == LUA_TTABLE; } @@ -268,7 +283,6 @@ std::list LuaScript::TableKeys(const char* name, int) { keys.sort(); } - // A missing/non-table global remains on the stack in the original. return keys; } @@ -293,15 +307,11 @@ int LuaScript::TableInteger(std::string table, int keyType, std::intptr_t key) { lua_pushstring(this->m_state, reinterpret_cast(key)); lua_gettable(this->m_state, -2); } else if (keyType != 2) { - // Unknown selectors construct signature "d": perform the integer lookup, - // but retain its value without attempting the absent output conversion. lua_pushnumber(this->m_state, static_cast(key)); lua_gettable(this->m_state, -2); return value; } - // Selector two constructs "ld"; the original input helper does not implement - // 'l', so it leaves the table itself for the numeric output check. if (lua_isnumber(this->m_state, -1)) { value = static_cast(lua_tonumber(this->m_state, -1)); lua_pop(this->m_state, 1); diff --git a/Source/Script/LuaScript.h b/Source/Script/LuaScript.h index fa93c1e..78f71ce 100644 --- a/Source/Script/LuaScript.h +++ b/Source/Script/LuaScript.h @@ -11,8 +11,6 @@ extern "C" { #include #include -// Reconstructed name for the original one-pointer script wrapper. This does not -// claim the unreconstructed application's native-registration initializer. class LuaScript { public: LuaScript(); diff --git a/Source/UI/UIChooseSellBuyWnd.cpp b/Source/UI/Acceptance/UIChooseSellBuyWnd.cpp similarity index 85% rename from Source/UI/UIChooseSellBuyWnd.cpp rename to Source/UI/Acceptance/UIChooseSellBuyWnd.cpp index d91f212..f200203 100644 --- a/Source/UI/UIChooseSellBuyWnd.cpp +++ b/Source/UI/Acceptance/UIChooseSellBuyWnd.cpp @@ -1,13 +1,12 @@ -#include "Client/ModeEvents.h" +#include "Client/Mode/ModeEvents.h" #include "Client/ReplayPacketRecorder.h" -#include "Resource/BitmapResource.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/UIBitmapButton.h" -#include "UI/UIJoinPartyAcceptWnd.h" -#include "UI/UITextViewer.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Buttons/UIBitmapButton.h" +#include "UI/Acceptance/UIJoinPartyAcceptWnd.h" +#include "UI/Text/UITextViewer.h" +#include "UI/Window/WindowManagerWindows.h" -#include #include namespace { @@ -15,11 +14,7 @@ namespace { } // OFFSET: 0x008C73C0 -UIChooseSellBuyWnd::UIChooseSellBuyWnd( - UIWindowContext& windows, - UIFrameContext& frames, - UIAcceptanceContext& acceptance -) +UIChooseSellBuyWnd::UIChooseSellBuyWnd(UIWindowContext& windows, UIFrameContext& frames, UIAcceptanceContext& acceptance) : UIFrameWnd(windows, frames, 0), identity(0), m_acceptance(&acceptance) { } @@ -63,9 +58,7 @@ void UIChooseSellBuyWnd::Slot15(int width, int height) { this->AddChoice("btn_cancel", 185, 234, 96); this->m_message0 = 224; this->CreateViewer(width, height); - this->viewer->SendMsg( - nullptr, 29, reinterpret_cast(this->m_acceptance->text.buttons.services.MessageText(92)), 38, 0, 0 - ); + this->viewer->SendMsg(nullptr, 29, reinterpret_cast(this->m_acceptance->text.buttons.services.MessageText(92)), 38, 0, 0); } // OFFSET: 0x008ED130 @@ -78,16 +71,9 @@ void UIChooseSellBuyWnd::Paint() { // OFFSET: 0x008F8860 // FUNCTION: fn_12332 -int UIChooseSellBuyWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIChooseSellBuyWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message == 6) { - const int response = std::bit_cast(static_cast(a)); + const int response = static_cast(a); this->m_acceptance->recorder.Record(this->geometry.id, response, b, c, d); if (this->geometry.visible != 0) { @@ -134,6 +120,7 @@ int UIChooseSellBuyWnd::SendMsg( this->m_frameContext->windows.CloseWindow(22); this->m_frameContext->windows.CloseWindow(23); this->m_frameContext->windows.CloseWindow(24); + return 0; } diff --git a/Source/UI/UIExchangeAcceptWnd.cpp b/Source/UI/Acceptance/UIExchangeAcceptWnd.cpp similarity index 76% rename from Source/UI/UIExchangeAcceptWnd.cpp rename to Source/UI/Acceptance/UIExchangeAcceptWnd.cpp index 42f863f..d630eb8 100644 --- a/Source/UI/UIExchangeAcceptWnd.cpp +++ b/Source/UI/Acceptance/UIExchangeAcceptWnd.cpp @@ -1,21 +1,16 @@ -#include "Client/ModeEvents.h" +#include "Client/Mode/ModeEvents.h" #include "Client/ReplayPacketRecorder.h" -#include "Contents/NormalItemSlots.h" +#include "Contents/UserData/NormalItemSlots.h" #include "File/ShortcutFilename.h" -#include "UI/UIButton.h" -#include "UI/UIJoinPartyAcceptWnd.h" -#include "UI/UITextViewer.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Buttons/UIButton.h" +#include "UI/Acceptance/UIJoinPartyAcceptWnd.h" +#include "UI/Text/UITextViewer.h" +#include "UI/Window/WindowManagerWindows.h" -#include #include // OFFSET: 0x008C7AA0 -UIExchangeAcceptWnd::UIExchangeAcceptWnd( - UIWindowContext& windows, - UIFrameContext& frames, - UIAcceptanceContext& acceptance -) +UIExchangeAcceptWnd::UIExchangeAcceptWnd(UIWindowContext& windows, UIFrameContext& frames, UIAcceptanceContext& acceptance) : UIChooseSellBuyWnd(windows, frames, acceptance), saved(nullptr) { } @@ -36,18 +31,11 @@ void UIExchangeAcceptWnd::Slot15(int width, int height) { // OFFSET: 0x008FA8C0 // FUNCTION: fn_12343 -int UIExchangeAcceptWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIExchangeAcceptWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { auto& owner = *this->m_acceptance; if (message == 6) { - const int response = std::bit_cast(static_cast(a)); + const int response = static_cast(a); owner.recorder.Record(this->geometry.id, response, b, c, d); if (response == 184 || response == 185) { @@ -61,10 +49,8 @@ int UIExchangeAcceptWnd::SendMsg( if (message == 34) { this->saved = reinterpret_cast(a); - if ( - this->saved->width != 280 || this->saved->height != 120 || this->saved->x < 0 || - this->saved->x > owner.screenWidth - 280 || this->saved->y < 0 || this->saved->y > owner.screenHeight - 120 - ) { + if (this->saved->width != 280 || this->saved->height != 120 || this->saved->x < 0 || this->saved->x > owner.screenWidth - 280 || this->saved->y < 0 || + this->saved->y > owner.screenHeight - 120) { this->saved->x = 200; this->saved->y = 200; this->saved->width = 280; @@ -86,8 +72,9 @@ int UIExchangeAcceptWnd::SendMsg( text += ShortcutFilename(static_cast(b)); text += " "; text += owner.service == 12 ? "Nv." : "Lv."; - text += std::to_string(std::bit_cast(static_cast(c))); + text += std::to_string(static_cast(c)); this->viewer->SendMsg(nullptr, 29, reinterpret_cast(text.c_str()), 138, 0, 0); + return 0; } diff --git a/Source/UI/UIJoinPartyAcceptWnd.cpp b/Source/UI/Acceptance/UIJoinPartyAcceptWnd.cpp similarity index 78% rename from Source/UI/UIJoinPartyAcceptWnd.cpp rename to Source/UI/Acceptance/UIJoinPartyAcceptWnd.cpp index 18c031b..93e16b4 100644 --- a/Source/UI/UIJoinPartyAcceptWnd.cpp +++ b/Source/UI/Acceptance/UIJoinPartyAcceptWnd.cpp @@ -1,19 +1,14 @@ -#include "Client/ModeEvents.h" +#include "Client/Mode/ModeEvents.h" #include "Client/ReplayPacketRecorder.h" -#include "UI/UIButton.h" -#include "UI/UIJoinPartyAcceptWnd.h" -#include "UI/UITextViewer.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Buttons/UIButton.h" +#include "UI/Acceptance/UIJoinPartyAcceptWnd.h" +#include "UI/Text/UITextViewer.h" +#include "UI/Window/WindowManagerWindows.h" -#include #include // OFFSET: 0x008C8240 -UIJoinPartyAcceptWnd::UIJoinPartyAcceptWnd( - UIWindowContext& windows, - UIFrameContext& frames, - UIAcceptanceContext& acceptance -) +UIJoinPartyAcceptWnd::UIJoinPartyAcceptWnd(UIWindowContext& windows, UIFrameContext& frames, UIAcceptanceContext& acceptance) : UIExchangeAcceptWnd(windows, frames, acceptance) { } @@ -23,16 +18,9 @@ UIJoinPartyAcceptWnd::~UIJoinPartyAcceptWnd() = default; // OFFSET: 0x008FE780 // FUNCTION: fn_12353 -int UIJoinPartyAcceptWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIJoinPartyAcceptWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message == 6) { - const int response = std::bit_cast(static_cast(a)); + const int response = static_cast(a); this->m_acceptance->recorder.Record(this->geometry.id, response, b, c, d); if (response == 184 || response == 185) { @@ -51,6 +39,7 @@ int UIJoinPartyAcceptWnd::SendMsg( text += this->m_acceptance->text.buttons.services.MessageText(94); this->viewer->Clear(); this->viewer->SendMsg(nullptr, 29, reinterpret_cast(text.c_str()), 38, 0, 0); + return 0; } diff --git a/Source/UI/UIJoinPartyAcceptWnd.h b/Source/UI/Acceptance/UIJoinPartyAcceptWnd.h similarity index 65% rename from Source/UI/UIJoinPartyAcceptWnd.h rename to Source/UI/Acceptance/UIJoinPartyAcceptWnd.h index 6bda32b..7690491 100644 --- a/Source/UI/UIJoinPartyAcceptWnd.h +++ b/Source/UI/Acceptance/UIJoinPartyAcceptWnd.h @@ -1,16 +1,14 @@ -#ifndef RAGNAROK_SOURCE_UI_UIJOINPARTYACCEPTWND_H -#define RAGNAROK_SOURCE_UI_UIJOINPARTYACCEPTWND_H +#ifndef RAGNAROK_SOURCE_UI_ACCEPTANCE_UIJOINPARTYACCEPTWND_H +#define RAGNAROK_SOURCE_UI_ACCEPTANCE_UIJOINPARTYACCEPTWND_H -#include "Contents/ItemInfo.h" -#include "UI/UIFrameWnd.h" +#include "Contents/Items/ItemInfo.h" +#include "UI/Window/UIFrameWnd.h" class UITextViewer; struct UITextViewerContext; struct WindowResponseRecorder; struct NormalItemSlotWindow; -// Borrowed owners used by the shared choice/exchange operations. Inventory -// Lists are the three temporary shop lists. struct UIAcceptanceContext { UITextViewerContext& text; WindowResponseRecorder& recorder; @@ -24,21 +22,13 @@ struct UIAcceptanceContext { std::string& replayExchangeName; }; -// RTTI UIChooseSellBuyWnd, original size 188. class UIChooseSellBuyWnd : public UIFrameWnd { public: UIChooseSellBuyWnd(UIWindowContext& windows, UIFrameContext& frames, UIAcceptanceContext& acceptance); ~UIChooseSellBuyWnd() override; void Slot15(int width, int height) override; void Paint() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; /* 00B4 */ std::uint32_t identity; /* 00B8 */ UITextViewer* viewer; @@ -49,37 +39,21 @@ protected: void CreateViewer(int width, int height); }; -// RTTI UIExchangeAcceptWnd, original size 192. class UIExchangeAcceptWnd : public UIChooseSellBuyWnd { public: UIExchangeAcceptWnd(UIWindowContext& windows, UIFrameContext& frames, UIAcceptanceContext& acceptance); ~UIExchangeAcceptWnd() override; void Slot15(int width, int height) override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; /* 00BC */ NormalItemSlotWindow* saved; }; -// RTTI UIJoinPartyAcceptWnd, original size 192. class UIJoinPartyAcceptWnd : public UIExchangeAcceptWnd { public: UIJoinPartyAcceptWnd(UIWindowContext& windows, UIFrameContext& frames, UIAcceptanceContext& acceptance); ~UIJoinPartyAcceptWnd() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; }; #if defined(_WIN32) && !defined(_WIN64) diff --git a/Source/UI/UIBasicButton.cpp b/Source/UI/Buttons/UIBasicButton.cpp similarity index 62% rename from Source/UI/UIBasicButton.cpp rename to Source/UI/Buttons/UIBasicButton.cpp index 0c1e41c..aa1a7a2 100644 --- a/Source/UI/UIBasicButton.cpp +++ b/Source/UI/Buttons/UIBasicButton.cpp @@ -1,20 +1,12 @@ -#include "Render/TextContext.h" -#include "Resource/BitmapResource.h" +#include "Render/Text/TextContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/UIBasicButton.h" +#include "UI/Buttons/UIBasicButton.h" -#include #include -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } -} - // OFFSET: 0x0084EA20 -UIBasicButton::UIBasicButton(UIWindowContext& windows, UIButtonContext& controls) - : UIButton(windows, controls), invalidateParent(0) { +UIBasicButton::UIBasicButton(UIWindowContext& windows, UIButtonContext& controls) : UIButton(windows, controls), invalidateParent(0) { this->geometry.height = 20; } @@ -48,22 +40,20 @@ void UIBasicButton::Paint() { if (this->m_disabled == 1 || this->geometry.unknown_0030 <= 2) { static constexpr const char* skins[] = {"out", "over", "press", "disable"}; - const std::string prefix = - std::string("\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\btn_") + skins[state]; + const std::string prefix = std::string("\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\btn_") + skins[state]; const auto drawBitmap = [&](const char* suffix, int x) { auto* bitmap = static_cast(this->m_buttonContext->resources.Load((prefix + suffix).c_str())); this->DrawBitmap(x, 0, bitmap ? &bitmap->image : nullptr, false); }; drawBitmap("_left.bmp", 0); - const int count = Add(this->geometry.width, -12) / 6 + 1; + const int count = (this->geometry.width - 12) / 6 + 1; - for (int index = 1, x = 6; index <= count; ++index, x = Add(x, 6)) { - drawBitmap("_mid.bmp", index == count ? Add(this->geometry.width, -12) : x); + for (int index = 1, x = 6; index <= count; ++index, x = (x + 6)) { + drawBitmap("_mid.bmp", index == count ? (this->geometry.width - 12) : x); } - drawBitmap("_right.bmp", Add(this->geometry.width, -6)); - const int width = - this->TextWidth(this->m_buttonContext->fonts, this->m_buttonContext->locale, this->text.c_str(), 0, 0, 12, 0, 0); + drawBitmap("_right.bmp", (this->geometry.width - 6)); + const int width = this->TextWidth(this->m_buttonContext->fonts, this->m_buttonContext->locale, this->text.c_str(), 0, 0, 12, 0, 0); int height; { @@ -72,17 +62,16 @@ void UIBasicButton::Paint() { height = context.Measure(this->text.c_str(), static_cast(std::strlen(this->text.c_str()))).cy; } - const int x = Add(this->geometry.width, -width) / 2; - const int y = Add(this->geometry.height, -height) / 2; + const int x = (this->geometry.width - width) / 2; + const int y = (this->geometry.height - height) / 2; const bool pressed = state == 2 || state == 3; const unsigned shadow = state == 0 ? 0xD7D7D7u : state == 1 ? 0xC7A796u : state == 2 ? 0xFFFFFFu : 0xE2E2E2u; this->DrawTextAt( - this->m_buttonContext->fonts, this->m_buttonContext->locale, Add(x, pressed ? 0 : 1), Add(y, pressed ? 0 : 1), - this->text.c_str(), 0, 0, 12, shadow, 0, 0 + this->m_buttonContext->fonts, this->m_buttonContext->locale, (x + (pressed ? 0 : 1)), (y + (pressed ? 0 : 1)), this->text.c_str(), 0, 0, 12, shadow, 0, 0 ); this->DrawTextAt( - this->m_buttonContext->fonts, this->m_buttonContext->locale, Add(x, pressed ? 1 : 0), Add(y, pressed ? 1 : 0), - this->text.c_str(), 0, 0, 12, state == 3 ? 0x6F6F6Fu : 0, 0, 0 + this->m_buttonContext->fonts, this->m_buttonContext->locale, (x + (pressed ? 1 : 0)), (y + (pressed ? 1 : 0)), this->text.c_str(), 0, 0, 12, + state == 3 ? 0x6F6F6Fu : 0, 0, 0 ); } diff --git a/Source/UI/UIBasicButton.h b/Source/UI/Buttons/UIBasicButton.h similarity index 71% rename from Source/UI/UIBasicButton.h rename to Source/UI/Buttons/UIBasicButton.h index e145903..3d4072d 100644 --- a/Source/UI/UIBasicButton.h +++ b/Source/UI/Buttons/UIBasicButton.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UIBASICBUTTON_H -#define RAGNAROK_SOURCE_UI_UIBASICBUTTON_H +#ifndef RAGNAROK_SOURCE_UI_BUTTONS_UIBASICBUTTON_H +#define RAGNAROK_SOURCE_UI_BUTTONS_UIBASICBUTTON_H -#include "UI/UIButton.h" +#include "UI/Buttons/UIButton.h" -// RTTI UIBasicButton, original x86 size 208. class UIBasicButton : public UIButton { public: UIBasicButton(UIWindowContext& windows, UIButtonContext& controls); diff --git a/Source/UI/UIBitmapButton.cpp b/Source/UI/Buttons/UIBitmapButton.cpp similarity index 95% rename from Source/UI/UIBitmapButton.cpp rename to Source/UI/Buttons/UIBitmapButton.cpp index 6e71a12..9550147 100644 --- a/Source/UI/UIBitmapButton.cpp +++ b/Source/UI/Buttons/UIBitmapButton.cpp @@ -1,11 +1,12 @@ -#include "Resource/BitmapResource.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/UIBitmapButton.h" +#include "UI/Buttons/UIBitmapButton.h" // OFFSET: 0x0084EAB0 UIBitmapButton::UIBitmapButton(UIWindowContext& windowContext, UIButtonContext& buttonContext) : UIButton(windowContext, buttonContext), m_bitmapWidth(0), m_bitmapHeight(0), m_invalidateParent(0) { } + // OFFSET: 0x008511B0 // FUNCTION: fn_10689 // OFFSET: 0x00852220 @@ -19,19 +20,24 @@ bool UIBitmapButton::SetBitmap(const char* name, int state, unsigned char exactS if (!bitmap) { return false; } + if (bitmap->image.width > this->m_bitmapWidth) { this->m_bitmapWidth = bitmap->image.width; } + if (bitmap->image.height > this->m_bitmapHeight) { this->m_bitmapHeight = bitmap->image.height; } + if (exactSize != 0) { this->m_bitmapWidth = bitmap->image.width; this->m_bitmapHeight = bitmap->image.height; } + if (state >= 0 && state <= 3) { this->m_names[state] = name; } + return true; } @@ -39,6 +45,7 @@ bool UIBitmapButton::SetBitmap(const char* name, int state, unsigned char exactS // FUNCTION: fn_10795 void UIBitmapButton::Paint() { CBitmapRes* bitmap; + switch (this->geometry.unknown_0030) { case 0: bitmap = static_cast(this->m_buttonContext->resources.Load(this->m_names[0].c_str())); @@ -50,9 +57,11 @@ void UIBitmapButton::Paint() { bitmap = static_cast(this->m_buttonContext->resources.Load(this->m_names[2].c_str())); break; } + if (this->m_disabled != 0 && !this->m_names[3].empty()) { bitmap = static_cast(this->m_buttonContext->resources.Load(this->m_names[3].c_str())); } + this->DrawBitmap(0, 0, bitmap ? &bitmap->image : nullptr, false); if (this->m_invalidateParent != 0 && this->parent) { static_cast(this->parent)->Invalidate(); diff --git a/Source/UI/UIBitmapButton.h b/Source/UI/Buttons/UIBitmapButton.h similarity index 83% rename from Source/UI/UIBitmapButton.h rename to Source/UI/Buttons/UIBitmapButton.h index ef5dfc5..e1eec01 100644 --- a/Source/UI/UIBitmapButton.h +++ b/Source/UI/Buttons/UIBitmapButton.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UIBITMAPBUTTON_H -#define RAGNAROK_SOURCE_UI_UIBITMAPBUTTON_H +#ifndef RAGNAROK_SOURCE_UI_BUTTONS_UIBITMAPBUTTON_H +#define RAGNAROK_SOURCE_UI_BUTTONS_UIBITMAPBUTTON_H -#include "UI/UIButton.h" +#include "UI/Buttons/UIButton.h" -// RTTI UIBitmapButton class UIBitmapButton : public UIButton { friend class UIAdvenPartyBoardWnd; diff --git a/Source/UI/UIBmpTextButton.cpp b/Source/UI/Buttons/UIBmpTextButton.cpp similarity index 62% rename from Source/UI/UIBmpTextButton.cpp rename to Source/UI/Buttons/UIBmpTextButton.cpp index 8b4925e..98c2244 100644 --- a/Source/UI/UIBmpTextButton.cpp +++ b/Source/UI/Buttons/UIBmpTextButton.cpp @@ -1,21 +1,13 @@ -#include "Render/FontCache.h" -#include "Render/TextContext.h" -#include "Resource/BitmapResource.h" +#include "Render/Text/FontCache.h" +#include "Render/Text/TextContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/UIBmpTextButton.h" +#include "UI/Buttons/UIBmpTextButton.h" -#include #include -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } -} - // OFFSET: 0x0084ED30 -UIBmpTextButton::UIBmpTextButton(UIWindowContext& windows, UIButtonContext& controls) - : UIBitmapButton(windows, controls) { +UIBmpTextButton::UIBmpTextButton(UIWindowContext& windows, UIButtonContext& controls) : UIBitmapButton(windows, controls) { } // OFFSET: 0x00852360 @@ -36,10 +28,7 @@ void UIBmpTextButton::Paint() { const BitmapButtonTextStyle* style = nullptr; for (const auto& candidate : this->styles) { - if ( - (this->m_disabled == 0 && candidate.state == this->geometry.unknown_0030) || - (this->m_disabled == 1 && candidate.state == 3) - ) { + if ((this->m_disabled == 0 && candidate.state == this->geometry.unknown_0030) || (this->m_disabled == 1 && candidate.state == 3)) { style = &candidate; break; } @@ -55,10 +44,7 @@ void UIBmpTextButton::Paint() { if (!this->text.empty()) { const auto draw = [&](int x, int y, int height, unsigned color, unsigned char bold) { - this->DrawTextAt( - this->m_buttonContext->fonts, this->m_buttonContext->locale, x, y, this->text.c_str(), 0, 0, height, color, - bold, 0 - ); + this->DrawTextAt(this->m_buttonContext->fonts, this->m_buttonContext->locale, x, y, this->text.c_str(), 0, 0, height, color, bold, 0); }; if (style) { @@ -66,15 +52,13 @@ void UIBmpTextButton::Paint() { const int offset = !disabled && (state == 0 || state == 1) ? 1 : 0; if (style->shadow == 1) { - draw(Add(style->x, offset), Add(style->y, offset), style->height, shadowColor, disabled ? 0 : style->bold); + draw((style->x + offset), (style->y + offset), style->height, shadowColor, disabled ? 0 : style->bold); } const int pressedOffset = disabled || state == 2 ? 1 : 0; - draw(Add(style->x, pressedOffset), Add(style->y, pressedOffset), style->height, style->color, style->bold); + draw((style->x + pressedOffset), (style->y + pressedOffset), style->height, style->color, style->bold); } else { - const int width = this->TextWidth( - this->m_buttonContext->fonts, this->m_buttonContext->locale, this->text.c_str(), 0, 0, 12, 0, 0 - ); + const int width = this->TextWidth(this->m_buttonContext->fonts, this->m_buttonContext->locale, this->text.c_str(), 0, 0, 12, 0, 0); int height; { @@ -83,12 +67,12 @@ void UIBmpTextButton::Paint() { height = context.Measure(this->text.c_str(), static_cast(std::strlen(this->text.c_str()))).cy; } - const int x = Add(this->geometry.width, -width) / 2; - const int y = Add(this->geometry.height, -height) / 2; + const int x = (this->geometry.width - width) / 2; + const int y = (this->geometry.height - height) / 2; const bool pressed = disabled || state == 2; const unsigned shadowColor = disabled ? 0xE2E2E2u : state == 0 ? 0xD7D7D7u : state == 1 ? 0xC7A796u : 0xFFFFFFu; - draw(Add(x, pressed ? 0 : 1), Add(y, pressed ? 0 : 1), 12, shadowColor, 0); - draw(Add(x, pressed ? 1 : 0), Add(y, pressed ? 1 : 0), 12, disabled ? 0x6F6F6Fu : 0, 0); + draw((x + (pressed ? 0 : 1)), (y + (pressed ? 0 : 1)), 12, shadowColor, 0); + draw((x + (pressed ? 1 : 0)), (y + (pressed ? 1 : 0)), 12, disabled ? 0x6F6F6Fu : 0, 0); } } } diff --git a/Source/UI/UIBmpTextButton.h b/Source/UI/Buttons/UIBmpTextButton.h similarity index 76% rename from Source/UI/UIBmpTextButton.h rename to Source/UI/Buttons/UIBmpTextButton.h index a6428f6..1678bde 100644 --- a/Source/UI/UIBmpTextButton.h +++ b/Source/UI/Buttons/UIBmpTextButton.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UIBMPTEXTBUTTON_H -#define RAGNAROK_SOURCE_UI_UIBMPTEXTBUTTON_H +#ifndef RAGNAROK_SOURCE_UI_BUTTONS_UIBMPTEXTBUTTON_H +#define RAGNAROK_SOURCE_UI_BUTTONS_UIBMPTEXTBUTTON_H -#include "UI/UIBitmapButton.h" +#include "UI/Buttons/UIBitmapButton.h" struct BitmapButtonTextStyle { int state; @@ -13,7 +13,6 @@ struct BitmapButtonTextStyle { unsigned char shadow; }; -// RTTI UIBmpTextButton, original x86 size 324, source size 332. class UIBmpTextButton : public UIBitmapButton { public: UIBmpTextButton(UIWindowContext& windows, UIButtonContext& controls); diff --git a/Source/UI/UIButton.cpp b/Source/UI/Buttons/UIButton.cpp similarity index 85% rename from Source/UI/UIButton.cpp rename to Source/UI/Buttons/UIButton.cpp index f8d2309..7c28daa 100644 --- a/Source/UI/UIButton.cpp +++ b/Source/UI/Buttons/UIButton.cpp @@ -1,27 +1,20 @@ -#include "Client/ModeCursor.h" -#include "Client/ModeEvents.h" -#include "Resource/BitmapResource.h" +#include "Client/Mode/ModeCursor.h" +#include "Client/Mode/ModeEvents.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" #include "Script/LuaScript.h" -#include "UI/FrameFocus.h" -#include "UI/UIButton.h" -#include "UI/WindowPolicy.h" +#include "UI/Window/FrameFocus.h" +#include "UI/Buttons/UIButton.h" +#include "UI/Window/WindowPolicy.h" -#include #include -namespace { - int Add(int a, int b) { - return std::bit_cast(static_cast(a) + static_cast(b)); - } -} - // OFFSET: 0x0084EDD0 UIButton::UIButton(UIWindowContext& windowContext, UIButtonContext& buttonContext) : UIWindow(windowContext, 0), m_disabled(0), m_argument(0), m_buttonContext(&buttonContext) { this->geometry.unknown_0030 = 0; - // m_drawLabel at original+173 is deliberately not initialized by original. } + // OFFSET: 0x008523F0 // FUNCTION: fn_10709 UIButton::~UIButton() = default; @@ -32,13 +25,15 @@ void UIButton::Paint() { if (this->m_drawLabel == 0) { return; } + static const char* const backgrounds[] = { "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\sml_button_up.bmp", "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\sml_button_act.bmp", "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\sml_button_down.bmp" }; - // Original leaves the selected pointer undefined for states outside0..2. + CBitmapRes* bitmap; + switch (this->geometry.unknown_0030) { case 0: bitmap = static_cast(this->m_buttonContext->resources.Load(backgrounds[0])); @@ -50,10 +45,9 @@ void UIButton::Paint() { bitmap = static_cast(this->m_buttonContext->resources.Load(backgrounds[2])); break; } + this->DrawBitmap(0, 0, bitmap ? &bitmap->image : nullptr, false); - this->DrawTextAt( - this->m_buttonContext->fonts, this->m_buttonContext->locale, 0, 0, this->label.c_str(), 0, 0, 12, 0, 0, 0 - ); + this->DrawTextAt(this->m_buttonContext->fonts, this->m_buttonContext->locale, 0, 0, this->label.c_str(), 0, 0, 12, 0, 0, 0); } // OFFSET: 0x0085EB20 @@ -62,34 +56,41 @@ void UIButton::Slot25(int, int) { if (this->m_disabled != 0) { return; } + this->m_buttonContext->focus.Set(this); this->geometry.unknown_0030 = 2; this->Invalidate(); } + // OFFSET: 0x0085E8B0 // FUNCTION: fn_10830 void UIButton::Slot26(int x, int y) { this->Slot25(x, y); } + // OFFSET: 0x0085F600 // FUNCTION: fn_10868 void UIButton::Slot27(int x, int y) { if (this->m_disabled != 0) { return; } + unsigned state = 0; if (x >= 0 && x < this->geometry.width && y >= 0 && y < this->geometry.height) { state = this->m_buttonContext->focus.Get() == this ? 2 : 1; } + if (this->geometry.unknown_0030 != state) { this->geometry.unknown_0030 = state; this->Invalidate(); } + UIWindow* parent = static_cast(this->parent); if (parent == this->m_buttonContext->hoverParent) { parent->SendMsg(this, 6, 271, state != 0, 0, 0); } } + // OFFSET: 0x0085F180 // FUNCTION: fn_10858 void UIButton::Slot28(int x, int y) { @@ -104,36 +105,40 @@ void UIButton::Slot28(int x, int y) { } } } + if (!this->m_tooltip.empty()) { int screenX = 0, screenY = -20; + for (const UIWindow* window = this; window; window = static_cast(window->parent)) { - screenX = Add(screenX, window->geometry.x); - screenY = Add(screenY, window->geometry.y); + screenX = (screenX + window->geometry.x); + screenY = (screenY + window->geometry.y); } + this->m_buttonContext->services.Tooltip(this->m_tooltip.c_str(), screenX, screenY, -1, false, true); } + if (this->m_disabled == 0) { this->Slot27(x, y); } } + // OFFSET: 0x0085F900 // FUNCTION: fn_10874 void UIButton::Slot29(int x, int y) { - if ( - x < this->geometry.x || x > Add(this->geometry.x, this->geometry.width) || y < this->geometry.y || - y > Add(this->geometry.y, this->geometry.height) - ) { + if (x < this->geometry.x || x > (this->geometry.x + this->geometry.width) || y < this->geometry.y || y > (this->geometry.y + this->geometry.height)) { if (this->geometry.unknown_0030 != 0) { this->geometry.unknown_0030 = 0; this->Invalidate(); } } } + // OFFSET: 0x0085F950 // FUNCTION: fn_10875 void UIButton::ResetCursor(int, int) { this->m_context->cursor.Set(this->m_disabled != 0 ? 0 : 2, this->m_context->cursorTick); } + // OFFSET: 0x0085EED0 // FUNCTION: fn_10852 // ORIGINAL_SITE: 0x03DE9C61 in fn_10852 (body) @@ -143,11 +148,14 @@ void UIButton::Slot31(int x, int y) { if (focus.Get() == this) { focus.Clear(); } + return; } + if (focus.Get() != this) { return; } + if (x < 0 || x >= this->geometry.width || y < 0 || y >= this->geometry.height) { this->geometry.unknown_0030 = 0; } else { @@ -167,6 +175,7 @@ void UIButton::Slot31(int x, int y) { id = this->geometry.id; parent = static_cast(this->parent); } + parent->SendMsg(this, 6, id, this->m_argument, 0, 0); } } @@ -174,9 +183,11 @@ void UIButton::Slot31(int x, int y) { this->m_context->mode->SendModeMessage(0, this->geometry.id, this->m_argument, 0, 0); } } + this->Invalidate(); focus.Clear(); } + // OFFSET: 0x005FEAF0 // FUNCTION: fn_04132 void UIButton::Enable(unsigned char value) { @@ -184,6 +195,7 @@ void UIButton::Enable(unsigned char value) { this->Invalidate(); this->geometry.visible = value; } + // OFFSET: 0x00869730 // FUNCTION: fn_10967 void UIButton::SetTooltip(const char* text) { diff --git a/Source/UI/UIButton.h b/Source/UI/Buttons/UIButton.h similarity index 70% rename from Source/UI/UIButton.h rename to Source/UI/Buttons/UIButton.h index 64e4158..aaa7247 100644 --- a/Source/UI/UIButton.h +++ b/Source/UI/Buttons/UIButton.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UIBUTTON_H -#define RAGNAROK_SOURCE_UI_UIBUTTON_H +#ifndef RAGNAROK_SOURCE_UI_BUTTONS_UIBUTTON_H +#define RAGNAROK_SOURCE_UI_BUTTONS_UIBUTTON_H -#include "UI/UIWindow.h" +#include "UI/Window/UIWindow.h" #include @@ -11,14 +11,11 @@ class LuaScript; class FontCache; struct TextLocale; -// Explicit unresolved mode/manager operations reached by real button behavior. -// Implementations must provide real tooltip/dialog/submission semantics. class ButtonServices { public: virtual void Tooltip(const char* text, int x, int y, int color, bool option, bool convert) = 0; virtual const char* MessageText(int id) = 0; - virtual int - Confirm(const char* text, int type, int option1, int option2, const char* caption, int width, int height) = 0; + virtual int Confirm(const char* text, int type, int option1, int option2, const char* caption, int width, int height) = 0; virtual void Submit(UIWindow* window) = 0; protected: @@ -38,8 +35,6 @@ struct UIButtonContext { UIWindow* const& hoverParent; }; -// RTTI UIButton,54 original virtual slots. Original180/source188 x86 due -// UIWindow owner pointer and this button's source-only context pointer. class UIButton : public UIWindow { friend class UIAdvenPartyBoardWnd; @@ -54,10 +49,10 @@ public: void Slot29(int x, int y) override; void ResetCursor(int x, int y) override; void Slot31(int x, int y) override; - virtual void Enable(unsigned char value); // 53 + virtual void Enable(unsigned char value); void SetTooltip(const char* text); - // Source accessor for original direct writes; deliberately no invalidation. + void SetDisabled(unsigned char value) { this->m_disabled = value; } diff --git a/Source/UI/UICheckBox.cpp b/Source/UI/Buttons/UICheckBox.cpp similarity index 77% rename from Source/UI/UICheckBox.cpp rename to Source/UI/Buttons/UICheckBox.cpp index e55d6bb..00e512a 100644 --- a/Source/UI/UICheckBox.cpp +++ b/Source/UI/Buttons/UICheckBox.cpp @@ -1,25 +1,17 @@ -#include "Client/ModeCursor.h" -#include "Render/DeviceContext.h" -#include "Resource/BitmapResource.h" +#include "Client/Mode/ModeCursor.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/FrameFocus.h" -#include "UI/UICheckBox.h" - -#include - -namespace { - int Add(int a, int b) { - return std::bit_cast(static_cast(a) + static_cast(b)); - } -} +#include "UI/Window/FrameFocus.h" +#include "UI/Buttons/UICheckBox.h" // OFFSET: 0x0084F010 UICheckBox::UICheckBox(UIWindowContext& windowContext, UIButtonContext& controls) - : UIWindow(windowContext, 0), m_disabled(0), m_hidden(0), m_color(0), m_fontHeight(12), m_message(-1), m_notify(0), - m_controls(&controls) { + : UIWindow(windowContext, 0), m_disabled(0), m_hidden(0), m_color(0), m_fontHeight(12), m_message(-1), m_notify(0), m_controls(&controls) { this->geometry.unknown_0030 = 0; this->geometry.id = 213; } + // OFFSET: 0x008525B0 // FUNCTION: fn_10712 UICheckBox::~UICheckBox() = default; @@ -30,15 +22,19 @@ void UICheckBox::Paint() { if (this->m_checked.empty() || this->m_unchecked.empty()) { return; } + if (this->m_disabled != 0) { if (this->geometry.surface) { this->geometry.surface->Fill(nullptr, 0xFFFF00FFu); } + return; } + if (this->m_hidden != 0) { return; } + int width = 0; if (this->geometry.unknown_0030 == 0 || this->geometry.unknown_0030 == 1) { const std::string& name = this->geometry.unknown_0030 == 0 ? this->m_unchecked : this->m_checked; @@ -46,65 +42,74 @@ void UICheckBox::Paint() { this->DrawBitmap(0, (this->geometry.height - bitmap->image.height) / 2, &bitmap->image, false); width = bitmap->image.width; } + if (!this->m_text.empty()) { - this->DrawTextAt( - this->m_controls->fonts, this->m_controls->locale, Add(width, 3), 0, this->m_text.c_str(), 0, 0, - this->m_fontHeight, this->m_color, 0, 0 - ); + this->DrawTextAt(this->m_controls->fonts, this->m_controls->locale, (width + 3), 0, this->m_text.c_str(), 0, 0, this->m_fontHeight, this->m_color, 0, 0); } } void UICheckBox::Notify() { this->Invalidate(); UIWindow* root = this; + while (root->parent) { root = static_cast(root->parent); } + root->Invalidate(); if (this->parent) { static_cast(this->parent)->SendMsg(this, 6, this->geometry.id, this->geometry.unknown_0030, 0, 0); } } + // OFFSET: 0x008658D0 // FUNCTION: fn_10932 void UICheckBox::SetChecked(int value) { if (this->m_disabled != 0) { return; } + this->geometry.unknown_0030 = value; this->Notify(); } + // OFFSET: 0x0085EB90 // FUNCTION: fn_10841 void UICheckBox::Slot25(int, int) { if (this->m_disabled != 0 || this->m_controls->restricted) { return; } + this->geometry.unknown_0030 = 1u - this->geometry.unknown_0030; this->Notify(); if (this->m_notify != 0) { static_cast(this->parent)->SendMsg(this, 2, this->m_message, 0, 0, 0); } } + // OFFSET: 0x0085F310 // FUNCTION: fn_10859 void UICheckBox::Slot28(int x, int y) { if (this->m_disabled != 0) { return; } + this->Slot27(x, y); if (this->m_tooltip.empty()) { return; } + int screenX = 0, screenY = -20; + for (const UIWindow* node = this; node; node = static_cast(node->parent)) { - screenX = Add(screenX, node->geometry.x); - screenY = Add(screenY, node->geometry.y); + screenX = (screenX + node->geometry.x); + screenY = (screenY + node->geometry.y); } - const std::string& tooltip = - this->geometry.unknown_0030 != 0 || this->m_uncheckedTooltip.empty() ? this->m_tooltip : this->m_uncheckedTooltip; + + const std::string& tooltip = this->geometry.unknown_0030 != 0 || this->m_uncheckedTooltip.empty() ? this->m_tooltip : this->m_uncheckedTooltip; this->m_controls->services.Tooltip(tooltip.c_str(), screenX, screenY, -1, false, true); } + // OFFSET: 0x0085F9C0 // FUNCTION: fn_10877 void UICheckBox::ResetCursor(int, int) { @@ -112,6 +117,7 @@ void UICheckBox::ResetCursor(int, int) { this->m_context->cursor.Set(2, this->m_context->cursorTick); } } + // OFFSET: 0x00865450 // FUNCTION: fn_10926 void UICheckBox::SetImages(const char* checked, const char* unchecked, const char* text) { @@ -119,21 +125,23 @@ void UICheckBox::SetImages(const char* checked, const char* unchecked, const cha this->m_unchecked = unchecked; this->m_controls->resources.Load(this->m_unchecked.c_str()); this->m_text = text ? text : ""; + if (!this->m_text.empty()) { - const int width = - this->TextWidth(this->m_controls->fonts, this->m_controls->locale, this->m_text.c_str(), 0, 0, 12, 0, 0); + const int width = this->TextWidth(this->m_controls->fonts, this->m_controls->locale, this->m_text.c_str(), 0, 0, 12, 0, 0); CBitmapRes* bitmap = nullptr; if (this->geometry.unknown_0030 == 0) { bitmap = static_cast(this->m_controls->resources.Load(this->m_unchecked.c_str())); } else if (this->geometry.unknown_0030 == 1) { bitmap = static_cast(this->m_controls->resources.Load(this->m_checked.c_str())); } - const int desired = Add(Add(bitmap->image.width, width), 3); + + const int desired = ((bitmap->image.width + width) + 3); if (desired != this->geometry.width) { this->Resize(desired, this->geometry.height); } } } + // OFFSET: 0x00869760 // FUNCTION: fn_10968 void UICheckBox::SetTooltip(const char* text) { diff --git a/Source/UI/UICheckBox.h b/Source/UI/Buttons/UICheckBox.h similarity index 80% rename from Source/UI/UICheckBox.h rename to Source/UI/Buttons/UICheckBox.h index 69191e4..7906033 100644 --- a/Source/UI/UICheckBox.h +++ b/Source/UI/Buttons/UICheckBox.h @@ -1,10 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UICHECKBOX_H -#define RAGNAROK_SOURCE_UI_UICHECKBOX_H +#ifndef RAGNAROK_SOURCE_UI_BUTTONS_UICHECKBOX_H +#define RAGNAROK_SOURCE_UI_BUTTONS_UICHECKBOX_H -#include "UI/UIButton.h" +#include "UI/Buttons/UIButton.h" -// RTTI UICheckBox derives from UIWindow, not UIButton. Uses the same real -// service dependency view; original size268/source276 x86. class UICheckBox : public UIWindow { public: UICheckBox(UIWindowContext& windowContext, UIButtonContext& controls); diff --git a/Source/UI/UIJobSlotButton.cpp b/Source/UI/Buttons/UIJobSlotButton.cpp similarity index 88% rename from Source/UI/UIJobSlotButton.cpp rename to Source/UI/Buttons/UIJobSlotButton.cpp index f54dd93..2e24cf4 100644 --- a/Source/UI/UIJobSlotButton.cpp +++ b/Source/UI/Buttons/UIJobSlotButton.cpp @@ -1,8 +1,7 @@ -#include "UI/UIJobSlotButton.h" +#include "UI/Buttons/UIJobSlotButton.h" // OFFSET: 0x007BAD70 -UIJobSlotButton::UIJobSlotButton(UIWindowContext& windows, UIButtonContext& controls) - : UIBitmapButton(windows, controls), selected(0) { +UIJobSlotButton::UIJobSlotButton(UIWindowContext& windows, UIButtonContext& controls) : UIBitmapButton(windows, controls), selected(0) { } // OFFSET: 0x007BB6B0 diff --git a/Source/UI/UIJobSlotButton.h b/Source/UI/Buttons/UIJobSlotButton.h similarity index 65% rename from Source/UI/UIJobSlotButton.h rename to Source/UI/Buttons/UIJobSlotButton.h index f10b71a..fa3f93b 100644 --- a/Source/UI/UIJobSlotButton.h +++ b/Source/UI/Buttons/UIJobSlotButton.h @@ -1,10 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UIJOBSLOTBUTTON_H -#define RAGNAROK_SOURCE_UI_UIJOBSLOTBUTTON_H +#ifndef RAGNAROK_SOURCE_UI_BUTTONS_UIJOBSLOTBUTTON_H +#define RAGNAROK_SOURCE_UI_BUTTONS_UIJOBSLOTBUTTON_H -#include "UI/UIBitmapButton.h" +#include "UI/Buttons/UIBitmapButton.h" -// RTTI UIJobSlotButton. Original x86 size 340; -// inherited source dependency pointers account for the eight-byte increase. class UIJobSlotButton : public UIBitmapButton { public: UIJobSlotButton(UIWindowContext& windows, UIButtonContext& controls); diff --git a/Source/UI/UINaviLinkButton.cpp b/Source/UI/Buttons/UINaviLinkButton.cpp similarity index 74% rename from Source/UI/UINaviLinkButton.cpp rename to Source/UI/Buttons/UINaviLinkButton.cpp index d2d6ed9..7ee2a60 100644 --- a/Source/UI/UINaviLinkButton.cpp +++ b/Source/UI/Buttons/UINaviLinkButton.cpp @@ -1,12 +1,8 @@ -#include "UI/NavigationLink.h" -#include "UI/UINaviLinkButton.h" +#include "UI/Text/NavigationLink.h" +#include "UI/Buttons/UINaviLinkButton.h" // OFFSET: 0x0086DF60 -UINaviLinkButton::UINaviLinkButton( - UIWindowContext& windows, - UIButtonContext& buttons, - NavigationDestination& navigation -) +UINaviLinkButton::UINaviLinkButton(UIWindowContext& windows, UIButtonContext& buttons, NavigationDestination& navigation) : UITextButton(windows, buttons), m_navigation(&navigation) { } @@ -30,7 +26,6 @@ void UINaviLinkButton::Slot25(int, int) { std::string map = this->link.substr(0, start); if (map.find("") != std::string::npos) { - // Original removes the marker's length from the beginning, not its match. map = map.substr(7); } diff --git a/Source/UI/UINaviLinkButton.h b/Source/UI/Buttons/UINaviLinkButton.h similarity index 79% rename from Source/UI/UINaviLinkButton.h rename to Source/UI/Buttons/UINaviLinkButton.h index c9ea33e..bbcdf4a 100644 --- a/Source/UI/UINaviLinkButton.h +++ b/Source/UI/Buttons/UINaviLinkButton.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UINAVILINKBUTTON_H -#define RAGNAROK_SOURCE_UI_UINAVILINKBUTTON_H +#ifndef RAGNAROK_SOURCE_UI_BUTTONS_UINAVILINKBUTTON_H +#define RAGNAROK_SOURCE_UI_BUTTONS_UINAVILINKBUTTON_H -#include "UI/UITextButton.h" +#include "UI/Buttons/UITextButton.h" class NavigationDestination { public: diff --git a/Source/UI/UITextButton.cpp b/Source/UI/Buttons/UITextButton.cpp similarity index 80% rename from Source/UI/UITextButton.cpp rename to Source/UI/Buttons/UITextButton.cpp index 8e4960a..77217c6 100644 --- a/Source/UI/UITextButton.cpp +++ b/Source/UI/Buttons/UITextButton.cpp @@ -1,20 +1,12 @@ -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "UI/FrameFocus.h" -#include "UI/UITextButton.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "UI/Window/FrameFocus.h" +#include "UI/Buttons/UITextButton.h" -#include #include -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } -} - // OFFSET: 0x0086EEB0 -UITextButton::UITextButton(UIWindowContext& windows, UIButtonContext& buttons) - : UIButton(windows, buttons), m_outlineColor(0xFFFFFF), m_value(0) { +UITextButton::UITextButton(UIWindowContext& windows, UIButtonContext& buttons) : UIButton(windows, buttons), m_outlineColor(0xFFFFFF), m_value(0) { } // OFFSET: 0x00874690 @@ -23,14 +15,7 @@ UITextButton::~UITextButton() = default; // OFFSET: 0x0087C590 // FUNCTION: fn_11254 -void UITextButton::Configure( - const char* text, - std::uint32_t color, - int family, - int height, - unsigned char outline, - unsigned char underline -) { +void UITextButton::Configure(const char* text, std::uint32_t color, int family, int height, unsigned char outline, unsigned char underline) { this->label = text; this->m_text = this->label; this->m_normalColor = this->m_hoverColor = this->m_color = color; @@ -39,10 +24,10 @@ void UITextButton::Configure( this->m_outline = outline; this->m_underline = underline; const auto extent = static_cast(height) * static_cast(std::strlen(text)); - const int width = std::bit_cast((extent >> 1) + 4u * outline + 12u); - this->Resize(width, Add(height, 2)); - this->Slot15(width, Add(height, 2)); - this->Slot22(width, Add(height, 2)); + const int width = static_cast(extent / 2 + 4u * outline + 12u); + this->Resize(width, height + 2); + this->Slot15(width, height + 2); + this->Slot22(width, height + 2); } // OFFSET: 0x0088F820 @@ -80,7 +65,7 @@ void UITextButton::Paint() { } if (this->m_underline != 0) { - this->FillRegion(0, Add(this->geometry.height, -1), this->geometry.width, 1, this->m_color); + this->FillRegion(0, (this->geometry.height - 1), this->geometry.width, 1, this->m_color); } } @@ -105,7 +90,7 @@ void UITextButton::Slot27(int x, int y) { // FUNCTION: fn_11461 void UITextButton::Slot28(int x, int y) { if (this->parent) { - static_cast(this->parent)->Slot28(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot28((x + this->geometry.x), (y + this->geometry.y)); } UIButton::Slot28(x, y); diff --git a/Source/UI/UITextButton.h b/Source/UI/Buttons/UITextButton.h similarity index 74% rename from Source/UI/UITextButton.h rename to Source/UI/Buttons/UITextButton.h index b4206a8..ff8bf6e 100644 --- a/Source/UI/UITextButton.h +++ b/Source/UI/Buttons/UITextButton.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_UI_UITEXTBUTTON_H -#define RAGNAROK_SOURCE_UI_UITEXTBUTTON_H +#ifndef RAGNAROK_SOURCE_UI_BUTTONS_UITEXTBUTTON_H +#define RAGNAROK_SOURCE_UI_BUTTONS_UITEXTBUTTON_H -#include "UI/UIButton.h" +#include "UI/Buttons/UIButton.h" #include -// Original UITextButton, 248-byte x86 value before source owner pointers. class UITextButton : public UIButton { friend class UITextViewer; friend class UIMessageBox; @@ -20,14 +19,7 @@ public: void Slot32(int x, int y) override; void Slot33(int x, int y) override; void Slot35(int value) override; - void Configure( - const char* text, - std::uint32_t color, - int family, - int height, - unsigned char outline, - unsigned char underline - ); + void Configure(const char* text, std::uint32_t color, int family, int height, unsigned char outline, unsigned char underline); protected: /* 00B4 */ std::uint32_t m_color; diff --git a/Source/UI/ChatNotifications.cpp b/Source/UI/Chat/ChatNotifications.cpp similarity index 69% rename from Source/UI/ChatNotifications.cpp rename to Source/UI/Chat/ChatNotifications.cpp index 4b92ae4..087e68e 100644 --- a/Source/UI/ChatNotifications.cpp +++ b/Source/UI/Chat/ChatNotifications.cpp @@ -1,14 +1,14 @@ -#include "UI/ChatNotifications.h" -#include "UI/ShortcutVisibility.h" -#include "UI/TextWrapping.h" -#include "UI/UIWindow.h" +#include "UI/Chat/ChatNotifications.h" +#include "UI/Shortcuts/ShortcutVisibility.h" +#include "UI/Text/TextWrapping.h" +#include "UI/Window/UIWindow.h" #include #include // OFFSET: 0x00AA9100 // FUNCTION: fn_17253 -// Complete kind-1/19 branches. + void ChatNotifications::Text(const char* text, std::uint32_t color, const char* extra, int value, bool alternate) { if (this->restricted != 0 && !this->allowsRestricted) { return; @@ -20,16 +20,15 @@ void ChatNotifications::Text(const char* text, std::uint32_t color, const char* if (this->chat) { if (std::strcmp(text, "No Msg") != 0 && std::strcmp(text, "NO MSG") != 0) { - this->chat->SendMsg( - nullptr, alternate ? 115 : 37, reinterpret_cast(text), color, - reinterpret_cast(extra), value - ); + this->chat->SendMsg(nullptr, alternate ? 115 : 37, reinterpret_cast(text), color, reinterpret_cast(extra), value); } + return; } std::vector lines; WrapPlainText(text, lines, 94, this->codePage, this->inlineCharset); + for (const auto& line : lines) { this->queued.push_back({line, color}); } @@ -37,7 +36,7 @@ void ChatNotifications::Text(const char* text, std::uint32_t color, const char* // OFFSET: 0x00AA9100 // FUNCTION: fn_17253 -// Complete kind-3 branch. + void ChatNotifications::Refresh() { this->shortcuts.Show(1); if (this->chat) { diff --git a/Source/UI/ChatNotifications.h b/Source/UI/Chat/ChatNotifications.h similarity index 63% rename from Source/UI/ChatNotifications.h rename to Source/UI/Chat/ChatNotifications.h index 5951e4d..80576c5 100644 --- a/Source/UI/ChatNotifications.h +++ b/Source/UI/Chat/ChatNotifications.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_CHATNOTIFICATIONS_H -#define RAGNAROK_SOURCE_UI_CHATNOTIFICATIONS_H +#ifndef RAGNAROK_SOURCE_UI_CHAT_CHATNOTIFICATIONS_H +#define RAGNAROK_SOURCE_UI_CHAT_CHATNOTIFICATIONS_H #include #include @@ -8,14 +8,11 @@ class UIWindow; struct ShortcutVisibility; -// Queued chat message records: string followed by a 32-bit color. struct QueuedChatNotification { std::string text; std::uint32_t color; }; -// Complete kind-1/19 text and kind-3 refresh branches of UIWindowMgr's message -// dispatcher. Other dispatcher kinds belong to their corresponding owners. struct ChatNotifications { UIWindow* const& chat; std::list& queued; diff --git a/Source/UI/ChatSuggestions.cpp b/Source/UI/Chat/ChatSuggestions.cpp similarity index 92% rename from Source/UI/ChatSuggestions.cpp rename to Source/UI/Chat/ChatSuggestions.cpp index 0dbe356..dc3ec63 100644 --- a/Source/UI/ChatSuggestions.cpp +++ b/Source/UI/Chat/ChatSuggestions.cpp @@ -1,10 +1,10 @@ -#include "UI/ChatSuggestions.h" -#include "UI/InputFocus.h" -#include "UI/ItemTagRetirement.h" -#include "UI/UIEditCtrl.h" -#include "UI/UIWindow.h" -#include "UI/WindowCoordinates.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Chat/ChatSuggestions.h" +#include "UI/Window/InputFocus.h" +#include "UI/Edit/ItemTagRetirement.h" +#include "UI/Edit/UIEditCtrl.h" +#include "UI/Window/UIWindow.h" +#include "UI/Layout/WindowCoordinates.h" +#include "UI/Window/WindowManagerWindows.h" // OFFSET: 0x0091E7E0 // FUNCTION: fn_12628 @@ -59,6 +59,7 @@ void ChatHeaderLayout::Apply() { (*this->buttons[2])->Move(-100, -100); UIWindow* button = *this->buttons[3]; button->Move(this->width - button->geometry.width - 2, 4); + return; } @@ -66,6 +67,7 @@ void ChatHeaderLayout::Apply() { for (UIWindow** button : this->buttons) { (*button)->Move(-100, -100); } + return; } @@ -96,8 +98,7 @@ void ChatRowLayout::Resize(int count) { chat.geometry.unknown_0030 = static_cast(rowCount); chat.Invalidate(); const int previousHeight = chat.geometry.height; - const int height = - rowCount == 0 ? this->input.inputHeight : this->input.inputHeight + (rowCount + 3) * 14 + this->headerHeight; + const int height = rowCount == 0 ? this->input.inputHeight : this->input.inputHeight + (rowCount + 3) * 14 + this->headerHeight; chat.Resize(chat.geometry.width, height); chat.Move(chat.geometry.x, chat.geometry.y - height + previousHeight); @@ -107,6 +108,7 @@ void ChatRowLayout::Resize(int count) { row->Resize(chat.geometry.width - 8, height - this->headerHeight - this->input.inputHeight - 4); this->rows[index]->Invalidate(); row = this->rows[index]; + if (index == static_cast(this->selected)) { row->Move(5, this->headerHeight + 2); } else { @@ -136,7 +138,6 @@ void ChatRowLayout::Resize(int count) { this->headerChild->Move(-100, -100); } - // These three positions are snapshotted together before the callbacks. const int base = chat.geometry.height - this->input.inputHeight; const int firstY = base + 3; const int lastY = base + 7; @@ -182,7 +183,7 @@ void ChatInputFocus::Toggle() { // OFFSET: 0x00AA4730 // FUNCTION: fn_17222 -// Outside-click suggestion branch of mouse message dispatch. + void ChatInputFocus::DismissOutside(ChatSuggestions& suggestions, UIWindow* companion, int button, int x, int y) { if (button != 1 || !suggestions.Visible()) { return; @@ -202,6 +203,7 @@ void ChatInputFocus::DismissOutside(ChatSuggestions& suggestions, UIWindow* comp if (this->secondary) { this->secondary->SetText(""); } + this->Toggle(); } } diff --git a/Source/UI/Chat/ChatSuggestions.h b/Source/UI/Chat/ChatSuggestions.h new file mode 100644 index 0000000..6c3ab61 --- /dev/null +++ b/Source/UI/Chat/ChatSuggestions.h @@ -0,0 +1,74 @@ +#ifndef RAGNAROK_SOURCE_UI_CHAT_CHATSUGGESTIONS_H +#define RAGNAROK_SOURCE_UI_CHAT_CHATSUGGESTIONS_H + +#include +#include +#include + +class UIWindow; +class WindowManagerWindows; +struct WindowAncestry; +class UIEditCtrl; +struct InputFocus; +struct ItemTagRetirement; + +struct ChatSuggestions { + UIWindow& chat; + UIWindow* const& window; + + bool Visible() const; + + void Show(std::uint8_t visible); +}; + +struct ChatInputLayout { + UIWindow& chat; + const std::uint8_t& open; + const int& inputHeight; + std::array children; + + void Apply(); +}; + +struct ChatHeaderLayout { + const std::uint8_t& enabled; + const std::uint32_t& mode; + const int& width; + std::array buttons; + + void Apply(); +}; + +struct ChatRowLayout { + ChatInputLayout& input; + ChatHeaderLayout& header; + WindowManagerWindows& windows; + WindowAncestry* const& capture; + UIWindow* const& popup26; + const std::vector& rows; + const int& selected; + const int& headerHeight; + const int& headerCellWidth; + UIWindow* const& headerChild; + UIWindow* const& suggestions; + + void Resize(int count); +}; + +struct ChatInputFocus { + ChatInputLayout& layout; + ChatRowLayout& rows; + InputFocus& focus; + std::uint8_t& open; + const std::uint8_t& alternate; + UIEditCtrl* const& primary; + UIEditCtrl* const& secondary; + UIWindow*& pressedRoot; + ItemTagRetirement* const& tags; + + void Toggle(); + + void DismissOutside(ChatSuggestions& suggestions, UIWindow* companion, int button, int x, int y); +}; + +#endif diff --git a/Source/UI/ChatSuggestions.h b/Source/UI/ChatSuggestions.h deleted file mode 100644 index 256cc3f..0000000 --- a/Source/UI/ChatSuggestions.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_CHATSUGGESTIONS_H -#define RAGNAROK_SOURCE_UI_CHATSUGGESTIONS_H - -#include -#include -#include - -class UIWindow; -class WindowManagerWindows; -struct WindowAncestry; -class UIEditCtrl; -struct InputFocus; -struct ItemTagRetirement; - -// Borrowed chat window and its suggestion child at +0x13C. This does not -// replace the chat window's layout, focus-toggle or suggestion-data owners. -struct ChatSuggestions { - UIWindow& chat; - UIWindow* const& window; - - bool Visible() const; - // Show forwards the full byte to the virtual, then moves the child to the - // end of the chat child list. Hide changes visibility without reordering. - void Show(std::uint8_t visible); -}; - -// Borrowed chat children in original movement order: +C0,+BC,+B8,+E0,+E4,+E8. -// Reread geometry and child pointers between virtual Move calls. -struct ChatInputLayout { - UIWindow& chat; - const std::uint8_t& open; - const int& inputHeight; - std::array children; - - void Apply(); -}; - -// Borrowed header buttons +104,+100,+128,+12C; width anchor is chat+108. -struct ChatHeaderLayout { - const std::uint8_t& enabled; - const std::uint32_t& mode; - const int& width; - std::array buttons; - - void Apply(); -}; - -// Chat +F4 row views borrow windows owned by the chat hierarchy. Popup close -// is still the manager's complete close operation, not a substitute callback. -struct ChatRowLayout { - ChatInputLayout& input; - ChatHeaderLayout& header; - WindowManagerWindows& windows; - WindowAncestry* const& capture; - UIWindow* const& popup26; - const std::vector& rows; - const int& selected; - const int& headerHeight; - const int& headerCellWidth; - UIWindow* const& headerChild; - UIWindow* const& suggestions; - - // Counts above 15 become zero; negative counts become 15. Popup close - // precedes capture rejection. Preserve bottom anchoring and final header - // then input layout, even when the shared chat-open byte hides the inputs. - void Resize(int count); -}; - -// Borrowed chat +B4 primary / +BC alternate edits, manager byte flags and -// alternate edit's +144 item-tag owner. The tag parser remains separate. -struct ChatInputFocus { - ChatInputLayout& layout; - ChatRowLayout& rows; - InputFocus& focus; - std::uint8_t& open; - const std::uint8_t& alternate; - UIEditCtrl* const& primary; - UIEditCtrl* const& secondary; - UIWindow*& pressedRoot; - ItemTagRetirement* const& tags; - - // Closing an empty alternate edit hides inputs and clears pressedRoot, - // not input focus. A nonempty alternate edit keeps open/pressedRoot; - // every path still drains the alternate edit's existing tag owner. - void Toggle(); - // Outside-click suggestion check. Both rectangles use - // inclusive endpoints, including a missing companion's zero rectangle. - void DismissOutside(ChatSuggestions& suggestions, UIWindow* companion, int button, int x, int y); -}; - -#endif diff --git a/Source/UI/ColoredText.h b/Source/UI/ColoredText.h deleted file mode 100644 index 143fae7..0000000 --- a/Source/UI/ColoredText.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_COLOREDTEXT_H -#define RAGNAROK_SOURCE_UI_COLOREDTEXT_H - -#include - -class UIWindow; -class FontCache; -struct TextLocale; - -void DrawColoredText( - UIWindow& window, - FontCache& fonts, - const TextLocale& locale, - unsigned short codePage, - int x, - int y, - const char* text, - unsigned bytes, - std::uint32_t& color, - int family, - int height, - bool shadow -); - -void DrawOutlinedText( - UIWindow& window, - FontCache& fonts, - const TextLocale& locale, - int x, - int y, - const char* text, - unsigned bytes, - std::uint32_t color, - std::uint32_t outline, - int family, - int height, - unsigned char bold, - unsigned char italic -); -void DrawOutlinedColoredText( - UIWindow& window, - FontCache& fonts, - const TextLocale& locale, - unsigned short codePage, - int x, - int y, - const char* text, - unsigned bytes, - std::uint32_t& color, - std::uint32_t outline, - int family, - int height, - unsigned char bold -); - -#endif diff --git a/Source/UI/CooldownDrawing.h b/Source/UI/CooldownDrawing.h deleted file mode 100644 index 3d329ed..0000000 --- a/Source/UI/CooldownDrawing.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_COOLDOWNDRAWING_H -#define RAGNAROK_SOURCE_UI_COOLDOWNDRAWING_H - -#include "UI/CooldownState.h" - -#include - -class RenderCommandPool; -class CRenderSystemBase; -struct RenderQueues; - -// Original cooldown owner's two transient command lists (+4 and +16). -// Commands borrow CooldownState::vertices until the renderer consumes them. -struct CooldownDrawing { - std::vector normal; - std::vector reverse; - - void Draw( - int centerX, - int centerY, - int radiusX, - int radiusY, - CooldownState& value, - int limit, - int offsetX, - int offsetY, - const CooldownClock& clock, - RenderCommandPool& pool, - CRenderSystemBase& system - ); - void SubmitNormal(RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd); - void SubmitReverse(RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd); - -private: - void - DrawReverse(CooldownState& value, const CooldownClock& clock, RenderCommandPool& pool, CRenderSystemBase& system); -}; - -#endif diff --git a/Source/UI/CooldownDrawing.cpp b/Source/UI/Cooldowns/CooldownDrawing.cpp similarity index 75% rename from Source/UI/CooldownDrawing.cpp rename to Source/UI/Cooldowns/CooldownDrawing.cpp index 49b4d63..8b61630 100644 --- a/Source/UI/CooldownDrawing.cpp +++ b/Source/UI/Cooldowns/CooldownDrawing.cpp @@ -1,27 +1,14 @@ -#include "Render/RenderCommandPool.h" -#include "Render/RenderQueues.h" +#include "Render/Primitives/RenderCommandPool.h" +#include "Render/Primitives/RenderQueues.h" #include "Render/RenderSystemBase.h" -#include "UI/CooldownDrawing.h" - -#include +#include "UI/Cooldowns/CooldownDrawing.h" namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Subtract(int left, int right) { - return std::bit_cast(static_cast(left) - static_cast(right)); - } - void Submit( - std::vector& commands, - RenderQueues& queues, - bool depthAlpha, - float depthStart, - float depthEnd - ) { + void Submit(std::vector& commands, RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd) { for (RenderCommand* command : commands) { queues.Submit(command, 513, depthAlpha, depthStart, depthEnd); } + commands.clear(); } } @@ -29,48 +16,46 @@ namespace { // OFFSET: 0x00CA66B0 // FUNCTION: fn_20964 void CooldownDrawing::Draw( - int centerX, - int centerY, - int radiusX, - int radiusY, - CooldownState& value, - int limit, - int offsetX, - int offsetY, - const CooldownClock& clock, - RenderCommandPool& pool, - CRenderSystemBase& system + int centerX, int centerY, int radiusX, int radiusY, CooldownState& value, int limit, int offsetX, int offsetY, const CooldownClock& clock, + RenderCommandPool& pool, CRenderSystemBase& system ) { if (value.x <= 0 || value.y <= 0 || (value.color & 0xFF000000u) == 0) { return; } + RenderVertex* vertices = value.vertices; - const float top = static_cast(Subtract(centerY, radiusY)); - const float bottom = static_cast(Add(centerY, radiusY)); + const float top = static_cast((centerY - radiusY)); + const float bottom = static_cast((centerY + radiusY)); + vertices[1].x = vertices[23].x = static_cast(centerX); vertices[1].y = vertices[23].y = top; vertices[11].x = vertices[13].x = static_cast(centerX); vertices[11].y = vertices[13].y = bottom; + for (unsigned i = 0; i < 24; ++i) { RenderVertex& vertex = vertices[i]; if (i % 3 == 0) { vertex.x = static_cast(centerX); vertex.y = static_cast(centerY); } + vertex.z = 0.000001f; vertex.rhw = 0.999999f; vertex.diffuse = value.color; vertex.u = vertex.v = 0; } + vertices[5].y = vertices[7].y = vertices[17].y = vertices[19].y = static_cast(centerY); vertices[2].y = vertices[4].y = vertices[20].y = vertices[22].y = top; vertices[8].y = vertices[10].y = vertices[14].y = vertices[16].y = bottom; - const float right = static_cast(Add(centerX, radiusX)); - const float left = static_cast(Subtract(centerX, radiusX)); + const float right = static_cast((centerX + radiusX)); + const float left = static_cast((centerX - radiusX)); const bool reversed = value.reverse != 0; + for (unsigned i : {2u, 4u, 5u, 7u, 8u, 10u}) { vertices[i].x = reversed ? right : left; } + for (unsigned i : {14u, 16u, 17u, 19u, 20u, 22u}) { vertices[i].x = reversed ? left : right; } @@ -83,14 +68,16 @@ void CooldownDrawing::Draw( value.AddEdge(5, vertices[reversed ? 16 : 8].y, radiusY, 0); value.AddEdge(6, vertices[reversed ? 19 : 5].y, radiusY, 0); value.AddEdge(7, vertices[reversed ? 22 : 2].x, radiusX, 1); + if (reversed) { this->DrawReverse(value, clock, pool, system); return; } + if (value.duration == 0) { return; } - // The destination is chosen from the old segment, before Update changes it. + const unsigned previous = value.segment; if (previous < 8) { const float position = value.Update(clock); @@ -101,31 +88,31 @@ void CooldownDrawing::Draw( vertex.y = position; } } + if ((limit != 0 ? limit : 6) <= value.y) { return; } + RenderCommand* command = pool.Acquire(); command->texture = system.BackBufferTexture(); command->vertices = vertices; command->vertexCount = value.vertexCount; + for (RenderVertex& vertex : value.vertices) { - vertex.x = static_cast(Add(Add(offsetX, value.x), 12)) + vertex.x; - vertex.y = static_cast(Add(Add(offsetY, value.y), 12)) + vertex.y; + vertex.x = static_cast(((offsetX + value.x) + 12)) + vertex.x; + vertex.y = static_cast(((offsetY + value.y) + 12)) + vertex.y; } + this->normal.push_back(command); } // OFFSET: 0x00CA6C00 // FUNCTION: fn_20965 -void CooldownDrawing::DrawReverse( - CooldownState& value, - const CooldownClock& clock, - RenderCommandPool& pool, - CRenderSystemBase& system -) { +void CooldownDrawing::DrawReverse(CooldownState& value, const CooldownClock& clock, RenderCommandPool& pool, CRenderSystemBase& system) { if (value.duration == 0) { return; } + const unsigned previous = value.segment; if (previous < 8) { const float position = value.Update(clock); @@ -135,19 +122,23 @@ void CooldownDrawing::DrawReverse( } else { vertex.y = position; } + if (previous < 7 && value.segment != previous) { value.vertices[5 + 3 * previous] = value.vertices[4 + 3 * previous]; vertex = value.vertices[4 + 3 * previous]; } } + RenderCommand* command = pool.Acquire(); command->texture = system.BackBufferTexture(); command->vertices = value.vertices; command->vertexCount = value.vertexCount; + for (RenderVertex& vertex : value.vertices) { vertex.x = static_cast(value.x) + vertex.x; vertex.y = static_cast(value.y) + vertex.y; } + this->reverse.push_back(command); } diff --git a/Source/UI/Cooldowns/CooldownDrawing.h b/Source/UI/Cooldowns/CooldownDrawing.h new file mode 100644 index 0000000..1874287 --- /dev/null +++ b/Source/UI/Cooldowns/CooldownDrawing.h @@ -0,0 +1,27 @@ +#ifndef RAGNAROK_SOURCE_UI_COOLDOWNS_COOLDOWNDRAWING_H +#define RAGNAROK_SOURCE_UI_COOLDOWNS_COOLDOWNDRAWING_H + +#include "UI/Cooldowns/CooldownState.h" + +#include + +class RenderCommandPool; +class CRenderSystemBase; +struct RenderQueues; + +struct CooldownDrawing { + std::vector normal; + std::vector reverse; + + void Draw( + int centerX, int centerY, int radiusX, int radiusY, CooldownState& value, int limit, int offsetX, int offsetY, const CooldownClock& clock, + RenderCommandPool& pool, CRenderSystemBase& system + ); + void SubmitNormal(RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd); + void SubmitReverse(RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd); + +private: + void DrawReverse(CooldownState& value, const CooldownClock& clock, RenderCommandPool& pool, CRenderSystemBase& system); +}; + +#endif diff --git a/Source/UI/CooldownOwner.cpp b/Source/UI/Cooldowns/CooldownOwner.cpp similarity index 87% rename from Source/UI/CooldownOwner.cpp rename to Source/UI/Cooldowns/CooldownOwner.cpp index 37666c2..439bdd1 100644 --- a/Source/UI/CooldownOwner.cpp +++ b/Source/UI/Cooldowns/CooldownOwner.cpp @@ -1,4 +1,4 @@ -#include "UI/CooldownOwner.h" +#include "UI/Cooldowns/CooldownOwner.h" // OFFSET: 0x00CA64C0 // FUNCTION: fn_20960 @@ -20,8 +20,6 @@ CooldownOwner::~CooldownOwner() { // OFFSET: 0x00CA61A0 // FUNCTION: fn_20957 void CooldownOwner::Register(unsigned id, std::uint32_t duration, std::uint32_t start, std::uint32_t elapsed) { - // Original erases the old value (including its edge tree) before creating - // a new reverse cooldown; replacing only the timer fields retains stale edges. this->m_values.erase(id); this->m_values.emplace(id, CooldownState(0, 0, 0, duration, start, elapsed, 1)); } diff --git a/Source/UI/CooldownOwner.h b/Source/UI/Cooldowns/CooldownOwner.h similarity index 64% rename from Source/UI/CooldownOwner.h rename to Source/UI/Cooldowns/CooldownOwner.h index 07d7b6f..c4d1a30 100644 --- a/Source/UI/CooldownOwner.h +++ b/Source/UI/Cooldowns/CooldownOwner.h @@ -1,12 +1,10 @@ -#ifndef RAGNAROK_SOURCE_UI_COOLDOWNOWNER_H -#define RAGNAROK_SOURCE_UI_COOLDOWNOWNER_H +#ifndef RAGNAROK_SOURCE_UI_COOLDOWNS_COOLDOWNOWNER_H +#define RAGNAROK_SOURCE_UI_COOLDOWNS_COOLDOWNOWNER_H -#include "UI/CooldownDrawing.h" +#include "UI/Cooldowns/CooldownDrawing.h" #include -// Singleton value, 36 bytes on x86. Global application -// creation/destruction remain the startup owner's responsibility. class CooldownOwner { public: CooldownOwner(); @@ -14,7 +12,6 @@ public: void Register(unsigned id, std::uint32_t duration, std::uint32_t start, std::uint32_t elapsed); void ClearReverseCommands(); - // Source accessors for original direct map/list access by render callers. CooldownState* Find(unsigned id); void Erase(unsigned id); CooldownDrawing& Drawing() { diff --git a/Source/UI/CooldownState.cpp b/Source/UI/Cooldowns/CooldownState.cpp similarity index 76% rename from Source/UI/CooldownState.cpp rename to Source/UI/Cooldowns/CooldownState.cpp index f1056ed..42223a8 100644 --- a/Source/UI/CooldownState.cpp +++ b/Source/UI/Cooldowns/CooldownState.cpp @@ -1,12 +1,9 @@ -#include "UI/CooldownState.h" +#include "UI/Cooldowns/CooldownState.h" -#include #include #include #include -// clang-format off -#include -// clang-format on +#include std::uint32_t CooldownClock::Now() const { return this->restricted ? this->serverTick : timeGetTime(); @@ -15,25 +12,20 @@ std::uint32_t CooldownClock::Now() const { // OFFSET: 0x00CA4F30 // FUNCTION: fn_20946 CooldownState::CooldownState( - int slotValue, - int xValue, - int yValue, - std::uint32_t durationValue, - std::uint32_t startValue, - std::uint32_t elapsedValue, - int reverseValue + int slotValue, int xValue, int yValue, std::uint32_t durationValue, std::uint32_t startValue, std::uint32_t elapsedValue, int reverseValue ) - : segment(0), vertexCount(24), angle(0), duration(durationValue), start(startValue), elapsed(elapsedValue), - finalMinute(0), reverse(reverseValue), x(xValue), y(yValue), slot(slotValue), - color(reverseValue != 0 ? 0xAAFFFFFFu : 0xAA000000u) { + : segment(0), vertexCount(24), angle(0), duration(durationValue), start(startValue), elapsed(elapsedValue), finalMinute(0), reverse(reverseValue), + x(xValue), y(yValue), slot(slotValue), color(reverseValue != 0 ? 0xAAFFFFFFu : 0xAA000000u) { this->ClearEdges(); std::memset(this->vertices, 0, sizeof(this->vertices)); } + // OFFSET: 0x00CA59C0 // FUNCTION: fn_20951 void CooldownState::ClearEdges() { this->edges.clear(); } + // OFFSET: 0x00CA54E0 // FUNCTION: fn_20949 void CooldownState::AddEdge(unsigned key, float origin, int radius, unsigned char increasing) { @@ -54,10 +46,9 @@ float CooldownState::Update(const CooldownClock& clock) { this->color = 0xAAFF6633u; progress = this->elapsed; } + if (this->duration != 0) { - this->angle = progress != 0 - ? static_cast((static_cast(progress) / static_cast(this->duration)) * 360.0) - : 0.0f; + this->angle = progress != 0 ? static_cast((static_cast(progress) / static_cast(this->duration)) * 360.0) : 0.0f; const float value = this->angle; if (value >= 0 && value < 45) { this->segment = 0; @@ -76,19 +67,21 @@ float CooldownState::Update(const CooldownClock& clock) { } else { this->segment = 7; } + this->vertexCount = this->reverse != 0 ? 3 * (this->segment + 1) : 24 - 3 * this->segment; this->angle = 90.0f - (this->angle - static_cast(this->segment) * 45.0f); } - // Original requires all selected edge records; missing key dereferences the - // tree sentinel's uninitialized value, not a fabricated default edge. + auto entry = this->edges.find(this->segment); CooldownEdge& edge = entry->second; if (this->duration <= progress) { return edge.origin; } + const float radians = this->angle * 0.017453292f; const float tangent = static_cast(std::tan(static_cast(radians))); const float distance = static_cast(edge.radius) / tangent; edge.current = edge.increasing != 0 ? edge.origin + distance : edge.origin - distance; + return edge.current; } diff --git a/Source/UI/CooldownState.h b/Source/UI/Cooldowns/CooldownState.h similarity index 66% rename from Source/UI/CooldownState.h rename to Source/UI/Cooldowns/CooldownState.h index 03a666d..5f19774 100644 --- a/Source/UI/CooldownState.h +++ b/Source/UI/Cooldowns/CooldownState.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_COOLDOWNSTATE_H -#define RAGNAROK_SOURCE_UI_COOLDOWNSTATE_H +#ifndef RAGNAROK_SOURCE_UI_COOLDOWNS_COOLDOWNSTATE_H +#define RAGNAROK_SOURCE_UI_COOLDOWNS_COOLDOWNSTATE_H -#include "Render/RenderPrimitive.h" +#include "Render/Primitives/RenderPrimitive.h" #include @@ -12,15 +12,12 @@ struct CooldownEdge { unsigned char increasing; }; -// Original clock chooses the replay server tick only in restricted mode. struct CooldownClock { const bool& restricted; const std::uint32_t& serverTick; std::uint32_t Now() const; }; -// Original824-byte radial cooldown value, copied into the shortcut lists. -// Geometry/renderer submission is owned by the separate drawing operation. struct CooldownState { /* 0000 */ std::map edges; /* 0008 */ unsigned segment; @@ -37,15 +34,7 @@ struct CooldownState { /* 0330 */ int slot; /* 0334 */ std::uint32_t color; - CooldownState( - int slot, - int x, - int y, - std::uint32_t duration, - std::uint32_t start, - std::uint32_t elapsed, - int reverse - ); + CooldownState(int slot, int x, int y, std::uint32_t duration, std::uint32_t start, std::uint32_t elapsed, int reverse); void ClearEdges(); void AddEdge(unsigned segment, float origin, int radius, unsigned char increasing); float Update(const CooldownClock& clock); diff --git a/Source/UI/EditPainting.cpp b/Source/UI/Edit/EditPainting.cpp similarity index 61% rename from Source/UI/EditPainting.cpp rename to Source/UI/Edit/EditPainting.cpp index 1f22198..257b13f 100644 --- a/Source/UI/EditPainting.cpp +++ b/Source/UI/Edit/EditPainting.cpp @@ -1,52 +1,41 @@ -#include "Client/InputCharset.h" -#include "Client/TextInputBuffer.h" -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "Resource/BitmapImage.h" -#include "UI/EditPainting.h" -#include "UI/EditViewport.h" -#include "UI/UIWindow.h" +#include "Client/Input/InputCharset.h" +#include "Client/Input/TextInputBuffer.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "Resource/Bitmap/BitmapImage.h" +#include "UI/Edit/EditPainting.h" +#include "UI/Edit/EditViewport.h" +#include "UI/Window/UIWindow.h" #include -#include #include -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } -} - // OFFSET: 0x00856980 // FUNCTION: fn_10755 void EditPainting::Draw() { TextContext context(this->surface, this->fonts, this->locale); context.SetFont(0, 12, 0, 0); - const auto measure = [&](const char* text, int bytes) { - return context.Measure(text, bytes ? bytes : static_cast(std::strlen(text))).cx; - }; + const auto measure = [&](const char* text, int bytes) { return context.Measure(text, bytes ? bytes : static_cast(std::strlen(text))).cx; }; int x = 3; if (this->invalidatesParent == 0 && this->firstVisible != 0) { - x = Add(3, -measure(this->text.c_str(), this->firstVisible)); + x = (3 - measure(this->text.c_str(), this->firstVisible)); } const auto draw = [&](const std::string& value) { - const bool placeholder = - this->alternate && !this->focused && this->placeholderEnabled && this->secondColor == 0xFFFFFFFFu; + const bool placeholder = this->alternate && !this->focused && this->placeholderEnabled && this->secondColor == 0xFFFFFFFFu; context.SetColor(placeholder ? this->placeholderColor : this->color); const std::string& displayed = placeholder && value.empty() ? *this->placeholder : value; context.Draw(x, this->y, displayed.c_str(), static_cast(displayed.size())); if (this->secondColor != 0xFFFFFFFFu) { context.SetColor(this->secondColor); - context.Draw(Add(x, -1), this->y, value.c_str(), static_cast(value.size())); + context.Draw((x - 1), this->y, value.c_str(), static_cast(value.size())); } }; const auto highlight = [&](int left, int extent) { - // Highlight helper samples theme pixel (6, 2). const int start = std::max(left, 3); - const int adjusted = left < 3 ? Add(extent, Add(left, -3)) : extent; + const int adjusted = left < 3 ? (extent + (left - 3)) : extent; if (start < this->width && adjusted > 0) { std::uint32_t pixel = 0x00FF0000u; @@ -56,7 +45,7 @@ void EditPainting::Draw() { } const std::uint32_t color = ((pixel >> 16) & 255) | (pixel & 0xFF00) | ((pixel & 255) << 16); - RECT rectangle{start, 0, std::min(Add(start, adjusted), this->width), this->height}; + RECT rectangle{start, 0, std::min((start + adjusted), this->width), this->height}; this->surface.Fill(&rectangle, color); } }; @@ -65,15 +54,15 @@ void EditPainting::Draw() { return; } - int left = Add(offset, this->absoluteX); - int top = Add(Add(this->height, 6), this->absoluteY); + int left = (offset + this->absoluteX); + int top = ((this->height + 6) + this->absoluteY); - if (Add(window->geometry.width, left) > this->screenWidth) { - left = Add(this->screenWidth, -window->geometry.width); + if ((window->geometry.width + left) > this->screenWidth) { + left = (this->screenWidth - window->geometry.width); } - if (Add(window->geometry.height, top) > this->screenHeight) { - top = Add(Add(Add(top, -12), -this->height), -window->geometry.height); + if ((window->geometry.height + top) > this->screenHeight) { + top = (((top - 12) - this->height) - window->geometry.height); } window->Move(left, top); @@ -100,26 +89,23 @@ void EditPainting::Draw() { const int right = end == 0 ? 0 : measure(display.c_str(), static_cast(end)); if (this->input.cursor != this->input.anchor) { - highlight(Add(x, left), Add(right, -left)); + highlight((x + left), (right - left)); draw(display); } else if (this->candidateCursor != 0) { moveCandidate(this->candidateWindow, left); moveCandidate(this->readingWindow, right); if (((this->tick / 500u) & 1u) == 0) { - highlight(Add(x, left), std::max(Add(right, -left), 2)); + highlight((x + left), std::max((right - left), 2)); } draw(display); } else { draw(display); - if ( - ((this->tick / 500u) & 1u) == 0 && - (this->alternate ? this->caretEnabled : (!this->chatInputFocused || this->caretEnabled)) - ) { + if (((this->tick / 500u) & 1u) == 0 && (this->alternate ? this->caretEnabled : (!this->chatInputFocused || this->caretEnabled))) { context.SetColor(this->color); - context.Draw(Add(Add(x, left), -2), this->y, "|", 1); + context.Draw(((x + left) - 2), this->y, "|", 1); } } } else { @@ -136,9 +122,7 @@ void EditPainting::Draw() { } } - if (std::any_of(this->linkWindows.begin(), this->linkWindows.end(), [](const UIWindow* window) { - return window->geometry.id == 438; - })) { + if (std::any_of(this->linkWindows.begin(), this->linkWindows.end(), [](const UIWindow* window) { return window->geometry.id == 438; })) { this->links.Update(); } } diff --git a/Source/UI/EditPainting.h b/Source/UI/Edit/EditPainting.h similarity index 75% rename from Source/UI/EditPainting.h rename to Source/UI/Edit/EditPainting.h index 2d065b1..f16c1f3 100644 --- a/Source/UI/EditPainting.h +++ b/Source/UI/Edit/EditPainting.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_EDITPAINTING_H -#define RAGNAROK_SOURCE_UI_EDITPAINTING_H +#ifndef RAGNAROK_SOURCE_UI_EDIT_EDITPAINTING_H +#define RAGNAROK_SOURCE_UI_EDIT_EDITPAINTING_H #include #include @@ -14,8 +14,6 @@ struct InputCharset; struct EditViewport; struct BitmapImage; -// Actual inline-link positioning mutates child windows and input selection. -// The concrete link owner must implement it; no default implementation exists. class EditLinkLayout { public: virtual void Update() = 0; @@ -38,7 +36,7 @@ struct EditPainting { const bool& chatInputFocused; const bool& caretEnabled; const std::uint32_t& tick; - const int& candidateCursor; // input owner +0x80 + const int& candidateCursor; const int& width; const int& height; const int& screenWidth; @@ -57,8 +55,7 @@ struct EditPainting { const int& absoluteY; const std::list& linkWindows; EditLinkLayout& links; - // Original UIEditCtrl4 painter shares selection/candidate drawing but uses - // its own prefix, placeholder, and caret policy. + bool alternate = false; const std::string* placeholder = nullptr; std::uint32_t placeholderColor = 0; diff --git a/Source/UI/EditTextState.cpp b/Source/UI/Edit/EditTextState.cpp similarity index 95% rename from Source/UI/EditTextState.cpp rename to Source/UI/Edit/EditTextState.cpp index b732884..1ab4426 100644 --- a/Source/UI/EditTextState.cpp +++ b/Source/UI/Edit/EditTextState.cpp @@ -1,5 +1,5 @@ -#include "Client/TextInputBuffer.h" -#include "UI/EditTextState.h" +#include "Client/Input/TextInputBuffer.h" +#include "UI/Edit/EditTextState.h" #include diff --git a/Source/UI/Edit/EditTextState.h b/Source/UI/Edit/EditTextState.h new file mode 100644 index 0000000..a186736 --- /dev/null +++ b/Source/UI/Edit/EditTextState.h @@ -0,0 +1,24 @@ +#ifndef RAGNAROK_SOURCE_UI_EDIT_EDITTEXTSTATE_H +#define RAGNAROK_SOURCE_UI_EDIT_EDITTEXTSTATE_H + +#include +#include + +struct TextInputBuffer; + +struct EditTextState { + std::string& text; + int& anchor; + int& cursor; + const int& maximum; + const bool& focused; + TextInputBuffer& input; + const UINT& codePage; + + void SetText(const char* value); + void Trim(); + void SelectAll(); + int Length() const; +}; + +#endif diff --git a/Source/UI/Edit/EditViewport.cpp b/Source/UI/Edit/EditViewport.cpp new file mode 100644 index 0000000..ea8d231 --- /dev/null +++ b/Source/UI/Edit/EditViewport.cpp @@ -0,0 +1,67 @@ +#include "Client/Input/TextInputBuffer.h" +#include "Render/Text/TextContext.h" +#include "UI/Edit/EditTextState.h" +#include "UI/Edit/EditViewport.h" + +#include +#include +#include + +// OFFSET: 0x00862FB0 +// FUNCTION: fn_10905 +void EditViewport::Synchronize() { + const int previousCursor = this->cursor; + this->input.CopyDisplayText(this->text); + this->input.Selection(this->anchor, this->cursor); + this->state.Trim(); + const auto length = static_cast(this->text.size()); + bool clamped = false; + + if (static_cast(this->cursor) > length || static_cast(this->anchor) > length) { + this->anchor = static_cast(std::min(static_cast(this->anchor), length)); + this->cursor = static_cast(std::min(static_cast(this->cursor), length)); + this->input.Select(this->anchor, this->cursor); + clamped = true; + } + + if (this->cursor == 0) { + this->firstVisible = 0; + return; + } + + const auto selection = + static_cast(std::max(this->input.cursor, this->input.anchor)) - static_cast(std::min(this->input.cursor, this->input.anchor)); + + if (selection >= length) { + this->firstVisible = 0; + } + + TextContext context(this->surface, this->fonts, this->locale); + context.SetFont(0, 12, 0, 0); + const auto measure = [&](const char* text, unsigned bytes) { return context.Measure(text, static_cast(bytes ? bytes : std::strlen(text))).cx; }; + const int available = this->width - 7; + + if (this->cursor > previousCursor || clamped) { + const int before = this->firstVisible == 0 ? 0 : measure(this->text.c_str(), static_cast(this->firstVisible)); + const int position = measure(this->text.c_str(), static_cast(this->cursor)) + 3 - before; + + if (position > available) { + const char* end = this->text.c_str() + this->text.size(); + const char* next = CharNextExA(static_cast(this->codePage), this->text.c_str(), 0); + + while (measure(next, 0) + 3 > available && next < end) { + next = CharNextExA(static_cast(this->codePage), next, 0); + } + + const auto tail = static_cast(std::strlen(next)); + const int candidate = this->firstVisible + this->cursor - previousCursor; + this->firstVisible = static_cast(std::min(static_cast(this->cursor) - tail, static_cast(candidate))); + } + } else if (this->cursor < previousCursor) { + if (measure(this->text.c_str(), static_cast(this->cursor)) + 3 < available && this->firstVisible > this->cursor) { + this->firstVisible += this->cursor - previousCursor; + } + + this->firstVisible = std::max(this->firstVisible, 0); + } +} diff --git a/Source/UI/EditViewport.h b/Source/UI/Edit/EditViewport.h similarity index 81% rename from Source/UI/EditViewport.h rename to Source/UI/Edit/EditViewport.h index c56b06e..24e6ab6 100644 --- a/Source/UI/EditViewport.h +++ b/Source/UI/Edit/EditViewport.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_EDITVIEWPORT_H -#define RAGNAROK_SOURCE_UI_EDITVIEWPORT_H +#ifndef RAGNAROK_SOURCE_UI_EDIT_EDITVIEWPORT_H +#define RAGNAROK_SOURCE_UI_EDIT_EDITVIEWPORT_H #include #include diff --git a/Source/UI/ItemTagRetirement.cpp b/Source/UI/Edit/ItemTagRetirement.cpp similarity index 82% rename from Source/UI/ItemTagRetirement.cpp rename to Source/UI/Edit/ItemTagRetirement.cpp index 7c7b211..163696d 100644 --- a/Source/UI/ItemTagRetirement.cpp +++ b/Source/UI/Edit/ItemTagRetirement.cpp @@ -1,6 +1,6 @@ -#include "UI/InputFocus.h" -#include "UI/ItemTagRetirement.h" -#include "UI/UIWindow.h" +#include "UI/Window/InputFocus.h" +#include "UI/Edit/ItemTagRetirement.h" +#include "UI/Window/UIWindow.h" FocusedItemTagRemoval::FocusedItemTagRemoval(InputFocus& focus) : m_focus(focus) { } diff --git a/Source/UI/ItemTagRetirement.h b/Source/UI/Edit/ItemTagRetirement.h similarity index 58% rename from Source/UI/ItemTagRetirement.h rename to Source/UI/Edit/ItemTagRetirement.h index 5cce002..24f2a4e 100644 --- a/Source/UI/ItemTagRetirement.h +++ b/Source/UI/Edit/ItemTagRetirement.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_ITEMTAGRETIREMENT_H -#define RAGNAROK_SOURCE_UI_ITEMTAGRETIREMENT_H +#ifndef RAGNAROK_SOURCE_UI_EDIT_ITEMTAGRETIREMENT_H +#define RAGNAROK_SOURCE_UI_EDIT_ITEMTAGRETIREMENT_H #include #include @@ -8,16 +8,11 @@ class UIWindow; struct InputFocus; -// UIItemTagCtrl list-node payload is 456 bytes on x86; the child pointer is -// first. The remaining inline bytes are copied as 114 DWORDs during parsing. -// Their interpretation is not required by retirement and remains unrecovered. struct ItemTagRecord { UIWindow* child; std::array unknown_0004; }; -// UIItemTagCtrl virtual slot 60. Derived mail/chat variants choose a different -// removal owner; clearing must retain that dispatch and the current list node. class ItemTagRemoval { public: virtual void Remove(UIWindow* child) = 0; diff --git a/Source/UI/UIEditCtrl.cpp b/Source/UI/Edit/UIEditCtrl.cpp similarity index 76% rename from Source/UI/UIEditCtrl.cpp rename to Source/UI/Edit/UIEditCtrl.cpp index 8bfea16..20e8457 100644 --- a/Source/UI/UIEditCtrl.cpp +++ b/Source/UI/Edit/UIEditCtrl.cpp @@ -1,27 +1,25 @@ -#include "Client/TextInputBuffer.h" +#include "Client/Input/TextInputBuffer.h" #include "Network/TextEncoding.h" -#include "Render/DeviceContext.h" -#include "UI/EditPainting.h" -#include "UI/EditTextState.h" -#include "UI/EditViewport.h" -#include "UI/InputFocus.h" -#include "UI/UIButton.h" -#include "UI/UIEditCtrl.h" -#include "UI/WindowManagerWindows.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "UI/Edit/EditPainting.h" +#include "UI/Edit/EditTextState.h" +#include "UI/Edit/EditViewport.h" +#include "UI/Window/InputFocus.h" +#include "UI/Buttons/UIButton.h" +#include "UI/Edit/UIEditCtrl.h" +#include "UI/Window/WindowManagerWindows.h" #include -#include #include -#include +#include +#include namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } class LinkLayout : public EditLinkLayout { public: explicit LinkLayout(UIEditCtrl& control) : m_control(control) { } + void Update() override { this->m_control.UpdateLinks(); } @@ -34,9 +32,9 @@ namespace { // OFFSET: 0x0084FAE0 // FUNCTION: fn_10663 UIEditCtrl::UIEditCtrl(UIWindowContext& windows, UIEditContext& edit) - : UIWindow(windows, 0), anchor(0), cursor(0), mask(0), maximum(255), flat(1), red(255), green(255), blue(255), - borderRed(0), borderGreen(0), borderBlue(0), textColor(0), secondColor(0xFFFFFFFF), firstVisible(0), textY(0), - invalidatesParent(0), disabled(0), unknown_00F0(0), topPadding(0), preserveInput(0), m_edit(&edit) { + : UIWindow(windows, 0), anchor(0), cursor(0), mask(0), maximum(255), flat(1), red(255), green(255), blue(255), borderRed(0), borderGreen(0), borderBlue(0), + textColor(0), secondColor(0xFFFFFFFF), firstVisible(0), textY(0), invalidatesParent(0), disabled(0), unknown_00F0(0), topPadding(0), preserveInput(0), + m_edit(&edit) { this->text.reserve(255); } @@ -54,27 +52,24 @@ bool UIEditCtrl::Slot05() { // OFFSET: 0x0085CCA0 // FUNCTION: fn_10807 void UIEditCtrl::Paint() { - const auto component = [&](int value) { - return static_cast(this->disabled != 0 && value > 30 ? Add(value, -30) : value); - }; + const auto component = [&](int value) { return static_cast(this->disabled != 0 && value > 30 ? value - 30 : value); }; const unsigned color = component(this->red) | (component(this->green) << 8) | (component(this->blue) << 16); this->textY = 0; if (this->geometry.surface) { if (this->flat == 0) { RECT rectangle{0, 0, this->geometry.width, this->geometry.height}; - const unsigned border = static_cast(this->borderRed) | - (static_cast(this->borderGreen) << 8) | + const unsigned border = static_cast(this->borderRed) | (static_cast(this->borderGreen) << 8) | (static_cast(this->borderBlue) << 16); this->geometry.surface->Fill(&rectangle, border); - rectangle = {1, 1, Add(this->geometry.width, -1), Add(this->geometry.height, -1)}; + rectangle = {1, 1, this->geometry.width - 1, this->geometry.height - 1}; this->geometry.surface->Fill(&rectangle, color); } else { this->geometry.surface->Fill(nullptr, color); } } - this->textY = Add(this->topPadding, 2); + this->textY = this->topPadding + 2; this->PaintText(); } @@ -116,8 +111,8 @@ void UIEditCtrl::Slot28(int x, int y) { int left = 10, top = -20; for (const UIWindow* window = this; window; window = static_cast(window->parent)) { - left = Add(left, window->geometry.x); - top = Add(top, window->geometry.y); + left += window->geometry.x; + top += window->geometry.y; } this->m_edit->buttons.services.Tooltip(this->tooltip.c_str(), left, top, -1, false, true); @@ -126,14 +121,7 @@ void UIEditCtrl::Slot28(int x, int y) { // OFFSET: 0x008641C0 // FUNCTION: fn_10914 -int UIEditCtrl::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIEditCtrl::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message == 153) { this->InsertLink(reinterpret_cast(a)); } else if (message == 98 && c > 0) { @@ -181,8 +169,7 @@ void UIEditCtrl::SetText(const char* value) { // FUNCTION: fn_10778 void UIEditCtrl::SelectAll() { const bool focused = this->m_edit->focus.window == this; - EditTextState state{this->text, this->anchor, this->cursor, this->maximum, - focused, this->m_edit->input, g_textCodePage}; + EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage}; state.SelectAll(); } @@ -192,15 +179,9 @@ void UIEditCtrl::PaintText() { this->PaintTextWithPolicy(false, nullptr, 0, false); } -void UIEditCtrl::PaintTextWithPolicy( - bool alternate, - const std::string* placeholder, - std::uint32_t placeholderColor, - bool placeholderEnabled -) { +void UIEditCtrl::PaintTextWithPolicy(bool alternate, const std::string* placeholder, std::uint32_t placeholderColor, bool placeholderEnabled) { const bool focused = this->m_edit->focus.window == this; - EditTextState state{this->text, this->anchor, this->cursor, this->maximum, - focused, this->m_edit->input, g_textCodePage}; + EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage}; EditViewport viewport{ this->text, this->anchor, @@ -218,8 +199,8 @@ void UIEditCtrl::PaintTextWithPolicy( int left = 0, top = 0; for (const UIWindow* window = this; window; window = static_cast(window->parent)) { - left = Add(left, window->geometry.x); - top = Add(top, window->geometry.y); + left += window->geometry.x; + top += window->geometry.y; } const bool chat = this->m_edit->input.chatInput == this || this->m_edit->otherChatInput == this; @@ -259,6 +240,7 @@ void UIEditCtrl::PaintTextWithPolicy( this->links, layout }; + painting.alternate = alternate; painting.placeholder = placeholder; painting.placeholderColor = placeholderColor; @@ -270,8 +252,7 @@ void UIEditCtrl::PaintTextWithPolicy( // FUNCTION: fn_10905 void UIEditCtrl::Synchronize() { const bool focused = this->m_edit->focus.window == this; - EditTextState state{this->text, this->anchor, this->cursor, this->maximum, - focused, this->m_edit->input, g_textCodePage}; + EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage}; EditViewport viewport{ this->text, this->anchor, @@ -292,8 +273,7 @@ void UIEditCtrl::Synchronize() { // FUNCTION: fn_10959 void UIEditCtrl::Trim() { const bool focused = this->m_edit->focus.window == this; - EditTextState state{this->text, this->anchor, this->cursor, this->maximum, - focused, this->m_edit->input, g_textCodePage}; + EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage}; state.Trim(); } diff --git a/Source/UI/UIEditCtrl.h b/Source/UI/Edit/UIEditCtrl.h similarity index 72% rename from Source/UI/UIEditCtrl.h rename to Source/UI/Edit/UIEditCtrl.h index 086a921..635d479 100644 --- a/Source/UI/UIEditCtrl.h +++ b/Source/UI/Edit/UIEditCtrl.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UIEDITCTRL_H -#define RAGNAROK_SOURCE_UI_UIEDITCTRL_H +#ifndef RAGNAROK_SOURCE_UI_EDIT_UIEDITCTRL_H +#define RAGNAROK_SOURCE_UI_EDIT_UIEDITCTRL_H -#include "UI/UIWindow.h" +#include "UI/Window/UIWindow.h" #include @@ -33,8 +33,6 @@ struct UIEditContext { const int& screenHeight; }; -// UIEditCtrl, 284-byte x86 value. Source adds the -// UIWindow context pointer and this control's explicit original-owner view. class UIEditCtrl : public UIWindow { public: UIEditCtrl(UIWindowContext& windows, UIEditContext& edit); @@ -45,23 +43,15 @@ public: void Slot24(int retained) override; void Slot25(int x, int y) override; void Slot28(int x, int y) override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; int Slot46() override; - virtual void SetText(const char* value); // 53 - virtual void SelectAll(); // 54 - virtual void PaintText(); // 55 - virtual void Synchronize(); // 56 - virtual void Trim(); // 57 + virtual void SetText(const char* value); + virtual void SelectAll(); + virtual void PaintText(); + virtual void Synchronize(); + virtual void Trim(); int Length() const; - // Focused reads synchronize through virtual slot 56 before returning this - // control's retained string, not a pointer into the shared input buffer. + const char* Text(); void Background(int red, int green, int blue); void TextColor(std::uint32_t primary, std::uint32_t secondary); @@ -94,12 +84,7 @@ public: protected: UIEditContext* m_edit; - void PaintTextWithPolicy( - bool alternate, - const std::string* placeholder, - std::uint32_t placeholderColor, - bool placeholderEnabled - ); + void PaintTextWithPolicy(bool alternate, const std::string* placeholder, std::uint32_t placeholderColor, bool placeholderEnabled); private: bool RemoveInvalidLink(std::list::iterator& entry); @@ -118,14 +103,7 @@ class UIEditCtrl2 : public UIEditCtrl { public: UIEditCtrl2(UIWindowContext& windows, UIEditContext& edit); ~UIEditCtrl2() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; }; class UIEditCtrl4 : public UIEditCtrl { @@ -144,14 +122,7 @@ class UIEditCtrl5 : public UIEditCtrl4 { public: UIEditCtrl5(UIWindowContext& windows, UIEditContext& edit); ~UIEditCtrl5() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; }; #if defined(_WIN32) && !defined(_WIN64) diff --git a/Source/UI/UIEditLinks.cpp b/Source/UI/Edit/UIEditLinks.cpp similarity index 77% rename from Source/UI/UIEditLinks.cpp rename to Source/UI/Edit/UIEditLinks.cpp index 5b0dbda..93fd699 100644 --- a/Source/UI/UIEditLinks.cpp +++ b/Source/UI/Edit/UIEditLinks.cpp @@ -1,10 +1,10 @@ -#include "Client/TextInputBuffer.h" -#include "UI/InputFocus.h" -#include "UI/NavigationLink.h" -#include "UI/TextFitting.h" -#include "UI/UIButton.h" -#include "UI/UIEditCtrl.h" -#include "UI/UINaviLinkButton.h" +#include "Client/Input/TextInputBuffer.h" +#include "UI/Window/InputFocus.h" +#include "UI/Text/NavigationLink.h" +#include "UI/Text/TextFitting.h" +#include "UI/Buttons/UIButton.h" +#include "UI/Edit/UIEditCtrl.h" +#include "UI/Buttons/UINaviLinkButton.h" #include #include @@ -21,9 +21,7 @@ bool UIEditCtrl::RemoveInvalidLink(std::list::iterator& entry) { return true; } - const std::string fitted = FitText( - *this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale, name, this->geometry.width / 2 - ); + const std::string fitted = FitText(*this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale, name, this->geometry.width / 2); std::size_t found = remaining.find(fitted); if (found == std::string::npos) { @@ -44,8 +42,7 @@ bool UIEditCtrl::RemoveInvalidLink(std::list::iterator& entry) { } if (left != right) { - const bool allowed = - !this->m_edit->linkInputRestricted || this->m_edit->permittedLinkInput == this->m_edit->focus.window; + const bool allowed = !this->m_edit->linkInputRestricted || this->m_edit->permittedLinkInput == this->m_edit->focus.window; const auto boundary = left ? absolute + bytes : absolute; if (allowed && boundary == static_cast(this->m_edit->input.cursor)) { @@ -56,6 +53,7 @@ bool UIEditCtrl::RemoveInvalidLink(std::list::iterator& entry) { this->m_edit->input.Insert(remaining.c_str()); this->RemoveChild(button, 1); entry = this->links.erase(entry); + return true; } } @@ -66,8 +64,6 @@ bool UIEditCtrl::RemoveInvalidLink(std::list::iterator& entry) { if (found != std::string::npos) { absolute = bytes + (absolute == previous ? absolute : absolute + previous); - // The next comparison in the original keeps the cumulative position - // separate from the next match relative to the shortened search string. } } @@ -93,9 +89,7 @@ void UIEditCtrl::SnapLinkSelection(std::size_t prefix, std::size_t bytes) { // OFFSET: 0x008624B0 // FUNCTION: fn_10904 void UIEditCtrl::UpdateLinks() { - if (std::none_of(this->links.begin(), this->links.end(), [](const UIWindow* window) { - return window->geometry.id == 438; - })) { + if (std::none_of(this->links.begin(), this->links.end(), [](const UIWindow* window) { return window->geometry.id == 438; })) { return; } @@ -111,9 +105,7 @@ void UIEditCtrl::UpdateLinks() { auto* button = static_cast(*entry); const std::string name = FormatNavigationLink(button->link, false); - const std::string fitted = FitText( - *this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale, name, this->geometry.width / 2 - ); + const std::string fitted = FitText(*this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale, name, this->geometry.width / 2); const std::string display = "<" + fitted + ">"; const auto found = remaining.find(display); @@ -132,11 +124,7 @@ void UIEditCtrl::UpdateLinks() { if (this->firstVisible != 0 && prefix.size() <= static_cast(this->firstVisible)) { button->Move(1000, this->textY - 1); } else { - button->Move( - this->TextWidth(this->m_edit->buttons.fonts, this->m_edit->buttons.locale, visible.c_str(), 0, 0, 12, 0, 0) + - 2, - this->textY - 1 - ); + button->Move(this->TextWidth(this->m_edit->buttons.fonts, this->m_edit->buttons.locale, visible.c_str(), 0, 0, 12, 0, 0) + 2, this->textY - 1); } this->SnapLinkSelection(prefix.size(), fitted.size()); @@ -156,10 +144,8 @@ void UIEditCtrl::UpdateLinks() { // FUNCTION: fn_10914 void UIEditCtrl::InsertLink(const char* value) { const std::string name = FormatNavigationLink(value, false); - // Original computes but discards this fitting result before building display. - FitText( - *this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale, name, this->geometry.width / 2 - ); + + FitText(*this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale, name, this->geometry.width / 2); const std::string display = "<" + name + ">"; std::string before; bool removed = false; @@ -173,10 +159,10 @@ void UIEditCtrl::InsertLink(const char* value) { removed = true; const auto* button = static_cast(window); const std::string fitted = FitText( - *this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale, - FormatNavigationLink(button->link, false), this->geometry.width / 2 + *this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale, FormatNavigationLink(button->link, false), this->geometry.width / 2 ); const std::string old = "<" + fitted + ">"; + oldBytes = old.size(); position = this->text.find(old); @@ -191,10 +177,8 @@ void UIEditCtrl::InsertLink(const char* value) { } } - if ( - !_mbsstr(reinterpret_cast(value), reinterpret_cast("")) && - !_mbsstr(reinterpret_cast(value), reinterpret_cast("")) - ) { + if (!_mbsstr(reinterpret_cast(value), reinterpret_cast("")) && + !_mbsstr(reinterpret_cast(value), reinterpret_cast(""))) { this->SetText(value); return; } @@ -218,8 +202,9 @@ void UIEditCtrl::InsertLink(const char* value) { this->SetText(this->text.c_str()); this->anchor = this->cursor = static_cast(this->text.size()); this->m_edit->input.Select(this->cursor, this->cursor); + auto* button = new UINaviLinkButton(*this->m_context, this->m_edit->buttons, this->m_edit->navigation); - // The immediate is a color constant, not a callback. + button->Configure(display.c_str(), 0x009E68F0, 0, 12, 0, 0); button->SetId(438); ExtractNavigationLink(button->link, value); diff --git a/Source/UI/UIEditVariants.cpp b/Source/UI/Edit/UIEditVariants.cpp similarity index 77% rename from Source/UI/UIEditVariants.cpp rename to Source/UI/Edit/UIEditVariants.cpp index 816ad4b..374078c 100644 --- a/Source/UI/UIEditVariants.cpp +++ b/Source/UI/Edit/UIEditVariants.cpp @@ -1,6 +1,6 @@ -#include "Client/TextInputBuffer.h" -#include "UI/InputFocus.h" -#include "UI/UIEditCtrl.h" +#include "Client/Input/TextInputBuffer.h" +#include "UI/Window/InputFocus.h" +#include "UI/Edit/UIEditCtrl.h" // OFFSET: 0x0084F250 UIEditCtrl2::UIEditCtrl2(UIWindowContext& windows, UIEditContext& edit) : UIEditCtrl(windows, edit) { @@ -12,14 +12,7 @@ UIEditCtrl2::~UIEditCtrl2() = default; // OFFSET: 0x00863BF0 // FUNCTION: fn_10911 -int UIEditCtrl2::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIEditCtrl2::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message != 0) { this->UIEditCtrl::SendMsg(sender, message, a, b, c, d); } else { @@ -31,8 +24,7 @@ int UIEditCtrl2::SendMsg( } // OFFSET: 0x0084F7B0 -UIEditCtrl4::UIEditCtrl4(UIWindowContext& windows, UIEditContext& edit) - : UIEditCtrl(windows, edit), placeholderColor(0xFFFFFFFFu), placeholderEnabled(0) { +UIEditCtrl4::UIEditCtrl4(UIWindowContext& windows, UIEditContext& edit) : UIEditCtrl(windows, edit), placeholderColor(0xFFFFFFFFu), placeholderEnabled(0) { } // OFFSET: 0x00852870 @@ -65,14 +57,7 @@ UIEditCtrl5::~UIEditCtrl5() = default; // OFFSET: 0x00864140 // FUNCTION: fn_10913 -int UIEditCtrl5::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIEditCtrl5::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message != 0) { this->UIEditCtrl::SendMsg(sender, message, a, b, c, d); } else { diff --git a/Source/UI/EditTextState.h b/Source/UI/EditTextState.h deleted file mode 100644 index 337afd1..0000000 --- a/Source/UI/EditTextState.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_EDITTEXTSTATE_H -#define RAGNAROK_SOURCE_UI_EDITTEXTSTATE_H - -#include -#include - -struct TextInputBuffer; - -// Noncontiguous UIEditCtrl fields. UIEditCtrl's actual virtual SetText also -// invalidates its parent; that ownership is retained by the concrete control. -struct EditTextState { - std::string& text; // +0xD8 - int& anchor; // +0x7C - int& cursor; // +0x80 - const int& maximum; // +0x88 - const bool& focused; - TextInputBuffer& input; - const UINT& codePage; - - void SetText(const char* value); - void Trim(); - void SelectAll(); - int Length() const; -}; - -#endif diff --git a/Source/UI/EditViewport.cpp b/Source/UI/EditViewport.cpp deleted file mode 100644 index a723167..0000000 --- a/Source/UI/EditViewport.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "Client/TextInputBuffer.h" -#include "Render/TextContext.h" -#include "UI/EditTextState.h" -#include "UI/EditViewport.h" - -#include -#include -#include -#include - -// OFFSET: 0x00862FB0 -// FUNCTION: fn_10905 -void EditViewport::Synchronize() { - const int previousCursor = this->cursor; - this->input.CopyDisplayText(this->text); - this->input.Selection(this->anchor, this->cursor); - this->state.Trim(); - const auto length = static_cast(this->text.size()); - bool clamped = false; - - if (static_cast(this->cursor) > length || static_cast(this->anchor) > length) { - this->anchor = static_cast(std::min(static_cast(this->anchor), length)); - this->cursor = static_cast(std::min(static_cast(this->cursor), length)); - this->input.Select(this->anchor, this->cursor); - clamped = true; - } - - if (this->cursor == 0) { - this->firstVisible = 0; - return; - } - - const auto selection = static_cast(std::max(this->input.cursor, this->input.anchor)) - - static_cast(std::min(this->input.cursor, this->input.anchor)); - - if (selection >= length) { - this->firstVisible = 0; - } - - TextContext context(this->surface, this->fonts, this->locale); - context.SetFont(0, 12, 0, 0); - const auto measure = [&](const char* text, unsigned bytes) { - return context.Measure(text, static_cast(bytes ? bytes : std::strlen(text))).cx; - }; - const auto add = [](int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - }; - const int available = add(this->width, -7); - - if (this->cursor > previousCursor || clamped) { - const int before = - this->firstVisible == 0 ? 0 : measure(this->text.c_str(), static_cast(this->firstVisible)); - const int position = add(add(measure(this->text.c_str(), static_cast(this->cursor)), 3), -before); - - if (position > available) { - const char* end = this->text.c_str() + this->text.size(); - const char* next = CharNextExA(static_cast(this->codePage), this->text.c_str(), 0); - - while (add(measure(next, 0), 3) > available && next < end) { - next = CharNextExA(static_cast(this->codePage), next, 0); - } - - const auto tail = static_cast(std::strlen(next)); - const auto candidate = static_cast(this->firstVisible) + static_cast(this->cursor) - - static_cast(previousCursor); - this->firstVisible = - std::bit_cast(std::min(static_cast(this->cursor) - tail, candidate)); - } - } else if (this->cursor < previousCursor) { - if ( - add(measure(this->text.c_str(), static_cast(this->cursor)), 3) < available && - this->firstVisible > this->cursor - ) { - this->firstVisible = add(add(this->firstVisible, this->cursor), -previousCursor); - } - - this->firstVisible = std::max(this->firstVisible, 0); - } -} diff --git a/Source/UI/InputFocus.h b/Source/UI/InputFocus.h deleted file mode 100644 index d491816..0000000 --- a/Source/UI/InputFocus.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_INPUTFOCUS_H -#define RAGNAROK_SOURCE_UI_INPUTFOCUS_H - -class UIWindow; - -// Original manager +0x1A0, distinct from mouse capture at +0x19C. -struct InputFocus { - UIWindow*& window; - void Set(UIWindow* value); - void First(); - void Next(); - void Advance(); - // Common mouse tail: invalidate current focus, reread after callback, then - // invalidate its root unless it is the manager's excluded frame. - void Refresh(UIWindow* const& excludedRoot); -}; - -void SetPressedWindowRoot(UIWindow*& pressedRoot, UIWindow* window); - -#endif diff --git a/Source/UI/ItemDrawing.cpp b/Source/UI/ItemDrawing.cpp deleted file mode 100644 index bd30d4a..0000000 --- a/Source/UI/ItemDrawing.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "Contents/ItemDescription.h" -#include "Contents/ItemInfo.h" -#include "Resource/BitmapResource.h" -#include "Resource/ResourceMgr.h" -#include "UI/ItemDrawing.h" -#include "UI/UIWindow.h" - -#include -#include - -// OFFSET: 0x008A8EE0 -// FUNCTION: fn_11717 -void DrawItemIcon( - UIWindow& window, - ResourceMgr& resources, - ItemDescriptions& descriptions, - int x, - int y, - const ItemInfo& item, - unsigned char identified -) { - char path[128]; - descriptions.IconPath(path, item.itemId.c_str(), item.identified != 0 || identified != 0); - CBitmapRes* bitmap = static_cast(resources.Load(path)); - if (bitmap) { - window.DrawBitmap(x, y, &bitmap->image, true); - } -} - -// OFFSET: 0x008A9040 -// FUNCTION: fn_11720 -void DrawItemWithQuantity( - UIWindow& window, - ResourceMgr& resources, - ItemDescriptions& descriptions, - FontCache& fonts, - const TextLocale& locale, - int x, - int y, - const ItemInfo& item, - unsigned char identified, - unsigned char plain -) { - DrawItemIcon(window, resources, descriptions, x, y, item, identified); - if (item.quantity == -1 || item.quantity == 0) { - return; - } - char text[16]; - std::sprintf(text, "%d", item.quantity); - const auto add = [](int value, int offset) { - return std::bit_cast(static_cast(value) + static_cast(offset)); - }; - if (plain != 0) { - window.DrawTextAt(fonts, locale, add(x, 16), add(y, 20), text, 0, 0, 11, 0, 0, 0); - } else { - const int left = add(x, item.quantity < 1000 ? 14 : 0); - window.DrawTextAt(fonts, locale, add(left, 1), add(y, 15), text, 0, 0, 11, 0xFFFFFF, 0, 0); - window.DrawTextAt(fonts, locale, add(left, -1), add(y, 15), text, 0, 0, 11, 0xFFFFFF, 0, 0); - window.DrawTextAt(fonts, locale, left, add(y, 16), text, 0, 0, 11, 0xFFFFFF, 0, 0); - window.DrawTextAt(fonts, locale, left, add(y, 14), text, 0, 0, 11, 0xFFFFFF, 0, 0); - window.DrawTextAt(fonts, locale, left, add(y, 15), text, 0, 0, 11, 0, 0, 0); - } -} diff --git a/Source/UI/ItemDrawing.h b/Source/UI/ItemDrawing.h deleted file mode 100644 index b39ae3b..0000000 --- a/Source/UI/ItemDrawing.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_ITEMDRAWING_H -#define RAGNAROK_SOURCE_UI_ITEMDRAWING_H - -struct ItemInfo; -struct ItemDescriptions; -class UIWindow; -class ResourceMgr; -class FontCache; -struct TextLocale; - -void DrawItemIcon( - UIWindow& window, - ResourceMgr& resources, - ItemDescriptions& descriptions, - int x, - int y, - const ItemInfo& item, - unsigned char identified -); -void DrawItemWithQuantity( - UIWindow& window, - ResourceMgr& resources, - ItemDescriptions& descriptions, - FontCache& fonts, - const TextLocale& locale, - int x, - int y, - const ItemInfo& item, - unsigned char identified, - unsigned char plain -); - -#endif diff --git a/Source/UI/SnapMgr.cpp b/Source/UI/Layout/SnapMgr.cpp similarity index 85% rename from Source/UI/SnapMgr.cpp rename to Source/UI/Layout/SnapMgr.cpp index f946c89..7100cdc 100644 --- a/Source/UI/SnapMgr.cpp +++ b/Source/UI/Layout/SnapMgr.cpp @@ -1,9 +1,7 @@ -#include "UI/SnapMgr.h" -#include "UI/SnapObject.h" -#include "UI/UIWindow.h" -#include "UI/WindowSnapping.h" - -#include +#include "UI/Layout/SnapMgr.h" +#include "UI/Layout/SnapObject.h" +#include "UI/Window/UIWindow.h" +#include "UI/Layout/WindowSnapping.h" // STATIC: 0x01334698 // GLOBAL: gl_21916 @@ -19,24 +17,21 @@ int g_snapDirection = 1; SnapObject* g_snapBoundary = nullptr; namespace { - int WrappedAdd(int a, int b) { - return std::bit_cast(static_cast(a) + static_cast(b)); - } - int Subtract(int a, int b) { - return std::bit_cast(static_cast(a) - static_cast(b)); - } int Magnitude(int value) { - return value < 0 ? Subtract(0, value) : value; + return value < 0 ? (0 - value) : value; } + bool ContainsUpward(SnapObject* object, SnapObject* target) { if (object == target) { return true; } + for (SnapObject* next : object->edges[1]) { if (ContainsUpward(next, target)) { return true; } } + return false; } } @@ -45,6 +40,7 @@ namespace { // FUNCTION: fn_09694 CSnapMgr::CSnapMgr() : root(nullptr) { } + // OFFSET: 0x007E23D0 // FUNCTION: fn_09697 // OFFSET: 0x007E2520 @@ -59,6 +55,7 @@ SnapObject* CSnapMgr::Find(const UIWindow* window) const { return object; } } + return nullptr; } @@ -74,6 +71,7 @@ void CSnapMgr::SetRoot(UIWindow* window) { if (!g_snapEnabled || this->Find(window) || this->root) { return; } + SnapObject* object = new SnapObject; object->window = window; this->root = object; @@ -86,6 +84,7 @@ void CSnapMgr::Add(UIWindow* window) { if (!g_snapEnabled || (this->root && this->root->window == window) || this->Find(window)) { return; } + SnapObject* object = new SnapObject; object->window = window; this->UpdateLinks(object); @@ -97,6 +96,7 @@ void CSnapMgr::Add(UIWindow* window) { bool CSnapMgr::IsRoot(const UIWindow* window) const { return this->root && this->root->window == window; } + // OFFSET: 0x007E2D80 // FUNCTION: fn_09713 bool CSnapMgr::Contains(const UIWindow* window) const { @@ -111,6 +111,7 @@ bool CSnapMgr::Connected(UIWindow* from, UIWindow* to) { if (!first) { return false; } + SnapObject* second = this->Find(to); return second && first->Connected(second); } @@ -121,6 +122,7 @@ bool CSnapMgr::ConnectedToRoot(UIWindow* window) { if (!this->root || this->root->window == window) { return false; } + this->ResetVisited(); SnapObject* object = this->Find(window); return object && object->Connected(this->root); @@ -133,6 +135,7 @@ void CSnapMgr::UpdateLinks(SnapObject* object) { const int side = object->AdjacentSide(*existing); object->Remove(existing); existing->Remove(object); + if (side != -1) { object->edges[side].push_back(existing); const int opposite = g_snapOppositeSide[side]; @@ -149,6 +152,7 @@ void CSnapMgr::Refresh(UIWindow* window) { if (!this->Find(window)) { return; } + for (SnapObject* object : this->objects) { this->UpdateLinks(object); } @@ -160,6 +164,7 @@ void CSnapMgr::CaptureOrigins(UIWindow* window) { if (!this->root || !window || this->root->window != window) { return; } + for (SnapObject* object : this->objects) { if (object->window && this->ConnectedToRoot(object->window)) { object->window->Slot12(); @@ -173,6 +178,7 @@ void CSnapMgr::ConstrainGroup(UIWindow* window, int& dx, int& dy, WindowSnapping if (!this->root) { return; } + int resultX = 0, resultY = 0; if (this->root->window == window) { for (SnapObject* object : this->objects) { @@ -180,20 +186,23 @@ void CSnapMgr::ConstrainGroup(UIWindow* window, int& dx, int& dy, WindowSnapping if (!this->ConnectedToRoot(member)) { continue; } + const int savedY = member->geometry.y; member->Slot13(dx, dy); int x, y; snapping.Constrain(member, x, y, 1); - // Saves y(+32), then writes it into x(+28). + member->geometry.x = savedY; if (Magnitude(resultX) < Magnitude(x)) { resultX = x; } + if (Magnitude(resultY) < Magnitude(y)) { resultY = y; } } } + dx = resultX; dy = resultY; } @@ -204,6 +213,7 @@ void CSnapMgr::MoveConnected(UIWindow* window, int dx, int dy, WindowSnapping& s if (!this->root || this->root->window != window) { return; } + for (SnapObject* object : this->objects) { if (this->ConnectedToRoot(object->window)) { object->window->Slot13(dx, dy); @@ -218,12 +228,14 @@ void CSnapMgr::MoveBranch(SnapObject* object, int dx, int dy, int side, WindowSn if (side == -1 || object->visited == 1) { return; } + object->visited = 1; if (object->window) { - object->window->geometry.x = WrappedAdd(object->window->geometry.x, dx); - object->window->geometry.y = WrappedAdd(object->window->geometry.y, dy); + object->window->geometry.x = (object->window->geometry.x + dx); + object->window->geometry.y = (object->window->geometry.y + dy); snapping.Store(object->window); } + for (SnapObject* next : object->edges[side]) { MoveBranch(next, dx, dy, side, snapping); } @@ -237,6 +249,7 @@ void CSnapMgr::MoveEdge(UIWindow* window, int dx, int dy, int side, WindowSnappi if (!object) { return; } + if (side != -1 && object->visited != 1) { object->visited = 1; int up = 0, down = 0; @@ -244,49 +257,52 @@ void CSnapMgr::MoveEdge(UIWindow* window, int dx, int dy, int side, WindowSnappi const int y = object->window->geometry.y; const int height = object->window->geometry.height; object->AccumulateHeight(down, 3); - const int candidateBottom = WrappedAdd(Subtract(object->window->geometry.y, dy), down); + const int candidateBottom = ((object->window->geometry.y - dy) + down); const int screenHeight = snapping.screenHeight; - if ( - Subtract(WrappedAdd(y, height), up) != 0 && - (!g_snapBoundary || g_snapBoundary != object || candidateBottom == screenHeight) - ) { + + if (((y + height) - up) != 0 && (!g_snapBoundary || g_snapBoundary != object || candidateBottom == screenHeight)) { bool moveSelf = side != 3; if (side == 3) { bool boundaryAncestor = g_snapBoundary == object; if (!boundaryAncestor) { - // Like the original, side3 requires a real boundary node here. for (SnapObject* next : g_snapBoundary->edges[1]) { if (next == object) { boundaryAncestor = true; break; } + for (SnapObject* above : next->edges[1]) { if (ContainsUpward(above, object)) { boundaryAncestor = true; break; } } + if (boundaryAncestor) { break; } } } + if (boundaryAncestor || candidateBottom == screenHeight) { side = g_snapDirection; - dy = Subtract(0, dy); + dy = (0 - dy); moveSelf = true; } } + if (moveSelf && side == 1 && object->window) { - object->window->geometry.x = WrappedAdd(object->window->geometry.x, dx); - object->window->geometry.y = WrappedAdd(object->window->geometry.y, dy); + object->window->geometry.x = (object->window->geometry.x + dx); + object->window->geometry.y = (object->window->geometry.y + dy); snapping.Store(object->window); } } + for (SnapObject* next : object->edges[side]) { MoveBranch(next, dx, dy, side, snapping); } } + this->Refresh(window); } @@ -296,6 +312,7 @@ void CSnapMgr::Clear() { for (SnapObject* object : this->objects) { delete object; } + this->objects.clear(); this->root = nullptr; } @@ -306,17 +323,20 @@ void CSnapMgr::Remove(UIWindow* window) { if (this->root && this->root->window == window) { this->root = nullptr; } + for (auto entry = this->objects.begin(); entry != this->objects.end(); ++entry) { SnapObject* object = *entry; if (object->window != window) { continue; } + delete object; this->objects.erase(entry); - // Remaining edges contain the old pointer as an identity only; never dereference it. + for (SnapObject* remaining : this->objects) { remaining->Remove(object); } + return; } } diff --git a/Source/UI/SnapMgr.h b/Source/UI/Layout/SnapMgr.h similarity index 86% rename from Source/UI/SnapMgr.h rename to Source/UI/Layout/SnapMgr.h index 16ea6a8..4f848db 100644 --- a/Source/UI/SnapMgr.h +++ b/Source/UI/Layout/SnapMgr.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_SNAPMGR_H -#define RAGNAROK_SOURCE_UI_SNAPMGR_H +#ifndef RAGNAROK_SOURCE_UI_LAYOUT_SNAPMGR_H +#define RAGNAROK_SOURCE_UI_LAYOUT_SNAPMGR_H #include @@ -7,8 +7,6 @@ class SnapObject; class UIWindow; struct WindowSnapping; -// RTTI CSnapMgr. Owns graph nodes, not their windows. Geometry movement and -// frame constraint policy remain separate operations on the same graph. class CSnapMgr { public: CSnapMgr(); diff --git a/Source/UI/SnapObject.cpp b/Source/UI/Layout/SnapObject.cpp similarity index 82% rename from Source/UI/SnapObject.cpp rename to Source/UI/Layout/SnapObject.cpp index ab37c91..c3dc771 100644 --- a/Source/UI/SnapObject.cpp +++ b/Source/UI/Layout/SnapObject.cpp @@ -1,12 +1,7 @@ -#include "UI/SnapObject.h" -#include "UI/UIWindow.h" - -#include +#include "UI/Layout/SnapObject.h" +#include "UI/Window/UIWindow.h" namespace { - int Add(int a, int b) { - return std::bit_cast(static_cast(a) + static_cast(b)); - } bool Overlaps(int a, int b, int c, int d) { return (c >= a && c <= b) || (d >= a && d <= b) || (a >= c && a <= d) || (b >= c && b <= d); } @@ -16,6 +11,7 @@ namespace { // FUNCTION: fn_09695 SnapObject::SnapObject() : window(nullptr), visited(0) { } + // OFFSET: 0x007E2550 // FUNCTION: fn_09699 // OFFSET: 0x007E2360 @@ -27,22 +23,27 @@ SnapObject::~SnapObject() = default; int SnapObject::AdjacentSide(const SnapObject& other) const { const WindowGeometry& a = this->window->geometry; const WindowGeometry& b = other.window->geometry; - const int right = Add(a.x, a.width); - const int bottom = Add(a.y, a.height); - const int otherRight = Add(b.x, b.width); - const int otherBottom = Add(b.y, b.height); + const int right = (a.x + a.width); + const int bottom = (a.y + a.height); + const int otherRight = (b.x + b.width); + const int otherBottom = (b.y + b.height); + if (a.x == otherRight && Overlaps(a.y, bottom, b.y, otherBottom)) { return 0; } + if (b.x == right && Overlaps(a.y, bottom, b.y, otherBottom)) { return 2; } + if (a.y == otherBottom && Overlaps(a.x, right, b.x, otherRight)) { return 1; } + if (b.y == bottom && Overlaps(a.x, right, b.x, otherRight)) { return 3; } + return -1; } @@ -52,6 +53,7 @@ void SnapObject::Remove(SnapObject* object) { if (!object) { return; } + for (auto& edge : this->edges) { for (auto node = edge.begin(); node != edge.end(); ++node) { if (*node == object) { @@ -68,10 +70,13 @@ bool SnapObject::Contains(SnapObject* target) { if (this->visited == 1) { return false; } + if (target == this) { return true; } + this->visited = 1; + for (auto& edge : this->edges) { for (SnapObject* node : edge) { if (node->Contains(target)) { @@ -79,6 +84,7 @@ bool SnapObject::Contains(SnapObject* target) { } } } + return false; } @@ -88,7 +94,9 @@ bool SnapObject::Connected(SnapObject* target) { if (this->visited == 1 || target == this) { return false; } + this->visited = 1; + for (auto& edge : this->edges) { for (SnapObject* node : edge) { if (node->Contains(target)) { @@ -96,6 +104,7 @@ bool SnapObject::Connected(SnapObject* target) { } } } + return false; } @@ -103,16 +112,19 @@ bool SnapObject::Connected(SnapObject* target) { // FUNCTION: fn_09708 void SnapObject::AccumulateHeight(int& height, int side) const { const SnapObject* current = this; + for (;;) { - height = Add(height, current->window->geometry.height); + height = (height + current->window->geometry.height); const SnapObject* next = nullptr; + for (SnapObject* candidate : current->edges[side]) { - // Original selection is overwritten even by a nonpositive final node. next = candidate->window->geometry.height > 0 ? candidate : nullptr; } + if (!next) { return; } + current = next; } } diff --git a/Source/UI/SnapObject.h b/Source/UI/Layout/SnapObject.h similarity index 77% rename from Source/UI/SnapObject.h rename to Source/UI/Layout/SnapObject.h index f9eb33d..96a9164 100644 --- a/Source/UI/SnapObject.h +++ b/Source/UI/Layout/SnapObject.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_UI_SNAPOBJECT_H -#define RAGNAROK_SOURCE_UI_SNAPOBJECT_H +#ifndef RAGNAROK_SOURCE_UI_LAYOUT_SNAPOBJECT_H +#define RAGNAROK_SOURCE_UI_LAYOUT_SNAPOBJECT_H #include class UIWindow; -// RTTI SnapObject, owned by CSnapMgr. Window/edge pointers are borrowed. class SnapObject { public: SnapObject(); diff --git a/Source/UI/SnapRectangle.cpp b/Source/UI/Layout/SnapRectangle.cpp similarity index 77% rename from Source/UI/SnapRectangle.cpp rename to Source/UI/Layout/SnapRectangle.cpp index 960102c..916cbca 100644 --- a/Source/UI/SnapRectangle.cpp +++ b/Source/UI/Layout/SnapRectangle.cpp @@ -1,28 +1,22 @@ -#include "UI/SnapRectangle.h" +#include "UI/Layout/SnapRectangle.h" -#include #include namespace { - int Add(int a, int b) { - return std::bit_cast(static_cast(a) + static_cast(b)); - } - int Subtract(int a, int b) { - return std::bit_cast(static_cast(a) - static_cast(b)); - } bool Overlaps(int a, int b, int c, int d) { return (c >= a && c <= b) || (d >= a && d <= b) || (a >= c && a <= d) || (b >= c && b <= d); } + bool Near(int value, int edge) { - return value >= Add(edge, -10) && value <= Add(edge, 10); + return value >= (edge - 10) && value <= (edge + 10); } } // OFFSET: 0x009B5250 // FUNCTION: fn_13839 void SnapRectangle::Set(int x, int y, int width, int height) { - const int right = Add(x, width); - const int bottom = Add(y, height); + const int right = (x + width); + const int bottom = (y + height); this->left = {x, y, bottom}; this->right = {right, y, bottom}; this->top = {y, x, right}; @@ -45,47 +39,56 @@ void SnapRectangle::Snap(const SnapRectangle& other, int& dx, int& dy) const { int edge = this->left.position; int value = other.right.position; bool close = Near(value, edge); + if (!close) { edge = this->right.position; value = other.left.position; close = Near(value, edge); } + if (close) { - dx = Subtract(edge, value); + dx = (edge - value); edge = this->top.position; value = other.top.position; close = Near(value, edge); + if (!close) { edge = this->bottom.position; value = other.bottom.position; close = Near(value, edge); } + if (close) { - dy = Subtract(edge, value); + dy = (edge - value); } } } + if (Overlaps(this->top.begin, this->top.end, other.bottom.begin, other.bottom.end)) { int edge = this->top.position; int value = other.bottom.position; bool close = Near(value, edge); + if (!close) { edge = this->bottom.position; value = other.top.position; close = Near(value, edge); } + if (close) { - dy = Subtract(edge, value); + dy = (edge - value); edge = this->left.position; value = other.left.position; close = Near(value, edge); + if (!close) { edge = this->right.position; value = other.right.position; close = Near(value, edge); } + if (close) { - dx = Subtract(edge, value); + dx = (edge - value); } } } diff --git a/Source/UI/SnapRectangle.h b/Source/UI/Layout/SnapRectangle.h similarity index 61% rename from Source/UI/SnapRectangle.h rename to Source/UI/Layout/SnapRectangle.h index 1e6b156..fb275b8 100644 --- a/Source/UI/SnapRectangle.h +++ b/Source/UI/Layout/SnapRectangle.h @@ -1,10 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_SNAPRECTANGLE_H -#define RAGNAROK_SOURCE_UI_SNAPRECTANGLE_H +#ifndef RAGNAROK_SOURCE_UI_LAYOUT_SNAPRECTANGLE_H +#define RAGNAROK_SOURCE_UI_LAYOUT_SNAPRECTANGLE_H #include -// Four axis-aligned edge records in original order: left, right, top, bottom. -// Vertical records store(x,top,bottom); horizontal records store(y,left,right). struct SnapRectangle { struct Edge { std::int32_t position; diff --git a/Source/UI/WindowCoordinates.cpp b/Source/UI/Layout/WindowCoordinates.cpp similarity index 55% rename from Source/UI/WindowCoordinates.cpp rename to Source/UI/Layout/WindowCoordinates.cpp index b7d2383..c489e01 100644 --- a/Source/UI/WindowCoordinates.cpp +++ b/Source/UI/Layout/WindowCoordinates.cpp @@ -1,24 +1,19 @@ -#include "UI/UIWindow.h" -#include "UI/WindowCoordinates.h" +#include "UI/Window/UIWindow.h" +#include "UI/Layout/WindowCoordinates.h" -#include #include -namespace { - int Add(int first, int second) { - return std::bit_cast(static_cast(first) + static_cast(second)); - } -} - // OFFSET: 0x00A91B70 // FUNCTION: fn_45428 void WindowScreenPosition(const UIWindow* window, int& x, int& y) { int horizontal = 0; int vertical = 0; + for (const UIWindow* node = window; node; node = static_cast(node->parent)) { - horizontal = Add(horizontal, node->geometry.x); - vertical = Add(vertical, node->geometry.y); + horizontal = (horizontal + node->geometry.x); + vertical = (vertical + node->geometry.y); } + x = horizontal; y = vertical; } @@ -33,23 +28,22 @@ void WindowScreenBounds(const UIWindow* window, int& left, int& top, int& right, int horizontal = 0; int vertical = 0; + for (const UIWindow* node = window; node; node = static_cast(node->parent)) { - horizontal = Add(horizontal, node->geometry.x); - vertical = Add(vertical, node->geometry.y); + horizontal = (horizontal + node->geometry.x); + vertical = (vertical + node->geometry.y); } + left = horizontal; top = vertical; if (window) { - right = Add(window->geometry.width, left); - bottom = Add(window->geometry.height, top); + right = (window->geometry.width + left); + bottom = (window->geometry.height + top); } } // OFFSET: 0x00AF64A0 // FUNCTION: fn_18253 bool WindowBoundsOverlap(const int first[4], const int second[4]) { - return first[2] > second[0] && - first[0] < second[2] && - first[3] > second[1] && - first[1] < second[3]; + return first[2] > second[0] && first[0] < second[2] && first[3] > second[1] && first[1] < second[3]; } diff --git a/Source/UI/Layout/WindowCoordinates.h b/Source/UI/Layout/WindowCoordinates.h new file mode 100644 index 0000000..25724e6 --- /dev/null +++ b/Source/UI/Layout/WindowCoordinates.h @@ -0,0 +1,12 @@ +#ifndef RAGNAROK_SOURCE_UI_LAYOUT_WINDOWCOORDINATES_H +#define RAGNAROK_SOURCE_UI_LAYOUT_WINDOWCOORDINATES_H + +class UIWindow; + +void WindowScreenPosition(const UIWindow* window, int& x, int& y); + +void WindowScreenBounds(const UIWindow* window, int& left, int& top, int& right, int& bottom); + +bool WindowBoundsOverlap(const int first[4], const int second[4]); + +#endif diff --git a/Source/UI/WindowGeometry.cpp b/Source/UI/Layout/WindowGeometry.cpp similarity index 71% rename from Source/UI/WindowGeometry.cpp rename to Source/UI/Layout/WindowGeometry.cpp index f1cbb5f..fd94386 100644 --- a/Source/UI/WindowGeometry.cpp +++ b/Source/UI/Layout/WindowGeometry.cpp @@ -1,14 +1,12 @@ -#include "UI/WindowGeometry.h" +#include "UI/Layout/WindowGeometry.h" #include -// clang-format off -#include -// clang-format on +#include // OFFSET: 0x00A79A90 WindowGeometry::WindowGeometry() - : width(0), height(0), x(0), y(0), surface(nullptr), visible(1), id(600), unknown_0030(0), unknown_0034(0), - targetAlpha(255), alphaStart(timeGetTime()), currentAlpha(255) { + : width(0), height(0), x(0), y(0), surface(nullptr), visible(1), id(600), unknown_0030(0), unknown_0034(0), targetAlpha(255), alphaStart(timeGetTime()), + currentAlpha(255) { } // OFFSET: 0x00A81D40 @@ -37,15 +35,16 @@ std::uint32_t WindowGeometry::Color() { if (value != this->targetAlpha) { const std::uint32_t step = (timeGetTime() - this->alphaStart) >> 4; const std::uint32_t candidate = value < this->targetAlpha ? value + step : value - step; - const bool keepCandidate = - value < this->targetAlpha ? candidate < this->targetAlpha : this->targetAlpha < candidate; + const bool keepCandidate = value < this->targetAlpha ? candidate < this->targetAlpha : this->targetAlpha < candidate; + value = keepCandidate ? candidate : this->targetAlpha; this->currentAlpha = value; } + if (value > 255) { value = this->targetAlpha; this->currentAlpha = value; } - // Adds 0xFFFFFF, rather than OR: retain wrap at unusual values. + return (value << 24) + 0xFFFFFF; } diff --git a/Source/UI/WindowGeometry.h b/Source/UI/Layout/WindowGeometry.h similarity index 72% rename from Source/UI/WindowGeometry.h rename to Source/UI/Layout/WindowGeometry.h index f2009fc..219f120 100644 --- a/Source/UI/WindowGeometry.h +++ b/Source/UI/Layout/WindowGeometry.h @@ -1,12 +1,10 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWGEOMETRY_H -#define RAGNAROK_SOURCE_UI_WINDOWGEOMETRY_H +#ifndef RAGNAROK_SOURCE_UI_LAYOUT_WINDOWGEOMETRY_H +#define RAGNAROK_SOURCE_UI_LAYOUT_WINDOWGEOMETRY_H #include class CDC; -// Contiguous UIWindow fields+20..+67. Parent/children, manager registration and -// virtual dispatch remain in the enclosing window; no replacement owner. struct WindowGeometry { /* 0014 */ int width; /* 0018 */ int height; diff --git a/Source/UI/WindowSnapping.cpp b/Source/UI/Layout/WindowSnapping.cpp similarity index 91% rename from Source/UI/WindowSnapping.cpp rename to Source/UI/Layout/WindowSnapping.cpp index 38496bf..ab5d74e 100644 --- a/Source/UI/WindowSnapping.cpp +++ b/Source/UI/Layout/WindowSnapping.cpp @@ -1,6 +1,6 @@ -#include "UI/SnapMgr.h" -#include "UI/UIWindow.h" -#include "UI/WindowSnapping.h" +#include "UI/Layout/SnapMgr.h" +#include "UI/Window/UIWindow.h" +#include "UI/Layout/WindowSnapping.h" // OFFSET: 0x00AAB0D0 // FUNCTION: fn_17280 @@ -10,9 +10,11 @@ void WindowSnapping::Store(UIWindow* window) { return; } } + if (!this->enabled || !window) { return; } + SnapRectangle& rectangle = this->rectangles[window]; rectangle.Set(window->geometry.x, window->geometry.y, window->geometry.width, window->geometry.height); } @@ -30,23 +32,28 @@ void WindowSnapping::Constrain(UIWindow* window, int& dx, int& dy, int groupMemb int x = 0, y = 0; screen.Snap(moving, x, y); bool needX = true, needY = true; + if (x != 0) { needX = false; dx = x; } + if (y != 0) { needY = false; dy = y; } + if (!needX && !needY) { return; } + const bool root = this->graph.IsRoot(window); + for (auto& [other, rectangle] : this->rectangles) { - // Query order matters: connectivity calls reset and mutate visit markers. const bool connected = this->graph.Connected(window, other); const bool otherRoot = this->graph.IsRoot(other); const bool otherConnected = this->graph.ConnectedToRoot(other); + if (groupMember != 0) { if (window == other || otherRoot || connected || otherConnected) { continue; @@ -56,15 +63,18 @@ void WindowSnapping::Constrain(UIWindow* window, int& dx, int& dy, int groupMemb continue; } } + rectangle.Snap(moving, x, y); if (x != 0 && needX) { needX = false; dx = x; } + if (y != 0 && needY) { needY = false; dy = y; } + if (!needX && !needY) { return; } diff --git a/Source/UI/WindowSnapping.h b/Source/UI/Layout/WindowSnapping.h similarity index 58% rename from Source/UI/WindowSnapping.h rename to Source/UI/Layout/WindowSnapping.h index 506d75d..3f65d45 100644 --- a/Source/UI/WindowSnapping.h +++ b/Source/UI/Layout/WindowSnapping.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWSNAPPING_H -#define RAGNAROK_SOURCE_UI_WINDOWSNAPPING_H +#ifndef RAGNAROK_SOURCE_UI_LAYOUT_WINDOWSNAPPING_H +#define RAGNAROK_SOURCE_UI_LAYOUT_WINDOWSNAPPING_H -#include "UI/SnapRectangle.h" +#include "UI/Layout/SnapRectangle.h" #include #include @@ -9,8 +9,6 @@ class CSnapMgr; class UIWindow; -// Borrowed UIWindowMgr map+404, excluded list+324160 and screen extent+1148. -// Option141 is supplied from the actual service option owner by the caller. struct WindowSnapping { CSnapMgr& graph; std::map& rectangles; diff --git a/Source/UI/UIComboBoxDefWnd.cpp b/Source/UI/Lists/UIComboBoxDefWnd.cpp similarity index 69% rename from Source/UI/UIComboBoxDefWnd.cpp rename to Source/UI/Lists/UIComboBoxDefWnd.cpp index dc7d689..783b53f 100644 --- a/Source/UI/UIComboBoxDefWnd.cpp +++ b/Source/UI/Lists/UIComboBoxDefWnd.cpp @@ -1,26 +1,18 @@ -#include "Render/DeviceContext.h" -#include "UI/UIBitmapButton.h" -#include "UI/UIComboBoxDefWnd.h" -#include "UI/UIListBox.h" -#include "UI/UIStaticText.h" -#include "UI/WindowPolicy.h" - -#include +#include "Render/DeviceContext/DeviceContext.h" +#include "UI/Buttons/UIBitmapButton.h" +#include "UI/Lists/UIComboBoxDefWnd.h" +#include "UI/Lists/UIListBox.h" +#include "UI/Text/UIStaticText.h" +#include "UI/Window/WindowPolicy.h" namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Subtract(int left, int right) { - return std::bit_cast(static_cast(left) - static_cast(right)); - } constexpr char prefix[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\"; } // OFFSET: 0x0086CC20 UIComboBoxDefWnd::UIComboBoxDefWnd(UIWindowContext& windows, UIComboBoxHeaderContext& controls) - : UIWindow(windows, 0), button(nullptr), list(nullptr), label(nullptr), borderless(0), expanded(0), red(255), - green(255), blue(255), borderRed(0), borderGreen(0), borderBlue(0), dropdownHeight(40), m_controls(&controls) { + : UIWindow(windows, 0), button(nullptr), list(nullptr), label(nullptr), borderless(0), expanded(0), red(255), green(255), blue(255), borderRed(0), + borderGreen(0), borderBlue(0), dropdownHeight(40), m_controls(&controls) { } // OFFSET: 0x00872AE0 @@ -39,15 +31,17 @@ void UIComboBoxDefWnd::Slot15(int, int) { } this->button->SetSize(this->button->BitmapWidth(), this->button->BitmapHeight()); - this->button->Move(Subtract(this->geometry.width, this->button->BitmapWidth()), 0); + this->button->Move((this->geometry.width - this->button->BitmapWidth()), 0); this->button->SetId(273); this->AddChild(this->button); + this->list = new UIComboBoxEx(*this->m_context, this->m_controls->combo); this->list->SetSize(this->geometry.width, this->dropdownHeight); this->list->Move(0, this->button->BitmapHeight()); this->AddChild(this->list); + this->label = new UIStaticText(*this->m_context, controls); - this->label->SetSize(Subtract(this->geometry.width, this->button->BitmapWidth()), this->button->BitmapHeight()); + this->label->SetSize((this->geometry.width - this->button->BitmapWidth()), this->button->BitmapHeight()); this->label->SetText("(NO SELECT)", 0); this->label->Move(2, 3); this->label->shadow = 1; @@ -57,17 +51,16 @@ void UIComboBoxDefWnd::Slot15(int, int) { // OFFSET: 0x00889D60 // FUNCTION: fn_11352 void UIComboBoxDefWnd::Paint() { - const unsigned background = static_cast(this->red) | (static_cast(this->green) << 8) | - (static_cast(this->blue) << 16); + const unsigned background = + static_cast(this->red) | (static_cast(this->green) << 8) | (static_cast(this->blue) << 16); if (this->borderless != 0) { this->geometry.surface->Fill(nullptr, background); } else { - const unsigned border = static_cast(this->borderRed) | - (static_cast(this->borderGreen) << 8) | - (static_cast(this->borderBlue) << 16); + const unsigned border = + static_cast(this->borderRed) | (static_cast(this->borderGreen) << 8) | (static_cast(this->borderBlue) << 16); this->geometry.surface->Fill(nullptr, border); - this->FillRegion(1, 1, Subtract(this->geometry.width, 2), Subtract(this->geometry.height, 2), background); + this->FillRegion(1, 1, (this->geometry.width - 2), (this->geometry.height - 2), background); } } @@ -92,23 +85,15 @@ void UIComboBoxDefWnd::Select(int index) { // OFFSET: 0x00897E90 // FUNCTION: fn_11544 -int UIComboBoxDefWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { - const int value = std::bit_cast(static_cast(a)); +int UIComboBoxDefWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { + const int value = static_cast(a); switch (message) { case 6: if (value == 273) { this->expanded = this->expanded == 0; this->Resize( - this->geometry.width, this->expanded ? Add(this->geometry.height, this->list->geometry.height) - : Subtract(this->geometry.height, this->list->geometry.height) + this->geometry.width, this->expanded ? (this->geometry.height + this->list->geometry.height) : (this->geometry.height - this->list->geometry.height) ); static_cast(this->parent)->Invalidate(); this->Invalidate(); @@ -128,13 +113,8 @@ int UIComboBoxDefWnd::SendMsg( return 0; case 39: - if ( - WindowPolicy( - this->m_controls->buttons.policy, this->m_controls->buttons.restricted, 3, - static_cast(this->parent)->geometry.id - ) == 0 || - value < 0 - ) { + if (WindowPolicy(this->m_controls->buttons.policy, this->m_controls->buttons.restricted, 3, static_cast(this->parent)->geometry.id) == 0 || + value < 0) { return 0; } @@ -168,6 +148,7 @@ UIComboBoxDef2Wnd::~UIComboBoxDef2Wnd() = default; void UIComboBoxDef2Wnd::Slot15(int width, int) { auto& controls = this->m_controls->buttons; const std::string path = std::string(prefix) + (this->skin == 1 ? "login_interface\\" : "UIadventurerAgency\\"); + this->button = new UIBitmapButton(*this->m_context, controls); const char* names[] = {"btn_dropdown_out.bmp", "btn_dropdown_over.bmp", "btn_dropdown_press.bmp"}; @@ -176,19 +157,19 @@ void UIComboBoxDef2Wnd::Slot15(int width, int) { } this->button->SetSize(this->button->BitmapWidth(), this->button->BitmapHeight()); - this->button->Move(Subtract(this->geometry.width, this->button->BitmapWidth()), 0); + this->button->Move((this->geometry.width - this->button->BitmapWidth()), 0); this->button->SetId(273); this->AddChild(this->button); + auto* list = new UIComboBoxEx2(*this->m_context, this->m_controls->combo); this->list = list; list->alignment = this->alignment; - list->SetSize(width, Add(this->dropdownHeight, 2)); + list->SetSize(width, (this->dropdownHeight + 2)); list->Move(0, this->button->BitmapHeight()); this->AddChild(list); + this->label = new UIStaticText(*this->m_context, controls); - this->label->SetSize( - Subtract(this->geometry.width, this->button->BitmapWidth()), Subtract(this->button->BitmapHeight(), 6) - ); + this->label->SetSize((this->geometry.width - this->button->BitmapWidth()), (this->button->BitmapHeight() - 6)); this->label->SetText("", 0); int x = 0; @@ -199,7 +180,7 @@ void UIComboBoxDef2Wnd::Slot15(int width, int) { } if (this->alignment == 0 || this->alignment == 1) { - this->label->Move(x, Add(this->textOffset, 3)); + this->label->Move(x, (this->textOffset + 3)); } this->label->shadow = 1; @@ -221,7 +202,7 @@ void UIComboBoxDef2Wnd::Paint() { if (x != this->previousTextX) { this->previousTextX = x; - this->label->Move(x, Add(this->textOffset, 3)); + this->label->Move(x, (this->textOffset + 3)); this->label->Invalidate(); } } diff --git a/Source/UI/UIComboBoxDefWnd.h b/Source/UI/Lists/UIComboBoxDefWnd.h similarity index 77% rename from Source/UI/UIComboBoxDefWnd.h rename to Source/UI/Lists/UIComboBoxDefWnd.h index 4c74281..bbdd991 100644 --- a/Source/UI/UIComboBoxDefWnd.h +++ b/Source/UI/Lists/UIComboBoxDefWnd.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UICOMBOBOXDEFWND_H -#define RAGNAROK_SOURCE_UI_UICOMBOBOXDEFWND_H +#ifndef RAGNAROK_SOURCE_UI_LISTS_UICOMBOBOXDEFWND_H +#define RAGNAROK_SOURCE_UI_LISTS_UICOMBOBOXDEFWND_H -#include "UI/UIComboBoxEx.h" -#include "UI/UIWindow.h" +#include "UI/Lists/UIComboBoxEx.h" +#include "UI/Window/UIWindow.h" class UIBitmapButton; class UIStaticText; @@ -13,7 +13,6 @@ struct UIComboBoxHeaderContext { UIButtonContext& buttons; }; -// RTTI UIComboBoxDefWnd, original x86 size 168. Children own list and label. class UIComboBoxDefWnd : public UIWindow { public: UIComboBoxDefWnd(UIWindowContext& windows, UIComboBoxHeaderContext& controls); @@ -21,14 +20,7 @@ public: void Slot15(int width, int height) override; void Paint() override; void Slot31(int x, int y) override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; void AddOption(std::string text, std::uint32_t color); void Select(int index); @@ -49,7 +41,6 @@ protected: UIComboBoxHeaderContext* m_controls; }; -// RTTI UIComboBoxDef2Wnd, original x86 size 184. class UIComboBoxDef2Wnd : public UIComboBoxDefWnd { public: UIComboBoxDef2Wnd(UIWindowContext& windows, UIComboBoxHeaderContext& controls); diff --git a/Source/UI/UIComboBoxEx.cpp b/Source/UI/Lists/UIComboBoxEx.cpp similarity index 65% rename from Source/UI/UIComboBoxEx.cpp rename to Source/UI/Lists/UIComboBoxEx.cpp index 0983e2c..e0e2f6d 100644 --- a/Source/UI/UIComboBoxEx.cpp +++ b/Source/UI/Lists/UIComboBoxEx.cpp @@ -1,41 +1,30 @@ -#include "Render/DeviceContext.h" -#include "Resource/BitmapResource.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/UIComboBoxEx.h" -#include "UI/UIListBox.h" -#include "UI/UIScrollBar.h" -#include "UI/UIScrollBarNavi.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Lists/UIComboBoxEx.h" +#include "UI/Lists/UIListBox.h" +#include "UI/Lists/UIScrollBar.h" +#include "UI/Lists/UIScrollBarNavi.h" +#include "UI/Window/WindowManagerWindows.h" #include -#include namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Subtract(int left, int right) { - return std::bit_cast(static_cast(left) - static_cast(right)); - } - int Multiply(int left, int right) { - return std::bit_cast(static_cast(left) * static_cast(right)); - } unsigned Palette(ResourceMgr& resources, int column, int row) { constexpr char path[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\colorchip.bmp"; auto* chip = static_cast(resources.Load(path)); const int x = column * 4 + 2; const int y = row * 4 + 2; const auto& image = chip->image; - const unsigned pixel = - x >= 0 && y >= 0 && x < image.width && y < image.height ? image.pixels[x + y * image.width] : 0x00FF0000u; + const unsigned pixel = x >= 0 && y >= 0 && x < image.width && y < image.height ? image.pixels[x + y * image.width] : 0x00FF0000u; + return ((pixel & 255) << 16) | (pixel & 0xFF00) | ((pixel >> 16) & 255); } } // OFFSET: 0x0086CD40 // FUNCTION: fn_11037 -UIComboBoxEx::UIComboBoxEx(UIWindowContext& windows, UIComboBoxContext& combo) - : UIListBoxEx(windows, combo.list), targetId(10041), m_combo(&combo) { +UIComboBoxEx::UIComboBoxEx(UIWindowContext& windows, UIComboBoxContext& combo) : UIListBoxEx(windows, combo.list), targetId(10041), m_combo(&combo) { } // OFFSET: 0x00872C00 @@ -64,7 +53,7 @@ void UIComboBoxEx::Resize(int width, int height) { this->UIListBoxEx::Resize(width, height); this->topLine = 0; this->verticalBar->position = 0; - this->verticalBar->Move(Subtract(width, 13), 0); + this->verticalBar->Move((width - 13), 0); if (this->verticalOverflow != 0) { this->verticalBar->Invalidate(); @@ -112,12 +101,12 @@ void UIComboBoxEx::Slot31(int x, int y) { void UIComboBoxEx::Refresh() { const int visible = this->geometry.height / this->lineHeight; const int count = static_cast(this->lines.size()); - const int overflow = std::max(Subtract(count, visible), 0); + const int overflow = std::max((count - visible), 0); this->verticalOverflow = overflow != 0; auto* bar = this->verticalBar; bar->visible = visible; bar->total = count; - bar->maximum = overflow != 0 ? Add(overflow, this->bottomMargin) : 0; + bar->maximum = overflow != 0 ? (overflow + this->bottomMargin) : 0; bar->Invalidate(); if (bar->position > bar->maximum) { @@ -127,8 +116,8 @@ void UIComboBoxEx::Refresh() { if (overflow != 0) { if (this->selected < this->topLine) { this->topLine = this->selected; - } else if (Add(this->topLine, visible) <= this->selected) { - this->topLine = Add(Subtract(this->selected, visible), 1); + } else if ((this->topLine + visible) <= this->selected) { + this->topLine = ((this->selected - visible) + 1); } this->topLine = std::clamp(this->topLine, 0, overflow); @@ -147,15 +136,8 @@ void UIComboBoxEx::Refresh() { // OFFSET: 0x00898050 // FUNCTION: fn_11545 -int UIComboBoxEx::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { - const int value = std::bit_cast(static_cast(a)); +int UIComboBoxEx::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { + const int value = static_cast(a); const unsigned count = static_cast(this->lines.size()); switch (message) { @@ -174,7 +156,7 @@ int UIComboBoxEx::SendMsg( return 0; } - this->selected = std::max(Subtract(this->selected, 1), 0); + this->selected = std::max((this->selected - 1), 0); if (this->selected < this->topLine) { this->topLine = this->selected; @@ -186,17 +168,17 @@ int UIComboBoxEx::SendMsg( return 0; } - this->selected = Add(this->selected, 1); + this->selected = (this->selected + 1); if (static_cast(this->selected) >= count) { this->selected = static_cast(count - 1); } { - const int edge = Add(Subtract(this->bottomMargin, this->geometry.height / this->lineHeight), this->selected); + const int edge = ((this->bottomMargin - this->geometry.height / this->lineHeight) + this->selected); if (this->topLine <= edge) { - this->topLine = Add(edge, 1); + this->topLine = (edge + 1); } } @@ -227,24 +209,20 @@ int UIComboBoxEx::SendMsg( void UIComboBoxEx::DrawRows(bool centered) { const unsigned end = std::min( - static_cast(this->lines.size()), - static_cast(Add(this->topLine, Subtract(this->geometry.height / this->lineHeight, this->bottomMargin))) + static_cast(this->lines.size()), static_cast((this->topLine + (this->geometry.height / this->lineHeight - this->bottomMargin))) ); auto& owner = *this->m_listContext; - for (int index = this->topLine; index < static_cast(end); index = Add(index, 1)) { + for (int index = this->topLine; index < static_cast(end); index = (index + 1)) { auto& row = this->lines[index]; - int x = Subtract(3, this->horizontalOffset); + int x = (3 - this->horizontalOffset); if (centered) { const int width = this->TextWidth(owner.fonts, owner.locale, row.text.c_str(), 0, 0, 12, 0, 0); x = static_cast(static_cast(this->geometry.width) * 0.5f - static_cast(width) * 0.5f); } - this->DrawTextAt( - owner.fonts, owner.locale, x, Add(Multiply(this->lineHeight, Subtract(index, this->topLine)), 2), - row.text.c_str(), 0, 0, 12, row.color, 0, 0 - ); + this->DrawTextAt(owner.fonts, owner.locale, x, ((this->lineHeight * (index - this->topLine)) + 2), row.text.c_str(), 0, 0, 12, row.color, 0, 0); } } @@ -253,36 +231,32 @@ void UIComboBoxEx::DrawRows(bool centered) { void UIComboBoxEx::Paint() { auto& resources = this->m_listContext->resources; this->geometry.surface->Fill(nullptr, Palette(resources, 6, 6)); - this->FillRegion( - 1, 1, Subtract(this->geometry.width, 2), Subtract(this->geometry.height, 2), Palette(resources, 2, 2) - ); + this->FillRegion(1, 1, (this->geometry.width - 2), (this->geometry.height - 2), Palette(resources, 2, 2)); constexpr char prefix[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\"; const char* names[] = {"sysboxs_lu.bmp", "sysboxs_ld.bmp", "sysboxs_ru.bmp", "sysboxs_rd.bmp"}; for (int corner = 0; corner < 4; ++corner) { auto* resource = static_cast(resources.Load((std::string(prefix) + names[corner]).c_str())); this->DrawBitmap( - corner >= 2 ? Subtract(this->geometry.width, resource->image.width) : 0, - (corner & 1) ? Subtract(this->geometry.height, resource->image.height) : 0, &resource->image, false + corner >= 2 ? (this->geometry.width - resource->image.width) : 0, (corner & 1) ? (this->geometry.height - resource->image.height) : 0, &resource->image, + false ); } const unsigned end = std::min( - static_cast(this->lines.size()), - static_cast(Add(this->topLine, Subtract(this->geometry.height / this->lineHeight, this->bottomMargin))) + static_cast(this->lines.size()), static_cast((this->topLine + (this->geometry.height / this->lineHeight - this->bottomMargin))) ); if (this->selected >= this->topLine && this->selected < static_cast(end)) { this->FillRegion( - 3, Add(Multiply(this->lineHeight, Subtract(this->selected, this->topLine)), 1), Subtract(this->geometry.width, 6), - Subtract(this->lineHeight, 2), Palette(resources, 6, 2) + 3, ((this->lineHeight * (this->selected - this->topLine)) + 1), (this->geometry.width - 6), (this->lineHeight - 2), Palette(resources, 6, 2) ); } this->DrawRows(false); if (this->verticalOverflow != 0) { - this->FillRegion(Subtract(this->geometry.width, 16), 0, 16, this->geometry.height, Palette(resources, 2, 2)); + this->FillRegion((this->geometry.width - 16), 0, 16, this->geometry.height, Palette(resources, 2, 2)); } static_cast(this->parent)->Invalidate(); @@ -290,8 +264,7 @@ void UIComboBoxEx::Paint() { // OFFSET: 0x00885250 // FUNCTION: fn_11318 -UIComboBoxEx2::UIComboBoxEx2(UIWindowContext& windows, UIComboBoxContext& combo) - : UIComboBoxEx(windows, combo), alignment(0) { +UIComboBoxEx2::UIComboBoxEx2(UIWindowContext& windows, UIComboBoxContext& combo) : UIComboBoxEx(windows, combo), alignment(0) { } // OFFSET: 0x00872B50 @@ -306,17 +279,18 @@ void UIComboBoxEx2::Slot15(int width, int height) { this->verticalBar = vertical; vertical->vertical = 1; vertical->UIWindow::Resize(vertical->thickness, height); - vertical->Move(Subtract(width, 7), 0); + vertical->Move((width - 7), 0); vertical->Slot15(vertical->thickness, height); vertical->Slot22(vertical->thickness, height); this->AddChild(vertical); + auto* horizontal = new UIScrollBar(*this->m_context, list.capture, list.resources); this->horizontalBar = horizontal; horizontal->vertical = 0; - horizontal->UIWindow::Resize(Subtract(width, 7), horizontal->thickness); - horizontal->Move(0, Subtract(height, 7)); - horizontal->Slot15(Subtract(width, 7), horizontal->thickness); - horizontal->Slot22(Subtract(width, 7), horizontal->thickness); + horizontal->UIWindow::Resize((width - 7), horizontal->thickness); + horizontal->Move(0, (height - 7)); + horizontal->Slot15((width - 7), horizontal->thickness); + horizontal->Slot22((width - 7), horizontal->thickness); this->AddChild(horizontal); this->lineHeight = 18; } @@ -326,13 +300,13 @@ void UIComboBoxEx2::Slot15(int width, int height) { void UIComboBoxEx2::Resize(int width, int height) { this->UIWindow::Resize(width, height); this->Refresh(); - this->verticalBar->Move(Subtract(width, 7), 0); + this->verticalBar->Move((width - 7), 0); if (this->verticalOverflow != 0) { this->verticalBar->Invalidate(); } else { this->verticalBar->Resize(7, height); - this->verticalBar->Move(Subtract(width, 6), 0); + this->verticalBar->Move((width - 6), 0); } } @@ -340,17 +314,13 @@ void UIComboBoxEx2::Resize(int width, int height) { // FUNCTION: fn_11353 void UIComboBoxEx2::Paint() { this->geometry.surface->Fill(nullptr, 0xC59582u); - this->FillRegion(1, 1, Subtract(this->geometry.width, 2), Subtract(this->geometry.height, 2), 0xFCF4F0u); + this->FillRegion(1, 1, (this->geometry.width - 2), (this->geometry.height - 2), 0xFCF4F0u); const unsigned end = std::min( - static_cast(this->lines.size()), - static_cast(Add(this->topLine, Subtract(this->geometry.height / this->lineHeight, this->bottomMargin))) + static_cast(this->lines.size()), static_cast((this->topLine + (this->geometry.height / this->lineHeight - this->bottomMargin))) ); if (this->selected >= this->topLine && this->selected < static_cast(end)) { - this->FillRegion( - 3, Add(Multiply(this->lineHeight, Subtract(this->selected, this->topLine)), 1), Subtract(this->geometry.width, 6), - Subtract(this->lineHeight, 2), 0xF8D5C4u - ); + this->FillRegion(3, ((this->lineHeight * (this->selected - this->topLine)) + 1), (this->geometry.width - 6), (this->lineHeight - 2), 0xF8D5C4u); } if (this->alignment == 0 || this->alignment == 1) { diff --git a/Source/UI/UIComboBoxEx.h b/Source/UI/Lists/UIComboBoxEx.h similarity index 70% rename from Source/UI/UIComboBoxEx.h rename to Source/UI/Lists/UIComboBoxEx.h index a78bb3a..e93ae8b 100644 --- a/Source/UI/UIComboBoxEx.h +++ b/Source/UI/Lists/UIComboBoxEx.h @@ -1,15 +1,14 @@ -#ifndef RAGNAROK_SOURCE_UI_UICOMBOBOXEX_H -#define RAGNAROK_SOURCE_UI_UICOMBOBOXEX_H +#ifndef RAGNAROK_SOURCE_UI_LISTS_UICOMBOBOXEX_H +#define RAGNAROK_SOURCE_UI_LISTS_UICOMBOBOXEX_H -#include "UI/UIListBoxEx.h" +#include "UI/Lists/UIListBoxEx.h" struct UIComboBoxContext { UIListBoxContext& list; - // Actual UIWindowMgr popup pointer and modal state, not a duplicate owner. + UIWindow* const& popup; }; -// RTTI UIComboBoxEx, original x86 size 196; inherits UIListBoxEx's map. class UIComboBoxEx : public UIListBoxEx { public: UIComboBoxEx(UIWindowContext& windows, UIComboBoxContext& combo); @@ -21,14 +20,7 @@ public: void Slot26(int x, int y) override; void Slot27(int x, int y) override; void Slot31(int x, int y) override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; void Configure(int x, int y, int width, int height, unsigned char transparent) override; void Refresh() override; @@ -39,7 +31,6 @@ protected: void DrawRows(bool centered); }; -// RTTI UIComboBoxEx2, original x86 size 200, navigation scrollbar skin. class UIComboBoxEx2 : public UIComboBoxEx { public: UIComboBoxEx2(UIWindowContext& windows, UIComboBoxContext& combo); diff --git a/Source/UI/UIDropDownBox.cpp b/Source/UI/Lists/UIDropDownBox.cpp similarity index 88% rename from Source/UI/UIDropDownBox.cpp rename to Source/UI/Lists/UIDropDownBox.cpp index c6bb0f5..106ca6a 100644 --- a/Source/UI/UIDropDownBox.cpp +++ b/Source/UI/Lists/UIDropDownBox.cpp @@ -1,7 +1,7 @@ -#include "Render/DeviceContext.h" -#include "UI/UIDropDownBox.h" -#include "UI/WindowBorder.h" -#include "UI/WindowOrdering.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "UI/Lists/UIDropDownBox.h" +#include "UI/Window/WindowBorder.h" +#include "UI/Window/WindowOrdering.h" #include @@ -37,9 +37,7 @@ bool CUIDropDownBox::HasChild(const UIWindow* window) const { // OFFSET: 0x009E3490 // FUNCTION: fn_14418 bool CUIDropDownBox::HasOwnerChild(const UIWindow* window) const { - return window && this->owner && - std::find(this->owner->m_children.begin(), this->owner->m_children.end(), window) != - this->owner->m_children.end(); + return window && this->owner && std::find(this->owner->m_children.begin(), this->owner->m_children.end(), window) != this->owner->m_children.end(); } // OFFSET: 0x009E3500 diff --git a/Source/UI/UIDropDownBox.h b/Source/UI/Lists/UIDropDownBox.h similarity index 67% rename from Source/UI/UIDropDownBox.h rename to Source/UI/Lists/UIDropDownBox.h index 365ba49..046fe04 100644 --- a/Source/UI/UIDropDownBox.h +++ b/Source/UI/Lists/UIDropDownBox.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_UI_UIDROPDOWNBOX_H -#define RAGNAROK_SOURCE_UI_UIDROPDOWNBOX_H +#ifndef RAGNAROK_SOURCE_UI_LISTS_UIDROPDOWNBOX_H +#define RAGNAROK_SOURCE_UI_LISTS_UIDROPDOWNBOX_H -#include "UI/UIControl.h" +#include "UI/Window/UIControl.h" struct WindowOrdering; -// RTTI CUIDropDownBox. Its attached child is borrowed from another window; -// detachment deliberately preserves that child's parent pointer and lifetime. + class CUIDropDownBox : public CUIControl { public: explicit CUIDropDownBox(UIWindowContext& context); @@ -19,7 +18,6 @@ public: /* 0080 */ UIWindow* owner; }; -// Borrowed manager popup pointer and rendered-order owner. struct WindowDropDown { UIWindowContext& windows; WindowOrdering& ordering; diff --git a/Source/UI/UIListBox.cpp b/Source/UI/Lists/UIListBox.cpp similarity index 65% rename from Source/UI/UIListBox.cpp rename to Source/UI/Lists/UIListBox.cpp index 0fa011a..9950fd2 100644 --- a/Source/UI/UIListBox.cpp +++ b/Source/UI/Lists/UIListBox.cpp @@ -1,46 +1,30 @@ -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "Resource/BitmapResource.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/ColoredText.h" -#include "UI/UIListBox.h" -#include "UI/UIScrollBar.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Text/ColoredText.h" +#include "UI/Lists/UIListBox.h" +#include "UI/Lists/UIScrollBar.h" +#include "UI/Window/WindowManagerWindows.h" #include -#include #include -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - - int Subtract(int left, int right) { - return std::bit_cast(static_cast(left) - static_cast(right)); - } - - int Multiply(int left, int right) { - return std::bit_cast(static_cast(left) * static_cast(right)); - } -} +namespace {} // OFFSET: 0x0086D940 // FUNCTION: fn_11055 UIListBox::UIListBox(UIWindowContext& windows, UIListBoxContext& list) - : UIWindow(windows, 0), backgroundRed(255), backgroundGreen(255), backgroundBlue(255), selected(0), topLine(0), - horizontalOffset(0), contentWidth(0), verticalOverflow(0), bottomMargin(0), verticalBar(nullptr), - horizontalBar(nullptr), transparent(0), lineHeight(16), selectable(1), textColor(0), centerVertically(0), - textInset(3), m_listContext(&list) { - // Original color service samples colorchip cell (3,2), pixel (14,10). + : UIWindow(windows, 0), backgroundRed(255), backgroundGreen(255), backgroundBlue(255), selected(0), topLine(0), horizontalOffset(0), contentWidth(0), + verticalOverflow(0), bottomMargin(0), verticalBar(nullptr), horizontalBar(nullptr), transparent(0), lineHeight(16), selectable(1), textColor(0), + centerVertically(0), textInset(3), m_listContext(&list) { constexpr char path[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\colorchip.bmp"; const auto* chip = static_cast(list.resources.Load(path)); this->selectionColor = 0; if (chip) { const auto& image = chip->image; - const std::uint32_t pixel = - image.width > 14 && image.height > 10 ? image.pixels[14 + 10 * image.width] : 0x00FF0000u; + const std::uint32_t pixel = image.width > 14 && image.height > 10 ? image.pixels[14 + 10 * image.width] : 0x00FF0000u; this->selectionColor = ((pixel & 255) << 16) | (pixel & 0xFF00) | ((pixel >> 16) & 255); } } @@ -68,7 +52,7 @@ void UIListBox::Slot15(int width, int height) { const int verticalWidth = vertical->thickness; vertical->vertical = 1; vertical->UIWindow::Resize(verticalWidth, height); - vertical->Move(Subtract(width, 13), 0); + vertical->Move((width - 13), 0); vertical->Slot15(verticalWidth, height); vertical->Slot22(verticalWidth, height); this->AddChild(vertical); @@ -77,10 +61,10 @@ void UIListBox::Slot15(int width, int height) { this->horizontalBar = horizontal; const int horizontalHeight = horizontal->thickness; horizontal->vertical = 0; - horizontal->UIWindow::Resize(Subtract(width, 13), horizontalHeight); - horizontal->Move(0, Subtract(height, 13)); - horizontal->Slot15(Subtract(width, 13), horizontalHeight); - horizontal->Slot22(Subtract(width, 13), horizontalHeight); + horizontal->UIWindow::Resize((width - 13), horizontalHeight); + horizontal->Move(0, (height - 13)); + horizontal->Slot15((width - 13), horizontalHeight); + horizontal->Slot22((width - 13), horizontalHeight); this->AddChild(horizontal); } @@ -89,9 +73,9 @@ void UIListBox::Slot15(int width, int height) { void UIListBox::Resize(int width, int height) { UIWindow::Resize(width, height); this->verticalBar->Resize(12, height); - this->verticalBar->Move(Subtract(width, 13), 0); - this->horizontalBar->Resize(Subtract(width, 13), 12); - this->horizontalBar->Move(0, Subtract(height, 13)); + this->verticalBar->Move((width - 13), 0); + this->horizontalBar->Resize((width - 13), 12); + this->horizontalBar->Move(0, (height - 13)); this->Refresh(); this->topLine = 0; } @@ -125,9 +109,10 @@ void UIListBox::Clear() { void UIListBox::Refresh() { const int visible = this->geometry.height / this->lineHeight; const int count = static_cast(this->lines.size()); - const int overflow = std::max(Subtract(count, visible), 0); + const int overflow = std::max((count - visible), 0); + this->verticalOverflow = overflow != 0; - this->verticalBar->maximum = overflow != 0 ? Add(this->bottomMargin, overflow) : 0; + this->verticalBar->maximum = overflow != 0 ? (this->bottomMargin + overflow) : 0; this->verticalBar->total = count; this->verticalBar->visible = visible; this->verticalBar->Invalidate(); @@ -146,7 +131,7 @@ int UIListBox::LineAt(int x, int y) const { return -1; } - const int index = Add(this->topLine, y / this->lineHeight); + const int index = (this->topLine + y / this->lineHeight); return index >= 0 && static_cast(index) < this->lines.size() ? index : -1; } @@ -190,27 +175,26 @@ void UIListBox::Paint() { static_cast(this->parent)->Invalidate(); } } else if (this->geometry.surface) { - const std::uint32_t color = - (this->backgroundRed & 255) | ((this->backgroundGreen & 255) << 8) | ((this->backgroundBlue & 255) << 16); + const std::uint32_t color = (this->backgroundRed & 255) | ((this->backgroundGreen & 255) << 8) | ((this->backgroundBlue & 255) << 16); this->geometry.surface->Fill(nullptr, color); } const int first = this->topLine; - const int limit = Add(Subtract(this->geometry.height / this->lineHeight, this->bottomMargin), first); + const int limit = ((this->geometry.height / this->lineHeight - this->bottomMargin) + first); const int end = static_cast(std::min(static_cast(this->lines.size()), static_cast(limit))); std::uint32_t color = this->textColor; auto& owner = *this->m_listContext; for (int index = first; index < end; ++index) { - const int row = Subtract(index, first); - int y = Multiply(row, this->lineHeight); + const int row = (index - first); + int y = (row * this->lineHeight); if (index == this->selected) { - this->FillRegion(0, y, this->geometry.width, Subtract(this->lineHeight, 1), this->selectionColor); + this->FillRegion(0, y, this->geometry.width, (this->lineHeight - 1), this->selectionColor); } const auto& line = this->lines[index]; - const int x = Subtract(this->textInset, this->horizontalOffset); + const int x = (this->textInset - this->horizontalOffset); if (this->centerVertically == 1) { int height = 0; @@ -221,27 +205,17 @@ void UIListBox::Paint() { height = context.Measure(line.c_str(), static_cast(std::strlen(line.c_str()))).cy; } - y = static_cast(static_cast(Subtract(this->lineHeight, height)) * 0.5f + static_cast(y)); + y = static_cast(static_cast((this->lineHeight - height)) * 0.5f + static_cast(y)); } - DrawColoredText( - *this, owner.fonts, owner.locale, owner.codePage, x, y, line.c_str(), static_cast(line.size()), color, - 0, 12, false - ); + DrawColoredText(*this, owner.fonts, owner.locale, owner.codePage, x, y, line.c_str(), static_cast(line.size()), color, 0, 12, false); } } // OFFSET: 0x00898B00 // FUNCTION: fn_11552 -int UIListBox::SendMsg( - UIWindow* sender, - int message, - std::intptr_t argument1, - std::intptr_t argument2, - std::intptr_t argument3, - std::intptr_t argument4 -) { - const int value = std::bit_cast(static_cast(argument1)); +int UIListBox::SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) { + const int value = static_cast(argument1); switch (message) { case 7: @@ -249,15 +223,14 @@ int UIListBox::SendMsg( case 10: { const int previous = this->topLine; const int visible = this->geometry.height / this->lineHeight; - const int delta = message == 9 ? Subtract(1, visible) : message == 10 ? Subtract(visible, 1) : value; - this->topLine = Add(previous, delta); + const int delta = message == 9 ? (1 - visible) : message == 10 ? (visible - 1) : value; + this->topLine = (previous + delta); if (this->topLine < 0) { this->topLine = 0; } - // This comparison is unsigned in the original, unlike horizontal scroll. - const int maximum = Add(Subtract(static_cast(this->lines.size()), visible), this->bottomMargin); + const int maximum = ((static_cast(this->lines.size()) - visible) + this->bottomMargin); if (static_cast(this->topLine) > static_cast(maximum)) { this->topLine = maximum; @@ -271,20 +244,20 @@ int UIListBox::SendMsg( static_cast(this->parent)->Invalidate(); } - return Subtract(this->topLine, previous); + return (this->topLine - previous); } case 8: case 11: case 12: { const int previous = this->horizontalOffset; const int delta = message == 11 ? -15 : message == 12 ? 15 : value; - this->horizontalOffset = Add(previous, delta); + this->horizontalOffset = (previous + delta); if (this->horizontalOffset < 0) { this->horizontalOffset = 0; } - const int maximum = Add(Subtract(Multiply(this->verticalOverflow, 16), this->geometry.width), this->contentWidth); + const int maximum = (((this->verticalOverflow * 16) - this->geometry.width) + this->contentWidth); if (this->horizontalOffset > maximum) { this->horizontalOffset = maximum; @@ -298,10 +271,10 @@ int UIListBox::SendMsg( static_cast(this->parent)->Invalidate(); } - return Subtract(this->horizontalOffset, previous); + return (this->horizontalOffset - previous); } case 18: - this->selected = Subtract(this->selected, 1); + this->selected = (this->selected - 1); if (this->selected < 0) { this->selected = 0; @@ -314,13 +287,13 @@ int UIListBox::SendMsg( break; case 19: case 40: { - this->selected = message == 19 ? Add(this->selected, 1) : value; + this->selected = message == 19 ? (this->selected + 1) : value; if (message == 40 && this->selected < 0) { this->selected = 0; } - const int last = Subtract(static_cast(this->lines.size()), 1); + const int last = (static_cast(this->lines.size()) - 1); if (static_cast(this->selected) > static_cast(last)) { this->selected = last; @@ -333,10 +306,9 @@ int UIListBox::SendMsg( top = this->topLine; } - // Selection scrolls by one row, even for a distant explicit selection. - const int edge = message == 19 ? Subtract(top, 1) : top; + const int edge = message == 19 ? (top - 1) : top; const int rows = this->geometry.height / this->lineHeight; - const int bottom = Add(edge, message == 19 ? rows : Subtract(rows, 1)); + const int bottom = (edge + (message == 19 ? rows : (rows - 1))); if (this->selected > bottom) { this->SendMsg(nullptr, 7, 1, 0, 0, 0); diff --git a/Source/UI/UIListBox.h b/Source/UI/Lists/UIListBox.h similarity index 69% rename from Source/UI/UIListBox.h rename to Source/UI/Lists/UIListBox.h index bef3321..661405c 100644 --- a/Source/UI/UIListBox.h +++ b/Source/UI/Lists/UIListBox.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UILISTBOX_H -#define RAGNAROK_SOURCE_UI_UILISTBOX_H +#ifndef RAGNAROK_SOURCE_UI_LISTS_UILISTBOX_H +#define RAGNAROK_SOURCE_UI_LISTS_UILISTBOX_H -#include "UI/UIWindow.h" +#include "UI/Window/UIWindow.h" #include #include @@ -20,8 +20,6 @@ struct UIListBoxContext { WindowManagerWindows& windows; }; -// RTTI UIListBox. Children own both scrollbars; this -// vector owns the line strings. Original x86 size 212, source size 220. class UIListBox : public UIWindow { public: UIListBox(UIWindowContext& windows, UIListBoxContext& list); @@ -33,19 +31,12 @@ public: void Slot26(int x, int y) override; void Slot32(int x, int y) override; void Slot35(int value) override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t argument1, - std::intptr_t argument2, - std::intptr_t argument3, - std::intptr_t argument4 - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) override; - virtual void Configure(int x, int y, int width, int height, unsigned char transparent); // 53 - virtual void AddLine(const char* text); // 54 - virtual void Clear(); // 55 - virtual void Refresh(); // 56 + virtual void Configure(int x, int y, int width, int height, unsigned char transparent); + virtual void AddLine(const char* text); + virtual void Clear(); + virtual void Refresh(); int LineAt(int x, int y) const; /* 007C */ int backgroundRed; diff --git a/Source/UI/UIListBoxEx.cpp b/Source/UI/Lists/UIListBoxEx.cpp similarity index 65% rename from Source/UI/UIListBoxEx.cpp rename to Source/UI/Lists/UIListBoxEx.cpp index 29a15f2..b388738 100644 --- a/Source/UI/UIListBoxEx.cpp +++ b/Source/UI/Lists/UIListBoxEx.cpp @@ -1,39 +1,25 @@ -#include "Render/DeviceContext.h" -#include "Resource/BitmapResource.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/ColoredText.h" -#include "UI/UIListBox.h" -#include "UI/UIListBoxEx.h" -#include "UI/UIScrollBar.h" +#include "UI/Text/ColoredText.h" +#include "UI/Lists/UIListBox.h" +#include "UI/Lists/UIListBoxEx.h" +#include "UI/Lists/UIScrollBar.h" #include -#include - -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Subtract(int left, int right) { - return std::bit_cast(static_cast(left) - static_cast(right)); - } - int Multiply(int left, int right) { - return std::bit_cast(static_cast(left) * static_cast(right)); - } -} // OFFSET: 0x0086DA90 // FUNCTION: fn_11056 UIListBoxEx::UIListBoxEx(UIWindowContext& windows, UIListBoxContext& list) - : UIWindow(windows, 0), backgroundRed(255), backgroundGreen(255), backgroundBlue(255), selected(0), topLine(0), - horizontalOffset(0), contentWidth(0), verticalOverflow(0), bottomMargin(0), verticalBar(nullptr), - horizontalBar(nullptr), transparent(0), lineHeight(16), selectionColor(0), m_listContext(&list) { + : UIWindow(windows, 0), backgroundRed(255), backgroundGreen(255), backgroundBlue(255), selected(0), topLine(0), horizontalOffset(0), contentWidth(0), + verticalOverflow(0), bottomMargin(0), verticalBar(nullptr), horizontalBar(nullptr), transparent(0), lineHeight(16), selectionColor(0), + m_listContext(&list) { constexpr char path[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\colorchip.bmp"; const auto* chip = static_cast(list.resources.Load(path)); if (chip) { const auto& image = chip->image; - const std::uint32_t pixel = - image.width > 10 && image.height > 10 ? image.pixels[10 + 10 * image.width] : 0x00FF0000u; + const std::uint32_t pixel = image.width > 10 && image.height > 10 ? image.pixels[10 + 10 * image.width] : 0x00FF0000u; this->selectionColor = ((pixel & 255) << 16) | (pixel & 0xFF00) | ((pixel >> 16) & 255); } } @@ -61,7 +47,7 @@ void UIListBoxEx::Slot15(int width, int height) { const int thickness = vertical->thickness; vertical->vertical = 1; vertical->UIWindow::Resize(thickness, height); - vertical->Move(Subtract(width, 13), 0); + vertical->Move((width - 13), 0); vertical->Slot15(thickness, height); vertical->Slot22(thickness, height); this->AddChild(vertical); @@ -70,10 +56,10 @@ void UIListBoxEx::Slot15(int width, int height) { this->horizontalBar = horizontal; const int horizontalHeight = horizontal->thickness; horizontal->vertical = 0; - horizontal->UIWindow::Resize(Subtract(width, 13), horizontalHeight); - horizontal->Move(0, Subtract(height, 13)); - horizontal->Slot15(Subtract(width, 13), horizontalHeight); - horizontal->Slot22(Subtract(width, 13), horizontalHeight); + horizontal->UIWindow::Resize((width - 13), horizontalHeight); + horizontal->Move(0, (height - 13)); + horizontal->Slot15((width - 13), horizontalHeight); + horizontal->Slot22((width - 13), horizontalHeight); this->AddChild(horizontal); } @@ -82,9 +68,9 @@ void UIListBoxEx::Slot15(int width, int height) { void UIListBoxEx::Resize(int width, int height) { UIWindow::Resize(width, height); this->verticalBar->Resize(12, height); - this->verticalBar->Move(Subtract(width, 13), 0); - this->horizontalBar->Resize(Subtract(width, 13), 12); - this->horizontalBar->Move(0, Subtract(height, 13)); + this->verticalBar->Move((width - 13), 0); + this->horizontalBar->Resize((width - 13), 12); + this->horizontalBar->Move(0, (height - 13)); this->Refresh(); } @@ -115,9 +101,10 @@ void UIListBoxEx::Clear() { void UIListBoxEx::Refresh() { const int visible = this->geometry.height / this->lineHeight; const int count = static_cast(this->lines.size()); - const int overflow = std::max(Subtract(count, visible), 0); + const int overflow = std::max((count - visible), 0); + this->verticalOverflow = overflow != 0; - this->verticalBar->maximum = overflow != 0 ? Add(this->bottomMargin, overflow) : 0; + this->verticalBar->maximum = overflow != 0 ? (this->bottomMargin + overflow) : 0; this->verticalBar->total = count; this->verticalBar->visible = visible; this->verticalBar->Invalidate(); @@ -134,7 +121,7 @@ int UIListBoxEx::LineAt(int x, int y) const { return -1; } - const int index = Add(this->topLine, y / this->lineHeight); + const int index = (this->topLine + y / this->lineHeight); return index >= 0 && static_cast(index) < this->lines.size() ? index : -1; } @@ -171,46 +158,36 @@ void UIListBoxEx::Paint() { static_cast(this->parent)->Invalidate(); } } else { - const unsigned color = static_cast(this->backgroundRed) | - (static_cast(this->backgroundGreen) << 8) | + const unsigned color = static_cast(this->backgroundRed) | (static_cast(this->backgroundGreen) << 8) | (static_cast(this->backgroundBlue) << 16); this->geometry.surface->Fill(nullptr, color); } const unsigned end = std::min( - static_cast(this->lines.size()), - static_cast(Add(this->topLine, Subtract(this->geometry.height / this->lineHeight, this->bottomMargin))) + static_cast(this->lines.size()), static_cast((this->topLine + (this->geometry.height / this->lineHeight - this->bottomMargin))) ); auto& owner = *this->m_listContext; - for (int index = this->topLine; index < static_cast(end); index = Add(index, 1)) { - const int y = Multiply(this->lineHeight, Subtract(index, this->topLine)); + for (int index = this->topLine; index < static_cast(end); index = (index + 1)) { + const int y = (this->lineHeight * (index - this->topLine)); if (index == this->selected) { - this->FillRegion(0, y, this->geometry.width, Subtract(this->lineHeight, 1), this->selectionColor); + this->FillRegion(0, y, this->geometry.width, (this->lineHeight - 1), this->selectionColor); } - // Original operator[] materializes gaps while painting. auto& line = this->lines[index]; auto color = line.color; DrawColoredText( - *this, owner.fonts, owner.locale, owner.codePage, Subtract(3, this->horizontalOffset), y, line.text.c_str(), - static_cast(line.text.size()), color, 0, 12, false + *this, owner.fonts, owner.locale, owner.codePage, (3 - this->horizontalOffset), y, line.text.c_str(), static_cast(line.text.size()), color, 0, + 12, false ); } } // OFFSET: 0x00898EB0 // FUNCTION: fn_11553 -int UIListBoxEx::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { - const int value = std::bit_cast(static_cast(a)); +int UIListBoxEx::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { + const int value = static_cast(a); switch (message) { case 7: @@ -218,9 +195,9 @@ int UIListBoxEx::SendMsg( case 10: { const int previous = this->topLine; const int visible = this->geometry.height / this->lineHeight; - const int delta = message == 9 ? Subtract(1, visible) : message == 10 ? Subtract(visible, 1) : value; - this->topLine = std::max(Add(previous, delta), 0); - const int maximum = Add(Subtract(static_cast(this->lines.size()), visible), this->bottomMargin); + const int delta = message == 9 ? (1 - visible) : message == 10 ? (visible - 1) : value; + this->topLine = std::max((previous + delta), 0); + const int maximum = ((static_cast(this->lines.size()) - visible) + this->bottomMargin); if (static_cast(this->topLine) > static_cast(maximum)) { this->topLine = maximum; @@ -241,15 +218,15 @@ int UIListBoxEx::SendMsg( } root->Invalidate(); - return Subtract(this->topLine, previous); + return (this->topLine - previous); } case 8: case 11: case 12: { const int previous = this->horizontalOffset; const int delta = message == 11 ? -15 : message == 12 ? 15 : value; - this->horizontalOffset = std::max(Add(previous, delta), 0); - const int maximum = Add(Subtract(Multiply(16, this->verticalOverflow), this->geometry.width), this->contentWidth); + this->horizontalOffset = std::max((previous + delta), 0); + const int maximum = (((16 * this->verticalOverflow) - this->geometry.width) + this->contentWidth); if (this->horizontalOffset > maximum) { this->horizontalOffset = maximum; @@ -263,10 +240,10 @@ int UIListBoxEx::SendMsg( static_cast(this->parent)->Invalidate(); } - return Subtract(this->horizontalOffset, previous); + return (this->horizontalOffset - previous); } case 18: - this->selected = std::max(Subtract(this->selected, 1), 0); + this->selected = std::max((this->selected - 1), 0); if (this->selected < this->topLine) { this->SendMsg(nullptr, 7, -1, 0, 0, 0); @@ -275,8 +252,8 @@ int UIListBoxEx::SendMsg( break; case 19: case 40: { - this->selected = message == 19 ? Add(this->selected, 1) : std::max(value, 0); - const int last = Subtract(static_cast(this->lines.size()), 1); + this->selected = message == 19 ? (this->selected + 1) : std::max(value, 0); + const int last = (static_cast(this->lines.size()) - 1); if (static_cast(this->selected) > static_cast(last)) { this->selected = last; @@ -289,7 +266,7 @@ int UIListBoxEx::SendMsg( top = this->topLine; } - const int bottom = Add(Add(top, this->geometry.height / this->lineHeight), -1); + const int bottom = ((top + this->geometry.height / this->lineHeight) - 1); if (this->selected > bottom) { this->SendMsg(nullptr, 7, 1, 0, 0, 0); diff --git a/Source/UI/UIListBoxEx.h b/Source/UI/Lists/UIListBoxEx.h similarity index 66% rename from Source/UI/UIListBoxEx.h rename to Source/UI/Lists/UIListBoxEx.h index f89891e..c17e3eb 100644 --- a/Source/UI/UIListBoxEx.h +++ b/Source/UI/Lists/UIListBoxEx.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UILISTBOXEX_H -#define RAGNAROK_SOURCE_UI_UILISTBOXEX_H +#ifndef RAGNAROK_SOURCE_UI_LISTS_UILISTBOXEX_H +#define RAGNAROK_SOURCE_UI_LISTS_UILISTBOXEX_H -#include "UI/UIWindow.h" +#include "UI/Window/UIWindow.h" #include #include @@ -14,8 +14,6 @@ struct ExtendedListLine { std::uint32_t color = 0; }; -// RTTI UIListBoxEx, original x86 size 192. -// Unlike UIListBox, rows are keyed map values with their own text color. class UIListBoxEx : public UIWindow { public: UIListBoxEx(UIWindowContext& windows, UIListBoxContext& list); @@ -26,18 +24,11 @@ public: void Slot25(int x, int y) override; void Slot26(int x, int y) override; void Slot35(int value) override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; - virtual void Configure(int x, int y, int width, int height, unsigned char transparent); // 53 - virtual void AddLine(const char* text, std::uint32_t color); // 54 - virtual void Clear(); // 55 - virtual void Refresh(); // 56 + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; + virtual void Configure(int x, int y, int width, int height, unsigned char transparent); + virtual void AddLine(const char* text, std::uint32_t color); + virtual void Clear(); + virtual void Refresh(); /* 007C */ int backgroundRed; /* 0080 */ int backgroundGreen; diff --git a/Source/UI/UIScrollBar.cpp b/Source/UI/Lists/UIScrollBar.cpp similarity index 62% rename from Source/UI/UIScrollBar.cpp rename to Source/UI/Lists/UIScrollBar.cpp index 4cb7505..9a13397 100644 --- a/Source/UI/UIScrollBar.cpp +++ b/Source/UI/Lists/UIScrollBar.cpp @@ -1,30 +1,16 @@ -#include "Client/ModeCursor.h" -#include "Render/DeviceContext.h" -#include "Resource/BitmapResource.h" +#include "Client/Mode/ModeCursor.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/FrameFocus.h" -#include "UI/UIScrollBar.h" +#include "UI/Window/FrameFocus.h" +#include "UI/Lists/UIScrollBar.h" #include -#include - -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Subtract(int left, int right) { - return std::bit_cast(static_cast(left) - static_cast(right)); - } - int Multiply(int left, int right) { - return std::bit_cast(static_cast(left) * static_cast(right)); - } -} // OFFSET: 0x0086E550 UIScrollBar::UIScrollBar(UIWindowContext& windows, FrameFocus& capture, ResourceMgr& resources) - : UIWindow(windows, 0), state(0), maximum(0), position(0), vertical(1), pressX(0), pressY(0), dragAmount(0), - total(0), visible(0), arrowLength(13), thickness(13), minimumThumb(1), horizontalStep(1), verticalStep(1), - m_capture(&capture), m_resources(&resources) { + : UIWindow(windows, 0), state(0), maximum(0), position(0), vertical(1), pressX(0), pressY(0), dragAmount(0), total(0), visible(0), arrowLength(13), + thickness(13), minimumThumb(1), horizontalStep(1), verticalStep(1), m_capture(&capture), m_resources(&resources) { } // OFFSET: 0x00873FA0 @@ -57,11 +43,10 @@ bool UIScrollBar::Slot08() { // OFFSET: 0x00880C60 // FUNCTION: fn_11288 int UIScrollBar::ThumbLength() { - int length = - Subtract(this->vertical == 0 ? this->geometry.width : this->geometry.height, Multiply(2, this->arrowLength)); + int length = ((this->vertical == 0 ? this->geometry.width : this->geometry.height) - (2 * this->arrowLength)); if (this->total != 0) { - length = Multiply(length, this->visible) / this->total; + length = (length * this->visible) / this->total; } if (this->minimumThumb != 0 && length < 8) { @@ -76,22 +61,19 @@ int UIScrollBar::ThumbLength() { int UIScrollBar::Travel() { const int length = this->vertical == 0 ? this->geometry.width : this->geometry.height; const int thumb = this->ThumbLength(); - return Subtract(Subtract(length, Multiply(2, this->arrowLength)), thumb); + return ((length - (2 * this->arrowLength)) - thumb); } // OFFSET: 0x00880C00 // FUNCTION: fn_11286 int UIScrollBar::ThumbOffset() { - return Multiply(this->Travel(), this->position) / this->maximum; + return (this->Travel() * this->position) / this->maximum; } // OFFSET: 0x008806E0 // FUNCTION: fn_11278 int UIScrollBar::Part(int x, int y) { - if ( - this->maximum == 0 || x < 0 || x >= this->geometry.width || y < 0 || y >= this->geometry.height || - (this->vertical != 0 && this->vertical != 1) - ) { + if (this->maximum == 0 || x < 0 || x >= this->geometry.width || y < 0 || y >= this->geometry.height || (this->vertical != 0 && this->vertical != 1)) { return -1; } @@ -102,18 +84,18 @@ int UIScrollBar::Part(int x, int y) { return 0; } - if (coordinate < Add(this->arrowLength, this->ThumbOffset())) { + if (coordinate < (this->arrowLength + this->ThumbOffset())) { return 1; } const int thumb = this->ThumbLength(); const int offset = this->ThumbOffset(); - if (coordinate < Add(Add(this->arrowLength, thumb), offset)) { + if (coordinate < ((this->arrowLength + thumb) + offset)) { return 2; } - return coordinate >= Subtract(length, this->arrowLength) ? 4 : 3; + return coordinate >= (length - this->arrowLength) ? 4 : 3; } // OFFSET: 0x00890720 @@ -122,7 +104,7 @@ void UIScrollBar::Slot25(int x, int y) { UIWindow* owner = static_cast(this->parent); if (this->maximum == 0) { - owner->Slot25(Add(x, this->geometry.x), Add(y, this->geometry.y)); + owner->Slot25((x + this->geometry.x), (y + this->geometry.y)); return; } @@ -137,9 +119,7 @@ void UIScrollBar::Slot25(int x, int y) { switch (part) { case 0: - owner->SendMsg( - this, vertical ? 7 : 8, Subtract(0, vertical ? this->verticalStep : this->horizontalStep), 0, 0, 0 - ); + owner->SendMsg(this, vertical ? 7 : 8, (0 - (vertical ? this->verticalStep : this->horizontalStep)), 0, 0, 0); break; case 1: owner->SendMsg(this, vertical ? 9 : 11, 0, 0, 0, 0); @@ -170,7 +150,7 @@ void UIScrollBar::Slot26(int x, int y) { this->Slot25(x, y); if (this->maximum == 0) { - static_cast(this->parent)->Slot26(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot26((x + this->geometry.x), (y + this->geometry.y)); } } @@ -180,7 +160,7 @@ void UIScrollBar::Slot27(int x, int y) { UIWindow* owner = static_cast(this->parent); if (this->maximum == 0) { - owner->Slot27(Add(x, this->geometry.x), Add(y, this->geometry.y)); + owner->Slot27((x + this->geometry.x), (y + this->geometry.y)); return; } @@ -214,13 +194,13 @@ void UIScrollBar::Slot27(int x, int y) { } if (this->m_capture->Get() == this && owner && (this->vertical == 0 || this->vertical == 1)) { - const int distance = this->vertical == 0 ? Subtract(x, this->pressX) : Subtract(y, this->pressY); - const int delta = Subtract(Multiply(distance, Add(this->maximum, 1)) / this->Travel(), this->dragAmount); + const int distance = this->vertical == 0 ? (x - this->pressX) : (y - this->pressY); + const int delta = ((distance * (this->maximum + 1)) / this->Travel() - this->dragAmount); if (delta != 0) { const int result = owner->SendMsg(this, this->vertical == 0 ? 8 : 7, delta, 0, 0, 0); - // Original accumulates the parent's return, not the requested delta. - this->dragAmount = Add(this->dragAmount, result); + + this->dragAmount = (this->dragAmount + result); } } } @@ -239,7 +219,7 @@ void UIScrollBar::Slot31(int x, int y) { this->m_capture->Clear(); } } else { - static_cast(this->parent)->Slot31(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot31((x + this->geometry.x), (y + this->geometry.y)); } } @@ -247,7 +227,7 @@ void UIScrollBar::Slot31(int x, int y) { // FUNCTION: fn_11491 void UIScrollBar::Slot33(int x, int y) { if (this->maximum == 0) { - static_cast(this->parent)->Slot33(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot33((x + this->geometry.x), (y + this->geometry.y)); } } @@ -274,30 +254,28 @@ void UIScrollBar::Paint() { const auto draw = [&](const char* name, int coordinate, bool transparent) { const std::string path = std::string(prefix) + name; auto* bitmap = static_cast(this->m_resources->Load(path.c_str())); - this->DrawBitmap( - vertical ? 0 : coordinate, vertical ? coordinate : 0, bitmap ? &bitmap->image : nullptr, transparent - ); + this->DrawBitmap(vertical ? 0 : coordinate, vertical ? coordinate : 0, bitmap ? &bitmap->image : nullptr, transparent); }; draw(vertical ? "scroll0up.bmp" : "scroll1left.bmp", 1, false); const char* middle = vertical ? "scroll0mid.bmp" : "scroll1mid.bmp"; - const int interior = Subtract(Subtract(length, this->arrowLength), 14); + const int interior = ((length - this->arrowLength) - 14); const int count = interior / 13 + (interior % 13 != 0); for (int index = 0; index < count; ++index) { - draw(middle, Add(Multiply(index, 13), this->arrowLength), false); + draw(middle, ((index * 13) + this->arrowLength), false); } - draw(middle, Subtract(Subtract(length, this->arrowLength), 13), false); + draw(middle, ((length - this->arrowLength) - 13), false); this->FillRegion( - vertical ? 0 : Subtract(length, this->arrowLength), vertical ? Subtract(length, this->arrowLength) : 0, - vertical ? this->geometry.width : 13, vertical ? 13 : this->geometry.height, 0xFFFF00FFu + vertical ? 0 : (length - this->arrowLength), vertical ? (length - this->arrowLength) : 0, vertical ? this->geometry.width : 13, + vertical ? 13 : this->geometry.height, 0xFFFF00FFu ); - draw(vertical ? "scroll0down.bmp" : "scroll1right.bmp", Subtract(Subtract(length, this->arrowLength), 1), true); - const int thumb = Add(this->arrowLength, this->ThumbOffset()); + draw(vertical ? "scroll0down.bmp" : "scroll1right.bmp", ((length - this->arrowLength) - 1), true); + const int thumb = (this->arrowLength + this->ThumbOffset()); draw(vertical ? "scroll0bar_up.bmp" : "scroll1bar_left.bmp", thumb, true); - const int end = Subtract(Add(thumb, this->ThumbLength()), 4); + const int end = ((thumb + this->ThumbLength()) - 4); - for (int offset = Add(thumb, 4); offset < end; offset = Add(offset, 4)) { + for (int offset = (thumb + 4); offset < end; offset = (offset + 4)) { draw(vertical ? "scroll0bar_mid.bmp" : "scroll1bar_mid.bmp", offset, true); } diff --git a/Source/UI/UIScrollBar.h b/Source/UI/Lists/UIScrollBar.h similarity index 81% rename from Source/UI/UIScrollBar.h rename to Source/UI/Lists/UIScrollBar.h index f4baadd..965d81a 100644 --- a/Source/UI/UIScrollBar.h +++ b/Source/UI/Lists/UIScrollBar.h @@ -1,13 +1,11 @@ -#ifndef RAGNAROK_SOURCE_UI_UISCROLLBAR_H -#define RAGNAROK_SOURCE_UI_UISCROLLBAR_H +#ifndef RAGNAROK_SOURCE_UI_LISTS_UISCROLLBAR_H +#define RAGNAROK_SOURCE_UI_LISTS_UISCROLLBAR_H -#include "UI/UIWindow.h" +#include "UI/Window/UIWindow.h" struct FrameFocus; class ResourceMgr; -// UIScrollBar. Base artwork is identical across -// hover states in this executable; do not substitute the derived skin policies. class UIScrollBar : public UIWindow { public: UIScrollBar(UIWindowContext& windows, FrameFocus& capture, ResourceMgr& resources); @@ -22,7 +20,7 @@ public: void Slot31(int x, int y) override; void Slot33(int x, int y) override; void Slot35(int value) override; - virtual int ThumbLength(); // 53 + virtual int ThumbLength(); int ThumbOffset(); int Travel(); int Part(int x, int y); diff --git a/Source/UI/UIScrollBarNavi.cpp b/Source/UI/Lists/UIScrollBarNavi.cpp similarity index 54% rename from Source/UI/UIScrollBarNavi.cpp rename to Source/UI/Lists/UIScrollBarNavi.cpp index eef14b4..c9dcbbf 100644 --- a/Source/UI/UIScrollBarNavi.cpp +++ b/Source/UI/Lists/UIScrollBarNavi.cpp @@ -1,18 +1,7 @@ -#include "Render/DeviceContext.h" -#include "Resource/BitmapResource.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/UIScrollBarNavi.h" - -#include - -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Multiply(int left, int right) { - return std::bit_cast(static_cast(left) * static_cast(right)); - } -} +#include "UI/Lists/UIScrollBarNavi.h" // OFFSET: 0x00885EE0 // FUNCTION: fn_11320 @@ -37,33 +26,28 @@ void UIScrollBar_Navi::Paint() { if (this->vertical == 1) { constexpr char prefix[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\navigation_interface3\\"; - const auto load = [&](const char* name) { - return static_cast(this->m_resources->Load((std::string(prefix) + name).c_str())); - }; - const auto draw = [&](CBitmapRes* image, int y, bool transparent) { - this->DrawBitmap(0, y, image ? &image->image : nullptr, transparent); - }; + const auto load = [&](const char* name) { return static_cast(this->m_resources->Load((std::string(prefix) + name).c_str())); }; + const auto draw = [&](CBitmapRes* image, int y, bool transparent) { this->DrawBitmap(0, y, image ? &image->image : nullptr, transparent); }; auto* up = load("Navi_scroll_up.bmp"); auto* middle = load("Navi_scroll_mid.bmp"); auto* down = load("Navi_scroll_down.bmp"); - const int interior = Add(this->geometry.height, -Multiply(2, this->arrowLength)); + const int interior = (this->geometry.height - (2 * this->arrowLength)); const int count = interior / this->arrowLength + (interior % this->arrowLength > 0); for (int index = 1; index <= count; ++index) { - draw(middle, Multiply(index, this->arrowLength), false); + draw(middle, (index * this->arrowLength), false); } draw(up, 0, false); - draw(down, Add(this->geometry.height, -this->arrowLength), false); + draw(down, (this->geometry.height - this->arrowLength), false); auto* thumbUp = load("Navi_bar_up.bmp"); auto* thumbMiddle = load("Navi_bar_mid.bmp"); auto* thumbDown = load("Navi_bar_down.bmp"); - const int thumb = - Add(this->arrowLength, Multiply(Add(interior, -this->ThumbLength()), this->position) / this->maximum); + const int thumb = (this->arrowLength + ((interior - this->ThumbLength()) * this->position) / this->maximum); draw(thumbUp, thumb, true); - const int end = Add(Add(thumb, thumbUp->image.height), this->ThumbLength()); + const int end = ((thumb + thumbUp->image.height) + this->ThumbLength()); - for (int y = Add(thumb, thumbUp->image.height); y < end; y = Add(y, thumbDown->image.height)) { + for (int y = (thumb + thumbUp->image.height); y < end; y = (y + thumbDown->image.height)) { draw(thumbDown, y, true); } diff --git a/Source/UI/UIScrollBarNavi.h b/Source/UI/Lists/UIScrollBarNavi.h similarity index 66% rename from Source/UI/UIScrollBarNavi.h rename to Source/UI/Lists/UIScrollBarNavi.h index 49a1fd1..cd570d2 100644 --- a/Source/UI/UIScrollBarNavi.h +++ b/Source/UI/Lists/UIScrollBarNavi.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UISCROLLBARNAVI_H -#define RAGNAROK_SOURCE_UI_UISCROLLBARNAVI_H +#ifndef RAGNAROK_SOURCE_UI_LISTS_UISCROLLBARNAVI_H +#define RAGNAROK_SOURCE_UI_LISTS_UISCROLLBARNAVI_H -#include "UI/UIScrollBar.h" +#include "UI/Lists/UIScrollBar.h" -// RTTI UIScrollBar_Navi. No additional original fields. class UIScrollBar_Navi : public UIScrollBar { public: UIScrollBar_Navi(UIWindowContext& windows, FrameFocus& focus, ResourceMgr& resources); diff --git a/Source/UI/NormalItemSlotLoad.h b/Source/UI/NormalItemSlotLoad.h deleted file mode 100644 index ac9aaae..0000000 --- a/Source/UI/NormalItemSlotLoad.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_NORMALITEMSLOTLOAD_H -#define RAGNAROK_SOURCE_UI_NORMALITEMSLOTLOAD_H - -#include "Contents/NormalItemSlots.h" - -class WindowManagerWindows; -struct ShortcutVisibility; - -void LoadNormalItemSlots( - Json::Value& data, - NormalItemSlot* slots, - NormalItemSlotWindow& saved, - bool& itemSlotActive, - WindowManagerWindows& windows, - ShortcutVisibility& visibility -); - -#endif diff --git a/Source/UI/UIAdvenPartyBoardWnd.cpp b/Source/UI/Party/UIAdvenPartyBoardWnd.cpp similarity index 86% rename from Source/UI/UIAdvenPartyBoardWnd.cpp rename to Source/UI/Party/UIAdvenPartyBoardWnd.cpp index b279e45..fde3e70 100644 --- a/Source/UI/UIAdvenPartyBoardWnd.cpp +++ b/Source/UI/Party/UIAdvenPartyBoardWnd.cpp @@ -1,44 +1,36 @@ -#include "Client/TextInputBuffer.h" -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/AgencyRequestContext.h" -#include "Render/DeviceContext.h" -#include "Resource/BitmapResource.h" +#include "Client/Input/TextInputBuffer.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/AgencyRequestContext.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/InputFocus.h" -#include "UI/UIAdvenPartyBoardWnd.h" -#include "UI/UIApplyForPartyWnd.h" -#include "UI/UIBasicButton.h" -#include "UI/UIBmpTextButton.h" -#include "UI/UIComboBoxDefWnd.h" -#include "UI/UIEditCtrl.h" -#include "UI/UIJobSlotButton.h" -#include "UI/UIPartyInfoWnd.h" -#include "UI/UIRegisterPartyWnd.h" -#include "UI/UIStaticText.h" -#include "UI/WindowManagerWindows.h" -#include "UI/WindowOrdering.h" +#include "UI/Window/InputFocus.h" +#include "UI/Party/UIAdvenPartyBoardWnd.h" +#include "UI/Party/UIApplyForPartyWnd.h" +#include "UI/Buttons/UIBasicButton.h" +#include "UI/Buttons/UIBmpTextButton.h" +#include "UI/Lists/UIComboBoxDefWnd.h" +#include "UI/Edit/UIEditCtrl.h" +#include "UI/Buttons/UIJobSlotButton.h" +#include "UI/Party/UIPartyInfoWnd.h" +#include "UI/Party/UIRegisterPartyWnd.h" +#include "UI/Text/UIStaticText.h" +#include "UI/Window/WindowManagerWindows.h" +#include "UI/Window/WindowOrdering.h" #include -#include #include #include #include namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } constexpr char prefix[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\UIadventurerAgency\\"; } // OFFSET: 0x007BAC40 -UIAdvenPartyBoardWnd::UIAdvenPartyBoardWnd( - UIWindowContext& windows, - UIFrameContext& frames, - UIAdvenPartyBoardContext& board -) - : UIFrameWnd(windows, frames, 0), unknown_0104(0), unknown_0108(0), page(1), totalPages(1), unknown_0114(1), - unknown_0118(0), selectedType(0), m_board(&board) { +UIAdvenPartyBoardWnd::UIAdvenPartyBoardWnd(UIWindowContext& windows, UIFrameContext& frames, UIAdvenPartyBoardContext& board) + : UIFrameWnd(windows, frames, 0), unknown_0104(0), unknown_0108(0), page(1), totalPages(1), unknown_0114(1), unknown_0118(0), selectedType(0), + m_board(&board) { } // OFFSET: 0x007BB590 @@ -61,24 +53,26 @@ void UIAdvenPartyBoardWnd::Slot11() { void UIAdvenPartyBoardWnd::Slot15(int, int) { auto& owner = *this->m_board; auto& controls = owner.buttons; + this->minimum = new UIEditCtrl2(*this->m_context, owner.edits); this->minimum->SetSize(25, 14); this->minimum->invalidatesParent = 1; this->minimum->maximum = 3; this->minimum->TextColor(0, 0xFFFFFFFFu); char number[10] = {}; - _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", std::max(Add(owner.playerLevel, -5), 1)); + _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", std::max((owner.playerLevel - 5), 1)); this->minimum->SetText(number); this->minimum->Move(10, 24); this->minimum->Background(242, 242, 242); this->minimum->Show(1); this->AddChild(this->minimum); + this->maximum = new UIEditCtrl2(*this->m_context, owner.edits); this->maximum->SetSize(25, 14); this->maximum->invalidatesParent = 1; this->maximum->maximum = 3; this->maximum->TextColor(0, 0xFFFFFFFFu); - _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", Add(owner.playerLevel, 5)); + _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", (owner.playerLevel + 5)); this->maximum->SetText(number); this->maximum->Move(46, 24); this->maximum->Background(242, 242, 242); @@ -119,23 +113,27 @@ void UIAdvenPartyBoardWnd::Slot15(int, int) { button->SetSize(button->BitmapWidth(), button->BitmapHeight()); }; + auto* search = new UIBmpTextButton(*this->m_context, controls); artwork(search, "btn_search"); search->Move(354, 22); search->SetId(365); search->SetText(controls.services.MessageText(3366)); this->AddChild(search); + auto* reset = new UIBmpTextButton(*this->m_context, controls); artwork(reset, "btn_initialize"); reset->Move(401, 22); reset->SetId(363); reset->SetText(controls.services.MessageText(3367)); this->AddChild(reset); + this->refresh = new UIBitmapButton(*this->m_context, controls); artwork(this->refresh, "btn_refresh"); this->refresh->Move(452, 22); this->refresh->SetId(415); this->AddChild(this->refresh); + const auto arrow = [&](const char* name, int id, int x) { auto* button = new UIBitmapButton(*this->m_context, controls); @@ -147,6 +145,7 @@ void UIAdvenPartyBoardWnd::Slot15(int, int) { button->Move(x, 319); button->SetId(id); this->AddChild(button); + return button; }; this->previous = arrow("btn_list_left", 246, 199); @@ -166,9 +165,7 @@ void UIAdvenPartyBoardWnd::Slot15(int, int) { } this->ownParty = new UIPartyInfoWnd(*this->m_context, controls, owner.rows); - const char* ownImages[] = { - "btn_recruit_on.bmp", "btn_recruit_on.bmp", "btn_recruiting_press.bmp", "btn_recruiting_disable.bmp" - }; + const char* ownImages[] = {"btn_recruit_on.bmp", "btn_recruit_on.bmp", "btn_recruiting_press.bmp", "btn_recruiting_disable.bmp"}; for (int state = 0; state < 4; ++state) { this->ownParty->SetBitmap((std::string(prefix) + ownImages[state]).c_str(), state, 0); @@ -179,6 +176,7 @@ void UIAdvenPartyBoardWnd::Slot15(int, int) { this->ownParty->SetId(564); this->ownParty->Enable(0); this->AddChild(this->ownParty); + auto* recruit = new UIBmpTextButton(*this->m_context, controls); this->recruit = recruit; artwork(recruit, "btn_recruit"); @@ -186,6 +184,7 @@ void UIAdvenPartyBoardWnd::Slot15(int, int) { recruit->SetId(565); recruit->Enable(0); this->AddChild(recruit); + this->types = new UIComboBoxDef2Wnd(*this->m_context, owner.combos); this->types->dropdownHeight = 126; this->types->SetSize(76, 18); @@ -200,24 +199,27 @@ void UIAdvenPartyBoardWnd::Slot15(int, int) { this->pageText = new UIStaticText(*this->m_context, controls); this->pageText->SetSize(this->geometry.width, 18); const int textWidth = this->TextWidth(controls.fonts, controls.locale, "1/1", 0, 0, 12, 0, 0); - this->pageText->Resize(Add(textWidth, 1), 16); + this->pageText->Resize((textWidth + 1), 16); this->pageText->SetText("1/1", 0); this->pageText->Move(this->geometry.width / 2 - textWidth / 2, 319); this->AddChild(this->pageText); this->LoadPage(1); this->m_message0 = 365; + auto* close = new UIBasicButton(*this->m_context, controls); close->Configure(42, controls.services.MessageText(3045)); close->Move(this->geometry.width - close->geometry.width - 10, 317); close->SetId(201); this->AddChild(close); + this->stop = new UIBasicButton(*this->m_context, controls); const char* stopText = controls.services.MessageText(3375); - this->stop->Configure(Add(this->TextWidth(controls.fonts, controls.locale, stopText, 0, 0, 12, 0, 0), 10), stopText); + this->stop->Configure((this->TextWidth(controls.fonts, controls.locale, stopText, 0, 0, 12, 0, 0) + 10), stopText); this->stop->Move(close->geometry.x - this->stop->geometry.width - 5, 317); this->stop->SetId(410); this->AddChild(this->stop); this->stop->Enable(0); + auto* titleClose = new UIBitmapButton(*this->m_context, controls); const std::string basic = std::string("\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\"); titleClose->SetBitmap((basic + "sys_close_off.bmp").c_str(), 0, 0); @@ -292,7 +294,6 @@ void UIAdvenPartyBoardWnd::RefreshRows() { row->Reset(); } - // The original copies the agency vector before assigning the ten controls. const auto entries = g_adventurerAgencyMgr->Entries(); for (std::size_t index = 0; index < entries.size() && index < 10; ++index) { @@ -304,7 +305,7 @@ void UIAdvenPartyBoardWnd::RefreshRows() { _snprintf_s(text, sizeof(text), _TRUNCATE, "%d / %d", this->page, this->totalPages); auto& controls = this->m_board->buttons; const int width = this->TextWidth(controls.fonts, controls.locale, text, 0, 0, 12, 0, 0); - this->pageText->Resize(Add(width, 1), 16); + this->pageText->Resize((width + 1), 16); this->pageText->SetText(text, 0); this->pageText->Move(this->geometry.width / 2 - width / 2, 319); this->previous->Move(this->geometry.width / 2 - this->previous->geometry.width - width / 2 - 3, 319); @@ -343,9 +344,9 @@ void UIAdvenPartyBoardWnd::UpdatePagination() { void UIAdvenPartyBoardWnd::ResetSearch() { char number[10] = {}; - _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", std::max(Add(this->m_board->playerLevel, -5), 1)); + _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", std::max((this->m_board->playerLevel - 5), 1)); this->minimum->SetText(number); - _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", Add(this->m_board->playerLevel, 5)); + _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", (this->m_board->playerLevel + 5)); this->maximum->SetText(number); this->types->Select(0); @@ -378,12 +379,12 @@ void UIAdvenPartyBoardWnd::Search(int trigger) { char number[10] = {}; if (!digits(this->minimum->Text())) { - _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", std::max(Add(this->m_board->playerLevel, -5), 1)); + _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", std::max((this->m_board->playerLevel - 5), 1)); this->minimum->SetText(number); } if (!digits(this->maximum->Text())) { - _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", Add(this->m_board->playerLevel, 5)); + _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", (this->m_board->playerLevel + 5)); this->maximum->SetText(number); } @@ -397,7 +398,6 @@ void UIAdvenPartyBoardWnd::Search(int trigger) { filter.minimumLevel = std::atoi(this->minimum->Text()); } - // The original checks minimum length again before reading maximum. if (this->minimum->Length() > 0) { filter.maximumLevel = std::atoi(this->maximum->Text()); } @@ -424,15 +424,8 @@ void UIAdvenPartyBoardWnd::Search(int trigger) { // OFFSET: 0x007C0420 // FUNCTION: fn_09312 -int UIAdvenPartyBoardWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { - const int value = std::bit_cast(static_cast(a)); +int UIAdvenPartyBoardWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { + const int value = static_cast(a); switch (message) { case 6: @@ -441,7 +434,7 @@ int UIAdvenPartyBoardWnd::SendMsg( this->m_board->requests.windows.CloseWindow(324); break; case 218: - this->page = Add(this->page, 1); + this->page = (this->page + 1); this->previous->SetDisabled(1); this->previous->Invalidate(); this->previous->Invalidate(); @@ -457,7 +450,7 @@ int UIAdvenPartyBoardWnd::SendMsg( break; case 246: - this->page = Add(this->page, -1); + this->page = (this->page - 1); if (this->searching == 1) { this->SendMsg(nullptr, 6, 365, this->page, 246, 0); @@ -532,11 +525,8 @@ int UIAdvenPartyBoardWnd::SendMsg( case 34: this->saved = reinterpret_cast(a); - if ( - this->saved->width <= 0 || this->saved->height <= 0 || this->saved->x < 0 || - this->saved->x > this->m_board->screenWidth - this->saved->width || this->saved->y < 0 || - this->saved->y > this->m_board->screenHeight - this->saved->height - ) { + if (this->saved->width <= 0 || this->saved->height <= 0 || this->saved->x < 0 || this->saved->x > this->m_board->screenWidth - this->saved->width || + this->saved->y < 0 || this->saved->y > this->m_board->screenHeight - this->saved->height) { *this->saved = {200, 200, 480, 340}; } @@ -588,7 +578,7 @@ void UIAdvenPartyBoardWnd::Paint() { const int extent = this->geometry.width - right - left; const int count = extent / bitmap->image.width + (extent % bitmap->image.width != 0); - for (int index = 0; index < count; ++index, left = Add(left, bitmap->image.width)) { + for (int index = 0; index < count; ++index, left = (left + bitmap->image.width)) { this->DrawBitmap(left, 0, &bitmap->image, false); } } @@ -605,15 +595,13 @@ void UIAdvenPartyBoardWnd::Paint() { const int leftWidth = barLeft ? barLeft->image.width : 0; const int rightWidth = barRight ? barRight->image.width : 0; this->DrawBitmap(0, this->geometry.height - barHeight, barLeft ? &barLeft->image : nullptr, false); - this->DrawBitmap( - this->geometry.width - rightWidth, this->geometry.height - barHeight, barRight ? &barRight->image : nullptr, false - ); + this->DrawBitmap(this->geometry.width - rightWidth, this->geometry.height - barHeight, barRight ? &barRight->image : nullptr, false); if (barMiddle) { const int extent = this->geometry.width - rightWidth - leftWidth; const int count = extent / barMiddle->image.width + (extent % barMiddle->image.width != 0); - for (int index = 0, x = leftWidth; index < count; ++index, x = Add(x, barMiddle->image.width)) { + for (int index = 0, x = leftWidth; index < count; ++index, x = (x + barMiddle->image.width)) { this->DrawBitmap(x, this->geometry.height - barHeight, &barMiddle->image, false); } } diff --git a/Source/UI/UIAdvenPartyBoardWnd.h b/Source/UI/Party/UIAdvenPartyBoardWnd.h similarity index 85% rename from Source/UI/UIAdvenPartyBoardWnd.h rename to Source/UI/Party/UIAdvenPartyBoardWnd.h index fe3d65f..759bded 100644 --- a/Source/UI/UIAdvenPartyBoardWnd.h +++ b/Source/UI/Party/UIAdvenPartyBoardWnd.h @@ -1,9 +1,9 @@ -#ifndef RAGNAROK_SOURCE_UI_UIADVENPARTYBOARDWND_H -#define RAGNAROK_SOURCE_UI_UIADVENPARTYBOARDWND_H +#ifndef RAGNAROK_SOURCE_UI_PARTY_UIADVENPARTYBOARDWND_H +#define RAGNAROK_SOURCE_UI_PARTY_UIADVENPARTYBOARDWND_H -#include "Contents/AdvenPartyInfo.h" -#include "UI/UIFrameWnd.h" -#include "UI/UIListBoxEx.h" +#include "Contents/Party/AdvenPartyInfo.h" +#include "UI/Window/UIFrameWnd.h" +#include "UI/Lists/UIListBoxEx.h" #include @@ -43,7 +43,6 @@ struct UIAdvenPartyBoardContext { const std::string& characterName; }; -// RTTI UIAdvenPartyBoardWnd, original x86 size 340. class UIAdvenPartyBoardWnd : public UIFrameWnd { public: UIAdvenPartyBoardWnd(UIWindowContext& windows, UIFrameContext& frames, UIAdvenPartyBoardContext& board); @@ -51,14 +50,7 @@ public: void Slot11() override; void Slot15(int width, int height) override; void Paint() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; void LoadPage(int page); void Registration(bool registered); void SetOwnParty(CAdvenPartyInfo value); diff --git a/Source/UI/UIApplyForPartyWnd.cpp b/Source/UI/Party/UIApplyForPartyWnd.cpp similarity index 79% rename from Source/UI/UIApplyForPartyWnd.cpp rename to Source/UI/Party/UIApplyForPartyWnd.cpp index 1cea84e..915fe23 100644 --- a/Source/UI/UIApplyForPartyWnd.cpp +++ b/Source/UI/Party/UIApplyForPartyWnd.cpp @@ -1,19 +1,18 @@ -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/AgencyRequestContext.h" -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "Resource/BitmapResource.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/AgencyRequestContext.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/TextFitting.h" -#include "UI/TextWrapping.h" -#include "UI/UIApplyForPartyWnd.h" -#include "UI/UIBasicButton.h" -#include "UI/UIBitmapButton.h" -#include "UI/UIPartyInfoWnd.h" -#include "UI/UIStaticText.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Text/TextFitting.h" +#include "UI/Text/TextWrapping.h" +#include "UI/Party/UIApplyForPartyWnd.h" +#include "UI/Buttons/UIBasicButton.h" +#include "UI/Buttons/UIBitmapButton.h" +#include "UI/Party/UIPartyInfoWnd.h" +#include "UI/Text/UIStaticText.h" +#include "UI/Window/WindowManagerWindows.h" -#include #include namespace { @@ -21,11 +20,7 @@ namespace { } // OFFSET: 0x007BAD00 -UIApplyForPartyWnd::UIApplyForPartyWnd( - UIWindowContext& windows, - UIFrameContext& frames, - UIApplyForPartyContext& application -) +UIApplyForPartyWnd::UIApplyForPartyWnd(UIWindowContext& windows, UIFrameContext& frames, UIApplyForPartyContext& application) : UIFrameWnd(windows, frames, 0), m_application(&application) { } @@ -63,9 +58,7 @@ void UIApplyForPartyWnd::Slot15(int, int) { } std::vector lines; - WrapPlainText( - controls.services.MessageText(3370), lines, 40, this->m_application->codePage, controls.locale.inlineCharset - ); + WrapPlainText(controls.services.MessageText(3370), lines, 40, this->m_application->codePage, controls.locale.inlineCharset); int y = 136; for (const auto& line : lines) { @@ -106,9 +99,7 @@ void UIApplyForPartyWnd::SetInfo(CAdvenPartyInfo value) { void UIApplyForPartyWnd::Paint() { auto& controls = this->m_application->buttons; this->geometry.surface->Fill(nullptr, 0xFFFF00FFu); - const auto load = [&](const char* name) { - return static_cast(controls.resources.Load((std::string(prefix) + name).c_str())); - }; + const auto load = [&](const char* name) { return static_cast(controls.resources.Load((std::string(prefix) + name).c_str())); }; const auto* background = load("UIadventurerAgency\\bg_agency_register.bmp"); this->DrawBitmap(0, 0, background ? &background->image : nullptr, false); int leftWidth = 0; @@ -141,12 +132,9 @@ void UIApplyForPartyWnd::Paint() { this->DrawTextAt(controls.fonts, controls.locale, 18, titleHeight - 14, caption, 0, 0, 12, 0, 0, 0); const auto* base = load("basic_interface\\sys_base_off.bmp"); this->DrawBitmap(3, 3, base ? &base->image : nullptr, true); - const auto text = [&](int x, int y, const char* value) { - this->DrawTextAt(controls.fonts, controls.locale, x, y, value, 0, 0, 12, 0, 0, 0); - }; + const auto text = [&](int x, int y, const char* value) { this->DrawTextAt(controls.fonts, controls.locale, x, y, value, 0, 0, 12, 0, 0, 0); }; text(10, 25, controls.services.MessageText(3415)); - const std::string fitted = - FitText(*this->geometry.surface, controls.fonts, controls.locale, this->info.characterName, 119); + const std::string fitted = FitText(*this->geometry.surface, controls.fonts, controls.locale, this->info.characterName, 119); text(60, 25, fitted.c_str()); text(10, 49, controls.services.MessageText(408)); char levels[10] = {}; @@ -159,8 +147,7 @@ void UIApplyForPartyWnd::Paint() { const bool selected[] = {this->info.tanker, this->info.healer, this->info.dealer, this->info.assist}; for (int index = 0; index < 4; ++index) { - const std::string name = - std::string("UIadventurerAgency\\btn_job_") + jobs[index] + (selected[index] ? "_on.bmp" : "_off.bmp"); + const std::string name = std::string("UIadventurerAgency\\btn_job_") + jobs[index] + (selected[index] ? "_on.bmp" : "_off.bmp"); const auto* icon = load(name.c_str()); this->DrawBitmap(60 + index * 18, 95, icon ? &icon->image : nullptr, false); } @@ -197,18 +184,11 @@ void UIApplyForPartyWnd::Slot28(int x, int y) { // OFFSET: 0x007C11E0 // FUNCTION: fn_09313 -int UIApplyForPartyWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIApplyForPartyWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message == 6) { auto& owner = *this->m_application; - switch (std::bit_cast(static_cast(a))) { + switch (static_cast(a)) { case 201: this->m_frameContext->windows.CloseWindow(345); break; @@ -238,11 +218,8 @@ int UIApplyForPartyWnd::SendMsg( this->saved = reinterpret_cast(a); const auto& owner = *this->m_application; - if ( - this->saved->width <= 0 || this->saved->height <= 0 || this->saved->x < 0 || - this->saved->x > owner.screenWidth - this->saved->width || this->saved->y < 0 || - this->saved->y > owner.screenHeight - this->saved->height - ) { + if (this->saved->width <= 0 || this->saved->height <= 0 || this->saved->x < 0 || this->saved->x > owner.screenWidth - this->saved->width || + this->saved->y < 0 || this->saved->y > owner.screenHeight - this->saved->height) { *this->saved = {200, 200, 220, 190}; } diff --git a/Source/UI/UIApplyForPartyWnd.h b/Source/UI/Party/UIApplyForPartyWnd.h similarity index 72% rename from Source/UI/UIApplyForPartyWnd.h rename to Source/UI/Party/UIApplyForPartyWnd.h index f5f2f75..4663567 100644 --- a/Source/UI/UIApplyForPartyWnd.h +++ b/Source/UI/Party/UIApplyForPartyWnd.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UIAPPLYFORPARTYWND_H -#define RAGNAROK_SOURCE_UI_UIAPPLYFORPARTYWND_H +#ifndef RAGNAROK_SOURCE_UI_PARTY_UIAPPLYFORPARTYWND_H +#define RAGNAROK_SOURCE_UI_PARTY_UIAPPLYFORPARTYWND_H -#include "UI/UIAdvenPartyBoardWnd.h" -#include "UI/UIFrameWnd.h" +#include "UI/Party/UIAdvenPartyBoardWnd.h" +#include "UI/Window/UIFrameWnd.h" struct PartyRowContext; @@ -19,7 +19,6 @@ struct UIApplyForPartyContext { const int& screenHeight; }; -// RTTI UIApplyForPartyWnd, original x86 size 260. class UIApplyForPartyWnd : public UIFrameWnd { public: UIApplyForPartyWnd(UIWindowContext& windows, UIFrameContext& frames, UIApplyForPartyContext& application); @@ -28,14 +27,7 @@ public: void Slot15(int width, int height) override; void Paint() override; void Slot28(int x, int y) override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; void SetInfo(CAdvenPartyInfo value); /* 00B4 */ CAdvenPartyInfo info; diff --git a/Source/UI/UIPartyInfoWnd.cpp b/Source/UI/Party/UIPartyInfoWnd.cpp similarity index 88% rename from Source/UI/UIPartyInfoWnd.cpp rename to Source/UI/Party/UIPartyInfoWnd.cpp index 8065b86..44bdd8c 100644 --- a/Source/UI/UIPartyInfoWnd.cpp +++ b/Source/UI/Party/UIPartyInfoWnd.cpp @@ -1,8 +1,8 @@ -#include "Render/DeviceContext.h" -#include "Resource/BitmapResource.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/TextFitting.h" -#include "UI/UIPartyInfoWnd.h" +#include "UI/Text/TextFitting.h" +#include "UI/Party/UIPartyInfoWnd.h" #include @@ -83,9 +83,7 @@ void UIPartyInfoWnd::Paint() { this->DrawBitmap(0, 0, &background->image, false); } - const auto text = [&](int x, const char* value, int bytes = 0) { - this->DrawTextAt(controls.fonts, controls.locale, x, 5, value, bytes, 0, 12, 0, 0, 0); - }; + const auto text = [&](int x, const char* value, int bytes = 0) { this->DrawTextAt(controls.fonts, controls.locale, x, 5, value, bytes, 0, 12, 0, 0, 0); }; text(11, this->levels.c_str()); text(64, TypeName(this->type, controls.services)); constexpr char prefix[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\UIadventurerAgency\\"; @@ -118,16 +116,12 @@ void UIPartyInfoWnd::Slot31(int x, int y) { // OFFSET: 0x007BFE90 // FUNCTION: fn_09310 void UIPartyInfoWnd::Slot33(int, int) { - if ( - this->m_disabled != 0 || this->info.accountId == this->m_row->accountId || - this->info.characterId == this->m_row->characterId - ) { + if (this->m_disabled != 0 || this->info.accountId == this->m_row->accountId || this->info.characterId == this->m_row->characterId) { return; } const std::string name = this->info.characterName; - const char* relationship = - this->m_row->services.IsFriend(name) ? this->m_buttonContext->services.MessageText(102) : nullptr; + const char* relationship = this->m_row->services.IsFriend(name) ? this->m_buttonContext->services.MessageText(102) : nullptr; if (this->m_row->services.IsGuildMember(this->info.accountId)) { relationship = "GuildMember"; diff --git a/Source/UI/UIPartyInfoWnd.h b/Source/UI/Party/UIPartyInfoWnd.h similarity index 82% rename from Source/UI/UIPartyInfoWnd.h rename to Source/UI/Party/UIPartyInfoWnd.h index fb4db88..60c43de 100644 --- a/Source/UI/UIPartyInfoWnd.h +++ b/Source/UI/Party/UIPartyInfoWnd.h @@ -1,10 +1,9 @@ -#ifndef RAGNAROK_SOURCE_UI_UIPARTYINFOWND_H -#define RAGNAROK_SOURCE_UI_UIPARTYINFOWND_H +#ifndef RAGNAROK_SOURCE_UI_PARTY_UIPARTYINFOWND_H +#define RAGNAROK_SOURCE_UI_PARTY_UIPARTYINFOWND_H -#include "Contents/AdvenPartyInfo.h" -#include "UI/UIBitmapButton.h" +#include "Contents/Party/AdvenPartyInfo.h" +#include "UI/Buttons/UIBitmapButton.h" -// Original client friend/guild/name-tooltip operations remain at their owners. class PartyRowServices { public: virtual bool IsFriend(const std::string& name) = 0; @@ -22,7 +21,6 @@ struct PartyRowContext { PartyRowServices& services; }; -// RTTI UIPartyInfoWnd, original x86 size 456. class UIPartyInfoWnd : public UIBitmapButton { public: UIPartyInfoWnd(UIWindowContext& windows, UIButtonContext& buttons, PartyRowContext& row); diff --git a/Source/UI/UIRegisterPartyWnd.cpp b/Source/UI/Party/UIRegisterPartyWnd.cpp similarity index 84% rename from Source/UI/UIRegisterPartyWnd.cpp rename to Source/UI/Party/UIRegisterPartyWnd.cpp index cfd36ca..98e3115 100644 --- a/Source/UI/UIRegisterPartyWnd.cpp +++ b/Source/UI/Party/UIRegisterPartyWnd.cpp @@ -1,36 +1,32 @@ -#include "Client/TextInputBuffer.h" -#include "Contents/AdventurerAgencyMgr.h" -#include "Contents/AgencyRequestContext.h" +#include "Client/Input/TextInputBuffer.h" +#include "Contents/Party/AdventurerAgencyMgr.h" +#include "Contents/Party/AgencyRequestContext.h" #include "Contents/ForbiddenWords.h" -#include "Contents/RegisterPartyAsyncWork.h" -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "Resource/BitmapResource.h" +#include "Contents/Party/RegisterPartyAsyncWork.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceFailures.h" #include "Resource/ResourceMgr.h" -#include "UI/InputFocus.h" -#include "UI/TextFitting.h" -#include "UI/TextWrapping.h" -#include "UI/UIBasicButton.h" -#include "UI/UIBitmapButton.h" -#include "UI/UIComboBoxDefWnd.h" -#include "UI/UIEditCtrl.h" -#include "UI/UIJobSlotButton.h" -#include "UI/UIRegisterPartyWnd.h" -#include "UI/UIStaticText.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Window/InputFocus.h" +#include "UI/Text/TextFitting.h" +#include "UI/Text/TextWrapping.h" +#include "UI/Buttons/UIBasicButton.h" +#include "UI/Buttons/UIBitmapButton.h" +#include "UI/Lists/UIComboBoxDefWnd.h" +#include "UI/Edit/UIEditCtrl.h" +#include "UI/Buttons/UIJobSlotButton.h" +#include "UI/Party/UIRegisterPartyWnd.h" +#include "UI/Text/UIStaticText.h" +#include "UI/Window/WindowManagerWindows.h" #include -#include #include #include #include namespace { constexpr char prefix[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\"; - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } // OFFSET: 0x007BBFC0 // FUNCTION: fn_09295 @@ -50,11 +46,7 @@ namespace { } // OFFSET: 0x007BAF30 -UIRegisterPartyWnd::UIRegisterPartyWnd( - UIWindowContext& windows, - UIFrameContext& frames, - UIRegisterPartyContext& registration -) +UIRegisterPartyWnd::UIRegisterPartyWnd(UIWindowContext& windows, UIFrameContext& frames, UIRegisterPartyContext& registration) : UIFrameWnd(windows, frames, 0), selectedType(0), m_registration(®istration) { } @@ -78,6 +70,7 @@ void UIRegisterPartyWnd::Slot11() { void UIRegisterPartyWnd::Slot15(int, int) { auto& owner = *this->m_registration; auto& controls = owner.buttons; + const auto label = [&](const char* text, int x, int y, int width) { auto* value = new UIStaticText(*this->m_context, controls); value->SetSize(width, 15); @@ -87,15 +80,16 @@ void UIRegisterPartyWnd::Slot15(int, int) { value->green = 0; value->blue = 0; this->AddChild(value); + return value; }; label(controls.services.MessageText(3415), 10, 23, 40); this->character = label(owner.characterName.c_str(), 60, 23, 119); - this->character->text = - FitText(*this->character->geometry.surface, controls.fonts, controls.locale, owner.characterName, 119); + this->character->text = FitText(*this->character->geometry.surface, controls.fonts, controls.locale, owner.characterName, 119); this->character->tooltipEnabled = this->character->text != owner.characterName; label(controls.services.MessageText(408), 10, 49, 40); const int level = owner.playerLevel; + const auto edit = [&](int x, int value) { auto* control = new UIEditCtrl(*this->m_context, owner.edits); control->SetSize(25, 16); @@ -107,10 +101,11 @@ void UIRegisterPartyWnd::Slot15(int, int) { _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", value); control->SetText(number); this->AddChild(control); + return control; }; - this->minimum = edit(60, std::max(Add(level, -5), 1)); - this->maximum = edit(96, Add(level, 5)); + this->minimum = edit(60, std::max((level - 5), 1)); + this->maximum = edit(96, (level + 5)); label(controls.services.MessageText(3369), 10, 73, this->geometry.width); auto* roleLabel = label(controls.services.MessageText(504), 10, 97, this->geometry.width); roleLabel->outline = 1; @@ -137,6 +132,7 @@ void UIRegisterPartyWnd::Slot15(int, int) { this->memo->Move(60, 119); this->memo->Background(232, 232, 232); this->AddChild(this->memo); + auto* submit = new UIBasicButton(*this->m_context, controls); const bool registered = g_adventurerAgencyMgr->registered; const char* title = controls.services.MessageText(registered ? 3376 : 3371); @@ -175,6 +171,7 @@ void UIRegisterPartyWnd::Slot15(int, int) { close->Move(173, 165); close->SetId(201); this->AddChild(close); + this->types = new UIComboBoxDef2Wnd(*this->m_context, owner.combos); this->types->dropdownHeight = 126; this->types->SetSize(63, 18); @@ -231,12 +228,12 @@ void UIRegisterPartyWnd::NormalizeLevels() { char number[10] = {}; if (!Digits(this->Text(*this->minimum))) { - _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", std::max(Add(level, -5), 1)); + _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", std::max((level - 5), 1)); this->minimum->SetText(number); } if (!Digits(this->Text(*this->maximum))) { - _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", Add(level, 5)); + _snprintf_s(number, sizeof(number), _TRUNCATE, "%d", (level + 5)); this->maximum->SetText(number); } } @@ -246,9 +243,7 @@ void UIRegisterPartyWnd::NormalizeLevels() { void UIRegisterPartyWnd::Paint() { auto& controls = this->m_registration->buttons; this->geometry.surface->Fill(nullptr, 0xFFFF00FFu); - const auto load = [&](const char* name) { - return static_cast(controls.resources.Load((std::string(prefix) + name).c_str())); - }; + const auto load = [&](const char* name) { return static_cast(controls.resources.Load((std::string(prefix) + name).c_str())); }; const auto* background = load("UIadventurerAgency\\bg_agency_register.bmp"); this->DrawBitmap(0, 0, background ? &background->image : nullptr, false); this->DrawTextAt(controls.fonts, controls.locale, 86, 50, "~", 0, 0, 12, 0, 0, 0); @@ -286,18 +281,11 @@ void UIRegisterPartyWnd::Paint() { // OFFSET: 0x007C1410 // FUNCTION: fn_09314 -int UIRegisterPartyWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIRegisterPartyWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { auto& owner = *this->m_registration; if (message == 6) { - const int value = std::bit_cast(static_cast(a)); + const int value = static_cast(a); if (value != 201) { if (value != 564 && value != 565) { @@ -346,11 +334,8 @@ int UIRegisterPartyWnd::SendMsg( if (message == 34) { this->saved = reinterpret_cast(a); - if ( - this->saved->width <= 0 || this->saved->height <= 0 || this->saved->x < 0 || - this->saved->x > owner.screenWidth - this->saved->width || this->saved->y < 0 || - this->saved->y > owner.screenHeight - this->saved->height - ) { + if (this->saved->width <= 0 || this->saved->height <= 0 || this->saved->x < 0 || this->saved->x > owner.screenWidth - this->saved->width || + this->saved->y < 0 || this->saved->y > owner.screenHeight - this->saved->height) { *this->saved = {200, 200, 220, 197}; } @@ -360,7 +345,7 @@ int UIRegisterPartyWnd::SendMsg( if (message == 39) { if (sender == this->types) { - this->selectedType = std::bit_cast(static_cast(a)); + this->selectedType = static_cast(a); } return 0; diff --git a/Source/UI/UIRegisterPartyWnd.h b/Source/UI/Party/UIRegisterPartyWnd.h similarity index 81% rename from Source/UI/UIRegisterPartyWnd.h rename to Source/UI/Party/UIRegisterPartyWnd.h index 7afca1f..3951f37 100644 --- a/Source/UI/UIRegisterPartyWnd.h +++ b/Source/UI/Party/UIRegisterPartyWnd.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UIREGISTERPARTYWND_H -#define RAGNAROK_SOURCE_UI_UIREGISTERPARTYWND_H +#ifndef RAGNAROK_SOURCE_UI_PARTY_UIREGISTERPARTYWND_H +#define RAGNAROK_SOURCE_UI_PARTY_UIREGISTERPARTYWND_H -#include "UI/UIAdvenPartyBoardWnd.h" -#include "UI/UIFrameWnd.h" +#include "UI/Party/UIAdvenPartyBoardWnd.h" +#include "UI/Window/UIFrameWnd.h" class UIComboBoxDef2Wnd; class UIEditCtrl; @@ -30,7 +30,6 @@ struct UIRegisterPartyContext { const unsigned short& codePage; }; -// RTTI UIRegisterPartyWnd, original x86 size 232. class UIRegisterPartyWnd : public UIFrameWnd { public: UIRegisterPartyWnd(UIWindowContext& windows, UIFrameContext& frames, UIRegisterPartyContext& registration); @@ -38,14 +37,7 @@ public: void Slot11() override; void Slot15(int width, int height) override; void Paint() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; void SetInfo(CAdvenPartyInfo value); /* 00B4 */ UIComboBoxDef2Wnd* types; diff --git a/Source/UI/UIRequestJoinPartyMgr.cpp b/Source/UI/Party/UIRequestJoinPartyMgr.cpp similarity index 84% rename from Source/UI/UIRequestJoinPartyMgr.cpp rename to Source/UI/Party/UIRequestJoinPartyMgr.cpp index c38bc79..b7eeab2 100644 --- a/Source/UI/UIRequestJoinPartyMgr.cpp +++ b/Source/UI/Party/UIRequestJoinPartyMgr.cpp @@ -1,6 +1,6 @@ -#include "UI/UIRequestJoinPartyMgr.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Party/UIRequestJoinPartyMgr.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" #include #include @@ -52,13 +52,7 @@ void UIRequestJoinPartyMgr::Shutdown() { // OFFSET: 0x007C00F0 // FUNCTION: fn_09311 -void UIRequestJoinPartyMgr::Add( - std::uint32_t accountId, - std::uint32_t characterId, - const char* name, - std::int16_t job, - std::int16_t level -) { +void UIRequestJoinPartyMgr::Add(std::uint32_t accountId, std::uint32_t characterId, const char* name, std::int16_t job, std::int16_t level) { if (std::find(this->m_blocked.begin(), this->m_blocked.end(), accountId) != this->m_blocked.end()) { return; } @@ -99,11 +93,9 @@ void UIRequestJoinPartyMgr::Advance() { } const PartyJoinRequest request = this->m_pending.front(); - const bool blocked = - std::find(this->m_blocked.begin(), this->m_blocked.end(), request.accountId) != this->m_blocked.end(); + const bool blocked = std::find(this->m_blocked.begin(), this->m_blocked.end(), request.accountId) != this->m_blocked.end(); if (!blocked) { - // Dispatch precedes removal: reentry observes the original queue head. window->SendMsg(nullptr, 56, reinterpret_cast(&request), 0, 0, 0); this->m_pending.pop_front(); return; diff --git a/Source/UI/UIRequestJoinPartyMgr.h b/Source/UI/Party/UIRequestJoinPartyMgr.h similarity index 81% rename from Source/UI/UIRequestJoinPartyMgr.h rename to Source/UI/Party/UIRequestJoinPartyMgr.h index 9470350..759abe8 100644 --- a/Source/UI/UIRequestJoinPartyMgr.h +++ b/Source/UI/Party/UIRequestJoinPartyMgr.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_UIREQUESTJOINPARTYMGR_H -#define RAGNAROK_SOURCE_UI_UIREQUESTJOINPARTYMGR_H +#ifndef RAGNAROK_SOURCE_UI_PARTY_UIREQUESTJOINPARTYMGR_H +#define RAGNAROK_SOURCE_UI_PARTY_UIREQUESTJOINPARTYMGR_H #include #include @@ -15,8 +15,6 @@ struct PartyJoinRequest { }; static_assert(sizeof(PartyJoinRequest) == 36); -// RTTI UIRequestJoinPartyMgr, original x86 size 24. Manager/factory view is -// borrowed source-only state after the original owning lists. class UIRequestJoinPartyMgr { public: explicit UIRequestJoinPartyMgr(WindowManagerWindows& windows); diff --git a/Source/UI/UIRequestJoinPartyWnd.cpp b/Source/UI/Party/UIRequestJoinPartyWnd.cpp similarity index 84% rename from Source/UI/UIRequestJoinPartyWnd.cpp rename to Source/UI/Party/UIRequestJoinPartyWnd.cpp index cdba673..f011b15 100644 --- a/Source/UI/UIRequestJoinPartyWnd.cpp +++ b/Source/UI/Party/UIRequestJoinPartyWnd.cpp @@ -1,19 +1,18 @@ -#include "Client/ModeEvents.h" -#include "Contents/JobNames.h" -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "Resource/BitmapResource.h" +#include "Client/Mode/ModeEvents.h" +#include "Contents/Jobs/JobNames.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/TextWrapping.h" -#include "UI/UIBasicButton.h" -#include "UI/UIBitmapButton.h" -#include "UI/UICheckBox.h" -#include "UI/UIRequestJoinPartyMgr.h" -#include "UI/UIRequestJoinPartyWnd.h" -#include "UI/UIStaticText.h" -#include "UI/UITextViewer.h" +#include "UI/Text/TextWrapping.h" +#include "UI/Buttons/UIBasicButton.h" +#include "UI/Buttons/UIBitmapButton.h" +#include "UI/Buttons/UICheckBox.h" +#include "UI/Party/UIRequestJoinPartyMgr.h" +#include "UI/Party/UIRequestJoinPartyWnd.h" +#include "UI/Text/UIStaticText.h" +#include "UI/Text/UITextViewer.h" -#include #include namespace { @@ -21,11 +20,7 @@ namespace { } // OFFSET: 0x007BB030 -UIRequestJoinPartyWnd::UIRequestJoinPartyWnd( - UIWindowContext& windows, - UIFrameContext& frames, - UIRequestJoinPartyContext& request -) +UIRequestJoinPartyWnd::UIRequestJoinPartyWnd(UIWindowContext& windows, UIFrameContext& frames, UIRequestJoinPartyContext& request) : UIFrameWnd(windows, frames, 0), m_request(&request) { } @@ -38,6 +33,7 @@ UIRequestJoinPartyWnd::~UIRequestJoinPartyWnd() = default; void UIRequestJoinPartyWnd::Slot15(int, int) { auto& text = this->m_request->text; auto& controls = text.buttons; + this->icon = new UIBitmapButton(*this->m_context, controls); this->icon->SetSize(25, 25); const std::string initial = std::string(prefix) + "renewalparty\\icon_jobs_4046.bmp"; @@ -48,6 +44,7 @@ void UIRequestJoinPartyWnd::Slot15(int, int) { this->icon->Move(12, 29); this->AddChild(this->icon); + this->levelText = new UIStaticText(*this->m_context, controls); this->levelText->SetSize(25, 14); this->levelText->Move(16, 56); @@ -75,6 +72,7 @@ void UIRequestJoinPartyWnd::Slot15(int, int) { this->details->textColor = 0xFFFFFFFFu; this->details->Invalidate(); this->AddChild(this->details); + this->block = new UICheckBox(*this->m_context, controls); this->block->SetSize(24, 47); const std::string checked = std::string(prefix) + "uiadventureragency\\btn_block_on.bmp"; @@ -86,6 +84,7 @@ void UIRequestJoinPartyWnd::Slot15(int, int) { this->AddChild(this->block); std::vector unused; WrapPlainText(controls.services.MessageText(3518), unused, 30, text.list.codePage, controls.locale.inlineCharset); + this->blockText = new UITextViewer(*this->m_context, text); this->blockText->Configure(31, 81, 182, 47, 0); this->blockText->textColor = 0xFFD7C53Cu; @@ -93,6 +92,7 @@ void UIRequestJoinPartyWnd::Slot15(int, int) { this->AddChild(this->blockText); this->blockText->lineHeight = 15; this->blockText->SendMsg(nullptr, 29, reinterpret_cast(controls.services.MessageText(3518)), 30, 0, 0); + auto* close = new UIBitmapButton(*this->m_context, controls); const std::string off = std::string(prefix) + "basic_interface\\big_sys_close_off.bmp"; const std::string on = std::string(prefix) + "basic_interface\\big_sys_close_on.bmp"; @@ -110,9 +110,7 @@ void UIRequestJoinPartyWnd::Slot15(int, int) { // FUNCTION: fn_09306 void UIRequestJoinPartyWnd::Paint() { auto& controls = this->m_request->text.buttons; - const auto load = [&](const char* name) { - return static_cast(controls.resources.Load((std::string(prefix) + name).c_str())); - }; + const auto load = [&](const char* name) { return static_cast(controls.resources.Load((std::string(prefix) + name).c_str())); }; const auto* background = load("UIadventurerAgency\\bg_agency_admit.bmp"); this->DrawBitmap(0, 0, background ? &background->image : nullptr, false); int leftWidth = 0; @@ -149,16 +147,9 @@ void UIRequestJoinPartyWnd::Paint() { // OFFSET: 0x007C1770 // FUNCTION: fn_09315 -int UIRequestJoinPartyWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIRequestJoinPartyWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message == 6) { - const int value = std::bit_cast(static_cast(a)); + const int value = static_cast(a); if (value == 201) { this->SendMsg(nullptr, 6, 542, 0, 0, 0); @@ -173,11 +164,10 @@ int UIRequestJoinPartyWnd::SendMsg( this->m_request->requests.Block(this->accountId); } - this->m_context->mode->SendModeMessage( - 264, this->characterId, value == 541, reinterpret_cast(&this->accountId), 0 - ); + this->m_context->mode->SendModeMessage(264, this->characterId, value == 541, reinterpret_cast(&this->accountId), 0); this->m_request->requests.Advance(); this->block->SetChecked(0); + return 0; } @@ -191,10 +181,7 @@ int UIRequestJoinPartyWnd::SendMsg( this->job = request.job; this->level = request.level; char path[500] = {}; - _snprintf_s( - path, sizeof(path), _TRUNCATE, "%srenewalparty\\icon_jobs_%lu.bmp", prefix, - static_cast(static_cast(this->job)) - ); + _snprintf_s(path, sizeof(path), _TRUNCATE, "%srenewalparty\\icon_jobs_%lu.bmp", prefix, static_cast(static_cast(this->job))); for (int state = 0; state < 3; ++state) { this->icon->SetBitmap(path, state, 0); @@ -213,5 +200,6 @@ int UIRequestJoinPartyWnd::SendMsg( this->details->SendMsg(nullptr, 29, reinterpret_cast(messageText), 0, 0, 1); this->details->Move(43, static_cast(this->details->lines.size()) - 3u >= 1u ? 30 : 20); this->Invalidate(); + return 0; } diff --git a/Source/UI/UIRequestJoinPartyWnd.h b/Source/UI/Party/UIRequestJoinPartyWnd.h similarity index 79% rename from Source/UI/UIRequestJoinPartyWnd.h rename to Source/UI/Party/UIRequestJoinPartyWnd.h index 34b8eda..94e5220 100644 --- a/Source/UI/UIRequestJoinPartyWnd.h +++ b/Source/UI/Party/UIRequestJoinPartyWnd.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UIREQUESTJOINPARTYWND_H -#define RAGNAROK_SOURCE_UI_UIREQUESTJOINPARTYWND_H +#ifndef RAGNAROK_SOURCE_UI_PARTY_UIREQUESTJOINPARTYWND_H +#define RAGNAROK_SOURCE_UI_PARTY_UIREQUESTJOINPARTYWND_H -#include "UI/UIFrameWnd.h" +#include "UI/Window/UIFrameWnd.h" #include @@ -20,21 +20,13 @@ struct UIRequestJoinPartyContext { UIRequestJoinPartyMgr& requests; }; -// RTTI UIRequestJoinPartyWnd, original x86 size 236. class UIRequestJoinPartyWnd : public UIFrameWnd { public: UIRequestJoinPartyWnd(UIWindowContext& windows, UIFrameContext& frames, UIRequestJoinPartyContext& request); ~UIRequestJoinPartyWnd() override; void Slot15(int width, int height) override; void Paint() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; /* 00B4 */ UITextViewer* details; /* 00B8 */ UITextViewer* blockText; diff --git a/Source/UI/PixelTextWrapping.h b/Source/UI/PixelTextWrapping.h deleted file mode 100644 index e4a1b66..0000000 --- a/Source/UI/PixelTextWrapping.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_PIXELTEXTWRAPPING_H -#define RAGNAROK_SOURCE_UI_PIXELTEXTWRAPPING_H - -#include -#include - -class CDC; -class FontCache; -struct TextLocale; - -void WrapPixelText( - CDC& surface, - FontCache& fonts, - const TextLocale& locale, - unsigned short codePage, - const char* text, - std::vector& lines, - int width -); - -#endif diff --git a/Source/UI/Shop/ItemDrawing.cpp b/Source/UI/Shop/ItemDrawing.cpp new file mode 100644 index 0000000..73e3a66 --- /dev/null +++ b/Source/UI/Shop/ItemDrawing.cpp @@ -0,0 +1,45 @@ +#include "Contents/Items/ItemDescription.h" +#include "Contents/Items/ItemInfo.h" +#include "Resource/Bitmap/BitmapResource.h" +#include "Resource/ResourceMgr.h" +#include "UI/Shop/ItemDrawing.h" +#include "UI/Window/UIWindow.h" + +#include + +// OFFSET: 0x008A8EE0 +// FUNCTION: fn_11717 +void DrawItemIcon(UIWindow& window, ResourceMgr& resources, ItemDescriptions& descriptions, int x, int y, const ItemInfo& item, unsigned char identified) { + char path[128]; + descriptions.IconPath(path, item.itemId.c_str(), item.identified != 0 || identified != 0); + CBitmapRes* bitmap = static_cast(resources.Load(path)); + + if (bitmap) { + window.DrawBitmap(x, y, &bitmap->image, true); + } +} + +// OFFSET: 0x008A9040 +// FUNCTION: fn_11720 +void DrawItemWithQuantity( + UIWindow& window, ResourceMgr& resources, ItemDescriptions& descriptions, FontCache& fonts, const TextLocale& locale, int x, int y, const ItemInfo& item, + unsigned char identified, unsigned char plain +) { + DrawItemIcon(window, resources, descriptions, x, y, item, identified); + if (item.quantity == -1 || item.quantity == 0) { + return; + } + + char text[16]; + std::sprintf(text, "%d", item.quantity); + if (plain != 0) { + window.DrawTextAt(fonts, locale, x + 16, y + 20, text, 0, 0, 11, 0, 0, 0); + } else { + const int left = x + (item.quantity < 1000 ? 14 : 0); + window.DrawTextAt(fonts, locale, left + 1, y + 15, text, 0, 0, 11, 0xFFFFFF, 0, 0); + window.DrawTextAt(fonts, locale, left - 1, y + 15, text, 0, 0, 11, 0xFFFFFF, 0, 0); + window.DrawTextAt(fonts, locale, left, y + 16, text, 0, 0, 11, 0xFFFFFF, 0, 0); + window.DrawTextAt(fonts, locale, left, y + 14, text, 0, 0, 11, 0xFFFFFF, 0, 0); + window.DrawTextAt(fonts, locale, left, y + 15, text, 0, 0, 11, 0, 0, 0); + } +} diff --git a/Source/UI/Shop/ItemDrawing.h b/Source/UI/Shop/ItemDrawing.h new file mode 100644 index 0000000..29977e8 --- /dev/null +++ b/Source/UI/Shop/ItemDrawing.h @@ -0,0 +1,17 @@ +#ifndef RAGNAROK_SOURCE_UI_SHOP_ITEMDRAWING_H +#define RAGNAROK_SOURCE_UI_SHOP_ITEMDRAWING_H + +struct ItemInfo; +struct ItemDescriptions; +class UIWindow; +class ResourceMgr; +class FontCache; +struct TextLocale; + +void DrawItemIcon(UIWindow& window, ResourceMgr& resources, ItemDescriptions& descriptions, int x, int y, const ItemInfo& item, unsigned char identified); +void DrawItemWithQuantity( + UIWindow& window, ResourceMgr& resources, ItemDescriptions& descriptions, FontCache& fonts, const TextLocale& locale, int x, int y, const ItemInfo& item, + unsigned char identified, unsigned char plain +); + +#endif diff --git a/Source/UI/MerchantShopRefresh.cpp b/Source/UI/Shop/MerchantShopRefresh.cpp similarity index 69% rename from Source/UI/MerchantShopRefresh.cpp rename to Source/UI/Shop/MerchantShopRefresh.cpp index ac717d5..98399ea 100644 --- a/Source/UI/MerchantShopRefresh.cpp +++ b/Source/UI/Shop/MerchantShopRefresh.cpp @@ -1,20 +1,13 @@ -#include "Contents/MCStoreInfoBackup.h" -#include "UI/MerchantShopRefresh.h" -#include "UI/PriceColor.h" -#include "UI/UIEditCtrl.h" -#include "UI/UIWindow.h" -#include "Utility/GroupedInteger.h" +#include "Contents/Store/MCStoreInfoBackup.h" +#include "UI/Shop/MerchantShopRefresh.h" +#include "UI/Shop/PriceColor.h" +#include "UI/Edit/UIEditCtrl.h" +#include "UI/Window/UIWindow.h" +#include "Utility/Text/GroupedInteger.h" #include -#include #include -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } -} - // OFFSET: 0x00970E60 // FUNCTION: fn_13262 void MerchantShopRefresh::Refresh() { @@ -41,22 +34,19 @@ void MerchantShopRefresh::Refresh() { } for (const ItemInfo& item : this->offered) { - // Inventory add preserves identity and wraps count. - const auto found = std::find_if(this->inventory.begin(), this->inventory.end(), [&](const ItemInfo& value) { - return value.unknown_0000[1] == item.unknown_0000[1]; - }); + const auto found = + std::find_if(this->inventory.begin(), this->inventory.end(), [&](const ItemInfo& value) { return value.unknown_0000[1] == item.unknown_0000[1]; }); if (found == this->inventory.end()) { this->inventory.push_back(item); } else { - found->quantity = Add(found->quantity, item.quantity); + found->quantity = (found->quantity + item.quantity); } } this->offered.clear(); this->backup.Restore(this->mode != 0, this->maximum, this->inventory, this->offered); - // The original snapshots the displayed vector before invoking edit virtuals. const std::vector displayed(this->backup.items); int index = 0; @@ -66,7 +56,7 @@ void MerchantShopRefresh::Refresh() { } UIEditCtrl& edit = *this->priceEdits[index]; - const int price = std::bit_cast(item.unknown_0014[0]); + const int price = static_cast(item.unknown_0014[0]); char value[24] = {}; std::snprintf(value, sizeof(value), "%d", price); edit.disabled = 0; @@ -97,9 +87,7 @@ void MerchantShopRefresh::Refresh() { store->SendMsg(nullptr, 23, 0, 0, 0, 0); } - UIWindow* inventory = this->mode == 1 ? this->otherInventoryWindow - : this->mode == 2 ? this->extraInventoryWindow - : this->inventoryWindow; + UIWindow* inventory = this->mode == 1 ? this->otherInventoryWindow : this->mode == 2 ? this->extraInventoryWindow : this->inventoryWindow; if (inventory) { inventory->SendMsg(nullptr, 23, 0, 0, 0, 0); diff --git a/Source/UI/MerchantShopRefresh.h b/Source/UI/Shop/MerchantShopRefresh.h similarity index 81% rename from Source/UI/MerchantShopRefresh.h rename to Source/UI/Shop/MerchantShopRefresh.h index 6a8bbc6..bd56325 100644 --- a/Source/UI/MerchantShopRefresh.h +++ b/Source/UI/Shop/MerchantShopRefresh.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_MERCHANTSHOPREFRESH_H -#define RAGNAROK_SOURCE_UI_MERCHANTSHOPREFRESH_H +#ifndef RAGNAROK_SOURCE_UI_SHOP_MERCHANTSHOPREFRESH_H +#define RAGNAROK_SOURCE_UI_SHOP_MERCHANTSHOPREFRESH_H -#include "Contents/ItemInfo.h" +#include "Contents/Items/ItemInfo.h" #include #include diff --git a/Source/UI/PriceColor.cpp b/Source/UI/Shop/PriceColor.cpp similarity index 95% rename from Source/UI/PriceColor.cpp rename to Source/UI/Shop/PriceColor.cpp index 281b73a..878a9f7 100644 --- a/Source/UI/PriceColor.cpp +++ b/Source/UI/Shop/PriceColor.cpp @@ -1,4 +1,4 @@ -#include "UI/PriceColor.h" +#include "UI/Shop/PriceColor.h" // OFFSET: 0x00A7D8F0 // FUNCTION: fn_16957 diff --git a/Source/UI/PriceColor.h b/Source/UI/Shop/PriceColor.h similarity index 62% rename from Source/UI/PriceColor.h rename to Source/UI/Shop/PriceColor.h index 05d800e..f9c239e 100644 --- a/Source/UI/PriceColor.h +++ b/Source/UI/Shop/PriceColor.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_PRICECOLOR_H -#define RAGNAROK_SOURCE_UI_PRICECOLOR_H +#ifndef RAGNAROK_SOURCE_UI_SHOP_PRICECOLOR_H +#define RAGNAROK_SOURCE_UI_SHOP_PRICECOLOR_H #include diff --git a/Source/UI/ShortcutActivation.cpp b/Source/UI/ShortcutActivation.cpp deleted file mode 100644 index 98ef931..0000000 --- a/Source/UI/ShortcutActivation.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "Client/ClientOptions.h" -#include "Contents/AutomaticSkills.h" -#include "UI/ShortcutActivation.h" -#include "UI/UIWindow.h" - -#include - -// OFFSET: 0x00930900 -// FUNCTION: fn_12689 -void ActivateShortcut( - UIWindow& window, - ShortcutGrid& grid, - int x, - int y, - bool itemSlotActive, - unsigned char& currentRow, - const NormalItemSlot* const* slots, - AutomaticSkills& automatic, - ClientOptions& options -) { - const int column = grid.HitTest(x, y, itemSlotActive, currentRow); - if (column == -1) { - return; - } - const unsigned index = 9u * currentRow + static_cast(column); - const int limit = std::bit_cast(9u * static_cast(grid.rows)); - if (limit <= std::bit_cast(index)) { - return; - } - const NormalItemSlot& slot = *slots[index]; - if (slot.unknown_0000 != 0 && automatic.Contains(static_cast(slot.itemId))) { - options.Set( - AutomaticSkills::CancelOption(std::bit_cast(static_cast(slot.itemId))), 1, 0 - ); - } else { - automatic.DisableAll(); - } - window.SendMsg(nullptr, 41, column, currentRow, 0, 0); -} diff --git a/Source/UI/ShortcutActivation.h b/Source/UI/ShortcutActivation.h deleted file mode 100644 index 2157933..0000000 --- a/Source/UI/ShortcutActivation.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTACTIVATION_H -#define RAGNAROK_SOURCE_UI_SHORTCUTACTIVATION_H - -#include "Contents/NormalItemSlots.h" -#include "UI/ShortcutGrid.h" - -class AutomaticSkills; -struct ClientOptions; -class UIWindow; - -void ActivateShortcut( - UIWindow& window, - ShortcutGrid& grid, - int x, - int y, - bool itemSlotActive, - unsigned char& currentRow, - const NormalItemSlot* const* slots, - AutomaticSkills& automatic, - ClientOptions& options -); - -#endif diff --git a/Source/UI/ShortcutBindings.h b/Source/UI/ShortcutBindings.h deleted file mode 100644 index 5110276..0000000 --- a/Source/UI/ShortcutBindings.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTBINDINGS_H -#define RAGNAROK_SOURCE_UI_SHORTCUTBINDINGS_H - -#include "Contents/ClientSkills.h" -#include "Contents/NormalItemSlots.h" -#include "UI/ShortcutCooldowns.h" - -class LuaScript; -class ModeEvents; -// Original binding banks and client rotation/use-level fields are borrowed. -struct ShortcutBindings { - NormalItemSlot* banks[2]; - NormalItemSlot* items; - const int& mode; - const int& rotation0; - const int& rotation1; - ClientSkills& skills; - ShortcutCooldowns& cooldowns; - // Same live saved-use-level owner used by incoming skill updates. - const SkillUseLevels& levels; - - int Rotate(int index, int bank) const; - void Refresh(NormalItemSlot** slots, NormalItemSlot** itemSlots); - void Assign( - unsigned char type, - std::uint32_t id, - int level, - int slot, - int bank, - const unsigned char& currentRow, - LuaScript& script, - ModeEvents& modeEvents - ); - void AssignItem(std::uint32_t id, int slot); -}; - -#endif diff --git a/Source/UI/ShortcutControls.h b/Source/UI/ShortcutControls.h deleted file mode 100644 index 1ff9018..0000000 --- a/Source/UI/ShortcutControls.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTCONTROLS_H -#define RAGNAROK_SOURCE_UI_SHORTCUTCONTROLS_H - -struct UIWindowContext; -struct UIButtonContext; -class UIFrameWnd; -class UICheckBox; -class UIBitmapButton; -struct NormalItemSlot; - -// Borrowed original child pointers; the frame's child list owns the windows. -struct ShortcutControls { - UICheckBox* bank; - UIBitmapButton* decrease; - UIBitmapButton* increase; - UIBitmapButton* showItems; - UIBitmapButton* hideItems; - - static ShortcutControls Create( - UIFrameWnd& frame, - UIWindowContext& windows, - UIButtonContext& buttons, - int bankOption, - NormalItemSlot** slots, - NormalItemSlot** itemSlots - ); -}; - -#endif diff --git a/Source/UI/ShortcutCooldowns.h b/Source/UI/ShortcutCooldowns.h deleted file mode 100644 index 292f2ef..0000000 --- a/Source/UI/ShortcutCooldowns.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTCOOLDOWNS_H -#define RAGNAROK_SOURCE_UI_SHORTCUTCOOLDOWNS_H - -#include "UI/CooldownDrawing.h" - -#include - -// Visible-icon records (16-byte values). -struct ShortcutCooldownIcon { - unsigned id; - int slot; - int x; - int y; -}; - -// 28-byte values; each node owns two radial lists. -struct ShortcutCooldownRecord { - unsigned id; - std::uint32_t end; - std::uint32_t duration; - std::list main; - std::list alternate; -}; - -struct ShortcutCooldowns { - std::list records; - - // Packet extent is validated by the original network dispatcher, not here. - void LoadSnapshot( - const void* packet, - const std::list& mainIcons, - const std::list& alternateIcons, - int replayMode, - const std::uint32_t& serverTick - ); - void ApplyStart( - const void* packet, - const std::list& mainIcons, - const std::list& alternateIcons, - int replayMode, - const std::uint32_t& serverTick - ); - bool RotateRows(int amount, int bank, int& rotation0, int& rotation1, const CooldownClock& clock); - - void PaintMain( - const std::list& icons, - int rows, - int x, - int y, - CooldownDrawing& drawing, - const CooldownClock& clock, - RenderCommandPool& pool, - CRenderSystemBase& system - ); - void PaintAlternate( - const std::list& icons, - int x, - int y, - CooldownDrawing& drawing, - const CooldownClock& clock, - RenderCommandPool& pool, - CRenderSystemBase& system - ); - -private: - void Paint( - const std::list& icons, - std::list ShortcutCooldownRecord::* values, - int limit, - int x, - int y, - CooldownDrawing& drawing, - const CooldownClock& clock, - RenderCommandPool& pool, - CRenderSystemBase& system - ); -}; - -static_assert(sizeof(ShortcutCooldownIcon) == 16); -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(ShortcutCooldownRecord) == 28); -#endif - -#endif diff --git a/Source/UI/ShortcutDetails.h b/Source/UI/ShortcutDetails.h deleted file mode 100644 index ffe1626..0000000 --- a/Source/UI/ShortcutDetails.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTDETAILS_H -#define RAGNAROK_SOURCE_UI_SHORTCUTDETAILS_H - -#include "Contents/ClientSkills.h" -#include "Contents/ItemInfo.h" -#include "Contents/NormalItemSlots.h" -#include "UI/ShortcutGrid.h" - -class UIWindow; -class WindowManagerWindows; -struct SkillDetailClose; - -struct ShortcutDetails { - WindowManagerWindows& windows; - SkillDetailClose& skillClose; - const std::uint32_t& describedSkill; - ClientSkills& skills; - const std::list& inventory; - const bool& itemSlotActive; - unsigned char& currentRow; - const unsigned& screenWidth; - const unsigned& screenHeight; - - void Open( - UIWindow& window, - ShortcutGrid& grid, - int x, - int y, - const NormalItemSlot* const* slots, - const NormalItemSlot* const* itemSlots - ); -}; - -#endif diff --git a/Source/UI/ShortcutGrid.h b/Source/UI/ShortcutGrid.h deleted file mode 100644 index 1f321b3..0000000 --- a/Source/UI/ShortcutGrid.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTGRID_H -#define RAGNAROK_SOURCE_UI_SHORTCUTGRID_H - -// UIShortCutWnd contiguous fields+340..+351. The current-row byte lives in -// original client state and is supplied explicitly, not duplicated globally. -struct ShortcutGrid { - int hovered; - int row; - int rows; - - ShortcutGrid(); - int HitTest(int x, int y, bool itemSlotActive, unsigned char& currentRow); -}; - -static_assert(sizeof(ShortcutGrid) == 12); - -#endif diff --git a/Source/UI/ShortcutPainting.h b/Source/UI/ShortcutPainting.h deleted file mode 100644 index b522a7f..0000000 --- a/Source/UI/ShortcutPainting.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTPAINTING_H -#define RAGNAROK_SOURCE_UI_SHORTCUTPAINTING_H - -#include "Contents/ClientSkills.h" -#include "Contents/ItemDescription.h" -#include "Contents/ItemInfo.h" -#include "Contents/NormalItemSlots.h" -#include "UI/ShortcutCooldowns.h" -#include "UI/ShortcutGrid.h" - -class UIWindow; -class ResourceMgr; -class FontCache; -struct TextLocale; - -// Borrowed original window/client/manager state used by the complete Paint -// operation. This does not replace the unresolved UIShortCutWnd lifecycle. -struct ShortcutPainting { - ResourceMgr& resources; - FontCache& fonts; - const TextLocale& locale; - ClientSkills& skills; - const std::list& inventory; - ItemDescriptions& descriptions; - std::list& icons; - ShortcutCooldowns& cooldowns; - CooldownDrawing& drawing; - const CooldownClock& clock; - RenderCommandPool& commands; - CRenderSystemBase& system; - const bool& itemSlotActive; - const unsigned char& currentRow; - - void Paint( - UIWindow& window, - const ShortcutGrid& grid, - const NormalItemSlot* const* slots, - const NormalItemSlot* const* itemSlots - ); -}; - -#endif diff --git a/Source/UI/ShortcutPress.h b/Source/UI/ShortcutPress.h deleted file mode 100644 index c74de18..0000000 --- a/Source/UI/ShortcutPress.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTPRESS_H -#define RAGNAROK_SOURCE_UI_SHORTCUTPRESS_H - -#include "Contents/ClientSkills.h" -#include "Contents/ItemDescription.h" -#include "Contents/ItemInfo.h" -#include "Contents/NormalItemSlots.h" -#include "UI/ShortcutGrid.h" - -class UIFrameWnd; -class WindowManagerWindows; -class ResourceMgr; -struct ModeDragState; - -struct ShortcutPress { - ClientSkills& skills; - const std::list& inventory; - ItemDescriptions& descriptions; - ResourceMgr& resources; - WindowManagerWindows& windows; - ModeDragState*& drag; - const bool& restricted; - const bool& itemSlotActive; - unsigned char& currentRow; - - void Press( - UIFrameWnd& window, - ShortcutGrid& grid, - int x, - int y, - const NormalItemSlot* const* slots, - const NormalItemSlot* const* itemSlots - ); -}; - -#endif diff --git a/Source/UI/ShortcutTooltip.h b/Source/UI/ShortcutTooltip.h deleted file mode 100644 index 8234051..0000000 --- a/Source/UI/ShortcutTooltip.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTTOOLTIP_H -#define RAGNAROK_SOURCE_UI_SHORTCUTTOOLTIP_H - -#include "Client/ClientOptions.h" -#include "Contents/ClientSkills.h" -#include "Contents/ItemInfo.h" -#include "Contents/ItemNaming.h" -#include "Contents/NormalItemSlots.h" -#include "UI/ShortcutGrid.h" - -class UIWindow; -class LuaScript; -class ButtonServices; - -struct ShortcutTooltip { - ClientSkills& skills; - const std::list& inventory; - ItemNaming& naming; - ClientOptions& options; - LuaScript& script; - ButtonServices* services; - const bool& itemSlotActive; - unsigned char& currentRow; - - void Hover( - UIWindow& window, - ShortcutGrid& grid, - int x, - int y, - const NormalItemSlot* const* slots, - const NormalItemSlot* const* itemSlots - ); -}; - -#endif diff --git a/Source/UI/NormalItemSlotLoad.cpp b/Source/UI/Shortcuts/NormalItemSlotLoad.cpp similarity index 83% rename from Source/UI/NormalItemSlotLoad.cpp rename to Source/UI/Shortcuts/NormalItemSlotLoad.cpp index b66c346..fba906d 100644 --- a/Source/UI/NormalItemSlotLoad.cpp +++ b/Source/UI/Shortcuts/NormalItemSlotLoad.cpp @@ -1,7 +1,7 @@ -#include "UI/NormalItemSlotLoad.h" -#include "UI/ShortcutVisibility.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Shortcuts/NormalItemSlotLoad.h" +#include "UI/Shortcuts/ShortcutVisibility.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" #include #include @@ -9,12 +9,7 @@ // OFFSET: 0x005E65E0 // FUNCTION: fn_03929 void LoadNormalItemSlots( - Json::Value& data, - NormalItemSlot* slots, - NormalItemSlotWindow& saved, - bool& itemSlotActive, - WindowManagerWindows& windows, - ShortcutVisibility& visibility + Json::Value& data, NormalItemSlot* slots, NormalItemSlotWindow& saved, bool& itemSlotActive, WindowManagerWindows& windows, ShortcutVisibility& visibility ) { Json::Value& values = data["NormalItemSlot"]; diff --git a/Source/UI/Shortcuts/NormalItemSlotLoad.h b/Source/UI/Shortcuts/NormalItemSlotLoad.h new file mode 100644 index 0000000..2cc75d7 --- /dev/null +++ b/Source/UI/Shortcuts/NormalItemSlotLoad.h @@ -0,0 +1,13 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_NORMALITEMSLOTLOAD_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_NORMALITEMSLOTLOAD_H + +#include "Contents/UserData/NormalItemSlots.h" + +class WindowManagerWindows; +struct ShortcutVisibility; + +void LoadNormalItemSlots( + Json::Value& data, NormalItemSlot* slots, NormalItemSlotWindow& saved, bool& itemSlotActive, WindowManagerWindows& windows, ShortcutVisibility& visibility +); + +#endif diff --git a/Source/UI/Shortcuts/ShortcutActivation.cpp b/Source/UI/Shortcuts/ShortcutActivation.cpp new file mode 100644 index 0000000..1370e3b --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutActivation.cpp @@ -0,0 +1,31 @@ +#include "Client/ClientOptions.h" +#include "Contents/Skills/AutomaticSkills.h" +#include "UI/Shortcuts/ShortcutActivation.h" +#include "UI/Window/UIWindow.h" + +// OFFSET: 0x00930900 +// FUNCTION: fn_12689 +void ActivateShortcut( + UIWindow& window, ShortcutGrid& grid, int x, int y, bool itemSlotActive, unsigned char& currentRow, const NormalItemSlot* const* slots, + AutomaticSkills& automatic, ClientOptions& options +) { + const int column = grid.HitTest(x, y, itemSlotActive, currentRow); + if (column == -1) { + return; + } + + const unsigned index = 9u * currentRow + static_cast(column); + const int limit = 9 * grid.rows; + if (limit <= static_cast(index)) { + return; + } + + const NormalItemSlot& slot = *slots[index]; + if (slot.unknown_0000 != 0 && automatic.Contains(static_cast(slot.itemId))) { + options.Set(AutomaticSkills::CancelOption(static_cast(slot.itemId)), 1, 0); + } else { + automatic.DisableAll(); + } + + window.SendMsg(nullptr, 41, column, currentRow, 0, 0); +} diff --git a/Source/UI/Shortcuts/ShortcutActivation.h b/Source/UI/Shortcuts/ShortcutActivation.h new file mode 100644 index 0000000..4f465ae --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutActivation.h @@ -0,0 +1,16 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTACTIVATION_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTACTIVATION_H + +#include "Contents/UserData/NormalItemSlots.h" +#include "UI/Shortcuts/ShortcutGrid.h" + +class AutomaticSkills; +struct ClientOptions; +class UIWindow; + +void ActivateShortcut( + UIWindow& window, ShortcutGrid& grid, int x, int y, bool itemSlotActive, unsigned char& currentRow, const NormalItemSlot* const* slots, + AutomaticSkills& automatic, ClientOptions& options +); + +#endif diff --git a/Source/UI/ShortcutBindings.cpp b/Source/UI/Shortcuts/ShortcutBindings.cpp similarity index 60% rename from Source/UI/ShortcutBindings.cpp rename to Source/UI/Shortcuts/ShortcutBindings.cpp index 837a543..9058436 100644 --- a/Source/UI/ShortcutBindings.cpp +++ b/Source/UI/Shortcuts/ShortcutBindings.cpp @@ -1,14 +1,11 @@ -#include "Client/ModeEvents.h" +#include "Client/Mode/ModeEvents.h" #include "Script/LuaScript.h" -#include "UI/ShortcutBindings.h" +#include "UI/Shortcuts/ShortcutBindings.h" #include -// clang-format off -#include -// clang-format on +#include #include -#include // OFFSET: 0x00E12FC0 // FUNCTION: fn_23821 @@ -16,15 +13,16 @@ int ShortcutBindings::Rotate(int index, int bank) const { if (bank != 0 && bank != 1) { return index; } + const int rotation = bank == 0 ? this->rotation0 : this->rotation1; if (rotation == 0) { return index; } - const int value = std::bit_cast(static_cast(index) + 9u * static_cast(rotation)); - return value < 36 ? value : std::bit_cast(static_cast(value) - 36u); + + const int value = index + 9 * rotation; + return value < 36 ? value : value - 36; } -// Message 23 branch. // OFFSET: 0x0093B450 // FUNCTION: fn_12760 void ShortcutBindings::Refresh(NormalItemSlot** slots, NormalItemSlot** itemSlots) { @@ -33,40 +31,39 @@ void ShortcutBindings::Refresh(NormalItemSlot** slots, NormalItemSlot** itemSlot if (this->mode == 0 || this->mode == 1) { slots[index] = &this->banks[this->mode][source]; } + NormalItemSlot& slot = *slots[index]; if (slot.itemId == 0 || slot.unknown_0000 == 0) { continue; } - CSkillInfo skill = this->skills.bundle.Lookup( - slot.itemId, this->skills.classMode, this->skills.HasEffect(1717), this->skills.HasEffect(1716) - ); + + CSkillInfo skill = this->skills.bundle.Lookup(slot.itemId, this->skills.classMode, this->skills.HasEffect(1717), this->skills.HasEffect(1716)); if (skill.available == 0) { - // Original removes the first matching main radial before trying the - // other skill owners, even if one of those later resolves the skill. - const auto record = std::find_if( - this->cooldowns.records.begin(), this->cooldowns.records.end(), - [&](const ShortcutCooldownRecord& value) { return value.id == slot.itemId; } - ); + const auto record = std::find_if(this->cooldowns.records.begin(), this->cooldowns.records.end(), [&](const ShortcutCooldownRecord& value) { + return value.id == slot.itemId; + }); if (record != this->cooldowns.records.end()) { - const auto value = std::find_if(record->main.begin(), record->main.end(), [&](const CooldownState& state) { - return state.slot == index; - }); + const auto value = std::find_if(record->main.begin(), record->main.end(), [&](const CooldownState& state) { return state.slot == index; }); if (value != record->main.end()) { record->main.erase(value); } } + skill = this->skills.LookupFirst(slot.itemId); if (skill.available == 0) { skill = this->skills.LookupOther(slot.itemId); } + if (skill.available == 0) { skill = this->skills.LookupAdditional(slot.itemId); } } - if (skill.available != 0 && skill.level != 0 && this->levels.Lookup(std::bit_cast(skill.id)) == 0) { - slot.unknown_0005 = static_cast(skill.level); + + if (skill.available != 0 && skill.level != 0 && this->levels.Lookup(static_cast(skill.id)) == 0) { + slot.unknown_0005 = static_cast(skill.level); } } + for (int index = 0; index < 9; ++index) { itemSlots[index] = &this->items[index]; } @@ -75,79 +72,74 @@ void ShortcutBindings::Refresh(NormalItemSlot** slots, NormalItemSlot** itemSlot // OFFSET: 0x00E26050 // FUNCTION: fn_23913 void ShortcutBindings::Assign( - unsigned char type, - std::uint32_t id, - int level, - int slot, - int bank, - const unsigned char& currentRow, - LuaScript& script, - ModeEvents& modeEvents + unsigned char type, std::uint32_t id, int level, int slot, int bank, const unsigned char& currentRow, LuaScript& script, ModeEvents& modeEvents ) { const int rowStart = this->Rotate(9 * currentRow, bank); const int destination = this->Rotate(slot, bank); if (id == 0) { if (type != 0) { bool erased = false; + for (ShortcutCooldownRecord& record : this->cooldowns.records) { - const auto value = std::find_if(record.main.begin(), record.main.end(), [&](const CooldownState& state) { - return state.slot == slot; - }); + const auto value = std::find_if(record.main.begin(), record.main.end(), [&](const CooldownState& state) { return state.slot == slot; }); if (value != record.main.end()) { record.main.erase(value); erased = true; } + if (erased) { break; } } } + if (bank == 0 || bank == 1) { this->banks[bank][destination] = {}; } + modeEvents.SendModeMessage(313, destination, bank, 0, 0); return; } + for (int offset = 0; offset < 9; ++offset) { if (bank != 0 && bank != 1) { continue; } - const int index = std::bit_cast(static_cast(rowStart) + offset); + + const int index = rowStart + offset; const NormalItemSlot previous = this->banks[bank][index]; - bool duplicate = previous.itemId == id && std::bit_cast(previous.unknown_0005) == level && - previous.unknown_0000 == type; + bool duplicate = previous.itemId == id && previous.unknown_0005 == level && previous.unknown_0000 == type; + if (!duplicate) { - // Original invokes the script for every scanned nonexact slot, including - // different IDs/types and empty entries; do not hoist or skip this call. - const bool usesLevel = CSkillInfo::UsesLevel(script, std::bit_cast(previous.itemId)); + const bool usesLevel = CSkillInfo::UsesLevel(script, static_cast(previous.itemId)); duplicate = !usesLevel && previous.itemId == id && previous.unknown_0000 == type; } + if (!duplicate) { continue; } - const auto record = std::find_if( - this->cooldowns.records.begin(), this->cooldowns.records.end(), - [&](const ShortcutCooldownRecord& value) { return value.id == id; } - ); + + const auto record = + std::find_if(this->cooldowns.records.begin(), this->cooldowns.records.end(), [&](const ShortcutCooldownRecord& value) { return value.id == id; }); if (record != this->cooldowns.records.end() && record->end > timeGetTime()) { - const int position = - std::bit_cast(static_cast(index) + 9u * currentRow - static_cast(rowStart)); - const auto value = std::find_if(record->main.begin(), record->main.end(), [&](const CooldownState& state) { - return state.slot == position; - }); + const int position = index + 9 * currentRow - rowStart; + const auto value = std::find_if(record->main.begin(), record->main.end(), [&](const CooldownState& state) { return state.slot == position; }); if (value != record->main.end()) { record->main.erase(value); } } + this->banks[bank][index] = {}; modeEvents.SendModeMessage(313, index, bank, 0, 0); } + if (bank == 0 || bank == 1) { NormalItemSlot& value = this->banks[bank][destination]; - value.unknown_0005 = static_cast(level); + value.unknown_0005 = static_cast(level); value.unknown_0000 = type; value.itemId = id; } + modeEvents.SendModeMessage(313, destination, bank, 0, 0); } @@ -161,6 +153,7 @@ void ShortcutBindings::AssignItem(std::uint32_t id, int slot) { break; } } + this->items[slot].unknown_0005 = 0; this->items[slot].unknown_0000 = 0; this->items[slot].itemId = id; diff --git a/Source/UI/Shortcuts/ShortcutBindings.h b/Source/UI/Shortcuts/ShortcutBindings.h new file mode 100644 index 0000000..b3790ea --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutBindings.h @@ -0,0 +1,28 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTBINDINGS_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTBINDINGS_H + +#include "Contents/Skills/ClientSkills.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "UI/Shortcuts/ShortcutCooldowns.h" + +class LuaScript; +class ModeEvents; + +struct ShortcutBindings { + NormalItemSlot* banks[2]; + NormalItemSlot* items; + const int& mode; + const int& rotation0; + const int& rotation1; + ClientSkills& skills; + ShortcutCooldowns& cooldowns; + + const SkillUseLevels& levels; + + int Rotate(int index, int bank) const; + void Refresh(NormalItemSlot** slots, NormalItemSlot** itemSlots); + void Assign(unsigned char type, std::uint32_t id, int level, int slot, int bank, const unsigned char& currentRow, LuaScript& script, ModeEvents& modeEvents); + void AssignItem(std::uint32_t id, int slot); +}; + +#endif diff --git a/Source/UI/ShortcutControlEvents.cpp b/Source/UI/Shortcuts/ShortcutControlEvents.cpp similarity index 83% rename from Source/UI/ShortcutControlEvents.cpp rename to Source/UI/Shortcuts/ShortcutControlEvents.cpp index 4b79e4c..8102a89 100644 --- a/Source/UI/ShortcutControlEvents.cpp +++ b/Source/UI/Shortcuts/ShortcutControlEvents.cpp @@ -1,12 +1,10 @@ #include "Client/ClientOptions.h" -#include "UI/ShortcutControlEvents.h" -#include "UI/ShortcutCooldowns.h" -#include "UI/ShortcutVisibility.h" -#include "UI/UIBitmapButton.h" -#include "UI/UICheckBox.h" -#include "UI/UIWindow.h" - -#include +#include "UI/Shortcuts/ShortcutControlEvents.h" +#include "UI/Shortcuts/ShortcutCooldowns.h" +#include "UI/Shortcuts/ShortcutVisibility.h" +#include "UI/Buttons/UIBitmapButton.h" +#include "UI/Buttons/UICheckBox.h" +#include "UI/Window/UIWindow.h" // OFFSET: 0x0093B450 // FUNCTION: fn_12760 @@ -22,7 +20,7 @@ void ShortcutControlEvents::Click(int id) { return; } - this->grid.rows = std::bit_cast(static_cast(this->grid.rows) + 1u); + this->grid.rows = this->grid.rows + 1; if (this->grid.rows > 4) { this->grid.rows = 1; diff --git a/Source/UI/ShortcutControlEvents.h b/Source/UI/Shortcuts/ShortcutControlEvents.h similarity index 62% rename from Source/UI/ShortcutControlEvents.h rename to Source/UI/Shortcuts/ShortcutControlEvents.h index a1acaa4..d0d90bd 100644 --- a/Source/UI/ShortcutControlEvents.h +++ b/Source/UI/Shortcuts/ShortcutControlEvents.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTCONTROLEVENTS_H -#define RAGNAROK_SOURCE_UI_SHORTCUTCONTROLEVENTS_H +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTCONTROLEVENTS_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTCONTROLEVENTS_H -#include "UI/ShortcutControls.h" -#include "UI/ShortcutGrid.h" +#include "UI/Shortcuts/ShortcutControls.h" +#include "UI/Shortcuts/ShortcutGrid.h" class UIWindow; struct ShortcutVisibility; diff --git a/Source/UI/ShortcutControls.cpp b/Source/UI/Shortcuts/ShortcutControls.cpp similarity index 67% rename from Source/UI/ShortcutControls.cpp rename to Source/UI/Shortcuts/ShortcutControls.cpp index 8d37087..edeacaa 100644 --- a/Source/UI/ShortcutControls.cpp +++ b/Source/UI/Shortcuts/ShortcutControls.cpp @@ -1,9 +1,8 @@ -#include "UI/ShortcutControls.h" -#include "UI/UIBitmapButton.h" -#include "UI/UICheckBox.h" -#include "UI/UIFrameWnd.h" +#include "UI/Shortcuts/ShortcutControls.h" +#include "UI/Buttons/UIBitmapButton.h" +#include "UI/Buttons/UICheckBox.h" +#include "UI/Window/UIFrameWnd.h" -#include #include #define SHORTCUT_RESOURCE "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA" @@ -11,19 +10,15 @@ // OFFSET: 0x0092A190 // FUNCTION: fn_12654 ShortcutControls ShortcutControls::Create( - UIFrameWnd& frame, - UIWindowContext& windows, - UIButtonContext& buttons, - int bankOption, - NormalItemSlot** slots, - NormalItemSlot** itemSlots + UIFrameWnd& frame, UIWindowContext& windows, UIButtonContext& buttons, int bankOption, NormalItemSlot** slots, NormalItemSlot** itemSlots ) { ShortcutControls result; - frame.AddCloseButton(buttons, "F12", 0) - ->Move(std::bit_cast(static_cast(frame.geometry.width) - 10u), 0); + frame.AddCloseButton(buttons, "F12", 0)->Move(frame.geometry.width - 10, 0); + for (int index = 0; index < 36; ++index) { slots[index] = nullptr; } + result.bank = new (std::nothrow) UICheckBox(windows, buttons); result.bank->SetSize(10, 26); result.bank->SetImages( @@ -37,16 +32,18 @@ ShortcutControls ShortcutControls::Create( frame.AddChild(result.bank); const auto create = [&]( - int id, int x, int y, unsigned char disabled, unsigned char enabled, const char* normal, - const char* over, const char* pressed, const char* unavailable + int id, int x, int y, unsigned char disabled, unsigned char enabled, const char* normal, const char* over, const char* pressed, + const char* unavailable ) { UIBitmapButton* button = new UIBitmapButton(windows, buttons); button->SetBitmap(normal, 0, 0); button->SetBitmap(over, 1, 0); button->SetBitmap(pressed, 2, 0); + if (unavailable) { button->SetBitmap(unavailable, 3, 0); } + button->SetSize(button->BitmapWidth(), button->BitmapHeight()); button->SetId(id); button->SetDisabled(disabled); @@ -54,30 +51,31 @@ ShortcutControls ShortcutControls::Create( button->Move(x, y); button->Enable(enabled); frame.AddChild(button); + return button; }; result.decrease = create( - 217, 276, 0, 0, 0, SHORTCUT_RESOURCE "\\Shortcut\\btn_minus_normal.bmp", - SHORTCUT_RESOURCE "\\Shortcut\\btn_minus_over.bmp", SHORTCUT_RESOURCE "\\Shortcut\\btn_minus_press.bmp", nullptr + 217, 276, 0, 0, 0, SHORTCUT_RESOURCE "\\Shortcut\\btn_minus_normal.bmp", SHORTCUT_RESOURCE "\\Shortcut\\btn_minus_over.bmp", + SHORTCUT_RESOURCE "\\Shortcut\\btn_minus_press.bmp", nullptr ); result.increase = create( - 216, 276, 19, 0, 1, SHORTCUT_RESOURCE "\\Shortcut\\btn_plus_normal.bmp", - SHORTCUT_RESOURCE "\\Shortcut\\btn_plus_over.bmp", SHORTCUT_RESOURCE "\\Shortcut\\btn_plus_press.bmp", - SHORTCUT_RESOURCE "\\Shortcut\\btn_plus_disable.bmp" + 216, 276, 19, 0, 1, SHORTCUT_RESOURCE "\\Shortcut\\btn_plus_normal.bmp", SHORTCUT_RESOURCE "\\Shortcut\\btn_plus_over.bmp", + SHORTCUT_RESOURCE "\\Shortcut\\btn_plus_press.bmp", SHORTCUT_RESOURCE "\\Shortcut\\btn_plus_disable.bmp" ); + for (int index = 0; index < 9; ++index) { itemSlots[index] = nullptr; } + result.showItems = create( - 588, 247, 33, 1, 0, SHORTCUT_RESOURCE "\\Shortcut\\btn_open_itemslot_normal.bmp", - SHORTCUT_RESOURCE "\\Shortcut\\btn_open_itemslot_normal.bmp", + 588, 247, 33, 1, 0, SHORTCUT_RESOURCE "\\Shortcut\\btn_open_itemslot_normal.bmp", SHORTCUT_RESOURCE "\\Shortcut\\btn_open_itemslot_normal.bmp", SHORTCUT_RESOURCE "\\Shortcut\\btn_open_itemslot_press.bmp", nullptr ); result.hideItems = create( - 589, 247, 33, 0, 1, SHORTCUT_RESOURCE "\\Shortcut\\btn_close_itemslot_normal.bmp", - SHORTCUT_RESOURCE "\\Shortcut\\btn_close_itemslot_normal.bmp", + 589, 247, 33, 0, 1, SHORTCUT_RESOURCE "\\Shortcut\\btn_close_itemslot_normal.bmp", SHORTCUT_RESOURCE "\\Shortcut\\btn_close_itemslot_normal.bmp", SHORTCUT_RESOURCE "\\Shortcut\\btn_close_itemslot_press.bmp", nullptr ); frame.SendMsg(nullptr, 23, 0, 0, 0, 0); + return result; } diff --git a/Source/UI/Shortcuts/ShortcutControls.h b/Source/UI/Shortcuts/ShortcutControls.h new file mode 100644 index 0000000..f2e2e3f --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutControls.h @@ -0,0 +1,22 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTCONTROLS_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTCONTROLS_H + +struct UIWindowContext; +struct UIButtonContext; +class UIFrameWnd; +class UICheckBox; +class UIBitmapButton; +struct NormalItemSlot; + +struct ShortcutControls { + UICheckBox* bank; + UIBitmapButton* decrease; + UIBitmapButton* increase; + UIBitmapButton* showItems; + UIBitmapButton* hideItems; + + static ShortcutControls + Create(UIFrameWnd& frame, UIWindowContext& windows, UIButtonContext& buttons, int bankOption, NormalItemSlot** slots, NormalItemSlot** itemSlots); +}; + +#endif diff --git a/Source/UI/ShortcutCooldowns.cpp b/Source/UI/Shortcuts/ShortcutCooldowns.cpp similarity index 69% rename from Source/UI/ShortcutCooldowns.cpp rename to Source/UI/Shortcuts/ShortcutCooldowns.cpp index d05689e..278c282 100644 --- a/Source/UI/ShortcutCooldowns.cpp +++ b/Source/UI/Shortcuts/ShortcutCooldowns.cpp @@ -1,12 +1,9 @@ -#include "UI/ShortcutCooldowns.h" +#include "UI/Shortcuts/ShortcutCooldowns.h" #include -#include #include #include -// clang-format off -#include -// clang-format on +#include namespace { // OFFSET: 0x00E1DCA0 @@ -14,6 +11,7 @@ namespace { bool IsFirstRange(unsigned id) { return id - 8000u <= 60; } + // OFFSET: 0x00E1DD20 // FUNCTION: fn_23878 bool IsOtherRange(unsigned id) { @@ -24,10 +22,7 @@ namespace { // OFFSET: 0x00D42070 // FUNCTION: fn_21827 void ShortcutCooldowns::LoadSnapshot( - const void* packet, - const std::list& mainIcons, - const std::list& alternateIcons, - int replayMode, + const void* packet, const std::list& mainIcons, const std::list& alternateIcons, int replayMode, const std::uint32_t& serverTick ) { this->records.clear(); @@ -35,6 +30,7 @@ void ShortcutCooldowns::LoadSnapshot( std::int16_t size; std::memcpy(&size, bytes + 2, sizeof(size)); const int count = (size - 2) / 10; + for (int index = 0; index < count; ++index) { const unsigned char* source = bytes + 4 + index * 10; std::uint16_t id; @@ -45,17 +41,19 @@ void ShortcutCooldowns::LoadSnapshot( std::memcpy(&remaining, source + 6, sizeof(remaining)); const std::uint32_t now = replayMode == 1 ? serverTick : timeGetTime(); ShortcutCooldownRecord value{id, now + remaining, duration, {}, {}}; + for (const ShortcutCooldownIcon& icon : mainIcons) { if (icon.id == id) { value.main.emplace_back(icon.slot, icon.x, icon.y, duration, now, duration - remaining, 0); } } + for (const ShortcutCooldownIcon& icon : alternateIcons) { if (icon.id == id) { value.alternate.emplace_back(icon.slot, icon.x, icon.y, duration, now, duration - remaining, 0); } } - // Original copies both lists into the record; do not alias temporary values. + this->records.push_back(value); } } @@ -63,10 +61,7 @@ void ShortcutCooldowns::LoadSnapshot( // OFFSET: 0x00D41990 // FUNCTION: fn_21826 void ShortcutCooldowns::ApplyStart( - const void* packet, - const std::list& mainIcons, - const std::list& alternateIcons, - int replayMode, + const void* packet, const std::list& mainIcons, const std::list& alternateIcons, int replayMode, const std::uint32_t& serverTick ) { const auto* bytes = static_cast(packet); @@ -77,33 +72,31 @@ void ShortcutCooldowns::ApplyStart( const std::uint32_t now = replayMode == 1 ? serverTick : timeGetTime(); ShortcutCooldownRecord value{id, now + duration, duration, {}, {}}; const auto find = [&]() { - return std::find_if(this->records.begin(), this->records.end(), [&](const ShortcutCooldownRecord& record) { - return record.id == id; - }); + return std::find_if(this->records.begin(), this->records.end(), [&](const ShortcutCooldownRecord& record) { return record.id == id; }); }; + for (const ShortcutCooldownIcon& icon : mainIcons) { if (icon.id != id) { continue; } + const auto entry = find(); if (entry == this->records.end()) { value.main.emplace_back(icon.slot, icon.x, icon.y, duration, now, 0, 0); this->records.push_back(value); } else { - const auto slot = std::find_if(entry->main.begin(), entry->main.end(), [&](const CooldownState& state) { - return state.slot == icon.slot; - }); + const auto slot = std::find_if(entry->main.begin(), entry->main.end(), [&](const CooldownState& state) { return state.slot == icon.slot; }); if (slot == entry->main.end()) { - // Adding a new slot does not update the existing record's expiry. entry->main.emplace_back(icon.slot, icon.x, icon.y, duration, now, 0, 0); } else { this->records.erase(entry); - // The original local lists accumulate across this packet's icons. + value.main.emplace_back(icon.slot, icon.x, icon.y, duration, now, 0, 0); this->records.push_back(value); } } } + for (const ShortcutCooldownIcon& icon : alternateIcons) { if (icon.id == id && find() == this->records.end()) { value.alternate.emplace_back(icon.slot, icon.x, icon.y, duration, now, 0, 0); @@ -119,100 +112,84 @@ bool ShortcutCooldowns::RotateRows(int amount, int bank, int& rotation0, int& ro if (rows <= 0) { return false; } - const auto add = [](int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - }; + if (bank == 0 || bank == 1) { int& rotation = bank == 0 ? rotation0 : rotation1; - rotation = add(rotation, rows); + rotation += rows; if (rotation >= 4) { - rotation = add(rotation, -4); + rotation -= 4; } } + const std::uint32_t now = clock.Now(); + for (auto entry = this->records.begin(); entry != this->records.end();) { if (entry->end <= now) { entry = this->records.erase(entry); continue; } + for (CooldownState& state : entry->main) { - state.slot = add(state.slot, -9 * rows); - state.y = add(state.y, -33 * rows); + state.slot -= 9 * rows; + state.y -= 33 * rows; if (state.slot < 0) { - state.slot = add(state.slot, 36); - state.y = add(state.y, 132); + state.slot += 36; + state.y += 132; } } + ++entry; } + return true; } // OFFSET: 0x0092F8E0 // FUNCTION: fn_12680 void ShortcutCooldowns::PaintMain( - const std::list& icons, - int rows, - int x, - int y, - CooldownDrawing& drawing, - const CooldownClock& clock, - RenderCommandPool& pool, + const std::list& icons, int rows, int x, int y, CooldownDrawing& drawing, const CooldownClock& clock, RenderCommandPool& pool, CRenderSystemBase& system ) { - const int limit = std::bit_cast(static_cast(rows) * 33u + 4u); + const int limit = rows * 33 + 4; this->Paint(icons, &ShortcutCooldownRecord::main, limit, x, y, drawing, clock, pool, system); } // OFFSET: 0x0092D660 // FUNCTION: fn_12671 void ShortcutCooldowns::PaintAlternate( - const std::list& icons, - int x, - int y, - CooldownDrawing& drawing, - const CooldownClock& clock, - RenderCommandPool& pool, + const std::list& icons, int x, int y, CooldownDrawing& drawing, const CooldownClock& clock, RenderCommandPool& pool, CRenderSystemBase& system ) { this->Paint(icons, &ShortcutCooldownRecord::alternate, 0, x, y, drawing, clock, pool, system); } void ShortcutCooldowns::Paint( - const std::list& icons, - std::list ShortcutCooldownRecord::* values, - int limit, - int x, - int y, - CooldownDrawing& drawing, - const CooldownClock& clock, - RenderCommandPool& pool, - CRenderSystemBase& system + const std::list& icons, std::list ShortcutCooldownRecord::* values, int limit, int x, int y, CooldownDrawing& drawing, + const CooldownClock& clock, RenderCommandPool& pool, CRenderSystemBase& system ) { const std::uint32_t now = clock.Now(); + for (auto entry = this->records.begin(); entry != this->records.end();) { - // Original uses absolute unsigned comparison, not signed tick subtraction. if (entry->end <= now) { entry = this->records.erase(entry); continue; } + std::list& states = (*entry).*values; + for (const ShortcutCooldownIcon& icon : icons) { - if ( - entry->id == icon.id || (entry->id == 577 && !IsFirstRange(icon.id)) || - (entry->id == 9999 && (IsFirstRange(icon.id) || IsOtherRange(icon.id))) - ) { - const auto previous = std::find_if(states.begin(), states.end(), [&](const CooldownState& state) { - return state.slot == icon.slot; - }); + if (entry->id == icon.id || (entry->id == 577 && !IsFirstRange(icon.id)) || (entry->id == 9999 && (IsFirstRange(icon.id) || IsOtherRange(icon.id)))) { + const auto previous = std::find_if(states.begin(), states.end(), [&](const CooldownState& state) { return state.slot == icon.slot; }); if (previous == states.end()) { states.emplace_back(icon.slot, icon.x, icon.y, entry->duration, entry->end - entry->duration, 0, 0); } } } + for (CooldownState& state : states) { drawing.Draw(0, 0, 12, 12, state, limit, x, y, clock, pool, system); } + ++entry; } } diff --git a/Source/UI/Shortcuts/ShortcutCooldowns.h b/Source/UI/Shortcuts/ShortcutCooldowns.h new file mode 100644 index 0000000..7274076 --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutCooldowns.h @@ -0,0 +1,57 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTCOOLDOWNS_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTCOOLDOWNS_H + +#include "UI/Cooldowns/CooldownDrawing.h" + +#include + +struct ShortcutCooldownIcon { + unsigned id; + int slot; + int x; + int y; +}; + +struct ShortcutCooldownRecord { + unsigned id; + std::uint32_t end; + std::uint32_t duration; + std::list main; + std::list alternate; +}; + +struct ShortcutCooldowns { + std::list records; + + void LoadSnapshot( + const void* packet, const std::list& mainIcons, const std::list& alternateIcons, int replayMode, + const std::uint32_t& serverTick + ); + void ApplyStart( + const void* packet, const std::list& mainIcons, const std::list& alternateIcons, int replayMode, + const std::uint32_t& serverTick + ); + bool RotateRows(int amount, int bank, int& rotation0, int& rotation1, const CooldownClock& clock); + + void PaintMain( + const std::list& icons, int rows, int x, int y, CooldownDrawing& drawing, const CooldownClock& clock, RenderCommandPool& pool, + CRenderSystemBase& system + ); + void PaintAlternate( + const std::list& icons, int x, int y, CooldownDrawing& drawing, const CooldownClock& clock, RenderCommandPool& pool, + CRenderSystemBase& system + ); + +private: + void Paint( + const std::list& icons, std::list ShortcutCooldownRecord::* values, int limit, int x, int y, CooldownDrawing& drawing, + const CooldownClock& clock, RenderCommandPool& pool, CRenderSystemBase& system + ); +}; + +static_assert(sizeof(ShortcutCooldownIcon) == 16); +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(ShortcutCooldownRecord) == 28); +#endif + +#endif diff --git a/Source/UI/ShortcutDetails.cpp b/Source/UI/Shortcuts/ShortcutDetails.cpp similarity index 52% rename from Source/UI/ShortcutDetails.cpp rename to Source/UI/Shortcuts/ShortcutDetails.cpp index 1e4f025..b2f1bda 100644 --- a/Source/UI/ShortcutDetails.cpp +++ b/Source/UI/Shortcuts/ShortcutDetails.cpp @@ -1,39 +1,24 @@ -#include "UI/ShortcutDetails.h" -#include "UI/SkillDetailClose.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" - -#include +#include "UI/Shortcuts/ShortcutDetails.h" +#include "UI/Shortcuts/SkillDetailClose.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" namespace { - - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - void ToScreen(const UIWindow& window, int& x, int& y) { - x = Add(x, window.geometry.x); - y = Add(y, window.geometry.y); + x = (x + window.geometry.x); + y = (y + window.geometry.y); for (const WindowAncestry* node = window.parent; node; node = node->parent) { const UIWindow* owner = static_cast(node); - x = Add(x, owner->geometry.x); - y = Add(y, owner->geometry.y); + x = (x + owner->geometry.x); + y = (y + owner->geometry.y); } } - } // OFFSET: 0x009332D0 // FUNCTION: fn_12724 -void ShortcutDetails::Open( - UIWindow& window, - ShortcutGrid& grid, - int x, - int y, - const NormalItemSlot* const* slots, - const NormalItemSlot* const* itemSlots -) { +void ShortcutDetails::Open(UIWindow& window, ShortcutGrid& grid, int x, int y, const NormalItemSlot* const* slots, const NormalItemSlot* const* itemSlots) { const int column = grid.HitTest(x, y, this->itemSlotActive, this->currentRow); if (column == -1) { @@ -41,7 +26,7 @@ void ShortcutDetails::Open( } const int index = 9 * this->currentRow + column; - const int limit = std::bit_cast(9u * static_cast(grid.rows)); + const int limit = 9 * grid.rows; const NormalItemSlot* slot; if (limit <= index) { @@ -59,7 +44,7 @@ void ShortcutDetails::Open( } if (limit <= index || slot->unknown_0000 == 0) { - ItemInfo item = LookupClientItem(this->inventory, std::bit_cast(slot->itemId), 1); + ItemInfo item = LookupClientItem(this->inventory, static_cast(slot->itemId), 1); if (item.unknown_0000[1] != 0) { UIWindow* detail = this->windows.EnsureWindow(12); @@ -88,17 +73,16 @@ void ShortcutDetails::Open( int originX = 0; int originY = 0; ToScreen(window, originX, originY); - const int targetX = Add(originX, x); - unsigned adjustment = 0; + const int targetX = (originX + x); + int adjustment = 0; if (this->screenWidth - static_cast(targetX) < static_cast(detail->geometry.width)) { - adjustment = static_cast(targetX) + detail->geometry.width - this->screenWidth; + adjustment = targetX + detail->geometry.width - static_cast(this->screenWidth); } - const int rowY = std::bit_cast(33u * static_cast(y / 33)); - const int targetY = static_cast(originY) <= static_cast(this->screenHeight) * 0.5f - ? Add(Add(originY, rowY), 33) - : Add(Add(originY, rowY), -detail->geometry.height); + const int rowY = 33 * (y / 33); + const int targetY = + static_cast(originY) <= static_cast(this->screenHeight) * 0.5f ? ((originY + rowY) + 33) : ((originY + rowY) - detail->geometry.height); - detail->Move(std::bit_cast(static_cast(targetX) - adjustment), targetY); + detail->Move(targetX - adjustment, targetY); } diff --git a/Source/UI/Shortcuts/ShortcutDetails.h b/Source/UI/Shortcuts/ShortcutDetails.h new file mode 100644 index 0000000..1a91f49 --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutDetails.h @@ -0,0 +1,27 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTDETAILS_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTDETAILS_H + +#include "Contents/Skills/ClientSkills.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "UI/Shortcuts/ShortcutGrid.h" + +class UIWindow; +class WindowManagerWindows; +struct SkillDetailClose; + +struct ShortcutDetails { + WindowManagerWindows& windows; + SkillDetailClose& skillClose; + const std::uint32_t& describedSkill; + ClientSkills& skills; + const std::list& inventory; + const bool& itemSlotActive; + unsigned char& currentRow; + const unsigned& screenWidth; + const unsigned& screenHeight; + + void Open(UIWindow& window, ShortcutGrid& grid, int x, int y, const NormalItemSlot* const* slots, const NormalItemSlot* const* itemSlots); +}; + +#endif diff --git a/Source/UI/ShortcutDrop.cpp b/Source/UI/Shortcuts/ShortcutDrop.cpp similarity index 77% rename from Source/UI/ShortcutDrop.cpp rename to Source/UI/Shortcuts/ShortcutDrop.cpp index a093ebe..ddfe264 100644 --- a/Source/UI/ShortcutDrop.cpp +++ b/Source/UI/Shortcuts/ShortcutDrop.cpp @@ -1,18 +1,14 @@ -#include "Client/ModeDragState.h" -#include "Client/ModeEvents.h" -#include "UI/ShortcutDrop.h" -#include "UI/UIWindow.h" +#include "Client/Mode/ModeDragState.h" +#include "Client/Mode/ModeEvents.h" +#include "UI/Shortcuts/ShortcutDrop.h" +#include "UI/Window/UIWindow.h" #include -#include #include #include -// clang-format off -#include -// clang-format on +#include namespace { - bool Grouped(std::uint32_t id) { return id - 8000u <= 60 || id - 8200u <= 41 || id - 8400u <= 57; } @@ -24,9 +20,7 @@ namespace { void RemoveFirst(ShortcutCooldowns& cooldowns, int slot) { for (ShortcutCooldownRecord& record : cooldowns.records) { - const auto value = std::find_if(record.main.begin(), record.main.end(), [&](const CooldownState& state) { - return state.slot == slot; - }); + const auto value = std::find_if(record.main.begin(), record.main.end(), [&](const CooldownState& state) { return state.slot == slot; }); if (value != record.main.end()) { record.main.erase(value); return; @@ -38,7 +32,6 @@ namespace { // OFFSET: 0x00917640 // FUNCTION: fn_12589 void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, const ModeDragState& value) { - // Original snapshots this option before any mode/script callback. const int bank = this->bindings.mode; if (value.skill != 0) { @@ -59,6 +52,7 @@ void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, cons if (this->mode) { this->mode->SendModeMessage(18, 0, 0, 0, 0); } + return; } @@ -70,17 +64,16 @@ void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, cons const std::uint32_t key = Grouped(skill.id) ? 9999 : skill.id; - const auto record = std::find_if( - this->bindings.cooldowns.records.begin(), this->bindings.cooldowns.records.end(), - [&](const ShortcutCooldownRecord& entry) { return entry.id == key; } - ); + const auto record = + std::find_if(this->bindings.cooldowns.records.begin(), this->bindings.cooldowns.records.end(), [&](const ShortcutCooldownRecord& entry) { + return entry.id == key; + }); if (record != this->bindings.cooldowns.records.end() && record->end > timeGetTime()) { - const auto previous = std::find_if(record->main.begin(), record->main.end(), [&](const CooldownState& state) { - return state.slot == originalSlot; - }); + const auto previous = std::find_if(record->main.begin(), record->main.end(), [&](const CooldownState& state) { return state.slot == originalSlot; }); const int targetX = 29 * column + 16; const int targetY = 33 * this->currentRow + 4; + if (previous != record->main.end() && previous->y == targetY) { previous->slot = index; previous->x = targetX; @@ -90,22 +83,21 @@ void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, cons } Refresh(window); - } else if (originalSlot != -1) { CSkillInfo skill = this->bindings.skills.Lookup(id); const std::uint32_t key = Grouped(skill.id) ? 9999 : skill.id; - const auto record = std::find_if( - this->bindings.cooldowns.records.begin(), this->bindings.cooldowns.records.end(), - [&](const ShortcutCooldownRecord& entry) { return entry.id == key; } - ); - if (record != this->bindings.cooldowns.records.end()) { - const auto previous = std::find_if(record->main.begin(), record->main.end(), [&](const CooldownState& state) { - return state.slot == originalSlot; + const auto record = + std::find_if(this->bindings.cooldowns.records.begin(), this->bindings.cooldowns.records.end(), [&](const ShortcutCooldownRecord& entry) { + return entry.id == key; }); + + if (record != this->bindings.cooldowns.records.end()) { + const auto previous = std::find_if(record->main.begin(), record->main.end(), [&](const CooldownState& state) { return state.slot == originalSlot; }); if (previous != record->main.end()) { record->main.erase(previous); } } + this->bindings.Assign(1, 0, 0, originalSlot, bank, this->currentRow, this->script, *this->mode); Refresh(window); } @@ -130,11 +122,12 @@ void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, cons if (type == 3 || type == 10 || type == 16 || type == 17 || type == 19) { const int column = grid.HitTest(x, y, this->itemSlotActive, this->currentRow); - if (column != -1 && std::bit_cast(9u * static_cast(grid.rows)) <= 9 * this->currentRow + column) { + if (column != -1 && 9 * grid.rows <= 9 * this->currentRow + column) { if (this->itemSlotActive) { this->bindings.AssignItem(static_cast(std::atoi(item.itemId.c_str())), column); Refresh(window); } + consumed = true; } } @@ -144,17 +137,16 @@ void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, cons if (type == 4 || type == 5 || type == 8 || type == 9 || (type >= 11 && type <= 15)) { allowed = item.unknown_0000[2] != 0; } + if (allowed) { const int column = grid.HitTest(x, y, this->itemSlotActive, this->currentRow); if (column != -1 && grid.rows > this->currentRow) { const int index = 9 * this->currentRow + column; - this->bindings.Assign( - 0, static_cast(std::atoi(item.itemId.c_str())), 0, index, bank, this->currentRow, this->script, - *this->mode - ); + this->bindings.Assign(0, static_cast(std::atoi(item.itemId.c_str())), 0, index, bank, this->currentRow, this->script, *this->mode); if (value.slot != index) { RemoveFirst(this->bindings.cooldowns, index); } + Refresh(window); } } diff --git a/Source/UI/ShortcutDrop.h b/Source/UI/Shortcuts/ShortcutDrop.h similarity index 60% rename from Source/UI/ShortcutDrop.h rename to Source/UI/Shortcuts/ShortcutDrop.h index 50f7d8e..a3cc04d 100644 --- a/Source/UI/ShortcutDrop.h +++ b/Source/UI/Shortcuts/ShortcutDrop.h @@ -1,9 +1,9 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTDROP_H -#define RAGNAROK_SOURCE_UI_SHORTCUTDROP_H +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTDROP_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTDROP_H -#include "Contents/ItemInfo.h" -#include "UI/ShortcutBindings.h" -#include "UI/ShortcutGrid.h" +#include "Contents/Items/ItemInfo.h" +#include "UI/Shortcuts/ShortcutBindings.h" +#include "UI/Shortcuts/ShortcutGrid.h" class UIWindow; struct ModeDragState; diff --git a/Source/UI/ShortcutGrid.cpp b/Source/UI/Shortcuts/ShortcutGrid.cpp similarity index 81% rename from Source/UI/ShortcutGrid.cpp rename to Source/UI/Shortcuts/ShortcutGrid.cpp index 6c30a2f..5d65359 100644 --- a/Source/UI/ShortcutGrid.cpp +++ b/Source/UI/Shortcuts/ShortcutGrid.cpp @@ -1,4 +1,4 @@ -#include "UI/ShortcutGrid.h" +#include "UI/Shortcuts/ShortcutGrid.h" #include #include @@ -11,25 +11,30 @@ ShortcutGrid::ShortcutGrid() : hovered(-1), row(-1), rows(1) { // FUNCTION: fn_12616 int ShortcutGrid::HitTest(int x, int y, bool itemSlotActive, unsigned char& currentRow) { this->row = -1; - std::uint32_t extent = 33u * static_cast(this->rows); + int extent = 33 * this->rows; if (itemSlotActive) { extent += 33; } - if (y <= 3 || y >= std::bit_cast(extent)) { + + if (y <= 3 || y >= extent) { return -1; } + const std::uint32_t columnOffset = static_cast(x) - 15; if (columnOffset > 260) { return -1; } + this->row = (y - 4) / 33; currentRow = static_cast(this->row); if (y > this->row * 33 + 30) { this->row = -1; } + const int column = static_cast(columnOffset) / 29; if (x > column * 29 + 41) { return -1; } + return column; } diff --git a/Source/UI/Shortcuts/ShortcutGrid.h b/Source/UI/Shortcuts/ShortcutGrid.h new file mode 100644 index 0000000..c006e68 --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutGrid.h @@ -0,0 +1,15 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTGRID_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTGRID_H + +struct ShortcutGrid { + int hovered; + int row; + int rows; + + ShortcutGrid(); + int HitTest(int x, int y, bool itemSlotActive, unsigned char& currentRow); +}; + +static_assert(sizeof(ShortcutGrid) == 12); + +#endif diff --git a/Source/UI/ShortcutLayout.cpp b/Source/UI/Shortcuts/ShortcutLayout.cpp similarity index 56% rename from Source/UI/ShortcutLayout.cpp rename to Source/UI/Shortcuts/ShortcutLayout.cpp index f11c87b..d82c917 100644 --- a/Source/UI/ShortcutLayout.cpp +++ b/Source/UI/Shortcuts/ShortcutLayout.cpp @@ -1,24 +1,9 @@ -#include "UI/ShortcutLayout.h" -#include "UI/UIBitmapButton.h" - -#include - -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Multiply(int value, unsigned scale) { - return std::bit_cast(static_cast(value) * scale); - } -} +#include "UI/Shortcuts/ShortcutLayout.h" +#include "UI/Buttons/UIBitmapButton.h" void ShortcutLayout::PlaceRowButtons() { - this->decrease.Move( - Add(Add(this->window.geometry.width, -this->decrease.geometry.width), -2), Add(Multiply(this->grid.rows, 33), -28) - ); - this->increase.Move( - Add(Add(this->window.geometry.width, -this->increase.geometry.width), -2), Add(Multiply(this->grid.rows, 33), -13) - ); + this->decrease.Move(this->window.geometry.width - this->decrease.geometry.width - 2, this->grid.rows * 33 - 28); + this->increase.Move(this->window.geometry.width - this->increase.geometry.width - 2, this->grid.rows * 33 - 13); this->decrease.Enable(this->grid.rows == 1 ? 0 : 1); this->increase.Enable(1); this->increase.SetDisabled(this->grid.rows == 4 ? 1 : 0); @@ -28,20 +13,17 @@ void ShortcutLayout::PlaceRowButtons() { // OFFSET: 0x0093B450 // FUNCTION: fn_12760 void ShortcutLayout::ResizeRows() { - const int height = Add(this->itemSlotActive ? 43 : 10, Multiply(this->grid.rows, 33)); + const int height = (this->itemSlotActive ? 43 : 10) + this->grid.rows * 33; if (height == this->window.geometry.height) { return; } + this->window.Resize(this->window.geometry.width, height); - // Original positions both row buttons before either Enable callback. - this->decrease.Move( - Add(Add(this->window.geometry.width, -this->decrease.geometry.width), -2), Add(Multiply(this->grid.rows, 33), -28) - ); - this->increase.Move( - Add(Add(this->window.geometry.width, -this->increase.geometry.width), -2), Add(Multiply(this->grid.rows, 33), -13) - ); - this->showItems.Move(247, Add(height, -10)); - this->hideItems.Move(247, Add(height, -10)); + + this->decrease.Move(this->window.geometry.width - this->decrease.geometry.width - 2, this->grid.rows * 33 - 28); + this->increase.Move(this->window.geometry.width - this->increase.geometry.width - 2, this->grid.rows * 33 - 13); + this->showItems.Move(247, height - 10); + this->hideItems.Move(247, height - 10); this->decrease.Enable(this->grid.rows == 1 ? 0 : 1); this->increase.Enable(1); this->increase.SetDisabled(this->grid.rows == 4 ? 1 : 0); @@ -56,11 +38,12 @@ void ShortcutLayout::Restore(NormalItemSlotWindow* value) { if (!value->IsValid(this->screenWidth, this->screenHeight, this->itemSlotActive)) { value->Reset(); } + const int height = value->height; this->window.Resize(this->window.geometry.width, height); - const int extent = this->itemSlotActive ? Add(height, -43) : height; - this->showItems.Move(247, Add(height, -10)); - this->hideItems.Move(247, Add(height, -10)); + const int extent = this->itemSlotActive ? height - 43 : height; + this->showItems.Move(247, height - 10); + this->hideItems.Move(247, height - 10); this->showItems.Enable(this->itemSlotActive ? 0 : 1); this->showItems.SetDisabled(this->itemSlotActive ? 1 : 0); this->showItems.Invalidate(); @@ -79,6 +62,7 @@ void ShortcutLayout::Persist() { if (!this->saved) { return; } + this->saved->x = this->window.geometry.x; this->saved->y = this->window.geometry.y; this->saved->width = this->window.geometry.width; diff --git a/Source/UI/ShortcutLayout.h b/Source/UI/Shortcuts/ShortcutLayout.h similarity index 60% rename from Source/UI/ShortcutLayout.h rename to Source/UI/Shortcuts/ShortcutLayout.h index f08c0ab..476c5a5 100644 --- a/Source/UI/ShortcutLayout.h +++ b/Source/UI/Shortcuts/ShortcutLayout.h @@ -1,14 +1,12 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTLAYOUT_H -#define RAGNAROK_SOURCE_UI_SHORTCUTLAYOUT_H +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTLAYOUT_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTLAYOUT_H -#include "Contents/NormalItemSlots.h" -#include "UI/ShortcutGrid.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "UI/Shortcuts/ShortcutGrid.h" class UIWindow; class UIBitmapButton; -// Original shortcut fields+184,+188,+192,+388,+392 and client item-row byte. -// Borrowed controls are actual child windows, not layout-only substitutes. struct ShortcutLayout { UIWindow& window; ShortcutGrid& grid; diff --git a/Source/UI/ShortcutPainting.cpp b/Source/UI/Shortcuts/ShortcutPainting.cpp similarity index 54% rename from Source/UI/ShortcutPainting.cpp rename to Source/UI/Shortcuts/ShortcutPainting.cpp index 1c8c6ce..01bed5f 100644 --- a/Source/UI/ShortcutPainting.cpp +++ b/Source/UI/Shortcuts/ShortcutPainting.cpp @@ -1,30 +1,26 @@ -#include "Render/TextContext.h" -#include "Resource/BitmapResource.h" +#include "Render/Text/TextContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/ItemDrawing.h" -#include "UI/ShortcutPainting.h" -#include "UI/UIWindow.h" +#include "UI/Shop/ItemDrawing.h" +#include "UI/Shortcuts/ShortcutPainting.h" +#include "UI/Window/UIWindow.h" -#include #include #include namespace { constexpr char prefix[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA"; - int Add(int value, int offset) { - return std::bit_cast(static_cast(value) + static_cast(offset)); - } - int Multiply(int value, unsigned scale) { - return std::bit_cast(static_cast(value) * scale); - } + CBitmapRes* Load(ResourceMgr& resources, const char* tail) { char path[200]; std::sprintf(path, "%s%s", prefix, tail); return static_cast(resources.Load(path)); } + void Bitmap(UIWindow& window, CBitmapRes* image, int x, int y, bool transparent) { window.DrawBitmap(x, y, image ? &image->image : nullptr, transparent); } + // OFFSET: 0x00A86200 // FUNCTION: fn_17019 void Count(UIWindow& window, FontCache& fonts, const TextLocale& locale, int right, int y, int value) { @@ -33,12 +29,12 @@ namespace { const int bytes = static_cast(std::strlen(text)); TextContext context(*window.geometry.surface, fonts, locale); context.SetFont(0, 11, 0, 0); - const int left = Add(right, -context.Measure(text, bytes).cx); + const int left = (right - context.Measure(text, bytes).cx); context.SetColor(0xFFFFFF); - context.Draw(Add(left, -1), y, text, bytes); - context.Draw(Add(left, 1), y, text, bytes); - context.Draw(left, Add(y, -1), text, bytes); - context.Draw(left, Add(y, 1), text, bytes); + context.Draw((left - 1), y, text, bytes); + context.Draw((left + 1), y, text, bytes); + context.Draw(left, (y - 1), text, bytes); + context.Draw(left, (y + 1), text, bytes); context.SetColor(0); context.Draw(left, y, text, bytes); } @@ -46,114 +42,115 @@ namespace { // OFFSET: 0x0092F8E0 // FUNCTION: fn_12680 -void ShortcutPainting::Paint( - UIWindow& window, - const ShortcutGrid& grid, - const NormalItemSlot* const* slots, - const NormalItemSlot* const* itemSlots -) { +void ShortcutPainting::Paint(UIWindow& window, const ShortcutGrid& grid, const NormalItemSlot* const* slots, const NormalItemSlot* const* itemSlots) { CBitmapRes* frame = Load(this->resources, "\\Shortcut\\shortcut_frame.bmp"); + for (int row = 0; row < grid.rows; ++row) { - Bitmap(window, frame, 0, Multiply(row, 33), false); + Bitmap(window, frame, 0, (row * 33), false); } + if (this->itemSlotActive) { - Bitmap( - window, Load(this->resources, "\\Shortcut\\shortcut_frame_item.bmp"), 0, - grid.rows > 0 ? Multiply(grid.rows, 33) : 0, false - ); + Bitmap(window, Load(this->resources, "\\Shortcut\\shortcut_frame_item.bmp"), 0, grid.rows > 0 ? (grid.rows * 33) : 0, false); } + if (grid.row != -1 && grid.hovered != -1) { - // Samples the current skin colorchip at(10,10). CBitmapRes* chip = Load(this->resources, "\\colorchip.bmp"); std::uint32_t color = 0; if (chip) { - const std::uint32_t pixel = chip->image.width > 10 && chip->image.height > 10 - ? chip->image.pixels[10 + 10 * chip->image.width] - : 0x00FF0000u; + const std::uint32_t pixel = chip->image.width > 10 && chip->image.height > 10 ? chip->image.pixels[10 + 10 * chip->image.width] : 0x00FF0000u; color = ((pixel & 255) << 16) | (pixel & 0xFF00) | ((pixel >> 16) & 255); } - window.FillRegion( - Add(Multiply(grid.hovered, 29), 16), 5 + 33 * static_cast(this->currentRow), 24, 24, color - ); + + window.FillRegion(((grid.hovered * 29) + 16), 5 + 33 * static_cast(this->currentRow), 24, 24, color); } + this->icons.clear(); + for (int row = 0; row < grid.rows; ++row) { - const int y = Add(Multiply(row, 33), 4); + const int y = ((row * 33) + 4); + for (int column = 0; column < 9; ++column) { - const int index = Add(Multiply(row, 9), column); + const int index = ((row * 9) + column); if (index >= 36) { continue; } + const NormalItemSlot& slot = *slots[index]; if (slot.itemId == 0) { continue; } + const int x = 16 + 29 * column; if (slot.unknown_0000 != 0) { CSkillInfo skill = this->skills.Lookup(slot.itemId); if (!skill.MatchesShortcut(&slot)) { continue; } + char path[200]; - // Original formats the borrowed skill name at+0x20, not a numeric ID. + std::sprintf(path, "%s\\item\\%s.bmp", prefix, skill.name); CBitmapRes* image = static_cast(this->resources.Load(path)); if (!image) { image = Load(this->resources, "\\item\\am_berserkpitcher.bmp"); } + this->icons.push_back({skill.id, index, x, y}); Bitmap(window, image, x, y, true); - int level = std::bit_cast(slot.unknown_0005); + int level = slot.unknown_0005; + if ((skill.id == 6579 || skill.id == 6580) && skill.level < level) { level = skill.level; } - Count(window, this->fonts, this->locale, x + 27, Add(y, 17), level); + + Count(window, this->fonts, this->locale, x + 27, (y + 17), level); } else { - ItemInfo item = LookupClientItem(this->inventory, std::bit_cast(slot.itemId), 1); + ItemInfo item = LookupClientItem(this->inventory, static_cast(slot.itemId), 1); if (item.unknown_0000[1] == 0) { continue; } - DrawItemIcon( - window, this->resources, this->descriptions, x, y, item, static_cast(item.unknown_0060) - ); + + DrawItemIcon(window, this->resources, this->descriptions, x, y, item, static_cast(item.unknown_0060)); if (item.quantity != 0) { - Count(window, this->fonts, this->locale, x + 27, Add(y, 17), item.quantity); + Count(window, this->fonts, this->locale, x + 27, (y + 17), item.quantity); } + if (item.unknown_0088 > 0) { char tail[96]; std::sprintf(tail, "\\grade_enchant\\grade_icon%d.bmp", item.unknown_0088); - Bitmap(window, Load(this->resources, tail), x, Add(y, 12), true); + Bitmap(window, Load(this->resources, tail), x, (y + 12), true); } } } } + if (this->itemSlotActive) { - const int y = Add(Multiply(grid.rows, 33), 4); + const int y = ((grid.rows * 33) + 4); + for (int column = 0; column < 9; ++column) { const NormalItemSlot& slot = *itemSlots[column]; if (slot.itemId == 0) { continue; } - ItemInfo item = LookupClientItem(this->inventory, std::bit_cast(slot.itemId), 1); + + ItemInfo item = LookupClientItem(this->inventory, static_cast(slot.itemId), 1); if (item.unknown_0000[1] == 0) { continue; } + const int x = 16 + 29 * column; - DrawItemIcon( - window, this->resources, this->descriptions, x, y, item, static_cast(item.unknown_0060) - ); + DrawItemIcon(window, this->resources, this->descriptions, x, y, item, static_cast(item.unknown_0060)); if (item.quantity != 0) { - Count(window, this->fonts, this->locale, x + 27, Add(y, 17), item.quantity); + Count(window, this->fonts, this->locale, x + 27, (y + 17), item.quantity); } } } + for (int row = 0; row < grid.rows; ++row) { char text[24]; - std::sprintf(text, "%d", Add(row, 1)); - window.DrawTextAt(this->fonts, this->locale, 6, Add(Multiply(row, 33), 13), text, 0, 0, 11, 0x2F4A4A, 0, 0); + std::sprintf(text, "%d", (row + 1)); + window.DrawTextAt(this->fonts, this->locale, 6, ((row * 33) + 13), text, 0, 0, 11, 0x2F4A4A, 0, 0); } - this->cooldowns.PaintMain( - this->icons, grid.rows, window.geometry.x, window.geometry.y, this->drawing, this->clock, this->commands, - this->system - ); + + this->cooldowns.PaintMain(this->icons, grid.rows, window.geometry.x, window.geometry.y, this->drawing, this->clock, this->commands, this->system); } diff --git a/Source/UI/Shortcuts/ShortcutPainting.h b/Source/UI/Shortcuts/ShortcutPainting.h new file mode 100644 index 0000000..059e196 --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutPainting.h @@ -0,0 +1,35 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTPAINTING_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTPAINTING_H + +#include "Contents/Skills/ClientSkills.h" +#include "Contents/Items/ItemDescription.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "UI/Shortcuts/ShortcutCooldowns.h" +#include "UI/Shortcuts/ShortcutGrid.h" + +class UIWindow; +class ResourceMgr; +class FontCache; +struct TextLocale; + +struct ShortcutPainting { + ResourceMgr& resources; + FontCache& fonts; + const TextLocale& locale; + ClientSkills& skills; + const std::list& inventory; + ItemDescriptions& descriptions; + std::list& icons; + ShortcutCooldowns& cooldowns; + CooldownDrawing& drawing; + const CooldownClock& clock; + RenderCommandPool& commands; + CRenderSystemBase& system; + const bool& itemSlotActive; + const unsigned char& currentRow; + + void Paint(UIWindow& window, const ShortcutGrid& grid, const NormalItemSlot* const* slots, const NormalItemSlot* const* itemSlots); +}; + +#endif diff --git a/Source/UI/ShortcutPress.cpp b/Source/UI/Shortcuts/ShortcutPress.cpp similarity index 57% rename from Source/UI/ShortcutPress.cpp rename to Source/UI/Shortcuts/ShortcutPress.cpp index d7bb1cf..e2ecf14 100644 --- a/Source/UI/ShortcutPress.cpp +++ b/Source/UI/Shortcuts/ShortcutPress.cpp @@ -1,49 +1,41 @@ -#include "Client/ModeDragState.h" -#include "UI/ShortcutPress.h" -#include "UI/UIFrameWnd.h" - -#include +#include "Client/Mode/ModeDragState.h" +#include "UI/Shortcuts/ShortcutPress.h" +#include "UI/Window/UIFrameWnd.h" // OFFSET: 0x009310E0 // FUNCTION: fn_12699 -void ShortcutPress::Press( - UIFrameWnd& window, - ShortcutGrid& grid, - int x, - int y, - const NormalItemSlot* const* slots, - const NormalItemSlot* const* itemSlots -) { - const int columnOffset = std::bit_cast(static_cast(x) - 15u); +void ShortcutPress::Press(UIFrameWnd& window, ShortcutGrid& grid, int x, int y, const NormalItemSlot* const* slots, const NormalItemSlot* const* itemSlots) { + const int columnOffset = x - 15; if (columnOffset >= 261 || x < 15 || y < 4) { window.UIFrameWnd::Slot25(x, y); return; } + if (this->restricted) { return; } + const int column = grid.HitTest(x, y, this->itemSlotActive, this->currentRow); if (column == -1) { return; } + grid.hovered = column; const int index = 9 * this->currentRow + column; - if (std::bit_cast(9u * static_cast(grid.rows)) > index) { + if (9 * grid.rows > index) { const NormalItemSlot& slot = *slots[index]; if (slot.itemId == 0) { return; } + if (slot.unknown_0000 != 0) { CSkillInfo skill = this->skills.Lookup(slot.itemId); if (skill.MatchesShortcut(&slot) && this->drag) { - this->drag->BeginSkill( - this->windows, this->resources, 7, skill.id, skill.name, std::bit_cast(slot.unknown_0005), index - ); + this->drag->BeginSkill(this->windows, this->resources, 7, skill.id, skill.name, slot.unknown_0005, index); } } else { - ItemInfo item = LookupClientItem(this->inventory, std::bit_cast(slot.itemId), 1); + ItemInfo item = LookupClientItem(this->inventory, static_cast(slot.itemId), 1); if (item.unknown_0000[1] != 0) { - // Original main-row item path does not guard the active mode pointer. this->drag->BeginItem(this->windows, this->descriptions, 7, item, item.quantity, -1); } } @@ -52,7 +44,8 @@ void ShortcutPress::Press( if (slot.itemId == 0) { return; } - ItemInfo item = LookupClientItem(this->inventory, std::bit_cast(slot.itemId), 1); + + ItemInfo item = LookupClientItem(this->inventory, static_cast(slot.itemId), 1); if (item.unknown_0000[1] != 0 && this->drag) { this->drag->BeginItem(this->windows, this->descriptions, 7, item, item.quantity, -1); } diff --git a/Source/UI/Shortcuts/ShortcutPress.h b/Source/UI/Shortcuts/ShortcutPress.h new file mode 100644 index 0000000..46fc6a6 --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutPress.h @@ -0,0 +1,29 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTPRESS_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTPRESS_H + +#include "Contents/Skills/ClientSkills.h" +#include "Contents/Items/ItemDescription.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "UI/Shortcuts/ShortcutGrid.h" + +class UIFrameWnd; +class WindowManagerWindows; +class ResourceMgr; +struct ModeDragState; + +struct ShortcutPress { + ClientSkills& skills; + const std::list& inventory; + ItemDescriptions& descriptions; + ResourceMgr& resources; + WindowManagerWindows& windows; + ModeDragState*& drag; + const bool& restricted; + const bool& itemSlotActive; + unsigned char& currentRow; + + void Press(UIFrameWnd& window, ShortcutGrid& grid, int x, int y, const NormalItemSlot* const* slots, const NormalItemSlot* const* itemSlots); +}; + +#endif diff --git a/Source/UI/ShortcutTooltip.cpp b/Source/UI/Shortcuts/ShortcutTooltip.cpp similarity index 61% rename from Source/UI/ShortcutTooltip.cpp rename to Source/UI/Shortcuts/ShortcutTooltip.cpp index f59900d..70c2dbc 100644 --- a/Source/UI/ShortcutTooltip.cpp +++ b/Source/UI/Shortcuts/ShortcutTooltip.cpp @@ -1,68 +1,67 @@ -#include "Contents/HotkeyInfo.h" -#include "UI/ShortcutTooltip.h" -#include "UI/UIButton.h" -#include "UI/UIWindow.h" +#include "Contents/Hotkeys/HotkeyInfo.h" +#include "UI/Shortcuts/ShortcutTooltip.h" +#include "UI/Buttons/UIButton.h" +#include "UI/Window/UIWindow.h" -#include #include namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } void ToScreen(const UIWindow& window, int& x, int& y) { - x = Add(x, window.geometry.x); - y = Add(y, window.geometry.y); + x = (x + window.geometry.x); + y = (y + window.geometry.y); + for (const WindowAncestry* node = window.parent; node; node = node->parent) { const UIWindow* owner = static_cast(node); - x = Add(x, owner->geometry.x); - y = Add(y, owner->geometry.y); + x = (x + owner->geometry.x); + y = (y + owner->geometry.y); } } } // OFFSET: 0x00932050 // FUNCTION: fn_12711 -void ShortcutTooltip::Hover( - UIWindow& window, - ShortcutGrid& grid, - int x, - int y, - const NormalItemSlot* const* slots, - const NormalItemSlot* const* itemSlots -) { +void ShortcutTooltip::Hover(UIWindow& window, ShortcutGrid& grid, int x, int y, const NormalItemSlot* const* slots, const NormalItemSlot* const* itemSlots) { const int column = grid.HitTest(x, y, this->itemSlotActive, this->currentRow); if (column != grid.hovered) { grid.hovered = column; window.Invalidate(); } + if (grid.hovered == -1 || grid.row == -1) { return; } - const int index = Add(grid.hovered, std::bit_cast(9u * static_cast(grid.row))); - int tooltipX = Add(std::bit_cast(29u * static_cast((x - 15) / 29)), 15); + + const int index = (grid.hovered + 9 * grid.row); + int tooltipX = 29 * ((x - 15) / 29) + 15; int tooltipY = -17; - if (std::bit_cast(9u * static_cast(grid.rows)) <= index) { + + if (9 * grid.rows <= index) { if (!this->itemSlotActive) { return; } + const NormalItemSlot& slot = *itemSlots[grid.hovered]; if (slot.itemId == 0) { return; } - ItemInfo item = LookupClientItem(this->inventory, std::bit_cast(slot.itemId), 1); + + ItemInfo item = LookupClientItem(this->inventory, static_cast(slot.itemId), 1); if (item.unknown_0000[1] == 0) { return; } + const std::string name = this->naming.DisplayName(item, 0); char text[4096]; _snprintf_s(text, sizeof(text), _TRUNCATE, this->naming.Message(183), name.c_str(), item.unknown_0000[1]); ToScreen(window, tooltipX, tooltipY); + if (this->services) { this->services->Tooltip(text, tooltipX, tooltipY, -1, false, true); } + return; } + HotkeyInfo hotkey; const int bank = this->options.Get(10); if (bank == 0) { @@ -70,13 +69,16 @@ void ShortcutTooltip::Hover( } else if (bank == 1) { hotkey = GetHotkeyInfo(this->script, 3, index); } + std::string shortcut; if (!hotkey.description.empty()) { shortcut = std::move(hotkey.text); } + ToScreen(window, tooltipX, tooltipY); std::string text; const NormalItemSlot& slot = *slots[index]; + if (slot.itemId == 0) { text = shortcut; } else if (slot.unknown_0000 != 0) { @@ -84,30 +86,26 @@ void ShortcutTooltip::Hover( if (!skill.MatchesShortcut(&slot)) { text = shortcut; } else { - int level = std::bit_cast(slot.unknown_0005); + int level = slot.unknown_0005; if ((skill.id == 6579 || skill.id == 6580) && skill.level < level) { level = skill.level; } + const int sp = skill.UseSpAmount(this->script, level); const int ap = skill.UseApAmount(this->script, level); - text = SkillTooltip( - shortcut.c_str(), skill.DisplayName(this->script), level, sp, ap, - SkillUsesPercentSp(std::bit_cast(skill.id)) - ); + text = SkillTooltip(shortcut.c_str(), skill.DisplayName(this->script), level, sp, ap, SkillUsesPercentSp(static_cast(skill.id))); } } else { - ItemInfo item = LookupClientItem(this->inventory, std::bit_cast(slot.itemId), 1); + ItemInfo item = LookupClientItem(this->inventory, static_cast(slot.itemId), 1); if (item.unknown_0000[1] == 0) { text = shortcut; } else { const std::string name = this->naming.DisplayName(item, 0); char formatted[4096]; - _snprintf_s( - formatted, sizeof(formatted), _TRUNCATE, this->naming.Message(184), shortcut.c_str(), name.c_str(), - item.unknown_0000[1] - ); + _snprintf_s(formatted, sizeof(formatted), _TRUNCATE, this->naming.Message(184), shortcut.c_str(), name.c_str(), item.unknown_0000[1]); text = formatted; } } + this->services->Tooltip(text.c_str(), tooltipX, tooltipY, -1, false, true); } diff --git a/Source/UI/Shortcuts/ShortcutTooltip.h b/Source/UI/Shortcuts/ShortcutTooltip.h new file mode 100644 index 0000000..7fde5ac --- /dev/null +++ b/Source/UI/Shortcuts/ShortcutTooltip.h @@ -0,0 +1,28 @@ +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTTOOLTIP_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTTOOLTIP_H + +#include "Client/ClientOptions.h" +#include "Contents/Skills/ClientSkills.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/Items/ItemNaming.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "UI/Shortcuts/ShortcutGrid.h" + +class UIWindow; +class LuaScript; +class ButtonServices; + +struct ShortcutTooltip { + ClientSkills& skills; + const std::list& inventory; + ItemNaming& naming; + ClientOptions& options; + LuaScript& script; + ButtonServices* services; + const bool& itemSlotActive; + unsigned char& currentRow; + + void Hover(UIWindow& window, ShortcutGrid& grid, int x, int y, const NormalItemSlot* const* slots, const NormalItemSlot* const* itemSlots); +}; + +#endif diff --git a/Source/UI/ShortcutUse.cpp b/Source/UI/Shortcuts/ShortcutUse.cpp similarity index 78% rename from Source/UI/ShortcutUse.cpp rename to Source/UI/Shortcuts/ShortcutUse.cpp index 4b3f111..60ace1d 100644 --- a/Source/UI/ShortcutUse.cpp +++ b/Source/UI/Shortcuts/ShortcutUse.cpp @@ -1,12 +1,10 @@ -#include "Client/ModeEvents.h" -#include "UI/ShortcutUse.h" -#include "UI/UIButton.h" +#include "Client/Mode/ModeEvents.h" +#include "UI/Shortcuts/ShortcutUse.h" +#include "UI/Buttons/UIButton.h" -#include #include #include -// Message 41 branch. // OFFSET: 0x0093B450 // FUNCTION: fn_12760 void ShortcutUse::Use(const NormalItemSlot& slot) { @@ -17,7 +15,7 @@ void ShortcutUse::Use(const NormalItemSlot& slot) { if (slot.unknown_0000 != 0) { CSkillInfo skill = this->skills.Lookup(slot.itemId); if (skill.MatchesShortcut(&slot)) { - int level = std::bit_cast(slot.unknown_0005); + int level = slot.unknown_0005; if ((skill.id == 6579 || skill.id == 6580) && skill.level < level) { level = skill.level; } @@ -28,7 +26,7 @@ void ShortcutUse::Use(const NormalItemSlot& slot) { return; } - ItemInfo item = LookupClientItem(this->inventory, std::bit_cast(slot.itemId), 1); + ItemInfo item = LookupClientItem(this->inventory, static_cast(slot.itemId), 1); if (item.unknown_0000[1] == 0) { return; } @@ -41,10 +39,7 @@ void ShortcutUse::Use(const NormalItemSlot& slot) { case 0: case 1: case 2: - if ( - std::atoi(item.itemId.c_str()) != 12802 || - this->dialogs.Confirm(this->naming.Message(2373), 2, 0, 0, "Message", 280, 120) != 188 - ) { + if (std::atoi(item.itemId.c_str()) != 12802 || this->dialogs.Confirm(this->naming.Message(2373), 2, 0, 0, "Message", 280, 120) != 188) { use(); } diff --git a/Source/UI/ShortcutUse.h b/Source/UI/Shortcuts/ShortcutUse.h similarity index 56% rename from Source/UI/ShortcutUse.h rename to Source/UI/Shortcuts/ShortcutUse.h index e6ad7b2..35e323a 100644 --- a/Source/UI/ShortcutUse.h +++ b/Source/UI/Shortcuts/ShortcutUse.h @@ -1,11 +1,11 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTUSE_H -#define RAGNAROK_SOURCE_UI_SHORTCUTUSE_H +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTUSE_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTUSE_H #include "Client/ClientOptions.h" -#include "Contents/ClientSkills.h" -#include "Contents/ItemInfo.h" -#include "Contents/ItemNaming.h" -#include "Contents/NormalItemSlots.h" +#include "Contents/Skills/ClientSkills.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/Items/ItemNaming.h" +#include "Contents/UserData/NormalItemSlots.h" class ModeEvents; class ButtonServices; diff --git a/Source/UI/ShortcutVisibility.cpp b/Source/UI/Shortcuts/ShortcutVisibility.cpp similarity index 78% rename from Source/UI/ShortcutVisibility.cpp rename to Source/UI/Shortcuts/ShortcutVisibility.cpp index f15e58c..5399195 100644 --- a/Source/UI/ShortcutVisibility.cpp +++ b/Source/UI/Shortcuts/ShortcutVisibility.cpp @@ -1,7 +1,7 @@ -#include "UI/ShortcutVisibility.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" -#include "UI/WindowOrdering.h" +#include "UI/Shortcuts/ShortcutVisibility.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" +#include "UI/Window/WindowOrdering.h" // OFFSET: 0x00AAA310 // FUNCTION: fn_17269 diff --git a/Source/UI/ShortcutVisibility.h b/Source/UI/Shortcuts/ShortcutVisibility.h similarity index 65% rename from Source/UI/ShortcutVisibility.h rename to Source/UI/Shortcuts/ShortcutVisibility.h index 92112bc..c0a7ec9 100644 --- a/Source/UI/ShortcutVisibility.h +++ b/Source/UI/Shortcuts/ShortcutVisibility.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_UI_SHORTCUTVISIBILITY_H -#define RAGNAROK_SOURCE_UI_SHORTCUTVISIBILITY_H +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTVISIBILITY_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SHORTCUTVISIBILITY_H class UIWindow; class WindowManagerWindows; struct WindowOrdering; -// Original UIWindowMgr shortcut pointer, visibility value and replay policy. struct ShortcutVisibility { WindowManagerWindows& windows; WindowOrdering& ordering; diff --git a/Source/UI/SkillDetailClose.cpp b/Source/UI/Shortcuts/SkillDetailClose.cpp similarity index 65% rename from Source/UI/SkillDetailClose.cpp rename to Source/UI/Shortcuts/SkillDetailClose.cpp index 12ad6c6..f16fe62 100644 --- a/Source/UI/SkillDetailClose.cpp +++ b/Source/UI/Shortcuts/SkillDetailClose.cpp @@ -1,14 +1,12 @@ -#include "UI/FrameFocus.h" -#include "UI/SkillDetailClose.h" -#include "UI/UIWindow.h" -#include "UI/WindowRetirement.h" +#include "UI/Window/FrameFocus.h" +#include "UI/Shortcuts/SkillDetailClose.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowRetirement.h" // OFFSET: 0x00A8CF20 bool SkillDetailClose::Close() { if (this->window) { - this->saved[46] = { - this->window->geometry.x, this->window->geometry.y, this->window->geometry.width, this->window->geometry.height - }; + this->saved[46] = {this->window->geometry.x, this->window->geometry.y, this->window->geometry.width, this->window->geometry.height}; } if (!this->modalStack.empty() && this->modalStack.back() != 0) { diff --git a/Source/UI/SkillDetailClose.h b/Source/UI/Shortcuts/SkillDetailClose.h similarity index 74% rename from Source/UI/SkillDetailClose.h rename to Source/UI/Shortcuts/SkillDetailClose.h index 13d68a9..f63aca8 100644 --- a/Source/UI/SkillDetailClose.h +++ b/Source/UI/Shortcuts/SkillDetailClose.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_SKILLDETAILCLOSE_H -#define RAGNAROK_SOURCE_UI_SKILLDETAILCLOSE_H +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_SKILLDETAILCLOSE_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_SKILLDETAILCLOSE_H #include #include @@ -15,7 +15,6 @@ struct SavedWindowRectangle { int height; }; -// Selected window46 branch over the original manager's borrowed state. struct SkillDetailClose { UIWindow*& window; int& visible; diff --git a/Source/UI/UIShortCutWnd.cpp b/Source/UI/Shortcuts/UIShortCutWnd.cpp similarity index 69% rename from Source/UI/UIShortCutWnd.cpp rename to Source/UI/Shortcuts/UIShortCutWnd.cpp index b78cff6..89ae13f 100644 --- a/Source/UI/UIShortCutWnd.cpp +++ b/Source/UI/Shortcuts/UIShortCutWnd.cpp @@ -1,27 +1,19 @@ #include "Client/ClientOptions.h" -#include "Client/ModeDragState.h" -#include "UI/ShortcutActivation.h" -#include "UI/ShortcutBindings.h" -#include "UI/ShortcutControlEvents.h" -#include "UI/ShortcutDetails.h" -#include "UI/ShortcutDrop.h" -#include "UI/ShortcutLayout.h" -#include "UI/ShortcutPainting.h" -#include "UI/ShortcutPress.h" -#include "UI/ShortcutTooltip.h" -#include "UI/ShortcutUse.h" -#include "UI/UIShortCutWnd.h" -#include "UI/WindowSnapping.h" +#include "Client/Mode/ModeDragState.h" +#include "UI/Shortcuts/ShortcutActivation.h" +#include "UI/Shortcuts/ShortcutBindings.h" +#include "UI/Shortcuts/ShortcutControlEvents.h" +#include "UI/Shortcuts/ShortcutDetails.h" +#include "UI/Shortcuts/ShortcutDrop.h" +#include "UI/Shortcuts/ShortcutLayout.h" +#include "UI/Shortcuts/ShortcutPainting.h" +#include "UI/Shortcuts/ShortcutPress.h" +#include "UI/Shortcuts/ShortcutTooltip.h" +#include "UI/Shortcuts/ShortcutUse.h" +#include "UI/Shortcuts/UIShortCutWnd.h" +#include "UI/Layout/WindowSnapping.h" -#include - -namespace { - - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - -} +namespace {} // OFFSET: 0x009122B0 UIShortCutWnd::UIShortCutWnd(UIWindowContext& windows, UIFrameContext& frames, ShortcutWindowContext& shortcuts) @@ -46,8 +38,8 @@ void UIShortCutWnd::Move(int x, int y) { this->geometry.x = x; this->geometry.y = y; this->m_frameContext->snapping.Constrain(this, x, y, 0); - this->geometry.x = Add(this->geometry.x, x); - const int top = Add(this->geometry.y, y); + this->geometry.x = (this->geometry.x + x); + const int top = (this->geometry.y + y); this->geometry.y = top < 0 ? 0 : top; this->m_frameContext->snapping.Store(this); } @@ -90,17 +82,15 @@ void UIShortCutWnd::Show(int visible) { // OFFSET: 0x0092A190 // FUNCTION: fn_12654 void UIShortCutWnd::Slot15(int, int) { - this->m_controls = ShortcutControls::Create( - *this, *this->m_context, this->m_shortcuts->buttons, this->m_shortcuts->options.Get(10), this->m_slots, - this->m_itemSlots - ); + this->m_controls = + ShortcutControls::Create(*this, *this->m_context, this->m_shortcuts->buttons, this->m_shortcuts->options.Get(10), this->m_slots, this->m_itemSlots); } // OFFSET: 0x00932F30 // FUNCTION: fn_12720 void UIShortCutWnd::Slot19() { - const int x = Add(this->m_shortcuts->cursorX, std::bit_cast(0u - static_cast(this->geometry.x))); - const int y = Add(this->m_shortcuts->cursorY, std::bit_cast(0u - static_cast(this->geometry.y))); + const int x = (this->m_shortcuts->cursorX - this->geometry.x); + const int y = (this->m_shortcuts->cursorY - this->geometry.y); this->m_grid.hovered = this->m_grid.HitTest(x, y, this->m_shortcuts->itemSlotActive, this->m_shortcuts->currentRow); this->Invalidate(); } @@ -121,8 +111,8 @@ void UIShortCutWnd::Slot25(int x, int y) { // FUNCTION: fn_12689 void UIShortCutWnd::Slot26(int x, int y) { ActivateShortcut( - *this, this->m_grid, x, y, this->m_shortcuts->itemSlotActive, this->m_shortcuts->currentRow, this->m_slots, - this->m_shortcuts->automatic, this->m_shortcuts->options + *this, this->m_grid, x, y, this->m_shortcuts->itemSlotActive, this->m_shortcuts->currentRow, this->m_slots, this->m_shortcuts->automatic, + this->m_shortcuts->options ); } @@ -147,25 +137,12 @@ void UIShortCutWnd::Slot32(int x, int y) { // OFFSET: 0x0093B450 // FUNCTION: fn_12760 -int UIShortCutWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIShortCutWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { ShortcutWindowContext& owner = *this->m_shortcuts; switch (message) { case 6: { - ShortcutControlEvents events{*this, - this->m_grid, - this->m_controls, - owner.visibility, - owner.options, - owner.bindings.cooldowns, - owner.itemSlotActive}; + ShortcutControlEvents events{*this, this->m_grid, this->m_controls, owner.visibility, owner.options, owner.bindings.cooldowns, owner.itemSlotActive}; events.Click(static_cast(a)); return 0; } @@ -210,17 +187,13 @@ int UIShortCutWnd::SendMsg( } case 41: { - const int index = std::bit_cast(9u * static_cast(b) + static_cast(a)); + const int index = 9 * static_cast(b) + static_cast(a); owner.use.Use(*this->m_slots[index]); return 0; } case 143: - if ( - owner.bindings.cooldowns.RotateRows( - static_cast(a), static_cast(b), owner.rotation0, owner.rotation1, owner.clock - ) - ) { + if (owner.bindings.cooldowns.RotateRows(static_cast(a), static_cast(b), owner.rotation0, owner.rotation1, owner.clock)) { this->SendMsg(nullptr, 23, 0, 0, 0, 0); } diff --git a/Source/UI/UIShortCutWnd.h b/Source/UI/Shortcuts/UIShortCutWnd.h similarity index 83% rename from Source/UI/UIShortCutWnd.h rename to Source/UI/Shortcuts/UIShortCutWnd.h index 70e1256..84e933b 100644 --- a/Source/UI/UIShortCutWnd.h +++ b/Source/UI/Shortcuts/UIShortCutWnd.h @@ -1,9 +1,9 @@ -#ifndef RAGNAROK_SOURCE_UI_UISHORTCUTWND_H -#define RAGNAROK_SOURCE_UI_UISHORTCUTWND_H +#ifndef RAGNAROK_SOURCE_UI_SHORTCUTS_UISHORTCUTWND_H +#define RAGNAROK_SOURCE_UI_SHORTCUTS_UISHORTCUTWND_H -#include "UI/ShortcutControls.h" -#include "UI/ShortcutGrid.h" -#include "UI/UIFrameWnd.h" +#include "UI/Shortcuts/ShortcutControls.h" +#include "UI/Shortcuts/ShortcutGrid.h" +#include "UI/Window/UIFrameWnd.h" struct ShortcutBindings; struct ShortcutPainting; @@ -42,7 +42,6 @@ struct ShortcutWindowContext { const int& cursorY; }; -// RTTI UIShortCutWnd, 396-byte x86 value. class UIShortCutWnd : public UIFrameWnd { public: UIShortCutWnd(UIWindowContext& windows, UIFrameContext& frames, ShortcutWindowContext& shortcuts); @@ -61,14 +60,7 @@ public: void Slot28(int x, int y) override; void Slot31(int x, int y) override; void Slot32(int x, int y) override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; private: ShortcutControls m_controls; diff --git a/Source/UI/ColoredText.cpp b/Source/UI/Text/ColoredText.cpp similarity index 71% rename from Source/UI/ColoredText.cpp rename to Source/UI/Text/ColoredText.cpp index e1c2ebb..6e6e93a 100644 --- a/Source/UI/ColoredText.cpp +++ b/Source/UI/Text/ColoredText.cpp @@ -1,15 +1,13 @@ -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "UI/ColoredText.h" -#include "UI/UIWindow.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "UI/Text/ColoredText.h" +#include "UI/Window/UIWindow.h" -#include #include #include #include namespace { - bool Hex(unsigned char value) { return (value >= '0' && value <= '9') || (value >= 'a' && value <= 'f') || (value >= 'A' && value <= 'F'); } @@ -56,28 +54,13 @@ namespace { return current; } - - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - } // OFFSET: 0x00A84E30 // FUNCTION: fn_17015 void DrawColoredText( - UIWindow& window, - FontCache& fonts, - const TextLocale& locale, - unsigned short codePage, - int x, - int y, - const char* text, - unsigned bytes, - std::uint32_t& color, - int family, - int height, - bool shadow + UIWindow& window, FontCache& fonts, const TextLocale& locale, unsigned short codePage, int x, int y, const char* text, unsigned bytes, std::uint32_t& color, + int family, int height, bool shadow ) { if (bytes == 0) { bytes = static_cast(std::strlen(text)); @@ -110,12 +93,12 @@ void DrawColoredText( if (next != current) { if (shadow) { context.SetColor(0); - context.Draw(Add(x, 1), Add(y, 1), segment.c_str(), static_cast(segment.size())); + context.Draw((x + 1), (y + 1), segment.c_str(), static_cast(segment.size())); } context.SetColor(color); context.Draw(x, y, segment.c_str(), static_cast(segment.size())); - x = Add(x, context.Measure(current, static_cast(next - current)).cx); + x = (x + context.Measure(current, static_cast(next - current)).cx); } current = next; @@ -129,19 +112,8 @@ void DrawColoredText( // OFFSET: 0x00A85720 // FUNCTION: fn_17016 void DrawOutlinedText( - UIWindow& window, - FontCache& fonts, - const TextLocale& locale, - int x, - int y, - const char* text, - unsigned bytes, - std::uint32_t color, - std::uint32_t outline, - int family, - int height, - unsigned char bold, - unsigned char italic + UIWindow& window, FontCache& fonts, const TextLocale& locale, int x, int y, const char* text, unsigned bytes, std::uint32_t color, std::uint32_t outline, + int family, int height, unsigned char bold, unsigned char italic ) { if (bytes == 0) { bytes = static_cast(std::strlen(text)); @@ -155,10 +127,10 @@ void DrawOutlinedText( } context.SetColor(outline); - context.Draw(Add(x, -1), y, text, bytes); - context.Draw(Add(x, 1), y, text, bytes); - context.Draw(x, Add(y, -1), text, bytes); - context.Draw(x, Add(y, 1), text, bytes); + context.Draw((x - 1), y, text, bytes); + context.Draw((x + 1), y, text, bytes); + context.Draw(x, (y - 1), text, bytes); + context.Draw(x, (y + 1), text, bytes); context.SetColor(color); context.Draw(x, y, text, bytes); @@ -170,19 +142,8 @@ void DrawOutlinedText( // OFFSET: 0x00A848B0 // FUNCTION: fn_17013 void DrawOutlinedColoredText( - UIWindow& window, - FontCache& fonts, - const TextLocale& locale, - unsigned short codePage, - int x, - int y, - const char* text, - unsigned bytes, - std::uint32_t& color, - std::uint32_t outline, - int family, - int height, - unsigned char bold + UIWindow& window, FontCache& fonts, const TextLocale& locale, unsigned short codePage, int x, int y, const char* text, unsigned bytes, std::uint32_t& color, + std::uint32_t outline, int family, int height, unsigned char bold ) { if (bytes == 0) { bytes = static_cast(std::strlen(text)); @@ -211,13 +172,13 @@ void DrawOutlinedColoredText( if (next != current) { const int length = static_cast(segment.size()); context.SetColor(outline); - context.Draw(Add(x, -1), y, segment.c_str(), length); - context.Draw(Add(x, 1), y, segment.c_str(), length); - context.Draw(x, Add(y, -1), segment.c_str(), length); - context.Draw(x, Add(y, 1), segment.c_str(), length); + context.Draw((x - 1), y, segment.c_str(), length); + context.Draw((x + 1), y, segment.c_str(), length); + context.Draw(x, (y - 1), segment.c_str(), length); + context.Draw(x, (y + 1), segment.c_str(), length); context.SetColor(color); context.Draw(x, y, segment.c_str(), length); - x = Add(x, context.Measure(current, static_cast(next - current)).cx); + x = (x + context.Measure(current, static_cast(next - current)).cx); } current = next; diff --git a/Source/UI/Text/ColoredText.h b/Source/UI/Text/ColoredText.h new file mode 100644 index 0000000..52b76c9 --- /dev/null +++ b/Source/UI/Text/ColoredText.h @@ -0,0 +1,24 @@ +#ifndef RAGNAROK_SOURCE_UI_TEXT_COLOREDTEXT_H +#define RAGNAROK_SOURCE_UI_TEXT_COLOREDTEXT_H + +#include + +class UIWindow; +class FontCache; +struct TextLocale; + +void DrawColoredText( + UIWindow& window, FontCache& fonts, const TextLocale& locale, unsigned short codePage, int x, int y, const char* text, unsigned bytes, std::uint32_t& color, + int family, int height, bool shadow +); + +void DrawOutlinedText( + UIWindow& window, FontCache& fonts, const TextLocale& locale, int x, int y, const char* text, unsigned bytes, std::uint32_t color, std::uint32_t outline, + int family, int height, unsigned char bold, unsigned char italic +); +void DrawOutlinedColoredText( + UIWindow& window, FontCache& fonts, const TextLocale& locale, unsigned short codePage, int x, int y, const char* text, unsigned bytes, std::uint32_t& color, + std::uint32_t outline, int family, int height, unsigned char bold +); + +#endif diff --git a/Source/UI/ItemLinkDisplay.cpp b/Source/UI/Text/ItemLinkDisplay.cpp similarity index 90% rename from Source/UI/ItemLinkDisplay.cpp rename to Source/UI/Text/ItemLinkDisplay.cpp index 33755cd..3990fb5 100644 --- a/Source/UI/ItemLinkDisplay.cpp +++ b/Source/UI/Text/ItemLinkDisplay.cpp @@ -1,9 +1,9 @@ -#include "Contents/ItemInfo.h" -#include "Contents/ItemLink.h" -#include "Contents/ItemNaming.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/Items/ItemLink.h" +#include "Contents/Items/ItemNaming.h" #include "Contents/TipBoxTitles.h" -#include "UI/ItemLinkDisplay.h" -#include "UI/TextFitting.h" +#include "UI/Text/ItemLinkDisplay.h" +#include "UI/Text/TextFitting.h" #include @@ -92,9 +92,7 @@ bool ItemLinkDisplay::Next(std::string& remaining, std::string& encoded, unsigne // OFFSET: 0x00879390 // FUNCTION: fn_11216 std::string ItemLinkDisplay::Convert(const std::string& text) { - if (!_mbsstr( - reinterpret_cast(text.c_str()), reinterpret_cast("") - )) { + if (!_mbsstr(reinterpret_cast(text.c_str()), reinterpret_cast(""))) { return text; } diff --git a/Source/UI/ItemLinkDisplay.h b/Source/UI/Text/ItemLinkDisplay.h similarity index 83% rename from Source/UI/ItemLinkDisplay.h rename to Source/UI/Text/ItemLinkDisplay.h index 6ee2d93..5f27f19 100644 --- a/Source/UI/ItemLinkDisplay.h +++ b/Source/UI/Text/ItemLinkDisplay.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_ITEMLINKDISPLAY_H -#define RAGNAROK_SOURCE_UI_ITEMLINKDISPLAY_H +#ifndef RAGNAROK_SOURCE_UI_TEXT_ITEMLINKDISPLAY_H +#define RAGNAROK_SOURCE_UI_TEXT_ITEMLINKDISPLAY_H #include diff --git a/Source/UI/NavigationLink.cpp b/Source/UI/Text/NavigationLink.cpp similarity index 94% rename from Source/UI/NavigationLink.cpp rename to Source/UI/Text/NavigationLink.cpp index 73535c0..b28f8bb 100644 --- a/Source/UI/NavigationLink.cpp +++ b/Source/UI/Text/NavigationLink.cpp @@ -1,6 +1,5 @@ -#include "UI/NavigationLink.h" +#include "UI/Text/NavigationLink.h" -#include #include #include #include @@ -28,7 +27,7 @@ int DecodeNavigationNumber(std::string value) { result += static_cast(digit - digits) * place; } - return std::bit_cast(result); + return static_cast(result); } // OFFSET: 0x00835890 @@ -40,7 +39,6 @@ bool ParseNavigationLink(std::string value, std::string& name, int& x, int& y) { return true; } - // Original substr throws when the closing tag precedes four coordinate bytes. const auto coordinates = end - 4; const std::string tail = value.substr(coordinates); x = DecodeNavigationNumber(tail.substr(0, 2)); diff --git a/Source/UI/NavigationLink.h b/Source/UI/Text/NavigationLink.h similarity index 78% rename from Source/UI/NavigationLink.h rename to Source/UI/Text/NavigationLink.h index c41ca44..ceab1a7 100644 --- a/Source/UI/NavigationLink.h +++ b/Source/UI/Text/NavigationLink.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_NAVIGATIONLINK_H -#define RAGNAROK_SOURCE_UI_NAVIGATIONLINK_H +#ifndef RAGNAROK_SOURCE_UI_TEXT_NAVIGATIONLINK_H +#define RAGNAROK_SOURCE_UI_TEXT_NAVIGATIONLINK_H #include diff --git a/Source/UI/PixelTextWrapping.cpp b/Source/UI/Text/PixelTextWrapping.cpp similarity index 69% rename from Source/UI/PixelTextWrapping.cpp rename to Source/UI/Text/PixelTextWrapping.cpp index f8cfecd..8ad459d 100644 --- a/Source/UI/PixelTextWrapping.cpp +++ b/Source/UI/Text/PixelTextWrapping.cpp @@ -1,15 +1,10 @@ -#include "Render/TextContext.h" -#include "UI/PixelTextWrapping.h" +#include "Render/Text/TextContext.h" +#include "UI/Text/PixelTextWrapping.h" -#include #include #include namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - unsigned Digit(unsigned char value) { if (value >= '0' && value <= '9') { return value - '0'; @@ -30,19 +25,12 @@ namespace { // OFFSET: 0x00A82310 // FUNCTION: fn_16993 void WrapPixelText( - CDC& surface, - FontCache& fonts, - const TextLocale& locale, - unsigned short codePage, - const char* text, - std::vector& lines, - int width + CDC& surface, FontCache& fonts, const TextLocale& locale, unsigned short codePage, const char* text, std::vector& lines, int width ) { if (!text || *text == '\0') { return; } - // Each original measurement constructs its own scoped text context. const auto measure = [&](const char* part, int bytes) { if (bytes == 0) { bytes = static_cast(std::strlen(part)); @@ -85,8 +73,9 @@ void WrapPixelText( const int previous = count; const char* next = CharNextExA(codePage, current, 0); const int length = static_cast(next - current); - extent = Add(extent, measure(current, length)); - count = Add(count, length); + + extent = (extent + measure(current, length)); + count = (count + length); if (length == 1 && (*current == '\r' || *current == '\n')) { measure("\n", 1); @@ -100,27 +89,23 @@ void WrapPixelText( } if (*current == '^') { - const unsigned color = (Digit(current[2]) + 16 * Digit(current[1])) | - ((Digit(current[4]) + 16 * Digit(current[3])) << 8) | + const unsigned color = (Digit(current[2]) + 16 * Digit(current[1])) | ((Digit(current[4]) + 16 * Digit(current[3])) << 8) | ((Digit(current[6]) + 16 * Digit(current[5])) << 16); if (color != 0 || std::strncmp(current, "^000000", 7) == 0) { - // The original visits each byte; it subtracts the seven-byte color - // marker's width here rather than advancing over the marker. - extent = Add(extent, -measure("^000000", 7)); + extent = (extent - measure("^000000", 7)); } } if (*current == '[') { - const auto* close = - _mbsstr(reinterpret_cast(current), reinterpret_cast("]")); + const auto* close = _mbsstr(reinterpret_cast(current), reinterpret_cast("]")); if (close) { const int bracketBytes = static_cast(reinterpret_cast(close) - current) + 1; const int bracketWidth = measure(current, bracketBytes); const int characterWidth = measure(current, length); - if (Add(Add(extent, bracketWidth), -characterWidth) > width && bracketWidth <= width) { + if (((extent + bracketWidth) - characterWidth) > width && bracketWidth <= width) { count = previous; break; } @@ -136,7 +121,6 @@ void WrapPixelText( } if (count <= 0) { - // Original retries the same byte until its row guard expires. continue; } @@ -150,6 +134,6 @@ void WrapPixelText( lines.push_back(std::move(line)); } - offset = Add(offset, count); + offset = (offset + count); } } diff --git a/Source/UI/Text/PixelTextWrapping.h b/Source/UI/Text/PixelTextWrapping.h new file mode 100644 index 0000000..acc9406 --- /dev/null +++ b/Source/UI/Text/PixelTextWrapping.h @@ -0,0 +1,15 @@ +#ifndef RAGNAROK_SOURCE_UI_TEXT_PIXELTEXTWRAPPING_H +#define RAGNAROK_SOURCE_UI_TEXT_PIXELTEXTWRAPPING_H + +#include +#include + +class CDC; +class FontCache; +struct TextLocale; + +void WrapPixelText( + CDC& surface, FontCache& fonts, const TextLocale& locale, unsigned short codePage, const char* text, std::vector& lines, int width +); + +#endif diff --git a/Source/UI/TextFitting.cpp b/Source/UI/Text/TextFitting.cpp similarity index 88% rename from Source/UI/TextFitting.cpp rename to Source/UI/Text/TextFitting.cpp index 4c102fe..ad50e6f 100644 --- a/Source/UI/TextFitting.cpp +++ b/Source/UI/Text/TextFitting.cpp @@ -1,5 +1,5 @@ -#include "Render/TextContext.h" -#include "UI/TextFitting.h" +#include "Render/Text/TextContext.h" +#include "UI/Text/TextFitting.h" #include #include @@ -22,7 +22,7 @@ std::string FitText(CDC& surface, FontCache& fonts, const TextLocale& locale, st } std::size_t length = remaining.size() - 1; - // Original checks the low bytes of adjacent UTF-16 units, not surrogates. + if ((remaining[remaining.size() - 2] & 0x80) != 0 && (remaining[remaining.size() - 1] & 0x80) != 0) { --length; } diff --git a/Source/UI/TextFitting.h b/Source/UI/Text/TextFitting.h similarity index 66% rename from Source/UI/TextFitting.h rename to Source/UI/Text/TextFitting.h index b8e2734..efad9b0 100644 --- a/Source/UI/TextFitting.h +++ b/Source/UI/Text/TextFitting.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_TEXTFITTING_H -#define RAGNAROK_SOURCE_UI_TEXTFITTING_H +#ifndef RAGNAROK_SOURCE_UI_TEXT_TEXTFITTING_H +#define RAGNAROK_SOURCE_UI_TEXT_TEXTFITTING_H #include diff --git a/Source/UI/TextMarkup.cpp b/Source/UI/Text/TextMarkup.cpp similarity index 89% rename from Source/UI/TextMarkup.cpp rename to Source/UI/Text/TextMarkup.cpp index 4f08d92..4e8749f 100644 --- a/Source/UI/TextMarkup.cpp +++ b/Source/UI/Text/TextMarkup.cpp @@ -1,4 +1,4 @@ -#include "UI/TextMarkup.h" +#include "UI/Text/TextMarkup.h" #include @@ -25,9 +25,8 @@ namespace { // OFFSET: 0x00A81A70 // FUNCTION: fn_16980 bool HasTextLinks(const std::string& text) { - return text.find("") != std::string::npos || text.find("") != std::string::npos || - text.find("") != std::string::npos || text.find("") != std::string::npos || - text.find("") != std::string::npos || text.find("") != std::string::npos; + return text.find("") != std::string::npos || text.find("") != std::string::npos || text.find("") != std::string::npos || + text.find("") != std::string::npos || text.find("") != std::string::npos || text.find("") != std::string::npos; } // OFFSET: 0x008791E0 @@ -96,8 +95,6 @@ std::string DisplayTextTag(std::string text, const std::string& begin, const std const auto close = tail.find(end); if (close == std::string::npos) { - // The original keeps the unconsumed text, including the opening tag, - // but appends the prefix again on its way to the next search. position = content; } else { result.append(tail, 0, close); @@ -140,12 +137,7 @@ std::string RemoveTextLinkInfo(std::string text) { // OFFSET: 0x00A7CAB0 // FUNCTION: fn_16950 -void ExtractTextLinks( - std::string text, - const std::string& begin, - const std::string& end, - std::vector& links -) { +void ExtractTextLinks(std::string text, const std::string& begin, const std::string& end, std::vector& links) { auto position = text.find(begin); if (position == std::string::npos) { diff --git a/Source/UI/TextMarkup.h b/Source/UI/Text/TextMarkup.h similarity index 78% rename from Source/UI/TextMarkup.h rename to Source/UI/Text/TextMarkup.h index 095728a..de81395 100644 --- a/Source/UI/TextMarkup.h +++ b/Source/UI/Text/TextMarkup.h @@ -1,13 +1,11 @@ -#ifndef RAGNAROK_SOURCE_UI_TEXTMARKUP_H -#define RAGNAROK_SOURCE_UI_TEXTMARKUP_H +#ifndef RAGNAROK_SOURCE_UI_TEXT_TEXTMARKUP_H +#define RAGNAROK_SOURCE_UI_TEXT_TEXTMARKUP_H #include #include #include #include -// Original link record is 60 bytes on x86. The two words after the byte -// position are not initialized by the extractor; do not infer meanings. struct TextLink { std::uint32_t position; std::byte unknown_0004[8]; diff --git a/Source/UI/TextWrapping.cpp b/Source/UI/Text/TextWrapping.cpp similarity index 86% rename from Source/UI/TextWrapping.cpp rename to Source/UI/Text/TextWrapping.cpp index bf4bbea..8a52be6 100644 --- a/Source/UI/TextWrapping.cpp +++ b/Source/UI/Text/TextWrapping.cpp @@ -1,7 +1,7 @@ -#include "Contents/ItemDescription.h" -#include "Contents/ItemInfo.h" -#include "Render/TextContext.h" -#include "UI/TextWrapping.h" +#include "Contents/Items/ItemDescription.h" +#include "Contents/Items/ItemInfo.h" +#include "Render/Text/TextContext.h" +#include "UI/Text/TextWrapping.h" #include #include @@ -13,13 +13,7 @@ // OFFSET: 0x009B4220 // FUNCTION: fn_13829 -void WrapPlainText( - const char* text, - std::vector& lines, - int width, - unsigned short codePage, - bool inlineCharset -) { +void WrapPlainText(const char* text, std::vector& lines, int width, unsigned short codePage, bool inlineCharset) { const char* begin = text; const char* chunk = text; const char* current = text; @@ -61,7 +55,6 @@ void WrapPlainText( } namespace { - bool Hex(unsigned char value) { return (value >= '0' && value <= '9') || (value >= 'a' && value <= 'f') || (value >= 'A' && value <= 'F'); } @@ -79,19 +72,12 @@ namespace { return true; } - } // OFFSET: 0x009B4730 // FUNCTION: fn_13833 void WrapRichText( - const char* text, - std::vector& lines, - int width, - bool carriageReturns, - unsigned short codePage, - bool inlineCharset, - ItemDescriptions& items + const char* text, std::vector& lines, int width, bool carriageReturns, unsigned short codePage, bool inlineCharset, ItemDescriptions& items ) { const char* begin = text; const char* current = text; @@ -170,10 +156,8 @@ void WrapRichText( } while (*current == '[') { - const unsigned char* bracket = - _mbsstr(reinterpret_cast(current), reinterpret_cast("]")); - const std::intptr_t extent = - reinterpret_cast(bracket) - reinterpret_cast(current) + 1; + const unsigned char* bracket = _mbsstr(reinterpret_cast(current), reinterpret_cast("]")); + const std::intptr_t extent = reinterpret_cast(bracket) - reinterpret_cast(current) + 1; if (reinterpret_cast(current) + extent < reinterpret_cast(limit)) { ++current; diff --git a/Source/UI/Text/TextWrapping.h b/Source/UI/Text/TextWrapping.h new file mode 100644 index 0000000..8394da1 --- /dev/null +++ b/Source/UI/Text/TextWrapping.h @@ -0,0 +1,15 @@ +#ifndef RAGNAROK_SOURCE_UI_TEXT_TEXTWRAPPING_H +#define RAGNAROK_SOURCE_UI_TEXT_TEXTWRAPPING_H + +#include +#include + +struct ItemDescriptions; + +void WrapPlainText(const char* text, std::vector& lines, int width, unsigned short codePage, bool inlineCharset); + +void WrapRichText( + const char* text, std::vector& lines, int width, bool carriageReturns, unsigned short codePage, bool inlineCharset, ItemDescriptions& items +); + +#endif diff --git a/Source/UI/UIBalloonText.cpp b/Source/UI/Text/UIBalloonText.cpp similarity index 71% rename from Source/UI/UIBalloonText.cpp rename to Source/UI/Text/UIBalloonText.cpp index 2f0fd2b..c256591 100644 --- a/Source/UI/UIBalloonText.cpp +++ b/Source/UI/Text/UIBalloonText.cpp @@ -1,17 +1,11 @@ -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "UI/TextWrapping.h" -#include "UI/UIBalloonText.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "UI/Text/TextWrapping.h" +#include "UI/Text/UIBalloonText.h" -#include #include namespace { - - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Family(unsigned mode) { switch (mode) { case 1: @@ -46,13 +40,11 @@ namespace { context.SetFont(family, height, 0, 0); return context.Measure(text.c_str(), static_cast(text.size())); } - } // OFFSET: 0x0084E970 UIBalloonText::UIBalloonText(UIWindowContext& windows, BalloonTextContext& text) - : UIWindow(windows, 0), unknown_007C(0), m_fontHeight(12), m_textColor(0xFFFFFF), m_outlineColor(0), m_richText(0), - m_textContext(&text) { + : UIWindow(windows, 0), unknown_007C(0), m_fontHeight(12), m_textColor(0xFFFFFF), m_outlineColor(0), m_richText(0), m_textContext(&text) { this->geometry.unknown_0034 = 0; } @@ -82,10 +74,7 @@ void UIBalloonText::SetText(const char* text, int width) { this->m_lines.clear(); if (this->m_richText != 0) { - WrapRichText( - text, this->m_lines, width, false, this->m_textContext->codePage, this->m_textContext->locale.inlineCharset, - this->m_textContext->items - ); + WrapRichText(text, this->m_lines, width, false, this->m_textContext->codePage, this->m_textContext->locale.inlineCharset, this->m_textContext->items); } else { WrapPlainText(text, this->m_lines, width, this->m_textContext->codePage, this->m_textContext->locale.inlineCharset); } @@ -109,12 +98,11 @@ void UIBalloonText::FitText() { width = extent.cx; } - const int lineHeight = - this->m_fontMode == 3 ? extent.cy : Measure(*this, *this->m_textContext, line, 0, this->m_fontHeight).cy; - height = Add(height, Add(lineHeight, 4)); + const int lineHeight = this->m_fontMode == 3 ? extent.cy : Measure(*this, *this->m_textContext, line, 0, this->m_fontHeight).cy; + height = (height + (lineHeight + 4)); } - this->Resize(Add(width, 12), height); + this->Resize((width + 12), height); this->Invalidate(); } @@ -128,12 +116,9 @@ void UIBalloonText::Paint() { int y = 4; for (const std::string& line : this->m_lines) { - this->DrawTextAt( - this->m_textContext->fonts, this->m_textContext->locale, 6, y, line.c_str(), 0, 0, this->m_fontHeight, - this->m_textColor, 0, 0 - ); + this->DrawTextAt(this->m_textContext->fonts, this->m_textContext->locale, 6, y, line.c_str(), 0, 0, this->m_fontHeight, this->m_textColor, 0, 0); const int height = Measure(*this, *this->m_textContext, line, 0, this->m_fontHeight).cy; - y = Add(y, Add(height, 4)); + y = (y + (height + 4)); } } diff --git a/Source/UI/UIBalloonText.h b/Source/UI/Text/UIBalloonText.h similarity index 86% rename from Source/UI/UIBalloonText.h rename to Source/UI/Text/UIBalloonText.h index e82a12b..3a65c3d 100644 --- a/Source/UI/UIBalloonText.h +++ b/Source/UI/Text/UIBalloonText.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UIBALLOONTEXT_H -#define RAGNAROK_SOURCE_UI_UIBALLOONTEXT_H +#ifndef RAGNAROK_SOURCE_UI_TEXT_UIBALLOONTEXT_H +#define RAGNAROK_SOURCE_UI_TEXT_UIBALLOONTEXT_H -#include "UI/UIWindow.h" +#include "UI/Window/UIWindow.h" #include #include @@ -17,7 +17,6 @@ struct BalloonTextContext { ItemDescriptions& items; }; -// RTTI UIBalloonText, 160-byte x86 object. class UIBalloonText : public UIWindow { public: UIBalloonText(UIWindowContext& windows, BalloonTextContext& text); diff --git a/Source/UI/UIStaticText.cpp b/Source/UI/Text/UIStaticText.cpp similarity index 61% rename from Source/UI/UIStaticText.cpp rename to Source/UI/Text/UIStaticText.cpp index 813d196..1dea800 100644 --- a/Source/UI/UIStaticText.cpp +++ b/Source/UI/Text/UIStaticText.cpp @@ -1,21 +1,12 @@ -#include "Render/DeviceContext.h" -#include "UI/UIButton.h" -#include "UI/UIStaticText.h" - -#include - -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } -} +#include "Render/DeviceContext/DeviceContext.h" +#include "UI/Buttons/UIButton.h" +#include "UI/Text/UIStaticText.h" // OFFSET: 0x00850550 // FUNCTION: fn_10678 UIStaticText::UIStaticText(UIWindowContext& windows, UIButtonContext& controls) - : UIWindow(windows, 0), red(0), green(0), blue(0), shadow(0), outline(0), background(0xFFFF00FFu), - outlineColor(0x969696), fontHeight(12), fontFamily(0), bold(0), italic(0), tooltipEnabled(0), - m_controls(&controls) { + : UIWindow(windows, 0), red(0), green(0), blue(0), shadow(0), outline(0), background(0xFFFF00FFu), outlineColor(0x969696), fontHeight(12), fontFamily(0), + bold(0), italic(0), tooltipEnabled(0), m_controls(&controls) { } // OFFSET: 0x00853050 @@ -38,8 +29,7 @@ void UIStaticText::Paint() { this->FillRegion(0, 0, this->geometry.width, this->geometry.height, this->background); const auto draw = [&](int x, int y, std::uint32_t color, unsigned char boldValue, unsigned char italicValue) { this->DrawTextAt( - this->m_controls->fonts, this->m_controls->locale, x, y, this->text.c_str(), 0, this->fontFamily, - this->fontHeight, color, boldValue, italicValue + this->m_controls->fonts, this->m_controls->locale, x, y, this->text.c_str(), 0, this->fontFamily, this->fontHeight, color, boldValue, italicValue ); }; @@ -53,28 +43,28 @@ void UIStaticText::Paint() { draw(0, 1, this->outlineColor, 0, 0); } - const unsigned color = static_cast(this->red) | (static_cast(this->green) << 8) | - (static_cast(this->blue) << 16); + const unsigned color = + static_cast(this->red) | (static_cast(this->green) << 8) | (static_cast(this->blue) << 16); draw(0, 0, color, this->bold, this->italic); } // OFFSET: 0x0085EE40 // FUNCTION: fn_10850 void UIStaticText::Slot25(int x, int y) { - static_cast(this->parent)->Slot25(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot25((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085EA60 // FUNCTION: fn_10837 void UIStaticText::Slot26(int x, int y) { - static_cast(this->parent)->Slot26(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot26((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085F8D0 // FUNCTION: fn_10873 void UIStaticText::Slot27(int x, int y) { this->Slot28(x, y); - static_cast(this->parent)->Slot27(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot27((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085F580 @@ -88,8 +78,8 @@ void UIStaticText::Slot28(int, int) { int y = -4; for (const UIWindow* node = this; node; node = static_cast(node->parent)) { - x = Add(x, node->geometry.x); - y = Add(y, node->geometry.y); + x = (x + node->geometry.x); + y = (y + node->geometry.y); } this->m_controls->services.Tooltip(this->tooltip.c_str(), x, y, -1, false, true); @@ -98,25 +88,25 @@ void UIStaticText::Slot28(int, int) { // OFFSET: 0x0085FAB0 // FUNCTION: fn_10881 void UIStaticText::ResetCursor(int x, int y) { - static_cast(this->parent)->ResetCursor(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->ResetCursor((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085F030 // FUNCTION: fn_10855 void UIStaticText::Slot31(int x, int y) { - static_cast(this->parent)->Slot31(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot31((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085FED0 // FUNCTION: fn_10889 void UIStaticText::Slot32(int x, int y) { - static_cast(this->parent)->Slot32(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot32((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085FF30 // FUNCTION: fn_10891 void UIStaticText::Slot33(int x, int y) { - static_cast(this->parent)->Slot33(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot33((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x00860020 diff --git a/Source/UI/UIStaticText.h b/Source/UI/Text/UIStaticText.h similarity index 88% rename from Source/UI/UIStaticText.h rename to Source/UI/Text/UIStaticText.h index 4ecd137..4fa56bb 100644 --- a/Source/UI/UIStaticText.h +++ b/Source/UI/Text/UIStaticText.h @@ -1,13 +1,12 @@ -#ifndef RAGNAROK_SOURCE_UI_UISTATICTEXT_H -#define RAGNAROK_SOURCE_UI_UISTATICTEXT_H +#ifndef RAGNAROK_SOURCE_UI_TEXT_UISTATICTEXT_H +#define RAGNAROK_SOURCE_UI_TEXT_UISTATICTEXT_H -#include "UI/UIWindow.h" +#include "UI/Window/UIWindow.h" #include struct UIButtonContext; -// RTTI UIStaticText. Original x86 size 216. class UIStaticText : public UIWindow { public: UIStaticText(UIWindowContext& windows, UIButtonContext& controls); diff --git a/Source/UI/UITextViewer.cpp b/Source/UI/Text/UITextViewer.cpp similarity index 81% rename from Source/UI/UITextViewer.cpp rename to Source/UI/Text/UITextViewer.cpp index 83211f8..e8afd35 100644 --- a/Source/UI/UITextViewer.cpp +++ b/Source/UI/Text/UITextViewer.cpp @@ -1,22 +1,17 @@ -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "Resource/BitmapResource.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/ColoredText.h" -#include "UI/ItemLinkDisplay.h" -#include "UI/TextMarkup.h" -#include "UI/UIScrollBar.h" -#include "UI/UITextButton.h" -#include "UI/UITextViewer.h" +#include "UI/Text/ColoredText.h" +#include "UI/Text/ItemLinkDisplay.h" +#include "UI/Text/TextMarkup.h" +#include "UI/Lists/UIScrollBar.h" +#include "UI/Buttons/UITextButton.h" +#include "UI/Text/UITextViewer.h" #include -#include namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - unsigned Digit(unsigned char value) { if (value >= '0' && value <= '9') { return value - '0'; @@ -67,7 +62,7 @@ UITextViewer::UITextViewer(UIWindowContext& windows, UITextViewerContext& text) const std::uint32_t pixel = image.width > 18 && image.height > 2 ? image.pixels[18 + 2 * image.width] : 0x00FF0000u; this->backgroundColor = 0xFF000000u | ((pixel & 255) << 16) | (pixel & 0xFF00) | ((pixel >> 16) & 255); this->Invalidate(); - // Only the low byte of original +0xBC is initialized by this constructor. + this->unknown_00BC = 0; } @@ -132,13 +127,13 @@ void UITextViewer::Paint() { static_cast(this->parent)->Invalidate(); } - int divisor = Add(this->lineHeight, -this->bottomMargin); + int divisor = (this->lineHeight - this->bottomMargin); if (divisor == 0) { divisor = 1; } - const int limit = Add(this->geometry.height / divisor, this->topLine); + const int limit = (this->geometry.height / divisor + this->topLine); const int end = static_cast(std::min(static_cast(this->lines.size()), static_cast(limit))); auto& owner = this->m_text->list; std::uint32_t color = 0; @@ -149,17 +144,13 @@ void UITextViewer::Paint() { for (int index = this->topLine; index < end; ++index) { const auto& line = this->lines[index]; - const int y = - Add(static_cast(static_cast(index - this->topLine) * static_cast(this->lineHeight)), 4); + const int y = (index - this->topLine) * this->lineHeight + 4; const auto bytes = static_cast(line.size()); if ((this->unknown_00BC & 255) != 0) { DrawOutlinedText(*this, owner.fonts, owner.locale, 3, y, line.c_str(), bytes, 0, 0xFFFFFF, 0, 12, 0, 0); } else if (this->outline != 0) { - DrawOutlinedColoredText( - *this, owner.fonts, owner.locale, owner.codePage, 3, y, line.c_str(), bytes, color, this->backgroundColor, 0, - 12, this->bold - ); + DrawOutlinedColoredText(*this, owner.fonts, owner.locale, owner.codePage, 3, y, line.c_str(), bytes, color, this->backgroundColor, 0, 12, this->bold); } else { DrawColoredText(*this, owner.fonts, owner.locale, owner.codePage, 3, y, line.c_str(), bytes, color, 0, 12, false); } diff --git a/Source/UI/UITextViewer.h b/Source/UI/Text/UITextViewer.h similarity index 76% rename from Source/UI/UITextViewer.h rename to Source/UI/Text/UITextViewer.h index f216488..2c0d466 100644 --- a/Source/UI/UITextViewer.h +++ b/Source/UI/Text/UITextViewer.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UITEXTVIEWER_H -#define RAGNAROK_SOURCE_UI_UITEXTVIEWER_H +#ifndef RAGNAROK_SOURCE_UI_TEXT_UITEXTVIEWER_H +#define RAGNAROK_SOURCE_UI_TEXT_UITEXTVIEWER_H -#include "UI/UIListBox.h" +#include "UI/Lists/UIListBox.h" #include @@ -11,8 +11,6 @@ struct ItemNaming; struct TipBoxTitles; struct ItemLinkDisplay; -// Original navigation, tip-window and active-mode operations. Their owners -// must supply real behavior; the viewer does not manufacture success. class TextViewerActions { public: virtual void Navigate(std::string map, int type, unsigned char flags, bool option, int x, int y, int target) = 0; @@ -31,12 +29,10 @@ struct UITextViewerContext { const TipBoxTitles& tips; TextViewerActions& actions; HWND& applicationWindow; - // Optional actual chat owner conversion list; order and repeated first - // Element are deliberate. + const std::vector* const& chatConversions; }; -// RTTI UITextViewer, original x86 size 236. class UITextViewer : public UIListBox { public: UITextViewer(UIWindowContext& windows, UITextViewerContext& text); @@ -49,14 +45,7 @@ public: void Configure(int x, int y, int width, int height, unsigned char transparent) override; void AddLine(const char* text) override; void Clear() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t argument1, - std::intptr_t argument2, - std::intptr_t argument3, - std::intptr_t argument4 - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) override; /* 00D4 */ std::vector links; /* 00E0 */ std::uint32_t backgroundColor; diff --git a/Source/UI/UITextViewerLinks.cpp b/Source/UI/Text/UITextViewerLinks.cpp similarity index 90% rename from Source/UI/UITextViewerLinks.cpp rename to Source/UI/Text/UITextViewerLinks.cpp index 05425fe..5ffc020 100644 --- a/Source/UI/UITextViewerLinks.cpp +++ b/Source/UI/Text/UITextViewerLinks.cpp @@ -1,13 +1,13 @@ -#include "Contents/ItemNaming.h" -#include "Render/TextContext.h" -#include "UI/ItemLinkDisplay.h" -#include "UI/NavigationLink.h" -#include "UI/PixelTextWrapping.h" -#include "UI/TextMarkup.h" -#include "UI/TextWrapping.h" -#include "UI/UIScrollBar.h" -#include "UI/UITextButton.h" -#include "UI/UITextViewer.h" +#include "Contents/Items/ItemNaming.h" +#include "Render/Text/TextContext.h" +#include "UI/Text/ItemLinkDisplay.h" +#include "UI/Text/NavigationLink.h" +#include "UI/Text/PixelTextWrapping.h" +#include "UI/Text/TextMarkup.h" +#include "UI/Text/TextWrapping.h" +#include "UI/Lists/UIScrollBar.h" +#include "UI/Buttons/UITextButton.h" +#include "UI/Text/UITextViewer.h" #include @@ -107,8 +107,6 @@ void UITextViewer::AddLinks(const char* text, unsigned addedLines, int kind) { std::vector labels; if (kind == 3 && this->splitTipLinks == 1) { - // Original first fragment gets the remaining byte budget of a 32-byte - // row; subsequent fragments use 32, retaining its space/newline rules. const char* begin = link.display.c_str(); const char* current = begin; const char* end = begin + link.display.size(); @@ -208,14 +206,10 @@ void UITextViewer::AppendText(char* text, int width, bool carriageReturns, bool if (pixels) { const int scrollWidth = carriageReturns ? this->verticalBar->geometry.width + 2 : 0; - WrapPixelText( - *this->geometry.surface, owner.fonts, owner.locale, owner.codePage, display.c_str(), wrapped, - this->geometry.width - scrollWidth - 4 - ); + WrapPixelText(*this->geometry.surface, owner.fonts, owner.locale, owner.codePage, display.c_str(), wrapped, this->geometry.width - scrollWidth - 4); } else { WrapRichText( - display.c_str(), wrapped, width == 0 ? 35 : width, carriageReturns, owner.codePage, owner.locale.inlineCharset, - this->m_text->items.descriptions + display.c_str(), wrapped, width == 0 ? 35 : width, carriageReturns, owner.codePage, owner.locale.inlineCharset, this->m_text->items.descriptions ); } diff --git a/Source/UI/UITextViewerMessages.cpp b/Source/UI/Text/UITextViewerMessages.cpp similarity index 77% rename from Source/UI/UITextViewerMessages.cpp rename to Source/UI/Text/UITextViewerMessages.cpp index 679f688..2803b76 100644 --- a/Source/UI/UITextViewerMessages.cpp +++ b/Source/UI/Text/UITextViewerMessages.cpp @@ -1,8 +1,8 @@ -#include "Contents/ItemInfo.h" -#include "UI/UIScrollBar.h" -#include "UI/UITextButton.h" -#include "UI/UITextViewer.h" -#include "UI/WindowManagerWindows.h" +#include "Contents/Items/ItemInfo.h" +#include "UI/Lists/UIScrollBar.h" +#include "UI/Buttons/UITextButton.h" +#include "UI/Text/UITextViewer.h" +#include "UI/Window/WindowManagerWindows.h" #include #include @@ -102,14 +102,7 @@ void UITextViewer::Activate(UITextButton* button, int id) { // OFFSET: 0x00899E90 // FUNCTION: fn_11562 -int UITextViewer::SendMsg( - UIWindow* sender, - int message, - std::intptr_t argument1, - std::intptr_t argument2, - std::intptr_t argument3, - std::intptr_t argument4 -) { +int UITextViewer::SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) { switch (message) { case 7: case 8: @@ -126,26 +119,18 @@ int UITextViewer::SendMsg( } const int row = button->m_value; - const int limit = static_cast( - static_cast(this->topLine) + static_cast(this->geometry.height / this->lineHeight) - - static_cast(this->bottomMargin) - ); + const int limit = this->topLine + this->geometry.height / this->lineHeight - this->bottomMargin; if (row < this->topLine || row >= limit) { button->Enable(0); } else { button->Enable(1); - const int x = std::bit_cast( - static_cast(previousX) + static_cast(button->geometry.x) - - static_cast(this->horizontalOffset) - ); - const int y = - std::bit_cast(static_cast(this->lineHeight) * static_cast(row - this->topLine) + 3u); + const int x = previousX + button->geometry.x - this->horizontalOffset; + const int y = this->lineHeight * (row - this->topLine) + 3; button->Move(x, y); } } - // Unlike UIListBox, this override discards the actual scroll delta. return 0; } case 18: diff --git a/Source/UI/UITransBalloonText.cpp b/Source/UI/Text/UITransBalloonText.cpp similarity index 77% rename from Source/UI/UITransBalloonText.cpp rename to Source/UI/Text/UITransBalloonText.cpp index 12df692..3eb86fa 100644 --- a/Source/UI/UITransBalloonText.cpp +++ b/Source/UI/Text/UITransBalloonText.cpp @@ -1,18 +1,12 @@ -#include "Render/DeviceContext.h" -#include "Render/TextContext.h" -#include "UI/ColoredText.h" -#include "UI/UITransBalloonText.h" -#include "UI/WindowBorder.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Render/Text/TextContext.h" +#include "UI/Text/ColoredText.h" +#include "UI/Text/UITransBalloonText.h" +#include "UI/Window/WindowBorder.h" -#include #include namespace { - - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Family(unsigned mode) { switch (mode) { case 1: @@ -37,12 +31,10 @@ namespace { return 0; } } - } // OFFSET: 0x00850810 -UITransBalloonText::UITransBalloonText(UIWindowContext& windows, BalloonTextContext& text) - : UIBalloonText(windows, text), m_borderColor(6052956) { +UITransBalloonText::UITransBalloonText(UIWindowContext& windows, BalloonTextContext& text) : UIBalloonText(windows, text), m_borderColor(6052956) { } // OFFSET: 0x00853210 @@ -75,9 +67,7 @@ bool UITransBalloonText::Slot07(void* output) { // OFFSET: 0x0085AFB0 // FUNCTION: fn_10790 void UITransBalloonText::Slot15(int, int) { - this->m_rectangle = { - this->geometry.x, this->geometry.y, this->geometry.width, this->geometry.height, 0, 1711276032u, 0 - }; + this->m_rectangle = {this->geometry.x, this->geometry.y, this->geometry.width, this->geometry.height, 0, 1711276032u, 0}; this->m_fontMode = 0; } @@ -110,20 +100,17 @@ void UITransBalloonText::Paint() { for (std::size_t index = 0; index < this->m_lines.size(); ++index) { const std::string& line = this->m_lines[index]; - std::uint32_t color = index < this->m_lineColors.size() && this->m_lineColors[index] != 0 - ? this->m_lineColors[index] - : this->m_textColor; + std::uint32_t color = index < this->m_lineColors.size() && this->m_lineColors[index] != 0 ? this->m_lineColors[index] : this->m_textColor; if (this->m_richText != 0) { DrawColoredText( - *this, this->m_textContext->fonts, this->m_textContext->locale, this->m_textContext->codePage, 6, y, - line.c_str(), 0, color, family, height, true + *this, this->m_textContext->fonts, this->m_textContext->locale, this->m_textContext->codePage, 6, y, line.c_str(), 0, color, family, height, true ); } else { TextContext context(*this->geometry.surface, this->m_textContext->fonts, this->m_textContext->locale); context.SetFont(family, height, 0, 0); context.SetColor(this->m_outlineColor); - context.Draw(7, Add(y, 1), line.c_str(), static_cast(line.size())); + context.Draw(7, (y + 1), line.c_str(), static_cast(line.size())); context.SetColor(color); context.Draw(6, y, line.c_str(), static_cast(line.size())); } @@ -136,6 +123,6 @@ void UITransBalloonText::Paint() { lineHeight = context.Measure(line.c_str(), static_cast(line.size())).cy; } - y = Add(y, Add(lineHeight, 4)); + y = (y + (lineHeight + 4)); } } diff --git a/Source/UI/UITransBalloonText.h b/Source/UI/Text/UITransBalloonText.h similarity index 78% rename from Source/UI/UITransBalloonText.h rename to Source/UI/Text/UITransBalloonText.h index 0f257dc..49109c9 100644 --- a/Source/UI/UITransBalloonText.h +++ b/Source/UI/Text/UITransBalloonText.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UITRANSBALLOONTEXT_H -#define RAGNAROK_SOURCE_UI_UITRANSBALLOONTEXT_H +#ifndef RAGNAROK_SOURCE_UI_TEXT_UITRANSBALLOONTEXT_H +#define RAGNAROK_SOURCE_UI_TEXT_UITRANSBALLOONTEXT_H -#include "UI/UIBalloonText.h" +#include "UI/Text/UIBalloonText.h" struct BalloonRectangle { int x; @@ -13,7 +13,6 @@ struct BalloonRectangle { std::uint32_t unknown_0018; }; -// RTTI UITransBalloonText, original 204-byte x86 value. class UITransBalloonText : public UIBalloonText { public: UITransBalloonText(UIWindowContext& windows, BalloonTextContext& text); @@ -25,7 +24,6 @@ public: void Slot15(int width, int height) override; void Paint() override; - // Source views for original direct accesses by the mode tooltip owner. void SetRichText(unsigned char value) { this->m_richText = value; } diff --git a/Source/UI/TextWrapping.h b/Source/UI/TextWrapping.h deleted file mode 100644 index f9b5c34..0000000 --- a/Source/UI/TextWrapping.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_TEXTWRAPPING_H -#define RAGNAROK_SOURCE_UI_TEXTWRAPPING_H - -#include -#include - -struct ItemDescriptions; - -void WrapPlainText( - const char* text, - std::vector& lines, - int width, - unsigned short codePage, - bool inlineCharset -); - -void WrapRichText( - const char* text, - std::vector& lines, - int width, - bool carriageReturns, - unsigned short codePage, - bool inlineCharset, - ItemDescriptions& items -); - -#endif diff --git a/Source/UI/UIStaticBitmap.cpp b/Source/UI/UIStaticBitmap.cpp index ee7cfe7..1379fe9 100644 --- a/Source/UI/UIStaticBitmap.cpp +++ b/Source/UI/UIStaticBitmap.cpp @@ -1,17 +1,9 @@ -#include "Render/DeviceContext.h" -#include "Resource/BitmapResource.h" +#include "Render/DeviceContext/DeviceContext.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/UIButton.h" +#include "UI/Buttons/UIButton.h" #include "UI/UIStaticBitmap.h" -#include - -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } -} - // OFFSET: 0x00850430 UIStaticBitmap::UIStaticBitmap(UIWindowContext& windows, UIButtonContext& controls) : UIWindow(windows, 0), tooltipX(0), tooltipY(-20), forwardHover(0), m_controls(&controls) { @@ -48,19 +40,19 @@ void UIStaticBitmap::Paint() { // OFFSET: 0x0085EE10 // FUNCTION: fn_10849 void UIStaticBitmap::Slot25(int x, int y) { - static_cast(this->parent)->Slot25(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot25((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085EA30 // FUNCTION: fn_10836 void UIStaticBitmap::Slot26(int x, int y) { - static_cast(this->parent)->Slot26(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot26((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085F8A0 // FUNCTION: fn_10872 void UIStaticBitmap::Slot27(int x, int y) { - static_cast(this->parent)->Slot27(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot27((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085F500 @@ -75,8 +67,8 @@ void UIStaticBitmap::Slot28(int x, int y) { int screenY = this->tooltipY; for (const UIWindow* window = this; window; window = static_cast(window->parent)) { - screenX = Add(screenX, window->geometry.x); - screenY = Add(screenY, window->geometry.y); + screenX = (screenX + window->geometry.x); + screenY = (screenY + window->geometry.y); } this->m_controls->services.Tooltip(this->tooltip.c_str(), screenX, screenY, -1, false, true); @@ -86,25 +78,25 @@ void UIStaticBitmap::Slot28(int x, int y) { // OFFSET: 0x0085FA80 // FUNCTION: fn_10880 void UIStaticBitmap::ResetCursor(int x, int y) { - static_cast(this->parent)->ResetCursor(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->ResetCursor((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085F000 // FUNCTION: fn_10854 void UIStaticBitmap::Slot31(int x, int y) { - static_cast(this->parent)->Slot31(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot31((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085FEA0 // FUNCTION: fn_10888 void UIStaticBitmap::Slot32(int x, int y) { - static_cast(this->parent)->Slot32(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot32((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x0085FF00 // FUNCTION: fn_10890 void UIStaticBitmap::Slot33(int x, int y) { - static_cast(this->parent)->Slot33(Add(x, this->geometry.x), Add(y, this->geometry.y)); + static_cast(this->parent)->Slot33((x + this->geometry.x), (y + this->geometry.y)); } // OFFSET: 0x00860010 diff --git a/Source/UI/UIStaticBitmap.h b/Source/UI/UIStaticBitmap.h index 68cfb8c..10620c8 100644 --- a/Source/UI/UIStaticBitmap.h +++ b/Source/UI/UIStaticBitmap.h @@ -1,13 +1,12 @@ #ifndef RAGNAROK_SOURCE_UI_UISTATICBITMAP_H #define RAGNAROK_SOURCE_UI_UISTATICBITMAP_H -#include "UI/UIWindow.h" +#include "UI/Window/UIWindow.h" #include struct UIButtonContext; -// UIStaticBitmap, 184-byte x86 value. class UIStaticBitmap : public UIWindow { public: UIStaticBitmap(UIWindowContext& windows, UIButtonContext& controls); diff --git a/Source/UI/FrameFocus.cpp b/Source/UI/Window/FrameFocus.cpp similarity index 56% rename from Source/UI/FrameFocus.cpp rename to Source/UI/Window/FrameFocus.cpp index 5d4196f..b545ae1 100644 --- a/Source/UI/FrameFocus.cpp +++ b/Source/UI/Window/FrameFocus.cpp @@ -1,6 +1,6 @@ -#include "UI/FrameFocus.h" -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" +#include "UI/Window/FrameFocus.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" #include @@ -11,19 +11,17 @@ int g_dragWindowId = -1; // OFFSET: 0x00A96A60 // FUNCTION: fn_17192 bool FrameFocus::IsOrderFixed(int id) { - static constexpr int fixed[] = {0, 1, 2, 3, 4, 6, 7, 9, 14, 15, 16, 17, 18, 20, 21, - 22, 23, 24, 26, 28, 29, 31, 32, 33, 34, 35, 36, 39, 42, 45, - 49, 50, 56, 58, 60, 61, 62, 63, 64, 65, 66, 67, 70, 73, 74, - 78, 79, 80, 81, 90, 91, 94, 95, 99, 100, 101, 104, 105, 107, 109, - 111, 115, 116, 123, 124, 127, 128, 130, 131, 133, 136, 137, 138, 144, 154, - 156, 158, 159, 160, 161, 164, 175, 176, 177, 179, 180, 183, 186, 187, 189, - 190, 196, 198, 199, 200, 204, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 253, 257, 258, 262, 267, 268, 269, 271, 277, 278, 284, 285, - 286, 289, 295, 301, 307, 325, 332, 343, 358, 359, 600, 10011, 10032}; + static constexpr int fixed[] = {0, 1, 2, 3, 4, 6, 7, 9, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 26, 28, 29, 31, 32, + 33, 34, 35, 36, 39, 42, 45, 49, 50, 56, 58, 60, 61, 62, 63, 64, 65, 66, 67, 70, 73, 74, 78, + 79, 80, 81, 90, 91, 94, 95, 99, 100, 101, 104, 105, 107, 109, 111, 115, 116, 123, 124, 127, 128, 130, 131, + 133, 136, 137, 138, 144, 154, 156, 158, 159, 160, 161, 164, 175, 176, 177, 179, 180, 183, 186, 187, 189, 190, 196, + 198, 199, 200, 204, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 253, 257, 258, 262, 267, 268, 269, + 271, 277, 278, 284, 285, 286, 289, 295, 301, 307, 325, 332, 343, 358, 359, 600, 10011, 10032}; if (id == 145) { UIWindow* window = this->windows.LookupWindow(145); return !window || window->geometry.visible == 0; } + return std::binary_search(std::begin(fixed), std::end(fixed), id); } @@ -33,6 +31,7 @@ void FrameFocus::RemoveOrder(int id) { if (this->IsOrderFixed(id)) { return; } + for (auto entry = this->order.begin(); entry != this->order.end(); ++entry) { if (*entry == id) { this->order.erase(entry); @@ -47,6 +46,7 @@ void FrameFocus::BringToFront(int id) { if (this->IsOrderFixed(id)) { return; } + this->RemoveOrder(id); if (id == 203) { this->order.push_back(id); @@ -54,16 +54,19 @@ void FrameFocus::BringToFront(int id) { this->order.push_front(id); } } + // OFFSET: 0x00AA9B30 // FUNCTION: fn_17255 void FrameFocus::Set(UIWindow* window) { this->focused = window; } + // OFFSET: 0x00AA66C0 // FUNCTION: fn_17232 void FrameFocus::Clear() { this->focused = nullptr; } + // OFFSET: 0x00A913F0 // FUNCTION: fn_17158 UIWindow* FrameFocus::Get() const { diff --git a/Source/UI/FrameFocus.h b/Source/UI/Window/FrameFocus.h similarity index 68% rename from Source/UI/FrameFocus.h rename to Source/UI/Window/FrameFocus.h index eff19d8..2d10e5d 100644 --- a/Source/UI/FrameFocus.h +++ b/Source/UI/Window/FrameFocus.h @@ -1,14 +1,13 @@ -#ifndef RAGNAROK_SOURCE_UI_FRAMEFOCUS_H -#define RAGNAROK_SOURCE_UI_FRAMEFOCUS_H +#ifndef RAGNAROK_SOURCE_UI_WINDOW_FRAMEFOCUS_H +#define RAGNAROK_SOURCE_UI_WINDOW_FRAMEFOCUS_H -#include "UI/WindowAncestry.h" +#include "UI/Window/WindowAncestry.h" #include class UIWindow; class WindowManagerWindows; -// Borrowed actual manager order list+24 and reference+412; no extra owner. struct FrameFocus { std::list& order; WindowAncestry*& focused; diff --git a/Source/UI/FrameTextCache.cpp b/Source/UI/Window/FrameTextCache.cpp similarity index 95% rename from Source/UI/FrameTextCache.cpp rename to Source/UI/Window/FrameTextCache.cpp index 2601742..7764741 100644 --- a/Source/UI/FrameTextCache.cpp +++ b/Source/UI/Window/FrameTextCache.cpp @@ -1,11 +1,13 @@ -#include "UI/FrameTextCache.h" +#include "UI/Window/FrameTextCache.h" namespace { std::uint32_t HashWord(std::uint32_t value) { std::uint32_t hash = 0x811C9DC5u; + for (unsigned shift = 0; shift < 32; shift += 8) { hash = 16777619u * (hash ^ ((value >> shift) & 255)); } + return hash; } } @@ -14,9 +16,11 @@ namespace { // FUNCTION: fn_11892 std::size_t FrameTextHash::operator()(const FrameTextKey& key) const { std::uint32_t hash = 0x811C9DC5u; + for (unsigned char value : key.text) { hash = 16777619u * (hash ^ value); } + hash ^= HashWord(key.word1) + 0x9E3779B9u + (hash << 6) + (hash >> 2); hash ^= HashWord(key.word0) + 0x9E3779B9u + (hash << 6) + (hash >> 2); return hash; diff --git a/Source/UI/FrameTextCache.h b/Source/UI/Window/FrameTextCache.h similarity index 72% rename from Source/UI/FrameTextCache.h rename to Source/UI/Window/FrameTextCache.h index b265214..5fd988c 100644 --- a/Source/UI/FrameTextCache.h +++ b/Source/UI/Window/FrameTextCache.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_FRAMETEXTCACHE_H -#define RAGNAROK_SOURCE_UI_FRAMETEXTCACHE_H +#ifndef RAGNAROK_SOURCE_UI_WINDOW_FRAMETEXTCACHE_H +#define RAGNAROK_SOURCE_UI_WINDOW_FRAMETEXTCACHE_H #include #include @@ -7,8 +7,6 @@ #include #include -// Original52-byte map node: links8,key32,value12. Key words are preserved -// without claiming semantics for the first two arguments to text layout. struct FrameTextKey { std::uint32_t word0; std::uint32_t word1; diff --git a/Source/UI/InputFocus.cpp b/Source/UI/Window/InputFocus.cpp similarity index 95% rename from Source/UI/InputFocus.cpp rename to Source/UI/Window/InputFocus.cpp index 95f9bed..2113837 100644 --- a/Source/UI/InputFocus.cpp +++ b/Source/UI/Window/InputFocus.cpp @@ -1,5 +1,5 @@ -#include "UI/InputFocus.h" -#include "UI/UIWindow.h" +#include "UI/Window/InputFocus.h" +#include "UI/Window/UIWindow.h" // OFFSET: 0x00AA9B40 // FUNCTION: fn_17256 @@ -105,7 +105,7 @@ void InputFocus::Advance() { // OFFSET: 0x00AA4730 // FUNCTION: fn_17222 -// Common focus refresh at the end of mouse message dispatch. + void InputFocus::Refresh(UIWindow* const& excludedRoot) { if (this->window) { this->window->Invalidate(); diff --git a/Source/UI/Window/InputFocus.h b/Source/UI/Window/InputFocus.h new file mode 100644 index 0000000..a8fcc87 --- /dev/null +++ b/Source/UI/Window/InputFocus.h @@ -0,0 +1,18 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_INPUTFOCUS_H +#define RAGNAROK_SOURCE_UI_WINDOW_INPUTFOCUS_H + +class UIWindow; + +struct InputFocus { + UIWindow*& window; + void Set(UIWindow* value); + void First(); + void Next(); + void Advance(); + + void Refresh(UIWindow* const& excludedRoot); +}; + +void SetPressedWindowRoot(UIWindow*& pressedRoot, UIWindow* window); + +#endif diff --git a/Source/UI/UIControl.cpp b/Source/UI/Window/UIControl.cpp similarity index 98% rename from Source/UI/UIControl.cpp rename to Source/UI/Window/UIControl.cpp index 6216e61..1197b23 100644 --- a/Source/UI/UIControl.cpp +++ b/Source/UI/Window/UIControl.cpp @@ -1,4 +1,4 @@ -#include "UI/UIControl.h" +#include "UI/Window/UIControl.h" // OFFSET: 0x00AA27B0 // FUNCTION: fn_17217 diff --git a/Source/UI/UIControl.h b/Source/UI/Window/UIControl.h similarity index 76% rename from Source/UI/UIControl.h rename to Source/UI/Window/UIControl.h index b54a2ff..a35fbd1 100644 --- a/Source/UI/UIControl.h +++ b/Source/UI/Window/UIControl.h @@ -1,10 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UICONTROL_H -#define RAGNAROK_SOURCE_UI_UICONTROL_H +#ifndef RAGNAROK_SOURCE_UI_WINDOW_UICONTROL_H +#define RAGNAROK_SOURCE_UI_WINDOW_UICONTROL_H -#include "UI/UIWindow.h" +#include "UI/Window/UIWindow.h" -// RTTI CUIControl. Coordinate callbacks translate into the immediate parent's -// space; invalidation dirties the root subtree instead of only this control. class CUIControl : public UIWindow { public: explicit CUIControl(UIWindowContext& context); diff --git a/Source/UI/UIFrameWnd.cpp b/Source/UI/Window/UIFrameWnd.cpp similarity index 64% rename from Source/UI/UIFrameWnd.cpp rename to Source/UI/Window/UIFrameWnd.cpp index 63125c0..bf45911 100644 --- a/Source/UI/UIFrameWnd.cpp +++ b/Source/UI/Window/UIFrameWnd.cpp @@ -1,73 +1,63 @@ -#include "UI/FrameFocus.h" -#include "UI/SnapMgr.h" -#include "UI/UIBitmapButton.h" -#include "UI/UIFrameWnd.h" -#include "UI/WindowManagerWindows.h" -#include "UI/WindowSnapping.h" +#include "UI/Window/FrameFocus.h" +#include "UI/Layout/SnapMgr.h" +#include "UI/Buttons/UIBitmapButton.h" +#include "UI/Window/UIFrameWnd.h" +#include "UI/Window/WindowManagerWindows.h" +#include "UI/Layout/WindowSnapping.h" -#include +#include #include -// clang-format off -#include -// clang-format on - -namespace { - int Add(int a, int b) { - return std::bit_cast(static_cast(a) + static_cast(b)); - } - int Subtract(int a, int b) { - return std::bit_cast(static_cast(a) - static_cast(b)); - } - int Magnitude(int value) { - return value < 0 ? Subtract(0, value) : value; - } -} +#include // OFFSET: 0x008A3700 UIFrameWnd::UIFrameWnd(UIWindowContext& windowContext, UIFrameContext& frameContext, unsigned char cached) - : UIWindow(windowContext, cached), m_dragX(0), m_dragY(0), m_message0(600), m_message1(600), - m_frameContext(&frameContext) { - // Original unordered-map starts with8 buckets and load factor1. + : UIWindow(windowContext, cached), m_dragX(0), m_dragY(0), m_message0(600), m_message1(600), m_frameContext(&frameContext) { this->m_textCache.max_load_factor(1.0f); this->m_textCache.rehash(8); } + // OFFSET: 0x008A4E90 // OFFSET: 0x008A60E0 // FUNCTION: fn_11692 UIFrameWnd::~UIFrameWnd() = default; + // OFFSET: 0x005C4640 // FUNCTION: fn_03570 bool UIFrameWnd::Slot02() { return true; } + // OFFSET: 0x008AD150 // FUNCTION: fn_11735 void UIFrameWnd::Move(int x, int y) { this->geometry.Move(x, y); this->Slot36(); } + // OFFSET: 0x008BB3F0 // FUNCTION: fn_11797 void UIFrameWnd::Slot12() { this->m_originX = this->geometry.x; this->m_originY = this->geometry.y; } + // OFFSET: 0x008AD170 // FUNCTION: fn_11736 void UIFrameWnd::Slot13(int dx, int dy) { - this->geometry.x = Add(this->m_originX, dx); - this->geometry.y = Add(this->m_originY, dy); + this->geometry.x = this->m_originX + dx; + this->geometry.y = this->m_originY + dy; } // OFFSET: 0x00A7D870 // FUNCTION: fn_16956 void UIFrameWnd::ToScreen(int& x, int& y) const { - x = Add(x, this->geometry.x); - y = Add(y, this->geometry.y); + x += this->geometry.x; + y += this->geometry.y; + for (const WindowAncestry* node = this->parent; node; node = node->parent) { const UIWindow* window = static_cast(node); - x = Add(x, window->geometry.x); - y = Add(y, window->geometry.y); + x += window->geometry.x; + y += window->geometry.y; } } @@ -78,6 +68,7 @@ void UIFrameWnd::Slot25(int x, int y) { this->m_frameContext->focus.BringToFront(this->geometry.id); g_dragWindowId = this->geometry.id; } + this->m_frameContext->focus.Set(this); this->ToScreen(x, y); this->m_dragX = x; @@ -92,71 +83,72 @@ void UIFrameWnd::Slot25(int x, int y) { // OFFSET: 0x008BA510 // FUNCTION: fn_11786 void UIFrameWnd::Slot27(int x, int y) { - if ( - this->m_frameContext->focus.Get() != this || x <= Subtract(0, this->m_frameContext->dragLimitX) || - y <= Subtract(0, this->m_frameContext->dragLimitY) - ) { + if (this->m_frameContext->focus.Get() != this || x <= -this->m_frameContext->dragLimitX || y <= -this->m_frameContext->dragLimitY) { return; } + this->ToScreen(x, y); - const int dx = Subtract(x, this->m_dragX); - const int dy = Subtract(y, this->m_dragY); + const int dx = x - this->m_dragX; + const int dy = y - this->m_dragY; WindowSnapping& snapping = this->m_frameContext->snapping; + if (!snapping.graph.Contains(this)) { - this->Move(Add(this->m_originX, dx), Add(this->m_originY, dy)); + this->Move(this->m_originX + dx, this->m_originY + dy); return; } + this->Slot13(dx, dy); int ownX, ownY; snapping.Constrain(this, ownX, ownY, 0); int groupX = dx, groupY = dy; snapping.graph.ConstrainGroup(this, groupX, groupY, snapping); - if (Magnitude(groupX) < Magnitude(ownX)) { + + if (std::abs(groupX) < std::abs(ownX)) { groupX = ownX; } - if (Magnitude(groupY) < Magnitude(ownY)) { + + if (std::abs(groupY) < std::abs(ownY)) { groupY = ownY; } - this->Slot13(Add(dx, groupX), Add(dy, groupY)); + + this->Slot13(dx + groupX, dy + groupY); snapping.Store(this); - snapping.graph.MoveConnected(this, Add(dx, groupX), Add(dy, groupY), snapping); + snapping.graph.MoveConnected(this, dx + groupX, dy + groupY, snapping); } + // OFFSET: 0x008BA3C0 // FUNCTION: fn_11783 void UIFrameWnd::Slot28(int, int) { } + // OFFSET: 0x008BA2C0 // FUNCTION: fn_11781 void UIFrameWnd::Slot31(int, int) { if (this->m_frameContext->focus.Get() != this) { return; } + g_dragWindowId = -1; this->geometry.targetAlpha = 255; this->geometry.alphaStart = timeGetTime(); this->m_frameContext->focus.Clear(); this->m_frameContext->snapping.graph.Refresh(this); } + // OFFSET: 0x008BB340 // FUNCTION: fn_11796 void UIFrameWnd::Slot36() { WindowSnapping& snapping = this->m_frameContext->snapping; int x, y; snapping.Constrain(this, x, y, 0); - this->geometry.x = Add(this->geometry.x, x); - this->geometry.y = Add(this->geometry.y, y); + this->geometry.x += x; + this->geometry.y += y; snapping.Store(this); } + // OFFSET: 0x008BDC90 // FUNCTION: fn_11802 -int UIFrameWnd::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIFrameWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message == 0 || message == 1) { const int id = message == 0 ? this->m_message0 : this->m_message1; if (id) { @@ -172,13 +164,16 @@ int UIFrameWnd::SendMsg( } else { return this->UIWindow::SendMsg(sender, message, a, b, c, d); } + return 0; } + // OFFSET: 0x005C4420 // FUNCTION: fn_03559 std::vector UIFrameWnd::Slot44() { return {}; } + // OFFSET: 0x005C44F0 // FUNCTION: fn_03562 int UIFrameWnd::Slot46() { @@ -191,20 +186,16 @@ UIBitmapButton* UIFrameWnd::AddCloseButton(UIButtonContext& controls, const char if (width == 0) { width = this->geometry.width; } + UIBitmapButton* button = new UIBitmapButton(*this->m_context, controls); - button->SetBitmap( - "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\sys_close_off.bmp", 0, 0 - ); - button->SetBitmap( - "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\sys_close_on.bmp", 1, 0 - ); - button->SetBitmap( - "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\sys_close_on.bmp", 2, 0 - ); + button->SetBitmap("\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\sys_close_off.bmp", 0, 0); + button->SetBitmap("\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\sys_close_on.bmp", 1, 0); + button->SetBitmap("\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\basic_interface\\sys_close_on.bmp", 2, 0); button->SetSize(button->BitmapWidth(), button->BitmapHeight()); - button->Move(Subtract(width, 14), 3); + button->Move(width - 14, 3); button->SetId(201); button->SetTooltip(tooltip); this->AddChild(button); + return button; } diff --git a/Source/UI/UIFrameWnd.h b/Source/UI/Window/UIFrameWnd.h similarity index 74% rename from Source/UI/UIFrameWnd.h rename to Source/UI/Window/UIFrameWnd.h index 5f00e0e..3319447 100644 --- a/Source/UI/UIFrameWnd.h +++ b/Source/UI/Window/UIFrameWnd.h @@ -1,8 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UI_UIFRAMEWND_H -#define RAGNAROK_SOURCE_UI_UIFRAMEWND_H +#ifndef RAGNAROK_SOURCE_UI_WINDOW_UIFRAMEWND_H +#define RAGNAROK_SOURCE_UI_WINDOW_UIFRAMEWND_H -#include "UI/FrameTextCache.h" -#include "UI/UIWindow.h" +#include "UI/Window/FrameTextCache.h" +#include "UI/Window/UIWindow.h" struct FrameFocus; struct WindowSnapping; @@ -18,8 +18,6 @@ struct UIFrameContext { const int& dragLimitY; }; -// RTTI UIFrameWnd, original size180. Explicit -// source dependency pointers in base/derived shift derived x86 fields by4. class UIFrameWnd : public UIWindow { public: UIFrameWnd(UIWindowContext& windowContext, UIFrameContext& frameContext, unsigned char cached); @@ -33,14 +31,7 @@ public: void Slot28(int x, int y) override; void Slot31(int x, int y) override; void Slot36() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t argument1, - std::intptr_t argument2, - std::intptr_t argument3, - std::intptr_t argument4 - ) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) override; std::vector Slot44() override; int Slot46() override; UIBitmapButton* AddCloseButton(UIButtonContext& controls, const char* tooltip, int width); diff --git a/Source/UI/UIMessageBox.cpp b/Source/UI/Window/UIMessageBox.cpp similarity index 70% rename from Source/UI/UIMessageBox.cpp rename to Source/UI/Window/UIMessageBox.cpp index fa4c7f6..accc789 100644 --- a/Source/UI/UIMessageBox.cpp +++ b/Source/UI/Window/UIMessageBox.cpp @@ -1,30 +1,27 @@ #include "Client/ReplayPacketRecorder.h" -#include "Resource/BitmapResource.h" +#include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" -#include "UI/UIBitmapButton.h" -#include "UI/UIMessageBox.h" +#include "UI/Buttons/UIBitmapButton.h" +#include "UI/Window/UIMessageBox.h" #include "UI/UIStaticBitmap.h" -#include "UI/UITextButton.h" -#include "UI/UITextViewer.h" -#include "UI/WindowBorder.h" -#include "UI/WindowRetirement.h" +#include "UI/Buttons/UITextButton.h" +#include "UI/Text/UITextViewer.h" +#include "UI/Window/WindowBorder.h" +#include "UI/Window/WindowRetirement.h" -#include #include -#include +#include +#include #include namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } constexpr char prefix[] = "\xC0\xAF\xC0\xFA\xC0\xCE\xC5\xCD\xC6\xE4\xC0\xCC\xBD\xBA\\"; std::uint32_t Palette(ResourceMgr& resources, int x, int y) { const auto* resource = static_cast(resources.Load((std::string(prefix) + "colorchip.bmp").c_str())); const auto& image = resource->image; - const std::uint32_t pixel = - x >= 0 && y >= 0 && x < image.width && y < image.height ? image.pixels[y * image.width + x] : 0x00FF0000u; + const std::uint32_t pixel = x >= 0 && y >= 0 && x < image.width && y < image.height ? image.pixels[y * image.width + x] : 0x00FF0000u; + return ((pixel & 255) << 16) | (pixel & 0xFF00) | ((pixel >> 16) & 255); } } @@ -44,9 +41,7 @@ UIMessageBox::~UIMessageBox() = default; // FUNCTION: fn_11768 void UIMessageBox::Paint() { auto& controls = this->m_dialog->text.buttons; - const auto load = [&](const char* name) { - return static_cast(controls.resources.Load((std::string(prefix) + name).c_str())); - }; + const auto load = [&](const char* name) { return static_cast(controls.resources.Load((std::string(prefix) + name).c_str())); }; int leftWidth = 0; int rightWidth = 0; int titleHeight = 0; @@ -60,36 +55,32 @@ void UIMessageBox::Paint() { if (const auto* right = load("basic_interface\\titlebar_right.bmp")) { rightWidth = right->image.width; - this->DrawBitmap(Add(width, -rightWidth), 0, &right->image, false); + this->DrawBitmap(width - rightWidth, 0, &right->image, false); } if (const auto* middle = load("basic_interface\\titlebar_mid.bmp")) { titleHeight = middle->image.height; const int tileWidth = middle->image.width; - const int extent = Add(Add(width, -rightWidth), -leftWidth); + const int extent = width - rightWidth - leftWidth; const int tiles = extent / tileWidth + (extent % tileWidth != 0); for (int index = 0; index < tiles; ++index) { this->DrawBitmap(leftWidth, 0, &middle->image, false); - leftWidth = Add(leftWidth, tileWidth); + leftWidth += tileWidth; } } - this->DrawTextAt( - controls.fonts, controls.locale, 19, Add(titleHeight, -13), this->caption.c_str(), 0, 0, 12, 0xFFFFFF, 0, 0 - ); - this->DrawTextAt( - controls.fonts, controls.locale, 18, Add(titleHeight, -14), this->caption.c_str(), 0, 0, 12, 0, 0, 0 - ); + this->DrawTextAt(controls.fonts, controls.locale, 19, titleHeight - 13, this->caption.c_str(), 0, 0, 12, 0xFFFFFF, 0, 0); + this->DrawTextAt(controls.fonts, controls.locale, 18, titleHeight - 14, this->caption.c_str(), 0, 0, 12, 0, 0, 0); const auto* base = load("basic_interface\\sys_base_off.bmp"); this->DrawBitmap(3, 3, base ? &base->image : nullptr, true); const auto border = Palette(controls.resources, 14, 6); - DrawRoundedBorder(*this, 0, 17, width, Add(height, -17), border); + DrawRoundedBorder(*this, 0, 17, width, height - 17, border); this->FillRegion(0, 17, width, 5, border); const auto background = Palette(controls.resources, 2, 2); - this->FillRegion(1, 17, Add(width, -2), Add(height, -19), background); - this->FillRegion(2, Add(height, -2), Add(width, -4), 1, background); + this->FillRegion(1, 17, width - 2, height - 19, background); + this->FillRegion(2, height - 2, width - 4, 1, background); } // OFFSET: 0x008B7A90 @@ -122,15 +113,7 @@ void UIMessageBox::AddButton(const char* name, int id, int x, int y) { // OFFSET: 0x008A7350 // FUNCTION: fn_11713 void UIMessageBox::Configure( - const char* text, - int type, - bool defaultAccept, - int timeout, - const char* title, - int width, - int height, - int modalValue, - const char* icon + const char* text, int type, bool defaultAccept, int timeout, const char* title, int width, int height, int modalValue, const char* icon ) { this->caption = title; this->messageText = text; @@ -149,9 +132,7 @@ void UIMessageBox::Configure( this->SetSize(width, height); this->Slot15(width, height); this->Slot22(width, height); - this->Move( - Add(Add(this->m_dialog->screenWidth, -640) / 2, 185), Add(Add(this->m_dialog->screenHeight, -480) / 2, 180) - ); + this->Move((this->m_dialog->screenWidth - 640) / 2 + 185, (this->m_dialog->screenHeight - 480) / 2 + 180); int inset = 0; if (icon) { @@ -160,39 +141,37 @@ void UIMessageBox::Configure( image->SetSize(image->geometry.width, image->geometry.height); image->Move(10, 22); this->AddChild(image); - inset = Add(image->geometry.width, image->geometry.x); + inset = image->geometry.width + image->geometry.x; } this->viewer = new UITextViewer(*this->m_context, this->m_dialog->text); - this->viewer->Configure(Add(inset, 10), 22, Add(Add(width, -inset), -20), Add(height, -55), 0); + this->viewer->Configure(inset + 10, 22, width - inset - 20, height - 55, 0); this->viewer->backgroundColor = Palette(this->m_dialog->text.buttons.resources, 2, 2) | 0xFF000000u; this->viewer->Invalidate(); this->AddChild(this->viewer); - this->viewer->SendMsg( - nullptr, 29, reinterpret_cast(this->messageText.data()), - static_cast(static_cast(width) / 7.5), 0, 0 - ); + this->viewer->SendMsg(nullptr, 29, reinterpret_cast(this->messageText.data()), static_cast(static_cast(width) / 7.5), 0, 0); this->m_message0 = type == 2 ? 188 : 185; switch (type) { case 0: - this->AddButton("btn_ok", 184, Add(width, -46), Add(height, -24)); + this->AddButton("btn_ok", 184, width - 46, height - 24); this->m_message0 = 184; break; case 2: - this->AddButton("btn_ok", 187, Add(width, -91), Add(height, -24)); - this->AddButton("btn_cancel", 188, Add(width, -46), Add(height, -24)); + this->AddButton("btn_ok", 187, width - 91, height - 24); + this->AddButton("btn_cancel", 188, width - 46, height - 24); this->m_message0 = defaultAccept ? 187 : 188; this->m_message1 = 188; break; case 4: - this->AddButton("btn_cancel", 185, Add(width, -46), Add(height, -24)); + this->AddButton("btn_cancel", 185, width - 46, height - 24); this->m_message0 = 185; break; case 5: { - this->AddButton("btn_ok", 184, Add(width, -46), Add(height, -24)); + this->AddButton("btn_ok", 184, width - 46, height - 24); this->m_message0 = 184; auto& controls = this->m_dialog->text.buttons; + auto* button = new UITextButton(*this->m_context, controls); button->Configure(controls.services.MessageText(3445), 0x00F4934A, 0, 12, 0, 0); button->m_hoverColor = 0x00FF7864; @@ -234,14 +213,7 @@ void UIMessageBox::Slot19() { // OFFSET: 0x008BF950 // FUNCTION: fn_11808 -int UIMessageBox::SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d -) { +int UIMessageBox::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { switch (message) { case 6: this->m_dialog->recorder.Record(this->geometry.id, static_cast(a), b, c, d); @@ -263,10 +235,7 @@ int UIMessageBox::SendMsg( case 98: if (a == 426) { auto& controls = this->m_dialog->text.buttons; - ShellExecuteA( - this->m_dialog->text.applicationWindow, "open", controls.services.MessageText(3445), nullptr, nullptr, - SW_SHOWNORMAL - ); + ShellExecuteA(this->m_dialog->text.applicationWindow, "open", controls.services.MessageText(3445), nullptr, nullptr, SW_SHOWNORMAL); } return 0; diff --git a/Source/UI/UIMessageBox.h b/Source/UI/Window/UIMessageBox.h similarity index 71% rename from Source/UI/UIMessageBox.h rename to Source/UI/Window/UIMessageBox.h index edb3eba..47b2010 100644 --- a/Source/UI/UIMessageBox.h +++ b/Source/UI/Window/UIMessageBox.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UI_UIMESSAGEBOX_H -#define RAGNAROK_SOURCE_UI_UIMESSAGEBOX_H +#ifndef RAGNAROK_SOURCE_UI_WINDOW_UIMESSAGEBOX_H +#define RAGNAROK_SOURCE_UI_WINDOW_UIMESSAGEBOX_H -#include "UI/UIFrameWnd.h" +#include "UI/Window/UIFrameWnd.h" #include @@ -21,7 +21,6 @@ struct UIMessageBoxContext { const int& screenHeight; }; -// RTTI UIMessageBox; original x86 size 288. class UIMessageBox : public UIFrameWnd { public: UIMessageBox(UIWindowContext& windows, UIFrameContext& frames, UIMessageBoxContext& dialog); @@ -29,25 +28,8 @@ public: void Slot18() override; void Slot19() override; void Paint() override; - int SendMsg( - UIWindow* sender, - int message, - std::intptr_t a, - std::intptr_t b, - std::intptr_t c, - std::intptr_t d - ) override; - void Configure( - const char* text, - int type, - bool defaultAccept, - int timeout, - const char* caption, - int width, - int height, - int modal, - const char* icon - ); + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; + void Configure(const char* text, int type, bool defaultAccept, int timeout, const char* caption, int width, int height, int modal, const char* icon); /* 00B4 */ UITextViewer* viewer; /* 00B8 */ int unknown_00B8; diff --git a/Source/UI/UIWindow.cpp b/Source/UI/Window/UIWindow.cpp similarity index 83% rename from Source/UI/UIWindow.cpp rename to Source/UI/Window/UIWindow.cpp index a4515c1..c5c659a 100644 --- a/Source/UI/UIWindow.cpp +++ b/Source/UI/Window/UIWindow.cpp @@ -1,14 +1,14 @@ -#include "Client/ModeCursor.h" -#include "Client/ModeEvents.h" -#include "Render/DCBitmap.h" -#include "Render/RenderPrimitivePool.h" -#include "Render/RenderQueues.h" +#include "Client/Mode/ModeCursor.h" +#include "Client/Mode/ModeEvents.h" +#include "Render/DeviceContext/DCBitmap.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Primitives/RenderQueues.h" #include "Render/Renderer.h" -#include "Render/TextContext.h" -#include "Render/Texture.h" -#include "Resource/BitmapImage.h" -#include "UI/UIWindow.h" -#include "UI/WindowRegistration.h" +#include "Render/Text/TextContext.h" +#include "Render/Textures/Texture.h" +#include "Resource/Bitmap/BitmapImage.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowRegistration.h" #include #include @@ -17,15 +17,6 @@ // GLOBAL: gl_24364 std::uint32_t g_windowUid = 0xFFFFFFFFu; -namespace { - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - int Subtract(int left, int right) { - return std::bit_cast(static_cast(left) - static_cast(right)); - } -} - // ORIGINAL_SITE: 0x00AA4730 in fn_17222 (fragment) void UIWindowContext::DestroyDeferredChildren() { for (UIWindow* window : this->deferredDeletion) { @@ -37,8 +28,7 @@ void UIWindowContext::DestroyDeferredChildren() { // OFFSET: 0x00A79A90 UIWindow::UIWindow(UIWindowContext& context, unsigned char cached) - : unknown_0044(0), unknown_0048(0), unknown_004C(4), m_dirty(1), m_uid(++g_windowUid), m_cached(cached), m_clip(0), - m_context(&context) { + : unknown_0044(0), unknown_0048(0), unknown_004C(4), m_dirty(1), m_uid(++g_windowUid), m_cached(cached), m_clip(0), m_context(&context) { } // OFFSET: 0x00A79E90 @@ -51,8 +41,8 @@ UIWindow::~UIWindow() { this->DeleteChildren(); this->m_context->registration.Remove(this); ForgetWindowReferences( - this, this->m_context->reference_019C, this->m_context->reference_01A0, this->m_context->reference_01B8, - this->m_context->reference_0A30, this->m_context->reference_4F1D4 + this, this->m_context->reference_019C, this->m_context->reference_01A0, this->m_context->reference_01B8, this->m_context->reference_0A30, + this->m_context->reference_4F1D4 ); } @@ -75,147 +65,181 @@ void UIWindow::Resize(int width, int height) { bool UIWindow::Slot02() { return false; } + // OFFSET: 0x005C4670 // FUNCTION: fn_03573 bool UIWindow::Slot03() { return false; } + // ORIGINAL_SITE: 0x00A81D40 in fn_16987 (body) void UIWindow::Move(int x, int y) { this->geometry.Move(x, y); } + // OFFSET: 0x005C3220 // FUNCTION: fn_03553 bool UIWindow::Slot05() { return false; } + // OFFSET: 0x005C4510 // FUNCTION: fn_03564 UIWindow* UIWindow::Slot06() { return this; } + // OFFSET: 0x005C45C0 // FUNCTION: fn_03567 bool UIWindow::Slot07(void*) { return false; } + // OFFSET: 0x005C4660 // FUNCTION: fn_03572 bool UIWindow::Slot08() { return false; } + // OFFSET: 0x005CA050 // FUNCTION: fn_03638 bool UIWindow::CanHitTest() { return true; } + // OFFSET: 0x00A7BB00 // FUNCTION: fn_16933 void UIWindow::Slot10(int, int, std::intptr_t) { this->m_context->mode->SendModeMessage(18, 0, 0, 0, 0); } + // OFFSET: 0x005CA0F0 // FUNCTION: fn_03640 void UIWindow::Slot11() { } + // OFFSET: 0x005C7B40 // FUNCTION: fn_03623 void UIWindow::Slot12() { } + // OFFSET: 0x005C4680 // FUNCTION: fn_03574 void UIWindow::Slot13(int, int) { } + // ORIGINAL_SITE: 0x005C9630 in fn_03632 (body) void UIWindow::Show(int visible) { this->geometry.Show(visible); } + // OFFSET: 0x005C6070 // FUNCTION: fn_03584 void UIWindow::Slot15(int, int) { } + // OFFSET: 0x005C6F10 // FUNCTION: fn_03592 void UIWindow::Slot16() { } + // OFFSET: 0x005C7340 // FUNCTION: fn_03613 void UIWindow::Grow(int width, int height) { - this->Resize(Add(this->geometry.width, width), Add(this->geometry.height, height)); + this->Resize((this->geometry.width + width), (this->geometry.height + height)); } + // OFFSET: 0x005C6080 // FUNCTION: fn_03585 void UIWindow::Slot18() { } + // OFFSET: 0x005C72D0 // FUNCTION: fn_03606 void UIWindow::Slot19() { } + // OFFSET: 0x006006C0 // FUNCTION: fn_04159 void UIWindow::Paint() { } + // OFFSET: 0x005C7320 // FUNCTION: fn_03611 void UIWindow::Slot21() { } + // OFFSET: 0x005C7330 // FUNCTION: fn_03612 void UIWindow::Slot22(int, int) { } + // OFFSET: 0x005C4C70 // FUNCTION: fn_03578 void UIWindow::Slot23() { } + // OFFSET: 0x005C6F00 // FUNCTION: fn_03591 void UIWindow::Slot24(int) { } + // OFFSET: 0x005FDA50 // FUNCTION: fn_04116 void UIWindow::Slot25(int, int) { } + // OFFSET: 0x005C6F30 // FUNCTION: fn_03594 void UIWindow::Slot26(int, int) { } + // OFFSET: 0x005C7280 // FUNCTION: fn_03602 void UIWindow::Slot27(int, int) { } + // OFFSET: 0x005C7260 // FUNCTION: fn_03600 void UIWindow::Slot28(int, int) { } + // OFFSET: 0x005C7290 // FUNCTION: fn_03603 void UIWindow::Slot29(int, int) { } + // OFFSET: 0x00A81D60 // FUNCTION: fn_16988 void UIWindow::ResetCursor(int, int) { this->m_context->cursor.Set(0, this->m_context->cursorTick); } + // OFFSET: 0x005C7240 // FUNCTION: fn_03598 void UIWindow::Slot31(int, int) { } + // OFFSET: 0x005C7300 // FUNCTION: fn_03609 void UIWindow::Slot32(int, int) { } + // OFFSET: 0x005C7310 // FUNCTION: fn_03610 void UIWindow::Slot33(int, int) { } + // OFFSET: 0x005C72E0 // FUNCTION: fn_03607 void UIWindow::Slot34(int, int) { } + // OFFSET: 0x005C73A0 // FUNCTION: fn_03615 void UIWindow::Slot35(int) { } + // OFFSET: 0x005C7AB0 // FUNCTION: fn_03620 void UIWindow::Slot36() { @@ -227,6 +251,7 @@ int UIWindow::SendMsg(UIWindow*, int message, std::intptr_t, std::intptr_t, std: if ((message == 0 || message == 1) && this->parent) { this->Parent()->SendMsg(this, message, 0, 0, 0, 0); } + return 0; } @@ -256,6 +281,7 @@ void UIWindow::InvalidateChildren() { // FUNCTION: fn_03569 void UIWindow::Slot39() { } + // ORIGINAL_SITE: 0x00A7D6F0 in fn_16954 (body) std::uint32_t UIWindow::Color() { return this->geometry.Color(); @@ -269,54 +295,66 @@ bool UIWindow::Update(int redraw) { this->m_dirty = 0; redraw = 1; } + bool changed = false; + for (UIWindow* child : this->m_children) { if (child->geometry.visible == 1) { changed = child->Update(redraw) || changed; } } + if (this->m_cached == 1) { if (redraw != 1 && !changed) { return false; } + std::list primitives(this->m_primitives); + for (UIWindow* child : this->m_children) { if (child->geometry.visible == 1) { primitives.push_back(child->DrawPrimitive()); } } + this->m_context->renderer.RenderToTexture(this->geometry.width, this->geometry.height, primitives, this->m_texture); return this->parent != nullptr; } + if (!this->parent || (redraw != 1 && !changed)) { return false; } + UIWindow* parentWindow = this->Parent(); if (parentWindow->m_cached != 0) { return true; } + CDCBitmap& source = *static_cast(this->geometry.surface); if (this->m_clip == 0) { - parentWindow->geometry.surface->BlendFrom( - this->geometry.x, this->geometry.y, this->geometry.width, this->geometry.height, source - ); + parentWindow->geometry.surface->BlendFrom(this->geometry.x, this->geometry.y, this->geometry.width, this->geometry.height, source); return true; } + int x = this->geometry.x >= 0 ? this->geometry.x : 0; int y = this->geometry.y >= 0 ? this->geometry.y : 0; - int sourceX = this->geometry.x >= 0 ? 0 : Subtract(0, this->geometry.x); - int sourceY = this->geometry.y >= 0 ? 0 : Subtract(0, this->geometry.y); - int width = this->geometry.x >= 0 ? this->geometry.width : Add(this->geometry.width, this->geometry.x); - int height = this->geometry.y >= 0 ? this->geometry.height : Add(this->geometry.height, this->geometry.y); - if (parentWindow->geometry.width < Add(x, width)) { - width = Subtract(parentWindow->geometry.width, x); + int sourceX = this->geometry.x >= 0 ? 0 : (0 - this->geometry.x); + int sourceY = this->geometry.y >= 0 ? 0 : (0 - this->geometry.y); + int width = this->geometry.x >= 0 ? this->geometry.width : (this->geometry.width + this->geometry.x); + int height = this->geometry.y >= 0 ? this->geometry.height : (this->geometry.height + this->geometry.y); + + if (parentWindow->geometry.width < (x + width)) { + width = (parentWindow->geometry.width - x); } - if (parentWindow->geometry.height < Add(y, height)) { - height = Subtract(parentWindow->geometry.height, y); + + if (parentWindow->geometry.height < (y + height)) { + height = (parentWindow->geometry.height - y); } + if (width > 0 && height > 0) { parentWindow->geometry.surface->CopyFrom(x, y, sourceX, sourceY, width, height, source); } + return true; } @@ -325,28 +363,34 @@ bool UIWindow::Update(int redraw) { bool UIWindow::Slot42(void*) { return false; } + // OFFSET: 0x005C33D0 // FUNCTION: fn_03556 void UIWindow::Slot43() { } + // OFFSET: 0x005C4480 // FUNCTION: fn_03560 std::vector UIWindow::Slot44() { return {}; } + // ORIGINAL_SITE: 0x005C8F60 in fn_03629 (body) void UIWindow::SetId(int value) { this->geometry.SetId(value); } + // OFFSET: 0x005C4500 // FUNCTION: fn_03563 int UIWindow::Slot46() { return 0; } + // OFFSET: 0x005C7250 // FUNCTION: fn_03599 void UIWindow::Slot47() { } + // OFFSET: 0x005C7270 // FUNCTION: fn_03601 void UIWindow::Slot48() { @@ -358,18 +402,20 @@ RenderPrimitive* UIWindow::DrawPrimitive() { if (this->m_cached == 0) { static_cast(this->geometry.surface)->UploadTexture(this->m_context->renderSystem, this->m_texture); } + RenderPrimitive* primitive = this->m_context->primitives.Acquire(); primitive->texture = this->m_texture; const float width = static_cast(std::bit_cast(this->m_texture->TextureWidth())); const float height = static_cast(std::bit_cast(this->m_texture->TextureHeight())); const float x = static_cast(this->geometry.x); const float y = static_cast(this->geometry.y); - const float right = static_cast(Add(this->geometry.x, this->geometry.width)); - const float bottom = static_cast(Add(this->geometry.y, this->geometry.height)); + const float right = static_cast((this->geometry.x + this->geometry.width)); + const float bottom = static_cast((this->geometry.y + this->geometry.height)); const float u0 = g_textureOffsetX / width; const float v0 = g_textureOffsetY / height; const float u1 = (static_cast(this->geometry.width) + g_textureOffsetX) / width; const float v1 = (static_cast(this->geometry.height) + g_textureOffsetY) / height; + primitive->quad[0].x = x; primitive->quad[0].y = y; primitive->quad[0].u = u0; @@ -386,11 +432,13 @@ RenderPrimitive* UIWindow::DrawPrimitive() { primitive->quad[3].y = bottom; primitive->quad[3].u = u1; primitive->quad[3].v = v1; + for (RenderVertex& vertex : primitive->quad) { vertex.z = 0.000001f; vertex.rhw = 0.999999f; vertex.diffuse = this->Color(); } + return primitive; } @@ -400,18 +448,18 @@ UIWindow* UIWindow::HitTest(int x, int y) { if (!this->CanHitTest() || this->geometry.visible == 0) { return nullptr; } - if ( - x < this->geometry.x || x >= Add(this->geometry.x, this->geometry.width) || y < this->geometry.y || - y >= Add(this->geometry.y, this->geometry.height) - ) { + + if (x < this->geometry.x || x >= (this->geometry.x + this->geometry.width) || y < this->geometry.y || y >= (this->geometry.y + this->geometry.height)) { return nullptr; } + for (auto child = this->m_children.rbegin(); child != this->m_children.rend(); ++child) { - UIWindow* hit = (*child)->HitTest(Subtract(x, this->geometry.x), Subtract(y, this->geometry.y)); + UIWindow* hit = (*child)->HitTest((x - this->geometry.x), (y - this->geometry.y)); if (hit) { return hit; } } + return this; } @@ -424,6 +472,7 @@ void UIWindow::VisitChildren() { } } } + // OFFSET: 0x005C7AC0 // FUNCTION: fn_03621 void UIWindow::Slot52(int) { @@ -435,6 +484,7 @@ void UIWindow::AddChild(UIWindow* child) { child->parent = this; this->m_children.push_back(child); } + // OFFSET: 0x00A7A0A0 // FUNCTION: fn_16921 void UIWindow::AddChildFront(UIWindow* child) { @@ -454,6 +504,7 @@ UIWindow* UIWindow::FindUid(std::uint32_t uid) { return found; } } + return nullptr; } @@ -461,19 +512,24 @@ UIWindow* UIWindow::FindUid(std::uint32_t uid) { // FUNCTION: fn_16953 UIWindow* UIWindow::Root() { UIWindow* root = this; + while (root->parent) { root = static_cast(root->parent); } + return root; } + // OFFSET: 0x00A82DD0 // FUNCTION: fn_16995 void UIWindow::DeleteChildren() { for (UIWindow* child : this->m_children) { delete child; } + this->m_children.clear(); } + // OFFSET: 0x00A82E30 // FUNCTION: fn_16996 void UIWindow::ClearChildren(bool destroy) { @@ -490,9 +546,10 @@ void UIWindow::DeferDeletion(UIWindow* window) { if (!window) { return; } + ForgetWindowReferences( - window, this->m_context->reference_019C, this->m_context->reference_01A0, this->m_context->reference_01B8, - this->m_context->reference_0A30, this->m_context->reference_4F1D4 + window, this->m_context->reference_019C, this->m_context->reference_01A0, this->m_context->reference_01B8, this->m_context->reference_0A30, + this->m_context->reference_4F1D4 ); this->m_context->deferredDeletion.insert(window); window->Show(0); @@ -504,32 +561,39 @@ void UIWindow::RemoveChild(UIWindow* child, unsigned char destroy) { if (!child) { return; } + for (auto entry = this->m_children.begin(); entry != this->m_children.end(); ++entry) { if (*entry == child) { if (destroy == 1) { this->DeferDeletion(child); } + this->m_children.erase(entry); return; } } } + // OFFSET: 0x00A81CC0 // FUNCTION: fn_16986 bool UIWindow::Contains(const UIWindow* window) const { if (!window) { return false; } + if (window == this) { return true; } + for (UIWindow* child : this->m_children) { if (child->Contains(window)) { return true; } } + return false; } + // OFFSET: 0x00A7B430 // FUNCTION: fn_16927 void UIWindow::ClearSurface(std::uint32_t color) { @@ -557,6 +621,7 @@ void UIWindow::DrawBitmap(int x, int y, const BitmapImage* image, bool transpare if (!this->geometry.surface || !image) { return; } + static_cast(this->geometry.surface)->SetAlpha(image->alpha != 0); this->geometry.surface->Copy(x, y, image->width, image->height, image->pixels, transparent); } @@ -564,11 +629,10 @@ void UIWindow::DrawBitmap(int x, int y, const BitmapImage* image, bool transpare // OFFSET: 0x00A7BD60 // FUNCTION: fn_16938 void UIWindow::FillRegion(int x, int y, int width, int height, std::uint32_t color) { - const int right = Add(x, width); - const int bottom = Add(y, height); + const int right = (x + width); + const int bottom = (y + height); RECT rectangle = { - x < 0 ? 0 : x, y < 0 ? 0 : y, this->geometry.width < right ? this->geometry.width : right, - this->geometry.height < bottom ? this->geometry.height : bottom + x < 0 ? 0 : x, y < 0 ? 0 : y, this->geometry.width < right ? this->geometry.width : right, this->geometry.height < bottom ? this->geometry.height : bottom }; this->geometry.surface->Fill(&rectangle, color); } @@ -576,24 +640,19 @@ void UIWindow::FillRegion(int x, int y, int width, int height, std::uint32_t col // OFFSET: 0x00A80580 // FUNCTION: fn_16975 int UIWindow::TextWidth( - FontCache& fonts, - const TextLocale& locale, - const char* text, - unsigned bytes, - int family, - int height, - unsigned char bold, - unsigned char italic + FontCache& fonts, const TextLocale& locale, const char* text, unsigned bytes, int family, int height, unsigned char bold, unsigned char italic ) { if (!text) { return 0; } + if (!bytes) { bytes = static_cast(std::strlen(text)); if (!bytes) { return 0; } } + TextContext context(*this->geometry.surface, fonts, locale); context.SetFont(family, height, bold, italic); return context.Measure(text, bytes).cx; @@ -602,31 +661,25 @@ int UIWindow::TextWidth( // OFFSET: 0x00A84360 // FUNCTION: fn_17009 void UIWindow::DrawTextAt( - FontCache& fonts, - const TextLocale& locale, - int x, - int y, - const char* text, - int bytes, - int family, - int height, - std::uint32_t color, - unsigned char bold, + FontCache& fonts, const TextLocale& locale, int x, int y, const char* text, int bytes, int family, int height, std::uint32_t color, unsigned char bold, unsigned char italic ) { if (!bytes) { bytes = static_cast(std::strlen(text)); } + TextContext context(*this->geometry.surface, fonts, locale); context.SetFont(family, height, bold, italic); context.SetColor(color); context.Draw(x, y, text, bytes); } + // OFFSET: 0x00A7C470 // FUNCTION: fn_16944 void UIWindow::FlushPrimitives(RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd) { for (RenderPrimitive* primitive : this->m_overlayPrimitives) { queues.Submit(primitive, 513, depthAlpha, depthStart, depthEnd); } + this->m_overlayPrimitives.clear(); } diff --git a/Source/UI/UIWindow.h b/Source/UI/Window/UIWindow.h similarity index 65% rename from Source/UI/UIWindow.h rename to Source/UI/Window/UIWindow.h index 0305606..a582743 100644 --- a/Source/UI/UIWindow.h +++ b/Source/UI/Window/UIWindow.h @@ -1,9 +1,9 @@ -#ifndef RAGNAROK_SOURCE_UI_UIWINDOW_H -#define RAGNAROK_SOURCE_UI_UIWINDOW_H +#ifndef RAGNAROK_SOURCE_UI_WINDOW_UIWINDOW_H +#define RAGNAROK_SOURCE_UI_WINDOW_UIWINDOW_H -#include "Render/UIRPData.h" -#include "UI/WindowAncestry.h" -#include "UI/WindowGeometry.h" +#include "Render/Primitives/UIRPData.h" +#include "UI/Window/WindowAncestry.h" +#include "UI/Layout/WindowGeometry.h" #include #include @@ -20,7 +20,6 @@ struct BitmapImage; class FontCache; struct TextLocale; -// Borrowed original owners and noncontiguous manager fields; no second manager. struct UIWindowContext { RenderPrimitivePool& primitives; CRenderSystemBase& renderSystem; @@ -36,13 +35,9 @@ struct UIWindowContext { WindowAncestry*& reference_4F1D4; std::unordered_set& deferredDeletion; - // Mouse-dispatch deferred children are independent of modal-gated retirees. - // Keep set membership visible until every virtual destructor has run. void DestroyDeferredChildren(); }; -// UIWindow vtable, 53 slots. Names of unknown slots remain -// positional; their bodies/argument extents come from the original entries. class UIWindow : public UIRPData, public WindowAncestry { friend struct WindowDialogs; friend struct InputFocus; @@ -50,27 +45,27 @@ class UIWindow : public UIRPData, public WindowAncestry { public: explicit UIWindow(UIWindowContext& context, unsigned char cached); - ~UIWindow() override; // 0 - virtual void Resize(int width, int height); // 1 + ~UIWindow() override; + virtual void Resize(int width, int height); virtual bool Slot02(); virtual bool Slot03(); - virtual void Move(int x, int y); // 4 + virtual void Move(int x, int y); virtual bool Slot05(); virtual UIWindow* Slot06(); virtual bool Slot07(void* output); virtual bool Slot08(); - virtual bool CanHitTest(); // 9 + virtual bool CanHitTest(); virtual void Slot10(int argument1, int argument2, std::intptr_t argument3); virtual void Slot11(); virtual void Slot12(); virtual void Slot13(int argument1, int argument2); - virtual void Show(int visible); // 14 + virtual void Show(int visible); virtual void Slot15(int width, int height); virtual void Slot16(); - virtual void Grow(int width, int height); // 17 + virtual void Grow(int width, int height); virtual void Slot18(); virtual void Slot19(); - virtual void Paint(); // 20 + virtual void Paint(); virtual void Slot21(); virtual void Slot22(int width, int height); virtual void Slot23(); @@ -80,35 +75,28 @@ public: virtual void Slot27(int argument1, int argument2); virtual void Slot28(int argument1, int argument2); virtual void Slot29(int argument1, int argument2); - virtual void ResetCursor(int argument1, int argument2); // 30 + virtual void ResetCursor(int argument1, int argument2); virtual void Slot31(int argument1, int argument2); virtual void Slot32(int argument1, int argument2); virtual void Slot33(int argument1, int argument2); virtual void Slot34(int argument1, int argument2); virtual void Slot35(int argument); virtual void Slot36(); - virtual int SendMsg( - UIWindow* sender, - int message, - std::intptr_t argument1, - std::intptr_t argument2, - std::intptr_t argument3, - std::intptr_t argument4 - ); // 37 - virtual void Invalidate(); // 38 + virtual int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4); + virtual void Invalidate(); virtual void Slot39(); - virtual std::uint32_t Color(); // 40 - virtual bool Update(int redraw); // 41 + virtual std::uint32_t Color(); + virtual bool Update(int redraw); virtual bool Slot42(void* output); virtual void Slot43(); virtual std::vector Slot44(); - virtual void SetId(int value); // 45 + virtual void SetId(int value); virtual int Slot46(); virtual void Slot47(); virtual void Slot48(); - virtual RenderPrimitive* DrawPrimitive(); // 49 - virtual UIWindow* HitTest(int x, int y); // 50 - virtual void VisitChildren(); // 51 + virtual RenderPrimitive* DrawPrimitive(); + virtual UIWindow* HitTest(int x, int y); + virtual void VisitChildren(); virtual void Slot52(int argument); void AddChild(UIWindow* child); @@ -116,8 +104,7 @@ public: void DeleteChildren(); void ClearChildren(bool destroy); void RemoveChild(UIWindow* child, unsigned char destroy); - // Dirty this window, invoke Slot39, then recurse into children with nonzero - // visibility (not cached-parent bubbling). + void InvalidateChildren(); bool Contains(const UIWindow* window) const; UIWindow* FindUid(std::uint32_t uid); @@ -129,32 +116,13 @@ public: void SetSize(int width, int height); void DrawBitmap(int x, int y, const BitmapImage* image, bool transparent); void FillRegion(int x, int y, int width, int height, std::uint32_t color); - int TextWidth( - FontCache& fonts, - const TextLocale& locale, - const char* text, - unsigned bytes, - int family, - int height, - unsigned char bold, - unsigned char italic - ); + int TextWidth(FontCache& fonts, const TextLocale& locale, const char* text, unsigned bytes, int family, int height, unsigned char bold, unsigned char italic); void DrawTextAt( - FontCache& fonts, - const TextLocale& locale, - int x, - int y, - const char* text, - int bytes, - int family, - int height, - std::uint32_t color, - unsigned char bold, + FontCache& fonts, const TextLocale& locale, int x, int y, const char* text, int bytes, int family, int height, std::uint32_t color, unsigned char bold, unsigned char italic ); void FlushPrimitives(RenderQueues& queues, bool depthAlpha, float depthStart, float depthEnd); - // Source accessors for original direct reads by the colored text operation. bool HasTextBackground() const { return this->unknown_0044 != 0; } @@ -175,8 +143,7 @@ protected: /* 0074 */ std::uint32_t m_uid; /* 0078 */ unsigned char m_cached; /* 0079 */ unsigned char m_clip; - // Source-only dependency view after all original fields. Original size124; - // reconstructed x86 size128 includes this explicit owner pointer. + UIWindowContext* m_context; private: diff --git a/Source/UI/WindowAncestry.cpp b/Source/UI/Window/WindowAncestry.cpp similarity index 84% rename from Source/UI/WindowAncestry.cpp rename to Source/UI/Window/WindowAncestry.cpp index 92dbbd3..c06702f 100644 --- a/Source/UI/WindowAncestry.cpp +++ b/Source/UI/Window/WindowAncestry.cpp @@ -1,4 +1,4 @@ -#include "UI/WindowAncestry.h" +#include "UI/Window/WindowAncestry.h" // OFFSET: 0x00A79A90 WindowAncestry::WindowAncestry() : parent(nullptr) { @@ -12,31 +12,32 @@ bool WindowAncestry::IsDescendantOf(const WindowAncestry* ancestor) const { return true; } } + return false; } // OFFSET: 0x00A8C200 // FUNCTION: fn_17130 void ForgetWindowReferences( - WindowAncestry* removed, - WindowAncestry*& reference_019C, - WindowAncestry*& reference_01A0, - WindowAncestry*& reference_01B8, - WindowAncestry*& reference_0A30, + WindowAncestry* removed, WindowAncestry*& reference_019C, WindowAncestry*& reference_01A0, WindowAncestry*& reference_01B8, WindowAncestry*& reference_0A30, WindowAncestry*& reference_4F1D4 ) { if (reference_019C && (reference_019C == removed || reference_019C->IsDescendantOf(removed))) { reference_019C = nullptr; } + if (reference_01A0 && (reference_01A0 == removed || reference_01A0->IsDescendantOf(removed))) { reference_01A0 = nullptr; } + if (reference_01B8 && (reference_01B8 == removed || reference_01B8->IsDescendantOf(removed))) { reference_01B8 = nullptr; } + if (reference_0A30 && reference_0A30 == removed) { reference_0A30 = nullptr; } + if (reference_4F1D4 && (reference_4F1D4 == removed || reference_4F1D4->IsDescendantOf(removed))) { reference_4F1D4 = nullptr; } diff --git a/Source/UI/Window/WindowAncestry.h b/Source/UI/Window/WindowAncestry.h new file mode 100644 index 0000000..05e4127 --- /dev/null +++ b/Source/UI/Window/WindowAncestry.h @@ -0,0 +1,16 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWANCESTRY_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWANCESTRY_H + +struct WindowAncestry { + WindowAncestry* parent; + + WindowAncestry(); + bool IsDescendantOf(const WindowAncestry* ancestor) const; +}; + +void ForgetWindowReferences( + WindowAncestry* removed, WindowAncestry*& reference_019C, WindowAncestry*& reference_01A0, WindowAncestry*& reference_01B8, WindowAncestry*& reference_0A30, + WindowAncestry*& reference_4F1D4 +); + +#endif diff --git a/Source/UI/Window/WindowBorder.cpp b/Source/UI/Window/WindowBorder.cpp new file mode 100644 index 0000000..c529c8e --- /dev/null +++ b/Source/UI/Window/WindowBorder.cpp @@ -0,0 +1,46 @@ +#include "Render/DeviceContext/DeviceContext.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowBorder.h" + +#include + +namespace {} + +// OFFSET: 0x00A7C060 +// FUNCTION: fn_16942 +void DrawRoundedBorder(UIWindow& window, int x, int y, int width, int height, std::uint32_t color) { + window.FillRegion((x + 3), y, (width - 6), 1, color); + window.FillRegion((x + 3), ((y + height) - 1), (width - 6), 1, color); + window.FillRegion(x, (y + 3), 1, (height - 6), color); + window.FillRegion(((x + width) - 1), (y + 3), 1, (height - 6), color); + + window.FillRegion((x + 1), (y + 1), 2, 1, color); + window.FillRegion((x + 1), ((y + height) - 2), 2, 1, color); + window.FillRegion(((x + width) - 3), (y + 1), 2, 1, color); + window.FillRegion(((x + width) - 3), ((y + height) - 2), 2, 1, color); + + window.FillRegion((x + 1), (y + 2), 1, 1, color); + window.FillRegion((x + 1), ((y + height) - 3), 1, 1, color); + window.FillRegion(((x + width) - 2), (y + 2), 1, 1, color); + window.FillRegion(((x + width) - 2), ((y + height) - 3), 1, 1, color); +} + +// OFFSET: 0x00A7BC30 +// FUNCTION: fn_16937 +void DrawRectangleBorder(UIWindow& window, int x, int y, int width, int height, std::uint32_t color) { + const int left = std::max(x, 0); + const int top = std::max(y, 0); + const int right = (x + width); + const int bottom = (y + height); + RECT rectangle{left, top, std::min(window.geometry.width, right), std::min(window.geometry.height, (y + 1))}; + window.geometry.surface->Fill(&rectangle, color); + + rectangle = {left, top, std::min(window.geometry.width, (x + 1)), std::min(window.geometry.height, bottom)}; + window.geometry.surface->Fill(&rectangle, color); + + rectangle = {std::max((right - 1), 0), top, std::min(window.geometry.width, right), std::min(window.geometry.height, bottom)}; + window.geometry.surface->Fill(&rectangle, color); + + rectangle = {left, std::max((bottom - 1), 0), std::min(window.geometry.width, right), std::min(window.geometry.height, bottom)}; + window.geometry.surface->Fill(&rectangle, color); +} diff --git a/Source/UI/WindowBorder.h b/Source/UI/Window/WindowBorder.h similarity index 51% rename from Source/UI/WindowBorder.h rename to Source/UI/Window/WindowBorder.h index a2fdda0..50df059 100644 --- a/Source/UI/WindowBorder.h +++ b/Source/UI/Window/WindowBorder.h @@ -1,13 +1,12 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWBORDER_H -#define RAGNAROK_SOURCE_UI_WINDOWBORDER_H +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWBORDER_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWBORDER_H #include class UIWindow; void DrawRoundedBorder(UIWindow& window, int x, int y, int width, int height, std::uint32_t color); -// Ordered top/left/right/bottom strips. Signed clipping follows wrapping -// endpoint arithmetic; empty/inverted rectangles are still sent to the DC. + void DrawRectangleBorder(UIWindow& window, int x, int y, int width, int height, std::uint32_t color); #endif diff --git a/Source/UI/WindowDialogs.cpp b/Source/UI/Window/WindowDialogs.cpp similarity index 92% rename from Source/UI/WindowDialogs.cpp rename to Source/UI/Window/WindowDialogs.cpp index 2509b61..acfab75 100644 --- a/Source/UI/WindowDialogs.cpp +++ b/Source/UI/Window/WindowDialogs.cpp @@ -1,6 +1,6 @@ -#include "UI/UIMessageBox.h" -#include "UI/WindowDialogs.h" -#include "UI/WindowRetirement.h" +#include "UI/Window/UIMessageBox.h" +#include "UI/Window/WindowDialogs.h" +#include "UI/Window/WindowRetirement.h" // OFFSET: 0x00A91450 // FUNCTION: fn_17160 @@ -39,15 +39,7 @@ void WindowDialogs::RestoreInput() { // OFFSET: 0x00A901E0 // FUNCTION: fn_17153 int WindowDialogs::Confirm( - const char* text, - int type, - bool defaultAccept, - bool replace, - int timeout, - const char* caption, - int width, - int height, - unsigned char protect + const char* text, int type, bool defaultAccept, bool replace, int timeout, const char* caption, int width, int height, unsigned char protect ) { if (this->suppressed) { return 185; diff --git a/Source/UI/WindowDialogs.h b/Source/UI/Window/WindowDialogs.h similarity index 53% rename from Source/UI/WindowDialogs.h rename to Source/UI/Window/WindowDialogs.h index 55b890c..a8be090 100644 --- a/Source/UI/WindowDialogs.h +++ b/Source/UI/Window/WindowDialogs.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWDIALOGS_H -#define RAGNAROK_SOURCE_UI_WINDOWDIALOGS_H +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWDIALOGS_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWDIALOGS_H #include #include @@ -12,8 +12,6 @@ struct UIFrameContext; struct UIMessageBoxContext; struct WindowAncestry; -// The current mode's virtual frame operation at slot 4. A modal dialog runs -// the real frame operation; it does not replace it with a private event loop. class ModalFramePump { public: virtual void Frame() = 0; @@ -22,9 +20,6 @@ protected: ~ModalFramePump() = default; }; -// Borrowed UIWindowMgr state: result+4, suspended roots+368, rendered+380, -// capture+412, input+416, modal stack+424, alternate result+1140 and latest -// dialog+323948. No duplicate window manager or ownership container. struct WindowDialogs { UIWindowContext& windows; UIFrameContext& frames; @@ -43,17 +38,7 @@ struct WindowDialogs { UIWindow* Top() const; void RestoreInput(); - int Confirm( - const char* text, - int type, - bool defaultAccept, - bool replace, - int timeout, - const char* caption, - int width, - int height, - unsigned char protect - ); + int Confirm(const char* text, int type, bool defaultAccept, bool replace, int timeout, const char* caption, int width, int height, unsigned char protect); }; #endif diff --git a/Source/UI/WindowFrameUpdate.cpp b/Source/UI/Window/WindowFrameUpdate.cpp similarity index 78% rename from Source/UI/WindowFrameUpdate.cpp rename to Source/UI/Window/WindowFrameUpdate.cpp index 7ac240e..9aabc54 100644 --- a/Source/UI/WindowFrameUpdate.cpp +++ b/Source/UI/Window/WindowFrameUpdate.cpp @@ -1,7 +1,7 @@ -#include "Client/BrowserRegistry.h" -#include "Client/WebBrowser.h" -#include "UI/UIWindow.h" -#include "UI/WindowFrameUpdate.h" +#include "Client/Browser/BrowserRegistry.h" +#include "Client/Browser/WebBrowser.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowFrameUpdate.h" // OFFSET: 0x00AA26C0 // FUNCTION: fn_17215 @@ -18,6 +18,7 @@ void WindowFrameUpdate::Update() { if (this->browsers.browsers.empty()) { break; } + ++browser; } diff --git a/Source/UI/Window/WindowFrameUpdate.h b/Source/UI/Window/WindowFrameUpdate.h new file mode 100644 index 0000000..c58acc9 --- /dev/null +++ b/Source/UI/Window/WindowFrameUpdate.h @@ -0,0 +1,18 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWFRAMEUPDATE_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWFRAMEUPDATE_H + +#include +#include + +class UIWindow; +struct BrowserRegistry; + +struct WindowFrameUpdate { + std::list& rendered; + BrowserRegistry& browsers; + std::map& overlays; + + void Update(); +}; + +#endif diff --git a/Source/UI/Window/WindowManagerWindows.h b/Source/UI/Window/WindowManagerWindows.h new file mode 100644 index 0000000..eb7f21c --- /dev/null +++ b/Source/UI/Window/WindowManagerWindows.h @@ -0,0 +1,17 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWMANAGERWINDOWS_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWMANAGERWINDOWS_H + +class UIWindow; + +class WindowManagerWindows { +public: + virtual UIWindow* LookupWindow(int id) = 0; + virtual UIWindow* EnsureWindow(int id) = 0; + + virtual bool CloseWindow(int id) = 0; + +protected: + ~WindowManagerWindows() = default; +}; + +#endif diff --git a/Source/UI/WindowMouseHit.cpp b/Source/UI/Window/WindowMouseHit.cpp similarity index 77% rename from Source/UI/WindowMouseHit.cpp rename to Source/UI/Window/WindowMouseHit.cpp index 6abc695..52798bf 100644 --- a/Source/UI/WindowMouseHit.cpp +++ b/Source/UI/Window/WindowMouseHit.cpp @@ -1,13 +1,11 @@ -#include "Client/Mouse.h" -#include "UI/InputFocus.h" -#include "UI/UIDropDownBox.h" -#include "UI/UIWindow.h" -#include "UI/WindowCoordinates.h" -#include "UI/WindowManagerWindows.h" -#include "UI/WindowMouseHit.h" -#include "UI/WindowOrdering.h" - -#include +#include "Client/Input/Mouse.h" +#include "UI/Window/InputFocus.h" +#include "UI/Lists/UIDropDownBox.h" +#include "UI/Window/UIWindow.h" +#include "UI/Layout/WindowCoordinates.h" +#include "UI/Window/WindowManagerWindows.h" +#include "UI/Window/WindowMouseHit.h" +#include "UI/Window/WindowOrdering.h" // OFFSET: 0x00A91B30 // FUNCTION: fn_17168 @@ -17,16 +15,13 @@ UIWindow* WindowMouseHit::FindUid(std::uint32_t uid) { return found; } } + return nullptr; } // OFFSET: 0x00A91C70 // FUNCTION: fn_17171 UIWindow* WindowMouseHit::HitTest(int x, int y) { - // The reference keeps a pointer to the list sentinel's previous link; it - // never advances that link on rejection. EDI also becomes the hit result, - // so a miss retries the same top window with y=0. Do not replace this with - // conventional reverse traversal: a top window that keeps missing can loop. while (!this->rendered.empty()) { UIWindow* hit = this->rendered.back()->HitTest(x, y); y = static_cast(static_cast(reinterpret_cast(hit))); @@ -35,11 +30,12 @@ UIWindow* WindowMouseHit::HitTest(int x, int y) { this->current = hit->Uid(); if (this->previous != this->current) { hit->Slot47(); - // Enter callbacks may mutate the previous UID or rendered tree. + if (UIWindow* old = this->FindUid(this->previous)) { old->Slot48(); } } + return hit; } } @@ -58,6 +54,7 @@ UIWindow* WindowMouseHit::HitTest(int x, int y) { old->Slot48(); } } + return nullptr; } @@ -74,8 +71,8 @@ bool WindowMouseCapture::Dispatch() { int top; UIWindow* window = static_cast(this->capture); WindowScreenPosition(window, left, top); - const int localX = std::bit_cast(static_cast(x) - static_cast(left)); - const int localY = std::bit_cast(static_cast(y) - static_cast(top)); + const int localX = x - left; + const int localY = y - top; if (this->mouse.buttons[0] == 1) { UIWindow* root = window->Root(); @@ -112,17 +109,13 @@ bool WindowMouseCapture::Dispatch() { // OFFSET: 0x00AA4730 // FUNCTION: fn_17222 -// Modal filtering follows hit enter/leave callbacks. A miss retains hover; -// right release precedes left release. Close requests require the real manager. + int WindowMouseUncaptured::Dispatch() { const int x = this->mouse.x; const int y = this->mouse.y; UIWindow* window = this->hit.HitTest(x, y); - if ( - !this->modal.empty() && this->modal.back() && window && window != this->modal.back() && - !window->IsDescendantOf(this->modal.back()) - ) { + if (!this->modal.empty() && this->modal.back() && window && window != this->modal.back() && !window->IsDescendantOf(this->modal.back())) { window = nullptr; } @@ -136,8 +129,8 @@ int WindowMouseUncaptured::Dispatch() { int left; int top; WindowScreenPosition(window, left, top); - const int localX = std::bit_cast(static_cast(x) - static_cast(left)); - const int localY = std::bit_cast(static_cast(y) - static_cast(top)); + const int localX = x - left; + const int localY = y - top; if (this->mouse.buttons[0] == 4 && (this->doubleClickGate == 0 || this->alternateDoubleClickGate == 0)) { window->Slot26(localX, localY); @@ -219,8 +212,8 @@ int WindowMouseUncaptured::Dispatch() { int left; int top; WindowScreenPosition(static_cast(this->hover), left, top); - const int localX = std::bit_cast(static_cast(x) - static_cast(left)); - const int localY = std::bit_cast(static_cast(y) - static_cast(top)); + const int localX = x - left; + const int localY = y - top; static_cast(this->hover)->Slot27(localX, localY); static_cast(this->hover)->ResetCursor(localX, localY); } diff --git a/Source/UI/WindowMouseHit.h b/Source/UI/Window/WindowMouseHit.h similarity index 63% rename from Source/UI/WindowMouseHit.h rename to Source/UI/Window/WindowMouseHit.h index bea489c..104e558 100644 --- a/Source/UI/WindowMouseHit.h +++ b/Source/UI/Window/WindowMouseHit.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWMOUSEHIT_H -#define RAGNAROK_SOURCE_UI_WINDOWMOUSEHIT_H +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWMOUSEHIT_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWMOUSEHIT_H #include #include @@ -14,10 +14,6 @@ struct WindowOrdering; class WindowManagerWindows; struct WindowDropDown; -// Borrowed manager rendered list, overlay map and hover UID fields. Overlay -// hits deliberately bypass the rendered-window enter/leave transition. -// Observed rendered-list rejection retries the same top window with the hit -// pointer's low DWORD as y (zero on a miss); a persistent miss does not return. struct WindowMouseHit { std::list& rendered; std::map& overlays; @@ -28,7 +24,6 @@ struct WindowMouseHit { UIWindow* HitTest(int x, int y); }; -// Borrowed captured-window branch of mouse polling, not a second manager. struct WindowMouseCapture { WindowAncestry*& capture; WindowOrdering& ordering; @@ -41,8 +36,6 @@ struct WindowMouseCapture { bool Dispatch(); }; -// Uncaptured branch and its hover handoff. CloseWindow remains the real -// manager's complete operation; this view does not invent window factories. struct WindowMouseUncaptured { WindowMouseHit& hit; WindowOrdering& ordering; @@ -58,7 +51,7 @@ struct WindowMouseUncaptured { UIWindow* const& dismiss26; UIWindow* const& dismiss260; WindowAncestry*& hover; - // Manager refresh order: +3D4,+1E0,+1E4,+3FC,+3D8,+2C4,+4F170. + std::array refresh; const int& refreshGate; diff --git a/Source/UI/Window/WindowNotifications.h b/Source/UI/Window/WindowNotifications.h new file mode 100644 index 0000000..d9b56dc --- /dev/null +++ b/Source/UI/Window/WindowNotifications.h @@ -0,0 +1,12 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWNOTIFICATIONS_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWNOTIFICATIONS_H + +class WindowNotifications { +public: + virtual void Notify(int type, const char* text, unsigned color) = 0; + +protected: + ~WindowNotifications() = default; +}; + +#endif diff --git a/Source/UI/WindowOrdering.cpp b/Source/UI/Window/WindowOrdering.cpp similarity index 75% rename from Source/UI/WindowOrdering.cpp rename to Source/UI/Window/WindowOrdering.cpp index 45a2596..32ab1fd 100644 --- a/Source/UI/WindowOrdering.cpp +++ b/Source/UI/Window/WindowOrdering.cpp @@ -1,6 +1,6 @@ -#include "UI/UIWindow.h" -#include "UI/WindowManagerWindows.h" -#include "UI/WindowOrdering.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowManagerWindows.h" +#include "UI/Window/WindowOrdering.h" #include @@ -11,10 +11,7 @@ void WindowOrdering::Promote(UIWindow* window) { return; } - if ( - this->windows.LookupWindow(278) || this->windows.LookupWindow(4) || this->windows.LookupWindow(199) || - this->windows.LookupWindow(200) - ) { + if (this->windows.LookupWindow(278) || this->windows.LookupWindow(4) || this->windows.LookupWindow(199) || this->windows.LookupWindow(200)) { return; } @@ -27,9 +24,7 @@ void WindowOrdering::Promote(UIWindow* window) { } if (companion != -1) { - const auto entry = std::find_if(this->rendered.begin(), this->rendered.end(), [&](const UIWindow* value) { - return value->geometry.id == companion; - }); + const auto entry = std::find_if(this->rendered.begin(), this->rendered.end(), [&](const UIWindow* value) { return value->geometry.id == companion; }); if (entry != this->rendered.end()) { UIWindow* value = *entry; @@ -54,6 +49,7 @@ void WindowOrdering::InvalidateFrames(int& latch) { } latch = 1; + for (UIWindow* window : this->rendered) { if (window->Slot03()) { window->InvalidateChildren(); diff --git a/Source/UI/Window/WindowOrdering.h b/Source/UI/Window/WindowOrdering.h new file mode 100644 index 0000000..1447b2a --- /dev/null +++ b/Source/UI/Window/WindowOrdering.h @@ -0,0 +1,20 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWORDERING_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWORDERING_H + +#include + +class UIWindow; +class WindowManagerWindows; + +struct WindowOrdering { + std::list& rendered; + WindowManagerWindows& windows; + const int& modal; + UIWindow* const& modalWindow; + + void Promote(UIWindow* window); + + void InvalidateFrames(int& latch); +}; + +#endif diff --git a/Source/UI/WindowPolicy.cpp b/Source/UI/Window/WindowPolicy.cpp similarity index 89% rename from Source/UI/WindowPolicy.cpp rename to Source/UI/Window/WindowPolicy.cpp index 8798c47..c73718f 100644 --- a/Source/UI/WindowPolicy.cpp +++ b/Source/UI/Window/WindowPolicy.cpp @@ -1,4 +1,4 @@ -#include "UI/WindowPolicy.h" +#include "UI/Window/WindowPolicy.h" // OFFSET: 0x00A970E0 // FUNCTION: fn_17200 @@ -10,8 +10,10 @@ int WindowPolicy(const int* table, bool restricted, unsigned action, unsigned id } else if (action >= 8) { return 0; } + if (id <= 10040) { return table[8 * id + action]; } + return 0; } diff --git a/Source/UI/Window/WindowPolicy.h b/Source/UI/Window/WindowPolicy.h new file mode 100644 index 0000000..7980bc5 --- /dev/null +++ b/Source/UI/Window/WindowPolicy.h @@ -0,0 +1,6 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWPOLICY_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWPOLICY_H + +int WindowPolicy(const int* table, bool restricted, unsigned action, unsigned id); + +#endif diff --git a/Source/UI/WindowRegistration.cpp b/Source/UI/Window/WindowRegistration.cpp similarity index 90% rename from Source/UI/WindowRegistration.cpp rename to Source/UI/Window/WindowRegistration.cpp index 469ef77..2ccbe12 100644 --- a/Source/UI/WindowRegistration.cpp +++ b/Source/UI/Window/WindowRegistration.cpp @@ -1,5 +1,5 @@ -#include "UI/UIWindow.h" -#include "UI/WindowRegistration.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowRegistration.h" // OFFSET: 0x00A8B060 // FUNCTION: fn_17120 @@ -9,6 +9,7 @@ void WindowRegistration::Add(WindowAncestry* window) { return; } } + this->windows.push_back(window); } diff --git a/Source/UI/Window/WindowRegistration.h b/Source/UI/Window/WindowRegistration.h new file mode 100644 index 0000000..e211d29 --- /dev/null +++ b/Source/UI/Window/WindowRegistration.h @@ -0,0 +1,21 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWREGISTRATION_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWREGISTRATION_H + +#include + +struct WindowAncestry; + +struct WindowRegistration { + std::list windows; + + void Add(WindowAncestry* window); + void Remove(WindowAncestry* window); + + void InvalidateAll(); +}; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(WindowRegistration) == 8); +#endif + +#endif diff --git a/Source/UI/WindowRetirement.cpp b/Source/UI/Window/WindowRetirement.cpp similarity index 87% rename from Source/UI/WindowRetirement.cpp rename to Source/UI/Window/WindowRetirement.cpp index 33fa86e..a010e1a 100644 --- a/Source/UI/WindowRetirement.cpp +++ b/Source/UI/Window/WindowRetirement.cpp @@ -1,7 +1,7 @@ -#include "UI/SnapMgr.h" -#include "UI/UIWindow.h" -#include "UI/WindowRetirement.h" -#include "UI/WindowSnapping.h" +#include "UI/Layout/SnapMgr.h" +#include "UI/Window/UIWindow.h" +#include "UI/Window/WindowRetirement.h" +#include "UI/Layout/WindowSnapping.h" #include @@ -34,7 +34,6 @@ void WindowRetirement::Schedule(UIWindow* window) { // OFFSET: 0x00AA7250 // FUNCTION: fn_17237 void WindowRetirement::Destroy(UIWindow* window) { - // The original queries option141 before checking the pointer. const bool snappingEnabled = this->snapping.enabled; if (!window) { @@ -81,11 +80,7 @@ void WindowRetirement::DismissTransient(UIWindow*& transient) { // OFFSET: 0x00AA4730 // FUNCTION: fn_17222 void WindowRetirement::DrainPending( - const std::deque& modal, - UIWindow*& reference_4F16C, - WindowAncestry*& capture, - WindowAncestry*& input, - WindowAncestry*& hover + const std::deque& modal, UIWindow*& reference_4F16C, WindowAncestry*& capture, WindowAncestry*& input, WindowAncestry*& hover ) { if (!modal.empty() && modal.back()) { return; diff --git a/Source/UI/Window/WindowRetirement.h b/Source/UI/Window/WindowRetirement.h new file mode 100644 index 0000000..348d8b5 --- /dev/null +++ b/Source/UI/Window/WindowRetirement.h @@ -0,0 +1,31 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_WINDOWRETIREMENT_H +#define RAGNAROK_SOURCE_UI_WINDOW_WINDOWRETIREMENT_H + +#include +#include +#include + +class UIWindow; +struct WindowAncestry; +struct WindowSnapping; + +struct WindowRetirement { + std::list& rendered; + std::list& retired; + std::map& overlays; + WindowSnapping& snapping; + UIWindow*& reference_03D4; + UIWindow*& reference_03D8; + UIWindow*& reference_03DC; + UIWindow*& reference_01B8; + UIWindow*& reference_4F2AC; + + void Schedule(UIWindow* window); + void Destroy(UIWindow* window); + + void DismissTransient(UIWindow*& transient); + + void DrainPending(const std::deque& modal, UIWindow*& reference_4F16C, WindowAncestry*& capture, WindowAncestry*& input, WindowAncestry*& hover); +}; + +#endif diff --git a/Source/UI/WindowAncestry.h b/Source/UI/WindowAncestry.h deleted file mode 100644 index 2287abd..0000000 --- a/Source/UI/WindowAncestry.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWANCESTRY_H -#define RAGNAROK_SOURCE_UI_WINDOWANCESTRY_H - -// The parent field of UIWindow at +0x10. Source pointers refer to this parent -// subobject, not binary-layout-compatible pointers into the original image. -struct WindowAncestry { - WindowAncestry* parent; - - WindowAncestry(); - bool IsDescendantOf(const WindowAncestry* ancestor) const; -}; - -// Actual manager fields are noncontiguous. Keep their established locations -// explicit instead of inventing a second packed owner/global manager. -void ForgetWindowReferences( - WindowAncestry* removed, - WindowAncestry*& reference_019C, - WindowAncestry*& reference_01A0, - WindowAncestry*& reference_01B8, - WindowAncestry*& reference_0A30, - WindowAncestry*& reference_4F1D4 -); - -#endif diff --git a/Source/UI/WindowBorder.cpp b/Source/UI/WindowBorder.cpp deleted file mode 100644 index 901dd75..0000000 --- a/Source/UI/WindowBorder.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "Render/DeviceContext.h" -#include "UI/UIWindow.h" -#include "UI/WindowBorder.h" - -#include -#include - -namespace { - - int Add(int left, int right) { - return std::bit_cast(static_cast(left) + static_cast(right)); - } - -} - -// OFFSET: 0x00A7C060 -// FUNCTION: fn_16942 -void DrawRoundedBorder(UIWindow& window, int x, int y, int width, int height, std::uint32_t color) { - window.FillRegion(Add(x, 3), y, Add(width, -6), 1, color); - window.FillRegion(Add(x, 3), Add(Add(y, height), -1), Add(width, -6), 1, color); - window.FillRegion(x, Add(y, 3), 1, Add(height, -6), color); - window.FillRegion(Add(Add(x, width), -1), Add(y, 3), 1, Add(height, -6), color); - - window.FillRegion(Add(x, 1), Add(y, 1), 2, 1, color); - window.FillRegion(Add(x, 1), Add(Add(y, height), -2), 2, 1, color); - window.FillRegion(Add(Add(x, width), -3), Add(y, 1), 2, 1, color); - window.FillRegion(Add(Add(x, width), -3), Add(Add(y, height), -2), 2, 1, color); - - window.FillRegion(Add(x, 1), Add(y, 2), 1, 1, color); - window.FillRegion(Add(x, 1), Add(Add(y, height), -3), 1, 1, color); - window.FillRegion(Add(Add(x, width), -2), Add(y, 2), 1, 1, color); - window.FillRegion(Add(Add(x, width), -2), Add(Add(y, height), -3), 1, 1, color); -} - -// OFFSET: 0x00A7BC30 -// FUNCTION: fn_16937 -void DrawRectangleBorder(UIWindow& window, int x, int y, int width, int height, std::uint32_t color) { - const int left = std::max(x, 0); - const int top = std::max(y, 0); - const int right = Add(x, width); - const int bottom = Add(y, height); - RECT rectangle{left, top, std::min(window.geometry.width, right), std::min(window.geometry.height, Add(y, 1))}; - window.geometry.surface->Fill(&rectangle, color); - - rectangle = {left, top, std::min(window.geometry.width, Add(x, 1)), std::min(window.geometry.height, bottom)}; - window.geometry.surface->Fill(&rectangle, color); - - rectangle = { - std::max(Add(right, -1), 0), top, std::min(window.geometry.width, right), std::min(window.geometry.height, bottom) - }; - window.geometry.surface->Fill(&rectangle, color); - - rectangle = { - left, std::max(Add(bottom, -1), 0), std::min(window.geometry.width, right), std::min(window.geometry.height, bottom) - }; - window.geometry.surface->Fill(&rectangle, color); -} diff --git a/Source/UI/WindowCoordinates.h b/Source/UI/WindowCoordinates.h deleted file mode 100644 index c5e3909..0000000 --- a/Source/UI/WindowCoordinates.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWCOORDINATES_H -#define RAGNAROK_SOURCE_UI_WINDOWCOORDINATES_H - -class UIWindow; - -// Original 32-bit coordinate accumulation includes the window itself. -void WindowScreenPosition(const UIWindow* window, int& x, int& y); -// Writes all outputs zero first, then left/top/right/bottom in original order. -// Outputs may alias each other or the window geometry. -void WindowScreenBounds(const UIWindow* window, int& left, int& top, int& right, int& bottom); - -// Tests whether two [left, top, right, bottom] bounds rectangles overlap. -bool WindowBoundsOverlap(const int first[4], const int second[4]); - -#endif diff --git a/Source/UI/WindowFrameUpdate.h b/Source/UI/WindowFrameUpdate.h deleted file mode 100644 index ceac883..0000000 --- a/Source/UI/WindowFrameUpdate.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWFRAMEUPDATE_H -#define RAGNAROK_SOURCE_UI_WINDOWFRAMEUPDATE_H - -#include -#include - -class UIWindow; -struct BrowserRegistry; - -// Borrowed UIWindowMgr rendered list, browser registry and overlay map. Calls -// retain original live traversal: callbacks may append entries, and browser -// polling may empty the registry. No snapshot or implicit lifetime extension. -struct WindowFrameUpdate { - std::list& rendered; - BrowserRegistry& browsers; - std::map& overlays; - - void Update(); -}; - -#endif diff --git a/Source/UI/WindowManagerWindows.h b/Source/UI/WindowManagerWindows.h deleted file mode 100644 index 488e8c4..0000000 --- a/Source/UI/WindowManagerWindows.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWMANAGERWINDOWS_H -#define RAGNAROK_SOURCE_UI_WINDOWMANAGERWINDOWS_H - -class UIWindow; - -// Source boundary for UIWindowMgr lookup and factory. Concrete owner/factory must implement all required window types. -class WindowManagerWindows { -public: - virtual UIWindow* LookupWindow(int id) = 0; - virtual UIWindow* EnsureWindow(int id) = 0; - // Close operation, including modal and retirement policy. - virtual bool CloseWindow(int id) = 0; - -protected: - ~WindowManagerWindows() = default; -}; - -#endif diff --git a/Source/UI/WindowNotifications.h b/Source/UI/WindowNotifications.h deleted file mode 100644 index 62eab17..0000000 --- a/Source/UI/WindowNotifications.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWNOTIFICATIONS_H -#define RAGNAROK_SOURCE_UI_WINDOWNOTIFICATIONS_H - -// Source boundary for UIWindowMgr notification routing. -// Type 1 displays text; type 3 restores/shows the message window and sends -// its reset message. Implementations must retain those real owner operations. -class WindowNotifications { -public: - virtual void Notify(int type, const char* text, unsigned color) = 0; - -protected: - ~WindowNotifications() = default; -}; - -#endif diff --git a/Source/UI/WindowOrdering.h b/Source/UI/WindowOrdering.h deleted file mode 100644 index 9c5a149..0000000 --- a/Source/UI/WindowOrdering.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWORDERING_H -#define RAGNAROK_SOURCE_UI_WINDOWORDERING_H - -#include - -class UIWindow; -class WindowManagerWindows; - -// Original rendered-window list and modal policy remain owned by UIWindowMgr. -struct WindowOrdering { - std::list& rendered; - WindowManagerWindows& windows; - const int& modal; - UIWindow* const& modalWindow; - - void Promote(UIWindow* window); - // Borrowed manager+0x4FC latch. Set before virtual callbacks to suppress - // reentrant passes; only windows whose Slot03 returns true are invalidated. - void InvalidateFrames(int& latch); -}; - -#endif diff --git a/Source/UI/WindowPolicy.h b/Source/UI/WindowPolicy.h deleted file mode 100644 index d3d9420..0000000 --- a/Source/UI/WindowPolicy.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWPOLICY_H -#define RAGNAROK_SOURCE_UI_WINDOWPOLICY_H - -// Manager table+2612,8 words per ID, IDs0..10040 inclusive. -int WindowPolicy(const int* table, bool restricted, unsigned action, unsigned id); - -#endif diff --git a/Source/UI/WindowRegistration.h b/Source/UI/WindowRegistration.h deleted file mode 100644 index 4d7f8ae..0000000 --- a/Source/UI/WindowRegistration.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWREGISTRATION_H -#define RAGNAROK_SOURCE_UI_WINDOWREGISTRATION_H - -#include - -struct WindowAncestry; - -// UIWindowMgr's contiguous list at +0x18C. Borrowed windows; destruction -// releases list nodes only. This does not replace the manager or its owners. -struct WindowRegistration { - std::list windows; - - void Add(WindowAncestry* window); - void Remove(WindowAncestry* window); - // Entries are UIWindow parent subobjects; invalidates each, then releases - // every node. - void InvalidateAll(); -}; - -#if defined(_WIN32) && !defined(_WIN64) -static_assert(sizeof(WindowRegistration) == 8); -#endif - -#endif diff --git a/Source/UI/WindowRetirement.h b/Source/UI/WindowRetirement.h deleted file mode 100644 index c8dbbd6..0000000 --- a/Source/UI/WindowRetirement.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UI_WINDOWRETIREMENT_H -#define RAGNAROK_SOURCE_UI_WINDOWRETIREMENT_H - -#include -#include -#include - -class UIWindow; -struct WindowAncestry; -struct WindowSnapping; - -// Borrowed UIWindowMgr lists, overlay map, and direct window references. -struct WindowRetirement { - std::list& rendered; - std::list& retired; - std::map& overlays; - WindowSnapping& snapping; - UIWindow*& reference_03D4; - UIWindow*& reference_03D8; - UIWindow*& reference_03DC; - UIWindow*& reference_01B8; - UIWindow*& reference_4F2AC; - - void Schedule(UIWindow* window); - void Destroy(UIWindow* window); - // Transient window owner. Schedule clears dependent refs - // before appending; clear the transient pointer only after scheduling. - void DismissTransient(UIWindow*& transient); - // A nonnull modal top postpones destruction. Keep all pending nodes through callbacks. - void DrainPending( - const std::deque& modal, - UIWindow*& reference_4F16C, - WindowAncestry*& capture, - WindowAncestry*& input, - WindowAncestry*& hover - ); -}; - -#endif diff --git a/Source/Utility/AsyncDiagnostic.cpp b/Source/Utility/Async/AsyncDiagnostic.cpp similarity index 94% rename from Source/Utility/AsyncDiagnostic.cpp rename to Source/Utility/Async/AsyncDiagnostic.cpp index 43243e3..e6cec1a 100644 --- a/Source/Utility/AsyncDiagnostic.cpp +++ b/Source/Utility/Async/AsyncDiagnostic.cpp @@ -1,4 +1,4 @@ -#include "Utility/AsyncDiagnostic.h" +#include "Utility/Async/AsyncDiagnostic.h" #include @@ -15,9 +15,11 @@ AsyncDiagnostic& AsyncDiagnostic::MoveFrom(AsyncDiagnostic& other) { if (&this->message != &other.message) { this->message = std::move(other.message); } + if (&this->file != &other.file) { this->file = std::move(other.file); } + this->line = other.line; return *this; } diff --git a/Source/Utility/AsyncDiagnostic.h b/Source/Utility/Async/AsyncDiagnostic.h similarity index 62% rename from Source/Utility/AsyncDiagnostic.h rename to Source/Utility/Async/AsyncDiagnostic.h index 36ae918..663f811 100644 --- a/Source/Utility/AsyncDiagnostic.h +++ b/Source/Utility/Async/AsyncDiagnostic.h @@ -1,11 +1,9 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_ASYNCDIAGNOSTIC_H -#define RAGNAROK_SOURCE_UTILITY_ASYNCDIAGNOSTIC_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_ASYNCDIAGNOSTIC_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_ASYNCDIAGNOSTIC_H #include #include -// Reconstructed semantic name; original non-polymorphic type name unavailable. -// This stores original diagnostic state; it does not add a logging backend. struct AsyncDiagnostic { AsyncDiagnostic(const bool* success, std::string* message, const char* file, const std::uint32_t* line); ~AsyncDiagnostic(); diff --git a/Source/Utility/NAsyncWork.cpp b/Source/Utility/Async/NAsyncWork.cpp similarity index 91% rename from Source/Utility/NAsyncWork.cpp rename to Source/Utility/Async/NAsyncWork.cpp index 1c26a28..fa0637f 100644 --- a/Source/Utility/NAsyncWork.cpp +++ b/Source/Utility/Async/NAsyncWork.cpp @@ -1,4 +1,4 @@ -#include "Utility/NAsyncWork.h" +#include "Utility/Async/NAsyncWork.h" #include @@ -31,8 +31,7 @@ NAsyncWorkPtr::NAsyncWorkPtr(NAsyncWorkPtr& other) : m_manager(other.m_manager), // OFFSET: 0x00731AC0 // FUNCTION: fn_07560 -NAsyncWorkPtr::NAsyncWorkPtr(NRecycleObjectPoolMgr* manager, std::string poolName) - : m_manager(manager), m_work(nullptr) { +NAsyncWorkPtr::NAsyncWorkPtr(NRecycleObjectPoolMgr* manager, std::string poolName) : m_manager(manager), m_work(nullptr) { if (manager) { this->m_work = static_cast(manager->Acquire(std::move(poolName))); } diff --git a/Source/Utility/NAsyncWork.h b/Source/Utility/Async/NAsyncWork.h similarity index 75% rename from Source/Utility/NAsyncWork.h rename to Source/Utility/Async/NAsyncWork.h index d4179c6..a8a5a27 100644 --- a/Source/Utility/NAsyncWork.h +++ b/Source/Utility/Async/NAsyncWork.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NASYNCWORK_H -#define RAGNAROK_SOURCE_UTILITY_NASYNCWORK_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_NASYNCWORK_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_NASYNCWORK_H -#include "Utility/NRecycleObjectPoolMgr.h" +#include "Utility/Async/NRecycleObjectPoolMgr.h" class NAsyncWork : public NRecycleObject { public: @@ -10,7 +10,6 @@ public: virtual bool Execute(); virtual void Complete(); - // Host source accessors for fields read directly by original queue code. std::pair GroupKey() const { return {m_group, m_key}; } @@ -27,7 +26,6 @@ public: NAsyncWorkPtr(NRecycleObjectPoolMgr* manager, std::string poolName); virtual ~NAsyncWorkPtr(); - // Host source accessor for the original direct pointer field access. NAsyncWork* Get() const { return this->m_work; } diff --git a/Source/Utility/NAsyncWorkMgr.cpp b/Source/Utility/Async/NAsyncWorkMgr.cpp similarity index 93% rename from Source/Utility/NAsyncWorkMgr.cpp rename to Source/Utility/Async/NAsyncWorkMgr.cpp index 1e907d6..e172a8f 100644 --- a/Source/Utility/NAsyncWorkMgr.cpp +++ b/Source/Utility/Async/NAsyncWorkMgr.cpp @@ -1,11 +1,10 @@ -#include "Utility/NAsyncWorkMgr.h" +#include "Utility/Async/NAsyncWorkMgr.h" #include // OFFSET: 0x007313C0 // FUNCTION: fn_07547 -NAsyncWorkMgr::NAsyncWorkMgr(std::uint32_t workers) - : m_enabled(false), m_workerCount(workers), m_requests(nullptr), m_responses(nullptr) { +NAsyncWorkMgr::NAsyncWorkMgr(std::uint32_t workers) : m_enabled(false), m_workerCount(workers), m_requests(nullptr), m_responses(nullptr) { if (this->Initialize(workers)) { this->m_enabled = true; } @@ -19,13 +18,16 @@ NAsyncWorkMgr::~NAsyncWorkMgr() { for (auto worker = this->m_workers.begin(); worker != this->m_workers.end(); ++worker) { (*worker)->Stop(); } + for (auto worker = this->m_workers.begin(); worker != this->m_workers.end(); ++worker) { delete *worker; } + if (this->m_requests) { delete this->m_requests; this->m_requests = nullptr; } + if (this->m_responses) { delete this->m_responses; this->m_responses = nullptr; @@ -39,6 +41,7 @@ void NAsyncWorkMgr::DestroyQueues() { delete this->m_requests; this->m_requests = nullptr; } + if (this->m_responses) { delete this->m_responses; this->m_responses = nullptr; @@ -52,31 +55,38 @@ bool NAsyncWorkMgr::Initialize(std::uint32_t workers) { if (!this->m_requests) { return false; } + if (!this->m_requests->m_enabled) { delete this->m_requests; this->m_requests = nullptr; return false; } + this->m_responses = new (std::nothrow) NAsyncWorkResponseQueue; if (!this->m_responses) { return false; } + if (!this->m_responses->m_enabled) { delete this->m_responses; this->m_responses = nullptr; return false; } + for (std::uint32_t i = 0; i < workers; ++i) { NAsyncWorkThread* worker = new (std::nothrow) NAsyncWorkThread(this->m_requests, this->m_responses); if (!worker) { return false; } + if (!worker->m_registered) { delete worker; return false; } + this->m_workers.push_back(worker); } + return true; } @@ -88,6 +98,7 @@ void NAsyncWorkMgr::Update(std::uint32_t maximum) { if (!response.valid) { break; } + if (response.work.Get()) { response.work.Get()->Complete(); } @@ -108,6 +119,7 @@ bool NAsyncWorkMgr::Start() { return false; } } + return true; } diff --git a/Source/Utility/NAsyncWorkMgr.h b/Source/Utility/Async/NAsyncWorkMgr.h similarity index 81% rename from Source/Utility/NAsyncWorkMgr.h rename to Source/Utility/Async/NAsyncWorkMgr.h index 6687a5f..a73350d 100644 --- a/Source/Utility/NAsyncWorkMgr.h +++ b/Source/Utility/Async/NAsyncWorkMgr.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NASYNCWORKMGR_H -#define RAGNAROK_SOURCE_UTILITY_NASYNCWORKMGR_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_NASYNCWORKMGR_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_NASYNCWORKMGR_H -#include "Utility/NAsyncWorkThread.h" +#include "Utility/Async/NAsyncWorkThread.h" #include #include diff --git a/Source/Utility/NAsyncWorkQueue.cpp b/Source/Utility/Async/NAsyncWorkQueue.cpp similarity index 97% rename from Source/Utility/NAsyncWorkQueue.cpp rename to Source/Utility/Async/NAsyncWorkQueue.cpp index b71fac6..f1fe85d 100644 --- a/Source/Utility/NAsyncWorkQueue.cpp +++ b/Source/Utility/Async/NAsyncWorkQueue.cpp @@ -1,5 +1,5 @@ -#include "Utility/NAsyncWorkQueue.h" -#include "Utility/NSyncObject.h" +#include "Utility/Async/NAsyncWorkQueue.h" +#include "Utility/Threading/NSyncObject.h" #include @@ -20,6 +20,7 @@ NAsyncWorkRequestQueue::~NAsyncWorkRequestQueue() { CloseHandle(this->m_semaphore); this->m_semaphore = nullptr; } + DeleteCriticalSection(&this->m_criticalSection); } @@ -29,20 +30,25 @@ NAsyncWorkPtr NAsyncWorkRequestQueue::Pop() { NSyncObject held(&this->m_criticalSection); if (!this->m_pending.empty()) { unsigned examined = 1; + for (auto work = this->m_pending.begin(); work != this->m_pending.end(); ++work) { if (examined > 40) { break; } + auto key = work->Get()->GroupKey(); if (std::find(this->m_active.begin(), this->m_active.end(), key) == this->m_active.end()) { this->m_active.push_back(key); NAsyncWorkPtr result(*work); this->m_pending.erase(work); + return result; } + ++examined; } } + ++this->m_waiting; return NAsyncWorkPtr(nullptr, ""); } @@ -71,6 +77,7 @@ void NAsyncWorkRequestQueue::Complete(std::uint32_t group, std::uint32_t key) { if (active != this->m_active.end()) { this->m_active.erase(active); } + if (this->m_waiting) { --this->m_waiting; ReleaseSemaphore(this->m_semaphore, 1, nullptr); @@ -104,6 +111,7 @@ NAsyncWorkResponse NAsyncWorkResponseQueue::Pop() { if (this->m_pending.empty()) { return {false, NAsyncWorkPtr(nullptr, "")}; } + NAsyncWorkPtr work(this->m_pending.front()); this->m_pending.pop_front(); return {true, work}; diff --git a/Source/Utility/NAsyncWorkQueue.h b/Source/Utility/Async/NAsyncWorkQueue.h similarity index 89% rename from Source/Utility/NAsyncWorkQueue.h rename to Source/Utility/Async/NAsyncWorkQueue.h index f0e0c31..c2fc89c 100644 --- a/Source/Utility/NAsyncWorkQueue.h +++ b/Source/Utility/Async/NAsyncWorkQueue.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NASYNCWORKQUEUE_H -#define RAGNAROK_SOURCE_UTILITY_NASYNCWORKQUEUE_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_NASYNCWORKQUEUE_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_NASYNCWORKQUEUE_H -#include "Utility/NAsyncWork.h" +#include "Utility/Async/NAsyncWork.h" #include #include diff --git a/Source/Utility/NAsyncWorkThread.cpp b/Source/Utility/Async/NAsyncWorkThread.cpp similarity index 85% rename from Source/Utility/NAsyncWorkThread.cpp rename to Source/Utility/Async/NAsyncWorkThread.cpp index 35005c8..b776383 100644 --- a/Source/Utility/NAsyncWorkThread.cpp +++ b/Source/Utility/Async/NAsyncWorkThread.cpp @@ -1,4 +1,4 @@ -#include "Utility/NAsyncWorkThread.h" +#include "Utility/Async/NAsyncWorkThread.h" // OFFSET: 0x00732980 // FUNCTION: fn_07576 @@ -13,8 +13,6 @@ NAsyncWorkThread::NAsyncWorkThread(NAsyncWorkRequestQueue* requests, NAsyncWorkR // OFFSET: 0x00732B40 // FUNCTION: fn_07581 NAsyncWorkThread::~NAsyncWorkThread() { - // Original ownership requires Stop before destruction: the message queue is - // destroyed before NThread's base destructor performs its own state check. g_messageMgr->Unregister(this->m_objectId, static_cast(this)); } @@ -27,7 +25,6 @@ void NAsyncWorkThread::Receive(std::uint64_t argument, std::uint32_t id) { // OFFSET: 0x00732C20 // FUNCTION: fn_07583 void NAsyncWorkThread::RequestStop() { - // Pushes low/high argument 0x50000/0, then message ID zero. this->m_messages.Push(0x50000, 0); } @@ -52,7 +49,7 @@ unsigned NAsyncWorkThread::Run() { if (ready == WAIT_OBJECT_0) { NMessage message; this->m_messages.Pop(&message); - // Original tests argumentLow, not message ID, for the stop token. + if (message.valid && message.argumentLow == 0x50000) { return 0; } @@ -65,6 +62,7 @@ unsigned NAsyncWorkThread::Run() { } else { this->m_responses->Push(work); } + this->m_requests->Complete(group.first, group.second); } } diff --git a/Source/Utility/NAsyncWorkThread.h b/Source/Utility/Async/NAsyncWorkThread.h similarity index 68% rename from Source/Utility/NAsyncWorkThread.h rename to Source/Utility/Async/NAsyncWorkThread.h index af624f8..d32be30 100644 --- a/Source/Utility/NAsyncWorkThread.h +++ b/Source/Utility/Async/NAsyncWorkThread.h @@ -1,11 +1,11 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NASYNCWORKTHREAD_H -#define RAGNAROK_SOURCE_UTILITY_NASYNCWORKTHREAD_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_NASYNCWORKTHREAD_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_NASYNCWORKTHREAD_H -#include "Utility/NAsyncWorkQueue.h" -#include "Utility/NMessageMgr.h" -#include "Utility/NMessageQueue.h" -#include "Utility/NObject.h" -#include "Utility/NThread.h" +#include "Utility/Async/NAsyncWorkQueue.h" +#include "Utility/Async/NMessageMgr.h" +#include "Utility/Async/NMessageQueue.h" +#include "Utility/Async/NObject.h" +#include "Utility/Threading/NThread.h" class NAsyncWorkThread : public NObject, public NInter, public NThread { friend class NAsyncWorkMgr; diff --git a/Source/Utility/NMessageMgr.cpp b/Source/Utility/Async/NMessageMgr.cpp similarity index 92% rename from Source/Utility/NMessageMgr.cpp rename to Source/Utility/Async/NMessageMgr.cpp index 44089e8..804b9aa 100644 --- a/Source/Utility/NMessageMgr.cpp +++ b/Source/Utility/Async/NMessageMgr.cpp @@ -1,5 +1,5 @@ -#include "Utility/NMessageMgr.h" -#include "Utility/NSyncObject.h" +#include "Utility/Async/NMessageMgr.h" +#include "Utility/Threading/NSyncObject.h" #include @@ -31,11 +31,13 @@ bool NMessageMgr::Initialize() { if (!g_messageMgr) { return false; } + if (!g_messageMgr->m_enabled) { delete g_messageMgr; g_messageMgr = nullptr; return false; } + return true; } @@ -63,7 +65,7 @@ bool NMessageMgr::Send(std::uint32_t objectId, std::uint64_t argument, std::uint if (object == this->m_objects.end()) { return false; } - // Original dispatch retains the recursive critical section across the callback. + object->second->Receive(argument, id); return true; } diff --git a/Source/Utility/NMessageMgr.h b/Source/Utility/Async/NMessageMgr.h similarity index 89% rename from Source/Utility/NMessageMgr.h rename to Source/Utility/Async/NMessageMgr.h index 211069b..0f36550 100644 --- a/Source/Utility/NMessageMgr.h +++ b/Source/Utility/Async/NMessageMgr.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NMESSAGEMGR_H -#define RAGNAROK_SOURCE_UTILITY_NMESSAGEMGR_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_NMESSAGEMGR_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_NMESSAGEMGR_H #include #include diff --git a/Source/Utility/NMessageQueue.cpp b/Source/Utility/Async/NMessageQueue.cpp similarity index 84% rename from Source/Utility/NMessageQueue.cpp rename to Source/Utility/Async/NMessageQueue.cpp index 7cf0cff..74df2da 100644 --- a/Source/Utility/NMessageQueue.cpp +++ b/Source/Utility/Async/NMessageQueue.cpp @@ -1,10 +1,10 @@ -#include "Utility/NMessageQueue.h" -#include "Utility/NSyncObject.h" +#include "Utility/Async/NMessageQueue.h" +#include "Utility/Threading/NSyncObject.h" // OFFSET: 0x00736340 NMessageQueue::NMessageQueue() : m_semaphore(nullptr), m_enabled(false) { InitializeCriticalSection(&this->m_criticalSection); - // The original passes the address of an empty string, not a null name. + this->m_semaphore = CreateSemaphoreA(nullptr, 0, 0x7FFFFFFF, ""); if (this->m_semaphore) { this->m_enabled = true; @@ -20,6 +20,7 @@ NMessageQueue::~NMessageQueue() { CloseHandle(this->m_semaphore); this->m_semaphore = nullptr; } + DeleteCriticalSection(&this->m_criticalSection); } @@ -40,6 +41,7 @@ NMessage* NMessageQueue::Pop(NMessage* message) { message->argumentLow = 0; message->valid = false; } + return message; } @@ -54,7 +56,5 @@ void NMessageQueue::Push(std::uint64_t argument, std::uint32_t id) { // OFFSET: 0x00736650 // FUNCTION: fn_07623 void NMessageQueue::Clear() { - // Original clear tears down deque storage without acquiring the lock or - // draining semaphore count; preserve that caller synchronization contract. std::deque().swap(this->m_messages); } diff --git a/Source/Utility/NMessageQueue.h b/Source/Utility/Async/NMessageQueue.h similarity index 76% rename from Source/Utility/NMessageQueue.h rename to Source/Utility/Async/NMessageQueue.h index 0d8de34..04429a8 100644 --- a/Source/Utility/NMessageQueue.h +++ b/Source/Utility/Async/NMessageQueue.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NMESSAGEQUEUE_H -#define RAGNAROK_SOURCE_UTILITY_NMESSAGEQUEUE_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_NMESSAGEQUEUE_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_NMESSAGEQUEUE_H #include #include #include -// Reconstructed result name; original pop writes these three words then valid. struct NMessage { std::uint32_t id; std::uint32_t argumentHigh; @@ -13,7 +12,6 @@ struct NMessage { bool valid; }; -// Original RTTI class; field and operation names are reconstructed. class NMessageQueue { friend class NAsyncWorkThread; diff --git a/Source/Utility/NObject.cpp b/Source/Utility/Async/NObject.cpp similarity index 89% rename from Source/Utility/NObject.cpp rename to Source/Utility/Async/NObject.cpp index 32729ae..558f36c 100644 --- a/Source/Utility/NObject.cpp +++ b/Source/Utility/Async/NObject.cpp @@ -1,11 +1,9 @@ -#include "Utility/NObject.h" +#include "Utility/Async/NObject.h" namespace { - // STATIC: 0x0138D3F0 // GLOBAL: gl_24362 std::uint32_t s_nextObjectId; - } // OFFSET: 0x007369B0 diff --git a/Source/Utility/NObject.h b/Source/Utility/Async/NObject.h similarity index 58% rename from Source/Utility/NObject.h rename to Source/Utility/Async/NObject.h index 904bdc8..3e6c75f 100644 --- a/Source/Utility/NObject.h +++ b/Source/Utility/Async/NObject.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NOBJECT_H -#define RAGNAROK_SOURCE_UTILITY_NOBJECT_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_NOBJECT_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_NOBJECT_H #include -// Original class identity established by RTTI. ID field name reconstructed. class NObject { public: NObject(); diff --git a/Source/Utility/NRecycleObject.cpp b/Source/Utility/Async/NRecycleObject.cpp similarity index 88% rename from Source/Utility/NRecycleObject.cpp rename to Source/Utility/Async/NRecycleObject.cpp index 2429684..3de4176 100644 --- a/Source/Utility/NRecycleObject.cpp +++ b/Source/Utility/Async/NRecycleObject.cpp @@ -1,4 +1,4 @@ -#include "Utility/NRecycleObject.h" +#include "Utility/Async/NRecycleObject.h" // OFFSET: 0x005B9E50 // FUNCTION: fn_03440 diff --git a/Source/Utility/NRecycleObject.h b/Source/Utility/Async/NRecycleObject.h similarity index 84% rename from Source/Utility/NRecycleObject.h rename to Source/Utility/Async/NRecycleObject.h index 4762b28..3e72e48 100644 --- a/Source/Utility/NRecycleObject.h +++ b/Source/Utility/Async/NRecycleObject.h @@ -1,7 +1,7 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NRECYCLEOBJECT_H -#define RAGNAROK_SOURCE_UTILITY_NRECYCLEOBJECT_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_NRECYCLEOBJECT_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_NRECYCLEOBJECT_H -#include "Utility/NSyncObject.h" +#include "Utility/Threading/NSyncObject.h" #include #include @@ -35,9 +35,6 @@ public: virtual ~NRecycleObjectPoolInter(); }; -// Family established by multiple RTTI specializations and matching operations. -// Address tags below identify the observed account-data-load specialization; -// they do not claim original addresses for unobserved template arguments. template class NRecycleObjectPool : public NRecycleObjectPoolInter { public: // OFFSET: 0x00575AC0 @@ -83,7 +80,7 @@ public: if (object) { auto owned = std::find(this->m_objects.begin(), this->m_objects.end(), object); if (owned != this->m_objects.end()) { - // The original does not reject duplicate releases. + this->m_free.push_back(*owned); } } diff --git a/Source/Utility/NRecycleObjectPoolMgr.cpp b/Source/Utility/Async/NRecycleObjectPoolMgr.cpp similarity index 86% rename from Source/Utility/NRecycleObjectPoolMgr.cpp rename to Source/Utility/Async/NRecycleObjectPoolMgr.cpp index 4ed6d09..2d0e78e 100644 --- a/Source/Utility/NRecycleObjectPoolMgr.cpp +++ b/Source/Utility/Async/NRecycleObjectPoolMgr.cpp @@ -1,18 +1,20 @@ -#include "Utility/NRecycleObjectPoolMgr.h" +#include "Utility/Async/NRecycleObjectPoolMgr.h" // OFFSET: 0x00736A10 // FUNCTION: fn_07631 std::size_t NRecycleObjectPoolMgr::NameHash::operator()(const std::string& name) const { std::uint32_t hash = 2166136261; + for (unsigned char byte : name) { hash = 16777619 * (hash ^ byte); } + std::uint32_t value = hash & 0x7FFFFFFF; - std::int32_t reduced = - static_cast(16807 * (value % 127773)) - static_cast(2836 * (value / 127773)); + std::int32_t reduced = static_cast(16807 * (value % 127773)) - static_cast(2836 * (value / 127773)); if (reduced < 0) { reduced += 0x7FFFFFFF; } + return static_cast(reduced); } @@ -34,6 +36,7 @@ NRecycleObject* NRecycleObjectPoolMgr::Acquire(std::string poolName) { if (pool == this->m_pools.end()) { return nullptr; } + return pool->second->Acquire(); } diff --git a/Source/Utility/NRecycleObjectPoolMgr.h b/Source/Utility/Async/NRecycleObjectPoolMgr.h similarity index 58% rename from Source/Utility/NRecycleObjectPoolMgr.h rename to Source/Utility/Async/NRecycleObjectPoolMgr.h index 88bc1db..1aef1ce 100644 --- a/Source/Utility/NRecycleObjectPoolMgr.h +++ b/Source/Utility/Async/NRecycleObjectPoolMgr.h @@ -1,13 +1,11 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NRECYCLEOBJECTPOOLMGR_H -#define RAGNAROK_SOURCE_UTILITY_NRECYCLEOBJECTPOOLMGR_H +#ifndef RAGNAROK_SOURCE_UTILITY_ASYNC_NRECYCLEOBJECTPOOLMGR_H +#define RAGNAROK_SOURCE_UTILITY_ASYNC_NRECYCLEOBJECTPOOLMGR_H -#include "Utility/NRecycleObject.h" +#include "Utility/Async/NRecycleObject.h" #include #include -// Original RTTI class. Pool registration is performed by derived managers; -// the base destroys container nodes, not the registered pool objects. class NRecycleObjectPoolMgr { public: NRecycleObjectPoolMgr(); @@ -17,8 +15,7 @@ public: protected: struct NameHash { - // Original hash traits retain one byte before the load-factor float; - // this is library trait state, not an invented application field. + std::uint8_t unknown_0000 = 0; std::size_t operator()(const std::string& name) const; }; diff --git a/Source/Utility/Base64.cpp b/Source/Utility/Base64.cpp index 01f9302..84db0dd 100644 --- a/Source/Utility/Base64.cpp +++ b/Source/Utility/Base64.cpp @@ -9,18 +9,23 @@ namespace { if (value >= 'A' && value <= 'Z') { return value - 'A'; } + if (value >= 'a' && value <= 'z') { return value - 'a' + 26; } + if (value >= '0' && value <= '9') { return value - '0' + 52; } + if (value == '+' || value == '-') { return 62; } + if (value == '/' || value == '_') { return 63; } + return value; } } @@ -45,12 +50,15 @@ std::string DecodeBase64(std::string encoded, bool removeLinebreaks) { if (encoded.empty()) { return {}; } + if (removeLinebreaks) { encoded.erase(std::remove(encoded.begin(), encoded.end(), '\n'), encoded.end()); return DecodeBase64(encoded, false); } + std::string decoded; decoded.reserve(encoded.size() / 4 * 3); + for (std::size_t pos = 0; pos < encoded.size(); pos += 4) { unsigned second = Position(encoded[pos + 1]); decoded.push_back(static_cast((Position(encoded[pos]) << 2) + ((second >> 4) & 3))); @@ -62,5 +70,6 @@ std::string DecodeBase64(std::string encoded, bool removeLinebreaks) { } } } + return decoded; } diff --git a/Source/Utility/Base64.h b/Source/Utility/Base64.h index cdb799b..b5f41f6 100644 --- a/Source/Utility/Base64.h +++ b/Source/Utility/Base64.h @@ -3,8 +3,6 @@ #include -// Recovered decoder resembles cpp-base64, but original invalid-character -// passthrough and unchecked indexing differ from current upstream. std::string InsertLinebreaks(std::string text, unsigned int distance); std::string DecodeBase64(std::string encoded, bool removeLinebreaks = false); diff --git a/Source/Utility/GroupedInteger.h b/Source/Utility/GroupedInteger.h deleted file mode 100644 index 6188309..0000000 --- a/Source/Utility/GroupedInteger.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_GROUPEDINTEGER_H -#define RAGNAROK_SOURCE_UTILITY_GROUPEDINTEGER_H - -#include - -// Original formatting preserves its trailing-character truncation policy. -// output must have capacity bytes; nonpositive capacity leaves it untouched. -char* FormatGroupedInteger(int value, char* output, int capacity); -char* FormatGroupedInteger(std::int64_t value, char* output, int capacity); - -const char* ReverseFindChar(const char* text, char target); - -#endif diff --git a/Source/Utility/GuidParse.cpp b/Source/Utility/GuidParse.cpp index 48436e3..b422845 100644 --- a/Source/Utility/GuidParse.cpp +++ b/Source/Utility/GuidParse.cpp @@ -6,14 +6,13 @@ namespace { // OFFSET: 0x00AFA440 // FUNCTION: fn_18290 - // Scalar %X conversions need no additional destination-length arguments. + int Scan(const char* text, std::size_t bytes, const char* format, ...) { va_list arguments; va_start(arguments, format); - const int count = __stdio_common_vsscanf( - _CRT_INTERNAL_LOCAL_SCANF_OPTIONS | _CRT_INTERNAL_SCANF_SECURECRT, text, bytes, format, nullptr, arguments - ); + const int count = __stdio_common_vsscanf(_CRT_INTERNAL_LOCAL_SCANF_OPTIONS | _CRT_INTERNAL_SCANF_SECURECRT, text, bytes, format, nullptr, arguments); va_end(arguments); + return count; } } @@ -21,11 +20,10 @@ namespace { // OFFSET: 0x00AF7610 // FUNCTION: fn_18260 int ParseGuid(const char* text, std::size_t bytes, GUID& output, bool braced) { - const char* format = braced ? "{%8X-%4hX-%4hX-%2hhX%2hhX-%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX}" - : "%8X-%4hX-%4hX-%2hhX%2hhX-%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX"; + const char* format = braced ? "{%8X-%4hX-%4hX-%2hhX%2hhX-%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX}" : "%8X-%4hX-%4hX-%2hhX%2hhX-%2hhX%2hhX%2hhX%2hhX%2hhX%2hhX"; const int count = Scan( - text, bytes, format, &output.Data1, &output.Data2, &output.Data3, &output.Data4[0], &output.Data4[1], - &output.Data4[2], &output.Data4[3], &output.Data4[4], &output.Data4[5], &output.Data4[6], &output.Data4[7] + text, bytes, format, &output.Data1, &output.Data2, &output.Data3, &output.Data4[0], &output.Data4[1], &output.Data4[2], &output.Data4[3], &output.Data4[4], + &output.Data4[5], &output.Data4[6], &output.Data4[7] ); return count == 11 ? 1 : count == EOF ? -1 : 0; } diff --git a/Source/Utility/GuidParse.h b/Source/Utility/GuidParse.h index 40b2ece..dfff812 100644 --- a/Source/Utility/GuidParse.h +++ b/Source/Utility/GuidParse.h @@ -4,8 +4,6 @@ #include #include -// Returns 1 for eleven conversions, -1 for input exhaustion, otherwise zero. -// Failed parsing may partially overwrite output; trailing text is not rejected. int ParseGuid(const char* text, std::size_t bytes, GUID& output, bool braced); #endif diff --git a/Source/Utility/LanguageCharset.cpp b/Source/Utility/LanguageCharset.cpp deleted file mode 100644 index 1abe990..0000000 --- a/Source/Utility/LanguageCharset.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "Utility/LanguageCharset.h" - -// OFFSET: 0x00ACD8B0 -// FUNCTION: fn_17771 -unsigned LanguageCharset(std::uint16_t language) { - switch (language & 0x3FF) { - case 1: - return 178; - case 2: - case 0x19: - case 0x22: - case 0x23: - return 204; - case 4: - if ((language >> 10) == 1) { - return 136; - } - if ((language >> 10) == 2) { - return 134; - } - return 161; - case 5: - case 0xE: - case 0x15: - case 0x18: - case 0x1A: - case 0x1B: - case 0x24: - case 0x2F: - return 238; - case 8: - return 161; - case 0xD: - return 177; - case 0x11: - return 128; - case 0x12: - return 129; - case 0x1E: - return 222; - case 0x1F: - return 162; - case 0x25: - case 0x26: - case 0x27: - return 186; - case 0x2A: - return 163; - default: - return 0; - } -} - -// OFFSET: 0x00ACDAE0 -// FUNCTION: fn_17773 -unsigned LanguageCodePage(std::uint16_t language) { - switch (LanguageCharset(language)) { - case 128: - return 932; - case 129: - return 949; - case 134: - return 936; - case 136: - return 950; - case 161: - return 1253; - case 162: - return 1254; - case 163: - return 1258; - case 177: - return 1255; - case 178: - return 1256; - case 186: - return 1257; - case 204: - return 1251; - case 222: - return 874; - case 238: - return 1250; - default: - return 1252; - } -} diff --git a/Source/Utility/AffineLookAt.cpp b/Source/Utility/Math/AffineLookAt.cpp similarity index 94% rename from Source/Utility/AffineLookAt.cpp rename to Source/Utility/Math/AffineLookAt.cpp index d1f876a..c284c7e 100644 --- a/Source/Utility/AffineLookAt.cpp +++ b/Source/Utility/Math/AffineLookAt.cpp @@ -1,4 +1,4 @@ -#include "Utility/AffineMatrix.h" +#include "Utility/Math/AffineMatrix.h" #include #include @@ -7,13 +7,11 @@ namespace { float Length(float squared) { return std::sqrt(squared); } - } // OFFSET: 0x00555110 // FUNCTION: fn_02033 void AffineMatrix::LookAt(const float* origin, const float* target, const float* up) { - // Identity precedes source reads in the original, including aliased inputs. this->Identity(); const float dx = target[0] - origin[0]; const float dy = target[1] - origin[1]; @@ -22,6 +20,7 @@ void AffineMatrix::LookAt(const float* origin, const float* target, const float* const float forwardZ = dz * forwardInverse; const float forwardY = dy * forwardInverse; const float forwardX = dx * forwardInverse; + const float sideX = forwardZ * up[1] - forwardY * up[2]; const float sideY = forwardX * up[2] - forwardZ * up[0]; const float sideZ = forwardY * up[0] - forwardX * up[1]; @@ -29,11 +28,13 @@ void AffineMatrix::LookAt(const float* origin, const float* target, const float* const float rightX = sideX * sideInverse; const float rightY = sideY * sideInverse; const float rightZ = sideZ * sideInverse; + const float crossX = rightZ * forwardY - rightY * forwardZ; const float crossY = rightX * forwardZ - rightZ * forwardX; const float crossZ = rightY * forwardX - rightX * forwardY; const float upInverse = 1.0f / Length((crossY * crossY + crossX * crossX) + crossZ * crossZ); const float upZ = crossZ * upInverse; + this->values[2] = forwardX; this->values[0] = rightX; this->values[7] = upZ; @@ -45,6 +46,7 @@ void AffineMatrix::LookAt(const float* origin, const float* target, const float* this->values[6] = rightZ; this->values[4] = upY; this->values[8] = forwardZ; + this->values[9] = -((rightX * origin[0] + rightY * origin[1]) + rightZ * origin[2]); this->values[10] = -((upX * origin[0] + upY * origin[1]) + upZ * origin[2]); this->values[11] = -((forwardX * origin[0] + forwardY * origin[1]) + forwardZ * origin[2]); diff --git a/Source/Utility/AffineMatrix.cpp b/Source/Utility/Math/AffineMatrix.cpp similarity index 90% rename from Source/Utility/AffineMatrix.cpp rename to Source/Utility/Math/AffineMatrix.cpp index 79aaf7b..18d3c5f 100644 --- a/Source/Utility/AffineMatrix.cpp +++ b/Source/Utility/Math/AffineMatrix.cpp @@ -1,4 +1,4 @@ -#include "Utility/AffineMatrix.h" +#include "Utility/Math/AffineMatrix.h" #include #include @@ -8,8 +8,6 @@ namespace { // GLOBAL: gl_21913 constexpr float identity[12] = {1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}; - // The original computes every term, including multiplication by zero. Retain - // those operations for nonfinite inputs rather than algebraically simplifying. void Rotate(float* values, const float* rotation) { for (unsigned row = 0; row < 4; ++row) { const float x = values[row * 3]; @@ -18,6 +16,7 @@ namespace { const float first = (x * rotation[0] + y * rotation[3]) + z * rotation[6]; const float second = (x * rotation[1] + y * rotation[4]) + z * rotation[7]; const float third = (x * rotation[2] + y * rotation[5]) + z * rotation[8]; + values[row * 3] = row == 3 ? first + rotation[9] : first; values[row * 3 + 1] = row == 3 ? second + rotation[10] : second; values[row * 3 + 2] = row == 3 ? third + rotation[11] : third; @@ -25,7 +24,6 @@ namespace { } } -// Identity assignment is inlined throughout the recovered matrix operations. void AffineMatrix::Identity() { std::memcpy(this->values, identity, sizeof(identity)); } @@ -34,6 +32,7 @@ void AffineMatrix::Identity() { // FUNCTION: fn_02034 void AffineMatrix::SetXRotation(float radians) { this->Identity(); + const float sine = ClientSin(radians); const float cosine = ClientCos(radians); this->values[4] = cosine; @@ -46,6 +45,7 @@ void AffineMatrix::SetXRotation(float radians) { // FUNCTION: fn_02035 void AffineMatrix::SetYRotation(float radians) { this->Identity(); + const float sine = ClientSin(radians); const float cosine = ClientCos(radians); this->values[0] = cosine; @@ -58,6 +58,7 @@ void AffineMatrix::SetYRotation(float radians) { // FUNCTION: fn_02036 void AffineMatrix::SetZRotation(float radians) { this->Identity(); + const float sine = ClientSin(radians); const float cosine = ClientCos(radians); this->values[0] = cosine; @@ -130,16 +131,17 @@ void AffineMatrix::Compose(const AffineMatrix& first, const AffineMatrix& second const float* a = first.values; const float* b = second.values; float* output = this->values; - // The original stores one output column before reading the next. Inputs - // aliasing the destination are deliberately not snapshotted. + output[0] = (a[0] * b[0] + b[3] * a[1]) + b[6] * a[2]; output[3] = (a[4] * b[3] + a[3] * b[0]) + a[5] * b[6]; output[6] = (a[7] * b[3] + a[6] * b[0]) + a[8] * b[6]; output[9] = ((a[10] * b[3] + a[9] * b[0]) + a[11] * b[6]) + b[9]; + output[1] = (b[4] * a[1] + b[1] * a[0]) + b[7] * a[2]; output[4] = (a[4] * b[4] + a[3] * b[1]) + a[5] * b[7]; output[7] = (a[7] * b[4] + a[6] * b[1]) + a[8] * b[7]; output[10] = ((a[10] * b[4] + a[9] * b[1]) + a[11] * b[7]) + b[10]; + output[2] = (b[5] * a[1] + b[2] * a[0]) + a[2] * b[8]; output[5] = (b[5] * a[4] + b[2] * a[3]) + a[5] * b[8]; output[8] = (b[5] * a[7] + b[2] * a[6]) + a[8] * b[8]; @@ -152,8 +154,7 @@ void AffineMatrix::Inverse(const AffineMatrix& source) { const float* a = source.values; float* output = this->values; const float minor = a[4] * a[8] - a[5] * a[7]; - const float inverse = - 1.0f / ((minor * a[0] - (a[3] * a[8] - a[6] * a[5]) * a[1]) + (a[3] * a[7] - a[6] * a[4]) * a[2]); + const float inverse = 1.0f / ((minor * a[0] - (a[3] * a[8] - a[6] * a[5]) * a[1]) + (a[3] * a[7] - a[6] * a[4]) * a[2]); const float negative = -inverse; output[0] = minor * inverse; const float firstY = (a[1] * a[8] - a[7] * a[2]) * negative; @@ -172,6 +173,7 @@ void AffineMatrix::Inverse(const AffineMatrix& source) { output[7] = thirdY; const float thirdZ = (a[4] * a[0] - a[1] * a[3]) * inverse; output[8] = thirdZ; + output[9] = -((secondX * a[10] + (minor * inverse) * a[9]) + thirdX * a[11]); output[10] = -((firstY * a[9] + secondY * a[10]) + thirdY * a[11]); output[11] = -((secondZ * a[10] + firstZ * a[9]) + thirdZ * a[11]); diff --git a/Source/Utility/AffineMatrix.h b/Source/Utility/Math/AffineMatrix.h similarity index 77% rename from Source/Utility/AffineMatrix.h rename to Source/Utility/Math/AffineMatrix.h index 9c252cf..5d0d20c 100644 --- a/Source/Utility/AffineMatrix.h +++ b/Source/Utility/Math/AffineMatrix.h @@ -1,8 +1,6 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_AFFINEMATRIX_H -#define RAGNAROK_SOURCE_UTILITY_AFFINEMATRIX_H +#ifndef RAGNAROK_SOURCE_UTILITY_MATH_AFFINEMATRIX_H +#define RAGNAROK_SOURCE_UTILITY_MATH_AFFINEMATRIX_H -// Original scalar x87 operations with a final float store. Non-x86 ports -// use the host math library; bit-equivalence there requires separate proof. float ClientSin(float radians); float ClientCos(float radians); float ClientRadians(int degrees); diff --git a/Source/Utility/ClientAngles.cpp b/Source/Utility/Math/ClientAngles.cpp similarity index 87% rename from Source/Utility/ClientAngles.cpp rename to Source/Utility/Math/ClientAngles.cpp index 6f031a1..924b195 100644 --- a/Source/Utility/ClientAngles.cpp +++ b/Source/Utility/Math/ClientAngles.cpp @@ -1,4 +1,4 @@ -#include "Utility/AffineMatrix.h" +#include "Utility/Math/AffineMatrix.h" #include #include @@ -14,8 +14,7 @@ float ClientCos(float radians) { namespace { // OFFSET: 0x00554280 // FUNCTION: fn_02021 - // The six adjacent arrays are one contiguous addressing domain: negative lookup indices intentionally reach - // the preceding array's tail, not abs(index) in the negative array. + struct AngleTables { float radians[361]; float negativeRadians[361]; @@ -38,6 +37,7 @@ namespace { }; const AngleTables tables; + int Wrapped(int degrees) { return degrees > 360 || degrees < -360 ? degrees % 360 : degrees; } diff --git a/Source/Utility/RayTriangle.cpp b/Source/Utility/Math/RayTriangle.cpp similarity index 88% rename from Source/Utility/RayTriangle.cpp rename to Source/Utility/Math/RayTriangle.cpp index 2839416..9ea2942 100644 --- a/Source/Utility/RayTriangle.cpp +++ b/Source/Utility/Math/RayTriangle.cpp @@ -1,18 +1,10 @@ -#include "Utility/RayTriangle.h" +#include "Utility/Math/RayTriangle.h" #include // OFFSET: 0x00554060 // FUNCTION: fn_02020 -bool IntersectRayTriangle( - const float* ray, - const float* first, - const float* second, - const float* third, - float& u, - float& v, - float& distance -) { +bool IntersectRayTriangle(const float* ray, const float* first, const float* second, const float* third, float& u, float& v, float& distance) { const float edgeX = second[0] - first[0]; const float edgeY = second[1] - first[1]; const float edgeZ = second[2] - first[2]; diff --git a/Source/Utility/Math/RayTriangle.h b/Source/Utility/Math/RayTriangle.h new file mode 100644 index 0000000..8468df0 --- /dev/null +++ b/Source/Utility/Math/RayTriangle.h @@ -0,0 +1,6 @@ +#ifndef RAGNAROK_SOURCE_UTILITY_MATH_RAYTRIANGLE_H +#define RAGNAROK_SOURCE_UTILITY_MATH_RAYTRIANGLE_H + +bool IntersectRayTriangle(const float* ray, const float* first, const float* second, const float* third, float& u, float& v, float& distance); + +#endif diff --git a/Source/Utility/Math/ScalarConversion.h b/Source/Utility/Math/ScalarConversion.h new file mode 100644 index 0000000..a5d474c --- /dev/null +++ b/Source/Utility/Math/ScalarConversion.h @@ -0,0 +1,10 @@ +#ifndef RAGNAROK_SOURCE_UTILITY_MATH_SCALARCONVERSION_H +#define RAGNAROK_SOURCE_UTILITY_MATH_SCALARCONVERSION_H + +#include + +inline int TruncateToInt(double value) { + return value > -2147483649.0 && value < 2147483648.0 ? static_cast(value) : std::numeric_limits::min(); +} + +#endif diff --git a/Source/Utility/RayTriangle.h b/Source/Utility/RayTriangle.h deleted file mode 100644 index 2acf645..0000000 --- a/Source/Utility/RayTriangle.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_RAYTRIANGLE_H -#define RAGNAROK_SOURCE_UTILITY_RAYTRIANGLE_H - -// Six floats: origin xyz followed by direction xyz. Outputs are written only -// as each original rejection stage is passed; signed distance is not clipped. -bool IntersectRayTriangle( - const float* ray, - const float* first, - const float* second, - const float* third, - float& u, - float& v, - float& distance -); - -#endif diff --git a/Source/Utility/Rijndael.cpp b/Source/Utility/Rijndael.cpp index eea9e6c..8a1b842 100644 --- a/Source/Utility/Rijndael.cpp +++ b/Source/Utility/Rijndael.cpp @@ -22,865 +22,338 @@ static constexpr const char* s_errorBlockLength = "Incorrect block length"; static constexpr const char* s_errorDataLength = "Data not multiple of Block Size"; -const char* CRijndael::sm_chain0 = - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +const char* CRijndael::sm_chain0 = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -const int CRijndael::sm_shifts[3][4][2] = { - {{0, 0}, {1, 3}, {2, 2}, {3, 1}}, - {{0, 0}, {1, 5}, {2, 4}, {3, 3}}, - {{0, 0}, {1, 7}, {3, 5}, {4, 4}} -}; +const int CRijndael::sm_shifts[3][4][2] = {{{0, 0}, {1, 3}, {2, 2}, {3, 1}}, {{0, 0}, {1, 5}, {2, 4}, {3, 3}}, {{0, 0}, {1, 7}, {3, 5}, {4, 4}}}; const signed char CRijndael::sm_S[256] = { - 99, 124, 119, 123, -14, 107, 111, -59, 48, 1, 103, 43, -2, -41, -85, 118, - -54, -126, -55, 125, -6, 89, 71, -16, -83, -44, -94, -81, -100, -92, 114, -64, - -73, -3, -109, 38, 54, 63, -9, -52, 52, -91, -27, -15, 113, -40, 49, 21, - 4, -57, 35, -61, 24, -106, 5, -102, 7, 18, -128, -30, -21, 39, -78, 117, - 9, -125, 44, 26, 27, 110, 90, -96, 82, 59, -42, -77, 41, -29, 47, -124, - 83, -47, 0, -19, 32, -4, -79, 91, 106, -53, -66, 57, 74, 76, 88, -49, - -48, -17, -86, -5, 67, 77, 51, -123, 69, -7, 2, 127, 80, 60, -97, -88, - 81, -93, 64, -113, -110, -99, 56, -11, -68, -74, -38, 33, 16, -1, -13, -46, - -51, 12, 19, -20, 95, -105, 68, 23, -60, -89, 126, 61, 100, 93, 25, 115, - 96, -127, 79, -36, 34, 42, -112, -120, 70, -18, -72, 20, -34, 94, 11, -37, - -32, 50, 58, 10, 73, 6, 36, 92, -62, -45, -84, 98, -111, -107, -28, 121, - -25, -56, 55, 109, -115, -43, 78, -87, 108, 86, -12, -22, 101, 122, -82, 8, - -70, 120, 37, 46, 28, -90, -76, -58, -24, -35, 116, 31, 75, -67, -117, -118, - 112, 62, -75, 102, 72, 3, -10, 14, 97, 53, 87, -71, -122, -63, 29, -98, - -31, -8, -104, 17, 105, -39, -114, -108, -101, 30, -121, -23, -50, 85, 40, -33, - -116, -95, -119, 13, -65, -26, 66, 104, 65, -103, 45, 15, -80, 84, -69, 22 + 99, 124, 119, 123, -14, 107, 111, -59, 48, 1, 103, 43, -2, -41, -85, 118, -54, -126, -55, 125, -6, 89, 71, -16, -83, -44, + -94, -81, -100, -92, 114, -64, -73, -3, -109, 38, 54, 63, -9, -52, 52, -91, -27, -15, 113, -40, 49, 21, 4, -57, 35, -61, + 24, -106, 5, -102, 7, 18, -128, -30, -21, 39, -78, 117, 9, -125, 44, 26, 27, 110, 90, -96, 82, 59, -42, -77, 41, -29, + 47, -124, 83, -47, 0, -19, 32, -4, -79, 91, 106, -53, -66, 57, 74, 76, 88, -49, -48, -17, -86, -5, 67, 77, 51, -123, + 69, -7, 2, 127, 80, 60, -97, -88, 81, -93, 64, -113, -110, -99, 56, -11, -68, -74, -38, 33, 16, -1, -13, -46, -51, 12, + 19, -20, 95, -105, 68, 23, -60, -89, 126, 61, 100, 93, 25, 115, 96, -127, 79, -36, 34, 42, -112, -120, 70, -18, -72, 20, + -34, 94, 11, -37, -32, 50, 58, 10, 73, 6, 36, 92, -62, -45, -84, 98, -111, -107, -28, 121, -25, -56, 55, 109, -115, -43, + 78, -87, 108, 86, -12, -22, 101, 122, -82, 8, -70, 120, 37, 46, 28, -90, -76, -58, -24, -35, 116, 31, 75, -67, -117, -118, + 112, 62, -75, 102, 72, 3, -10, 14, 97, 53, 87, -71, -122, -63, 29, -98, -31, -8, -104, 17, 105, -39, -114, -108, -101, 30, + -121, -23, -50, 85, 40, -33, -116, -95, -119, 13, -65, -26, 66, 104, 65, -103, 45, 15, -80, 84, -69, 22 }; const signed char CRijndael::sm_Si[256] = { - 82, 9, 106, -43, 48, 54, -91, 56, -65, 64, -93, -98, -127, -13, -41, -5, - 124, -29, 57, -126, -101, 47, -1, -121, 52, -114, 67, 68, -60, -34, -23, -53, - 84, 123, -108, 50, -90, -62, 35, 61, -18, 76, -107, 11, 66, -6, -61, 78, - 8, 46, -95, 102, 40, -39, 36, -78, 118, 91, -94, 73, 109, -117, -47, 37, - 114, -8, -10, 100, -122, 104, -104, 22, -44, -92, 92, -52, 93, 101, -74, -110, - 108, 112, 72, 80, -3, -19, -71, -38, 94, 21, 70, 87, -89, -115, -99, -124, - -112, -40, -85, 0, -116, -68, -45, 10, -9, -28, 88, 5, -72, -77, 69, 6, - -48, 44, 30, -113, -54, 63, 15, 2, -63, -81, -67, 3, 1, 19, -118, 107, - 58, -111, 17, 65, 79, 103, -36, -22, -105, -14, -49, -50, -16, -76, -26, 115, - -106, -84, 116, 34, -25, -83, 53, -123, -30, -7, 55, -24, 28, 117, -33, 110, - 71, -15, 26, 113, 29, 41, -59, -119, 111, -73, 98, 14, -86, 24, -66, 27, - -4, 86, 62, 75, -58, -46, 121, 32, -102, -37, -64, -2, 120, -51, 90, -12, - 31, -35, -88, 51, -120, 7, -57, 49, -79, 18, 16, 89, 39, -128, -20, 95, - 96, 81, 127, -87, 25, -75, 74, 13, 45, -27, 122, -97, -109, -55, -100, -17, - -96, -32, 59, 77, -82, 42, -11, -80, -56, -21, -69, 60, -125, 83, -103, 97, - 23, 43, 4, 126, -70, 119, -42, 38, -31, 105, 20, 99, 85, 33, 12, 125 + 82, 9, 106, -43, 48, 54, -91, 56, -65, 64, -93, -98, -127, -13, -41, -5, 124, -29, 57, -126, -101, 47, -1, -121, 52, -114, + 67, 68, -60, -34, -23, -53, 84, 123, -108, 50, -90, -62, 35, 61, -18, 76, -107, 11, 66, -6, -61, 78, 8, 46, -95, 102, + 40, -39, 36, -78, 118, 91, -94, 73, 109, -117, -47, 37, 114, -8, -10, 100, -122, 104, -104, 22, -44, -92, 92, -52, 93, 101, + -74, -110, 108, 112, 72, 80, -3, -19, -71, -38, 94, 21, 70, 87, -89, -115, -99, -124, -112, -40, -85, 0, -116, -68, -45, 10, + -9, -28, 88, 5, -72, -77, 69, 6, -48, 44, 30, -113, -54, 63, 15, 2, -63, -81, -67, 3, 1, 19, -118, 107, 58, -111, + 17, 65, 79, 103, -36, -22, -105, -14, -49, -50, -16, -76, -26, 115, -106, -84, 116, 34, -25, -83, 53, -123, -30, -7, 55, -24, + 28, 117, -33, 110, 71, -15, 26, 113, 29, 41, -59, -119, 111, -73, 98, 14, -86, 24, -66, 27, -4, 86, 62, 75, -58, -46, + 121, 32, -102, -37, -64, -2, 120, -51, 90, -12, 31, -35, -88, 51, -120, 7, -57, 49, -79, 18, 16, 89, 39, -128, -20, 95, + 96, 81, 127, -87, 25, -75, 74, 13, 45, -27, 122, -97, -109, -55, -100, -17, -96, -32, 59, 77, -82, 42, -11, -80, -56, -21, + -69, 60, -125, 83, -103, 97, 23, 43, 4, 126, -70, 119, -42, 38, -31, 105, 20, 99, 85, 33, 12, 125 }; const int CRijndael::sm_T1[256] = { - -966564955, -126059388, -294160487, -159679603, - -855539, -697603139, -563122255, -1849309868, - 1613770832, 33620227, -832084055, 1445669757, - -402719207, -1244145822, 1303096294, -327780710, - -1882535355, 528646813, -1983264448, -92439161, - -268764651, -1302767125, -1907931191, -68095989, - 1101901292, -1277897625, 1604494077, 1169141738, - 597466303, 1403299063, -462261610, -1681866661, - 1974974402, -503448292, 1033081774, 1277568618, - 1815492186, 2118074177, -168298750, -2083730353, - 1748251740, 1369810420, -773462732, -101584632, - -495881837, -1411852173, 1647391059, 706024767, - 134480908, -1782069422, 1176707941, -1648114850, - 806885416, 932615841, 168101135, 798661301, - 235341577, 605164086, 461406363, -538779075, - -840176858, 1311188841, 2142417613, -361400929, - 302582043, 495158174, 1479289972, 874125870, - 907746093, -596742478, -1269146898, 1537253627, - -1538108682, 1983593293, -1210657183, 2108928974, - 1378429307, -572267714, 1580150641, 327451799, - -1504488459, -1177431704, 0, -1041371860, - 1075847264, -469959649, 2041688520, -1235526675, - -731223362, -1916023994, 1740553945, 1916352843, - -1807070498, -1739830060, -1336387352, -2049978550, - -1143943061, -974131414, 1336584933, -302253290, - -2042412091, -1706209833, 1714631509, 293963156, - -1975171633, -369493744, 67240454, -25198719, - -1605349136, 2017213508, 631218106, 1269344483, - -1571728909, 1571005438, -2143272768, 93294474, - 1066570413, 563977660, 1882732616, -235539196, - 1673313503, 2008463041, -1344611723, 1109467491, - 537923632, -436207846, -34344178, -1076702611, - -2117218996, 403442708, 638784309, -1007883217, - -1101045791, 899127202, -2008791860, 773265209, - -1815821225, 1437050866, -58818942, 2050833735, - -932944724, -1168286233, 840505643, -428641387, - -1067425632, 427917720, -1638969391, -1545806721, - 1143087718, 1412049534, 999329963, 193497219, - -1941551414, -940642775, 1807268051, 672404540, - -1478566279, -1134666014, 369822493, -1378100362, - -606019525, 1681011286, 1949973070, 336202270, - -1840690725, 201721354, 1210328172, -1201906460, - -1614626211, -1110191250, 1135389935, -1000185178, - 965841320, 831886756, -739974089, -226920053, - -706222286, -1949775805, 1849112409, -630362697, - 26054028, -1311386268, -1672589614, 1235855840, - -663982924, -1403627782, -202050553, -806688219, - -899324497, -193299826, 1202630377, 268961816, - 1874508501, -260540280, 1243948399, 1546530418, - 941366308, 1470539505, 1941222599, -1748580783, - -873928669, -1579295364, -395021156, 1042226977, - -1773450275, 1639824860, 227249030, 260737669, - -529502064, 2084453954, 1907733956, -865704278, - -1874310952, 100860677, -134810111, 470683154, - -1033805405, 1781871967, -1370007559, 1773779408, - 394692241, -1715355304, 974986535, 664706745, - -639508168, -336005101, 731420851, 571543859, - -764843589, -1445340816, 126783113, 865375399, - 765172662, 1008606754, 361203602, -907417312, - -2016489911, -1437248001, 1344809080, -1512054918, - 59542671, 1503764984, 160008576, 437062935, - 1707065306, -672733647, -2076032314, -798463816, - -2109652541, 697932208, 1512910199, 504303377, - 2075177163, -1470868228, 1841019862, 739644986 + -966564955, -126059388, -294160487, -159679603, -855539, -697603139, -563122255, -1849309868, 1613770832, 33620227, -832084055, 1445669757, + -402719207, -1244145822, 1303096294, -327780710, -1882535355, 528646813, -1983264448, -92439161, -268764651, -1302767125, -1907931191, -68095989, + 1101901292, -1277897625, 1604494077, 1169141738, 597466303, 1403299063, -462261610, -1681866661, 1974974402, -503448292, 1033081774, 1277568618, + 1815492186, 2118074177, -168298750, -2083730353, 1748251740, 1369810420, -773462732, -101584632, -495881837, -1411852173, 1647391059, 706024767, + 134480908, -1782069422, 1176707941, -1648114850, 806885416, 932615841, 168101135, 798661301, 235341577, 605164086, 461406363, -538779075, + -840176858, 1311188841, 2142417613, -361400929, 302582043, 495158174, 1479289972, 874125870, 907746093, -596742478, -1269146898, 1537253627, + -1538108682, 1983593293, -1210657183, 2108928974, 1378429307, -572267714, 1580150641, 327451799, -1504488459, -1177431704, 0, -1041371860, + 1075847264, -469959649, 2041688520, -1235526675, -731223362, -1916023994, 1740553945, 1916352843, -1807070498, -1739830060, -1336387352, -2049978550, + -1143943061, -974131414, 1336584933, -302253290, -2042412091, -1706209833, 1714631509, 293963156, -1975171633, -369493744, 67240454, -25198719, + -1605349136, 2017213508, 631218106, 1269344483, -1571728909, 1571005438, -2143272768, 93294474, 1066570413, 563977660, 1882732616, -235539196, + 1673313503, 2008463041, -1344611723, 1109467491, 537923632, -436207846, -34344178, -1076702611, -2117218996, 403442708, 638784309, -1007883217, + -1101045791, 899127202, -2008791860, 773265209, -1815821225, 1437050866, -58818942, 2050833735, -932944724, -1168286233, 840505643, -428641387, + -1067425632, 427917720, -1638969391, -1545806721, 1143087718, 1412049534, 999329963, 193497219, -1941551414, -940642775, 1807268051, 672404540, + -1478566279, -1134666014, 369822493, -1378100362, -606019525, 1681011286, 1949973070, 336202270, -1840690725, 201721354, 1210328172, -1201906460, + -1614626211, -1110191250, 1135389935, -1000185178, 965841320, 831886756, -739974089, -226920053, -706222286, -1949775805, 1849112409, -630362697, + 26054028, -1311386268, -1672589614, 1235855840, -663982924, -1403627782, -202050553, -806688219, -899324497, -193299826, 1202630377, 268961816, + 1874508501, -260540280, 1243948399, 1546530418, 941366308, 1470539505, 1941222599, -1748580783, -873928669, -1579295364, -395021156, 1042226977, + -1773450275, 1639824860, 227249030, 260737669, -529502064, 2084453954, 1907733956, -865704278, -1874310952, 100860677, -134810111, 470683154, + -1033805405, 1781871967, -1370007559, 1773779408, 394692241, -1715355304, 974986535, 664706745, -639508168, -336005101, 731420851, 571543859, + -764843589, -1445340816, 126783113, 865375399, 765172662, 1008606754, 361203602, -907417312, -2016489911, -1437248001, 1344809080, -1512054918, + 59542671, 1503764984, 160008576, 437062935, 1707065306, -672733647, -2076032314, -798463816, -2109652541, 697932208, 1512910199, 504303377, + 2075177163, -1470868228, 1841019862, 739644986 }; const int CRijndael::sm_T2[256] = { - -1513725085, -2064089988, -1712425097, -1913226373, - 234877682, -1110021269, -1310822545, 1418839493, - 1348481072, 50462977, -1446090905, 2102799147, - 434634494, 1656084439, -431117397, -1695779210, - 1167051466, -1658879358, 1082771913, -2013627011, - 368048890, -340633255, -913422521, 201060592, - -331240019, 1739838676, -44064094, -364531793, - -1088185188, -145513308, -1763413390, 1536934080, - -1032472649, 484572669, -1371696237, 1783375398, - 1517041206, 1098792767, 49674231, 1334037708, - 1550332980, -195975771, 886171109, 150598129, - -1813876367, 1940642008, 1398944049, 1059722517, - 201851908, 1385547719, 1699095331, 1587397571, - 674240536, -1590192490, 252314885, -1255171430, - 151914247, 908333586, -1692696448, 1038082786, - 651029483, 1766729511, -847269198, -1612024459, - 454166793, -1642232957, 1951935532, 775166490, - 758520603, -1294176658, -290170278, -77881184, - -157003182, 1299594043, 1639438038, -830622797, - 2068982057, 1054729187, 1901997871, -1760328572, - -173649069, 1757008337, 0, 750906861, - 1614815264, 535035132, -931548751, -306816165, - -1093375382, 1183697867, -647512386, 1265776953, - -560706998, -728216500, -391096232, 1250283471, - 1807470800, 717615087, -447763798, 384695291, - -981056701, -677753523, 1432761139, -1810791035, - -813021883, 283769337, 100925954, -2114027649, - -257929136, 1148730428, -1171939425, -481580888, - -207466159, -27417693, -1065336768, -1979347057, - -1388342638, -1138647651, 1215313976, 82966005, - -547111748, -1049119050, 1974459098, 1665278241, - 807407632, 451280895, 251524083, 1841287890, - 1283575245, 337120268, 891687699, 801369324, - -507617441, -1573546089, -863484860, 959321879, - 1469301956, -229267545, -2097381762, 1199193405, - -1396153244, -407216803, 724703513, -1780059277, - -1598005152, -1743158911, -778154161, 2141445340, - 1715741218, 2119445034, -1422159728, -2096396152, - -896776634, 700968686, -747915080, 1009259540, - 2041044702, -490971554, 487983883, 1991105499, - 1004265696, 1449407026, 1316239930, 504629770, - -611169975, 168560134, 1816667172, -457679780, - 1570751170, 1857934291, -280777556, -1497079198, - -1472622191, -1540254315, 936633572, -1947043463, - 852879335, 1133234376, 1500395319, -1210421907, - -1946055283, 1689376213, -761508274, -532043351, - -1260884884, -89369002, 133428468, 634383082, - -1345690267, -1896580486, -381178194, 403703816, - -714097990, -1997506440, 1867130149, 1918643758, - 607656988, -245913946, -948718412, 1368901318, - 600565992, 2090982877, -1662487436, 557719327, - -577352885, -597574211, -2045932661, -2062579062, - -1864339344, 1115438654, -999180875, -1429445018, - -661632952, 84280067, 33027830, 303828494, - -1547542175, 1600795957, -106014889, -798377543, - -1860729210, 1486471617, 658119965, -1188585826, - 953803233, 334231800, -1288988520, 857870609, - -1143838359, 1890179545, -1995993458, -1489791852, - -1238525029, 574365214, -1844082809, 550103529, - 1233637070, -5614251, 2018519080, 2057691103, - -1895592820, -128343647, -2146858615, 387583245, - -630865985, 836232934, -964410814, -1194301336, - -1014873791, -1339450983, 2002398509, 287182607, - -881086288, -56077228, -697451589, 975967766 + -1513725085, -2064089988, -1712425097, -1913226373, 234877682, -1110021269, -1310822545, 1418839493, 1348481072, 50462977, -1446090905, 2102799147, + 434634494, 1656084439, -431117397, -1695779210, 1167051466, -1658879358, 1082771913, -2013627011, 368048890, -340633255, -913422521, 201060592, + -331240019, 1739838676, -44064094, -364531793, -1088185188, -145513308, -1763413390, 1536934080, -1032472649, 484572669, -1371696237, 1783375398, + 1517041206, 1098792767, 49674231, 1334037708, 1550332980, -195975771, 886171109, 150598129, -1813876367, 1940642008, 1398944049, 1059722517, + 201851908, 1385547719, 1699095331, 1587397571, 674240536, -1590192490, 252314885, -1255171430, 151914247, 908333586, -1692696448, 1038082786, + 651029483, 1766729511, -847269198, -1612024459, 454166793, -1642232957, 1951935532, 775166490, 758520603, -1294176658, -290170278, -77881184, + -157003182, 1299594043, 1639438038, -830622797, 2068982057, 1054729187, 1901997871, -1760328572, -173649069, 1757008337, 0, 750906861, + 1614815264, 535035132, -931548751, -306816165, -1093375382, 1183697867, -647512386, 1265776953, -560706998, -728216500, -391096232, 1250283471, + 1807470800, 717615087, -447763798, 384695291, -981056701, -677753523, 1432761139, -1810791035, -813021883, 283769337, 100925954, -2114027649, + -257929136, 1148730428, -1171939425, -481580888, -207466159, -27417693, -1065336768, -1979347057, -1388342638, -1138647651, 1215313976, 82966005, + -547111748, -1049119050, 1974459098, 1665278241, 807407632, 451280895, 251524083, 1841287890, 1283575245, 337120268, 891687699, 801369324, + -507617441, -1573546089, -863484860, 959321879, 1469301956, -229267545, -2097381762, 1199193405, -1396153244, -407216803, 724703513, -1780059277, + -1598005152, -1743158911, -778154161, 2141445340, 1715741218, 2119445034, -1422159728, -2096396152, -896776634, 700968686, -747915080, 1009259540, + 2041044702, -490971554, 487983883, 1991105499, 1004265696, 1449407026, 1316239930, 504629770, -611169975, 168560134, 1816667172, -457679780, + 1570751170, 1857934291, -280777556, -1497079198, -1472622191, -1540254315, 936633572, -1947043463, 852879335, 1133234376, 1500395319, -1210421907, + -1946055283, 1689376213, -761508274, -532043351, -1260884884, -89369002, 133428468, 634383082, -1345690267, -1896580486, -381178194, 403703816, + -714097990, -1997506440, 1867130149, 1918643758, 607656988, -245913946, -948718412, 1368901318, 600565992, 2090982877, -1662487436, 557719327, + -577352885, -597574211, -2045932661, -2062579062, -1864339344, 1115438654, -999180875, -1429445018, -661632952, 84280067, 33027830, 303828494, + -1547542175, 1600795957, -106014889, -798377543, -1860729210, 1486471617, 658119965, -1188585826, 953803233, 334231800, -1288988520, 857870609, + -1143838359, 1890179545, -1995993458, -1489791852, -1238525029, 574365214, -1844082809, 550103529, 1233637070, -5614251, 2018519080, 2057691103, + -1895592820, -128343647, -2146858615, 387583245, -630865985, 836232934, -964410814, -1194301336, -1014873791, -1339450983, 2002398509, 287182607, + -881086288, -56077228, -697451589, 975967766 }; const int CRijndael::sm_T3[256] = { - 1671808611, 2089089148, 2006576759, 2072901243, - -233963534, 1807603307, 1873927791, -984313403, - 810573872, 16974337, 1739181671, 729634347, - -31856642, -681396777, -1410970197, 1989864566, - -901410870, -2103631998, -918517303, 2106063485, - -99225606, 1508618841, 1204391495, -267650064, - -1377025619, -731401260, -1560453214, -1343601233, - -1665195108, -1527295068, 1922491506, -1067738176, - -1211992649, -48438787, -1817297517, 644500518, - 911895606, 1061256767, -150800905, -867204148, - 878471220, -1510714971, -449523227, -251069967, - 1905517169, -663508008, 827548209, 356461077, - 67897348, -950889017, 593839651, -1017209405, - 405286936, -1767819370, 84871685, -1699401830, - 118033927, 305538066, -2137318528, -499261470, - -349778453, 661212711, -1295155278, 1973414517, - 152769033, -2086789757, 745822252, 439235610, - 455947803, 1857215598, 1525593178, -1594139744, - 1391895634, 994932283, -698239018, -1278313037, - 695947817, -482419229, 795958831, -2070473852, - 1408607827, -781665839, 0, -315833875, - 543178784, -65018884, -1312261711, 1542305371, - 1790891114, -884568629, -1093048386, 961245753, - 1256100938, 1289001036, 1491644504, -817199665, - -798245936, -282409489, -1427812438, -82383365, - 1137018435, 1305975373, 861234739, -2053893755, - 1171229253, -116332039, 33948674, 2139225727, - 1357946960, 1011120188, -1615190625, -1461498968, - 1374921297, -1543610973, 1086357568, -1886780017, - -1834139758, -1648615011, 944271416, -184225291, - -1126210628, -1228834890, -629821478, 560153121, - 271589392, -15014401, -217121293, -764559406, - -850624051, 202643468, 322250259, -332413972, - 1608629855, -1750977129, 1154254916, 389623319, - -1000893500, -1477290585, 2122513534, 1028094525, - 1689045092, 1575467613, 422261273, 1939203699, - 1621147744, -2120738431, 1339137615, -595614756, - 577127458, 712922154, -1867826288, -2004677752, - 1187679302, -299251730, -1194103880, 339486740, - -562452514, 1591917662, 186455563, -612979237, - -532948000, 844522546, 978220090, 169743370, - 1239126601, 101321734, 611076132, 1558493276, - -1034051646, -747717165, -1393605716, 1655096418, - -1851246191, -1784401515, -466103324, 2039214713, - -416098841, -935097400, 928607799, 1840765549, - -1920204403, -714821163, 1322425422, -1444918871, - 1823791212, 1459268694, -200805388, -366620694, - 1706019429, 2056189050, -1360443474, 135794696, - -1160417350, 2022240376, 628050469, 779246638, - 472135708, -1494132826, -1261997132, -967731258, - -400307224, -579034659, 1956440180, 522272287, - 1272813131, -1109630531, -1954148981, -1970991222, - 1888542832, 1044544574, -1245417035, 1722469478, - 1222152264, 50660867, -167643146, 236067854, - 1638122081, 895445557, 1475980887, -1177523783, - -2037311610, -1051158079, 489110045, -1632032866, - -516367903, -132912136, -1733088360, 288563729, - 1773916777, -646927911, -1903622258, -1800981612, - -1682559589, 505560094, -2020469369, -383727127, - -834041906, 1442818645, 678973480, -545610273, - -1936784500, -1577559647, -1988097655, 219617805, - -1076206145, -432941082, 1120306242, 1756942440, - 1103331905, -1716508263, 762796589, 252780047, - -1328841808, 1425844308, -1143575109, 372911126 + 1671808611, 2089089148, 2006576759, 2072901243, -233963534, 1807603307, 1873927791, -984313403, 810573872, 16974337, 1739181671, 729634347, + -31856642, -681396777, -1410970197, 1989864566, -901410870, -2103631998, -918517303, 2106063485, -99225606, 1508618841, 1204391495, -267650064, + -1377025619, -731401260, -1560453214, -1343601233, -1665195108, -1527295068, 1922491506, -1067738176, -1211992649, -48438787, -1817297517, 644500518, + 911895606, 1061256767, -150800905, -867204148, 878471220, -1510714971, -449523227, -251069967, 1905517169, -663508008, 827548209, 356461077, + 67897348, -950889017, 593839651, -1017209405, 405286936, -1767819370, 84871685, -1699401830, 118033927, 305538066, -2137318528, -499261470, + -349778453, 661212711, -1295155278, 1973414517, 152769033, -2086789757, 745822252, 439235610, 455947803, 1857215598, 1525593178, -1594139744, + 1391895634, 994932283, -698239018, -1278313037, 695947817, -482419229, 795958831, -2070473852, 1408607827, -781665839, 0, -315833875, + 543178784, -65018884, -1312261711, 1542305371, 1790891114, -884568629, -1093048386, 961245753, 1256100938, 1289001036, 1491644504, -817199665, + -798245936, -282409489, -1427812438, -82383365, 1137018435, 1305975373, 861234739, -2053893755, 1171229253, -116332039, 33948674, 2139225727, + 1357946960, 1011120188, -1615190625, -1461498968, 1374921297, -1543610973, 1086357568, -1886780017, -1834139758, -1648615011, 944271416, -184225291, + -1126210628, -1228834890, -629821478, 560153121, 271589392, -15014401, -217121293, -764559406, -850624051, 202643468, 322250259, -332413972, + 1608629855, -1750977129, 1154254916, 389623319, -1000893500, -1477290585, 2122513534, 1028094525, 1689045092, 1575467613, 422261273, 1939203699, + 1621147744, -2120738431, 1339137615, -595614756, 577127458, 712922154, -1867826288, -2004677752, 1187679302, -299251730, -1194103880, 339486740, + -562452514, 1591917662, 186455563, -612979237, -532948000, 844522546, 978220090, 169743370, 1239126601, 101321734, 611076132, 1558493276, + -1034051646, -747717165, -1393605716, 1655096418, -1851246191, -1784401515, -466103324, 2039214713, -416098841, -935097400, 928607799, 1840765549, + -1920204403, -714821163, 1322425422, -1444918871, 1823791212, 1459268694, -200805388, -366620694, 1706019429, 2056189050, -1360443474, 135794696, + -1160417350, 2022240376, 628050469, 779246638, 472135708, -1494132826, -1261997132, -967731258, -400307224, -579034659, 1956440180, 522272287, + 1272813131, -1109630531, -1954148981, -1970991222, 1888542832, 1044544574, -1245417035, 1722469478, 1222152264, 50660867, -167643146, 236067854, + 1638122081, 895445557, 1475980887, -1177523783, -2037311610, -1051158079, 489110045, -1632032866, -516367903, -132912136, -1733088360, 288563729, + 1773916777, -646927911, -1903622258, -1800981612, -1682559589, 505560094, -2020469369, -383727127, -834041906, 1442818645, 678973480, -545610273, + -1936784500, -1577559647, -1988097655, 219617805, -1076206145, -432941082, 1120306242, 1756942440, 1103331905, -1716508263, 762796589, 252780047, + -1328841808, 1425844308, -1143575109, 372911126 }; const int CRijndael::sm_T4[256] = { - 1667474886, 2088535288, 2004326894, 2071694838, - -219017729, 1802223062, 1869591006, -976923503, - 808472672, 16843522, 1734846926, 724270422, - -16901657, -673750347, -1414797747, 1987484396, - -892713585, -2105369313, -909557623, 2105378810, - -84273681, 1499065266, 1195886990, -252703749, - -1381110719, -724277325, -1566376609, -1347425723, - -1667449053, -1532692653, 1920112356, -1061135461, - -1212693899, -33743647, -1819038147, 640051788, - 909531756, 1061110142, -134806795, -859025533, - 875846760, -1515850671, -437963567, -235861767, - 1903268834, -656903253, 825316194, 353713962, - 67374088, -943238507, 589522246, -1010606435, - 404236336, -1768513225, 84217610, -1701137105, - 117901582, 303183396, -2139055333, -488489505, - -336910643, 656894286, -1296904833, 1970642922, - 151591698, -2088526307, 741110872, 437923380, - 454765878, 1852748508, 1515908788, -1600062629, - 1381168804, 993742198, -690593353, -1280061827, - 690584402, -471646499, 791638366, -2071685357, - 1398011302, -774805319, 0, -303223615, - 538992704, -50585629, -1313748871, 1532751286, - 1785380564, -875870579, -1094788761, 960056178, - 1246420628, 1280103576, 1482221744, -808498555, - -791647301, -269538619, -1431640753, -67430675, - 1128514950, 1296947098, 859002214, -2054843375, - 1162203018, -101117719, 33687044, 2139062782, - 1347481760, 1010582648, -1616922075, -1465326773, - 1364325282, -1549533603, 1077985408, -1886418427, - -1835881153, -1650607071, 943212656, -168491791, - -1128472733, -1229536905, -623217233, 555836226, - 269496352, -58651, -202174723, -757961281, - -842183551, 202118168, 320025894, -320065597, - 1600119230, -1751670219, 1145359496, 387397934, - -993765485, -1482165675, 2122220284, 1027426170, - 1684319432, 1566435258, 421079858, 1936954854, - 1616945344, -2122213351, 1330631070, -589529181, - 572679748, 707427924, -1869567173, -2004319477, - 1179044492, -286381625, -1195846805, 336870440, - -555845209, 1583276732, 185277718, -606374227, - -522175525, 842159716, 976899700, 168435220, - 1229577106, 101059084, 606366792, 1549591736, - -1027449441, -741118275, -1397952701, 1650632388, - -1852725191, -1785355215, -454805549, 2038008818, - -404278571, -926399605, 926374254, 1835907034, - -1920103423, -707435343, 1313788572, -1448484791, - 1819063512, 1448540844, -185333773, -353753649, - 1701162954, 2054852340, -1364268729, 134748176, - -1162160785, 2021165296, 623210314, 774795868, - 471606328, -1499008681, -1263220877, -960081513, - -387439669, -572687199, 1953799400, 522133822, - 1263263126, -1111630751, -1953790451, -1970633457, - 1886425312, 1044267644, -1246378895, 1718004428, - 1212733584, 50529542, -151649801, 235803164, - 1633788866, 892690282, 1465383342, -1179004823, - -2038001385, -1044293479, 488449850, -1633765081, - -505333543, -117959701, -1734823125, 286339874, - 1768537042, -640061271, -1903261433, -1802197197, - -1684294099, 505291324, -2021158379, -370597687, - -825341561, 1431699370, 673740880, -539002203, - -1936945405, -1583220647, -1987477495, 218961690, - -1077945755, -421121577, 1111672452, 1751693520, - 1094828930, -1717981143, 757954394, 252645662, - -1330590853, 1414855848, -1145317779, 370555436 + 1667474886, 2088535288, 2004326894, 2071694838, -219017729, 1802223062, 1869591006, -976923503, 808472672, 16843522, 1734846926, 724270422, + -16901657, -673750347, -1414797747, 1987484396, -892713585, -2105369313, -909557623, 2105378810, -84273681, 1499065266, 1195886990, -252703749, + -1381110719, -724277325, -1566376609, -1347425723, -1667449053, -1532692653, 1920112356, -1061135461, -1212693899, -33743647, -1819038147, 640051788, + 909531756, 1061110142, -134806795, -859025533, 875846760, -1515850671, -437963567, -235861767, 1903268834, -656903253, 825316194, 353713962, + 67374088, -943238507, 589522246, -1010606435, 404236336, -1768513225, 84217610, -1701137105, 117901582, 303183396, -2139055333, -488489505, + -336910643, 656894286, -1296904833, 1970642922, 151591698, -2088526307, 741110872, 437923380, 454765878, 1852748508, 1515908788, -1600062629, + 1381168804, 993742198, -690593353, -1280061827, 690584402, -471646499, 791638366, -2071685357, 1398011302, -774805319, 0, -303223615, + 538992704, -50585629, -1313748871, 1532751286, 1785380564, -875870579, -1094788761, 960056178, 1246420628, 1280103576, 1482221744, -808498555, + -791647301, -269538619, -1431640753, -67430675, 1128514950, 1296947098, 859002214, -2054843375, 1162203018, -101117719, 33687044, 2139062782, + 1347481760, 1010582648, -1616922075, -1465326773, 1364325282, -1549533603, 1077985408, -1886418427, -1835881153, -1650607071, 943212656, -168491791, + -1128472733, -1229536905, -623217233, 555836226, 269496352, -58651, -202174723, -757961281, -842183551, 202118168, 320025894, -320065597, + 1600119230, -1751670219, 1145359496, 387397934, -993765485, -1482165675, 2122220284, 1027426170, 1684319432, 1566435258, 421079858, 1936954854, + 1616945344, -2122213351, 1330631070, -589529181, 572679748, 707427924, -1869567173, -2004319477, 1179044492, -286381625, -1195846805, 336870440, + -555845209, 1583276732, 185277718, -606374227, -522175525, 842159716, 976899700, 168435220, 1229577106, 101059084, 606366792, 1549591736, + -1027449441, -741118275, -1397952701, 1650632388, -1852725191, -1785355215, -454805549, 2038008818, -404278571, -926399605, 926374254, 1835907034, + -1920103423, -707435343, 1313788572, -1448484791, 1819063512, 1448540844, -185333773, -353753649, 1701162954, 2054852340, -1364268729, 134748176, + -1162160785, 2021165296, 623210314, 774795868, 471606328, -1499008681, -1263220877, -960081513, -387439669, -572687199, 1953799400, 522133822, + 1263263126, -1111630751, -1953790451, -1970633457, 1886425312, 1044267644, -1246378895, 1718004428, 1212733584, 50529542, -151649801, 235803164, + 1633788866, 892690282, 1465383342, -1179004823, -2038001385, -1044293479, 488449850, -1633765081, -505333543, -117959701, -1734823125, 286339874, + 1768537042, -640061271, -1903261433, -1802197197, -1684294099, 505291324, -2021158379, -370597687, -825341561, 1431699370, 673740880, -539002203, + -1936945405, -1583220647, -1987477495, 218961690, -1077945755, -421121577, 1111672452, 1751693520, 1094828930, -1717981143, 757954394, 252645662, + -1330590853, 1414855848, -1145317779, 370555436 }; const int CRijndael::sm_T5[256] = { - 1374988112, 2118214995, 437757123, 975658646, - 1001089995, 530400753, -1392879445, 1273168787, - 540080725, -1384747530, -1999866223, -184398811, - 1340463100, -987051049, 641025152, -1251826801, - -558802359, 632953703, 1172967064, 1576976609, - -1020300030, -2125664238, -1924753501, 1809054150, - 59727847, 361929877, -1083344149, -1789765158, - -725712083, 1484005843, 1239443753, -1899378620, - 1975683434, -191989384, -1722270101, 666464733, - -1092530250, -259478249, -920605594, 2110667444, - 1675577880, -451268222, -1756286112, 1649639237, - -1318815776, -1150570876, -25059300, -116905068, - 1883793496, -1891238631, -1797362553, 1383856311, - -1418472669, 1917518562, -484470953, 1716890410, - -1293211641, 800440835, -2033878118, -751368027, - 807962610, 599762354, 33778362, -317291940, - -1966138325, -1485196142, -217582864, 1315562145, - 1708848333, 101039829, -785096161, -995688822, - 875451293, -1561111136, 92987698, -1527321739, - 193195065, 1080094634, 1584504582, -1116860335, - 1042385657, -1763899843, -583137874, 1306967366, - -1856729675, 1908694277, 67556463, 1615861247, - 429456164, -692196969, -1992277044, 1742315127, - -1326955843, 126454664, -417768648, 2043211483, - -1585706425, 2084704233, -125559095, 0, - 159417987, 841739592, 504459436, 1817866830, - -49348613, 260388950, 1034867998, 908933415, - 168810852, 1750902305, -1688513327, 607530554, - 202008497, -1822955761, -1259432238, 463180190, - -2134850225, 1641816226, 1517767529, 470948374, - -493635062, -1063245083, 1008918595, 303765277, - 235474187, -225720403, 766945465, 337553864, - 1475418501, -1351284916, -291906117, -1551933187, - -150919521, 1551037884, 1147550661, 1543208500, - -1958532746, -886847780, -1225917336, -1192955549, - -684598070, 1113818384, 328671808, -2067394272, - -2058738563, -759480840, -1359400431, -953573011, - 496906059, -592301837, 226906860, 2009195472, - 733156972, -1452230247, 294930682, 1206477858, - -1459843900, -1594867942, 1451044056, 573804783, - -2025238841, -650587711, -1932877058, -1730933962, - -1493859889, -1518674392, -625504730, 1068351396, - 742039012, 1350078989, 1784663195, 1417561698, - -158526526, -1864845080, 775550814, -2101104651, - -1621262146, 1775276924, 1876241833, -819653965, - -928212677, 270040487, -392404114, -616842373, - -853116919, 1851332852, -325404927, -2091935064, - -426414491, -1426069890, 566021896, -283776794, - -1159226407, 1248802510, -358676012, 699432150, - 832877231, 708780849, -962227152, 899835584, - 1951317047, -58537306, -527380304, 866637845, - -251357110, 1106041591, 2144161806, 395441711, - 1984812685, 1139781709, -861254316, -459930401, - -1630423581, 1282050075, -1054072904, 1181045119, - -1654724092, 25965917, -91786125, -83148498, - -1285087910, -1831087534, -384805325, 1842759443, - -1697160820, 933301370, 1509430414, -351060855, - -827774994, -1218328267, -518199827, 2051518780, - -1663901863, 1441952575, 404016761, 1942435775, - 1408749034, 1610459739, -549621996, 2017778566, - -894438527, -1184316354, 941896748, -1029488545, - 371049330, -1126030068, 675039627, -15887039, - 967311729, 135050206, -659233636, 1683407248, - 2076935265, -718096784, 1215061108, -793225406 + 1374988112, 2118214995, 437757123, 975658646, 1001089995, 530400753, -1392879445, 1273168787, 540080725, -1384747530, -1999866223, -184398811, + 1340463100, -987051049, 641025152, -1251826801, -558802359, 632953703, 1172967064, 1576976609, -1020300030, -2125664238, -1924753501, 1809054150, + 59727847, 361929877, -1083344149, -1789765158, -725712083, 1484005843, 1239443753, -1899378620, 1975683434, -191989384, -1722270101, 666464733, + -1092530250, -259478249, -920605594, 2110667444, 1675577880, -451268222, -1756286112, 1649639237, -1318815776, -1150570876, -25059300, -116905068, + 1883793496, -1891238631, -1797362553, 1383856311, -1418472669, 1917518562, -484470953, 1716890410, -1293211641, 800440835, -2033878118, -751368027, + 807962610, 599762354, 33778362, -317291940, -1966138325, -1485196142, -217582864, 1315562145, 1708848333, 101039829, -785096161, -995688822, + 875451293, -1561111136, 92987698, -1527321739, 193195065, 1080094634, 1584504582, -1116860335, 1042385657, -1763899843, -583137874, 1306967366, + -1856729675, 1908694277, 67556463, 1615861247, 429456164, -692196969, -1992277044, 1742315127, -1326955843, 126454664, -417768648, 2043211483, + -1585706425, 2084704233, -125559095, 0, 159417987, 841739592, 504459436, 1817866830, -49348613, 260388950, 1034867998, 908933415, + 168810852, 1750902305, -1688513327, 607530554, 202008497, -1822955761, -1259432238, 463180190, -2134850225, 1641816226, 1517767529, 470948374, + -493635062, -1063245083, 1008918595, 303765277, 235474187, -225720403, 766945465, 337553864, 1475418501, -1351284916, -291906117, -1551933187, + -150919521, 1551037884, 1147550661, 1543208500, -1958532746, -886847780, -1225917336, -1192955549, -684598070, 1113818384, 328671808, -2067394272, + -2058738563, -759480840, -1359400431, -953573011, 496906059, -592301837, 226906860, 2009195472, 733156972, -1452230247, 294930682, 1206477858, + -1459843900, -1594867942, 1451044056, 573804783, -2025238841, -650587711, -1932877058, -1730933962, -1493859889, -1518674392, -625504730, 1068351396, + 742039012, 1350078989, 1784663195, 1417561698, -158526526, -1864845080, 775550814, -2101104651, -1621262146, 1775276924, 1876241833, -819653965, + -928212677, 270040487, -392404114, -616842373, -853116919, 1851332852, -325404927, -2091935064, -426414491, -1426069890, 566021896, -283776794, + -1159226407, 1248802510, -358676012, 699432150, 832877231, 708780849, -962227152, 899835584, 1951317047, -58537306, -527380304, 866637845, + -251357110, 1106041591, 2144161806, 395441711, 1984812685, 1139781709, -861254316, -459930401, -1630423581, 1282050075, -1054072904, 1181045119, + -1654724092, 25965917, -91786125, -83148498, -1285087910, -1831087534, -384805325, 1842759443, -1697160820, 933301370, 1509430414, -351060855, + -827774994, -1218328267, -518199827, 2051518780, -1663901863, 1441952575, 404016761, 1942435775, 1408749034, 1610459739, -549621996, 2017778566, + -894438527, -1184316354, 941896748, -1029488545, 371049330, -1126030068, 675039627, -15887039, 967311729, 135050206, -659233636, 1683407248, + 2076935265, -718096784, 1215061108, -793225406 }; const int CRijndael::sm_T6[256] = { - 1347548327, 1400783205, -1021700188, -1774573730, - -885281941, -249586363, -1414727080, -1823743229, - 1428173050, -156404115, -1853305738, 636813900, - -61872681, -674944309, -2144979644, -1883938141, - 1239331162, 1730525723, -1740248562, -513933632, - 46346101, 310463728, -1551022441, -966011911, - -419197089, -1793748324, -339776134, -627748263, - 768917123, -749177823, 692707433, 1150208456, - 1786102409, 2029293177, 1805211710, -584599183, - -1229004465, 401639597, 1724457132, -1266823622, - 409198410, -2098914767, 1620529459, 1164071807, - -525245321, -2068091986, 486441376, -1795618773, - 1483753576, 428819965, -2020286868, -1219331080, - 598438867, -495826174, 1474502543, 711349675, - 129166120, 53458370, -1702443653, -1512884472, - -231724921, -1306280027, -1174273174, 1559041666, - 730517276, -1834518092, -252508174, -1588696606, - -848962828, -721025602, 533804130, -1966823682, - -1657524653, -1599933611, 839224033, 1973745387, - 957055980, -1438621457, 106852767, 1371368976, - -113368694, 1033297158, -1361232379, 1179510461, - -1248766835, 91341917, 1862534868, -10465259, - 605657339, -1747534359, -863420349, 2003294622, - -1112479678, -2012771957, 954669403, -612775698, - 1201765386, -377732593, -906460130, 0, - -2096529274, 1211247597, -1407315600, 1315723890, - -67301633, 1443857720, 507358933, 657861945, - 1678381017, 560487590, -778347692, 975451694, - -1324610969, 261314535, -759894378, -1642357871, - 1333838021, -1570644960, 1767536459, 370938394, - 182621114, -440360918, 1128014560, 487725847, - 185469197, -1376613433, -1188186456, -938205527, - -2057834215, 1286567175, -1141990947, -39616672, - -1611202266, -1134791947, -985373125, 878443390, - 1988838185, -590666810, 1756818940, 1673061617, - -891866660, 272786309, 1075025698, 545572369, - 2105887268, -120407235, 296679730, 1841768865, - 1260232239, -203640272, -334657966, -797457949, - 1814803222, -1716948807, -99511224, 575138148, - -995558260, 446754879, -665420500, -282971248, - -947435186, -1042728751, -24327518, 915985419, - -811141759, 681933534, 651868046, -1539330625, - -466863459, 223377554, -1687527476, 1649704518, - -1024029421, -393160520, 1580087799, -175979601, - -1096852096, 2087309459, -1452288723, -1278270190, - 1003007129, -1492117379, 1860738147, 2077965243, - 164439672, -194094824, 32283319, -1467789414, - 1709610350, 2125135846, 136428751, -420538904, - -642062437, -833982666, -722821367, -701910916, - -1355701070, 824852259, 818324884, -1070226842, - 930369212, -1493400886, -1327460144, 355706840, - 1257309336, -146674470, 243256656, 790073846, - -1921626666, 1296297904, 1422699085, -538667516, - -476130891, 457992840, -1195299809, 2135319889, - 77422314, 1560382517, 1945798516, 788204353, - 1521706781, 1385356242, 870912086, 325965383, - -1936009375, 2050466060, -1906706412, -1981082820, - -288446169, 901210569, -304014107, 1014646705, - 1503449823, 1062597235, 2031621326, -1082931401, - -363595827, 1533017514, 350174575, -2038938405, - -2117423117, 1052338372, 741876788, 1606591296, - 1914052035, 213705253, -1960297399, 1107234197, - 1899603969, -569897805, -1663519516, -1872472383, - 1635502980, 1893020342, 1950903388, 1120974935 + 1347548327, 1400783205, -1021700188, -1774573730, -885281941, -249586363, -1414727080, -1823743229, 1428173050, -156404115, -1853305738, 636813900, + -61872681, -674944309, -2144979644, -1883938141, 1239331162, 1730525723, -1740248562, -513933632, 46346101, 310463728, -1551022441, -966011911, + -419197089, -1793748324, -339776134, -627748263, 768917123, -749177823, 692707433, 1150208456, 1786102409, 2029293177, 1805211710, -584599183, + -1229004465, 401639597, 1724457132, -1266823622, 409198410, -2098914767, 1620529459, 1164071807, -525245321, -2068091986, 486441376, -1795618773, + 1483753576, 428819965, -2020286868, -1219331080, 598438867, -495826174, 1474502543, 711349675, 129166120, 53458370, -1702443653, -1512884472, + -231724921, -1306280027, -1174273174, 1559041666, 730517276, -1834518092, -252508174, -1588696606, -848962828, -721025602, 533804130, -1966823682, + -1657524653, -1599933611, 839224033, 1973745387, 957055980, -1438621457, 106852767, 1371368976, -113368694, 1033297158, -1361232379, 1179510461, + -1248766835, 91341917, 1862534868, -10465259, 605657339, -1747534359, -863420349, 2003294622, -1112479678, -2012771957, 954669403, -612775698, + 1201765386, -377732593, -906460130, 0, -2096529274, 1211247597, -1407315600, 1315723890, -67301633, 1443857720, 507358933, 657861945, + 1678381017, 560487590, -778347692, 975451694, -1324610969, 261314535, -759894378, -1642357871, 1333838021, -1570644960, 1767536459, 370938394, + 182621114, -440360918, 1128014560, 487725847, 185469197, -1376613433, -1188186456, -938205527, -2057834215, 1286567175, -1141990947, -39616672, + -1611202266, -1134791947, -985373125, 878443390, 1988838185, -590666810, 1756818940, 1673061617, -891866660, 272786309, 1075025698, 545572369, + 2105887268, -120407235, 296679730, 1841768865, 1260232239, -203640272, -334657966, -797457949, 1814803222, -1716948807, -99511224, 575138148, + -995558260, 446754879, -665420500, -282971248, -947435186, -1042728751, -24327518, 915985419, -811141759, 681933534, 651868046, -1539330625, + -466863459, 223377554, -1687527476, 1649704518, -1024029421, -393160520, 1580087799, -175979601, -1096852096, 2087309459, -1452288723, -1278270190, + 1003007129, -1492117379, 1860738147, 2077965243, 164439672, -194094824, 32283319, -1467789414, 1709610350, 2125135846, 136428751, -420538904, + -642062437, -833982666, -722821367, -701910916, -1355701070, 824852259, 818324884, -1070226842, 930369212, -1493400886, -1327460144, 355706840, + 1257309336, -146674470, 243256656, 790073846, -1921626666, 1296297904, 1422699085, -538667516, -476130891, 457992840, -1195299809, 2135319889, + 77422314, 1560382517, 1945798516, 788204353, 1521706781, 1385356242, 870912086, 325965383, -1936009375, 2050466060, -1906706412, -1981082820, + -288446169, 901210569, -304014107, 1014646705, 1503449823, 1062597235, 2031621326, -1082931401, -363595827, 1533017514, 350174575, -2038938405, + -2117423117, 1052338372, 741876788, 1606591296, 1914052035, 213705253, -1960297399, 1107234197, 1899603969, -569897805, -1663519516, -1872472383, + 1635502980, 1893020342, 1950903388, 1120974935 }; const int CRijndael::sm_T7[256] = { - -1487908364, 1699970625, -1530717673, 1586903591, - 1808481195, 1173430173, 1487645946, 59984867, - -95084496, 1844882806, 1989249228, 1277555970, - -671330331, -875051734, 1149249077, -1550863006, - 1514790577, 459744698, 244860394, -1058972162, - 1963115311, -267222708, -1750889146, -104436781, - 1608975247, -1667951214, 2062270317, 1507497298, - -2094148418, 567498868, 1764313568, -935031095, - -1989511742, 2037970062, 1047239000, 1910319033, - 1337376481, -1390940024, -1402549984, 984907214, - 1243112415, 830661914, 861968209, 2135253587, - 2011214180, -1367032981, -1608712575, 731183368, - 1750626376, -48656571, 1820824798, -122203525, - -752637069, 48394827, -1890065633, -1423284651, - 671593195, -1039978571, 2073724613, 145085239, - -2014171096, -1515052097, 1790575107, -2107839210, - 472615631, -1265457287, -219090169, -492745111, - -187865638, -1093335547, 1646252340, -24460122, - 1402811438, 1436590835, -516815478, -344611594, - -331805821, -274055072, -1626972559, 273792366, - -1963377119, 104699613, 95345982, -1119466010, - -1917480620, 1560637892, -730921978, 369057872, - -81520232, -375925059, 1137477952, -1636341799, - 1119727848, -1954019447, 1530455833, -287606328, - 172466556, 266959938, 516552836, 0, - -2038232704, -314035669, 1890328081, 1917742170, - -262898, 945164165, -719438418, 958871085, - -647755249, -1507760036, 1423022939, 775562294, - 1739656202, -418409641, -1764576018, -1851909221, - -984645440, 547512796, 1265195639, 437656594, - -1173691757, 719700128, -532464606, 387781147, - 218828297, -944901493, -1464259146, -1446505442, - 428169201, 122466165, -574886247, 1627235199, - 648017665, -172204942, 1002783846, 2117360635, - 695634755, -958608605, -60246291, -245122844, - -590686415, -2062531997, 574624663, 287343814, - 612205898, 1039717051, 840019705, -1586641111, - 793451934, 821288114, 1391201670, -472877119, - 376187827, -1181111952, 1224348052, 1679968233, - -1933268740, 1058709744, 752375421, -1863376333, - 1321699145, -775825096, -1560376118, 188127444, - -2117097739, -567761542, -1910056265, -1079754835, - -1645990854, -1844621192, -862229921, 1180849278, - 331544205, -1192718120, -144822727, -1342864701, - -2134991011, -1820562992, 766078933, 313773861, - -1724135252, 2108100632, 1668212892, -1149510853, - 2013908262, 418672217, -1224610662, -1700232369, - 1852171925, -427906305, -821550660, -387518699, - -1680229657, 919489135, 164948639, 2094410160, - -1297141340, 590424639, -1808742747, 1723872674, - -1137216434, -895026046, -793714544, -669699161, - -1739919100, -621329940, 1343127501, -164685935, - -695372211, -1337113617, 1297403050, 81781910, - -1243373871, -2011476886, 532201772, 1367295589, - -368796322, 895287692, 1953757831, 1093597963, - 492483431, -766340389, 1446242576, 1192455638, - 1636604631, 209336225, 344873464, 1015671571, - 669961897, -919226527, -437395172, -1321436601, - -547775278, 1933530610, -830924780, 935293895, - -840281097, -1436852227, 1863638845, -611944380, - -209597777, -1002522264, 875313188, 1080017571, - -1015933411, 621591778, 1233856572, -1790836979, - 24197544, -1277294580, -459482956, -1047501738, - -2073986101, -1234119374, 1551124588, 1463996600 + -1487908364, 1699970625, -1530717673, 1586903591, 1808481195, 1173430173, 1487645946, 59984867, -95084496, 1844882806, 1989249228, 1277555970, + -671330331, -875051734, 1149249077, -1550863006, 1514790577, 459744698, 244860394, -1058972162, 1963115311, -267222708, -1750889146, -104436781, + 1608975247, -1667951214, 2062270317, 1507497298, -2094148418, 567498868, 1764313568, -935031095, -1989511742, 2037970062, 1047239000, 1910319033, + 1337376481, -1390940024, -1402549984, 984907214, 1243112415, 830661914, 861968209, 2135253587, 2011214180, -1367032981, -1608712575, 731183368, + 1750626376, -48656571, 1820824798, -122203525, -752637069, 48394827, -1890065633, -1423284651, 671593195, -1039978571, 2073724613, 145085239, + -2014171096, -1515052097, 1790575107, -2107839210, 472615631, -1265457287, -219090169, -492745111, -187865638, -1093335547, 1646252340, -24460122, + 1402811438, 1436590835, -516815478, -344611594, -331805821, -274055072, -1626972559, 273792366, -1963377119, 104699613, 95345982, -1119466010, + -1917480620, 1560637892, -730921978, 369057872, -81520232, -375925059, 1137477952, -1636341799, 1119727848, -1954019447, 1530455833, -287606328, + 172466556, 266959938, 516552836, 0, -2038232704, -314035669, 1890328081, 1917742170, -262898, 945164165, -719438418, 958871085, + -647755249, -1507760036, 1423022939, 775562294, 1739656202, -418409641, -1764576018, -1851909221, -984645440, 547512796, 1265195639, 437656594, + -1173691757, 719700128, -532464606, 387781147, 218828297, -944901493, -1464259146, -1446505442, 428169201, 122466165, -574886247, 1627235199, + 648017665, -172204942, 1002783846, 2117360635, 695634755, -958608605, -60246291, -245122844, -590686415, -2062531997, 574624663, 287343814, + 612205898, 1039717051, 840019705, -1586641111, 793451934, 821288114, 1391201670, -472877119, 376187827, -1181111952, 1224348052, 1679968233, + -1933268740, 1058709744, 752375421, -1863376333, 1321699145, -775825096, -1560376118, 188127444, -2117097739, -567761542, -1910056265, -1079754835, + -1645990854, -1844621192, -862229921, 1180849278, 331544205, -1192718120, -144822727, -1342864701, -2134991011, -1820562992, 766078933, 313773861, + -1724135252, 2108100632, 1668212892, -1149510853, 2013908262, 418672217, -1224610662, -1700232369, 1852171925, -427906305, -821550660, -387518699, + -1680229657, 919489135, 164948639, 2094410160, -1297141340, 590424639, -1808742747, 1723872674, -1137216434, -895026046, -793714544, -669699161, + -1739919100, -621329940, 1343127501, -164685935, -695372211, -1337113617, 1297403050, 81781910, -1243373871, -2011476886, 532201772, 1367295589, + -368796322, 895287692, 1953757831, 1093597963, 492483431, -766340389, 1446242576, 1192455638, 1636604631, 209336225, 344873464, 1015671571, + 669961897, -919226527, -437395172, -1321436601, -547775278, 1933530610, -830924780, 935293895, -840281097, -1436852227, 1863638845, -611944380, + -209597777, -1002522264, 875313188, 1080017571, -1015933411, 621591778, 1233856572, -1790836979, 24197544, -1277294580, -459482956, -1047501738, + -2073986101, -1234119374, 1551124588, 1463996600 }; const int CRijndael::sm_T8[256] = { - -190361519, 1097159550, 396673818, 660510266, - -1418998981, -1656360673, -94852180, -486304949, - 821712160, 1986918061, -864644728, 38544885, - -438830001, 718002117, 893681702, 1654886325, - -1319482914, -1172609243, -368142267, -20913827, - 796197571, 1290801793, 1184342925, -738605461, - -1889540349, -1835231979, 1836772287, 1381620373, - -1098699308, 1948373848, -529979063, -909622130, - -1031181707, -1904641804, 1480485785, -1183720153, - -514869570, -2001922064, 548169417, -835013507, - -548792221, 439452389, 1362321559, 1400849762, - 1685577905, 1806599355, -2120213250, 137073913, - 1214797936, 1174215055, -563312748, 2079897426, - 1943217067, 1258480242, 529487843, 1437280870, - -349698126, -1245576401, -981755258, 923313619, - 679998000, -1079659997, 57326082, 377642221, - -820237430, 2041877159, 133361907, 1776460110, - -621490843, 96392454, 878845905, -1493267772, - 777231668, -212492126, -1964953083, -152341084, - -2081670901, 1626319424, 1906247262, 1846563261, - 562755902, -586793578, 1040559837, -423803315, - 1418573201, -1000536719, 114585348, 1343618912, - -1728371687, -1108764714, 1078185097, -643926169, - -398279248, -1987344377, 425408743, -923870343, - 2081048481, 1108339068, -2078357000, 0, - -2138668279, 736970802, 292596766, 1517440620, - 251657213, -2059905521, -1361764803, 758720310, - 265905162, 1554391400, 1532285339, 908999204, - 174567692, 1474760595, -292105548, -1684955621, - -1060810880, -601841055, 2001430874, 303699484, - -1816524062, -1607801408, 585122620, 454499602, - 151849742, -1949848078, -1230456531, 514443284, - -249985705, 1963412655, -1713521682, 2137062819, - 19308535, 1928707164, 1715193156, -75615141, - 1126790795, 600235211, -302225226, -453942344, - 836553431, 1669664834, -1759363053, -971956092, - 1243905413, -1153566510, -114159186, 698445255, - -1641067747, -1305414692, -2041385971, -1042034569, - -1290376149, 1891211689, -1807156719, -379313593, - -57883480, -264299872, 2100090966, 865136418, - 1229899655, 953270745, -895287668, -737462632, - -176042074, 2061379749, -1215420710, -1379949505, - 983426092, 2022837584, 1607244650, 2118541908, - -1928084746, -658970480, 972512814, -1011878526, - 1568718495, -795640727, -718427793, 621982671, - -1399243832, 410887952, -1671205144, 1002142683, - 645401037, 1494807662, -1699282452, 1335535747, - -1787927066, -1671510, -1127282655, 367585007, - -409216582, 1865862730, -1626745622, -1333995991, - -1531793615, 1059270954, -1517014842, -1570324427, - 1320957812, -2100648196, -1865371424, -1479011021, - 77089521, -321194175, -850391425, -1846137065, - 1305906550, -273658557, -1437772596, -1778065436, - -776608866, 1787304780, 740276417, 1699839814, - 1592394909, -1942659839, -2022411270, 188821243, - 1729977011, -606973294, 274084841, -699985043, - -681472870, -1593017801, -132870567, 322734571, - -1457000754, 1640576439, 484830689, 1202797690, - -757114468, -227328171, 349075736, -952647821, - -137500077, -39167137, 1030690015, 1155237496, - -1342996022, 1757691577, 607398968, -1556062270, - 499347990, -500888388, 1011452712, 227885567, - -1476300487, 213114376, -1260086056, 1455525988, - -880516741, 850817237, 1817998408, -1202240816 + -190361519, 1097159550, 396673818, 660510266, -1418998981, -1656360673, -94852180, -486304949, 821712160, 1986918061, -864644728, 38544885, + -438830001, 718002117, 893681702, 1654886325, -1319482914, -1172609243, -368142267, -20913827, 796197571, 1290801793, 1184342925, -738605461, + -1889540349, -1835231979, 1836772287, 1381620373, -1098699308, 1948373848, -529979063, -909622130, -1031181707, -1904641804, 1480485785, -1183720153, + -514869570, -2001922064, 548169417, -835013507, -548792221, 439452389, 1362321559, 1400849762, 1685577905, 1806599355, -2120213250, 137073913, + 1214797936, 1174215055, -563312748, 2079897426, 1943217067, 1258480242, 529487843, 1437280870, -349698126, -1245576401, -981755258, 923313619, + 679998000, -1079659997, 57326082, 377642221, -820237430, 2041877159, 133361907, 1776460110, -621490843, 96392454, 878845905, -1493267772, + 777231668, -212492126, -1964953083, -152341084, -2081670901, 1626319424, 1906247262, 1846563261, 562755902, -586793578, 1040559837, -423803315, + 1418573201, -1000536719, 114585348, 1343618912, -1728371687, -1108764714, 1078185097, -643926169, -398279248, -1987344377, 425408743, -923870343, + 2081048481, 1108339068, -2078357000, 0, -2138668279, 736970802, 292596766, 1517440620, 251657213, -2059905521, -1361764803, 758720310, + 265905162, 1554391400, 1532285339, 908999204, 174567692, 1474760595, -292105548, -1684955621, -1060810880, -601841055, 2001430874, 303699484, + -1816524062, -1607801408, 585122620, 454499602, 151849742, -1949848078, -1230456531, 514443284, -249985705, 1963412655, -1713521682, 2137062819, + 19308535, 1928707164, 1715193156, -75615141, 1126790795, 600235211, -302225226, -453942344, 836553431, 1669664834, -1759363053, -971956092, + 1243905413, -1153566510, -114159186, 698445255, -1641067747, -1305414692, -2041385971, -1042034569, -1290376149, 1891211689, -1807156719, -379313593, + -57883480, -264299872, 2100090966, 865136418, 1229899655, 953270745, -895287668, -737462632, -176042074, 2061379749, -1215420710, -1379949505, + 983426092, 2022837584, 1607244650, 2118541908, -1928084746, -658970480, 972512814, -1011878526, 1568718495, -795640727, -718427793, 621982671, + -1399243832, 410887952, -1671205144, 1002142683, 645401037, 1494807662, -1699282452, 1335535747, -1787927066, -1671510, -1127282655, 367585007, + -409216582, 1865862730, -1626745622, -1333995991, -1531793615, 1059270954, -1517014842, -1570324427, 1320957812, -2100648196, -1865371424, -1479011021, + 77089521, -321194175, -850391425, -1846137065, 1305906550, -273658557, -1437772596, -1778065436, -776608866, 1787304780, 740276417, 1699839814, + 1592394909, -1942659839, -2022411270, 188821243, 1729977011, -606973294, 274084841, -699985043, -681472870, -1593017801, -132870567, 322734571, + -1457000754, 1640576439, 484830689, 1202797690, -757114468, -227328171, 349075736, -952647821, -137500077, -39167137, 1030690015, 1155237496, + -1342996022, 1757691577, 607398968, -1556062270, 499347990, -500888388, 1011452712, 227885567, -1476300487, 213114376, -1260086056, 1455525988, + -880516741, 850817237, 1817998408, -1202240816 }; const int CRijndael::sm_U1[256] = { - 0, 235474187, 470948374, 303765277, - 941896748, 908933415, 607530554, 708780849, - 1883793496, 2118214995, 1817866830, 1649639237, - 1215061108, 1181045119, 1417561698, 1517767529, - -527380304, -291906117, -58537306, -225720403, - -659233636, -692196969, -995688822, -894438527, - -1864845080, -1630423581, -1932877058, -2101104651, - -1459843900, -1493859889, -1259432238, -1159226407, - -616842373, -718096784, -953573011, -920605594, - -484470953, -317291940, -15887039, -251357110, - -1418472669, -1518674392, -1218328267, -1184316354, - -1822955761, -1654724092, -1891238631, -2125664238, - 1001089995, 899835584, 666464733, 699432150, - 59727847, 226906860, 530400753, 294930682, - 1273168787, 1172967064, 1475418501, 1509430414, - 1942435775, 2110667444, 1876241833, 1641816226, - -1384747530, -1551933187, -1318815776, -1083344149, - -1789765158, -1688513327, -1992277044, -2025238841, - -583137874, -751368027, -1054072904, -819653965, - -451268222, -351060855, -116905068, -150919521, - 1306967366, 1139781709, 1374988112, 1610459739, - 1975683434, 2076935265, 1775276924, 1742315127, - 1034867998, 866637845, 566021896, 800440835, - 92987698, 193195065, 429456164, 395441711, - 1984812685, 2017778566, 1784663195, 1683407248, - 1315562145, 1080094634, 1383856311, 1551037884, - 101039829, 135050206, 437757123, 337553864, - 1042385657, 807962610, 573804783, 742039012, - -1763899843, -1730933962, -1966138325, -2067394272, - -1359400431, -1594867942, -1293211641, -1126030068, - -426414491, -392404114, -91786125, -191989384, - -558802359, -793225406, -1029488545, -861254316, - 1106041591, 1340463100, 1576976609, 1408749034, - 2043211483, 2009195472, 1708848333, 1809054150, - 832877231, 1068351396, 766945465, 599762354, - 159417987, 126454664, 361929877, 463180190, - -1585706425, -1351284916, -1116860335, -1285087910, - -1722270101, -1756286112, -2058738563, -1958532746, - -785096161, -549621996, -853116919, -1020300030, - -384805325, -417768648, -184398811, -83148498, - -1697160820, -1797362553, -2033878118, -1999866223, - -1561111136, -1392879445, -1092530250, -1326955843, - -358676012, -459930401, -158526526, -125559095, - -759480840, -592301837, -827774994, -1063245083, - 2051518780, 1951317047, 1716890410, 1750902305, - 1113818384, 1282050075, 1584504582, 1350078989, - 168810852, 67556463, 371049330, 404016761, - 841739592, 1008918595, 775550814, 540080725, - -325404927, -493635062, -259478249, -25059300, - -725712083, -625504730, -928212677, -962227152, - -1663901863, -1831087534, -2134850225, -1899378620, - -1527321739, -1426069890, -1192955549, -1225917336, - 202008497, 33778362, 270040487, 504459436, - 875451293, 975658646, 675039627, 641025152, - 2084704233, 1917518562, 1615861247, 1851332852, - 1147550661, 1248802510, 1484005843, 1451044056, - 933301370, 967311729, 733156972, 632953703, - 260388950, 25965917, 328671808, 496906059, - 1206477858, 1239443753, 1543208500, 1441952575, - 2144161806, 1908694277, 1675577880, 1842759443, - -684598070, -650587711, -886847780, -987051049, - -283776794, -518199827, -217582864, -49348613, - -1485196142, -1452230247, -1150570876, -1251826801, + 0, 235474187, 470948374, 303765277, 941896748, 908933415, 607530554, 708780849, 1883793496, 2118214995, 1817866830, 1649639237, + 1215061108, 1181045119, 1417561698, 1517767529, -527380304, -291906117, -58537306, -225720403, -659233636, -692196969, -995688822, -894438527, + -1864845080, -1630423581, -1932877058, -2101104651, -1459843900, -1493859889, -1259432238, -1159226407, -616842373, -718096784, -953573011, -920605594, + -484470953, -317291940, -15887039, -251357110, -1418472669, -1518674392, -1218328267, -1184316354, -1822955761, -1654724092, -1891238631, -2125664238, + 1001089995, 899835584, 666464733, 699432150, 59727847, 226906860, 530400753, 294930682, 1273168787, 1172967064, 1475418501, 1509430414, + 1942435775, 2110667444, 1876241833, 1641816226, -1384747530, -1551933187, -1318815776, -1083344149, -1789765158, -1688513327, -1992277044, -2025238841, + -583137874, -751368027, -1054072904, -819653965, -451268222, -351060855, -116905068, -150919521, 1306967366, 1139781709, 1374988112, 1610459739, + 1975683434, 2076935265, 1775276924, 1742315127, 1034867998, 866637845, 566021896, 800440835, 92987698, 193195065, 429456164, 395441711, + 1984812685, 2017778566, 1784663195, 1683407248, 1315562145, 1080094634, 1383856311, 1551037884, 101039829, 135050206, 437757123, 337553864, + 1042385657, 807962610, 573804783, 742039012, -1763899843, -1730933962, -1966138325, -2067394272, -1359400431, -1594867942, -1293211641, -1126030068, + -426414491, -392404114, -91786125, -191989384, -558802359, -793225406, -1029488545, -861254316, 1106041591, 1340463100, 1576976609, 1408749034, + 2043211483, 2009195472, 1708848333, 1809054150, 832877231, 1068351396, 766945465, 599762354, 159417987, 126454664, 361929877, 463180190, + -1585706425, -1351284916, -1116860335, -1285087910, -1722270101, -1756286112, -2058738563, -1958532746, -785096161, -549621996, -853116919, -1020300030, + -384805325, -417768648, -184398811, -83148498, -1697160820, -1797362553, -2033878118, -1999866223, -1561111136, -1392879445, -1092530250, -1326955843, + -358676012, -459930401, -158526526, -125559095, -759480840, -592301837, -827774994, -1063245083, 2051518780, 1951317047, 1716890410, 1750902305, + 1113818384, 1282050075, 1584504582, 1350078989, 168810852, 67556463, 371049330, 404016761, 841739592, 1008918595, 775550814, 540080725, + -325404927, -493635062, -259478249, -25059300, -725712083, -625504730, -928212677, -962227152, -1663901863, -1831087534, -2134850225, -1899378620, + -1527321739, -1426069890, -1192955549, -1225917336, 202008497, 33778362, 270040487, 504459436, 875451293, 975658646, 675039627, 641025152, + 2084704233, 1917518562, 1615861247, 1851332852, 1147550661, 1248802510, 1484005843, 1451044056, 933301370, 967311729, 733156972, 632953703, + 260388950, 25965917, 328671808, 496906059, 1206477858, 1239443753, 1543208500, 1441952575, 2144161806, 1908694277, 1675577880, 1842759443, + -684598070, -650587711, -886847780, -987051049, -283776794, -518199827, -217582864, -49348613, -1485196142, -1452230247, -1150570876, -1251826801, -1621262146, -1856729675, -2091935064, -1924753501 }; const int CRijndael::sm_U2[256] = { - 0, 185469197, 370938394, 487725847, - 741876788, 657861945, 975451694, 824852259, - 1483753576, 1400783205, 1315723890, 1164071807, - 1950903388, 2135319889, 1649704518, 1767536459, - -1327460144, -1141990947, -1493400886, -1376613433, - -1663519516, -1747534359, -1966823682, -2117423117, - -393160520, -476130891, -24327518, -175979601, - -995558260, -811141759, -759894378, -642062437, - 2077965243, 1893020342, 1841768865, 1724457132, - 1474502543, 1559041666, 1107234197, 1257309336, - 598438867, 681933534, 901210569, 1052338372, - 261314535, 77422314, 428819965, 310463728, - -885281941, -1070226842, -584599183, -701910916, - -419197089, -334657966, -249586363, -99511224, - -1823743229, -1740248562, -2057834215, -1906706412, - -1082931401, -1266823622, -1452288723, -1570644960, - -156404115, -39616672, -525245321, -339776134, - -627748263, -778347692, -863420349, -947435186, - -1361232379, -1512884472, -1195299809, -1278270190, - -2098914767, -1981082820, -1795618773, -1611202266, - 1179510461, 1296297904, 1347548327, 1533017514, - 1786102409, 1635502980, 2087309459, 2003294622, - 507358933, 355706840, 136428751, 53458370, - 839224033, 957055980, 605657339, 790073846, - -1921626666, -2038938405, -1687527476, -1872472383, - -1588696606, -1438621457, -1219331080, -1134791947, - -721025602, -569897805, -1021700188, -938205527, - -113368694, -231724921, -282971248, -466863459, - 1033297158, 915985419, 730517276, 545572369, - 296679730, 446754879, 129166120, 213705253, - 1709610350, 1860738147, 1945798516, 2029293177, - 1239331162, 1120974935, 1606591296, 1422699085, - -146674470, -61872681, -513933632, -363595827, - -612775698, -797457949, -848962828, -966011911, - -1355701070, -1539330625, -1188186456, -1306280027, - -2096529274, -2012771957, -1793748324, -1642357871, - 1201765386, 1286567175, 1371368976, 1521706781, - 1805211710, 1620529459, 2105887268, 1988838185, - 533804130, 350174575, 164439672, 46346101, - 870912086, 954669403, 636813900, 788204353, - -1936009375, -2020286868, -1702443653, -1853305738, - -1599933611, -1414727080, -1229004465, -1112479678, - -722821367, -538667516, -1024029421, -906460130, - -120407235, -203640272, -288446169, -440360918, - 1014646705, 930369212, 711349675, 560487590, - 272786309, 457992840, 106852767, 223377554, - 1678381017, 1862534868, 1914052035, 2031621326, - 1211247597, 1128014560, 1580087799, 1428173050, - 32283319, 182621114, 401639597, 486441376, - 768917123, 651868046, 1003007129, 818324884, - 1503449823, 1385356242, 1333838021, 1150208456, - 1973745387, 2125135846, 1673061617, 1756818940, - -1324610969, -1174273174, -1492117379, -1407315600, - -1657524653, -1774573730, -1960297399, -2144979644, - -377732593, -495826174, -10465259, -194094824, - -985373125, -833982666, -749177823, -665420500, - 2050466060, 1899603969, 1814803222, 1730525723, - 1443857720, 1560382517, 1075025698, 1260232239, - 575138148, 692707433, 878443390, 1062597235, - 243256656, 91341917, 409198410, 325965383, - -891866660, -1042728751, -590666810, -674944309, - -420538904, -304014107, -252508174, -67301633, - -1834518092, -1716948807, -2068091986, -1883938141, + 0, 185469197, 370938394, 487725847, 741876788, 657861945, 975451694, 824852259, 1483753576, 1400783205, 1315723890, 1164071807, + 1950903388, 2135319889, 1649704518, 1767536459, -1327460144, -1141990947, -1493400886, -1376613433, -1663519516, -1747534359, -1966823682, -2117423117, + -393160520, -476130891, -24327518, -175979601, -995558260, -811141759, -759894378, -642062437, 2077965243, 1893020342, 1841768865, 1724457132, + 1474502543, 1559041666, 1107234197, 1257309336, 598438867, 681933534, 901210569, 1052338372, 261314535, 77422314, 428819965, 310463728, + -885281941, -1070226842, -584599183, -701910916, -419197089, -334657966, -249586363, -99511224, -1823743229, -1740248562, -2057834215, -1906706412, + -1082931401, -1266823622, -1452288723, -1570644960, -156404115, -39616672, -525245321, -339776134, -627748263, -778347692, -863420349, -947435186, + -1361232379, -1512884472, -1195299809, -1278270190, -2098914767, -1981082820, -1795618773, -1611202266, 1179510461, 1296297904, 1347548327, 1533017514, + 1786102409, 1635502980, 2087309459, 2003294622, 507358933, 355706840, 136428751, 53458370, 839224033, 957055980, 605657339, 790073846, + -1921626666, -2038938405, -1687527476, -1872472383, -1588696606, -1438621457, -1219331080, -1134791947, -721025602, -569897805, -1021700188, -938205527, + -113368694, -231724921, -282971248, -466863459, 1033297158, 915985419, 730517276, 545572369, 296679730, 446754879, 129166120, 213705253, + 1709610350, 1860738147, 1945798516, 2029293177, 1239331162, 1120974935, 1606591296, 1422699085, -146674470, -61872681, -513933632, -363595827, + -612775698, -797457949, -848962828, -966011911, -1355701070, -1539330625, -1188186456, -1306280027, -2096529274, -2012771957, -1793748324, -1642357871, + 1201765386, 1286567175, 1371368976, 1521706781, 1805211710, 1620529459, 2105887268, 1988838185, 533804130, 350174575, 164439672, 46346101, + 870912086, 954669403, 636813900, 788204353, -1936009375, -2020286868, -1702443653, -1853305738, -1599933611, -1414727080, -1229004465, -1112479678, + -722821367, -538667516, -1024029421, -906460130, -120407235, -203640272, -288446169, -440360918, 1014646705, 930369212, 711349675, 560487590, + 272786309, 457992840, 106852767, 223377554, 1678381017, 1862534868, 1914052035, 2031621326, 1211247597, 1128014560, 1580087799, 1428173050, + 32283319, 182621114, 401639597, 486441376, 768917123, 651868046, 1003007129, 818324884, 1503449823, 1385356242, 1333838021, 1150208456, + 1973745387, 2125135846, 1673061617, 1756818940, -1324610969, -1174273174, -1492117379, -1407315600, -1657524653, -1774573730, -1960297399, -2144979644, + -377732593, -495826174, -10465259, -194094824, -985373125, -833982666, -749177823, -665420500, 2050466060, 1899603969, 1814803222, 1730525723, + 1443857720, 1560382517, 1075025698, 1260232239, 575138148, 692707433, 878443390, 1062597235, 243256656, 91341917, 409198410, 325965383, + -891866660, -1042728751, -590666810, -674944309, -420538904, -304014107, -252508174, -67301633, -1834518092, -1716948807, -2068091986, -1883938141, -1096852096, -1248766835, -1467789414, -1551022441 }; const int CRijndael::sm_U3[256] = { - 0, 218828297, 437656594, 387781147, - 875313188, 958871085, 775562294, 590424639, - 1750626376, 1699970625, 1917742170, 2135253587, - 1551124588, 1367295589, 1180849278, 1265195639, - -793714544, -574886247, -895026046, -944901493, - -459482956, -375925059, -24460122, -209597777, - -1192718120, -1243373871, -1560376118, -1342864701, - -1933268740, -2117097739, -1764576018, -1680229657, - -1149510853, -1234119374, -1586641111, -1402549984, - -1890065633, -2107839210, -1790836979, -1739919100, - -752637069, -567761542, -919226527, -1002522264, - -418409641, -368796322, -48656571, -267222708, - 1808481195, 1723872674, 1910319033, 2094410160, - 1608975247, 1391201670, 1173430173, 1224348052, - 59984867, 244860394, 428169201, 344873464, - 935293895, 984907214, 766078933, 547512796, - 1844882806, 1627235199, 2011214180, 2062270317, - 1507497298, 1423022939, 1137477952, 1321699145, - 95345982, 145085239, 532201772, 313773861, - 830661914, 1015671571, 731183368, 648017665, - -1119466010, -1337113617, -1487908364, -1436852227, - -1989511742, -2073986101, -1820562992, -1636341799, - -719438418, -669699161, -821550660, -1039978571, - -516815478, -331805821, -81520232, -164685935, - -695372211, -611944380, -862229921, -1047501738, - -492745111, -274055072, -122203525, -172204942, - -1093335547, -1277294580, -1530717673, -1446505442, - -1963377119, -2014171096, -1863376333, -1645990854, - 104699613, 188127444, 472615631, 287343814, - 840019705, 1058709744, 671593195, 621591778, - 1852171925, 1668212892, 1953757831, 2037970062, - 1514790577, 1463996600, 1080017571, 1297403050, - -621329940, -671330331, -1058972162, -840281097, - -287606328, -472877119, -187865638, -104436781, - -1297141340, -1079754835, -1464259146, -1515052097, - -2038232704, -1954019447, -1667951214, -1851909221, - 172466556, 122466165, 273792366, 492483431, - 1047239000, 861968209, 612205898, 695634755, - 1646252340, 1863638845, 2013908262, 1963115311, - 1446242576, 1530455833, 1277555970, 1093597963, - 1636604631, 1820824798, 2073724613, 1989249228, - 1436590835, 1487645946, 1337376481, 1119727848, - 164948639, 81781910, 331544205, 516552836, - 1039717051, 821288114, 669961897, 719700128, - -1321436601, -1137216434, -1423284651, -1507760036, - -2062531997, -2011476886, -1626972559, -1844621192, - -647755249, -730921978, -1015933411, -830924780, - -314035669, -532464606, -144822727, -95084496, - -1224610662, -1173691757, -1390940024, -1608712575, - -2094148418, -1910056265, -1724135252, -1808742747, - -547775278, -766340389, -984645440, -935031095, - -344611594, -427906305, -245122844, -60246291, - 1739656202, 1790575107, 2108100632, 1890328081, - 1402811438, 1586903591, 1233856572, 1149249077, - 266959938, 48394827, 369057872, 418672217, - 1002783846, 919489135, 567498868, 752375421, - 209336225, 24197544, 376187827, 459744698, - 945164165, 895287692, 574624663, 793451934, - 1679968233, 1764313568, 2117360635, 1933530610, - 1343127501, 1560637892, 1243112415, 1192455638, - -590686415, -775825096, -958608605, -875051734, - -387518699, -437395172, -219090169, -262898, - -1265457287, -1181111952, -1367032981, -1550863006, + 0, 218828297, 437656594, 387781147, 875313188, 958871085, 775562294, 590424639, 1750626376, 1699970625, 1917742170, 2135253587, + 1551124588, 1367295589, 1180849278, 1265195639, -793714544, -574886247, -895026046, -944901493, -459482956, -375925059, -24460122, -209597777, + -1192718120, -1243373871, -1560376118, -1342864701, -1933268740, -2117097739, -1764576018, -1680229657, -1149510853, -1234119374, -1586641111, -1402549984, + -1890065633, -2107839210, -1790836979, -1739919100, -752637069, -567761542, -919226527, -1002522264, -418409641, -368796322, -48656571, -267222708, + 1808481195, 1723872674, 1910319033, 2094410160, 1608975247, 1391201670, 1173430173, 1224348052, 59984867, 244860394, 428169201, 344873464, + 935293895, 984907214, 766078933, 547512796, 1844882806, 1627235199, 2011214180, 2062270317, 1507497298, 1423022939, 1137477952, 1321699145, + 95345982, 145085239, 532201772, 313773861, 830661914, 1015671571, 731183368, 648017665, -1119466010, -1337113617, -1487908364, -1436852227, + -1989511742, -2073986101, -1820562992, -1636341799, -719438418, -669699161, -821550660, -1039978571, -516815478, -331805821, -81520232, -164685935, + -695372211, -611944380, -862229921, -1047501738, -492745111, -274055072, -122203525, -172204942, -1093335547, -1277294580, -1530717673, -1446505442, + -1963377119, -2014171096, -1863376333, -1645990854, 104699613, 188127444, 472615631, 287343814, 840019705, 1058709744, 671593195, 621591778, + 1852171925, 1668212892, 1953757831, 2037970062, 1514790577, 1463996600, 1080017571, 1297403050, -621329940, -671330331, -1058972162, -840281097, + -287606328, -472877119, -187865638, -104436781, -1297141340, -1079754835, -1464259146, -1515052097, -2038232704, -1954019447, -1667951214, -1851909221, + 172466556, 122466165, 273792366, 492483431, 1047239000, 861968209, 612205898, 695634755, 1646252340, 1863638845, 2013908262, 1963115311, + 1446242576, 1530455833, 1277555970, 1093597963, 1636604631, 1820824798, 2073724613, 1989249228, 1436590835, 1487645946, 1337376481, 1119727848, + 164948639, 81781910, 331544205, 516552836, 1039717051, 821288114, 669961897, 719700128, -1321436601, -1137216434, -1423284651, -1507760036, + -2062531997, -2011476886, -1626972559, -1844621192, -647755249, -730921978, -1015933411, -830924780, -314035669, -532464606, -144822727, -95084496, + -1224610662, -1173691757, -1390940024, -1608712575, -2094148418, -1910056265, -1724135252, -1808742747, -547775278, -766340389, -984645440, -935031095, + -344611594, -427906305, -245122844, -60246291, 1739656202, 1790575107, 2108100632, 1890328081, 1402811438, 1586903591, 1233856572, 1149249077, + 266959938, 48394827, 369057872, 418672217, 1002783846, 919489135, 567498868, 752375421, 209336225, 24197544, 376187827, 459744698, + 945164165, 895287692, 574624663, 793451934, 1679968233, 1764313568, 2117360635, 1933530610, 1343127501, 1560637892, 1243112415, 1192455638, + -590686415, -775825096, -958608605, -875051734, -387518699, -437395172, -219090169, -262898, -1265457287, -1181111952, -1367032981, -1550863006, -2134991011, -1917480620, -1700232369, -1750889146 }; const int CRijndael::sm_U4[256] = { - 0, 151849742, 303699484, 454499602, - 607398968, 758720310, 908999204, 1059270954, - 1214797936, 1097159550, 1517440620, 1400849762, - 1817998408, 1699839814, 2118541908, 2001430874, - -1865371424, -1713521682, -2100648196, -1949848078, - -1260086056, -1108764714, -1493267772, -1342996022, - -658970480, -776608866, -895287668, -1011878526, - -57883480, -176042074, -292105548, -409216582, - 1002142683, 850817237, 698445255, 548169417, - 529487843, 377642221, 227885567, 77089521, - 1943217067, 2061379749, 1640576439, 1757691577, - 1474760595, 1592394909, 1174215055, 1290801793, - -1418998981, -1570324427, -1183720153, -1333995991, - -1889540349, -2041385971, -1656360673, -1807156719, - -486304949, -368142267, -249985705, -132870567, - -952647821, -835013507, -718427793, -601841055, - 1986918061, 2137062819, 1685577905, 1836772287, - 1381620373, 1532285339, 1078185097, 1229899655, - 1040559837, 923313619, 740276417, 621982671, - 439452389, 322734571, 137073913, 19308535, - -423803315, -273658557, -190361519, -39167137, - -1031181707, -880516741, -795640727, -643926169, - -1361764803, -1479011021, -1127282655, -1245576401, - -1964953083, -2081670901, -1728371687, -1846137065, - 1305906550, 1155237496, 1607244650, 1455525988, - 1776460110, 1626319424, 2079897426, 1928707164, - 96392454, 213114376, 396673818, 514443284, - 562755902, 679998000, 865136418, 983426092, - -586793578, -737462632, -820237430, -971956092, - -114159186, -264299872, -349698126, -500888388, - -1787927066, -1671205144, -2022411270, -1904641804, - -1319482914, -1202240816, -1556062270, -1437772596, - -321194175, -438830001, -20913827, -137500077, - -923870343, -1042034569, -621490843, -738605461, - -1531793615, -1379949505, -1230456531, -1079659997, - -2138668279, -1987344377, -1835231979, -1684955621, - 2081048481, 1963412655, 1846563261, 1729977011, - 1480485785, 1362321559, 1243905413, 1126790795, - 878845905, 1030690015, 645401037, 796197571, - 274084841, 425408743, 38544885, 188821243, - -681472870, -563312748, -981755258, -864644728, - -212492126, -94852180, -514869570, -398279248, - -1626745622, -1778065436, -1928084746, -2078357000, - -1153566510, -1305414692, -1457000754, -1607801408, - 1202797690, 1320957812, 1437280870, 1554391400, - 1669664834, 1787304780, 1906247262, 2022837584, - 265905162, 114585348, 499347990, 349075736, - 736970802, 585122620, 972512814, 821712160, - -1699282452, -1816524062, -2001922064, -2120213250, - -1098699308, -1215420710, -1399243832, -1517014842, - -757114468, -606973294, -1060810880, -909622130, - -152341084, -1671510, -453942344, -302225226, - 174567692, 57326082, 410887952, 292596766, - 777231668, 660510266, 1011452712, 893681702, - 1108339068, 1258480242, 1343618912, 1494807662, - 1715193156, 1865862730, 1948373848, 2100090966, - -1593017801, -1476300487, -1290376149, -1172609243, - -2059905521, -1942659839, -1759363053, -1641067747, - -379313593, -529979063, -75615141, -227328171, - -850391425, -1000536719, -548792221, -699985043, - 836553431, 953270745, 600235211, 718002117, - 367585007, 484830689, 133361907, 251657213, - 2041877159, 1891211689, 1806599355, 1654886325, - 1568718495, 1418573201, 1335535747, 1184342925 -}; - -const signed char CRijndael::sm_rcon[30] = { - 1, 2, 4, 8, 16, 32, - 64, -128, 27, 54, 108, -40, - -85, 77, -102, 47, 94, -68, - 99, -58, -105, 53, 106, -44, - -77, 125, -6, -17, -59, -111 + 0, 151849742, 303699484, 454499602, 607398968, 758720310, 908999204, 1059270954, 1214797936, 1097159550, 1517440620, 1400849762, + 1817998408, 1699839814, 2118541908, 2001430874, -1865371424, -1713521682, -2100648196, -1949848078, -1260086056, -1108764714, -1493267772, -1342996022, + -658970480, -776608866, -895287668, -1011878526, -57883480, -176042074, -292105548, -409216582, 1002142683, 850817237, 698445255, 548169417, + 529487843, 377642221, 227885567, 77089521, 1943217067, 2061379749, 1640576439, 1757691577, 1474760595, 1592394909, 1174215055, 1290801793, + -1418998981, -1570324427, -1183720153, -1333995991, -1889540349, -2041385971, -1656360673, -1807156719, -486304949, -368142267, -249985705, -132870567, + -952647821, -835013507, -718427793, -601841055, 1986918061, 2137062819, 1685577905, 1836772287, 1381620373, 1532285339, 1078185097, 1229899655, + 1040559837, 923313619, 740276417, 621982671, 439452389, 322734571, 137073913, 19308535, -423803315, -273658557, -190361519, -39167137, + -1031181707, -880516741, -795640727, -643926169, -1361764803, -1479011021, -1127282655, -1245576401, -1964953083, -2081670901, -1728371687, -1846137065, + 1305906550, 1155237496, 1607244650, 1455525988, 1776460110, 1626319424, 2079897426, 1928707164, 96392454, 213114376, 396673818, 514443284, + 562755902, 679998000, 865136418, 983426092, -586793578, -737462632, -820237430, -971956092, -114159186, -264299872, -349698126, -500888388, + -1787927066, -1671205144, -2022411270, -1904641804, -1319482914, -1202240816, -1556062270, -1437772596, -321194175, -438830001, -20913827, -137500077, + -923870343, -1042034569, -621490843, -738605461, -1531793615, -1379949505, -1230456531, -1079659997, -2138668279, -1987344377, -1835231979, -1684955621, + 2081048481, 1963412655, 1846563261, 1729977011, 1480485785, 1362321559, 1243905413, 1126790795, 878845905, 1030690015, 645401037, 796197571, + 274084841, 425408743, 38544885, 188821243, -681472870, -563312748, -981755258, -864644728, -212492126, -94852180, -514869570, -398279248, + -1626745622, -1778065436, -1928084746, -2078357000, -1153566510, -1305414692, -1457000754, -1607801408, 1202797690, 1320957812, 1437280870, 1554391400, + 1669664834, 1787304780, 1906247262, 2022837584, 265905162, 114585348, 499347990, 349075736, 736970802, 585122620, 972512814, 821712160, + -1699282452, -1816524062, -2001922064, -2120213250, -1098699308, -1215420710, -1399243832, -1517014842, -757114468, -606973294, -1060810880, -909622130, + -152341084, -1671510, -453942344, -302225226, 174567692, 57326082, 410887952, 292596766, 777231668, 660510266, 1011452712, 893681702, + 1108339068, 1258480242, 1343618912, 1494807662, 1715193156, 1865862730, 1948373848, 2100090966, -1593017801, -1476300487, -1290376149, -1172609243, + -2059905521, -1942659839, -1759363053, -1641067747, -379313593, -529979063, -75615141, -227328171, -850391425, -1000536719, -548792221, -699985043, + 836553431, 953270745, 600235211, 718002117, 367585007, 484830689, 133361907, 251657213, 2041877159, 1891211689, 1806599355, 1654886325, + 1568718495, 1418573201, 1335535747, 1184342925 }; +const signed char CRijndael::sm_rcon[30] = {1, 2, 4, 8, 16, 32, 64, -128, 27, 54, 108, -40, -85, 77, -102, + 47, 94, -68, 99, -58, -105, 53, 106, -44, -77, 125, -6, -17, -59, -111}; // OFFSET: 0x00617FE0 // FUNCTION: fn_04401 @@ -948,19 +421,18 @@ void CRijndael::MakeKey(const char* key, const char* chain, int keyLength, int b } int t = 0; + for (int j = 0; j < KC && t < roundKeyCount; ++j, ++t) { this->m_Ke[t / BC][t % BC] = this->tk[j]; this->m_Kd[this->m_iROUNDS - (t / BC)][t % BC] = this->tk[j]; } int rconPointer = 0; + while (t < roundKeyCount) { int tt = this->tk[KC - 1]; - this->tk[0] ^= ((sm_S[(tt >> 16) & 0xFF] & 0xFF) << 24) ^ - ((sm_S[(tt >> 8) & 0xFF] & 0xFF) << 16) ^ - ((sm_S[tt & 0xFF] & 0xFF) << 8) ^ - (sm_S[(tt >> 24) & 0xFF] & 0xFF) ^ - ((sm_rcon[rconPointer++] & 0xFF) << 24); + this->tk[0] ^= ((sm_S[(tt >> 16) & 0xFF] & 0xFF) << 24) ^ ((sm_S[(tt >> 8) & 0xFF] & 0xFF) << 16) ^ ((sm_S[tt & 0xFF] & 0xFF) << 8) ^ + (sm_S[(tt >> 24) & 0xFF] & 0xFF) ^ ((sm_rcon[rconPointer++] & 0xFF) << 24); if (KC != 8) { for (int i = 1, j = 0; i < KC;) { @@ -970,11 +442,11 @@ void CRijndael::MakeKey(const char* key, const char* chain, int keyLength, int b for (int i = 1, j = 0; i < KC / 2;) { this->tk[i++] ^= this->tk[j++]; } + tt = this->tk[KC / 2 - 1]; - this->tk[KC / 2] ^= (sm_S[tt & 0xFF] & 0xFF) ^ - ((sm_S[(tt >> 8) & 0xFF] & 0xFF) << 8) ^ - ((sm_S[(tt >> 16) & 0xFF] & 0xFF) << 16) ^ - ((sm_S[(tt >> 24) & 0xFF] & 0xFF) << 24); + this->tk[KC / 2] ^= + (sm_S[tt & 0xFF] & 0xFF) ^ ((sm_S[(tt >> 8) & 0xFF] & 0xFF) << 8) ^ ((sm_S[(tt >> 16) & 0xFF] & 0xFF) << 16) ^ ((sm_S[(tt >> 24) & 0xFF] & 0xFF) << 24); + for (int j = KC / 2, i = j + 1; i < KC;) { this->tk[i++] ^= this->tk[j++]; } @@ -989,10 +461,7 @@ void CRijndael::MakeKey(const char* key, const char* chain, int keyLength, int b for (int r = 1; r < this->m_iROUNDS; ++r) { for (int j = 0; j < BC; ++j) { int tt = this->m_Kd[r][j]; - this->m_Kd[r][j] = sm_U1[(tt >> 24) & 0xFF] ^ - sm_U2[(tt >> 16) & 0xFF] ^ - sm_U3[(tt >> 8) & 0xFF] ^ - sm_U4[tt & 0xFF]; + this->m_Kd[r][j] = sm_U1[(tt >> 24) & 0xFF] ^ sm_U2[(tt >> 16) & 0xFF] ^ sm_U3[(tt >> 8) & 0xFF] ^ sm_U4[tt & 0xFF]; } } @@ -1029,22 +498,10 @@ void CRijndael::DefEncryptBlock(const char* in, char* result) { for (int r = 1; r < this->m_iROUNDS; ++r) { Ker = this->m_Ke[r]; - int a0 = (sm_T1[(t0 >> 24) & 0xFF] ^ - sm_T2[(t1 >> 16) & 0xFF] ^ - sm_T3[(t2 >> 8) & 0xFF] ^ - sm_T4[t3 & 0xFF]) ^ Ker[0]; - int a1 = (sm_T1[(t1 >> 24) & 0xFF] ^ - sm_T2[(t2 >> 16) & 0xFF] ^ - sm_T3[(t3 >> 8) & 0xFF] ^ - sm_T4[t0 & 0xFF]) ^ Ker[1]; - int a2 = (sm_T1[(t2 >> 24) & 0xFF] ^ - sm_T2[(t3 >> 16) & 0xFF] ^ - sm_T3[(t0 >> 8) & 0xFF] ^ - sm_T4[t1 & 0xFF]) ^ Ker[2]; - int a3 = (sm_T1[(t3 >> 24) & 0xFF] ^ - sm_T2[(t0 >> 16) & 0xFF] ^ - sm_T3[(t1 >> 8) & 0xFF] ^ - sm_T4[t2 & 0xFF]) ^ Ker[3]; + int a0 = (sm_T1[(t0 >> 24) & 0xFF] ^ sm_T2[(t1 >> 16) & 0xFF] ^ sm_T3[(t2 >> 8) & 0xFF] ^ sm_T4[t3 & 0xFF]) ^ Ker[0]; + int a1 = (sm_T1[(t1 >> 24) & 0xFF] ^ sm_T2[(t2 >> 16) & 0xFF] ^ sm_T3[(t3 >> 8) & 0xFF] ^ sm_T4[t0 & 0xFF]) ^ Ker[1]; + int a2 = (sm_T1[(t2 >> 24) & 0xFF] ^ sm_T2[(t3 >> 16) & 0xFF] ^ sm_T3[(t0 >> 8) & 0xFF] ^ sm_T4[t1 & 0xFF]) ^ Ker[2]; + int a3 = (sm_T1[(t3 >> 24) & 0xFF] ^ sm_T2[(t0 >> 16) & 0xFF] ^ sm_T3[(t1 >> 8) & 0xFF] ^ sm_T4[t2 & 0xFF]) ^ Ker[3]; t0 = a0; t1 = a1; @@ -1108,22 +565,10 @@ void CRijndael::DefDecryptBlock(const char* in, char* result) { for (int r = 1; r < this->m_iROUNDS; ++r) { Kdr = this->m_Kd[r]; - int a0 = (sm_T5[(t0 >> 24) & 0xFF] ^ - sm_T6[(t3 >> 16) & 0xFF] ^ - sm_T7[(t2 >> 8) & 0xFF] ^ - sm_T8[t1 & 0xFF]) ^ Kdr[0]; - int a1 = (sm_T5[(t1 >> 24) & 0xFF] ^ - sm_T6[(t0 >> 16) & 0xFF] ^ - sm_T7[(t3 >> 8) & 0xFF] ^ - sm_T8[t2 & 0xFF]) ^ Kdr[1]; - int a2 = (sm_T5[(t2 >> 24) & 0xFF] ^ - sm_T6[(t1 >> 16) & 0xFF] ^ - sm_T7[(t0 >> 8) & 0xFF] ^ - sm_T8[t3 & 0xFF]) ^ Kdr[2]; - int a3 = (sm_T5[(t3 >> 24) & 0xFF] ^ - sm_T6[(t2 >> 16) & 0xFF] ^ - sm_T7[(t1 >> 8) & 0xFF] ^ - sm_T8[t0 & 0xFF]) ^ Kdr[3]; + int a0 = (sm_T5[(t0 >> 24) & 0xFF] ^ sm_T6[(t3 >> 16) & 0xFF] ^ sm_T7[(t2 >> 8) & 0xFF] ^ sm_T8[t1 & 0xFF]) ^ Kdr[0]; + int a1 = (sm_T5[(t1 >> 24) & 0xFF] ^ sm_T6[(t0 >> 16) & 0xFF] ^ sm_T7[(t3 >> 8) & 0xFF] ^ sm_T8[t2 & 0xFF]) ^ Kdr[1]; + int a2 = (sm_T5[(t2 >> 24) & 0xFF] ^ sm_T6[(t1 >> 16) & 0xFF] ^ sm_T7[(t0 >> 8) & 0xFF] ^ sm_T8[t3 & 0xFF]) ^ Kdr[2]; + int a3 = (sm_T5[(t3 >> 24) & 0xFF] ^ sm_T6[(t2 >> 16) & 0xFF] ^ sm_T7[(t1 >> 8) & 0xFF] ^ sm_T8[t0 & 0xFF]) ^ Kdr[3]; t0 = a0; t1 = a1; @@ -1176,6 +621,7 @@ void CRijndael::EncryptBlock(const char* in, char* result) { const int s3 = sm_shifts[SC][3][0]; int* pi = this->t; + for (int i = 0; i < BC; ++i) { *pi = static_cast(*in++) << 24; *pi |= static_cast(*in++) << 16; @@ -1185,11 +631,11 @@ void CRijndael::EncryptBlock(const char* in, char* result) { for (int r = 1; r < this->m_iROUNDS; ++r) { for (int i = 0; i < BC; ++i) { - this->a[i] = (sm_T1[(this->t[i] >> 24) & 0xFF] ^ - sm_T2[(this->t[(i + s1) % BC] >> 16) & 0xFF] ^ - sm_T3[(this->t[(i + s2) % BC] >> 8) & 0xFF] ^ - sm_T4[this->t[(i + s3) % BC] & 0xFF]) ^ this->m_Ke[r][i]; + this->a[i] = (sm_T1[(this->t[i] >> 24) & 0xFF] ^ sm_T2[(this->t[(i + s1) % BC] >> 16) & 0xFF] ^ sm_T3[(this->t[(i + s2) % BC] >> 8) & 0xFF] ^ + sm_T4[this->t[(i + s3) % BC] & 0xFF]) ^ + this->m_Ke[r][i]; } + std::memcpy(this->t, this->a, 4 * BC); } @@ -1221,6 +667,7 @@ void CRijndael::DecryptBlock(const char* in, char* result) { const int s3 = sm_shifts[SC][3][1]; int* pi = this->t; + for (int i = 0; i < BC; ++i) { *pi = static_cast(*in++) << 24; *pi |= static_cast(*in++) << 16; @@ -1230,11 +677,11 @@ void CRijndael::DecryptBlock(const char* in, char* result) { for (int r = 1; r < this->m_iROUNDS; ++r) { for (int i = 0; i < BC; ++i) { - this->a[i] = (sm_T5[(this->t[i] >> 24) & 0xFF] ^ - sm_T6[(this->t[(i + s1) % BC] >> 16) & 0xFF] ^ - sm_T7[(this->t[(i + s2) % BC] >> 8) & 0xFF] ^ - sm_T8[this->t[(i + s3) % BC] & 0xFF]) ^ this->m_Kd[r][i]; + this->a[i] = (sm_T5[(this->t[i] >> 24) & 0xFF] ^ sm_T6[(this->t[(i + s1) % BC] >> 16) & 0xFF] ^ sm_T7[(this->t[(i + s2) % BC] >> 8) & 0xFF] ^ + sm_T8[this->t[(i + s3) % BC] & 0xFF]) ^ + this->m_Kd[r][i]; } + std::memcpy(this->t, this->a, 4 * BC); } diff --git a/Source/Utility/Rijndael.h b/Source/Utility/Rijndael.h index 95ffb75..9c2b794 100644 --- a/Source/Utility/Rijndael.h +++ b/Source/Utility/Rijndael.h @@ -6,32 +6,16 @@ class CRijndael { public: - enum { - ECB = 0, - CBC = 1, - CFB = 2 - }; + enum { ECB = 0, CBC = 1, CFB = 2 }; - enum { - DEFAULT_BLOCK_SIZE = 16 - }; + enum { DEFAULT_BLOCK_SIZE = 16 }; - enum { - MAX_BLOCK_SIZE = 32, - MAX_ROUNDS = 14, - MAX_KC = 8, - MAX_BC = 8 - }; + enum { MAX_BLOCK_SIZE = 32, MAX_ROUNDS = 14, MAX_KC = 8, MAX_BC = 8 }; CRijndael(); virtual ~CRijndael(); - void MakeKey( - const char* key, - const char* chain, - int keyLength = DEFAULT_BLOCK_SIZE, - int blockSize = DEFAULT_BLOCK_SIZE - ); + void MakeKey(const char* key, const char* chain, int keyLength = DEFAULT_BLOCK_SIZE, int blockSize = DEFAULT_BLOCK_SIZE); void EncryptBlock(const char* in, char* result); void DecryptBlock(const char* in, char* result); @@ -57,7 +41,6 @@ public: } } - static const char* sm_chain0; private: diff --git a/Source/Utility/FormatString.cpp b/Source/Utility/Text/FormatString.cpp similarity index 94% rename from Source/Utility/FormatString.cpp rename to Source/Utility/Text/FormatString.cpp index 3bb1fe4..2f52e30 100644 --- a/Source/Utility/FormatString.cpp +++ b/Source/Utility/Text/FormatString.cpp @@ -1,5 +1,5 @@ -#include "Utility/FormatString.h" -#include "Utility/NSyncObject.h" +#include "Utility/Text/FormatString.h" +#include "Utility/Threading/NSyncObject.h" #include #include @@ -24,7 +24,6 @@ int StringFormat(char* buffer, std::size_t sizeInBytes, std::size_t count, const } namespace { - class ThreadSafeBuffer { public: ThreadSafeBuffer() { @@ -55,7 +54,6 @@ namespace { return it->second.data(); } - } // OFFSET: 0x00734470 diff --git a/Source/Utility/FormatString.h b/Source/Utility/Text/FormatString.h similarity index 63% rename from Source/Utility/FormatString.h rename to Source/Utility/Text/FormatString.h index aa06d11..180e84f 100644 --- a/Source/Utility/FormatString.h +++ b/Source/Utility/Text/FormatString.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_FORMATSTRING_H -#define RAGNAROK_SOURCE_UTILITY_FORMATSTRING_H +#ifndef RAGNAROK_SOURCE_UTILITY_TEXT_FORMATSTRING_H +#define RAGNAROK_SOURCE_UTILITY_TEXT_FORMATSTRING_H #include diff --git a/Source/Utility/GroupedInteger.cpp b/Source/Utility/Text/GroupedInteger.cpp similarity index 89% rename from Source/Utility/GroupedInteger.cpp rename to Source/Utility/Text/GroupedInteger.cpp index 6671a0b..d782334 100644 --- a/Source/Utility/GroupedInteger.cpp +++ b/Source/Utility/Text/GroupedInteger.cpp @@ -1,10 +1,9 @@ -#include "Utility/GroupedInteger.h" +#include "Utility/Text/GroupedInteger.h" #include #include namespace { - // OFFSET: 0x00AF8730 // FUNCTION: fn_18263 void GroupDigits(const char* digits, int length, char* output, int capacity) { @@ -35,11 +34,8 @@ namespace { } } - // The original overwrites the final comma, or the last copied digit if the - // buffer filled. Do not replace this with conventional snprintf truncation. output[written - 1] = '\0'; } - } // OFFSET: 0x00AF60E0 diff --git a/Source/Utility/Text/GroupedInteger.h b/Source/Utility/Text/GroupedInteger.h new file mode 100644 index 0000000..a1d5193 --- /dev/null +++ b/Source/Utility/Text/GroupedInteger.h @@ -0,0 +1,11 @@ +#ifndef RAGNAROK_SOURCE_UTILITY_TEXT_GROUPEDINTEGER_H +#define RAGNAROK_SOURCE_UTILITY_TEXT_GROUPEDINTEGER_H + +#include + +char* FormatGroupedInteger(int value, char* output, int capacity); +char* FormatGroupedInteger(std::int64_t value, char* output, int capacity); + +const char* ReverseFindChar(const char* text, char target); + +#endif diff --git a/Source/Utility/Text/LanguageCharset.cpp b/Source/Utility/Text/LanguageCharset.cpp new file mode 100644 index 0000000..887fd83 --- /dev/null +++ b/Source/Utility/Text/LanguageCharset.cpp @@ -0,0 +1,89 @@ +#include "Utility/Text/LanguageCharset.h" + +#include + +// OFFSET: 0x00ACD8B0 +// FUNCTION: fn_17771 +unsigned LanguageCharset(std::uint16_t language) { + switch (PRIMARYLANGID(language)) { + case LANG_ARABIC: + return ARABIC_CHARSET; + case LANG_BULGARIAN: + case LANG_RUSSIAN: + case LANG_UKRAINIAN: + case LANG_BELARUSIAN: + return RUSSIAN_CHARSET; + case LANG_CHINESE: + if (SUBLANGID(language) == SUBLANG_CHINESE_TRADITIONAL) { + return CHINESEBIG5_CHARSET; + } + if (SUBLANGID(language) == SUBLANG_CHINESE_SIMPLIFIED) { + return GB2312_CHARSET; + } + return GREEK_CHARSET; + case LANG_CZECH: + case LANG_HUNGARIAN: + case LANG_POLISH: + case LANG_ROMANIAN: + case LANG_CROATIAN: + case LANG_SLOVAK: + case LANG_SLOVENIAN: + case LANG_MACEDONIAN: + return EASTEUROPE_CHARSET; + case LANG_GREEK: + return GREEK_CHARSET; + case LANG_HEBREW: + return HEBREW_CHARSET; + case LANG_JAPANESE: + return SHIFTJIS_CHARSET; + case LANG_KOREAN: + return HANGUL_CHARSET; + case LANG_THAI: + return THAI_CHARSET; + case LANG_TURKISH: + return TURKISH_CHARSET; + case LANG_ESTONIAN: + case LANG_LATVIAN: + case LANG_LITHUANIAN: + return BALTIC_CHARSET; + case LANG_VIETNAMESE: + return VIETNAMESE_CHARSET; + default: + return ANSI_CHARSET; + } +} + +// OFFSET: 0x00ACDAE0 +// FUNCTION: fn_17773 +unsigned LanguageCodePage(std::uint16_t language) { + switch (LanguageCharset(language)) { + case SHIFTJIS_CHARSET: + return 932; + case HANGUL_CHARSET: + return 949; + case GB2312_CHARSET: + return 936; + case CHINESEBIG5_CHARSET: + return 950; + case GREEK_CHARSET: + return 1253; + case TURKISH_CHARSET: + return 1254; + case VIETNAMESE_CHARSET: + return 1258; + case HEBREW_CHARSET: + return 1255; + case ARABIC_CHARSET: + return 1256; + case BALTIC_CHARSET: + return 1257; + case RUSSIAN_CHARSET: + return 1251; + case THAI_CHARSET: + return 874; + case EASTEUROPE_CHARSET: + return 1250; + default: + return 1252; + } +} diff --git a/Source/Utility/LanguageCharset.h b/Source/Utility/Text/LanguageCharset.h similarity index 54% rename from Source/Utility/LanguageCharset.h rename to Source/Utility/Text/LanguageCharset.h index 6e654fe..5d4e5a9 100644 --- a/Source/Utility/LanguageCharset.h +++ b/Source/Utility/Text/LanguageCharset.h @@ -1,5 +1,5 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_LANGUAGECHARSET_H -#define RAGNAROK_SOURCE_UTILITY_LANGUAGECHARSET_H +#ifndef RAGNAROK_SOURCE_UTILITY_TEXT_LANGUAGECHARSET_H +#define RAGNAROK_SOURCE_UTILITY_TEXT_LANGUAGECHARSET_H #include diff --git a/Source/Utility/CSyncObject.cpp b/Source/Utility/Threading/CSyncObject.cpp similarity index 86% rename from Source/Utility/CSyncObject.cpp rename to Source/Utility/Threading/CSyncObject.cpp index 8698175..2a86cfc 100644 --- a/Source/Utility/CSyncObject.cpp +++ b/Source/Utility/Threading/CSyncObject.cpp @@ -1,4 +1,4 @@ -#include "Utility/CSyncObject.h" +#include "Utility/Threading/CSyncObject.h" CSyncObject::CSyncObject(CRITICAL_SECTION* criticalSection) : m_criticalSection(criticalSection) { EnterCriticalSection(this->m_criticalSection); diff --git a/Source/Utility/CSyncObject.h b/Source/Utility/Threading/CSyncObject.h similarity index 61% rename from Source/Utility/CSyncObject.h rename to Source/Utility/Threading/CSyncObject.h index 2496ffa..9accd9d 100644 --- a/Source/Utility/CSyncObject.h +++ b/Source/Utility/Threading/CSyncObject.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_CSYNC_OBJECT_H -#define RAGNAROK_SOURCE_UTILITY_CSYNC_OBJECT_H +#ifndef RAGNAROK_SOURCE_UTILITY_THREADING_CSYNCOBJECT_H +#define RAGNAROK_SOURCE_UTILITY_THREADING_CSYNCOBJECT_H #include -// RTTI CSyncObject. Owns a scoped critical-section entry with virtual destruction. class CSyncObject { public: explicit CSyncObject(CRITICAL_SECTION* criticalSection); diff --git a/Source/Utility/NSyncObject.cpp b/Source/Utility/Threading/NSyncObject.cpp similarity index 89% rename from Source/Utility/NSyncObject.cpp rename to Source/Utility/Threading/NSyncObject.cpp index 0383e37..06b91aa 100644 --- a/Source/Utility/NSyncObject.cpp +++ b/Source/Utility/Threading/NSyncObject.cpp @@ -1,4 +1,4 @@ -#include "Utility/NSyncObject.h" +#include "Utility/Threading/NSyncObject.h" // OFFSET: 0x00737130 // FUNCTION: fn_07640 diff --git a/Source/Utility/NSyncObject.h b/Source/Utility/Threading/NSyncObject.h similarity index 62% rename from Source/Utility/NSyncObject.h rename to Source/Utility/Threading/NSyncObject.h index dd60dec..4bae4a4 100644 --- a/Source/Utility/NSyncObject.h +++ b/Source/Utility/Threading/NSyncObject.h @@ -1,9 +1,8 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NSYNC_OBJECT_H -#define RAGNAROK_SOURCE_UTILITY_NSYNC_OBJECT_H +#ifndef RAGNAROK_SOURCE_UTILITY_THREADING_NSYNCOBJECT_H +#define RAGNAROK_SOURCE_UTILITY_THREADING_NSYNCOBJECT_H #include -// Original class name established by RTTI; owns one critical-section entry. class NSyncObject { public: explicit NSyncObject(CRITICAL_SECTION* criticalSection); diff --git a/Source/Utility/NThread.cpp b/Source/Utility/Threading/NThread.cpp similarity index 76% rename from Source/Utility/NThread.cpp rename to Source/Utility/Threading/NThread.cpp index ca7b6fb..ffaf997 100644 --- a/Source/Utility/NThread.cpp +++ b/Source/Utility/Threading/NThread.cpp @@ -1,12 +1,11 @@ -#include "Utility/NThread.h" +#include "Utility/Threading/NThread.h" #include #include namespace { - // OFFSET: 0x00737510 - // Original debugger naming exception; this is not compiler array-unwind code. + void SetDebuggerThreadName(unsigned id, const char* name) { ULONG_PTR arguments[4] = {0x1000, reinterpret_cast(name), id, 0}; __try { @@ -14,13 +13,11 @@ namespace { } __except (EXCEPTION_EXECUTE_HANDLER) { } } - } // OFFSET: 0x00737200 // FUNCTION: fn_07643 -NThread::NThread(std::string name) - : m_threadId(0), unknown_0008(true), m_state(0), m_handle(nullptr), m_name(std::move(name)) { +NThread::NThread(std::string name) : m_threadId(0), unknown_0008(true), m_state(0), m_handle(nullptr), m_name(std::move(name)) { } // OFFSET: 0x00737290 @@ -28,8 +25,6 @@ NThread::NThread(std::string name) // OFFSET: 0x00737350 // FUNCTION: fn_07645 NThread::~NThread() { - // The original installs NThread's own vtable before this sequence. A live - // worker here therefore reaches its pure virtual stop slot, not an override. this->Stop(); } @@ -38,6 +33,7 @@ unsigned __stdcall NThread::Entry(void* parameter) { NThread* thread = static_cast(parameter); unsigned result = thread->Run(); thread->m_state = 3; + return result; } @@ -46,14 +42,16 @@ bool NThread::Start() { if (this->m_handle || this->m_state) { return false; } - this->m_handle = - reinterpret_cast(_beginthreadex(nullptr, 0, Entry, this, CREATE_SUSPENDED, &this->m_threadId)); + + this->m_handle = reinterpret_cast(_beginthreadex(nullptr, 0, Entry, this, CREATE_SUSPENDED, &this->m_threadId)); if (!this->m_handle) { return false; } + ResumeThread(this->m_handle); this->m_state = 1; SetDebuggerThreadName(this->m_threadId, this->m_name.c_str()); + return true; } diff --git a/Source/Utility/NThread.h b/Source/Utility/Threading/NThread.h similarity index 80% rename from Source/Utility/NThread.h rename to Source/Utility/Threading/NThread.h index dd44608..30853c1 100644 --- a/Source/Utility/NThread.h +++ b/Source/Utility/Threading/NThread.h @@ -1,11 +1,10 @@ -#ifndef RAGNAROK_SOURCE_UTILITY_NTHREAD_H -#define RAGNAROK_SOURCE_UTILITY_NTHREAD_H +#ifndef RAGNAROK_SOURCE_UTILITY_THREADING_NTHREAD_H +#define RAGNAROK_SOURCE_UTILITY_THREADING_NTHREAD_H #include #include #include -// Original RTTI class; method/state names are reconstructed. class NThread { public: explicit NThread(std::string name); diff --git a/Source/Utility/XorBytes.cpp b/Source/Utility/XorBytes.cpp index 77d04d9..9cc5a4d 100644 --- a/Source/Utility/XorBytes.cpp +++ b/Source/Utility/XorBytes.cpp @@ -1,7 +1,6 @@ #include "Utility/XorBytes.h" namespace utility { - // OFFSET: 0x005A45E0 // FUNCTION: fn_03149 void XorBytes(std::uint8_t* bytes, std::uint64_t length, std::uint64_t key) { @@ -9,5 +8,4 @@ namespace utility { bytes[i] ^= static_cast(key >> (8 * (i & 7))); } } - } diff --git a/Source/Utility/XorBytes.h b/Source/Utility/XorBytes.h index f450205..f6c70de 100644 --- a/Source/Utility/XorBytes.h +++ b/Source/Utility/XorBytes.h @@ -5,7 +5,6 @@ namespace utility { - // Reconstructed semantic name; the original symbol is unavailable. void XorBytes(std::uint8_t* bytes, std::uint64_t length, std::uint64_t key); } diff --git a/compile.json b/compile.json index 2444fea..9e1dba6 100644 --- a/compile.json +++ b/compile.json @@ -1,7 +1,7 @@ { "compiler": "${TC}/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x86/cl.exe", "env": { - "INCLUDE": "${TC}\\VC\\Tools\\MSVC\\14.29.30133\\include;${TC}\\VC\\Tools\\MSVC\\14.29.30133\\atlmfc\\include;${TC}\\Program Files\\Windows Kits\\10\\Include\\10.0.19041.0\\ucrt;${TC}\\Program Files\\Windows Kits\\10\\Include\\10.0.19041.0\\shared;${TC}\\Program Files\\Windows Kits\\10\\Include\\10.0.19041.0\\um" + "INCLUDE": "${TC}\\VC\\Tools\\MSVC\\14.29.30133\\include;${TC}\\VC\\Tools\\MSVC\\14.29.30133\\atlmfc\\include;${TC}\\Program Files\\Windows Kits\\10\\Include\\10.0.19041.0\\ucrt;${TC}\\Program Files\\Windows Kits\\10\\Include\\10.0.19041.0\\shared;${TC}\\Program Files\\Windows Kits\\10\\Include\\10.0.19041.0\\um;${TC}\\Program Files\\Windows Kits\\10\\Include\\10.0.19041.0\\winrt" }, "shapes": [ [ @@ -198,421 +198,421 @@ "Source/Archive/PakFile.cpp": 1, "Source/Archive/PakName.cpp": 1, "Source/Archive/PakRegistry.cpp": 1, - "Source/Client/ActiveGameMode.cpp": 0, - "Source/Client/ApplicationActivation.cpp": 4, - "Source/Client/ApplicationMessages.cpp": 4, - "Source/Client/ApplicationWindow.cpp": 0, - "Source/Client/BrowserAddressBar.cpp": 0, - "Source/Client/BrowserAddressEdit.cpp": 0, - "Source/Client/BrowserClientSite.cpp": 0, - "Source/Client/BrowserClose.cpp": 0, - "Source/Client/BrowserCommandTarget.cpp": 0, - "Source/Client/BrowserCreation.cpp": 0, - "Source/Client/BrowserCursor.cpp": 0, - "Source/Client/BrowserDocumentUI.cpp": 0, - "Source/Client/BrowserFrame.cpp": 0, - "Source/Client/BrowserHostWindow.cpp": 0, - "Source/Client/BrowserInPlace.cpp": 0, - "Source/Client/BrowserInputHandoff.cpp": 4, - "Source/Client/BrowserInterface.cpp": 0, - "Source/Client/BrowserMessages.cpp": 4, - "Source/Client/BrowserRegistry.cpp": 4, - "Source/Client/BrowserSiteAttachment.cpp": 0, - "Source/Client/BrowserWindowSizing.cpp": 0, + "Source/Client/Mode/ActiveGameMode.cpp": 0, + "Source/Client/Application/ApplicationActivation.cpp": 4, + "Source/Client/Application/ApplicationMessages.cpp": 4, + "Source/Client/Application/ApplicationWindow.cpp": 0, + "Source/Client/Browser/BrowserAddressBar.cpp": 0, + "Source/Client/Browser/BrowserAddressEdit.cpp": 0, + "Source/Client/Browser/BrowserClientSite.cpp": 0, + "Source/Client/Browser/BrowserClose.cpp": 0, + "Source/Client/Browser/BrowserCommandTarget.cpp": 0, + "Source/Client/Browser/BrowserCreation.cpp": 0, + "Source/Client/Browser/BrowserCursor.cpp": 0, + "Source/Client/Browser/BrowserDocumentUI.cpp": 0, + "Source/Client/Browser/BrowserFrame.cpp": 0, + "Source/Client/Browser/BrowserHostWindow.cpp": 0, + "Source/Client/Browser/BrowserInPlace.cpp": 0, + "Source/Client/Browser/BrowserInputHandoff.cpp": 4, + "Source/Client/Browser/BrowserInterface.cpp": 0, + "Source/Client/Browser/BrowserMessages.cpp": 4, + "Source/Client/Browser/BrowserRegistry.cpp": 4, + "Source/Client/Browser/BrowserSiteAttachment.cpp": 0, + "Source/Client/Browser/BrowserWindowSizing.cpp": 0, "Source/Client/ClientOptions.cpp": 0, - "Source/Client/ErrorDialog.cpp": 0, - "Source/Client/ImeInput.cpp": 0, - "Source/Client/InputCharset.cpp": 0, - "Source/Client/Launcher.cpp": 0, - "Source/Client/ModeCursor.cpp": 0, - "Source/Client/ModeDragState.cpp": 2, - "Source/Client/ModeTooltip.cpp": 2, - "Source/Client/Mouse.cpp": 0, + "Source/Client/Application/ErrorDialog.cpp": 0, + "Source/Client/Input/ImeInput.cpp": 0, + "Source/Client/Input/InputCharset.cpp": 0, + "Source/Client/Application/Launcher.cpp": 0, + "Source/Client/Mode/ModeCursor.cpp": 0, + "Source/Client/Mode/ModeDragState.cpp": 2, + "Source/Client/Mode/ModeTooltip.cpp": 2, + "Source/Client/Input/Mouse.cpp": 0, "Source/Client/ReplayPacketRecorder.cpp": 2, - "Source/Client/TextInputBuffer.cpp": 0, - "Source/Client/TraditionalKeyInput.cpp": 0, - "Source/Client/UnhandledExceptionHandler.cpp": 0, - "Source/Client/WebBrowser.cpp": 4, - "Source/Client/WebEventReceiver.cpp": 4, - "Source/Contents/AccountLinkedUserDataLoadAsyncWork.cpp": 4, - "Source/Contents/AccountLinkedUserDataMgr.cpp": 4, - "Source/Contents/AccountLinkedUserDataSaveAsyncWork.cpp": 4, - "Source/Contents/AccountService.cpp": 4, - "Source/Contents/AccountUserData.cpp": 4, - "Source/Contents/AdvenPartyInfo.cpp": 4, - "Source/Contents/AdventurerAgencyMgr.cpp": 4, - "Source/Contents/AgencyRequests.cpp": 4, - "Source/Contents/AsyncWorkMgr.cpp": 4, - "Source/Contents/AsyncWorkRecycleObjectPoolMgr.cpp": 4, - "Source/Contents/AttachedEffect.cpp": 4, - "Source/Contents/AttackMotion.cpp": 4, - "Source/Contents/AutomaticSkills.cpp": 4, - "Source/Contents/BinkMovie.cpp": 3, - "Source/Contents/BinkMovies.cpp": 3, - "Source/Contents/CameraFrame.cpp": 3, - "Source/Contents/CameraQueries.cpp": 3, - "Source/Contents/CameraShake.cpp": 3, - "Source/Contents/CameraSmoothing.cpp": 3, + "Source/Client/Input/TextInputBuffer.cpp": 0, + "Source/Client/Input/TraditionalKeyInput.cpp": 0, + "Source/Client/Application/UnhandledExceptionHandler.cpp": 0, + "Source/Client/Browser/WebBrowser.cpp": 4, + "Source/Client/Browser/WebEventReceiver.cpp": 4, + "Source/Contents/UserData/AccountLinkedUserDataLoadAsyncWork.cpp": 4, + "Source/Contents/UserData/AccountLinkedUserDataMgr.cpp": 4, + "Source/Contents/UserData/AccountLinkedUserDataSaveAsyncWork.cpp": 4, + "Source/Contents/UserData/AccountService.cpp": 4, + "Source/Contents/UserData/AccountUserData.cpp": 4, + "Source/Contents/Party/AdvenPartyInfo.cpp": 4, + "Source/Contents/Party/AdventurerAgencyMgr.cpp": 4, + "Source/Contents/Party/AgencyRequests.cpp": 4, + "Source/Contents/Async/AsyncWorkMgr.cpp": 4, + "Source/Contents/Async/AsyncWorkRecycleObjectPoolMgr.cpp": 4, + "Source/Contents/Effects/AttachedEffect.cpp": 4, + "Source/Contents/Actors/AttackMotion.cpp": 4, + "Source/Contents/Skills/AutomaticSkills.cpp": 4, + "Source/Contents/Movies/BinkMovie.cpp": 3, + "Source/Contents/Movies/BinkMovies.cpp": 3, + "Source/Contents/Camera/CameraFrame.cpp": 3, + "Source/Contents/Camera/CameraQueries.cpp": 3, + "Source/Contents/Camera/CameraShake.cpp": 3, + "Source/Contents/Camera/CameraSmoothing.cpp": 3, "Source/Contents/CashEmotionMgr.cpp": 4, - "Source/Contents/ChangePartyMasterAsyncWork.cpp": 4, - "Source/Contents/ChangePartyMasterCompletion.cpp": 2, - "Source/Contents/CharacterConfigLoad.cpp": 2, - "Source/Contents/CharacterConfigSave.cpp": 4, - "Source/Contents/CharacterLinkedUserDataLoadAsyncWork.cpp": 2, - "Source/Contents/CharacterLinkedUserDataMgr.cpp": 4, - "Source/Contents/CharacterLinkedUserDataSaveAsyncWork.cpp": 4, - "Source/Contents/ClientMessenger.cpp": 4, - "Source/Contents/ClientSkills.cpp": 4, - "Source/Contents/Effect.cpp": 0, - "Source/Contents/EffectActor.cpp": 4, - "Source/Contents/EffectAttachments.cpp": 4, - "Source/Contents/EffectLists.cpp": 0, - "Source/Contents/EffectParticle.cpp": 4, - "Source/Contents/EffectPrimitiveColor.cpp": 4, - "Source/Contents/EffectPrimitiveMotion.cpp": 4, - "Source/Contents/EffectPrimitiveRecords.cpp": 4, - "Source/Contents/EffectPrimitiveRendering.cpp": 4, - "Source/Contents/EffectPrimitiveState.cpp": 4, - "Source/Contents/EffectTypes.cpp": 4, - "Source/Contents/EffectVisibility.cpp": 4, - "Source/Contents/EmblemCache.cpp": 2, - "Source/Contents/EmblemDataDownloadAsyncWork.cpp": 4, - "Source/Contents/EmblemDataMgr.cpp": 4, - "Source/Contents/EmblemDataUploadAsyncWork.cpp": 4, - "Source/Contents/EmblemDownload.cpp": 4, - "Source/Contents/EmblemUpload.cpp": 2, - "Source/Contents/EmotionHotkeys.cpp": 4, + "Source/Contents/Party/ChangePartyMasterAsyncWork.cpp": 4, + "Source/Contents/Party/ChangePartyMasterCompletion.cpp": 2, + "Source/Contents/UserData/CharacterConfigLoad.cpp": 2, + "Source/Contents/UserData/CharacterConfigSave.cpp": 4, + "Source/Contents/UserData/CharacterLinkedUserDataLoadAsyncWork.cpp": 2, + "Source/Contents/UserData/CharacterLinkedUserDataMgr.cpp": 4, + "Source/Contents/UserData/CharacterLinkedUserDataSaveAsyncWork.cpp": 4, + "Source/Contents/Messenger/ClientMessenger.cpp": 4, + "Source/Contents/Skills/ClientSkills.cpp": 4, + "Source/Contents/Effects/Effect.cpp": 0, + "Source/Contents/Effects/EffectActor.cpp": 4, + "Source/Contents/Effects/EffectAttachments.cpp": 4, + "Source/Contents/Effects/EffectLists.cpp": 0, + "Source/Contents/Effects/EffectParticle.cpp": 4, + "Source/Contents/Effects/EffectPrimitiveColor.cpp": 4, + "Source/Contents/Effects/EffectPrimitiveMotion.cpp": 4, + "Source/Contents/Effects/EffectPrimitiveRecords.cpp": 4, + "Source/Contents/Effects/EffectPrimitiveRendering.cpp": 4, + "Source/Contents/Effects/EffectPrimitiveState.cpp": 4, + "Source/Contents/Effects/EffectTypes.cpp": 4, + "Source/Contents/Effects/EffectVisibility.cpp": 4, + "Source/Contents/Emblems/EmblemCache.cpp": 2, + "Source/Contents/Emblems/EmblemDataDownloadAsyncWork.cpp": 4, + "Source/Contents/Emblems/EmblemDataMgr.cpp": 4, + "Source/Contents/Emblems/EmblemDataUploadAsyncWork.cpp": 4, + "Source/Contents/Emblems/EmblemDownload.cpp": 4, + "Source/Contents/Emblems/EmblemUpload.cpp": 2, + "Source/Contents/Hotkeys/EmotionHotkeys.cpp": 4, "Source/Contents/ForbiddenWords.cpp": 4, - "Source/Contents/GameObject.cpp": 4, - "Source/Contents/GraphicsConfiguration.cpp": 4, - "Source/Contents/GroundDecals.cpp": 3, - "Source/Contents/GroundGeometry.cpp": 3, - "Source/Contents/GroundLighting.cpp": 3, - "Source/Contents/GroundLightingInitialization.cpp": 3, - "Source/Contents/GroundLightmaps.cpp": 3, - "Source/Contents/GroundPicking.cpp": 3, - "Source/Contents/GroundRendering.cpp": 3, - "Source/Contents/GroundSamples.cpp": 3, - "Source/Contents/GroundSpatial.cpp": 3, - "Source/Contents/GroundWaterRendering.cpp": 3, - "Source/Contents/GroundWaterState.cpp": 3, - "Source/Contents/GuildEmblemReqBundle.cpp": 4, - "Source/Contents/HotkeyInfo.cpp": 4, + "Source/Contents/Actors/GameObject.cpp": 4, + "Source/Contents/Configuration/GraphicsConfiguration.cpp": 4, + "Source/Contents/Ground/GroundDecals.cpp": 3, + "Source/Contents/Ground/GroundGeometry.cpp": 3, + "Source/Contents/Ground/GroundLighting.cpp": 3, + "Source/Contents/Ground/GroundLightingInitialization.cpp": 3, + "Source/Contents/Ground/GroundLightmaps.cpp": 3, + "Source/Contents/Ground/GroundPicking.cpp": 3, + "Source/Contents/Ground/GroundRendering.cpp": 3, + "Source/Contents/Ground/GroundSamples.cpp": 3, + "Source/Contents/Ground/GroundSpatial.cpp": 3, + "Source/Contents/Ground/GroundWaterRendering.cpp": 3, + "Source/Contents/Ground/GroundWaterState.cpp": 3, + "Source/Contents/Emblems/GuildEmblemReqBundle.cpp": 4, + "Source/Contents/Hotkeys/HotkeyInfo.cpp": 4, "Source/Contents/InstantVar.cpp": 0, - "Source/Contents/ItemDescription.cpp": 4, - "Source/Contents/ItemInfo.cpp": 4, - "Source/Contents/ItemLink.cpp": 4, - "Source/Contents/ItemNaming.cpp": 4, - "Source/Contents/ItemResources.cpp": 4, - "Source/Contents/JobInheritance.cpp": 4, - "Source/Contents/JobNameInitialization.cpp": 4, - "Source/Contents/JobNames.cpp": 4, - "Source/Contents/LoadMyPartyAsyncWork.cpp": 4, - "Source/Contents/LoadPartyInfoAsyncWork.cpp": 4, - "Source/Contents/LoadPartyListAsyncWork.cpp": 4, - "Source/Contents/MCStoreInfoBackup.cpp": 4, - "Source/Contents/MCStoreInfoBackupAsyncWork.cpp": 4, + "Source/Contents/Items/ItemDescription.cpp": 4, + "Source/Contents/Items/ItemInfo.cpp": 4, + "Source/Contents/Items/ItemLink.cpp": 4, + "Source/Contents/Items/ItemNaming.cpp": 4, + "Source/Contents/Items/ItemResources.cpp": 4, + "Source/Contents/Jobs/JobInheritance.cpp": 4, + "Source/Contents/Jobs/JobNameInitialization.cpp": 4, + "Source/Contents/Jobs/JobNames.cpp": 4, + "Source/Contents/Party/LoadMyPartyAsyncWork.cpp": 4, + "Source/Contents/Party/LoadPartyInfoAsyncWork.cpp": 4, + "Source/Contents/Party/LoadPartyListAsyncWork.cpp": 4, + "Source/Contents/Store/MCStoreInfoBackup.cpp": 4, + "Source/Contents/Store/MCStoreInfoBackupAsyncWork.cpp": 4, "Source/Contents/MessageTable.cpp": 4, - "Source/Contents/MessengerMember.cpp": 4, - "Source/Contents/ModelActor.cpp": 3, - "Source/Contents/ModelActorBounds.cpp": 3, - "Source/Contents/ModelAnimation.cpp": 3, - "Source/Contents/ModelLighting.cpp": 3, - "Source/Contents/ModelMovies.cpp": 3, - "Source/Contents/ModelNode.cpp": 3, - "Source/Contents/ModelNodeBounds.cpp": 3, - "Source/Contents/ModelOcclusion.cpp": 3, - "Source/Contents/ModelPlayback.cpp": 3, - "Source/Contents/ModelQuaternion.cpp": 3, - "Source/Contents/ModelRendering.cpp": 3, - "Source/Contents/ModelSpatial.cpp": 3, - "Source/Contents/ModelTextureAnimation.cpp": 3, - "Source/Contents/ModelTextureUV.cpp": 3, - "Source/Contents/MyPartyCompletion.cpp": 2, - "Source/Contents/NormalItemSlots.cpp": 4, - "Source/Contents/OptionWriter.cpp": 4, - "Source/Contents/PartyEffect.cpp": 4, - "Source/Contents/PartyInfoCompletion.cpp": 2, - "Source/Contents/PartyInvitation.cpp": 2, - "Source/Contents/PartyJoinResult.cpp": 2, - "Source/Contents/PartyListCompletion.cpp": 2, - "Source/Contents/PartyMemberEffects.cpp": 4, - "Source/Contents/PartyRegistrationCompletion.cpp": 2, + "Source/Contents/Messenger/MessengerMember.cpp": 4, + "Source/Contents/Models/ModelActor.cpp": 3, + "Source/Contents/Models/ModelActorBounds.cpp": 3, + "Source/Contents/Models/ModelAnimation.cpp": 3, + "Source/Contents/Models/ModelLighting.cpp": 3, + "Source/Contents/Models/ModelMovies.cpp": 3, + "Source/Contents/Models/ModelNode.cpp": 3, + "Source/Contents/Models/ModelNodeBounds.cpp": 3, + "Source/Contents/Models/ModelOcclusion.cpp": 3, + "Source/Contents/Models/ModelPlayback.cpp": 3, + "Source/Contents/Models/ModelQuaternion.cpp": 3, + "Source/Contents/Models/ModelRendering.cpp": 3, + "Source/Contents/Models/ModelSpatial.cpp": 3, + "Source/Contents/Models/ModelTextureAnimation.cpp": 3, + "Source/Contents/Models/ModelTextureUV.cpp": 3, + "Source/Contents/Party/MyPartyCompletion.cpp": 2, + "Source/Contents/UserData/NormalItemSlots.cpp": 4, + "Source/Contents/Configuration/OptionWriter.cpp": 4, + "Source/Contents/Effects/PartyEffect.cpp": 4, + "Source/Contents/Party/PartyInfoCompletion.cpp": 2, + "Source/Contents/Party/PartyInvitation.cpp": 2, + "Source/Contents/Party/PartyJoinResult.cpp": 2, + "Source/Contents/Party/PartyListCompletion.cpp": 2, + "Source/Contents/Effects/PartyMemberEffects.cpp": 4, + "Source/Contents/Party/PartyRegistrationCompletion.cpp": 2, "Source/Contents/PlayerNameDictionary.cpp": 4, - "Source/Contents/PlayerSkillBundle.cpp": 4, - "Source/Contents/RagEffectInitialization.cpp": 4, - "Source/Contents/RagEffectResourceSelection.cpp": 4, - "Source/Contents/RagEffectState.cpp": 4, - "Source/Contents/RegisterPartyAsyncWork.cpp": 4, - "Source/Contents/RenderObject.cpp": 4, - "Source/Contents/RenderObjectState.cpp": 4, - "Source/Contents/ScriptOptions.cpp": 4, - "Source/Contents/ServiceOptions.cpp": 4, + "Source/Contents/Skills/PlayerSkillBundle.cpp": 4, + "Source/Contents/Effects/RagEffectInitialization.cpp": 4, + "Source/Contents/Effects/RagEffectResourceSelection.cpp": 4, + "Source/Contents/Effects/RagEffectState.cpp": 4, + "Source/Contents/Party/RegisterPartyAsyncWork.cpp": 4, + "Source/Contents/Actors/RenderObject.cpp": 4, + "Source/Contents/Actors/RenderObjectState.cpp": 4, + "Source/Contents/Configuration/ScriptOptions.cpp": 4, + "Source/Contents/Configuration/ServiceOptions.cpp": 4, "Source/Contents/ShowRankingScheduler.cpp": 4, - "Source/Contents/SkillInfo.cpp": 4, - "Source/Contents/SkillLevelConfig.cpp": 4, - "Source/Contents/SkillLevelRegistry.cpp": 4, - "Source/Contents/SkillTreeScript.cpp": 4, + "Source/Contents/Skills/SkillInfo.cpp": 4, + "Source/Contents/Skills/SkillLevelConfig.cpp": 4, + "Source/Contents/Skills/SkillLevelRegistry.cpp": 4, + "Source/Contents/Skills/SkillTreeScript.cpp": 4, "Source/Contents/SkinInfo.cpp": 3, - "Source/Contents/SoundConfiguration.cpp": 4, - "Source/Contents/SoundMgr.cpp": 4, - "Source/Contents/SpriteDrawingPolicy.cpp": 4, - "Source/Contents/StopRecruitingAsyncWork.cpp": 4, - "Source/Contents/StopRecruitingCompletion.cpp": 2, - "Source/Contents/StoreBackupData.cpp": 4, - "Source/Contents/TerrainCoordinates.cpp": 4, - "Source/Contents/TerrainHeight.cpp": 4, - "Source/Contents/TerrainPicking.cpp": 4, - "Source/Contents/TerrainPlane.cpp": 4, + "Source/Contents/Sound/SoundConfiguration.cpp": 4, + "Source/Contents/Sound/SoundMgr.cpp": 4, + "Source/Contents/Actors/SpriteDrawingPolicy.cpp": 4, + "Source/Contents/Party/StopRecruitingAsyncWork.cpp": 4, + "Source/Contents/Party/StopRecruitingCompletion.cpp": 2, + "Source/Contents/Store/StoreBackupData.cpp": 4, + "Source/Contents/Ground/TerrainCoordinates.cpp": 4, + "Source/Contents/Ground/TerrainHeight.cpp": 4, + "Source/Contents/Ground/TerrainPicking.cpp": 4, + "Source/Contents/Ground/TerrainPlane.cpp": 4, "Source/Contents/TipBoxTitles.cpp": 4, - "Source/Contents/UserHotkeyMgr.cpp": 4, - "Source/Contents/UserHotkeyScript.cpp": 4, - "Source/Contents/WhisperBlockMgr.cpp": 4, - "Source/Contents/WorldActors.cpp": 4, - "Source/Contents/WorldEnvironment.cpp": 3, - "Source/Contents/WorldGroundImport.cpp": 3, - "Source/Contents/WorldModelLoading.cpp": 3, - "Source/Contents/WorldModelPlacement.cpp": 3, - "Source/Contents/WorldModelView.cpp": 3, - "Source/Contents/WorldObjects.cpp": 4, - "Source/Contents/WorldOcclusion.cpp": 3, - "Source/Contents/WorldProximity.cpp": 4, - "Source/Contents/WorldRayQuery.cpp": 3, - "Source/Contents/WorldSpatialInitialization.cpp": 3, - "Source/Contents/WorldSpatialTree.cpp": 3, - "Source/Contents/WorldTerrainPicking.cpp": 4, - "Source/Contents/WorldViewSpatial.cpp": 3, + "Source/Contents/Hotkeys/UserHotkeyMgr.cpp": 4, + "Source/Contents/Hotkeys/UserHotkeyScript.cpp": 4, + "Source/Contents/Messenger/WhisperBlockMgr.cpp": 4, + "Source/Contents/World/WorldActors.cpp": 4, + "Source/Contents/World/WorldEnvironment.cpp": 3, + "Source/Contents/World/WorldGroundImport.cpp": 3, + "Source/Contents/World/WorldModelLoading.cpp": 3, + "Source/Contents/World/WorldModelPlacement.cpp": 3, + "Source/Contents/World/WorldModelView.cpp": 3, + "Source/Contents/World/WorldObjects.cpp": 4, + "Source/Contents/World/WorldOcclusion.cpp": 3, + "Source/Contents/World/WorldProximity.cpp": 4, + "Source/Contents/World/WorldRayQuery.cpp": 3, + "Source/Contents/World/WorldSpatialInitialization.cpp": 3, + "Source/Contents/World/WorldSpatialTree.cpp": 3, + "Source/Contents/World/WorldTerrainPicking.cpp": 4, + "Source/Contents/World/WorldViewSpatial.cpp": 3, "Source/File/CommonObject.cpp": 1, "Source/File/File.cpp": 1, "Source/File/MapName.cpp": 1, "Source/File/ResourcePath.cpp": 1, "Source/File/ShortcutFilename.cpp": 1, - "Source/Network/CURLMgr.cpp": 0, - "Source/Network/CURLPostHander.cpp": 0, - "Source/Network/Connection.cpp": 0, - "Source/Network/ConnectionBuffer.cpp": 0, - "Source/Network/ConnectionRuntime.cpp": 0, - "Source/Network/PacketLengths.cpp": 0, - "Source/Network/PartyJoinPacket.cpp": 0, - "Source/Network/PartyJoinRequest.cpp": 2, - "Source/Network/ShortcutPacket.cpp": 0, - "Source/Network/SkillUpdatePacket.cpp": 4, + "Source/Network/Http/CURLMgr.cpp": 0, + "Source/Network/Http/CURLPostHander.cpp": 0, + "Source/Network/Connection/Connection.cpp": 0, + "Source/Network/Connection/ConnectionBuffer.cpp": 0, + "Source/Network/Connection/ConnectionRuntime.cpp": 0, + "Source/Network/Packets/PacketLengths.cpp": 0, + "Source/Network/Packets/PartyJoinPacket.cpp": 0, + "Source/Network/Packets/PartyJoinRequest.cpp": 2, + "Source/Network/Packets/ShortcutPacket.cpp": 0, + "Source/Network/Packets/SkillUpdatePacket.cpp": 4, "Source/Network/TextEncoding.cpp": 0, - "Source/Render/AlphaQueuesDX9.cpp": 0, - "Source/Render/BackBufferDX7.cpp": 0, - "Source/Render/BackBufferDX9.cpp": 0, - "Source/Render/BitmapPixels.cpp": 0, - "Source/Render/BitmapTextureCache.cpp": 0, + "Source/Render/DX9/AlphaQueuesDX9.cpp": 0, + "Source/Render/DX7/BackBufferDX7.cpp": 0, + "Source/Render/DX9/BackBufferDX9.cpp": 0, + "Source/Render/Textures/BitmapPixels.cpp": 0, + "Source/Render/Textures/BitmapTextureCache.cpp": 0, "Source/Render/BlendColor.cpp": 0, - "Source/Render/ClientTextureSources.cpp": 3, - "Source/Render/D3DX9Runtime.cpp": 0, - "Source/Render/DCBitmap.cpp": 0, - "Source/Render/DCSurface.cpp": 0, - "Source/Render/DepthAlpha.cpp": 0, - "Source/Render/DeviceCapabilitiesDX7.cpp": 0, - "Source/Render/DeviceContext.cpp": 0, - "Source/Render/DeviceOwnerDX7.cpp": 0, - "Source/Render/DeviceOwnerDX9.cpp": 0, - "Source/Render/DeviceRecoveryDX9.cpp": 0, - "Source/Render/DeviceStateDX9.cpp": 0, + "Source/Render/Textures/ClientTextureSources.cpp": 3, + "Source/Render/DX9/D3DX9Runtime.cpp": 0, + "Source/Render/DeviceContext/DCBitmap.cpp": 0, + "Source/Render/DeviceContext/DCSurface.cpp": 0, + "Source/Render/Primitives/DepthAlpha.cpp": 0, + "Source/Render/DX7/DeviceCapabilitiesDX7.cpp": 0, + "Source/Render/DeviceContext/DeviceContext.cpp": 0, + "Source/Render/DX7/DeviceOwnerDX7.cpp": 0, + "Source/Render/DX9/DeviceOwnerDX9.cpp": 0, + "Source/Render/DX9/DeviceRecoveryDX9.cpp": 0, + "Source/Render/DX9/DeviceStateDX9.cpp": 0, "Source/Render/Direct3DErrors.cpp": 0, - "Source/Render/DirectDrawEnumeration.cpp": 0, + "Source/Render/DX7/DirectDrawEnumeration.cpp": 0, "Source/Render/DisplayMode.cpp": 0, - "Source/Render/DisplayModeDX7.cpp": 0, - "Source/Render/FontCache.cpp": 0, - "Source/Render/GroundQueuesDX9.cpp": 0, - "Source/Render/LightmappedPrimitive.cpp": 0, - "Source/Render/OpaqueQueuesDX9.cpp": 0, - "Source/Render/QueuedDrawingDX9.cpp": 0, + "Source/Render/DX7/DisplayModeDX7.cpp": 0, + "Source/Render/Text/FontCache.cpp": 0, + "Source/Render/DX9/GroundQueuesDX9.cpp": 0, + "Source/Render/Primitives/LightmappedPrimitive.cpp": 0, + "Source/Render/DX9/OpaqueQueuesDX9.cpp": 0, + "Source/Render/DX9/QueuedDrawingDX9.cpp": 0, "Source/Render/RenderAdapter.cpp": 0, - "Source/Render/RenderAdapterDX7.cpp": 0, + "Source/Render/DX7/RenderAdapterDX7.cpp": 0, "Source/Render/RenderBackends.cpp": 0, - "Source/Render/RenderCommandPool.cpp": 0, - "Source/Render/RenderPrimitive.cpp": 0, - "Source/Render/RenderPrimitivePool.cpp": 0, - "Source/Render/RenderProjection.cpp": 0, - "Source/Render/RenderQueues.cpp": 0, - "Source/Render/RenderRay.cpp": 0, - "Source/Render/RenderSystemDX7.cpp": 0, - "Source/Render/RenderSystemDX9.cpp": 0, - "Source/Render/RenderToTextureDX7.cpp": 0, - "Source/Render/RenderVertexPool.cpp": 0, + "Source/Render/Primitives/RenderCommandPool.cpp": 0, + "Source/Render/Primitives/RenderPrimitive.cpp": 0, + "Source/Render/Primitives/RenderPrimitivePool.cpp": 0, + "Source/Render/Projection/RenderProjection.cpp": 0, + "Source/Render/Primitives/RenderQueues.cpp": 0, + "Source/Render/Projection/RenderRay.cpp": 0, + "Source/Render/DX7/RenderSystemDX7.cpp": 0, + "Source/Render/DX9/RenderSystemDX9.cpp": 0, + "Source/Render/DX7/RenderToTextureDX7.cpp": 0, + "Source/Render/Primitives/RenderVertexPool.cpp": 0, "Source/Render/Renderer.cpp": 0, - "Source/Render/RendererBackBuffer.cpp": 0, - "Source/Render/RendererDX7Operations.cpp": 0, - "Source/Render/RendererDX9.cpp": 0, - "Source/Render/RendererDX9Operations.cpp": 0, - "Source/Render/RendererFogDX7.cpp": 0, - "Source/Render/RendererFogDX9.cpp": 0, - "Source/Render/RendererFrameDX9.cpp": 0, - "Source/Render/RendererPresentation.cpp": 0, - "Source/Render/RendererPresentationDX7.cpp": 0, - "Source/Render/RendererViewport.cpp": 0, - "Source/Render/ScreenshotDX7.cpp": 0, - "Source/Render/ScreenshotDX9.cpp": 0, - "Source/Render/SpriteAtlas.cpp": 0, - "Source/Render/Surface.cpp": 0, - "Source/Render/SurfaceDX7.cpp": 0, - "Source/Render/SurfaceDX9.cpp": 0, - "Source/Render/TextContext.cpp": 0, - "Source/Render/Texture.cpp": 0, - "Source/Render/TextureAllocationDX7.cpp": 0, - "Source/Render/TextureBindingDX7.cpp": 0, - "Source/Render/TextureCache.cpp": 3, - "Source/Render/TextureCalibrationDX7.cpp": 0, - "Source/Render/TextureDX7.cpp": 0, - "Source/Render/TextureDX9.cpp": 0, - "Source/Render/TextureModesDX7.cpp": 0, - "Source/Render/TextureModesDX9.cpp": 0, + "Source/Render/DX9/RendererBackBuffer.cpp": 0, + "Source/Render/DX7/RendererDX7Operations.cpp": 0, + "Source/Render/DX9/RendererDX9.cpp": 0, + "Source/Render/DX9/RendererDX9Operations.cpp": 0, + "Source/Render/DX7/RendererFogDX7.cpp": 0, + "Source/Render/DX9/RendererFogDX9.cpp": 0, + "Source/Render/DX9/RendererFrameDX9.cpp": 0, + "Source/Render/DX9/RendererPresentation.cpp": 0, + "Source/Render/DX7/RendererPresentationDX7.cpp": 0, + "Source/Render/Projection/RendererViewport.cpp": 0, + "Source/Render/DX7/ScreenshotDX7.cpp": 0, + "Source/Render/DX9/ScreenshotDX9.cpp": 0, + "Source/Render/Textures/SpriteAtlas.cpp": 0, + "Source/Render/Textures/Surface.cpp": 0, + "Source/Render/DX7/SurfaceDX7.cpp": 0, + "Source/Render/DX9/SurfaceDX9.cpp": 0, + "Source/Render/Text/TextContext.cpp": 0, + "Source/Render/Textures/Texture.cpp": 0, + "Source/Render/DX7/TextureAllocationDX7.cpp": 0, + "Source/Render/DX7/TextureBindingDX7.cpp": 0, + "Source/Render/Textures/TextureCache.cpp": 3, + "Source/Render/DX7/TextureCalibrationDX7.cpp": 0, + "Source/Render/DX7/TextureDX7.cpp": 0, + "Source/Render/DX9/TextureDX9.cpp": 0, + "Source/Render/DX7/TextureModesDX7.cpp": 0, + "Source/Render/DX9/TextureModesDX9.cpp": 0, "Source/Render/TextureStageModes.cpp": 0, - "Source/Render/UIRPData.cpp": 0, - "Source/Resource/ActionResource.cpp": 3, - "Source/Resource/AnimatedModelResource.cpp": 3, + "Source/Render/Primitives/UIRPData.cpp": 0, + "Source/Resource/Sprites/ActionResource.cpp": 3, + "Source/Resource/Models/AnimatedModelResource.cpp": 3, "Source/Resource/BinkRuntime.cpp": 3, - "Source/Resource/BitmapImage.cpp": 3, - "Source/Resource/BitmapImageJpeg.cpp": 3, - "Source/Resource/BitmapImagePng.cpp": 3, - "Source/Resource/BitmapResource.cpp": 3, + "Source/Resource/Bitmap/BitmapImage.cpp": 3, + "Source/Resource/Bitmap/BitmapImageJpeg.cpp": 3, + "Source/Resource/Bitmap/BitmapImagePng.cpp": 3, + "Source/Resource/Bitmap/BitmapResource.cpp": 3, "Source/Resource/EZeffectResource.cpp": 3, - "Source/Resource/GroundResource.cpp": 3, - "Source/Resource/IJL15Runtime.cpp": 3, - "Source/Resource/MilesRuntime.cpp": 3, - "Source/Resource/ModelMesh.cpp": 3, - "Source/Resource/ModelNodeLoading.cpp": 3, - "Source/Resource/ModelNodeLoadingV2.cpp": 3, - "Source/Resource/ModelResource.cpp": 3, - "Source/Resource/ModelResourceV2.cpp": 3, + "Source/Resource/World/GroundResource.cpp": 3, + "Source/Resource/Bitmap/IJL15Runtime.cpp": 3, + "Source/Resource/Audio/MilesRuntime.cpp": 3, + "Source/Resource/Models/ModelMesh.cpp": 3, + "Source/Resource/Models/ModelNodeLoading.cpp": 3, + "Source/Resource/Models/ModelNodeLoadingV2.cpp": 3, + "Source/Resource/Models/ModelResource.cpp": 3, + "Source/Resource/Models/ModelResourceV2.cpp": 3, "Source/Resource/Resource.cpp": 3, "Source/Resource/ResourceAliases.cpp": 3, "Source/Resource/ResourceFailures.cpp": 3, "Source/Resource/ResourceMgr.cpp": 3, "Source/Resource/ResourceTransient.cpp": 3, - "Source/Resource/SpriteEncoding.cpp": 3, - "Source/Resource/SpriteResource.cpp": 3, - "Source/Resource/TerrainResource.cpp": 3, + "Source/Resource/Sprites/SpriteEncoding.cpp": 3, + "Source/Resource/Sprites/SpriteResource.cpp": 3, + "Source/Resource/World/TerrainResource.cpp": 3, "Source/Resource/TextureNames.cpp": 3, - "Source/Resource/WaveResource.cpp": 3, - "Source/Resource/WorldEnvironment.cpp": 3, - "Source/Resource/WorldObjects.cpp": 3, - "Source/Resource/WorldResource.cpp": 3, + "Source/Resource/Audio/WaveResource.cpp": 3, + "Source/Resource/World/WorldEnvironment.cpp": 3, + "Source/Resource/World/WorldObjects.cpp": 3, + "Source/Resource/World/WorldResource.cpp": 3, "Source/Script/LuaInstance.cpp": 5, "Source/Script/LuaScript.cpp": 5, - "Source/UI/BrowserFactory.cpp": 2, - "Source/UI/BrowserPopupDispatch.cpp": 2, - "Source/UI/ChatNotifications.cpp": 2, - "Source/UI/ChatSuggestions.cpp": 2, - "Source/UI/ColoredText.cpp": 2, - "Source/UI/CooldownDrawing.cpp": 2, - "Source/UI/CooldownOwner.cpp": 2, - "Source/UI/CooldownState.cpp": 2, - "Source/UI/EditPainting.cpp": 2, - "Source/UI/EditTextState.cpp": 2, - "Source/UI/EditViewport.cpp": 2, - "Source/UI/FrameFocus.cpp": 2, - "Source/UI/FrameTextCache.cpp": 2, - "Source/UI/InputFocus.cpp": 2, - "Source/UI/ItemDrawing.cpp": 2, - "Source/UI/ItemLinkDisplay.cpp": 2, - "Source/UI/ItemTagRetirement.cpp": 2, - "Source/UI/MerchantShopRefresh.cpp": 2, - "Source/UI/NavigationLink.cpp": 2, - "Source/UI/NormalItemSlotLoad.cpp": 2, - "Source/UI/PixelTextWrapping.cpp": 2, - "Source/UI/PriceColor.cpp": 2, - "Source/UI/ShortcutActivation.cpp": 2, - "Source/UI/ShortcutBindings.cpp": 2, - "Source/UI/ShortcutControlEvents.cpp": 2, - "Source/UI/ShortcutControls.cpp": 2, - "Source/UI/ShortcutCooldowns.cpp": 2, - "Source/UI/ShortcutDetails.cpp": 2, - "Source/UI/ShortcutDrop.cpp": 2, - "Source/UI/ShortcutGrid.cpp": 2, - "Source/UI/ShortcutLayout.cpp": 2, - "Source/UI/ShortcutPainting.cpp": 2, - "Source/UI/ShortcutPress.cpp": 2, - "Source/UI/ShortcutTooltip.cpp": 2, - "Source/UI/ShortcutUse.cpp": 2, - "Source/UI/ShortcutVisibility.cpp": 2, - "Source/UI/SkillDetailClose.cpp": 2, - "Source/UI/SnapMgr.cpp": 2, - "Source/UI/SnapObject.cpp": 2, - "Source/UI/SnapRectangle.cpp": 2, - "Source/UI/TextFitting.cpp": 2, - "Source/UI/TextMarkup.cpp": 2, - "Source/UI/TextWrapping.cpp": 2, - "Source/UI/UIAdvenPartyBoardWnd.cpp": 2, - "Source/UI/UIApplyForPartyWnd.cpp": 2, - "Source/UI/UIBalloonText.cpp": 2, - "Source/UI/UIBasicButton.cpp": 2, - "Source/UI/UIBitmapButton.cpp": 2, - "Source/UI/UIBmpTextButton.cpp": 2, - "Source/UI/UIButton.cpp": 2, - "Source/UI/UICheckBox.cpp": 2, - "Source/UI/UIChooseSellBuyWnd.cpp": 2, - "Source/UI/UIComboBoxDefWnd.cpp": 2, - "Source/UI/UIComboBoxEx.cpp": 2, - "Source/UI/UIControl.cpp": 2, - "Source/UI/UIDropDownBox.cpp": 2, - "Source/UI/UIEditCtrl.cpp": 2, - "Source/UI/UIEditLinks.cpp": 2, - "Source/UI/UIEditVariants.cpp": 2, - "Source/UI/UIExchangeAcceptWnd.cpp": 2, - "Source/UI/UIFrameWnd.cpp": 2, - "Source/UI/UIJobSlotButton.cpp": 2, - "Source/UI/UIJoinPartyAcceptWnd.cpp": 2, - "Source/UI/UIListBox.cpp": 2, - "Source/UI/UIListBoxEx.cpp": 2, - "Source/UI/UIMessageBox.cpp": 2, - "Source/UI/UINaviLinkButton.cpp": 2, - "Source/UI/UIPartyInfoWnd.cpp": 2, - "Source/UI/UIRegisterPartyWnd.cpp": 2, - "Source/UI/UIRequestJoinPartyMgr.cpp": 2, - "Source/UI/UIRequestJoinPartyWnd.cpp": 2, - "Source/UI/UIScrollBar.cpp": 2, - "Source/UI/UIScrollBarNavi.cpp": 2, - "Source/UI/UIShortCutWnd.cpp": 2, + "Source/Client/Browser/BrowserFactory.cpp": 2, + "Source/Client/Browser/BrowserPopupDispatch.cpp": 2, + "Source/UI/Chat/ChatNotifications.cpp": 2, + "Source/UI/Chat/ChatSuggestions.cpp": 2, + "Source/UI/Text/ColoredText.cpp": 2, + "Source/UI/Cooldowns/CooldownDrawing.cpp": 2, + "Source/UI/Cooldowns/CooldownOwner.cpp": 2, + "Source/UI/Cooldowns/CooldownState.cpp": 2, + "Source/UI/Edit/EditPainting.cpp": 2, + "Source/UI/Edit/EditTextState.cpp": 2, + "Source/UI/Edit/EditViewport.cpp": 2, + "Source/UI/Window/FrameFocus.cpp": 2, + "Source/UI/Window/FrameTextCache.cpp": 2, + "Source/UI/Window/InputFocus.cpp": 2, + "Source/UI/Shop/ItemDrawing.cpp": 2, + "Source/UI/Text/ItemLinkDisplay.cpp": 2, + "Source/UI/Edit/ItemTagRetirement.cpp": 2, + "Source/UI/Shop/MerchantShopRefresh.cpp": 2, + "Source/UI/Text/NavigationLink.cpp": 2, + "Source/UI/Shortcuts/NormalItemSlotLoad.cpp": 2, + "Source/UI/Text/PixelTextWrapping.cpp": 2, + "Source/UI/Shop/PriceColor.cpp": 2, + "Source/UI/Shortcuts/ShortcutActivation.cpp": 2, + "Source/UI/Shortcuts/ShortcutBindings.cpp": 2, + "Source/UI/Shortcuts/ShortcutControlEvents.cpp": 2, + "Source/UI/Shortcuts/ShortcutControls.cpp": 2, + "Source/UI/Shortcuts/ShortcutCooldowns.cpp": 2, + "Source/UI/Shortcuts/ShortcutDetails.cpp": 2, + "Source/UI/Shortcuts/ShortcutDrop.cpp": 2, + "Source/UI/Shortcuts/ShortcutGrid.cpp": 2, + "Source/UI/Shortcuts/ShortcutLayout.cpp": 2, + "Source/UI/Shortcuts/ShortcutPainting.cpp": 2, + "Source/UI/Shortcuts/ShortcutPress.cpp": 2, + "Source/UI/Shortcuts/ShortcutTooltip.cpp": 2, + "Source/UI/Shortcuts/ShortcutUse.cpp": 2, + "Source/UI/Shortcuts/ShortcutVisibility.cpp": 2, + "Source/UI/Shortcuts/SkillDetailClose.cpp": 2, + "Source/UI/Layout/SnapMgr.cpp": 2, + "Source/UI/Layout/SnapObject.cpp": 2, + "Source/UI/Layout/SnapRectangle.cpp": 2, + "Source/UI/Text/TextFitting.cpp": 2, + "Source/UI/Text/TextMarkup.cpp": 2, + "Source/UI/Text/TextWrapping.cpp": 2, + "Source/UI/Party/UIAdvenPartyBoardWnd.cpp": 2, + "Source/UI/Party/UIApplyForPartyWnd.cpp": 2, + "Source/UI/Text/UIBalloonText.cpp": 2, + "Source/UI/Buttons/UIBasicButton.cpp": 2, + "Source/UI/Buttons/UIBitmapButton.cpp": 2, + "Source/UI/Buttons/UIBmpTextButton.cpp": 2, + "Source/UI/Buttons/UIButton.cpp": 2, + "Source/UI/Buttons/UICheckBox.cpp": 2, + "Source/UI/Acceptance/UIChooseSellBuyWnd.cpp": 2, + "Source/UI/Lists/UIComboBoxDefWnd.cpp": 2, + "Source/UI/Lists/UIComboBoxEx.cpp": 2, + "Source/UI/Window/UIControl.cpp": 2, + "Source/UI/Lists/UIDropDownBox.cpp": 2, + "Source/UI/Edit/UIEditCtrl.cpp": 2, + "Source/UI/Edit/UIEditLinks.cpp": 2, + "Source/UI/Edit/UIEditVariants.cpp": 2, + "Source/UI/Acceptance/UIExchangeAcceptWnd.cpp": 2, + "Source/UI/Window/UIFrameWnd.cpp": 2, + "Source/UI/Buttons/UIJobSlotButton.cpp": 2, + "Source/UI/Acceptance/UIJoinPartyAcceptWnd.cpp": 2, + "Source/UI/Lists/UIListBox.cpp": 2, + "Source/UI/Lists/UIListBoxEx.cpp": 2, + "Source/UI/Window/UIMessageBox.cpp": 2, + "Source/UI/Buttons/UINaviLinkButton.cpp": 2, + "Source/UI/Party/UIPartyInfoWnd.cpp": 2, + "Source/UI/Party/UIRegisterPartyWnd.cpp": 2, + "Source/UI/Party/UIRequestJoinPartyMgr.cpp": 2, + "Source/UI/Party/UIRequestJoinPartyWnd.cpp": 2, + "Source/UI/Lists/UIScrollBar.cpp": 2, + "Source/UI/Lists/UIScrollBarNavi.cpp": 2, + "Source/UI/Shortcuts/UIShortCutWnd.cpp": 2, "Source/UI/UIStaticBitmap.cpp": 2, - "Source/UI/UIStaticText.cpp": 2, - "Source/UI/UITextButton.cpp": 2, - "Source/UI/UITextViewer.cpp": 2, - "Source/UI/UITextViewerLinks.cpp": 2, - "Source/UI/UITextViewerMessages.cpp": 2, - "Source/UI/UITransBalloonText.cpp": 2, - "Source/UI/UIWindow.cpp": 2, - "Source/UI/WindowAncestry.cpp": 2, - "Source/UI/WindowBorder.cpp": 2, - "Source/UI/WindowCoordinates.cpp": 2, - "Source/UI/WindowDialogs.cpp": 2, - "Source/UI/WindowFrameUpdate.cpp": 2, - "Source/UI/WindowGeometry.cpp": 2, - "Source/UI/WindowMouseHit.cpp": 2, - "Source/UI/WindowOrdering.cpp": 2, - "Source/UI/WindowPolicy.cpp": 2, - "Source/UI/WindowRegistration.cpp": 2, - "Source/UI/WindowRetirement.cpp": 2, - "Source/UI/WindowSnapping.cpp": 2, - "Source/Utility/AffineLookAt.cpp": 0, - "Source/Utility/AffineMatrix.cpp": 0, - "Source/Utility/AsyncDiagnostic.cpp": 0, + "Source/UI/Text/UIStaticText.cpp": 2, + "Source/UI/Buttons/UITextButton.cpp": 2, + "Source/UI/Text/UITextViewer.cpp": 2, + "Source/UI/Text/UITextViewerLinks.cpp": 2, + "Source/UI/Text/UITextViewerMessages.cpp": 2, + "Source/UI/Text/UITransBalloonText.cpp": 2, + "Source/UI/Window/UIWindow.cpp": 2, + "Source/UI/Window/WindowAncestry.cpp": 2, + "Source/UI/Window/WindowBorder.cpp": 2, + "Source/UI/Layout/WindowCoordinates.cpp": 2, + "Source/UI/Window/WindowDialogs.cpp": 2, + "Source/UI/Window/WindowFrameUpdate.cpp": 2, + "Source/UI/Layout/WindowGeometry.cpp": 2, + "Source/UI/Window/WindowMouseHit.cpp": 2, + "Source/UI/Window/WindowOrdering.cpp": 2, + "Source/UI/Window/WindowPolicy.cpp": 2, + "Source/UI/Window/WindowRegistration.cpp": 2, + "Source/UI/Window/WindowRetirement.cpp": 2, + "Source/UI/Layout/WindowSnapping.cpp": 2, + "Source/Utility/Math/AffineLookAt.cpp": 0, + "Source/Utility/Math/AffineMatrix.cpp": 0, + "Source/Utility/Async/AsyncDiagnostic.cpp": 0, "Source/Utility/Base64.cpp": 0, - "Source/Utility/CSyncObject.cpp": 0, - "Source/Utility/ClientAngles.cpp": 0, - "Source/Utility/FormatString.cpp": 0, - "Source/Utility/GroupedInteger.cpp": 0, + "Source/Utility/Threading/CSyncObject.cpp": 0, + "Source/Utility/Math/ClientAngles.cpp": 0, + "Source/Utility/Text/FormatString.cpp": 0, + "Source/Utility/Text/GroupedInteger.cpp": 0, "Source/Utility/GuidParse.cpp": 0, - "Source/Utility/LanguageCharset.cpp": 0, - "Source/Utility/NAsyncWork.cpp": 0, - "Source/Utility/NAsyncWorkMgr.cpp": 0, - "Source/Utility/NAsyncWorkQueue.cpp": 0, - "Source/Utility/NAsyncWorkThread.cpp": 0, - "Source/Utility/NMessageMgr.cpp": 0, - "Source/Utility/NMessageQueue.cpp": 0, - "Source/Utility/NObject.cpp": 0, - "Source/Utility/NRecycleObject.cpp": 0, - "Source/Utility/NRecycleObjectPoolMgr.cpp": 0, - "Source/Utility/NSyncObject.cpp": 0, - "Source/Utility/NThread.cpp": 0, - "Source/Utility/RayTriangle.cpp": 0, + "Source/Utility/Text/LanguageCharset.cpp": 0, + "Source/Utility/Async/NAsyncWork.cpp": 0, + "Source/Utility/Async/NAsyncWorkMgr.cpp": 0, + "Source/Utility/Async/NAsyncWorkQueue.cpp": 0, + "Source/Utility/Async/NAsyncWorkThread.cpp": 0, + "Source/Utility/Async/NMessageMgr.cpp": 0, + "Source/Utility/Async/NMessageQueue.cpp": 0, + "Source/Utility/Async/NObject.cpp": 0, + "Source/Utility/Async/NRecycleObject.cpp": 0, + "Source/Utility/Async/NRecycleObjectPoolMgr.cpp": 0, + "Source/Utility/Threading/NSyncObject.cpp": 0, + "Source/Utility/Threading/NThread.cpp": 0, + "Source/Utility/Math/RayTriangle.cpp": 0, "Source/Utility/Rijndael.cpp": 0, "Source/Utility/XorBytes.cpp": 0, "ThirdParty/jsoncpp/src/lib_json/json_reader.cpp": 8,