Implement/match LegoNavController::CalculateNewPosDir (#675)

* Implement/match LegoNavController::CalculateNewPosDir

* Fix naming

* Fix naming
This commit is contained in:
Christian Semmler 2024-03-15 11:33:32 -04:00 committed by GitHub
parent 5e0e7ab908
commit 0e146f08d6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 341 additions and 194 deletions

View file

@ -1,45 +1,22 @@
#ifndef LEGONAVCONTROLLER_H
#define LEGONAVCONTROLLER_H
#ifndef __LEGONAVCONTROLLER_H
#define __LEGONAVCONTROLLER_H
#include "decomp.h"
#include "mxcore.h"
#include "mxtimer.h"
#include "mxtypes.h"
#include "realtime/vector.h"
//////////////////////////////////////////////////////////////////////////////
//
// LegoMouseController
// VTABLE: LEGO1 0x100d85b8
// SIZE 0x70
class LegoNavController : public MxCore {
public:
static void GetDefaults(
int* p_mouseDeadzone,
float* p_movementMaxSpeed,
float* p_turnMaxSpeed,
float* p_movementMaxAccel,
float* p_turnMaxAccel,
float* p_movementDecel,
float* p_turnDecel,
float* p_movementMinAccel,
float* p_turnMinAccel,
float* p_rotationSensitivity,
MxBool* p_turnUseVelocity
);
static void SetDefaults(
int p_mouseDeadzone,
float p_movementMaxSpeed,
float p_turnMaxSpeed,
float p_movementMaxAccel,
float p_turnMaxAccel,
float p_movementDecel,
float p_turnDecel,
float p_movementMinAccel,
float p_turnMinAccel,
float p_rotationSensitivity,
MxBool p_turnUseVelocity
);
LegoNavController();
~LegoNavController() override; // vtable+0x00
~LegoNavController() override;
MxLong Notify(MxParam& p_param) override; // vtable+0x04
// FUNCTION: LEGO1 0x10054b80
@ -55,55 +32,98 @@ class LegoNavController : public MxCore {
return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name);
}
void SetControlMax(int p_hMax, int p_vMax);
void ResetToDefault();
void SetTargets(int p_hPos, int p_vPos, MxBool p_accel);
static void SetLocation(MxU32 p_location);
float CalculateNewTargetSpeed(int p_pos, int p_center, float p_maxSpeed);
float CalculateNewAccel(int p_pos, int p_center, float p_maxAccel, int p_minAccel);
float CalculateNewVel(float p_targetVel, float p_currentVel, float p_accel, float p_time);
void SetControlMax(int p_hMax, int p_vMax);
void SetTrackDefaultParams(MxBool p_state) { m_trackDefault = p_state; }
void SetToDefaultParams();
MxBool CalculateNewPosDir(
const Vector3& p_curPos,
const Vector3& p_curDir,
Vector3& p_newPos,
Vector3& p_newDir,
undefined* p_und
const Vector3* p_und
);
inline void SetTrackDefaultParams(MxBool p_trackDefault) { m_trackDefault = p_trackDefault; }
static void GetDefaults(
int* p_dz,
float* p_lv,
float* p_rv,
float* p_la,
float* p_ra,
float* p_ld,
float* p_rd,
float* p_lmina,
float* p_rmina,
float* p_rs,
MxBool* p_urs
);
static void SetDefaults(
int p_dz,
float p_lv,
float p_rv,
float p_la,
float p_ra,
float p_ld,
float p_rd,
float p_lmina,
float p_rmina,
float p_rs,
MxBool p_urs
);
static void SetLocation(MxU32 p_location);
// SYNTHETIC: LEGO1 0x10054c10
// LegoNavController::`scalar deleting destructor'
private:
int m_hMax;
int m_vMax;
int m_mouseDeadzone;
float m_zeroThreshold;
float m_unk0x18;
float m_unk0x1c;
float m_targetMovementSpeed;
float m_targetTurnSpeed;
float m_movementMaxSpeed;
float m_turnMaxSpeed;
float m_movementAccel;
float m_turnAccel;
float m_movementMaxAccel;
float m_turnMaxAccel;
float m_movementMinAccel;
float m_turnMinAccel;
float m_movementDecel;
float m_turnDecel;
float m_turnSensitivity;
MxBool m_turnUseVelocity;
int m_time;
MxBool m_trackDefault;
MxBool m_unk0x5d;
char m_unk0x5e[2];
int m_unk0x60;
int m_unk0x64;
int m_unk0x68;
MxBool m_unk0x6c;
protected:
float CalculateNewVel(float p_targetVel, float p_currentVel, float p_accel, float p_time);
float CalculateNewTargetVel(int p_pos, int p_center, float p_max);
float CalculateNewAccel(int p_pos, int p_center, float p_max, int p_min);
int FUN_10055750(MxBool& p_und);
int FUN_100558b0();
int m_hMax; // 0x08
int m_vMax; // 0x0c
int m_deadZone; // 0x10
float m_zeroThreshold; // 0x14
float m_linearVel; // 0x18
float m_rotationalVel; // 0x1c
float m_targetLinearVel; // 0x20
float m_targetRotationalVel; // 0x24
float m_maxLinearVel; // 0x28
float m_maxRotationalVel; // 0x2c
float m_linearAccel; // 0x30
float m_rotationalAccel; // 0x34
float m_maxLinearAccel; // 0x38
float m_maxRotationalAccel; // 0x3c
float m_minLinearAccel; // 0x40
float m_minRotationalAccel; // 0x44
float m_maxLinearDeccel; // 0x48
float m_maxRotationalDeccel; // 0x4c
float m_rotSensitivity; // 0x50
MxBool m_useRotationalVel; // 0x54
MxTime m_lastTime; // 0x58
MxBool m_trackDefault; // 0x5c
MxBool m_unk0x5d; // 0x5d
float m_unk0x60; // 0x60
float m_unk0x64; // 0x64
float m_unk0x68; // 0x68
MxBool m_unk0x6c; // 0x6c
// one copy of defaults (these can be set by App.)
static int g_defdeadZone;
static float g_defzeroThreshold;
static float g_defmaxLinearVel;
static float g_defmaxRotationalVel;
static float g_defmaxLinearAccel;
static float g_defmaxRotationalAccel;
static float g_defminLinearAccel;
static float g_defminRotationalAccel;
static float g_defmaxLinearDeccel;
static float g_defmaxRotationalDeccel;
static float g_defrotSensitivity;
static MxBool g_defuseRotationalVel;
};
#endif // LEGONAVCONTROLLER_H
#endif // __LEGOPOVCONTROLLER_H

View file

@ -26,6 +26,8 @@ class MxTransitionManager;
class ViewLODListManager;
class ViewManager;
extern MxBool g_isWorldActive;
LegoOmni* Lego();
LegoInputManager* InputManager();
LegoSoundManager* SoundManager();

View file

@ -5,63 +5,77 @@
#include "legovideomanager.h"
#include "misc.h"
#include "mxmisc.h"
#include "mxtimer.h"
#include <vec.h>
//////////////////////////////////////////////////////////////////////
#ifndef M_PI
#define M_PI 3.1416
#endif
#ifdef DTOR
#undef DTOR
#endif
#define DTOR(angle) ((angle) * M_PI / 180.)
//////////////////////////////////////////////////////////////////////
// GLOBAL: LEGO1 0x100f4c28
int g_mouseDeadzone = 40;
int LegoNavController::g_defdeadZone = 40;
// GLOBAL: LEGO1 0x100f4c2c
float g_zeroThreshold = 0.001f;
float LegoNavController::g_defzeroThreshold = 0.001f;
// GLOBAL: LEGO1 0x100f4c30
float g_movementMaxSpeed = 40.0f;
float LegoNavController::g_defmaxLinearVel = 40.0f;
// GLOBAL: LEGO1 0x100f4c34
float g_turnMaxSpeed = 20.0f;
float LegoNavController::g_defmaxRotationalVel = 20.0f;
// GLOBAL: LEGO1 0x100f4c38
float g_movementMaxAccel = 15.0f;
float LegoNavController::g_defmaxLinearAccel = 15.0f;
// GLOBAL: LEGO1 0x100f4c3c
float g_turnMaxAccel = 30.0f;
float LegoNavController::g_defmaxRotationalAccel = 30.0f;
// GLOBAL: LEGO1 0x100f4c40
float g_movementMinAccel = 4.0f;
float LegoNavController::g_defminLinearAccel = 4.0f;
// GLOBAL: LEGO1 0x100f4c44
float g_turnMinAccel = 15.0f;
float LegoNavController::g_defminRotationalAccel = 15.0f;
// GLOBAL: LEGO1 0x100f4c48
float g_movementDecel = 50.0f;
float LegoNavController::g_defmaxLinearDeccel = 50.0f;
// GLOBAL: LEGO1 0x100f4c4c
float g_turnDecel = 50.0f;
float LegoNavController::g_defmaxRotationalDeccel = 50.0f;
// GLOBAL: LEGO1 0x100f4c50
float g_turnSensitivity = 0.4f;
float LegoNavController::g_defrotSensitivity = 0.4f;
// GLOBAL: LEGO1 0x100f4c54
MxBool g_turnUseVelocity = FALSE;
MxBool LegoNavController::g_defuseRotationalVel = FALSE;
// FUNCTION: LEGO1 0x10054ac0
LegoNavController::LegoNavController()
{
ResetToDefault();
SetToDefaultParams();
this->m_unk0x18 = 0.0f;
this->m_unk0x1c = 0.0f;
this->m_targetMovementSpeed = 0.0f;
this->m_targetTurnSpeed = 0.0f;
this->m_movementAccel = 0.0f;
this->m_turnAccel = 0.0f;
this->m_trackDefault = FALSE;
this->m_unk0x5d = FALSE;
this->m_unk0x6c = FALSE;
this->m_unk0x64 = 0;
this->m_unk0x68 = 0;
this->m_unk0x60 = 0;
m_linearVel = 0.0f;
m_rotationalVel = 0.0f;
m_targetLinearVel = 0.0f;
m_targetRotationalVel = 0.0f;
m_linearAccel = 0.0f;
m_rotationalAccel = 0.0f;
m_trackDefault = FALSE;
m_unk0x5d = FALSE;
m_unk0x6c = FALSE;
m_unk0x64 = 0.0f;
m_unk0x68 = 0.0f;
m_unk0x60 = 0.0f;
MxTimer* timer = Timer();
this->m_time = timer->GetTime();
m_lastTime = Timer()->GetTime();
InputManager()->Register(this);
}
@ -75,148 +89,141 @@ LegoNavController::~LegoNavController()
// FUNCTION: LEGO1 0x10054ca0
void LegoNavController::SetControlMax(int p_hMax, int p_vMax)
{
this->m_hMax = p_hMax;
this->m_vMax = p_vMax;
m_hMax = p_hMax;
m_vMax = p_vMax;
if (VideoManager()->GetVideoParam().Flags().GetFullScreen()) {
this->m_hMax = 640;
this->m_vMax = 480;
m_hMax = 640;
m_vMax = 480;
}
}
// FUNCTION: LEGO1 0x10054cd0
void LegoNavController::ResetToDefault()
void LegoNavController::SetToDefaultParams()
{
this->m_mouseDeadzone = g_mouseDeadzone;
this->m_zeroThreshold = g_zeroThreshold;
this->m_turnMaxAccel = g_turnMaxAccel;
this->m_movementMaxAccel = g_movementMaxAccel;
this->m_turnMinAccel = g_turnMinAccel;
this->m_movementMinAccel = g_movementMinAccel;
this->m_turnDecel = g_turnDecel;
this->m_movementDecel = g_movementDecel;
this->m_turnMaxSpeed = g_turnMaxSpeed;
this->m_movementMaxSpeed = g_movementMaxSpeed;
this->m_turnUseVelocity = g_turnUseVelocity;
this->m_turnSensitivity = g_turnSensitivity;
m_deadZone = g_defdeadZone;
m_zeroThreshold = g_defzeroThreshold;
m_maxRotationalAccel = g_defmaxRotationalAccel;
m_maxLinearAccel = g_defmaxLinearAccel;
m_minRotationalAccel = g_defminRotationalAccel;
m_minLinearAccel = g_defminLinearAccel;
m_maxRotationalDeccel = g_defmaxRotationalDeccel;
m_maxLinearDeccel = g_defmaxLinearDeccel;
m_maxRotationalVel = g_defmaxRotationalVel;
m_maxLinearVel = g_defmaxLinearVel;
m_useRotationalVel = g_defuseRotationalVel;
m_rotSensitivity = g_defrotSensitivity;
}
// FUNCTION: LEGO1 0x10054d40
void LegoNavController::GetDefaults(
int* p_mouseDeadzone,
float* p_movementMaxSpeed,
float* p_turnMaxSpeed,
float* p_movementMaxAccel,
float* p_turnMaxAccel,
float* p_movementDecel,
float* p_turnDecel,
float* p_movementMinAccel,
float* p_turnMinAccel,
float* p_turnSensitivity,
MxBool* p_turnUseVelocity
int* p_dz,
float* p_lv,
float* p_rv,
float* p_la,
float* p_ra,
float* p_ld,
float* p_rd,
float* p_lmina,
float* p_rmina,
float* p_rs,
MxBool* p_urs
)
{
*p_mouseDeadzone = g_mouseDeadzone;
*p_movementMaxSpeed = g_movementMaxSpeed;
*p_turnMaxSpeed = g_turnMaxSpeed;
*p_movementMaxAccel = g_movementMaxAccel;
*p_turnMaxAccel = g_turnMaxAccel;
*p_movementDecel = g_movementDecel;
*p_turnDecel = g_turnDecel;
*p_movementMinAccel = g_movementMinAccel;
*p_turnMinAccel = g_turnMinAccel;
*p_turnSensitivity = g_turnSensitivity;
*p_turnUseVelocity = g_turnUseVelocity;
*p_dz = g_defdeadZone;
*p_lv = g_defmaxLinearVel;
*p_rv = g_defmaxRotationalVel;
*p_la = g_defmaxLinearAccel;
*p_ra = g_defmaxRotationalAccel;
*p_ld = g_defmaxLinearDeccel;
*p_rd = g_defmaxRotationalDeccel;
*p_lmina = g_defminLinearAccel;
*p_rmina = g_defminRotationalAccel;
*p_rs = g_defrotSensitivity;
*p_urs = g_defuseRotationalVel;
}
// FUNCTION: LEGO1 0x10054dd0
void LegoNavController::SetDefaults(
int p_mouseDeadzone,
float p_movementMaxSpeed,
float p_turnMaxSpeed,
float p_movementMaxAccel,
float p_turnMaxAccel,
float p_movementDecel,
float p_turnDecel,
float p_movementMinAccel,
float p_turnMinAccel,
float p_turnSensitivity,
MxBool p_turnUseVelocity
int p_dz,
float p_lv,
float p_rv,
float p_la,
float p_ra,
float p_ld,
float p_rd,
float p_lmina,
float p_rmina,
float p_rs,
MxBool p_urs
)
{
g_mouseDeadzone = p_mouseDeadzone;
g_movementMaxSpeed = p_movementMaxSpeed;
g_turnMaxSpeed = p_turnMaxSpeed;
g_movementMaxAccel = p_movementMaxAccel;
g_turnMaxAccel = p_turnMaxAccel;
g_movementDecel = p_movementDecel;
g_turnDecel = p_turnDecel;
g_movementMinAccel = p_movementMinAccel;
g_turnMinAccel = p_turnMinAccel;
g_turnSensitivity = p_turnSensitivity;
g_turnUseVelocity = p_turnUseVelocity;
g_defdeadZone = p_dz;
g_defmaxLinearVel = p_lv;
g_defmaxRotationalVel = p_rv;
g_defmaxLinearAccel = p_la;
g_defmaxRotationalAccel = p_ra;
g_defmaxLinearDeccel = p_ld;
g_defmaxRotationalDeccel = p_rd;
g_defminLinearAccel = p_lmina;
g_defminRotationalAccel = p_rmina;
g_defrotSensitivity = p_rs;
g_defuseRotationalVel = p_urs;
}
// FUNCTION: LEGO1 0x10054e40
void LegoNavController::SetTargets(int p_hPos, int p_vPos, MxBool p_accel)
{
if (this->m_trackDefault != FALSE) {
ResetToDefault();
if (m_trackDefault != FALSE) {
SetToDefaultParams();
}
if (p_accel != FALSE) {
this->m_targetTurnSpeed = CalculateNewTargetSpeed(p_hPos, this->m_hMax / 2, this->m_turnMaxSpeed);
this->m_targetMovementSpeed =
CalculateNewTargetSpeed(this->m_vMax - p_vPos, this->m_vMax / 2, this->m_movementMaxSpeed);
this->m_turnAccel =
CalculateNewAccel(p_hPos, this->m_hMax / 2, this->m_turnMaxAccel, (int) this->m_turnMinAccel);
this->m_movementAccel = CalculateNewAccel(
this->m_vMax - p_vPos,
this->m_vMax / 2,
this->m_movementMaxAccel,
(int) this->m_movementMinAccel
);
m_targetRotationalVel = CalculateNewTargetVel(p_hPos, m_hMax / 2, m_maxRotationalVel);
m_targetLinearVel = CalculateNewTargetVel(m_vMax - p_vPos, m_vMax / 2, m_maxLinearVel);
m_rotationalAccel = CalculateNewAccel(p_hPos, m_hMax / 2, m_maxRotationalAccel, (int) m_minRotationalAccel);
m_linearAccel = CalculateNewAccel(m_vMax - p_vPos, m_vMax / 2, m_maxLinearAccel, (int) m_minLinearAccel);
}
else {
this->m_targetTurnSpeed = 0.0f;
this->m_targetMovementSpeed = 0.0f;
this->m_movementAccel = this->m_movementDecel;
this->m_turnAccel = this->m_turnDecel;
m_targetRotationalVel = 0;
m_targetLinearVel = 0;
m_linearAccel = m_maxLinearDeccel;
m_rotationalAccel = m_maxRotationalDeccel;
}
}
// FUNCTION: LEGO1 0x10054f10
float LegoNavController::CalculateNewTargetSpeed(int p_pos, int p_center, float p_maxSpeed)
float LegoNavController::CalculateNewTargetVel(int p_pos, int p_center, float p_max)
{
float result;
float newVel;
int diff = p_pos - p_center;
if (diff > this->m_mouseDeadzone) {
result = (diff - m_mouseDeadzone) * p_maxSpeed / (p_center - m_mouseDeadzone);
if (diff > m_deadZone) {
newVel = (diff - m_deadZone) * p_max / (p_center - m_deadZone);
}
else if (diff < -m_mouseDeadzone) {
result = (diff + m_mouseDeadzone) * p_maxSpeed / (p_center - m_mouseDeadzone);
else if (diff < -m_deadZone) {
newVel = (diff + m_deadZone) * p_max / (p_center - m_deadZone);
}
else {
result = 0.0f;
newVel = 0.0;
}
return result;
return newVel;
}
// FUNCTION: LEGO1 0x10054f90
float LegoNavController::CalculateNewAccel(int p_pos, int p_center, float p_maxAccel, int p_minAccel)
float LegoNavController::CalculateNewAccel(int p_pos, int p_center, float p_max, int p_min)
{
float result;
float newAccel;
int diff = p_pos - p_center;
result = Abs(diff) * p_maxAccel / p_center;
newAccel = Abs(diff) * p_max / p_center;
if (result < p_minAccel) {
result = (float) p_minAccel;
if (newAccel < p_min) {
newAccel = (float) p_min;
}
return result;
return newAccel;
}
// FUNCTION: LEGO1 0x10054fe0
@ -227,7 +234,7 @@ float LegoNavController::CalculateNewVel(float p_targetVel, float p_currentVel,
float velDiff = p_targetVel - p_currentVel;
int vSign = velDiff > 0 ? 1 : -1;
if (Abs(velDiff) > this->m_zeroThreshold) {
if (Abs(velDiff) > m_zeroThreshold) {
float deltaVel = p_accel * p_time;
newVel = p_currentVel + (deltaVel * vSign);
@ -242,22 +249,134 @@ float LegoNavController::CalculateNewVel(float p_targetVel, float p_currentVel,
return newVel;
}
// STUB: LEGO1 0x10055080
// FUNCTION: LEGO1 0x10055080
MxBool LegoNavController::CalculateNewPosDir(
const Vector3& p_curPos,
const Vector3& p_curDir,
Vector3& p_newPos,
Vector3& p_newDir,
undefined* p_und
const Vector3* p_und
)
{
// TODO
return TRUE;
if (!g_isWorldActive) {
return FALSE;
}
MxBool changed = FALSE;
MxBool und = FALSE;
MxTime currentTime = Timer()->GetTime();
float deltaTime = (currentTime - m_lastTime) / 1000.0;
m_lastTime = currentTime;
if (FUN_100558b0() == -1) {
FUN_10055750(und);
}
if (m_useRotationalVel) {
m_rotationalVel = CalculateNewVel(m_targetRotationalVel, m_rotationalVel, m_rotationalAccel * 40.0f, deltaTime);
}
else {
m_rotationalVel = m_targetRotationalVel;
}
m_linearVel = CalculateNewVel(m_targetLinearVel, m_linearVel, m_linearAccel, deltaTime);
if (und || (Abs(m_rotationalVel) > m_zeroThreshold) || (Abs(m_linearVel) > m_zeroThreshold)) {
float rot_mat[3][3];
Mx3DPointFloat delta_pos, new_dir, new_pos;
if (m_linearVel < -(m_maxLinearVel * 0.4f)) {
m_linearVel = -(m_maxLinearVel * 0.4f);
}
VXS3(delta_pos, p_curDir, m_linearVel * deltaTime);
VPV3(p_newPos, p_curPos, delta_pos);
float delta_rad;
if (m_useRotationalVel) {
delta_rad = DTOR(m_rotationalVel * deltaTime);
}
else {
delta_rad = DTOR(m_rotationalVel * m_rotSensitivity);
}
if (p_und != NULL && (*p_und)[1] < 0.0f) {
delta_rad = -delta_rad;
}
IDENTMAT3(rot_mat);
rot_mat[0][0] = rot_mat[2][2] = cos(delta_rad);
rot_mat[0][2] = rot_mat[2][0] = sin(delta_rad);
rot_mat[0][2] *= -1.0f;
VXM3(p_newDir, p_curDir, rot_mat);
changed = TRUE;
}
if (m_unk0x5d) {
float rot_mat[3][3];
Mx3DPointFloat delta_pos, new_pos, new_dir;
if (changed) {
SET3(new_pos, p_newPos);
SET3(new_dir, p_newDir);
}
else {
SET3(new_pos, p_curPos);
SET3(new_dir, p_curDir);
}
if (m_unk0x64 != 0.0f) {
delta_pos[0] = new_dir[0] * m_unk0x64;
delta_pos[1] = new_dir[1] * m_unk0x64;
delta_pos[2] = new_dir[2] * m_unk0x64;
}
else {
FILLVEC3(delta_pos, 0.0f);
}
delta_pos[1] += m_unk0x60;
VPV3(p_newPos, new_pos, delta_pos);
if (m_unk0x68 != 0.0f) {
float delta_rad = DTOR(m_unk0x68);
IDENTMAT3(rot_mat);
rot_mat[0][0] = rot_mat[2][2] = cos(delta_rad);
rot_mat[0][2] = rot_mat[2][0] = sin(delta_rad);
rot_mat[0][2] *= -1.0f;
VXM3(p_newDir, new_dir, rot_mat);
}
else {
SET3(p_newDir, new_dir);
}
m_unk0x60 = m_unk0x64 = m_unk0x68 = 0.0f;
m_unk0x5d = FALSE;
changed = TRUE;
}
return changed;
}
// STUB: LEGO1 0x10055620
void LegoNavController::SetLocation(MxU32 p_location)
{
// TODO
}
// STUB: LEGO1 0x10055750
int LegoNavController::FUN_10055750(MxBool& p_und)
{
// TODO
return -1;
}
// STUB: LEGO1 0x100558b0
int LegoNavController::FUN_100558b0()
{
// TODO
return -1;
}
// STUB: LEGO1 0x10055a60

View file

@ -7,6 +7,7 @@
#include "misc.h"
#include "mxmisc.h"
#include "mxticklemanager.h"
#include "mxtimer.h"
#include "realtime/realtime.h"
#include "roi/legoroi.h"

View file

@ -16,3 +16,8 @@ e_RAMStream: 'Allow this enum constant'
p_milliseconds: 'Probably a bug with function call'
m_increaseAmount: "Can't currently detect member in union"
m_increaseFactor: "Can't currently detect member in union"
delta_rad: "Allow original naming from 1996"
delta_pos: "Allow original naming from 1996"
rot_mat: "Allow original naming from 1996"
new_pos: "Allow original naming from 1996"
new_dir: "Allow original naming from 1996"