mirror of
https://github.com/izzy2lost/Torch.git
synced 2026-07-06 00:18:35 -07:00
F-Zero Course Track Segment Info Docs
This commit is contained in:
@@ -10,10 +10,6 @@
|
||||
|
||||
#define ARRAY_COUNT(arr) (int32_t)(sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
#define TRACK_SEGMENT_JOINT_MASK 0x600
|
||||
#define TRACK_SEGMENT_FORM_MASK 0x38000
|
||||
#define TRACK_SEGMENT_FLAG_CONTINUE 0x40000000
|
||||
|
||||
#define FORMAT_HEX(x, w) std::hex << std::setfill('0') << std::setw(w) << x
|
||||
#define FORMAT_FLOAT(x, w, p) std::dec << std::setfill(' ') << std::fixed << std::setprecision(p) << std::setw(w) << x
|
||||
|
||||
@@ -23,9 +19,9 @@ uint32_t FZX::CourseData::CalculateChecksum(void) {
|
||||
|
||||
for (const auto& controlPointInfo : mControlPointInfos) {
|
||||
int32_t trackSegmentInfo = controlPointInfo.controlPoint.trackSegmentInfo;
|
||||
trackSegmentInfo &= ~TRACK_SEGMENT_JOINT_MASK;
|
||||
trackSegmentInfo &= ~TRACK_SEGMENT_FORM_MASK;
|
||||
trackSegmentInfo &= ~TRACK_SEGMENT_FLAG_CONTINUE;
|
||||
trackSegmentInfo &= ~TRACK_JOIN_MASK;
|
||||
trackSegmentInfo &= ~TRACK_FORM_MASK;
|
||||
trackSegmentInfo &= ~TRACK_FLAG_CONTINUOUS;
|
||||
|
||||
checksum += (int32_t) ((controlPointInfo.controlPoint.pos.x + ((1.1f + (0.7f * counter)) * controlPointInfo.controlPoint.pos.y)) +
|
||||
((2.2f + (1.2f * counter)) * controlPointInfo.controlPoint.pos.z * (4.4f + (0.9f * counter))) +
|
||||
@@ -99,8 +95,173 @@ ExportResult FZX::CourseCodeExporter::Export(std::ostream &write, std::shared_pt
|
||||
Vec3f pos(controlPointInfo.controlPoint.pos.x, controlPointInfo.controlPoint.pos.y, controlPointInfo.controlPoint.pos.z);
|
||||
write << "{ { " << FORMAT_FLOAT(pos, 6, 4) << "}, ";
|
||||
write << controlPointInfo.controlPoint.radiusLeft << ", ";
|
||||
write << controlPointInfo.controlPoint.radiusRight << ", ";
|
||||
write << "0x" << std::hex << controlPointInfo.controlPoint.trackSegmentInfo << std::dec;
|
||||
write << controlPointInfo.controlPoint.radiusRight << ",\n";
|
||||
write << fourSpaceTab << fourSpaceTab << " ";
|
||||
int32_t trackSegmentInfo = controlPointInfo.controlPoint.trackSegmentInfo;
|
||||
bool hasFlags = false;
|
||||
if (trackSegmentInfo & TRACK_FLAG_20000000) {
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_FLAG_20000000";
|
||||
hasFlags = true;
|
||||
trackSegmentInfo &= ~TRACK_FLAG_20000000;
|
||||
}
|
||||
|
||||
if (trackSegmentInfo & TRACK_FLAG_JOINABLE) {
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_FLAG_JOINABLE";
|
||||
hasFlags = true;
|
||||
trackSegmentInfo &= ~TRACK_FLAG_JOINABLE;
|
||||
}
|
||||
|
||||
if (trackSegmentInfo & TRACK_FLAG_8000000) {
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_FLAG_8000000";
|
||||
hasFlags = true;
|
||||
trackSegmentInfo &= ~TRACK_FLAG_8000000;
|
||||
}
|
||||
|
||||
switch (trackSegmentInfo & TRACK_FORM_MASK) {
|
||||
case TRACK_FORM_STRAIGHT:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_FORM_STRAIGHT";
|
||||
break;
|
||||
case TRACK_FORM_LEFT:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_FORM_LEFT";
|
||||
break;
|
||||
case TRACK_FORM_RIGHT:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_FORM_RIGHT";
|
||||
break;
|
||||
case TRACK_FORM_S:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_FORM_S";
|
||||
break;
|
||||
case TRACK_FORM_S_FLIPPED:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_FORM_S_FLIPPED";
|
||||
break;
|
||||
}
|
||||
trackSegmentInfo &= ~TRACK_FORM_MASK;
|
||||
|
||||
switch (trackSegmentInfo & TRACK_SHAPE_MASK) {
|
||||
case TRACK_SHAPE_ROAD:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_SHAPE_ROAD";
|
||||
trackSegmentInfo &= ~TRACK_SHAPE_MASK;
|
||||
if ((trackSegmentInfo & TRACK_TYPE_MASK) == TRACK_TYPE_NONE) {
|
||||
write << " | TRACK_TYPE_NONE";
|
||||
} else {
|
||||
write << " | " << static_cast<Road>(trackSegmentInfo & TRACK_TYPE_MASK);
|
||||
}
|
||||
break;
|
||||
case TRACK_SHAPE_WALLED_ROAD:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_SHAPE_WALLED_ROAD";
|
||||
trackSegmentInfo &= ~TRACK_SHAPE_MASK;
|
||||
if ((trackSegmentInfo & TRACK_TYPE_MASK) == TRACK_TYPE_NONE) {
|
||||
write << " | TRACK_TYPE_NONE";
|
||||
} else {
|
||||
write << " | " << static_cast<WalledRoad>(trackSegmentInfo & TRACK_TYPE_MASK);
|
||||
}
|
||||
break;
|
||||
case TRACK_SHAPE_PIPE:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_SHAPE_PIPE";
|
||||
trackSegmentInfo &= ~TRACK_SHAPE_MASK;
|
||||
if ((trackSegmentInfo & TRACK_TYPE_MASK) == TRACK_TYPE_NONE) {
|
||||
write << " | TRACK_TYPE_NONE";
|
||||
} else {
|
||||
write << " | " << static_cast<Pipe>(trackSegmentInfo & TRACK_TYPE_MASK);
|
||||
}
|
||||
break;
|
||||
case TRACK_SHAPE_CYLINDER:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_SHAPE_CYLINDER";
|
||||
trackSegmentInfo &= ~TRACK_SHAPE_MASK;
|
||||
if ((trackSegmentInfo & TRACK_TYPE_MASK) == TRACK_TYPE_NONE) {
|
||||
write << " | TRACK_TYPE_NONE";
|
||||
} else {
|
||||
write << " | " << static_cast<Cylinder>(trackSegmentInfo & TRACK_TYPE_MASK);
|
||||
}
|
||||
break;
|
||||
case TRACK_SHAPE_HALF_PIPE:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_SHAPE_HALF_PIPE";
|
||||
trackSegmentInfo &= ~TRACK_SHAPE_MASK;
|
||||
if ((trackSegmentInfo & TRACK_TYPE_MASK) == TRACK_TYPE_NONE) {
|
||||
write << " | TRACK_TYPE_NONE";
|
||||
} else {
|
||||
write << " | " << static_cast<HalfPipe>(trackSegmentInfo & TRACK_TYPE_MASK);
|
||||
}
|
||||
break;
|
||||
case TRACK_SHAPE_TUNNEL:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_SHAPE_TUNNEL";
|
||||
trackSegmentInfo &= ~TRACK_SHAPE_MASK;
|
||||
if ((trackSegmentInfo & TRACK_TYPE_MASK) == TRACK_TYPE_NONE) {
|
||||
write << " | TRACK_TYPE_NONE";
|
||||
} else {
|
||||
write << " | " << static_cast<Tunnel>(trackSegmentInfo & TRACK_TYPE_MASK);
|
||||
}
|
||||
break;
|
||||
case TRACK_SHAPE_AIR:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_SHAPE_AIR";
|
||||
trackSegmentInfo &= ~TRACK_SHAPE_MASK;
|
||||
if ((trackSegmentInfo & TRACK_TYPE_MASK) == TRACK_TYPE_NONE) {
|
||||
write << " | TRACK_TYPE_NONE";
|
||||
}
|
||||
break;
|
||||
case TRACK_SHAPE_BORDERLESS_ROAD:
|
||||
if (hasFlags) {
|
||||
write << " | ";
|
||||
}
|
||||
write << "TRACK_SHAPE_BORDERLESS_ROAD";
|
||||
trackSegmentInfo &= ~TRACK_SHAPE_MASK;
|
||||
if ((trackSegmentInfo & TRACK_TYPE_MASK) == TRACK_TYPE_NONE) {
|
||||
write << " | TRACK_TYPE_NONE";
|
||||
} else {
|
||||
write << " | " << static_cast<BorderlessRoad>(trackSegmentInfo & TRACK_TYPE_MASK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
trackSegmentInfo &= ~TRACK_TYPE_MASK;
|
||||
|
||||
if (trackSegmentInfo != 0) {
|
||||
SPDLOG_WARN("Invalid Track Segment Information Found: 0x{:X}", trackSegmentInfo);
|
||||
}
|
||||
|
||||
write << " },\n";
|
||||
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,37 @@
|
||||
|
||||
#define CREATOR_NINTENDO 4
|
||||
|
||||
#define TRACK_TYPE_NONE 0x3F
|
||||
#define TRACK_TYPE_MASK 0x3F
|
||||
|
||||
#define TRACK_SHAPE_ROAD 0x0
|
||||
#define TRACK_SHAPE_WALLED_ROAD 0x40
|
||||
#define TRACK_SHAPE_PIPE 0x80
|
||||
#define TRACK_SHAPE_CYLINDER 0xC0
|
||||
#define TRACK_SHAPE_HALF_PIPE 0x100
|
||||
#define TRACK_SHAPE_TUNNEL 0x140
|
||||
#define TRACK_SHAPE_AIR 0x180
|
||||
#define TRACK_SHAPE_BORDERLESS_ROAD 0x1C0
|
||||
|
||||
#define TRACK_SHAPE_MASK 0x1C0
|
||||
|
||||
#define TRACK_JOIN_PREVIOUS 0x200
|
||||
#define TRACK_JOIN_NEXT 0x400
|
||||
#define TRACK_JOIN_MASK 0x600
|
||||
|
||||
#define TRACK_FORM_STRAIGHT 0x00008000
|
||||
#define TRACK_FORM_LEFT 0x00010000
|
||||
#define TRACK_FORM_RIGHT 0x00018000
|
||||
#define TRACK_FORM_S 0x00020000
|
||||
#define TRACK_FORM_S_FLIPPED 0x00028000
|
||||
|
||||
#define TRACK_FORM_MASK 0x00038000
|
||||
|
||||
#define TRACK_FLAG_8000000 0x8000000
|
||||
#define TRACK_FLAG_JOINABLE 0x10000000
|
||||
#define TRACK_FLAG_20000000 0x20000000
|
||||
#define TRACK_FLAG_CONTINUOUS 0x40000000
|
||||
|
||||
namespace FZX {
|
||||
enum class Venue {
|
||||
/* 0 */ VENUE_MUTE_CITY,
|
||||
@@ -111,6 +142,57 @@ enum class Sign {
|
||||
/* 4 */ SIGN_OVERHEAD,
|
||||
};
|
||||
|
||||
enum class Road {
|
||||
/* 0 */ ROAD_START_LINE,
|
||||
/* 1 */ ROAD_1,
|
||||
/* 2 */ ROAD_2,
|
||||
/* 3 */ ROAD_3,
|
||||
/* 4 */ ROAD_4,
|
||||
/* 5 */ ROAD_5,
|
||||
/* 6 */ ROAD_6,
|
||||
/* 7 */ ROAD_7,
|
||||
};
|
||||
|
||||
enum class WalledRoad {
|
||||
/* 0 */ WALLED_ROAD_0,
|
||||
/* 1 */ WALLED_ROAD_1,
|
||||
/* 2 */ WALLED_ROAD_2,
|
||||
};
|
||||
|
||||
enum class Pipe {
|
||||
/* 0 */ PIPE_0,
|
||||
/* 1 */ PIPE_1,
|
||||
/* 2 */ PIPE_2,
|
||||
/* 3 */ PIPE_3,
|
||||
};
|
||||
|
||||
enum class Cylinder {
|
||||
/* 0 */ CYLINDER_0,
|
||||
/* 1 */ CYLINDER_1,
|
||||
/* 2 */ CYLINDER_2,
|
||||
/* 3 */ CYLINDER_3,
|
||||
};
|
||||
|
||||
enum class HalfPipe {
|
||||
/* 0 */ HALF_PIPE_0,
|
||||
/* 1 */ HALF_PIPE_1,
|
||||
/* 2 */ HALF_PIPE_2,
|
||||
/* 3 */ HALF_PIPE_3,
|
||||
};
|
||||
|
||||
enum class Tunnel {
|
||||
/* 0 */ TUNNEL_0,
|
||||
/* 1 */ TUNNEL_1,
|
||||
/* 2 */ TUNNEL_2,
|
||||
/* 3 */ TUNNEL_3,
|
||||
};
|
||||
|
||||
enum class BorderlessRoad {
|
||||
/* 0 */ BORDERLESS_ROAD_0,
|
||||
/* 1 */ BORDERLESS_ROAD_1,
|
||||
/* 2 */ BORDERLESS_ROAD_2,
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Venue& venue) {
|
||||
std::string output;
|
||||
switch (venue) {
|
||||
@@ -400,4 +482,144 @@ inline std::ostream& operator<<(std::ostream& out, const Sign& sign) {
|
||||
}
|
||||
return out << output;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Road& road) {
|
||||
std::string output;
|
||||
switch (road) {
|
||||
case Road::ROAD_START_LINE:
|
||||
output = "ROAD_START_LINE";
|
||||
break;
|
||||
case Road::ROAD_1:
|
||||
output = "ROAD_1";
|
||||
break;
|
||||
case Road::ROAD_2:
|
||||
output = "ROAD_2";
|
||||
break;
|
||||
case Road::ROAD_3:
|
||||
output = "ROAD_3";
|
||||
break;
|
||||
case Road::ROAD_4:
|
||||
output = "ROAD_4";
|
||||
break;
|
||||
case Road::ROAD_5:
|
||||
output = "ROAD_5";
|
||||
break;
|
||||
case Road::ROAD_6:
|
||||
output = "ROAD_6";
|
||||
break;
|
||||
case Road::ROAD_7:
|
||||
output = "ROAD_7";
|
||||
break;
|
||||
}
|
||||
return out << output;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const WalledRoad& walledRoad) {
|
||||
std::string output;
|
||||
switch (walledRoad) {
|
||||
case WalledRoad::WALLED_ROAD_0:
|
||||
output = "WALLED_ROAD_0";
|
||||
break;
|
||||
case WalledRoad::WALLED_ROAD_1:
|
||||
output = "WALLED_ROAD_1";
|
||||
break;
|
||||
case WalledRoad::WALLED_ROAD_2:
|
||||
output = "WALLED_ROAD_2";
|
||||
break;
|
||||
}
|
||||
return out << output;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Pipe& pipe) {
|
||||
std::string output;
|
||||
switch (pipe) {
|
||||
case Pipe::PIPE_0:
|
||||
output = "PIPE_0";
|
||||
break;
|
||||
case Pipe::PIPE_1:
|
||||
output = "PIPE_1";
|
||||
break;
|
||||
case Pipe::PIPE_2:
|
||||
output = "PIPE_2";
|
||||
break;
|
||||
case Pipe::PIPE_3:
|
||||
output = "PIPE_3";
|
||||
break;
|
||||
}
|
||||
return out << output;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Cylinder& cylinder) {
|
||||
std::string output;
|
||||
switch (cylinder) {
|
||||
case Cylinder::CYLINDER_0:
|
||||
output = "CYLINDER_0";
|
||||
break;
|
||||
case Cylinder::CYLINDER_1:
|
||||
output = "CYLINDER_1";
|
||||
break;
|
||||
case Cylinder::CYLINDER_2:
|
||||
output = "CYLINDER_2";
|
||||
break;
|
||||
case Cylinder::CYLINDER_3:
|
||||
output = "CYLINDER_3";
|
||||
break;
|
||||
}
|
||||
return out << output;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const HalfPipe& halfPipe) {
|
||||
std::string output;
|
||||
switch (halfPipe) {
|
||||
case HalfPipe::HALF_PIPE_0:
|
||||
output = "HALF_PIPE_0";
|
||||
break;
|
||||
case HalfPipe::HALF_PIPE_1:
|
||||
output = "HALF_PIPE_1";
|
||||
break;
|
||||
case HalfPipe::HALF_PIPE_2:
|
||||
output = "HALF_PIPE_2";
|
||||
break;
|
||||
case HalfPipe::HALF_PIPE_3:
|
||||
output = "HALF_PIPE_3";
|
||||
break;
|
||||
}
|
||||
return out << output;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Tunnel& tunnel) {
|
||||
std::string output;
|
||||
switch (tunnel) {
|
||||
case Tunnel::TUNNEL_0:
|
||||
output = "TUNNEL_0";
|
||||
break;
|
||||
case Tunnel::TUNNEL_1:
|
||||
output = "TUNNEL_1";
|
||||
break;
|
||||
case Tunnel::TUNNEL_2:
|
||||
output = "TUNNEL_2";
|
||||
break;
|
||||
case Tunnel::TUNNEL_3:
|
||||
output = "TUNNEL_3";
|
||||
break;
|
||||
}
|
||||
return out << output;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const BorderlessRoad& borderlessRoad) {
|
||||
std::string output;
|
||||
switch (borderlessRoad) {
|
||||
case BorderlessRoad::BORDERLESS_ROAD_0:
|
||||
output = "BORDERLESS_ROAD_0";
|
||||
break;
|
||||
case BorderlessRoad::BORDERLESS_ROAD_1:
|
||||
output = "BORDERLESS_ROAD_1";
|
||||
break;
|
||||
case BorderlessRoad::BORDERLESS_ROAD_2:
|
||||
output = "BORDERLESS_ROAD_2";
|
||||
break;
|
||||
}
|
||||
return out << output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user