49 constexpr u32 TEST_HEADER_SIGNATURE = 0x54535448;
50 constexpr u32 TEST_FOOTER_SIGNATURE = 0x54535446;
51 constexpr u16 SUITE_MAJOR_VER = 1;
52 constexpr u16 SUITE_MAX_MINOR_VER = 0;
54 u16 numTestCases = m_stream.read_u16();
55 u16 testMajorVer = m_stream.read_u16();
56 u16 testMinorVer = m_stream.read_u16();
58 if (testMajorVer != SUITE_MAJOR_VER || testMinorVer > SUITE_MAX_MINOR_VER) {
59 PANIC(
"Version not supported! Provided file is %d.%d while Kinoko supports up to %d.%d",
60 testMajorVer, testMinorVer, SUITE_MAJOR_VER, SUITE_MAX_MINOR_VER);
63 for (
u16 i = 0; i < numTestCases; ++i) {
65 if (m_stream.read_u32() != TEST_HEADER_SIGNATURE) {
66 PANIC(
"Invalid binary data for test case!");
69 u16 totalSize = m_stream.read_u16();
72 u16 nameLen = m_stream.read_u16();
73 testCase.name = m_stream.read_string();
74 if (nameLen != testCase.name.size() + 1) {
75 PANIC(
"Test case name length mismatch!");
78 u16 rkgPathLen = m_stream.read_u16();
79 testCase.rkgPath = m_stream.read_string();
80 if (rkgPathLen != testCase.rkgPath.size() + 1) {
81 PANIC(
"Test case RKG Path length mismatch!");
84 u16 krkgPathLen = m_stream.read_u16();
85 testCase.krkgPath = m_stream.read_string();
86 if (krkgPathLen != testCase.krkgPath.size() + 1) {
87 PANIC(
"Test case KRKG Path length mismatch!");
90 testCase.targetFrame = m_stream.read_u16();
93 if (m_stream.read_u32() != TEST_FOOTER_SIGNATURE) {
94 PANIC(
"Invalid binary data for test case!");
97 if (totalSize !=
sizeof(
u16) * 4 + nameLen + rkgPathLen + krkgPathLen) {
98 PANIC(
"Unexpected bytes in test case");
101 m_testCases.push(testCase);
138 PANIC(
"Expected suite/ghost/krkg argument!");
141 std::optional<char *> rkgPath;
142 std::optional<char *> krkgPath;
143 std::optional<u16> target;
145 for (
int i = 0; i < argc; ++i) {
146 std::optional<Host::EOption> flag = Host::Option::CheckFlag(argv[i]);
147 if (!flag || *flag == Host::EOption::Invalid) {
148 WARN(
"Expected a flag! Got: %s", argv[i]);
153 case Host::EOption::Suite: {
155 PANIC(
"Mode was already set!");
160 ASSERT(i + 1 < argc);
163 u8 *data = Abstract::File::Load(argv[++i], size);
166 PANIC(
"Failed to load suite data!");
170 m_stream.setEndian(std::endian::big);
173 case Host::EOption::Ghost:
175 PANIC(
"Mode was already set!");
179 ASSERT(i + 1 < argc);
183 case Host::EOption::KRKG:
185 PANIC(
"Mode was already set!");
189 ASSERT(i + 1 < argc);
190 krkgPath = argv[++i];
193 case Host::EOption::TargetFrame:
194 ASSERT(i + 1 < argc);
196 if (strlen(argv[++i]) > 5) {
197 PANIC(
"Target has too many digits");
199 target = atoi(argv[i]);
200 if (target < 0 || target > std::numeric_limits<u16>::max()) {
201 PANIC(
"Target is out of bounds (expected 0-65535), got %d\n", target);
206 case Host::EOption::Invalid:
208 PANIC(
"Invalid flag!");
213 if (target &&
m_testMode != Host::EOption::Ghost) {
214 PANIC(
"'--framecount' is only supported in a single ghost test");
219 PANIC(
"Missing ghost argument!");
223 PANIC(
"Missing KRKG argument!");
230 m_testCases.emplace(*rkgPath, *rkgPath, *krkgPath, *target);
258 constexpr u32 KRKG_SIGNATURE = 0x4b524b47;
267 u16 mark = *
reinterpret_cast<u16 *
>(krkg + offsetof(
TestHeader, byteOrderMark));
268 std::endian endian = parse<u16>(mark) == 0xfeff ? std::endian::big : std::endian::little;
269 m_stream.setEndian(endian);
271 ASSERT(m_stream.read_u32() == KRKG_SIGNATURE);
273 m_frameCount = m_stream.read_u16();
274 m_versionMajor = m_stream.read_u16();
275 m_versionMinor = m_stream.read_u16();
277 ASSERT(m_stream.read_u32() == m_stream.index());
282 ASSERT(m_testCases.size() == 1);
283 auto &front = m_testCases.front();
284 if (front.targetFrame == 0) {
285 front.targetFrame = m_frameCount;
288 front.targetFrame = std::min(front.targetFrame, m_frameCount);
329 f32 acceleration = 0.0f;
330 f32 softSpeedLimit = 0.0f;
333 f32 raceCompletion = 0.0f;
334 u16 checkpointId = 0;
338 fullRot.read(m_stream);
340 if (m_versionMinor >= Changelog::AddedExtVel) {
341 extVel.
read(m_stream);
344 if (m_versionMinor >= Changelog::AddedIntVel) {
345 intVel.
read(m_stream);
348 if (m_versionMinor >= Changelog::AddedSpeed) {
349 speed = m_stream.read_f32();
350 acceleration = m_stream.read_f32();
351 softSpeedLimit = m_stream.read_f32();
354 if (m_versionMinor >= Changelog::AddedRotation) {
355 mainRot.read(m_stream);
356 angVel2.
read(m_stream);
359 if (m_versionMinor >= Changelog::AddedCheckpoints) {
360 raceCompletion = m_stream.read_f32();
361 checkpointId = m_stream.read_u16();
362 jugemId = m_stream.read_u8();
368 data.fullRot = fullRot;
369 data.extVel = extVel;
370 data.intVel = intVel;
372 data.acceleration = acceleration;
373 data.softSpeedLimit = softSpeedLimit;
374 data.mainRot = mainRot;
375 data.angVel2 = angVel2;
376 data.raceCompletion = raceCompletion;
377 data.checkpointId = checkpointId;
378 data.jugemId = jugemId;
385 auto *
object = Kart::KartObjectManager::Instance()->object(0);
386 const auto &pos =
object->pos();
387 const auto &fullRot =
object->fullRot();
388 const auto &extVel =
object->extVel();
389 const auto &intVel =
object->intVel();
390 f32 speed =
object->speed();
391 f32 acceleration =
object->acceleration();
392 f32 softSpeedLimit =
object->softSpeedLimit();
393 const auto &mainRot =
object->mainRot();
394 const auto &angVel2 =
object->angVel2();
396 const auto &player = System::RaceManager::Instance()->player();
397 f32 raceCompletion = player.raceCompletion();
398 u16 checkpointId = player.checkpointId();
399 u8 jugemId = player.jugemId();
401 switch (m_versionMinor) {
402 case Changelog::AddedCheckpoints:
403 checkDesync(data.raceCompletion, raceCompletion,
"raceCompletion");
404 checkDesync(data.checkpointId, checkpointId,
"checkpointId");
405 checkDesync(data.jugemId, jugemId,
"jugemId");
407 case Changelog::AddedRotation:
408 checkDesync(data.mainRot, mainRot,
"mainRot");
409 checkDesync(data.angVel2, angVel2,
"angVel2");
411 case Changelog::AddedSpeed:
412 checkDesync(data.speed, speed,
"speed");
413 checkDesync(data.acceleration, acceleration,
"acceleration");
414 checkDesync(data.softSpeedLimit, softSpeedLimit,
"softSpeedLimit");
416 case Changelog::AddedIntVel:
417 checkDesync(data.intVel, intVel,
"intVel");
419 case Changelog::AddedExtVel:
420 checkDesync(data.extVel, extVel,
"extVel");
423 checkDesync(data.pos, pos,
"pos");
424 checkDesync(data.fullRot, fullRot,
"fullRot");