Merge pull request #168 from encounter/dtk-fixes

Update to latest dtk-template & fix some stuff
This commit is contained in:
shibboleet 2024-10-14 13:20:40 -04:00 committed by GitHub
commit 04cdf295d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 675 additions and 296 deletions

38
.gitignore vendored
View File

@ -1,13 +1,35 @@
# IDE folders
.idea/
.vs/
# Caches
__pycache__
.idea
.vscode
.ninja_*
.mypy_cache
*.exe
build
build.ninja
objdiff.json
.cache/
# Original files
orig/*/*
!orig/*/.gitkeep
*.dol
*.rel
*.elf
*.o
*.map
*.MAP
# Build files
build/
.ninja_*
build.ninja
# decompctx output
ctx.*
*.ctx
# Generated configs
objdiff.json
compile_commands.json
# Miscellaneous
/*.txt
ctx.c
*.exe

12
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"recommendations": [
"llvm-vs-code-extensions.vscode-clangd",
"ms-python.black-formatter",
"ms-python.flake8",
],
"unwantedRecommendations": [
"ms-vscode.cmake-tools",
"ms-vscode.cpptools-extension-pack",
"ms-vscode.cpptools",
]
}

23
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,23 @@
{
"[c]": {
"files.encoding": "utf8",
"editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd"
},
"[cpp]": {
"files.encoding": "utf8",
"editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd"
},
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
"editor.tabSize": 4,
"files.autoSave": "onFocusChange",
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"files.associations": {
"*.inc": "c",
".clangd": "yaml"
},
// Disable C/C++ IntelliSense, use clangd instead
"C_Cpp.intelliSenseEngine": "disabled",
}

16
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
// Use Ctrl+Shift+B to run build tasks.
// Or "Run Build Task" in the Command Palette.
"version": "2.0.0",
"tasks": [
{
"label": "ninja",
"type": "shell",
"command": "ninja",
"group": {
"kind": "build",
"isDefault": true
}
},
]
}

View File

@ -113,6 +113,12 @@ parser.add_argument(
action="store_true",
help="builds equivalent (but non-matching) or modded objects",
)
parser.add_argument(
"--no-progress",
dest="progress",
action="store_false",
help="disable progress calculation",
)
args = parser.parse_args()
config = ProjectConfig()
@ -129,6 +135,7 @@ config.generate_map = args.map
config.non_matching = args.non_matching
config.shift_jis = False
config.sjiswrap_path = args.sjiswrap
config.progress = args.progress
if not is_windows():
config.wrapper = args.wrapper
# Don't build asm unless we're --non-matching
@ -138,8 +145,8 @@ if not config.non_matching:
# Tool versions
config.binutils_tag = "2.42-1"
config.compilers_tag = "20240706"
config.dtk_tag = "v0.9.5"
config.objdiff_tag = "v2.0.0"
config.dtk_tag = "v1.1.2"
config.objdiff_tag = "v2.3.2"
config.sjiswrap_tag = "v1.1.1"
config.wibo_tag = "0.6.11"

View File

@ -1,6 +1,7 @@
#pragma once
#include "Game/AreaObj/AreaObj.hpp"
#include "Game/LiveActor/LiveActor.hpp"
class MercatorTransformCube : public AreaObj {
public:
@ -23,4 +24,4 @@ namespace MR {
void convertMercatorPlaneToSphereTransAndRotate(TVec3f *, TPos3f *, const TVec3f &, bool);
MapPartsRailMover* createMapPartsRailMoverForMercator(LiveActor *, const JMapInfoIter &, bool);
};
};

View File

@ -305,7 +305,7 @@ namespace MR {
}
inline void multAndSet(TVec3f *a1, const TVec3f &a2, f32 a3) {
a1->set<f32>(a2 * a3);
a1->set(a2 * a3);
}
inline int getRemainder(int ra, int rb) {

View File

@ -125,15 +125,15 @@ namespace JGeometry {
void identity33();
void getXDir(TVec3f &rDest) const NO_INLINE {
rDest.set<f32>(mMtx[0][0], mMtx[1][0], mMtx[2][0]);
rDest.set(mMtx[0][0], mMtx[1][0], mMtx[2][0]);
};
void getYDir(TVec3f &rDest) const NO_INLINE {
rDest.set<f32>(mMtx[0][1], mMtx[1][1], mMtx[2][1]);
rDest.set(mMtx[0][1], mMtx[1][1], mMtx[2][1]);
};
void getZDir(TVec3f &rDest) const NO_INLINE {
rDest.set<f32>(mMtx[0][2], mMtx[1][2], mMtx[2][2]);
rDest.set(mMtx[0][2], mMtx[1][2], mMtx[2][2]);
};
void getXYZDir(TVec3f &rDestX, TVec3f &rDestY, TVec3f &rDestZ) const;

View File

@ -10,18 +10,17 @@ namespace JGeometry {
inline TQuat4() {}
inline TQuat4(T xyz, T _w) {
x = xyz;
y = xyz;
z = xyz;
w = _w;
this->x = xyz;
this->y = xyz;
this->z = xyz;
this->w = _w;
}
template<typename T>
TQuat4(T _x, T _y, T _z, T _w) {
x = _x;
y = _y;
z = _z;
w = _w;
this->x = _x;
this->y = _y;
this->z = _z;
this->w = _w;
}
void set(T, T, T, T);

View File

@ -17,7 +17,6 @@ namespace JGeometry {
/* Constructors */
inline TVec2() {}
template <typename T>
TVec2(T _x, T _y)
{
x = _x;
@ -31,10 +30,8 @@ namespace JGeometry {
}*/
/* General operations */
template <typename T>
void set(const JGeometry::TVec2<T> &rSrc);
template <typename T>
void set(T _x, T _y);
void setMin(const TVec2<T> &);
@ -92,7 +89,6 @@ namespace JGeometry {
z = _z;
}
template<typename T>
TVec3(T _x, T _y , T _z) {
x = _x;
y = _y;
@ -111,18 +107,19 @@ namespace JGeometry {
register f32 z;
register f32 xy;
#if __MWERKS__
__asm {
psq_l xy, 0(src), 0, 0
lfs z, 8(src)
psq_st xy, 0(dst), 0, 0
stfs z, 8(dst)
};
#endif
}
/* General operations */
void set(const Vec &rSrc);
template <typename T>
void set(const JGeometry::TVec3<T> &rSrc) NO_INLINE
{
x = rSrc.x;
@ -130,7 +127,6 @@ namespace JGeometry {
z = rSrc.z;
}
template <typename T>
void set(T _x, T _y, T _z);
void setZYX(T val)
@ -140,12 +136,12 @@ namespace JGeometry {
x = val;
}
template <typename T>
void setAll(T val);
void add(const register TVec3<T> &rSrc) NO_INLINE
{
register const JGeometry::TVec3<f32> *this_vec = this;
#if __MWERKS__
__asm {
psq_l f3, 0(this_vec), 0, 0
psq_l f2, 0(rSrc), 0, 0
@ -156,6 +152,7 @@ namespace JGeometry {
psq_st f2, 0(this_vec), 0, 0
psq_st f0, 8(this_vec), 0, 0
};
#endif
}
void addXY(const register TVec3<T> &rSrc) NO_INLINE
@ -187,7 +184,7 @@ namespace JGeometry {
T squared() const NO_INLINE
{
register const JGeometry::TVec3<f32> *this_vec = this;
#if __MWERKS__
__asm {
psq_l f2, 0(this_vec), 0, 0
lfs f0, 8(this_vec)
@ -196,6 +193,7 @@ namespace JGeometry {
ps_sum0 f1, f1, f2, f2
blr
};
#endif
}
inline void scaleAdd(f32 val, const TVec3<f32> &a1, const TVec3<f32> &a2) {
@ -210,7 +208,7 @@ namespace JGeometry {
{
register const JGeometry::TVec3<f32> *this_vec = this;
register f32 _xy, _z;
#if __MWERKS__
__asm {
psq_l _xy, 0(this_vec), 0, 0
lfs _z, 8(this_vec)
@ -218,6 +216,7 @@ namespace JGeometry {
ps_madd _z, _z, _z, _xy
ps_sum0 _z, _z, _xy, _xy
};
#endif
return _z;
}
@ -236,6 +235,7 @@ namespace JGeometry {
T dot(const register TVec3<T> &rOther) const NO_INLINE
{
register const JGeometry::TVec3<f32> *this_vec = this;
#if __MWERKS__
__asm {
psq_l f2, 4(this_vec), 0, 0
psq_l f1, 4(rOther), 0, 0
@ -246,6 +246,7 @@ namespace JGeometry {
ps_sum0 f1, f1, f2, f2
blr
};
#endif
}
void zero();
@ -253,7 +254,7 @@ namespace JGeometry {
void negate()
{
register const JGeometry::TVec3<f32> *this_vec = this;
#if __MWERKS__
__asm {
psq_l f1, 0(this_vec), 0, 0
lfs f0, 8(this_vec)
@ -262,6 +263,7 @@ namespace JGeometry {
psq_st f1, 0(this_vec), 0, 0
stfs f0, 8(this_vec)
};
#endif
}
void negate(const TVec3<T> &rSrc);
@ -348,6 +350,7 @@ namespace JGeometry {
const TVec3<T> operator-() const NO_INLINE
{
register f32 z, xy;
#if __MWERKS__
__asm {
psq_l xy, 0(r4), 0, 0
lfs z, 8(r4)
@ -357,6 +360,7 @@ namespace JGeometry {
stfs z, 8(r3)
blr
};
#endif
}
TVec3<T> operator%(T scalar) const
@ -408,13 +412,14 @@ namespace JGeometry {
register TVec3<T> *dst = this;
register f32 xy;
register f32 z;
#if __MWERKS__
__asm {
psq_l xy, 0(src), 0, 0
lfs z, 8(src)
psq_st xy, 0(dst), 0, 0
stfs z, 8(dst)
};
#endif
}
inline void setInlinePS_2(register const TVec3<T> &src)
@ -422,26 +427,27 @@ namespace JGeometry {
register TVec3<T> *dst = this;
register f32 z;
register f32 xy;
#if __MWERKS__
__asm {
psq_l xy, 0(src), 0, 0
lfs z, 8(src)
psq_st xy, 0(dst), 0, 0
stfs z, 8(dst)
};
#endif
}
inline void setInlineXYPS(register const TVec3<T> &src)
{
register TVec3<T> *dst = this;
register f32 xy, scalar, _z;
#if __MWERKS__
__asm {
psq_l xy, 0(src), 0, 0
lfs _z, 8(src)
psq_st xy, 0(dst), 0, 0
};
#endif
scalar = 500.0f;
f32 __z = _z;
@ -461,13 +467,14 @@ namespace JGeometry {
register const Vec *src = &gZeroVec;
register f32 z;
register f32 xy;
#if __MWERKS__
__asm {
psq_l xy, 0(src), 0, 0
lfs z, 8(src)
psq_st xy, 0(dst), 0, 0
stfs z, 8(dst)
};
#endif
}
inline void scaleInline(T scale)
@ -481,7 +488,7 @@ namespace JGeometry {
{
register TVec3<T> *dst = this;
register f32 aXY, bXY, aZ, bZ;
#if __MWERKS__
__asm {
psq_l aXY, 0(dst), 0, 0
psq_l bXY, 0(rOther), 0, 0
@ -492,6 +499,7 @@ namespace JGeometry {
psq_st bXY, 0(dst), 0, 0
psq_st bZ, 8(dst), 1, 0
};
#endif
}
inline void addInline2(register const TVec3<T> &rOther)
@ -516,7 +524,7 @@ namespace JGeometry {
register TVec3<T> *dst = this;
// register f32 _2, _1, _0;
register f32 dstXY, dstZ, srcXY, srcZ, totalZ;
#if __MWERKS__
__asm {
psq_l dstXY, 0(dst), 0, 0
psq_l srcXY, 0(rOther), 0, 0
@ -527,13 +535,14 @@ namespace JGeometry {
psq_st dstXY, 0(dst), 0, 0
psq_st totalZ, 8(dst), 1, 0
};
#endif
}
inline void addInline_4(register const TVec3<T> &rOther)
{
register TVec3<T> *dst = this;
register f32 bZ, bXY, aZ, aXY;
#if __MWERKS__
__asm {
psq_l bXY, 0(rOther), 0, 0
psq_l bZ, 0(rOther), 1, 0
@ -544,13 +553,14 @@ namespace JGeometry {
psq_st aXY, 0(dst), 0, 0
psq_st aZ, 8(dst), 1, 0
};
#endif
}
inline void addInline_5(register const TVec3<T> &rOther)
{
register TVec3<T> *dst = this;
register f32 bZ, bXY, aZ, aXY;
#if __MWERKS__
__asm {
psq_l bXY, 0(rOther), 0, 0
psq_l aXY, 0(dst), 0, 0
@ -561,6 +571,7 @@ namespace JGeometry {
psq_st bXY, 0(dst), 0, 0
psq_st aXY, 8(dst), 1, 0
};
#endif
}
inline void addInline6(register const TVec3<T> &rOther)
@ -587,7 +598,7 @@ namespace JGeometry {
{
register TVec3<T> *dst = this;
register f32 sumZ, bZ, aZ, bXY, aXY;
#if __MWERKS__
__asm {
psq_l bXY, 0(rOther), 0, 0
psq_l aXY, 0(dst), 0, 0
@ -598,6 +609,7 @@ namespace JGeometry {
psq_st aXY, 0(dst), 0, 0
psq_st sumZ, 8(dst), 1, 0
};
#endif
}
inline TVec3<T> _madd(const TVec3<T> &v) const {
@ -617,7 +629,7 @@ namespace JGeometry {
register const TVec3<T> *b = &rB;
register f32 aXY, bZ, aZ, bXY;
z = rA.z;
#if __MWERKS__
__asm {
psq_l aXY, 0(a), 0, 0
psq_l bXY, 0(b), 0, 0
@ -628,6 +640,7 @@ namespace JGeometry {
psq_st bXY, 0(dst), 0, 0
psq_st aZ, 8(dst), 1, 0
};
#endif
}
inline void subInline2(const TVec3<T> &rA, const TVec3<T> &rB)
@ -636,7 +649,7 @@ namespace JGeometry {
register const TVec3<T> *a = &rA;
register const TVec3<T> *b = &rB;
register f32 bXY, aXY, bZ, aZ;
#if __MWERKS__
__asm {
psq_l aXY, 0(a), 0, 0
psq_l bXY, 0(b), 0, 0
@ -647,6 +660,7 @@ namespace JGeometry {
ps_sub aZ, aZ, bZ
psq_st aZ, 8(dst), 1, 0
};
#endif
}
inline void subInline3(const TVec3<T> &rA, const TVec3<T> &rB)
@ -655,7 +669,7 @@ namespace JGeometry {
register const TVec3<T> *a = &rA;
register const TVec3<T> *b = &rB;
register f32 bZ, bXY, aXY, aZ;
#if __MWERKS__
__asm {
psq_l aXY, 0(a), 0, 0
psq_l bXY, 0(b), 0, 0
@ -666,6 +680,7 @@ namespace JGeometry {
ps_sub aZ, aZ, bZ
psq_st aZ, 8(dst), 1, 0
};
#endif
}
inline void subInline(const TVec3<T> &rA)
@ -673,7 +688,7 @@ namespace JGeometry {
register TVec3<T> *this_vec = this;
register const TVec3<T> *a = &rA;
register f32 bZ, aZ, aXY, bXY;
#if __MWERKS__
__asm {
psq_l aXY, 0(a), 0, 0
psq_l bXY, 0(this_vec), 0, 0
@ -684,6 +699,7 @@ namespace JGeometry {
ps_sub aZ, bZ, aZ
psq_st aZ, 8(this_vec), 1, 0
};
#endif
}
inline void subInline4(register const TVec3<T> &rVec)
@ -691,6 +707,7 @@ namespace JGeometry {
register const TVec3<T> *this_vec = this;
//register const TVec3<T> *a = &rVec;
register f32 z_2, z_1, xy_2, xy_1, z_ret, xy_ret;
#if __MWERKS__
__asm {
psq_l xy_2, 0(rVec), 0, 0
psq_l xy_1, 0(this_vec), 0, 0
@ -701,6 +718,7 @@ namespace JGeometry {
psq_st xy_ret, 0(this_vec), 0, 0
psq_st z_ret, 8(this_vec), 1, 0
};
#endif
}
inline const TVec3<T> negateInline() const
@ -709,7 +727,7 @@ namespace JGeometry {
register const TVec3<T> *src = this;
register TVec3<T> *dest = &ret;
register f32 xy, z;
#if __MWERKS__
__asm {
psq_l xy, 0(src), 0, 0
ps_neg xy, xy
@ -718,7 +736,7 @@ namespace JGeometry {
fneg z, z
stfs z, 8(dest)
};
#endif
return ret;
}
@ -728,7 +746,7 @@ namespace JGeometry {
register const TVec3<T> *src = this;
register TVec3<T> *dest = &ret;
register f32 xy, z;
#if __MWERKS__
__asm {
psq_l xy, 0(src), 0, 0
ps_neg xy, xy
@ -737,8 +755,8 @@ namespace JGeometry {
fneg z, z
stfs z, 8(dest)
};
TVec3f trueRet = TVec3f(ret);
#endif
TVec3<f32> trueRet = TVec3f(ret);
trueRet.scale(scalar);
return trueRet;
}
@ -748,7 +766,7 @@ namespace JGeometry {
register TVec3<T> *dst = this;
register f32 xy;
register f32 z;
#if __MWERKS__
__asm {
psq_l xy, 0(rSrc), 0, 0
lfs z, 8(rSrc)
@ -757,6 +775,7 @@ namespace JGeometry {
psq_st xy, 0(dst), 0, 0
stfs z, 8(dst)
};
#endif
}
inline void negateInline_2(register const TVec3<T> &rSrc)
@ -764,7 +783,7 @@ namespace JGeometry {
register TVec3<T> *dst = this;
register f32 xy;
register f32 z;
#if __MWERKS__
__asm {
psq_l xy, 0(rSrc), 0, 0
ps_neg xy, xy
@ -773,6 +792,7 @@ namespace JGeometry {
fneg z, z
stfs z, 8(dst)
};
#endif
}
inline TVec3<T> negateInline_2() const
@ -787,7 +807,7 @@ namespace JGeometry {
register TVec3<T> *dst = this;
register f32 xy;
register f32 z_neg, x, y, z, z_single;
#if __MWERKS__
__asm {
psq_l xy, 0(rSrc), 0, 0
lfs z, 8(rSrc)
@ -803,6 +823,7 @@ namespace JGeometry {
stfs y, 4(rDest)
stfs z_single, 8(rDest)
};
#endif
}
inline void negateSelf()
@ -811,7 +832,7 @@ namespace JGeometry {
register TVec3<T> *dst = this;
register f32 xy;
register f32 z;
#if __MWERKS__
__asm {
psq_l xy, 0(src), 0, 0
ps_neg xy, xy
@ -820,6 +841,7 @@ namespace JGeometry {
fneg z, z
stfs z, 8(dst)
};
#endif
}
inline void setNegatedInline(register const TVec3<T> &rSrc)
@ -827,7 +849,7 @@ namespace JGeometry {
register TVec3<T> *rDst = this;
register f32 xy;
register f32 z;
#if __MWERKS__
__asm {
psq_l xy, 0(rSrc), 0, 0
ps_neg xy, xy
@ -836,6 +858,7 @@ namespace JGeometry {
fneg z, z
stfs z, 8(rDst)
};
#endif
}
inline void multAndSet(TVec3<T> *pDest, T scalar)
@ -851,7 +874,7 @@ namespace JGeometry {
register TVec3<T> *rDst = this;
register f32 xy_1, xy_2;
register f32 z_1, z_2;
#if __MWERKS__
__asm {
psq_l xy_1, 0(rVec1), 0, 0
psq_l xy_2, 0(rVec2), 0, 0
@ -862,6 +885,7 @@ namespace JGeometry {
fmuls z_2, z_1, z_2
stfs z_2, 8(rDst)
};
#endif
}
inline f32 squareDistancePS(const register TVec3<T> &rVec1) const
@ -870,6 +894,7 @@ namespace JGeometry {
register f32 yz_1, x_1;
register f32 yz_2, x_2;
register f32 ret;
#if __MWERKS__
__asm {
psq_l yz_1, 4(this_vec), 0, 0
psq_l yz_2, 4(rVec1), 0, 0
@ -881,6 +906,7 @@ namespace JGeometry {
ps_madd ret, x_2, x_2, yz_2
ps_sum0 ret, ret, yz_2, yz_2
};
#endif
return ret;
}
@ -900,7 +926,6 @@ namespace JGeometry {
/* Constructors */
inline TVec4() {}
template <typename T>
TVec4(T _x, T _y, T _z, T _h)
{
x = _x;
@ -910,10 +935,8 @@ namespace JGeometry {
}
/* General operations */
template <typename T>
void set(const JGeometry::TVec4<T> &);
template <typename T>
void set(T _x, T _y, T _z, T _h)
{
x = _x;

View File

@ -2,4 +2,6 @@
#ifdef __MWERKS__
typedef unsigned long size_t;
#endif
#else
typedef unsigned int size_t;
#endif

View File

@ -69,7 +69,7 @@ void AreaFormCube::calcWorldPos(TVec3f *pPos) const {
return;
}
pPos->set<f32>(mTranslation);
pPos->set(mTranslation);
}
// AreaFormCube::calcWorldRotate
@ -127,8 +127,8 @@ void AreaFormCube::updateBoxParam() {
TVec3f v9(v20, v21, v22);
_30.set<f32>(v10);
_3C.set<f32>(v9);
_30.set(v10);
_3C.set(v9);
if (_8 == 1) {
TVec3f temp;
@ -181,7 +181,7 @@ void AreaFormSphere::calcUpVec(TVec3f *pOut) const {
MR::normalize(pOut);
}
else {
pOut->set<f32>(mUp);
pOut->set(mUp);
}
}
@ -190,7 +190,7 @@ void AreaFormSphere::calcPos(TVec3f *pOut) const {
_4->mult(mTranslation, *pOut);
}
else {
pOut->set<f32>(mTranslation);
pOut->set(mTranslation);
}
}
@ -264,7 +264,7 @@ void AreaFormCylinder::calcPos(TVec3f *pPos) const {
return;
}
pPos->set<f32>(mTranslation);
pPos->set(mTranslation);
}
void AreaFormCylinder::calcCenterPos(TVec3f *pCenterPos) const {
@ -281,7 +281,7 @@ void AreaFormCylinder::calcUpVec(TVec3f *pUpVec) const {
MR::normalize(pUpVec);
}
else {
pUpVec->set<f32>(mRotation);
pUpVec->set(mRotation);
}
}
@ -360,4 +360,4 @@ void AreaFormCylinder::init(const JMapInfoIter &rIter) {
rIter.getValue<f32>("scale_y", &temp);
_24 = temp;
_24 *= 500.0f;
}
}

View File

@ -1,4 +1,5 @@
#include "Game/AreaObj/AreaObj.hpp"
#include "Game/AreaObj/AreaForm.hpp"
#include "Game/AreaObj/AreaObjFollower.hpp"
#include "Game/Map/SleepControllerHolder.hpp"
#include "Game/Util.hpp"

View File

@ -2,6 +2,7 @@
#include "Game/Util/CameraUtil.hpp"
#include "Game/Util/JMapUtil.hpp"
#include "Game/Util/DirectDraw.hpp"
#include "Game/Util/ObjUtil.hpp"
BigBubbleGoalArea::BigBubbleGoalArea(int type, const char *pName) : AreaObj(type, pName) {
mTranslation.x = 0.0f;

View File

@ -1,4 +1,5 @@
#include "Game/AreaObj/CameraRepulsiveArea.hpp"
#include "Game/Util/AreaObjUtil.hpp"
CameraRepulsiveArea::~CameraRepulsiveArea() {
@ -53,4 +54,4 @@ TVec3f CameraRepulsiveCylinder::getRepulsion(const TVec3f &rRep) {
const char* CameraRepulsiveArea::getManagerName() const {
return "CameraRepulsiveArea";
}
}

View File

@ -1,6 +1,7 @@
#include "Game/AreaObj/ChangeBgmCube.hpp"
#include "Game/AudioLib/AudWrap.hpp"
#include "Game/GameAudio/AudStageBgmTable.hpp"
#include "Game/Util/ObjUtil.hpp"
ChangeBgmCube::ChangeBgmCube(int a1, const char *pName) : AreaObj(a1, pName) {
_3C = 0;

View File

@ -1,4 +1,4 @@
#include "Game/AreaObj/CollisionArea.hpp"
#include "Game/AreaObj/CollisionArea.hpp"
#include "Game/MapObj/DynamicCollisionObj.hpp"
#include "Game/Util/JMapUtil.hpp"
#include "Game/Util/LiveActorUtil.hpp"
@ -222,4 +222,4 @@ void CollisionArea::movement() {
}
}
}
}
}

View File

@ -1,4 +1,6 @@
#include "Game/AreaObj/MercatorTransformCube.hpp"
#include "Game/Util/AreaObjUtil.hpp"
#include "Game/Util/SceneUtil.hpp"
#include "JSystem/JMath/JMath.hpp"
MercatorTransformCube::MercatorTransformCube(int type, const char *pName) : AreaObj(type, pName) {

View File

@ -14,14 +14,14 @@ PartsModel::PartsModel(LiveActor *pActor, const char *pName, const char *pModelN
}
if (mMtx) {
mPosition.set<f32>(mMtx[0][3], mMtx[1][3], mMtx[2][3]);
mPosition.set(mMtx[0][3], mMtx[1][3], mMtx[2][3]);
}
else {
mPosition.set<f32>(pActor->mPosition);
mPosition.set(pActor->mPosition);
}
mRotation.set<f32>(pActor->mRotation);
mScale.set<f32>(pActor->mScale);
mRotation.set(pActor->mRotation);
mScale.set(pActor->mScale);
initModelManagerWithAnm(pModelName, nullptr, a6);
@ -132,10 +132,10 @@ void PartsModel::offFixedPosNormalizeScale() {
void PartsModel::calcAndSetBaseMtx() {
if (mMtx && mCalcOwnMtx) {
mPosition.set<f32>(mMtx[0][3], mMtx[1][3], mMtx[2][3]);
mPosition.set(mMtx[0][3], mMtx[1][3], mMtx[2][3]);
MR::setBaseTRMtx(this, mMtx);
}
else {
LiveActor::calcAndSetBaseMtx();
}
}
}

View File

@ -94,7 +94,7 @@ void BezierRailPart::calcVelocity(TVec3f *pOut, f32 a2) const {
v12.scale(v5);
v11.scale(v7);
pOut->set<f32>(_C);
pOut->set(_C);
pOut->add(v11);
pOut->add(v12);
pOut->scale(3.0f);

View File

@ -32,7 +32,7 @@ void RailPart::calcPos(TVec3f *pOut, f32 a2) const {
void RailPart::calcVelocity(TVec3f *pOut, f32 a2) const {
if (mRailPartLinear) {
pOut->set<f32>(mRailPartLinear->_C);
pOut->set(mRailPartLinear->_C);
}
else {
mRailPartBezier->calcVelocity(pOut, a2);
@ -82,4 +82,4 @@ void LinearRailPart::set(const TVec3f &a1, const TVec3f &a2) {
f32 LinearRailPart::getNearestParam(const register TVec3f &a1, f32 a2) const {
}
*/
*/

View File

@ -31,10 +31,10 @@ void BenefitItemInvincible::init(const JMapInfoIter &rIter) {
_13A = 0;
TVec3f axis_z;
MR::getRotatedAxisZ(&axis_z, mRotation);
_148.set<f32>(axis_z);
_148.set(axis_z);
TVec3f axis_y;
MR::getRotatedAxisY(&axis_y, mRotation);
_13C.set<f32>(axis_y);
_13C.set(axis_y);
}
}

View File

@ -238,7 +238,7 @@ void BenefitItemObj::init(const JMapInfoIter &rIter) {
TVec3f rotate_axis_y;
MR::getRotatedAxisY(&rotate_axis_y, mRotation);
_A4.set<f32>(rotate_axis_y);
_A4.set(rotate_axis_y);
if (_DC) {
MR::initShadowVolumeCylinder(this, 50.0f);
@ -336,7 +336,7 @@ void BenefitItemObj::appearThrowUp() {
runBck("Appear");
TVec3f rotated_axis;
MR::getRotatedAxisY(&rotated_axis, mRotation);
_A4.set<f32>(rotated_axis);
_A4.set(rotated_axis);
setNerve(&NrvBenefitItemObj::HostTypeNrvShoot::sInstance);
if (!_DD) {

View File

@ -43,7 +43,7 @@ void Coin::init(const JMapInfoIter &rIter) {
if (_BA) {
TVec3f axis;
MR::calcActorAxisY(&axis, this);
mGravity.set<f32>(-axis);
mGravity.set(-axis);
}
initShadow(rIter);
@ -165,7 +165,7 @@ void Coin::makeActorDead() {
void Coin::calcAndSetBaseMtx() {
TVec3f another_vec;
another_vec.set<f32>(MR::isNearZero(mGravity, 0.001f) ? TVec3f(0.0f, 1.0f, 0.0f) : -mGravity);
another_vec.set(MR::isNearZero(mGravity, 0.001f) ? TVec3f(0.0f, 1.0f, 0.0f) : -mGravity);
JMAVECScaleAdd(another_vec.toCVec(), mPosition.toCVec(), mDropPosition.toVec(), 70.0f);
TPos3f pos;
@ -381,13 +381,13 @@ void Coin::appearFixTimer(s32 a1, s32 a2) {
}
void Coin::appearMove(const TVec3f &a1, const TVec3f &a2, s32 a3, s32 a4) {
mPosition.set<f32>(a1);
mPosition.set(a1);
makeActorAppeared();
MR::invalidateClipping(this);
MR::invalidateHitSensors(this);
MR::onBind(this);
MR::onCalcShadow(this, nullptr);
mVelocity.set<f32>(a2);
mVelocity.set(a2);
TVec3f stack_14;
if (MR::normalizeOrZero(a2, &stack_14)) {
@ -421,7 +421,7 @@ void Coin::appearHop(const TVec3f &a1, const TVec3f &a2) {
MR::invalidateHitSensors(this);
MR::offBind(this);
MR::invalidateShadow(this, nullptr);
mVelocity.set<f32>(a2 * 30.0f);
mVelocity.set(a2 * 30.0f);
mCannotTime = 0;
setNerve(&NrvCoin::CoinNrvHop::sInstance);
}
@ -442,7 +442,7 @@ bool Coin::requestActiveWithGravity() {
MR::validateHitSensors(this);
MR::onBind(this);
MR::calcGravityOrZero(this);
mVelocity.set<f32>(-mGravity * 30.0f);
mVelocity.set(-mGravity * 30.0f);
setNerve(&NrvCoin::CoinNrvMove::sInstance);
return true;
}
@ -738,4 +738,4 @@ namespace NrvCoin {
Coin::~Coin() {
}
}

View File

@ -17,7 +17,7 @@ void CrystalCage::init(const JMapInfoIter &rIter) {
MR::calcGravity(this);
initModel(obj_name);
MR::connectToSceneCrystal(this);
_E8.set<f32>(mPosition);
_E8.set(mPosition);
initHitSensor(1);
MR::addHitSensorPosMapObj(this, "body", 8, (130.0f * mScale.x), &_E8, TVec3f(0.0f, 0.0f, 0.0f));
@ -61,10 +61,10 @@ void CrystalCage::init(const JMapInfoIter &rIter) {
}
else {
if (!mCrystalCageType) {
v23.set<f32>(-30.0f, 100.0f, -30.0f);
v23.set(-30.0f, 100.0f, -30.0f);
}
else {
v23.set<f32>(0.0f, 200.0f, 0.0f);
v23.set(0.0f, 200.0f, 0.0f);
}
mDisplayModel = MR::createDummyDisplayModelCrystalItem(this, rIter, v23, TVec3f(0.0f, 0.0f, 0.0f));
@ -128,7 +128,7 @@ void CrystalCage::initAfterPlacement() {
stack_2C.scale((-(2.0f * val) * mScale.x), up_vec);
if (!MR::getFirstPolyOnLineToMapExceptActor(&_F8, 0, stack_20, stack_2C, this)) {
_F8.set<f32>(mPosition);
_F8.set(mPosition);
}
if (mHasBinding) {
@ -224,7 +224,7 @@ bool CrystalCage::receiveMsgEnemyAttack(u32 msg, HitSensor *, HitSensor *) {
void CrystalCage::initMapToolInfo(const JMapInfoIter &rIter) {
MR::initDefaultPos(this, rIter);
_DC.set<f32>(mPosition);
_DC.set(mPosition);
if (MR::isEqualObjectName(rIter, "CrystalCageS")) {
mCrystalCageType = 0;
@ -268,7 +268,7 @@ void CrystalCage::initModel(const char *pName) {
}
MR::invalidateClipping(this);
mBreakObj->mScale.set<f32>(mScale);
mBreakObj->mScale.set(mScale);
MR::registerDemoSimpleCastAll(mBreakObj);
mBreakObj->makeActorDead();
}
@ -302,7 +302,7 @@ void CrystalCage::exeWait() {
JMathInlineVEC::PSVECAdd(_DC.toCVec(), v9.toCVec(), mPosition.toVec());
}
else {
mPosition.set<f32>(_DC);
mPosition.set(_DC);
}
}
@ -326,7 +326,7 @@ void CrystalCage::exeBreak() {
}
else {
MR::setBvaFrameAndStop(this, mCrystalCageType == 2 ? 2.0f : 1.0f);
mPosition.set<f32>(_F8);
mPosition.set(_F8);
}
if (mHasBinding) {

View File

@ -29,7 +29,7 @@ void CrystalCageMoving::init(const JMapInfoIter &rIter) {
vec.z = 0.0f;
info.setupHitSensorParam(4, 350.0f, vec);
initialize(rIter, info);
_FC.set<f32>(mPosition);
_FC.set(mPosition);
initDummyModel(rIter);
MR::initActorCamera(this, rIter, &mCameraInfo);
MR::startBck(this, "Wait", nullptr);
@ -166,7 +166,7 @@ void CrystalCageMoving::crashMario(HitSensor *a1, HitSensor *a2) {
void CrystalCageMoving::updateHitSensor(HitSensor *pSensor) {
if (!_108) {
pSensor->mPosition.set<f32>(mPosition);
pSensor->mPosition.set(mPosition);
}
else {
f32 radius = pSensor->mRadius;
@ -176,7 +176,7 @@ void CrystalCageMoving::updateHitSensor(HitSensor *pSensor) {
f32 z = joint_mtx.mMtx[2][1];
f32 y = joint_mtx.mMtx[1][1];
f32 x = joint_mtx.mMtx[0][1];
joint_pos.set<f32>(x, y, z);
joint_pos.set(x, y, z);
TVec3f stack_14;
JMAVECScaleAdd(joint_pos.toCVec(), mPosition.toCVec(), stack_14.toVec(), (-450.0f + radius));
TVec3f stack_8;
@ -291,4 +291,4 @@ namespace NrvCrystalCageMoving {
void CrystalCageMovingNrvWaitBig::execute(Spine *) const {
}
};
};

View File

@ -26,10 +26,10 @@ void FloaterFloatingForce::start() {
x = matrix.mMtx[0][1];
y = matrix.mMtx[1][1];
z = matrix.mMtx[2][1];
_28.set<f32>(x, y, z);
_28.set(x, y, z);
MR::normalize(&_28);
}
const TVec3f& FloaterFloatingForce::getCurrentVelocity() const {
return TVec3f(0.0f, 0.0f, 0.0f);
}
}

View File

@ -36,7 +36,7 @@ void Fountain::init(const JMapInfoIter &rIter) {
mtx.mMtx[2][2] = v15 * v14;
mtx.mMtx[1][2] = ((v15 * v16) * v17) - (v19 * v13);
_90.set<f32>(v22, v21, v20);
_90.set(v22, v21, v20);
MR::normalize(&_90);
MR::getObjectName(&mFountainName, rIter);
initEffectKeeper(0, mFountainName, false);
@ -118,4 +118,4 @@ Fountain::~Fountain() {
namespace NrvFountain {
INIT_NERVE(HostTypeWait);
INIT_NERVE(HostTypeMove);
};
};

View File

@ -55,7 +55,7 @@ void ShootingStar::init(const JMapInfoIter &rIter) {
x = matrix.mMtx[0][1];
y = matrix.mMtx[1][1];
z = matrix.mMtx[2][1];
_98.set<f32>(x, y, z);
_98.set(x, y, z);
MR::startBpk(this, "ShootingStar");
}

View File

@ -99,16 +99,16 @@ void WaterPressureBullet::shotWaterBullet(LiveActor *pActor, const TPos3f &rPos,
_B1 = a5;
_B2 = a6;
mCameraInfo = pInfo;
_8C.set<f32>(x, y, z);
_8C.set(x, y, z);
mVelocity.scale(_A8, _8C);
z = rPos.mMtx[2][3];
y = rPos.mMtx[1][3];
x = rPos.mMtx[0][3];
mPosition.set<f32>(x, y, z);
mPosition.set(x, y, z);
z = rPos.mMtx[2][0];
y = rPos.mMtx[1][0];
x = rPos.mMtx[0][0];
_98.set<f32>(x, y, z);
_98.set(x, y, z);
mRotation.zero();
makeActorAppeared();
MR::validateHitSensors(this);
@ -319,4 +319,4 @@ namespace NrvWaterPressureBullet {
WaterPressureBullet* bullet = reinterpret_cast<WaterPressureBullet*>(pSpine->mExecutor);
bullet->exeFly();
}
};
};

View File

@ -38,7 +38,7 @@ NPCActorCaps::NPCActorCaps(const char *pName) {
mMessageOffset.x = 0.0f;
mMessageOffset.y = 150.0f;
mMessageOffset.z = 0.0f;
mSensorOffset.set<f32>(0.0f, 50.0f, 0.0f);
mSensorOffset.set(0.0f, 50.0f, 0.0f);
_10 = pName;
mTalkMtx = 0;
mTalkJointName = 0;
@ -178,7 +178,7 @@ void NPCActor::setInitPose() {
_B0.y = _A0.y;
_B0.z = _A0.z;
_B0.h = _A0.h;
_C0.set<f32>(mPosition);
_C0.set(mPosition);
}
void NPCActor::init(const JMapInfoIter &rIter) {

View File

@ -312,7 +312,7 @@ namespace MR {
TVec3f curSenderPos(pSender->mPosition);
JMathInlineVEC::PSVECSubtract((Vec*)&pReceiver->mPosition, (Vec*)&rDir, (Vec*)&pSender->mPosition);
bool ret = pReceiver->receiveMessage(msg, pSender);
pSender->mPosition.set<f32>(curSenderPos);
pSender->mPosition.set(curSenderPos);
return ret;
}

View File

@ -22,15 +22,15 @@ void FixedPosition::setBaseMtx(MtxPtr mtx) {
}
void FixedPosition::setLocalTrans(const TVec3f &rLocalTrans) {
mLocalTrans.set<f32>(rLocalTrans);
mLocalTrans.set(rLocalTrans);
}
void FixedPosition::init(MtxPtr mtx, const TVec3f &rLocalTrans, const TVec3f &a3) {
mBaseMtx = mtx;
mLocalTrans.set<f32>(rLocalTrans);
_10.set<f32>(a3);
mLocalTrans.set(rLocalTrans);
_10.set(a3);
_1C.identity();
mNormalizeScale = true;
}
//FixedPosition::FixedPosition(const LiveActor *, const char *, const LiveActor *)
//FixedPosition::FixedPosition(const LiveActor *, const char *, const LiveActor *)

View File

@ -24,7 +24,7 @@ namespace MR {
f32 v12 = getRandom();
f32 dist = a3 - a2;
pOut->set<f32>((a2 + (dist * v12)), v11, v10);
pOut->set((a2 + (dist * v12)), v11, v10);
}
u8 isHalfProbability() {
@ -413,4 +413,4 @@ namespace MR {
return 2;
}
};
};

View File

@ -17,7 +17,7 @@ import os
import platform
import sys
from pathlib import Path
from typing import Any, Dict, List, Optional, Set, Tuple, Union, cast
from typing import IO, Any, Dict, Iterable, List, Optional, Set, Tuple, Union, cast
from . import ninja_syntax
from .ninja_syntax import serialize_path
@ -81,6 +81,20 @@ class Object:
set_default("shift_jis", config.shift_jis)
set_default("src_dir", config.src_dir)
# Validate progress categories
def check_category(category: str):
if not any(category == c.id for c in config.progress_categories):
sys.exit(
f"Progress category '{category}' missing from config.progress_categories"
)
progress_category = obj.options["progress_category"]
if isinstance(progress_category, list):
for category in progress_category:
check_category(category)
elif progress_category is not None:
check_category(progress_category)
# Resolve paths
build_dir = config.out_path()
obj.src_path = Path(obj.options["src_dir"]) / obj.options["source"]
@ -155,14 +169,21 @@ class ProjectConfig:
self.custom_build_steps: Optional[Dict[str, List[Dict[str, Any]]]] = (
None # Custom build steps, types are ["pre-compile", "post-compile", "post-link", "post-build"]
)
self.generate_compile_commands: bool = (
True # Generate compile_commands.json for clangd
)
# Progress output, progress.json and report.json config
self.progress = True # Enable progress output
self.progress_all: bool = True # Include combined "all" category
self.progress_modules: bool = True # Include combined "modules" category
self.progress_each_module: bool = (
False # Include individual modules, disable for large numbers of modules
)
self.progress_categories: List[ProgressCategory] = [] # Additional categories
self.print_progress_categories: Union[bool, List[str]] = (
True # Print additional progress categories in the CLI progress output
)
# Progress fancy printing
self.progress_use_fancy: bool = False
@ -199,9 +220,40 @@ class ProjectConfig:
out[obj.name] = obj.resolve(self, lib)
return out
# Gets the output path for build-related files.
def out_path(self) -> Path:
return self.build_dir / str(self.version)
# Gets the path to the compilers directory.
# Exits the program if neither `compilers_path` nor `compilers_tag` is provided.
def compilers(self) -> Path:
if self.compilers_path:
return self.compilers_path
elif self.compilers_tag:
return self.build_dir / "compilers"
else:
sys.exit("ProjectConfig.compilers_tag missing")
# Gets the wrapper to use for compiler commands, if set.
def compiler_wrapper(self) -> Optional[Path]:
wrapper = self.wrapper
if self.use_wibo():
wrapper = self.build_dir / "tools" / "wibo"
if not is_windows() and wrapper is None:
wrapper = Path("wine")
return wrapper
# Determines whether or not to use wibo as the compiler wrapper.
def use_wibo(self) -> bool:
return (
self.wibo_tag is not None
and sys.platform == "linux"
and platform.machine() in ("i386", "x86_64")
and self.wrapper is None
)
def is_windows() -> bool:
return os.name == "nt"
@ -213,13 +265,26 @@ CHAIN = "cmd /c " if is_windows() else ""
EXE = ".exe" if is_windows() else ""
def make_flags_str(flags: Optional[Union[str, List[str]]]) -> str:
def file_is_asm(path: Path) -> bool:
return path.suffix.lower() == ".s"
def file_is_c(path: Path) -> bool:
return path.suffix.lower() == ".c"
def file_is_cpp(path: Path) -> bool:
return path.suffix.lower() in (".cc", ".cp", ".cpp", ".cxx")
def file_is_c_cpp(path: Path) -> bool:
return file_is_c(path) or file_is_cpp(path)
def make_flags_str(flags: Optional[List[str]]) -> str:
if flags is None:
return ""
elif isinstance(flags, list):
return " ".join(flags)
else:
return flags
return " ".join(flags)
# Load decomp-toolkit generated config.json
@ -252,13 +317,14 @@ def load_build_config(
return build_config
# Generate build.ninja and objdiff.json
# Generate build.ninja, objdiff.json and compile_commands.json
def generate_build(config: ProjectConfig) -> None:
config.validate()
objects = config.objects()
build_config = load_build_config(config, config.out_path() / "config.json")
generate_build_ninja(config, objects, build_config)
generate_objdiff_config(config, objects, build_config)
generate_compile_commands(config, objects, build_config)
# Generate build.ninja
@ -405,16 +471,10 @@ def generate_build_ninja(
else:
sys.exit("ProjectConfig.sjiswrap_tag missing")
wrapper = config.compiler_wrapper()
# Only add an implicit dependency on wibo if we download it
wrapper = config.wrapper
wrapper_implicit: Optional[Path] = None
if (
config.wibo_tag is not None
and sys.platform == "linux"
and platform.machine() in ("i386", "x86_64")
and config.wrapper is None
):
wrapper = build_tools_path / "wibo"
if wrapper is not None and config.use_wibo():
wrapper_implicit = wrapper
n.build(
outputs=wrapper,
@ -425,15 +485,11 @@ def generate_build_ninja(
"tag": config.wibo_tag,
},
)
if not is_windows() and wrapper is None:
wrapper = Path("wine")
wrapper_cmd = f"{wrapper} " if wrapper else ""
compilers = config.compilers()
compilers_implicit: Optional[Path] = None
if config.compilers_path:
compilers = config.compilers_path
elif config.compilers_tag:
compilers = config.build_dir / "compilers"
if config.compilers_path is None and config.compilers_tag is not None:
compilers_implicit = compilers
n.build(
outputs=compilers,
@ -444,8 +500,6 @@ def generate_build_ninja(
"tag": config.compilers_tag,
},
)
else:
sys.exit("ProjectConfig.compilers_tag missing")
binutils_implicit = None
if config.binutils_path:
@ -659,7 +713,6 @@ def generate_build_ninja(
n.comment(f"Link {self.name}")
if self.module_id == 0:
elf_path = build_path / f"{self.name}.elf"
dol_path = build_path / f"{self.name}.dol"
elf_ldflags = f"$ldflags -lcf {serialize_path(self.ldscript)}"
if config.generate_map:
elf_map = map_path(elf_path)
@ -724,17 +777,36 @@ def generate_build_ninja(
source_added: Set[Path] = set()
def c_build(obj: Object, src_path: Path) -> Optional[Path]:
cflags_str = make_flags_str(obj.options["cflags"])
if obj.options["extra_cflags"] is not None:
extra_cflags_str = make_flags_str(obj.options["extra_cflags"])
cflags_str += " " + extra_cflags_str
used_compiler_versions.add(obj.options["mw_version"])
# Avoid creating duplicate build rules
if obj.src_obj_path is None or obj.src_obj_path in source_added:
return obj.src_obj_path
source_added.add(obj.src_obj_path)
cflags = obj.options["cflags"]
extra_cflags = obj.options["extra_cflags"]
# Add appropriate language flag if it doesn't exist already
# Added directly to the source so it flows to other generation tasks
if not any(flag.startswith("-lang") for flag in cflags) and (
extra_cflags is None
or not any(flag.startswith("-lang") for flag in extra_cflags)
):
# Ensure extra_cflags is a unique instance,
# and insert into there to avoid modifying shared sets of flags
if extra_cflags is None:
extra_cflags = []
extra_cflags = obj.options["extra_cflags"] = list(extra_cflags)
if file_is_cpp(src_path):
extra_cflags.insert(0, "-lang=c++")
else:
extra_cflags.insert(0, "-lang=c")
cflags_str = make_flags_str(cflags)
if extra_cflags is not None:
extra_cflags_str = make_flags_str(extra_cflags)
cflags_str += " " + extra_cflags_str
used_compiler_versions.add(obj.options["mw_version"])
# Add MWCC build rule
lib_name = obj.options["lib"]
n.comment(f"{obj.name}: {lib_name} (linked {obj.completed})")
@ -766,7 +838,7 @@ def generate_build_ninja(
if obj.options["host"] and obj.host_obj_path is not None:
n.build(
outputs=obj.host_obj_path,
rule="host_cc" if src_path.suffix == ".c" else "host_cpp",
rule="host_cc" if file_is_c(src_path) else "host_cpp",
inputs=src_path,
variables={
"basedir": os.path.dirname(obj.host_obj_path),
@ -826,10 +898,10 @@ def generate_build_ninja(
link_built_obj = obj.completed
built_obj_path: Optional[Path] = None
if obj.src_path is not None and obj.src_path.exists():
if obj.src_path.suffix in (".c", ".cp", ".cpp"):
if file_is_c_cpp(obj.src_path):
# Add MWCC & host build rules
built_obj_path = c_build(obj, obj.src_path)
elif obj.src_path.suffix == ".s":
elif file_is_asm(obj.src_path):
# Add assembler build rule
built_obj_path = asm_build(obj, obj.src_path, obj.src_obj_path)
else:
@ -1036,7 +1108,12 @@ def generate_build_ninja(
n.build(
outputs=progress_path,
rule="progress",
implicit=[ok_path, configure_script, python_lib, config.config_path],
implicit=[
ok_path,
configure_script,
python_lib,
report_path,
],
)
###
@ -1149,8 +1226,10 @@ def generate_build_ninja(
if build_config:
if config.non_matching:
n.default(link_outputs)
else:
elif config.progress:
n.default(progress_path)
else:
n.default(ok_path)
else:
n.default(build_config_path)
@ -1169,6 +1248,13 @@ def generate_objdiff_config(
if build_config is None:
return
# Load existing objdiff.json
existing_units = {}
if Path("objdiff.json").is_file():
with open("objdiff.json", "r", encoding="utf-8") as r:
existing_config = json.load(r)
existing_units = {unit["name"]: unit for unit in existing_config["units"]}
objdiff_config: Dict[str, Any] = {
"min_version": "2.0.0-beta.5",
"custom_make": "ninja",
@ -1226,15 +1312,27 @@ def generate_objdiff_config(
) -> None:
obj_path, obj_name = build_obj["object"], build_obj["name"]
base_object = Path(obj_name).with_suffix("")
name = str(Path(module_name) / base_object).replace(os.sep, "/")
unit_config: Dict[str, Any] = {
"name": Path(module_name) / base_object,
"name": name,
"target_path": obj_path,
"base_path": None,
"scratch": None,
"metadata": {
"auto_generated": build_obj["autogenerated"],
"complete": None,
"reverse_fn_order": None,
"source_path": None,
"progress_categories": progress_categories,
"auto_generated": build_obj["autogenerated"],
},
"symbol_mappings": None,
}
# Preserve existing symbol mappings
existing_unit = existing_units.get(name)
if existing_unit is not None:
unit_config["symbol_mappings"] = existing_unit.get("symbol_mappings")
obj = objects.get(obj_name)
if obj is None:
objdiff_config["units"].append(unit_config)
@ -1243,33 +1341,24 @@ def generate_objdiff_config(
src_exists = obj.src_path is not None and obj.src_path.exists()
if src_exists:
unit_config["base_path"] = obj.src_obj_path
unit_config["metadata"]["source_path"] = obj.src_path
cflags = obj.options["cflags"]
reverse_fn_order = False
if type(cflags) is list:
for flag in cflags:
if not flag.startswith("-inline "):
continue
for value in flag.split(" ")[1].split(","):
if value == "deferred":
reverse_fn_order = True
elif value == "nodeferred":
reverse_fn_order = False
for flag in cflags:
if not flag.startswith("-inline "):
continue
for value in flag.split(" ")[1].split(","):
if value == "deferred":
reverse_fn_order = True
elif value == "nodeferred":
reverse_fn_order = False
# Filter out include directories
def keep_flag(flag):
return not flag.startswith("-i ") and not flag.startswith("-I ")
# Filter out include directories
def keep_flag(flag):
return not flag.startswith("-i ") and not flag.startswith("-I ")
cflags = list(filter(keep_flag, cflags))
# Add appropriate lang flag
if obj.src_path is not None and not any(
flag.startswith("-lang") for flag in cflags
):
if obj.src_path.suffix in (".cp", ".cpp"):
cflags.insert(0, "-lang=c++")
else:
cflags.insert(0, "-lang=c")
cflags = list(filter(keep_flag, cflags))
compiler_version = COMPILER_MAP.get(obj.options["mw_version"])
if compiler_version is None:
@ -1300,7 +1389,6 @@ def generate_objdiff_config(
{
"complete": obj.completed,
"reverse_fn_order": reverse_fn_order,
"source_path": obj.src_path,
"progress_categories": progress_categories,
}
)
@ -1344,136 +1432,294 @@ def generate_objdiff_config(
for category in config.progress_categories:
add_category(category.id, category.name)
def cleandict(d):
if isinstance(d, dict):
return {k: cleandict(v) for k, v in d.items() if v is not None}
elif isinstance(d, list):
return [cleandict(v) for v in d]
else:
return d
# Write objdiff.json
with open("objdiff.json", "w", encoding="utf-8") as w:
def unix_path(input: Any) -> str:
return str(input).replace(os.sep, "/") if input else ""
json.dump(objdiff_config, w, indent=4, default=unix_path)
json.dump(cleandict(objdiff_config), w, indent=2, default=unix_path)
def generate_compile_commands(
config: ProjectConfig,
objects: Dict[str, Object],
build_config: Optional[Dict[str, Any]],
) -> None:
if build_config is None or not config.generate_compile_commands:
return
# The following code attempts to convert mwcc flags to clang flags
# for use with clangd.
# Flags to ignore explicitly
CFLAG_IGNORE: Set[str] = {
# Search order modifier
# Has a different meaning to Clang, and would otherwise
# be picked up by the include passthrough prefix
"-I-",
"-i-",
}
CFLAG_IGNORE_PREFIX: Tuple[str, ...] = tuple()
# Flags to replace
CFLAG_REPLACE: Dict[str, str] = {}
CFLAG_REPLACE_PREFIX: Tuple[Tuple[str, str], ...] = (
# Includes
("-i ", "-I"),
("-I ", "-I"),
("-I+", "-I"),
# Defines
("-d ", "-D"),
("-D ", "-D"),
("-D+", "-D"),
)
# Flags with a finite set of options
CFLAG_REPLACE_OPTIONS: Tuple[Tuple[str, Dict[str, Tuple[str, ...]]], ...] = (
# Exceptions
(
"-Cpp_exceptions",
{
"off": ("-fno-cxx-exceptions",),
"on": ("-fcxx-exceptions",),
},
),
# RTTI
(
"-RTTI",
{
"off": ("-fno-rtti",),
"on": ("-frtti",),
},
),
# Language configuration
(
"-lang",
{
"c": ("--language=c", "--std=c89"),
"c99": ("--language=c", "--std=c99"),
"c++": ("--language=c++", "--std=c++98"),
"cplus": ("--language=c++", "--std=c++98"),
},
),
)
# Flags to pass through
CFLAG_PASSTHROUGH: Set[str] = set()
CFLAG_PASSTHROUGH_PREFIX: Tuple[str, ...] = (
"-I", # includes
"-D", # defines
)
clangd_config = []
def add_unit(build_obj: Dict[str, Any]) -> None:
obj = objects.get(build_obj["name"])
if obj is None:
return
# Skip unresolved objects
if (
obj.src_path is None
or obj.src_obj_path is None
or not file_is_c_cpp(obj.src_path)
):
return
# Gather cflags for source file
cflags: list[str] = []
def append_cflags(flags: Iterable[str]) -> None:
# Match a flag against either a set of concrete flags, or a set of prefixes.
def flag_match(
flag: str, concrete: Set[str], prefixes: Tuple[str, ...]
) -> bool:
if flag in concrete:
return True
for prefix in prefixes:
if flag.startswith(prefix):
return True
return False
# Determine whether a flag should be ignored.
def should_ignore(flag: str) -> bool:
return flag_match(flag, CFLAG_IGNORE, CFLAG_IGNORE_PREFIX)
# Determine whether a flag should be passed through.
def should_passthrough(flag: str) -> bool:
return flag_match(flag, CFLAG_PASSTHROUGH, CFLAG_PASSTHROUGH_PREFIX)
# Attempts replacement for the given flag.
def try_replace(flag: str) -> bool:
replacement = CFLAG_REPLACE.get(flag)
if replacement is not None:
cflags.append(replacement)
return True
for prefix, replacement in CFLAG_REPLACE_PREFIX:
if flag.startswith(prefix):
cflags.append(flag.replace(prefix, replacement, 1))
return True
for prefix, options in CFLAG_REPLACE_OPTIONS:
if not flag.startswith(prefix):
continue
# "-lang c99" and "-lang=c99" are both generally valid option forms
option = flag.removeprefix(prefix).removeprefix("=").lstrip()
replacements = options.get(option)
if replacements is not None:
cflags.extend(replacements)
return True
return False
for flag in flags:
# Ignore flags first
if should_ignore(flag):
continue
# Then find replacements
if try_replace(flag):
continue
# Pass flags through last
if should_passthrough(flag):
cflags.append(flag)
continue
append_cflags(obj.options["cflags"])
if isinstance(obj.options["extra_cflags"], list):
append_cflags(obj.options["extra_cflags"])
unit_config = {
"directory": Path.cwd(),
"file": obj.src_path,
"output": obj.src_obj_path,
"arguments": [
"clang",
"-nostdinc",
"-fno-builtin",
"--target=powerpc-eabi",
*cflags,
"-c",
obj.src_path,
"-o",
obj.src_obj_path,
],
}
clangd_config.append(unit_config)
# Add DOL units
for unit in build_config["units"]:
add_unit(unit)
# Add REL units
for module in build_config["modules"]:
for unit in module["units"]:
add_unit(unit)
# Write compile_commands.json
with open("compile_commands.json", "w", encoding="utf-8") as w:
def default_format(o):
if isinstance(o, Path):
return o.resolve().as_posix()
return str(o)
json.dump(clangd_config, w, indent=2, default=default_format)
# Calculate, print and write progress to progress.json
def calculate_progress(config: ProjectConfig) -> None:
config.validate()
objects = config.objects()
out_path = config.out_path()
build_config = load_build_config(config, out_path / "config.json")
if build_config is None:
return
report_path = out_path / "report.json"
if not report_path.is_file():
sys.exit(f"Report file {report_path} does not exist")
class ProgressUnit:
def __init__(self, name: str) -> None:
self.name: str = name
self.code_total: int = 0
self.code_progress: int = 0
self.data_total: int = 0
self.data_progress: int = 0
self.objects: Set[Object] = set()
self.objects_progress: int = 0
report_data: Dict[str, Any] = {}
with open(report_path, "r", encoding="utf-8") as f:
report_data = json.load(f)
def add(self, build_obj: Dict[str, Any]) -> None:
self.code_total += build_obj["code_size"]
self.data_total += build_obj["data_size"]
# Convert string numbers (u64) to int
def convert_numbers(data: Dict[str, Any]) -> None:
for key, value in data.items():
if isinstance(value, str) and value.isdigit():
data[key] = int(value)
# Avoid counting the same object in different modules twice
include_object = build_obj["name"] not in self.objects
if include_object:
self.objects.add(build_obj["name"])
convert_numbers(report_data["measures"])
for category in report_data["categories"]:
convert_numbers(category["measures"])
if build_obj["autogenerated"]:
# Skip autogenerated objects
return
# Output to GitHub Actions job summary, if available
summary_path = os.getenv("GITHUB_STEP_SUMMARY")
summary_file: Optional[IO[str]] = None
if summary_path:
summary_file = open(summary_path, "a", encoding="utf-8")
summary_file.write("```\n")
obj = objects.get(build_obj["name"])
if obj is None or not obj.completed:
return
self.code_progress += build_obj["code_size"]
self.data_progress += build_obj["data_size"]
if include_object:
self.objects_progress += 1
def code_frac(self) -> float:
if self.code_total == 0:
return 1.0
return self.code_progress / self.code_total
def data_frac(self) -> float:
if self.data_total == 0:
return 1.0
return self.data_progress / self.data_total
progress_units: Dict[str, ProgressUnit] = {}
if config.progress_all:
progress_units["all"] = ProgressUnit("All")
progress_units["dol"] = ProgressUnit("DOL")
if len(build_config["modules"]) > 0:
if config.progress_modules:
progress_units["modules"] = ProgressUnit("Modules")
if len(config.progress_categories) > 0:
for category in config.progress_categories:
progress_units[category.id] = ProgressUnit(category.name)
if config.progress_each_module:
for module in build_config["modules"]:
progress_units[module["name"]] = ProgressUnit(module["name"])
def add_unit(id: str, unit: Dict[str, Any]) -> None:
progress = progress_units.get(id)
if progress is not None:
progress.add(unit)
# Add DOL units
for unit in build_config["units"]:
add_unit("all", unit)
add_unit("dol", unit)
obj = objects.get(unit["name"])
if obj is not None:
category_opt = obj.options["progress_category"]
if isinstance(category_opt, list):
for id in category_opt:
add_unit(id, unit)
elif category_opt is not None:
add_unit(category_opt, unit)
# Add REL units
for module in build_config["modules"]:
for unit in module["units"]:
add_unit("all", unit)
add_unit("modules", unit)
add_unit(module["name"], unit)
obj = objects.get(unit["name"])
if obj is not None:
category_opt = obj.options["progress_category"]
if isinstance(category_opt, list):
for id in category_opt:
add_unit(id, unit)
elif category_opt is not None:
add_unit(category_opt, unit)
def progress_print(s: str) -> None:
print(s)
if summary_file:
summary_file.write(s + "\n")
# Print human-readable progress
print("Progress:")
progress_print("Progress:")
for unit in progress_units.values():
if len(unit.objects) == 0:
continue
def print_category(name: str, measures: Dict[str, Any]) -> None:
total_code = measures.get("total_code", 0)
matched_code = measures.get("matched_code", 0)
matched_code_percent = measures.get("matched_code_percent", 0)
total_data = measures.get("total_data", 0)
matched_data = measures.get("matched_data", 0)
matched_data_percent = measures.get("matched_data_percent", 0)
total_functions = measures.get("total_functions", 0)
matched_functions = measures.get("matched_functions", 0)
complete_code_percent = measures.get("complete_code_percent", 0)
total_units = measures.get("total_units", 0)
complete_units = measures.get("complete_units", 0)
code_frac = unit.code_frac()
data_frac = unit.data_frac()
print(
f" {unit.name}: {code_frac:.2%} code, {data_frac:.2%} data ({unit.objects_progress} / {len(unit.objects)} files)"
progress_print(
f" {name}: {matched_code_percent:.2f}% matched, {complete_code_percent:.2f}% linked ({complete_units} / {total_units} files)"
)
print(f" Code: {unit.code_progress} / {unit.code_total} bytes")
print(f" Data: {unit.data_progress} / {unit.data_total} bytes")
progress_print(
f" Code: {matched_code} / {total_code} bytes ({matched_functions} / {total_functions} functions)"
)
progress_print(
f" Data: {matched_data} / {total_data} bytes ({matched_data_percent:.2f}%)"
)
print_category("All", report_data["measures"])
for category in report_data["categories"]:
if config.print_progress_categories is True or (
isinstance(config.print_progress_categories, list)
and category["id"] in config.print_progress_categories
):
print_category(category["name"], category["measures"])
if config.progress_use_fancy:
unit = progress_units.get("all") or progress_units.get("dol")
if unit is None or len(unit.objects) == 0:
measures = report_data["measures"]
total_code = measures.get("total_code", 0)
total_data = measures.get("total_data", 0)
if total_code == 0 or total_data == 0:
return
code_frac = measures.get("complete_code", 0) / total_code
data_frac = measures.get("complete_data", 0) / total_data
code_frac = unit.code_frac()
data_frac = unit.data_frac()
print(
progress_print(
"\nYou have {} out of {} {} and {} out of {} {}.".format(
math.floor(code_frac * config.progress_code_fancy_frac),
config.progress_code_fancy_frac,
@ -1484,17 +1730,39 @@ def calculate_progress(config: ProjectConfig) -> None:
)
)
# Finalize GitHub Actions job summary
if summary_file:
summary_file.write("```\n")
summary_file.close()
# Generate and write progress.json
progress_json: Dict[str, Any] = {}
for id, unit in progress_units.items():
if len(unit.objects) == 0:
continue
def add_category(id: str, measures: Dict[str, Any]) -> None:
progress_json[id] = {
"code": unit.code_progress,
"code/total": unit.code_total,
"data": unit.data_progress,
"data/total": unit.data_total,
"code": measures.get("complete_code", 0),
"code/total": measures.get("total_code", 0),
"data": measures.get("complete_data", 0),
"data/total": measures.get("total_data", 0),
"matched_code": measures.get("matched_code", 0),
"matched_code/total": measures.get("total_code", 0),
"matched_data": measures.get("matched_data", 0),
"matched_data/total": measures.get("total_data", 0),
"matched_functions": measures.get("matched_functions", 0),
"matched_functions/total": measures.get("total_functions", 0),
"fuzzy_match": int(measures.get("fuzzy_match_percent", 0) * 100),
"fuzzy_match/total": 10000,
"units": measures.get("complete_units", 0),
"units/total": measures.get("total_units", 0),
}
if config.progress_all:
add_category("all", report_data["measures"])
else:
# Support for old behavior where "dol" was the main category
add_category("dol", report_data["measures"])
for category in report_data["categories"]:
add_category(category["id"], category["measures"])
with open(out_path / "progress.json", "w", encoding="utf-8") as w:
json.dump(progress_json, w, indent=4)
json.dump(progress_json, w, indent=2)