| 138 | } |
| 139 | |
| 140 | bool NFS4::LoadFRD(const std::string &frd_path, const std::string &track_name, const std::shared_ptr<TRACK> &track) { |
| 141 | ifstream ar(frd_path, ios::in | ios::binary); |
| 142 | uint32_t nPos; |
| 143 | unsigned char ptrspace[44]; // some useless data from HS FRDs |
| 144 | |
| 145 | char header[28]; /* file header */ |
| 146 | SAFE_READ(ar, header, 28); // header & numblocks |
| 147 | SAFE_READ(ar, &track->nBlocks, 4); |
| 148 | track->nBlocks++; |
| 149 | if ((track->nBlocks < 1) || (track->nBlocks > 500)) return false; // 1st sanity check |
| 150 | |
| 151 | track->trk = new TRKBLOCK[track->nBlocks](); |
| 152 | track->poly = new POLYGONBLOCK[track->nBlocks](); |
| 153 | track->xobj = new XOBJBLOCK[4 * track->nBlocks + 1](); |
| 154 | |
| 155 | SAFE_READ(ar, &nPos, 4); // choose between NFS3 & NFSHS |
| 156 | if (nPos > 5000) track->bHSMode = false; |
| 157 | else if (((nPos + 7) / 8) == track->nBlocks) track->bHSMode = true; |
| 158 | else return false; // unknown file type |
| 159 | |
| 160 | // emulate the COL file |
| 161 | memcpy(track->col.collID, "COLL", 4); |
| 162 | track->col.version = 11; |
| 163 | track->col.fileLength = 36 * nPos + 48; |
| 164 | track->col.nBlocks = 2; |
| 165 | track->col.xbTable[0] = 8; |
| 166 | track->col.xbTable[1] = 24; |
| 167 | // fake a texture table with only one entry to please NFS3_4/T3ED |
| 168 | track->col.textureHead.size = 16; |
| 169 | track->col.textureHead.xbid = XBID_TEXTUREINFO; |
| 170 | track->col.textureHead.nrec = 1; |
| 171 | track->col.texture = new COLTEXTUREINFO(); |
| 172 | // vroad XB |
| 173 | track->col.vroadHead.size = 8 + 36 * nPos; |
| 174 | track->col.vroadHead.xbid = XBID_VROAD; |
| 175 | track->col.vroadHead.nrec = (uint16_t) nPos; |
| 176 | track->col.vroad = new COLVROAD[track->nBlocks * 8](); |
| 177 | track->col.hs_extra = new uint32_t[7 * nPos]; |
| 178 | |
| 179 | for (uint32_t i = 0; i < nPos; i++) { |
| 180 | COLVROAD vr = track->col.vroad[i]; |
| 181 | HS_VROADBLOCK vroadblk; |
| 182 | ar.read((char *) &vroadblk, 84); |
| 183 | vr.refPt.x = (long) (vroadblk.refPt.x * 65536); |
| 184 | vr.refPt.z = (long) (vroadblk.refPt.z * 65536); |
| 185 | vr.refPt.y = (long) (vroadblk.refPt.y * 65536); |
| 186 | // a wild guess |
| 187 | vr.unknown = (uint32_t) ((vroadblk.unknown2[3] & 0xFFFF) + // unknownLanes[2] |
| 188 | ((vroadblk.unknown2[4] & 0xF) << 16) + // wallKinds[0] |
| 189 | ((vroadblk.unknown2[4] & 0xF00) << 20)); // wallKinds[1] |
| 190 | if (vroadblk.normal.x >= 1.0) vr.normal.x = 127; |
| 191 | else vr.normal.x = (signed char) (vroadblk.normal.x * 128); |
| 192 | if (vroadblk.normal.z >= 1.0) vr.normal.z = 127; |
| 193 | else vr.normal.z = (signed char) (vroadblk.normal.z * 128); |
| 194 | if (vroadblk.normal.y >= 1.0) vr.normal.y = 127; |
| 195 | else vr.normal.y = (signed char) (vroadblk.normal.y * 128); |
| 196 | if (vroadblk.forward.x >= 1.0) vr.forward.x = 127; |
| 197 | else vr.forward.x = (signed char) (vroadblk.forward.x * 128); |
nothing calls this directly
no outgoing calls
no test coverage detected