3#include <game/bases/d_wm_lib.hpp>
4#include <lib/nw4r/g3d.h>
5#include <lib/MSL/stdlib.h>
6#include <constants/sjis_constants.h>
9const int dCsvData_c::c_COURSE_ID = STAGE_1;
10const int dCsvData_c::c_GHOST_ID = STAGE_GHOST_HOUSE;
11const int dCsvData_c::c_TOWER_ID = STAGE_TOWER;
12const int dCsvData_c::c_CASTLE_ID = STAGE_CASTLE;
13const int dCsvData_c::c_KINOKO_ID = STAGE_KINOKO_HOUSE;
14const int dCsvData_c::c_ENEMY_ID = STAGE_ENEMY;
15const int dCsvData_c::c_CANON_ID = STAGE_CANNON;
16const int dCsvData_c::c_TRSHIP_ID = STAGE_TRSHIP;
17const int dCsvData_c::c_AIRSHIP_ID = STAGE_AIRSHIP;
19const int dCsvData_c::c_PEACH_ID = STAGE_PEACH_CASTLE;
21const char *l_routeInfoArcName =
"RouteInfo";
25int read(
char *buffer,
const char *csv,
int bufferSize) {
39 if (*csv ==
',' || *csv ==
'"' || *csv ==
'\r' && *(csv + 1) ==
'\n') {
51 for (
int i = 0; i < MAX_ROUTE_COUNT; i++) {
52 if (
mRoutes[i].mChildPoints !=
nullptr) {
69 for (
int i = 0; i < MAX_POINT_COUNT; i++) {
70 for (
int j = 0; j < MAX_POINT_NAME_LEN; j++) {
73 for (
int k = 0; k < MAX_OPEN_POINT_COUNT; k++) {
74 for (
int j = 0; j < MAX_POINT_NAME_LEN; j++) {
75 mPoints[i].mOpenPointNameRegular[k][j] =
'\0';
76 mPoints[i].mOpenPointNameSecret[k][j] =
'\0';
80 for (
int k = 0; k < 64; k++) {
81 for (
int j = 0; j < MAX_ROUTE_NAME_LEN; j++) {
82 mPoints[i].mRouteNameRegular[k][j] =
'\0';
83 mPoints[i].mRouteNameSecret[k][j] =
'\0';
86 for (
int k = 0; k < MAX_FLAG_DATA_COUNT; k++) {
87 for (
int j = 0; j < MAX_FLAG_DATA_LEN; j++) {
88 mPoints[i].mFlagDataRegular[k][j] =
'\0';
89 mPoints[i].mFlagDataSecret[k][j] =
'\0';
92 mPoints[i].mFlagDataNumRegular = 0;
93 mPoints[i].mFlagDataNumSecret = 0;
99 for (
int i = 0; i < MAX_SUBROUTE_COUNT; i++) {
100 for (
int j = 0; j < MAX_ROUTE_NAME_LEN; j++) {
107 for (
int i = 0; i < MAX_ROUTE_COUNT; i++) {
108 for (
int j = 0; j < MAX_ROUTE_NAME_LEN; j++) {
111 mRoutes[i].mChildPoints =
nullptr;
112 mRoutes[i].mNumSubroutes = 99999;
122 nw4r::g3d::ResFile res;
126 snprintf(fileName,
sizeof(fileName),
"W%X/pointW%X.csv",
mWorld + 1,
mWorld + 1);
127 res = resMng->
getResSilently(l_routeInfoArcName, fileName, &fileSize);
128 if (!res.IsValid()) {
129 snprintf(fileName,
sizeof(fileName),
"W%X/pointW%Xa.csv",
mWorld + 1,
mWorld + 1);
130 fileName[SUBWORLD_CHAR_OFFSET] +=
mSubworld;
131 res = resMng->
getRes(l_routeInfoArcName, fileName, &fileSize);
133 csv = (
char *) res.ptr();
139 while (csv[pos] !=
',') {
186 }
while (pos != fileSize);
189 snprintf(fileName,
sizeof(fileName),
"W%X/routeW%X.csv",
mWorld + 1,
mWorld + 1);
190 res = resMng->
getResSilently(l_routeInfoArcName, fileName, &fileSize);
191 if (!res.IsValid()) {
192 snprintf(fileName,
sizeof(fileName),
"W%X/routeW%Xa.csv",
mWorld + 1,
mWorld + 1);
193 fileName[SUBWORLD_CHAR_OFFSET] +=
mSubworld;
194 res = resMng->
getRes(l_routeInfoArcName, fileName, &fileSize);
196 csv = (
char *) res.ptr();
209 }
while (pos != fileSize);
218 if (csv[pos] ==
'"' && csv[pos + 1] ==
'"') {
222 if (csv[pos] ==
',') {
228 if (csv[pos] ==
'"') {
237 if (csv[pos] ==
',' || csv[pos] ==
'"' ||
isLineEnd(csv, pos)) {
241 pointName[i] = csv[pos];
247 if (strcmp(pointName,
"ura") == 0) {
249 }
else if (strcmp(pointName,
"stop") == 0) {
251 }
else if (strcmp(pointName,
"link1") == 0) {
253 }
else if (strcmp(pointName,
"link2") == 0) {
255 }
else if (strcmp(pointName,
"link3") == 0) {
257 }
else if (strcmp(pointName,
"link4") == 0) {
259 }
else if (strcmp(pointName,
"link5") == 0) {
261 }
else if (strcmp(pointName,
"scroll") == 0) {
263 }
else if (strcmp(pointName,
"scale") == 0) {
265 }
else if (strcmp(pointName,
"dokan") == 0) {
267 }
else if (strcmp(pointName,
"switch") == 0) {
269 }
else if (strcmp(pointName,
"crossroad") == 0) {
271 }
else if (strcmp(pointName,
"focus") == 0) {
273 }
else if (strncmp(pointName,
"anchor", 6) == 0) {
274 int len = strlen(pointName);
278 }
else if (len == 7 || len == 8) {
279 if (pointName[6] ==
'x') {
281 }
else if (pointName[6] ==
'y') {
283 }
else if (
'1' <= pointName[6] && pointName[6] <=
'9') {
286 if (
'1' <= pointName[7] && pointName[7] <=
'9') {
290 }
else if (strcmp(pointName,
"tilt") == 0) {
292 }
else if (strcmp(pointName,
"demo1") == 0) {
294 }
else if (strcmp(pointName,
"demo2") == 0) {
296 }
else if (strcmp(pointName,
"demo3") == 0) {
298 }
else if (strcmp(pointName,
"demo4") == 0) {
300 }
else if (strcmp(pointName,
"demo5") == 0) {
302 }
else if (strcmp(pointName,
"demo6") == 0) {
304 }
else if (strcmp(pointName,
"demo7") == 0) {
306 }
else if (strcmp(pointName,
"camstop") == 0) {
308 }
else if (strcmp(pointName,
"noshift") == 0) {
310 }
else if (strncmp(pointName,
"board", 5) == 0) {
312 }
else if (strcmp(pointName,
"demostop") == 0) {
314 }
else if (strcmp(pointName,
"scrollY") == 0) {
316 }
else if (strcmp(pointName,
"sand") == 0) {
318 }
else if (strcmp(pointName,
"ice") == 0) {
320 }
else if (strcmp(pointName,
"scrollA") == 0) {
325 if (strcmp(pointName,
"kuribo1") == 0) {
327 }
else if (strcmp(pointName,
"kuribo2") == 0) {
329 }
else if (strcmp(pointName,
"Puku1") == 0) {
331 }
else if (strcmp(pointName,
"Puku2") == 0) {
333 }
else if (strcmp(pointName,
"Pak1") == 0) {
335 }
else if (strcmp(pointName,
"Pak2") == 0) {
337 }
else if (strcmp(pointName,
"Pak3") == 0) {
339 }
else if (strcmp(pointName,
"Hbros1") == 0) {
341 }
else if (strcmp(pointName,
"trap1") == 0) {
343 }
else if (strcmp(pointName,
"trap2") == 0) {
347 if (csv[pos] ==
'"') {
351 if (!isStr && csv[pos] ==
',' ||
isLineEnd(csv, pos)) {
363 if (csv[pos] ==
'"' && csv[pos + 1] ==
'"') {
365 }
else if (csv[pos] ==
'"') {
369 for (
int i = 0; i < MAX_POINT_NAME_LEN - 1; i++) {
370 if (csv[pos] ==
',') {
382 }
while (csv[pos++] !=
'"');
383 }
else if (csv[pos] !=
',') {
386 for (
int i = 0; i < MAX_POINT_NAME_LEN - 1; i++) {
387 if (csv[pos] ==
',') {
399 while (csv[pos] !=
',') {
405 }
while (csv[pos] !=
',' && !
isLineEnd(csv, pos));
416 if (csv[pos] ==
'"' && csv[pos + 1] ==
'"') {
418 }
else if (csv[pos] ==
'"') {
422 for (
int i = 0; i < MAX_ROUTE_NAME_LEN - 1; i++) {
423 if (csv[pos] ==
',' || csv[pos] ==
'"') {
426 if (csv[pos] !=
' ') {
437 }
while (csv[pos++] !=
'"');
438 }
else if (csv[pos] !=
',') {
441 for (
int i = 0; i < MAX_ROUTE_NAME_LEN - 1; i++) {
442 if (csv[pos] ==
',' || csv[pos] ==
'"') {
445 if (csv[pos] !=
' ') {
456 while (csv[pos] !=
',') {
462 }
while (csv[pos] !=
',' && !
isLineEnd(csv, pos));
474 if (csv[pos] ==
'"') {
482 if (csv[pos] ==
',' || csv[pos] ==
'"' || csv[pos] ==
'\r' && csv[pos + 1] ==
'\n') {
505 if (csv[pos] ==
'\"') {
509 if (!isStr && csv[pos] ==
',' || csv[pos] ==
'\r' && csv[pos + 1] ==
'\n') {
510 if (i == 0 && csv[pos] ==
',') {
523 char buf[MAX_ROUTE_NAME_LEN];
524 int len =
read(buf, &csv[pos],
sizeof(buf));
528 if (strncmp(
mSubRoutes[i].mName, buf,
sizeof(buf)) == 0) {
534 strncpy(firstFreeRoute->
mName, buf,
sizeof(firstFreeRoute->
mName));
542 pos +=
read(buf, &csv[pos],
sizeof(buf));
545 static int unusedLocal[] = { 0, 0, 0, 0 };
547 static const char *l_actionName[] = {
555 CSV_ACTION_ICE_SLOPE,
556 CSV_ACTION_SWITCH_BLOCK,
557 CSV_ACTION_QUICKSAND,
562 CSV_ACTION_RIGHT_LADDER,
563 CSV_ACTION_LEFT_LADDER,
564 CSV_ACTION_ROCK_LADDER,
565 CSV_ACTION_ROPE_LADDER,
578 ACTION_TYPE_ICE_SLOPE,
579 ACTION_TYPE_SWITCH_BLOCK,
580 ACTION_TYPE_QUICKSAND,
585 ACTION_TYPE_RIGHT_LADDER,
586 ACTION_TYPE_LEFT_LADDER,
587 ACTION_TYPE_ROCK_LADDER,
588 ACTION_TYPE_ROPE_LADDER,
594 while (l_actionName[i] !=
nullptr) {
595 if (strcmp(l_actionName[i], buf) == 0) {
605 if (csv[pos] ==
'\r' && csv[pos + 1] ==
'\n') {
610 if (csv[pos] ==
'"') {
618 if (csv[pos] ==
',' || csv[pos] ==
'"' || csv[pos] ==
'\r' && csv[pos + 1] ==
'\n') {
627 if (strcmp(buf,
"A") == 0) {
629 }
else if (strcmp(buf,
"B") == 0) {
631 }
else if (strcmp(buf,
"C") == 0) {
635 if (csv[pos] ==
'\"') {
639 if (!isStr && csv[pos] ==
',' || csv[pos] ==
'\r' && csv[pos + 1] ==
'\n') {
648 if (strcmp(
mSubRoutes[i].mName, route) == 0) {
652 return ACTION_TYPE_NONE;
657 if (strcmp(
mPoints[i].mName, pointName) == 0) {
665 nw4r::g3d::ResMdl res = model.getResMdl();
666 for (
int i = 0; i < res.GetResNodeNumEntries(); i++) {
667 nw4r::g3d::ResNode node = res.GetResNode(i);
668 const char *name = node.GetName();
669 if (name[0] ==
'K') {
677 nw4r::g3d::ResMdl res = model.getResMdl();
678 for (
int i = 0; i < res.GetResNodeNumEntries(); i++) {
679 nw4r::g3d::ResNode node = res.GetResNode(i);
680 const char *name = node.GetName();
681 if (strlen(name) != 9) {
684 if (name[0] ==
'R' && name[4] >=
'0' && name[4] <=
'9' && name[8] >=
'0' && name[8] <=
'9') {
687 char startPoint[MAX_POINT_NAME_LEN];
688 char endPoint[MAX_POINT_NAME_LEN];
710 return mPoints[idx].mOpenPointNameRegular[openPointIdx];
712 return mPoints[idx].mOpenPointNameSecret[openPointIdx];
718 return mPoints[idx].mOpenPointNumRegular;
720 return mPoints[idx].mOpenPointNumSecret;
726 return mPoints[idx].mRouteNameRegular[openRouteIdx];
728 return mPoints[idx].mRouteNameSecret[openRouteIdx];
734 return mPoints[idx].mOpenRouteNumRegular;
736 return mPoints[idx].mOpenRouteNumSecret;
741 return mPoints[idx].mFlags & flags;
745 return mPoints[idx].mFlagsEnemy & flags;
757 return mRoutes[idx].mChildPoints[childIdx];
770 strncmp(subRoutePointA, pointA, 4) == 0 && strncmp(subRoutePointB, pointB, 4) == 0 ||
771 strncmp(subRoutePointB, pointA, 4) == 0 && strncmp(subRoutePointA, pointB, 4) == 0
781 return mRoutes[idx].mChildPointNum;
790 return mPoints[idx].mFlagDataNumRegular;
792 return mPoints[idx].mFlagDataNumSecret;
798 return mPoints[idx].mFlagDataRegular[animIdx];
800 return mPoints[idx].mFlagDataSecret[animIdx];
805 route->
mChildPoints =
new char[childCount][MAX_POINT_NAME_LEN];
806 for (
int i = 0; i < childCount; i++) {
818 static int s_Level = 0;
819 bool success =
false;
826 if (s_Level >= maxLevel) {
832 char routeStartPoint[MAX_POINT_NAME_LEN];
833 char routeEndPoint[MAX_POINT_NAME_LEN];
835 dWmLib::GetStartPointNameFromRouteName(
mSubRoutes[i].mName, routeStartPoint);
836 if (strncmp(routeStartPoint, startPointName, ARRAY_MAX_STRLEN(routeStartPoint)) == 0) {
837 dWmLib::GetEndPointNameFromRouteName(
mSubRoutes[i].mName, routeEndPoint);
838 if (strncmp(routeEndPoint, endPointName, ARRAY_MAX_STRLEN(routeEndPoint)) == 0) {
860 static int s_Level = 0;
866 bool success =
false;
868 if (s_Level >= maxLevel) {
874 char routeStartPoint[MAX_POINT_NAME_LEN];
875 char routeEndPoint[MAX_POINT_NAME_LEN];
877 dWmLib::GetStartPointNameFromRouteName(
mSubRoutes[i].mName, routeStartPoint);
878 if (strncmp(routeStartPoint, startPointName, ARRAY_MAX_STRLEN(routeStartPoint)) == 0) {
879 dWmLib::GetEndPointNameFromRouteName(
mSubRoutes[i].mName, routeEndPoint);
880 if (strncmp(routeEndPoint, endPointName, ARRAY_MAX_STRLEN(routeEndPoint)) == 0) {
899 nw4r::g3d::ResNodeData *nodeData = (nw4r::g3d::ResNodeData *) (node.ptr());
900 nw4r::g3d::ResNode curr;
902 curr = nw4r::g3d::ResNode(nodeData).GetChildNode();
904 while (curr.IsValid()) {
906 curr = curr.GetChildNode();
909 if (count <
mRoutes[routeIdx].mChildPointNum) {
913 curr = nw4r::g3d::ResNode(nodeData).GetChildNode();
914 mRoutes[routeIdx].mChildPointNum = 0;
915 while (curr.IsValid()) {
916 strncpy(
mRoutes[routeIdx].mChildPoints[
mRoutes[routeIdx].mChildPointNum], curr.GetName(), MAX_POINT_NAME_LEN);
917 mRoutes[routeIdx].mChildPointNum++;
918 curr = curr.GetChildNode();
923 static char s_Tmp[MAX_POINT_NAME_LEN + 1];
927 for (
int i = 0; i < pointNum / 2; i++) {
928 int otherIdx = pointNum - i - 1;
929 strncpy(s_Tmp, route->
mChildPoints[i], MAX_POINT_NAME_LEN);
931 strncpy(route->
mChildPoints[otherIdx], s_Tmp, MAX_POINT_NAME_LEN);
937 bool lineEnd =
false;
938 if (csv[pos] ==
'\r' && csv[pos + 1] ==
'\n') {
u32 GetPointFlags(int idx, PointFlag_e flags) const
Returns the flags ANDed with flags.
Route_s mRoutes[(64)]
The loaded route data.
SubRoute_s mSubRoutes[(160)]
The loaded subroute data.
int GetOpenPointNum(bool regularExit, int idx) const
Returns the number of points that are opened from a regular or secret exit from this point.
bool findSubRoutesForRoute(const char *startPointName, const char *endPointName, Route_s *route, int maxLevel, bool resetLevel=true)
Searches the subroute graph for a path between two points and writes the length of the path to route.
virtual ~dCsvData_c()
Destroys the class.
bool isLineEnd(char *csv, int pos)
Returns whether the the CSV has a line ending at the specified position.
const char * GetRouteAnimName(bool regularExit, int idx, int animIdx)
Returns the value of a flag data entry for a point.
ActionType_e GetActionLabel(const char *route)
Gets the action type for a given route name.
const char * GetOpenRouteName(bool regularExit, int idx, int openRouteIdx) const
Returns the name of a route that is opened from a regular or secret exit from this point.
int GetPointNum(int idx)
Returns the number of points that are part of a route at the specified index.
void ReadPointType(char *csv, int &pos)
Reads a point type from a CSV entry.
int mWorld
The world number for which to load the point and route data.
void RouteInfoInit()
Resets all currently loaded point and route data.
int GetOpenRouteNum(bool regularExit, int idx) const
Returns the number of routes that are opened from a regular or secret exit from this point.
const char * GetChildPointName(int idx, int childIdx)
Returns the name of a point that is part of a route at the specified index.
void ReadRouteFlag(char *csv, int &pos)
Reads the route flag data from a CSV entry.
int mSubrouteCount
The number of loaded subroutes in mSubRoutes.
int mRouteCount
The number of loaded routes in mRoutes.
void ReadOpenRouteName(char *csv, int &pos, bool regularExit)
Reads an open route name from a CSV entry.
u32 GetSubRouteFlag(int idx)
Returns the flags for a route at the specified index.
int GetSubRouteIdx(const char *pointA, const char *pointB)
Returns the index of a route connecting two points.
int mPointCount
The number of loaded points in mPoints.
void ReadPointName(char *csv, int &pos)
Reads a point name from a CSV entry.
const char * GetPointName(int idx) const
Returns the name of a point at the specified index.
const char * GetOpenPointName(bool regularExit, int idx, int openPointIdx) const
Returns the name of a point that is opened from a regular or secret exit from this point.
void SetRouteInfo(const m3d::mdl_c &model)
Creates a route from a model and adds it to the route list.
void initialize(int world, int subworld)
Initializes the class and loads the CSV data for the specified world and subworld.
void ReadOpenPointName(char *csv, int &pos, bool regularExit)
Reads an open point name from a CSV entry.
u32 GetEnemyPointFlags(int idx, EnemyFlag_e flags) const
Returns the enemy flags ANDed with flags.
static void initRouteStruct(Route_s *route, int childCount)
Initializes a route with the specified number of child points.
void ReadCsvData()
Loads the CSV point and route data for the specified world and subworld.
void ReadAnimeRouteName(char *csv, int &pos)
Reads a route name from a CSV entry.
const char * GetRouteName(int idx)
Returns the name of a route at the specified index.
int GetIndexFromPointName(const char *pointName)
Gets the index of a point.
Point_s mPoints[(192)]
The loaded point data.
const char * GetSubRouteName(int idx)
Returns the name of a subroute at the specified index.
bool appendChildFromSubRoute(const char *startPointName, const char *endPointName, Route_s *route, int maxLevel, bool resetLevel=true)
Searches the subroute graph for a path between two points and appends the child points to route.
int GetRouteAnimNum(bool regularExit, int idx)
Returns the number of flag data entries for a point.
int mSubworld
The subworld number for which to load the point and route data.
void appendChildFromModel(const nw4r::g3d::ResNode &node, int)
Appends the child points of a route from a model to route.
void ReadFlagData(char *csv, int &pos, bool regularExit)
Reads the point flag data from a CSV entry.
static void destroyRouteStruct(Route_s *route)
Destroys a route and frees its child point data.
void ReadAction(char *csv, int &pos)
Reads a route action type from a CSV entry.
void addKeyPoint(const m3d::mdl_c &model)
Adds a key point from a model.
u32 GetPointParam(int idx)
Returns the parameter value for this point.
void adjustChildInfo(Route_s *route)
Reverses the order of the child points of a route.
A higher-level archive resource management class.
nw4r::g3d::ResFile getRes(const char *arcName, const char *resPath) const
Gets a resource.
static dResMng_c * m_instance
The instance of this class.
nw4r::g3d::ResFile getResSilently(const char *arcName, const char *resPath) const
Gets a resource without logging a message if the resource is not found.
int read(char *buffer, const char *csv, int bufferSize)
Reads a single CSV field into a buffer.
@ STAGE_START_KINOKO_HOUSE
The toad house on the starting node of each world.
Contains the points of a route on the world map.
int mChildPointNum
The number of occupied entries in mChildPoints.
char(* mChildPoints)[(5)]
The points that make up the route.
int mNumSubroutes
The number of subroutes this route is made up of.
Contains the data for a point-to-point route on the world map.
char mName[(10)]
The name of the route.