1
0

10 Commits

18 changed files with 301 additions and 102 deletions

View File

@@ -9,6 +9,19 @@ MKDIR install
:: Build with x64 architecture in Release mode
CD build
:: We set this to revert the incompatible ABI for MSVC STL.
:: See: https://github.com/microsoft/STL/wiki/VS-2022-Changelog#vs-2022-1710
::
:: Ideally, I can install new VCRedist to resolve this issue.
:: However, Blender embeds its own VCRedist when distribution which has lower VCRedist version.
:: And at the same time, Blender will load our BMap.dll built by new VCRedist, so it trigger the incompatible ABI issue.
::
:: Currently, the VCRedist distributed by Blender 4.5 LTS is incompatible with our BMap.dll.
:: So I write it in script, rather than in CMake file, to temporaryly fix this issue.
::
:: This fix also is written in dependency build scripts, please remove them together if you remove this,
:: when Blender migrate to the new VCRedist.
set CXXFLAGS=/D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR=1
cmake -A x64 -DCMAKE_CXX_STANDARD=23 -DNEMO_BUILD_UNVIRT=ON -DNEMO_BUILD_BALLANCE=ON -DNEMO_BUILD_BMAP=ON -DNEMO_BUILD_BMAPINSPECTOR=ON -DYYCCommonplace_ROOT=%YYCCommonplace_ROOT% -DSTB_ROOT=%STB_ROOT% -DZLIB_ROOT=%ZLIB_ROOT% ../..
cmake --build . --config Release
cmake --install . --prefix=../install --config Release

View File

@@ -9,6 +9,7 @@ MKDIR install
:: Build with x64 architecture in Release mode
CD build
set CXXFLAGS=/D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR=1
cmake -A x64 -DCMAKE_CXX_STANDARD=23 ../..
cmake --build . --config Release
cmake --install . --prefix=../install --config Release

View File

@@ -18,7 +18,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: 'yyc12345/YYCCommonplace'
ref: 'master'
ref: 'v2.0.0'
path: 'extern/YYCCommonplace'
- name: Build YYCCommonplace
shell: bash

View File

@@ -13,7 +13,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: 'yyc12345/YYCCommonplace'
ref: 'master'
ref: 'v2.0.0'
path: 'extern/YYCCommonplace'
- name: Build YYCCommonplace
shell: bash

View File

@@ -20,7 +20,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: 'yyc12345/YYCCommonplace'
ref: 'master'
ref: 'v2.0.0'
path: 'extern/YYCCommonplace'
- name: Build YYCCommonplace
shell: cmd

View File

@@ -5,10 +5,11 @@
#include "Rule.hpp"
#include <VTAll.hpp>
#include <yycc.hpp>
#include <yycc/carton/termcolor.hpp>
#include <yycc/string/op.hpp>
#include <yycc/patch/stream.hpp>
#include <yycc/windows/console.hpp>
#include <yycc/carton/termcolor.hpp>
#include <yycc/carton/ironpad.hpp>
#include <iostream>
#include <optional>

View File

@@ -30,6 +30,8 @@ namespace BMapInspector::Rule {
rules.emplace_back(new Ruleset::YYCRule2());
rules.emplace_back(new Ruleset::YYCRule3());
rules.emplace_back(new Ruleset::YYCRule4());
rules.emplace_back(new Ruleset::YYCRule5());
rules.emplace_back(new Ruleset::YYCRule6());
rules.emplace_back(new Ruleset::BBugRule1());
rules.emplace_back(new Ruleset::BBugRule2());
rules.emplace_back(new Ruleset::BBugRule3());
@@ -59,4 +61,4 @@ namespace BMapInspector::Rule {
#pragma endregion
} // namespace BMapInspector::RuleCollection
} // namespace BMapInspector::Rule

View File

@@ -54,9 +54,9 @@ namespace BMapInspector::Ruleset {
void BBugRule3::Check(Reporter::Reporter& reporter, Map::Level& level) const {
// TODO:
// This function is already presented in Ballance Blender Plugin,
// so I don't want write it in there now.
// Write this if I have spare time in future.
// This rule is complex and can be done by Ballance Blender Plugin.
// So we are not urgently to implement it in there.
// Just make a rule placeholder in there and may finish it in future.
}
#pragma endregion

View File

@@ -23,8 +23,9 @@ namespace BMapInspector::Ruleset {
void GpRule1::Check(Reporter::Reporter& reporter, Map::Level& level) const {
// TODO:
// Finish this rule.
// It is so complex that I don't want to implement it now.
// This rule is complex and can be done by Ballance Blender Plugin.
// So we are not urgently to implement it in there.
// Just make a rule placeholder in there and may finish it in future.
}
#pragma endregion

View File

@@ -4,6 +4,7 @@
#include <yycc/macro/class_copy_move.hpp>
#include <yycc/macro/ptr_size_detector.hpp>
#include <utility>
#include <optional>
#define BMAPINSP_L LibCmo
#define BMAPINSP_C LibCmo::CK2

View File

@@ -0,0 +1,3 @@
#include "Name.hpp"
namespace BMapInspector::Ruleset::Shared::Name {}

View File

@@ -7,6 +7,7 @@
#include <vector>
#include <set>
#include <optional>
#include <algorithm>
#include <unordered_set>
namespace L = LibCmo;
@@ -262,13 +263,13 @@ namespace BMapInspector::Ruleset {
auto lower_tex_filename = strop::to_lower(tex_filename.value());
if (opaque_texs.contains(lower_tex_filename)) {
if (tex->GetVideoFormat() != V::VX_PIXELFORMAT::_16_ARGB1555) {
reporter.FormatWarning(u8"Texture %s is Ballance opaque texture. But its video format is not ARGB1555. "
reporter.FormatInfo(u8"Texture %s is Ballance opaque texture. But its video format is not ARGB1555. "
u8"This is mismatched with vanilla Ballance.",
Shared::Utility::QuoteObjectName(tex).c_str());
}
} else if (transparent_texs.contains(lower_tex_filename)) {
if (tex->GetVideoFormat() != V::VX_PIXELFORMAT::_32_ARGB8888) {
reporter.FormatWarning(u8"Texture %s is Ballance transparent texture. But its video format is not ARGB8888. "
reporter.FormatInfo(u8"Texture %s is Ballance transparent texture. But its video format is not ARGB8888. "
u8"This is mismatched with vanilla Ballance.",
Shared::Utility::QuoteObjectName(tex).c_str());
}
@@ -278,13 +279,13 @@ namespace BMapInspector::Ruleset {
// Do nothing.
break;
case V::VX_PIXELFORMAT::_32_ARGB8888:
reporter.FormatWarning(u8"Texture %s is not Ballance texture. Its video format is ARGB8888. "
reporter.FormatInfo(u8"Texture %s is not Ballance texture. Its video format is ARGB8888. "
u8"This may cause useless performance consumption if there is no transparent inside it. "
u8"Please check whether this is essential.",
Shared::Utility::QuoteObjectName(tex).c_str());
break;
default:
reporter.FormatWarning(
reporter.FormatInfo(
u8"Texture %s is not Ballance texture. Its video format is not ARGB1555 or ARGB8888. "
u8"This is mismatched with vanilla Ballance. "
u8"Please set it to ARGB1555 for opaque texture, or ARGB8888 for transaprent texture, except special scenario.",
@@ -295,4 +296,79 @@ namespace BMapInspector::Ruleset {
}
}
#pragma endregion
#pragma region YYC Rule 5
YYCRule5::YYCRule5() : Rule::IRule() {}
YYCRule5::~YYCRule5() {}
std::u8string_view YYCRule5::GetRuleName() const {
return u8"YYC5";
}
void YYCRule5::Check(Reporter::Reporter& reporter, Map::Level& level) const {
// Build lowercase texture name set first.
std::set<std::u8string> texs;
for (const auto* tex_name : Shared::Name::Texture::ALL) {
texs.emplace(strop::to_lower(tex_name));
}
// Check texture one by one
for (auto& tex : level.GetTextures()) {
auto tex_filename = Shared::Utility::ExtractTextureFileName(tex);
if (!tex_filename.has_value()) continue;
auto lower_tex_filename = strop::to_lower(tex_filename.value());
bool is_ballance_tex = texs.contains(lower_tex_filename);
using C::CK_TEXTURE_SAVEOPTIONS;
switch (tex->GetUnderlyingData().GetSaveOptions()) {
case CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_USEGLOBAL:
reporter.FormatInfo(u8"The save option of texture %s rely on global Virtools settings. "
u8"This cause ambiguity and different behavior on different Virtools by different user settings. "
u8"Please consider change it to explicit option, such as External or Raw Data.",
Shared::Utility::QuoteObjectName(tex).c_str());
break;
case CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_EXTERNAL:
if (!is_ballance_tex) {
reporter.FormatWarning(u8"Texture %s is not Ballance texture, but its save option is External. "
u8"This may cause texture loss when rendering in game. Please consider store it inside map.",
Shared::Utility::QuoteObjectName(tex).c_str());
}
break;
default:
if (is_ballance_tex) {
reporter.FormatInfo(u8"Texture %s is Ballance texture, but its save option is not External. "
u8"Please consider storing it as External to reduce the final size of map file, "
u8"and let user specified texture pack work.",
Shared::Utility::QuoteObjectName(tex).c_str());
}
break;
}
}
}
#pragma endregion
#pragma region YYC Rule 6
YYCRule6::YYCRule6() : Rule::IRule() {}
YYCRule6::~YYCRule6() {}
std::u8string_view YYCRule6::GetRuleName() const {
return u8"YYC6";
}
void YYCRule6::Check(Reporter::Reporter& reporter, Map::Level& level) const {
// TODO:
// This rule is not so essential.
// So we are not urgently to implement it in there.
// Just make a rule placeholder in there and may finish it in future.
}
#pragma endregion
} // namespace BMapInspector::Ruleset

View File

@@ -56,9 +56,8 @@ namespace BMapInspector::Ruleset {
/**
* @brief YYC12345 Rule 4
* @details
* \li Check the video format for opaque and transparent texture respectively.
* \li Warning for video format which is not used by vanilla Ballance.
* \li Warning for transparent used video format in non-Ballance textures to conserve resources.
* Check the video format for Ballance and user-defined texture respectively.
* Report if there is non-vanilla Ballance settings.
*/
class YYCRule4 : public Rule::IRule {
public:
@@ -71,4 +70,37 @@ namespace BMapInspector::Ruleset {
void Check(Reporter::Reporter& reporter, Map::Level& level) const override;
};
/**
* @brief YYC12345 Rule 5
* @details
* Check the save options for Ballance and user-defined texture respectively
* for reducing map size and avoid ambiguity.
*/
class YYCRule5 : public Rule::IRule {
public:
YYCRule5();
virtual ~YYCRule5();
YYCC_DELETE_COPY_MOVE(YYCRule5)
public:
std::u8string_view GetRuleName() const override;
void Check(Reporter::Reporter& reporter, Map::Level& level) const override;
};
/**
* @brief YYC12345 Rule 6
* @details
* Show info hint for the skip of progressbar when loading map.
*/
class YYCRule6 : public Rule::IRule {
public:
YYCRule6();
virtual ~YYCRule6();
YYCC_DELETE_COPY_MOVE(YYCRule6)
public:
std::u8string_view GetRuleName() const override;
void Check(Reporter::Reporter& reporter, Map::Level& level) const override;
};
}

View File

@@ -34,7 +34,7 @@ namespace BMapInspector::Ruleset {
public:
ZZQRule2();
virtual ~ZZQRule2();
YYCC_DEFAULT_COPY_MOVE(ZZQRule2)
YYCC_DELETE_COPY_MOVE(ZZQRule2)
public:
std::u8string_view GetRuleName() const override;

View File

@@ -50,8 +50,12 @@ It would be okey for you to use any Antlr you like.
### Passing Dependencies
When executing Java code relying on these dependencies,
you can use `-cp` option of Java runtime to pass the directory where you can find those dependency's JAR files.
When compiling or executing Java code relying on these dependencies,
you can use `-cp` option to pass these dependency's JAR files.
All dependencies should be specified in one `-cp` option with `;` as separator.
For example, when compiling, you can pass `-cp "<path-to-antlr4-jar>;<path-to-gson-jar>"` as option.
Or pass `-cp ".;<path-to-antlr4-jar>;<path-to-gson-jar>"` when executing.
## Python

View File

@@ -34,3 +34,8 @@ add_custom_target (LibCmoDocuments
install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
DESTINATION ${NEMO_INSTALL_DOC_PATH}
)
# Install UNVIRT.md documentation
install(FILES ${CMAKE_CURRENT_LIST_DIR}/UNVIRT.md
DESTINATION ${NEMO_INSTALL_DOC_PATH}
)

View File

@@ -538,6 +538,121 @@ namespace LibCmo::VxMath {
#pragma endregion
#pragma region VxImageDescEx
VxImageDescEx::VxImageDescEx() : m_Width(0), m_Height(0), m_Image(nullptr) {}
VxImageDescEx::VxImageDescEx(CKDWORD width, CKDWORD height) : m_Width(width), m_Height(height), m_Image(nullptr) {
CreateImage(width, height);
}
YYCC_IMPL_COPY_CTOR(VxImageDescEx, rhs) : m_Width(rhs.m_Width), m_Height(rhs.m_Height), m_Image(nullptr) {
// copy image
if (rhs.m_Image != nullptr) {
CreateImage(rhs.m_Width, rhs.m_Height, rhs.m_Image);
}
}
YYCC_IMPL_COPY_OPER(VxImageDescEx, rhs) {
FreeImage();
m_Width = rhs.m_Width;
m_Height = rhs.m_Height;
if (rhs.m_Image != nullptr) {
CreateImage(rhs.m_Width, rhs.m_Height, rhs.m_Image);
}
return *this;
}
YYCC_IMPL_MOVE_CTOR(VxImageDescEx, rhs) : m_Width(rhs.m_Width), m_Height(rhs.m_Height), m_Image(rhs.m_Image) {
// move image
rhs.m_Height = 0;
rhs.m_Width = 0;
rhs.m_Image = nullptr;
}
YYCC_IMPL_MOVE_OPER(VxImageDescEx, rhs) {
FreeImage();
m_Height = rhs.m_Height;
m_Width = rhs.m_Width;
m_Image = rhs.m_Image;
rhs.m_Height = 0;
rhs.m_Width = 0;
rhs.m_Image = nullptr;
return *this;
}
VxImageDescEx::~VxImageDescEx() {
FreeImage();
}
void VxImageDescEx::CreateImage(CKDWORD Width, CKDWORD Height) {
FreeImage();
m_Width = Width;
m_Height = Height;
m_Image = new CKBYTE[GetImageSize()];
}
void VxImageDescEx::CreateImage(CKDWORD Width, CKDWORD Height, const void* dataptr) {
CreateImage(Width, Height);
std::memcpy(m_Image, dataptr, GetImageSize());
}
void VxImageDescEx::FreeImage() {
m_Width = 0;
m_Height = 0;
if (m_Image != nullptr) {
delete[] m_Image;
m_Image = nullptr;
}
}
CKDWORD VxImageDescEx::GetImageSize() const {
return static_cast<CKDWORD>(PIXEL_SIZE * m_Width * m_Height);
}
const CKBYTE* VxImageDescEx::GetImage() const { return m_Image; }
CKBYTE* VxImageDescEx::GetMutableImage() { return m_Image; }
CKDWORD VxImageDescEx::GetPixelCount() const {
return static_cast<CKDWORD>(m_Width * m_Height);
}
const CKDWORD* VxImageDescEx::GetPixels() const {
return reinterpret_cast<CKDWORD*>(m_Image);
}
CKDWORD* VxImageDescEx::GetMutablePixels() {
return reinterpret_cast<CKDWORD*>(m_Image);
}
CKDWORD VxImageDescEx::GetWidth() const { return m_Width; }
CKDWORD VxImageDescEx::GetHeight() const { return m_Height; }
bool VxImageDescEx::IsValid() const {
return (m_Width != 0u && m_Height != 0u && m_Image != nullptr);
}
bool VxImageDescEx::IsHWEqual(const VxImageDescEx& rhs) const {
return (m_Width == rhs.m_Width && m_Height == rhs.m_Height);
}
// bool VxImageDescEx::IsMaskEqual(const VxImageDescEx& rhs) const {
// return (
// m_RedMask == rhs.m_RedMask &&
// m_GreenMask == rhs.m_GreenMask &&
// m_BlueMask == rhs.m_BlueMask &&
// m_AlphaMask == rhs.m_AlphaMask
// );
// }
#pragma endregion
#pragma region Patched
namespace NSVxVector {

View File

@@ -341,53 +341,20 @@ namespace LibCmo::VxMath {
public:
static constexpr CKDWORD FACTOR_SIZE = 1u; /**< Single color factor (one of ARGB) occpied size in byte. */
static constexpr CKDWORD PIXEL_SIZE = FACTOR_SIZE * 4u; /**< Single pixel occpied size in byte. */
public:
/**
* @brief Create a blank (invalid) image.
*/
VxImageDescEx() : m_Width(0), m_Height(0), m_Image(nullptr) {}
VxImageDescEx();
/**
* @brief Create a image with given width and height.
* @param[in] width The width of image.
* @param[in] height The height of image.
*/
VxImageDescEx(CKDWORD width, CKDWORD height) : m_Width(width), m_Height(height), m_Image(nullptr) { CreateImage(width, height); }
VxImageDescEx(const VxImageDescEx& rhs) : m_Width(rhs.m_Width), m_Height(rhs.m_Height), m_Image(nullptr) {
// copy image
if (rhs.m_Image != nullptr) {
CreateImage(rhs.m_Width, rhs.m_Height, rhs.m_Image);
}
}
VxImageDescEx(VxImageDescEx&& rhs) noexcept : m_Width(rhs.m_Width), m_Height(rhs.m_Height), m_Image(rhs.m_Image) {
// move image
rhs.m_Height = 0;
rhs.m_Width = 0;
rhs.m_Image = nullptr;
}
VxImageDescEx& operator=(const VxImageDescEx& rhs) {
FreeImage();
m_Width = rhs.m_Width;
m_Height = rhs.m_Height;
if (rhs.m_Image != nullptr) {
CreateImage(rhs.m_Width, rhs.m_Height, rhs.m_Image);
}
return *this;
}
VxImageDescEx& operator=(VxImageDescEx&& rhs) noexcept {
FreeImage();
m_Height = rhs.m_Height;
m_Width = rhs.m_Width;
m_Image = rhs.m_Image;
rhs.m_Height = 0;
rhs.m_Width = 0;
rhs.m_Image = nullptr;
return *this;
}
~VxImageDescEx() { FreeImage(); }
VxImageDescEx(CKDWORD width, CKDWORD height);
~VxImageDescEx();
YYCC_DECL_COPY_MOVE(VxImageDescEx)
/**
* @brief Create image with given width and height
@@ -397,12 +364,7 @@ namespace LibCmo::VxMath {
* \li There is no initialization (fill with zero) for this new created image.
* \li Old image will be free first before creating.
*/
void CreateImage(CKDWORD Width, CKDWORD Height) {
FreeImage();
m_Width = Width;
m_Height = Height;
m_Image = new CKBYTE[GetImageSize()];
}
void CreateImage(CKDWORD Width, CKDWORD Height);
/**
* @brief Create image with given width, height and data.
* @param[in] Width The width of image.
@@ -413,86 +375,69 @@ namespace LibCmo::VxMath {
* an undefined behavior is raised.
* @remarks Old image will be free first before creating.
*/
void CreateImage(CKDWORD Width, CKDWORD Height, const void* dataptr) {
CreateImage(Width, Height);
std::memcpy(m_Image, dataptr, GetImageSize());
}
void CreateImage(CKDWORD Width, CKDWORD Height, const void* dataptr);
/**
* @brief Free current image. Reset this to invalid status.
*/
void FreeImage() {
m_Width = 0;
m_Height = 0;
if (m_Image != nullptr) {
delete[] m_Image;
m_Image = nullptr;
}
}
void FreeImage();
/**
* @brief Get the allocated memory size of image.
* @return The allocated memory size of image.
* Basically it is image width * height * (single pixel size).
*/
CKDWORD GetImageSize() const { return static_cast<CKDWORD>(PIXEL_SIZE * m_Width * m_Height); }
CKDWORD GetImageSize() const;
/**
* @brief Get a constant pointer to image in memory unit for viewing.
* @return A constant pointer to image in memory unit.
*/
const CKBYTE* GetImage() const { return m_Image; }
const CKBYTE* GetImage() const;
/**
* @brief Get a mutable pointer to image in memory unit for modifying.
* @return A mutable pointer to image in memory uint.
*/
CKBYTE* GetMutableImage() { return m_Image; }
CKBYTE* GetMutableImage();
/**
* @brief Get the full count of pixel in image.
* @return The count of image. Basically it is image width * height.
*/
CKDWORD GetPixelCount() const { return static_cast<CKDWORD>(m_Width * m_Height); }
CKDWORD GetPixelCount() const;
/**
* @brief Get a constant pointer to image in pixel unit for viewing.
* @return A constant pointer to image in pixel unit.
*/
const CKDWORD* GetPixels() const { return reinterpret_cast<CKDWORD*>(m_Image); }
const CKDWORD* GetPixels() const;
/**
* @brief Get a mutable pointer to image in pixel uint for modifying.
* @return A mutable pointer to image in pixel uint.
*/
CKDWORD* GetMutablePixels() { return reinterpret_cast<CKDWORD*>(m_Image); }
CKDWORD* GetMutablePixels();
/**
* @brief Get the width of this image in pixel.
* @return The width of this image in pixel.
*/
CKDWORD GetWidth() const { return m_Width; }
CKDWORD GetWidth() const;
/**
* @brief Get the height of this image in pixel.
* @return The height of this image in pixel.
*/
CKDWORD GetHeight() const { return m_Height; }
CKDWORD GetHeight() const;
/**
* @brief Check whether this image is valid image for using.
* @details If one of width and height is zero, or underlying image pointer, this image is invalid.
* @return True if it is, otherwise false.
*/
bool IsValid() const { return (m_Width != 0u && m_Height != 0u && m_Image != nullptr); }
bool IsValid() const;
/**
* @brief Check whether the width and height of this image are equal to another image.
* @param[in] rhs Another image for comparing.
* @return True if their width and height are equal, otherwise false.
*/
bool IsHWEqual(const VxImageDescEx& rhs) const { return (m_Width == rhs.m_Width && m_Height == rhs.m_Height); }
// bool IsMaskEqual(const VxImageDescEx& rhs) const {
// return (
// m_RedMask == rhs.m_RedMask &&
// m_GreenMask == rhs.m_GreenMask &&
// m_BlueMask == rhs.m_BlueMask &&
// m_AlphaMask == rhs.m_AlphaMask
// );
// }
bool IsHWEqual(const VxImageDescEx& rhs) const;
// bool IsMaskEqual(const VxImageDescEx& rhs) const;
//public:
// CKDWORD m_RedMask;