mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Let a want reach RivaTuner Statistics Server's profile only once it stayed two polls, and write nothing before the first host present.
A want that flips between a limit and kept-out created and removed RTSS's profile at each flip: with a driver's low latency vk_lowlat_on() is 0 before the first swapchain and during every swapchain rebuild, so a warm start without the boot screen wrote the profile and removed it a poll later, and a poll that fell into a rebuild did the same (lane A's probe: 6 creations and 5 removals for a want flipping each poll, 1 and 1 at start before RTSS hooked the game). rtss_decide now counts the polls in a row a want stayed: a limit goes into the profile and a kept-out want puts it back only after RTSS_SETTLE_POLLS (2), while standing aside still ends at once (rtss_limit_active compares the want), and nothing is written before the first host present (RTSS_WHY_NO_PRESENT). A limit change reaches the profile up to a second later; the game's limiter holds the new limit meanwhile. The created and removed lines were numbered before. Not reproduced before the change. rtss_limit_check (T8: kept out for one poll and for two, a second reason, a limit again; T9: 20 flips after a written limit give no write or put back, 20 from the start none, flips every two polls act; no write while no host present) and rtss_worker_check (churn_run and every scenario that now settles) pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -190,14 +190,17 @@ static void why_is(const RtssOut *o, const RtssState *s, const char *want, int l
|
||||
#define WHY(o, r, text) why_is(&(o), &(r).s, text, __LINE__)
|
||||
|
||||
// RTSS's injection delay: it runs but has not hooked the game for 30 polls. The limit goes into the profile at the
|
||||
// first poll, with no second write. Once RTSS lists the game the game's limiter stands aside only after RTSS has seen
|
||||
// its Vulkan presents, read the profile and measured a period of its frames lately.
|
||||
// second poll (the first sees the want new), with no second write. Once RTSS lists the game the game's limiter stands
|
||||
// aside only after RTSS has seen its Vulkan presents, read the profile and measured a period of its frames lately.
|
||||
static void injection_delay(void) {
|
||||
Run r;
|
||||
run_init(&r);
|
||||
r.listed = 0;
|
||||
RtssOut o = step(&r, 60000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && !o.holds && o.why == RTSS_WHY_NOT_LISTED, "written at once, not held yet");
|
||||
CHECK(o.act == RTSS_DO_NOTHING && !o.holds && o.why == RTSS_WHY_SETTLING, "a new want: not written yet");
|
||||
WHY(o, r, "a new limit: RivaTuner Statistics Server gets it once it stays");
|
||||
o = step(&r, 60000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && !o.holds && o.why == RTSS_WHY_NOT_LISTED, "written, not held yet");
|
||||
CHECK(r.st.firsts == 1 && r.s.applied == 60000 && r.s.changed, "the first write of the run");
|
||||
for (int i = 0; i < 30; i++) o = step(&r, 60000);
|
||||
CHECK(r.st.applies == 1 && !o.holds && o.why == RTSS_WHY_NOT_LISTED, "no write while not listed");
|
||||
@@ -227,6 +230,7 @@ static void quit(void) {
|
||||
Run r;
|
||||
run_init(&r);
|
||||
step(&r, 60000);
|
||||
step(&r, 60000);
|
||||
RtssOut o = step(&r, 60000);
|
||||
CHECK(o.holds, "held");
|
||||
r.running = 0;
|
||||
@@ -243,6 +247,7 @@ static void readonly(void) {
|
||||
Run r;
|
||||
run_init(&r);
|
||||
r.st.readonly = 1;
|
||||
step(&r, 60000);
|
||||
RtssOut o = step(&r, 60000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && !o.holds && o.why == RTSS_WHY_FAILED && r.s.fail == RTSS_FAIL_READONLY, "failed");
|
||||
CHECK(!r.s.changed, "nothing of the run in the profile");
|
||||
@@ -252,27 +257,32 @@ static void readonly(void) {
|
||||
}
|
||||
|
||||
// A limit out of RTSS's range: refused and kept by the game; the earlier limit of this run is cleared to none; a limit
|
||||
// in range goes to RTSS at once.
|
||||
// in range goes to RTSS once it stays.
|
||||
static void refused(void) {
|
||||
Run r;
|
||||
run_init(&r);
|
||||
r.st.refuse_above = 200000;
|
||||
step(&r, 60000);
|
||||
step(&r, 60000);
|
||||
step(&r, 240000);
|
||||
RtssOut o = step(&r, 240000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && !o.holds && o.why == RTSS_WHY_REFUSED, "refused");
|
||||
CHECK(r.s.refused == 240000 && r.s.applied == 0 && r.st.clears == 1 && r.st.holds == 0, "the 60 cleared to none");
|
||||
for (int i = 0; i < 5; i++) o = step(&r, 240000);
|
||||
CHECK(r.st.applies == 2 && o.why == RTSS_WHY_REFUSED && !o.holds, "not written again");
|
||||
o = step(&r, 144000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && !o.holds && r.st.holds == 144000, "144 at once");
|
||||
CHECK(o.act == RTSS_DO_NOTHING && o.why == RTSS_WHY_SETTLING, "144 settles first");
|
||||
o = step(&r, 144000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && !o.holds && r.st.holds == 144000, "144 written");
|
||||
o = step(&r, 144000);
|
||||
CHECK(o.holds, "held from the next poll");
|
||||
CHECK(r.st.firsts == 1, "one first write in the run (%d)", r.st.firsts);
|
||||
o = step(&r, 240000);
|
||||
CHECK(o.act == RTSS_DO_NOTHING && o.why == RTSS_WHY_REFUSED, "the refused limit stays with the game");
|
||||
CHECK(o.act == RTSS_DO_NOTHING && o.why == RTSS_WHY_REFUSED, "the refused limit stays with the game at once");
|
||||
// refused as the run's first write: the profile is the run's from then on
|
||||
run_init(&r);
|
||||
r.st.refuse_above = 200000;
|
||||
step(&r, 240000);
|
||||
o = step(&r, 240000);
|
||||
CHECK(o.why == RTSS_WHY_REFUSED && r.s.changed && r.st.clears == 1, "a first refusal clears too, as it stands");
|
||||
}
|
||||
@@ -319,7 +329,7 @@ static void frame_count(void) {
|
||||
// two periods over, then one under: the count starts again
|
||||
run_init(&r);
|
||||
r.frames = 144;
|
||||
for (int i = 0; i < 6; i++) step(&r, 60000);
|
||||
for (int i = 0; i < 7; i++) step(&r, 60000);
|
||||
CHECK(r.s.over == 2, "two periods over (%d)", r.s.over);
|
||||
r.frames = 60;
|
||||
for (int i = 0; i < 2; i++) step(&r, 60000);
|
||||
@@ -327,22 +337,25 @@ static void frame_count(void) {
|
||||
// a want that changed while the poll ran: nothing decided, the count waits
|
||||
run_init(&r);
|
||||
r.frames = 144;
|
||||
for (int i = 0; i < 4; i++) step(&r, 60000);
|
||||
for (int i = 0; i < 5; i++) step(&r, 60000);
|
||||
o = step_ex(&r, 60000, 0);
|
||||
CHECK(o.why == RTSS_WHY_NEWER && !o.holds && o.act == RTSS_DO_NOTHING && r.s.over == 1, "a newer want: no count");
|
||||
}
|
||||
|
||||
// No picture went out for 200 ms (a minimised window, a frame hold) or none yet: RTSS has nothing to hold, and the
|
||||
// game's limiter takes the limit back until pictures go out again.
|
||||
// game's limiter takes the limit back until pictures go out again. Before the first picture nothing is written.
|
||||
static void idle(void) {
|
||||
Run r;
|
||||
run_init(&r);
|
||||
r.presenting = 0;
|
||||
step(&r, 60000);
|
||||
RtssOut o = step(&r, 60000);
|
||||
CHECK(!o.holds && o.why == RTSS_WHY_IDLE, "no host present yet");
|
||||
RtssOut o;
|
||||
for (int i = 0; i < 4; i++) o = step(&r, 60000);
|
||||
CHECK(!o.holds && o.why == RTSS_WHY_NO_PRESENT && !r.st.applies, "no host present yet: nothing written");
|
||||
WHY(o, r, "no picture has gone out yet");
|
||||
r.presenting = 1;
|
||||
o = step(&r, 60000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && !o.holds, "written at the first picture, the want having stayed");
|
||||
o = step(&r, 60000);
|
||||
CHECK(o.holds, "held once pictures go out");
|
||||
r.presenting = 0;
|
||||
r.hosted_ns = r.now_ns + 500000000ull - 199000000ull; // the next poll comes 199 ms after the last present
|
||||
@@ -362,16 +375,22 @@ static void kept_out(void) {
|
||||
Run r;
|
||||
run_init(&r);
|
||||
step(&r, 60000);
|
||||
step(&r, 60000);
|
||||
RtssOut o = step(&r, RTSS_OUT_FRAMEGEN);
|
||||
CHECK(o.act == RTSS_DO_NOTHING && o.why == RTSS_WHY_OUT && !o.holds && r.st.holds == 60000,
|
||||
"the game's limiter at once, the profile once the want stays");
|
||||
o = step(&r, RTSS_OUT_FRAMEGEN);
|
||||
CHECK(o.act == RTSS_DO_PUT_BACK && o.why == RTSS_WHY_OUT && !o.holds && r.st.holds == -1, "put back");
|
||||
CHECK(r.st.last_put_back_why == RTSS_WHY_OUT, "the put back says why");
|
||||
o = step(&r, RTSS_OUT_FRAMEGEN);
|
||||
CHECK(o.act == RTSS_DO_NOTHING && r.st.put_backs == 1, "once");
|
||||
o = step(&r, RTSS_OUT_LOWLAT);
|
||||
CHECK(o.act == RTSS_DO_NOTHING && o.mhz == RTSS_OUT_LOWLAT, "a second reason: nothing more");
|
||||
for (int i = 0; i < 3; i++) o = step(&r, RTSS_OUT_LOWLAT);
|
||||
CHECK(o.act == RTSS_DO_NOTHING && o.mhz == RTSS_OUT_LOWLAT && r.st.put_backs == 1, "a second reason: nothing more");
|
||||
WHY(o, r, "RivaTuner Statistics Server kept out: the driver's low latency");
|
||||
o = step(&r, 60000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && !o.holds && r.st.firsts == 2, "written at once, the run's first write again");
|
||||
CHECK(o.act == RTSS_DO_NOTHING && o.why == RTSS_WHY_SETTLING, "a limit again: settles first");
|
||||
o = step(&r, 60000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && !o.holds && r.st.firsts == 2, "written, the run's first write again");
|
||||
o = step(&r, 60000);
|
||||
CHECK(o.holds, "held from the next poll");
|
||||
// kept out from the start: the hooks library is never wanted, and nothing is written or put back
|
||||
@@ -380,13 +399,31 @@ static void kept_out(void) {
|
||||
CHECK(!r.st.loaded && !r.st.applies && !r.st.put_backs && o.why == RTSS_WHY_OUT, "read only");
|
||||
}
|
||||
|
||||
// Low latency switching on and off at every poll: each switch writes or puts back, as it stands.
|
||||
// Low latency switching on and off at every poll (a swapchain rebuild, the time before the first swapchain): the want
|
||||
// never stays two polls, so the profile keeps the limit written before, and the game's limiter holds the frames while
|
||||
// the want is new. From the start, the same flips write nothing.
|
||||
static void churn(void) {
|
||||
Run r;
|
||||
run_init(&r);
|
||||
step(&r, 60000);
|
||||
step(&r, 60000);
|
||||
RtssOut o;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
o = step(&r, i & 1 ? 60000 : RTSS_OUT_LOWLAT);
|
||||
CHECK(!(i & 1) ? !o.holds : 1, "kept out at poll %d: the game's limiter", i);
|
||||
}
|
||||
CHECK(r.st.applies == 1 && !r.st.put_backs && r.st.holds == 60000, "%d writes, %d put backs", r.st.applies,
|
||||
r.st.put_backs);
|
||||
o = step(&r, 60000);
|
||||
CHECK(o.holds && r.st.applies == 1, "held once the limit stays");
|
||||
run_init(&r);
|
||||
for (int i = 0; i < 20; i++) step(&r, i & 1 ? 60000 : RTSS_OUT_LOWLAT);
|
||||
CHECK(r.st.applies == 11 && r.st.put_backs == 10, "%d writes, %d put backs", r.st.applies, r.st.put_backs);
|
||||
CHECK(!r.st.applies && !r.st.put_backs, "from the start: nothing written");
|
||||
// a flip every two polls is a want that stays: each one acts
|
||||
run_init(&r);
|
||||
for (int i = 0; i < 8; i++) step(&r, i & 2 ? RTSS_OUT_LOWLAT : 60000);
|
||||
CHECK(r.st.applies == 2 && r.st.put_backs == 2, "two polls each: %d writes, %d put backs", r.st.applies,
|
||||
r.st.put_backs);
|
||||
}
|
||||
|
||||
// A movie under RTSS: the want stays the play limit and the game's pacer holds the movie. At a limit of 144 the profile
|
||||
@@ -396,6 +433,7 @@ static void movie(void) {
|
||||
Run r;
|
||||
run_init(&r);
|
||||
step(&r, 144000);
|
||||
step(&r, 144000);
|
||||
r.movie_mhz = 60000;
|
||||
RtssOut o = step(&r, 144000);
|
||||
CHECK(o.act == RTSS_DO_NOTHING && !o.holds && o.why == RTSS_WHY_MOVIE, "a movie at 144: no write, the pacer's");
|
||||
@@ -407,6 +445,7 @@ static void movie(void) {
|
||||
CHECK(o.act == RTSS_DO_NOTHING && o.holds && o.why == RTSS_WHY_HOLDS && r.st.applies == 1, "held again after it");
|
||||
run_init(&r);
|
||||
step(&r, 40000);
|
||||
step(&r, 40000);
|
||||
r.movie_mhz = 60000;
|
||||
o = step(&r, 40000);
|
||||
CHECK(o.act == RTSS_DO_APPLY && o.mhz == 0 && !o.holds && o.why == RTSS_WHY_MOVIE && r.st.holds == 0,
|
||||
|
||||
@@ -379,6 +379,11 @@ static void ask(int64_t mhz) { // a want at a present; the first one that star
|
||||
CHECK(WaitForMultipleObjects(2, h, FALSE, 5000) != WAIT_TIMEOUT, "the worker did not finish its first poll");
|
||||
}
|
||||
}
|
||||
static void settle(int64_t mhz) { // a new want, then the polls it takes to reach the profile (RTSS_SETTLE_POLLS)
|
||||
ask(mhz);
|
||||
poll();
|
||||
poll();
|
||||
}
|
||||
static void show(const char *what) {
|
||||
printf(" %s: profile %s %lu/%lu; active %d; state %d; saves %ld deletes %ld updates %ld loads %ld\n", what,
|
||||
own.exists ? "exists," : "absent,", own.limit, own.denom, rtss_limit_active(), rtss_limit_state(), saves,
|
||||
@@ -498,8 +503,7 @@ static void kept_lowlat_then_limit(void) {
|
||||
"the driver's low latency"),
|
||||
"the two-limiter line names the game's profile and low latency");
|
||||
CHECK(!loads, "kept out, the hooks library is never loaded");
|
||||
ask(60000);
|
||||
poll();
|
||||
settle(60000);
|
||||
show("low latency off, limit 60");
|
||||
CHECK(loads == 1 && own.exists && own.limit == 60, "the limit goes into the profile once RTSS is let in");
|
||||
poll();
|
||||
@@ -525,6 +529,7 @@ static void active_race(void) {
|
||||
app_set(1, 0xA, 1000, 2000, 60);
|
||||
ask(60000);
|
||||
poll();
|
||||
poll();
|
||||
CHECK(rtss_limit_active(), "RTSS limits at 60");
|
||||
quiet = 1, free_run = 1;
|
||||
SetEvent(tick);
|
||||
@@ -555,6 +560,7 @@ static void active_logged(void) {
|
||||
app_set(1, 0xA, 1000, 2000, 60);
|
||||
during_save = framegen_on;
|
||||
ask(60000);
|
||||
poll();
|
||||
show("frame generation switched on during the first write");
|
||||
CHECK(own.exists && own.limit == 60, "the limit went into the profile");
|
||||
CHECK(!rtss_limit_active(), "the game's limiter paces the kept-out want");
|
||||
@@ -589,11 +595,9 @@ static void round_logged_whole(void) {
|
||||
show("display at 59.94 Hz, RTSS without a denominator");
|
||||
CHECK(own.limit == 60, "rounded to whole frames");
|
||||
CHECK(logged("profile ocarina.exe limits to 60/1 (60.000 fps; the game asked 59.940)"), "the log names 60/1");
|
||||
ask(143856);
|
||||
poll();
|
||||
settle(143856);
|
||||
CHECK(logged("profile ocarina.exe limits to 144/1 (144.000 fps; the game asked 143.856)"), "the log names 144/1");
|
||||
ask(60000);
|
||||
poll();
|
||||
settle(60000);
|
||||
CHECK(logged("profile ocarina.exe limits to 60.000 fps\n"), "a whole limit as it is");
|
||||
}
|
||||
|
||||
@@ -712,9 +716,9 @@ static void refused_run(void) {
|
||||
app_set(1, 0xA, 1000, 2000, 60);
|
||||
ask(60000);
|
||||
poll();
|
||||
CHECK(own.limit == 60 && rtss_limit_active(), "60 taken");
|
||||
ask(240000);
|
||||
poll();
|
||||
CHECK(own.limit == 60 && rtss_limit_active(), "60 taken");
|
||||
settle(240000);
|
||||
show("240 refused");
|
||||
CHECK(own.exists && own.limit == 0, "the earlier limit of this run is cleared to none");
|
||||
CHECK(!rtss_limit_active() && rtss_limit_state() == 0, "the game's limiter keeps 240");
|
||||
@@ -722,15 +726,15 @@ static void refused_run(void) {
|
||||
poll();
|
||||
poll();
|
||||
CHECK(saves == s0, "the refused limit is not written again");
|
||||
ask(144000);
|
||||
poll();
|
||||
settle(144000);
|
||||
show("144 after the refusal");
|
||||
CHECK(own.limit == 144, "144 written at once");
|
||||
CHECK(own.limit == 144, "144 written once it stayed");
|
||||
poll();
|
||||
CHECK(rtss_limit_active(), "and held from the next poll");
|
||||
ask(240000);
|
||||
CHECK(!rtss_limit_active(), "240 with the game at once");
|
||||
poll();
|
||||
CHECK(!rtss_limit_active(), "240 stays with the game");
|
||||
CHECK(!rtss_limit_active() && own.limit == 144, "240 stays with the game");
|
||||
}
|
||||
|
||||
// RTSS lists the game but lets it run well over the limit: three fresh periods in a row over 1.05 times the limit, each
|
||||
@@ -738,15 +742,14 @@ static void refused_run(void) {
|
||||
static void over_run(void) {
|
||||
app_set(1, 0xA, 1000, 2000, 144);
|
||||
ask(60000);
|
||||
for (int i = 0; i < 3; i++) poll();
|
||||
for (int i = 0; i < 4; i++) poll();
|
||||
CHECK(rtss_limit_active() && own.exists, "two periods over: RTSS still limits");
|
||||
poll();
|
||||
show("three periods at 144 fps with the limit at 60");
|
||||
CHECK(rtss_limit_state() == 3 && !rtss_limit_active(), "the menu says RTSS does not limit the game");
|
||||
CHECK(!own.exists, "the profile is put back");
|
||||
CHECK(logged("RivaTuner Statistics Server measures 144.0 fps with its limit at 60.000 fps"), "logged");
|
||||
ask(30000);
|
||||
poll();
|
||||
settle(30000);
|
||||
CHECK(saves == 1 && rtss_limit_state() == 3, "out for the run");
|
||||
}
|
||||
// 1.05 times the limit is not caught; a period RTSS no longer moves (the limit lowered, then the window minimised)
|
||||
@@ -796,6 +799,7 @@ static void idle_run(void) {
|
||||
app_set(1, 0xA, 1000, 2000, 60);
|
||||
ask(60000);
|
||||
poll();
|
||||
poll();
|
||||
CHECK(rtss_limit_active(), "RTSS limits");
|
||||
presenting = 0;
|
||||
poll();
|
||||
@@ -843,26 +847,36 @@ static void library_run(void) {
|
||||
CHECK(logged("RivaTuner Statistics Server's hooks library did not load"), "logged");
|
||||
}
|
||||
|
||||
// Low latency switching on and off at every poll (the want flips between a limit and kept out): each switch writes or
|
||||
// puts back the profile, as it stands, and the log numbers each creation and removal so a play-test can count them.
|
||||
// Low latency switching on and off at every poll (the want flips between a limit and kept out, as at each swapchain
|
||||
// rebuild): a want acts on the profile only once it stayed two polls, so the flips write and remove nothing, and the
|
||||
// game's limiter holds each kept-out want at once. A want that stays two polls each time does act, and the log numbers
|
||||
// each creation and removal so a play-test can count them.
|
||||
static void churn_run(void) {
|
||||
app_set(1, 0xA, 1000, 2000, 60);
|
||||
ask(60000);
|
||||
poll();
|
||||
poll();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ask(i & 1 ? 60000 : RTSS_OUT_LOWLAT);
|
||||
if (!(i & 1)) CHECK(!rtss_limit_active(), "kept out at flip %d: the game's limiter at once", i);
|
||||
poll();
|
||||
}
|
||||
show("ten polls with the want flipping");
|
||||
CHECK(created == 1 && removed == 0, "%ld creations, %ld removals", created, removed);
|
||||
poll();
|
||||
CHECK(created == 6 && removed == 5, "%ld creations, %ld removals", created, removed);
|
||||
CHECK(rtss_limit_active(), "RTSS limits once the limit stays");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
settle(RTSS_OUT_LOWLAT);
|
||||
settle(60000);
|
||||
}
|
||||
show("four flips of two polls each");
|
||||
CHECK(created == 5 && removed == 4, "%ld creations, %ld removals", created, removed);
|
||||
CHECK(logged("created; it goes away when the game closes (creation 1 this run)\n") &&
|
||||
logged("(creation 6 this run)\n") && !logged("(creation 7"),
|
||||
logged("(creation 5 this run)\n") && !logged("(creation 6"),
|
||||
"the created lines are numbered");
|
||||
CHECK(logged("removed, as before the game started (removal 1 this run)\n") && logged("(removal 5 this run)\n") &&
|
||||
!logged("(removal 6"),
|
||||
CHECK(logged("removed, as before the game started (removal 1 this run)\n") && logged("(removal 4 this run)\n") &&
|
||||
!logged("(removal 5"),
|
||||
"the removed lines are numbered");
|
||||
CHECK(rtss_limit_active(), "RTSS limits after the last want of a limit");
|
||||
}
|
||||
|
||||
// The state file: the run's first write records the profile as it was, each later one the value written, and the exit's
|
||||
@@ -874,8 +888,7 @@ static void state_record(void) {
|
||||
show("playing at 60");
|
||||
CHECK(own.exists && own.limit == 60 && state_has("\nrtss1 0 0 1 60 1 ocarina.exe\n"), "recorded:\n%s", state());
|
||||
CHECK(!strncmp(state(), "# RivaTuner Statistics Server's profiles", 40), "the header first");
|
||||
ask(144000);
|
||||
poll();
|
||||
settle(144000);
|
||||
CHECK(own.limit == 144 && state_has("\nrtss1 0 0 1 144 1 ocarina.exe\n"), "the line follows:\n%s", state());
|
||||
rtss_limit_restore();
|
||||
show("after the restore");
|
||||
@@ -887,11 +900,9 @@ static void state_player(void) {
|
||||
ask(60000);
|
||||
poll();
|
||||
CHECK(own.limit == 60 && state_has("\nrtss1 1 30 1 60 1 ocarina.exe\n"), "recorded:\n%s", state());
|
||||
ask(RTSS_OUT_LOWLAT); // kept out: put back during the run, and the line goes with it
|
||||
poll();
|
||||
settle(RTSS_OUT_LOWLAT); // kept out: put back during the run, and the line goes with it
|
||||
CHECK(own.limit == 30 && !*state(), "put back, no line:\n%s", state());
|
||||
ask(60000);
|
||||
poll();
|
||||
settle(60000);
|
||||
CHECK(own.limit == 60 && state_has("\nrtss1 1 30 1 60 1 ocarina.exe\n"), "recorded again:\n%s", state());
|
||||
rtss_limit_restore();
|
||||
CHECK(own.exists && own.limit == 30 && !*state(), "the player's 30 back, no line");
|
||||
@@ -904,6 +915,7 @@ static void state_unwritable(void) {
|
||||
app_set(1, 0xA, 1000, 2000, 60);
|
||||
ask(60000);
|
||||
poll();
|
||||
poll();
|
||||
show("no state file");
|
||||
CHECK(own.exists && own.limit == 60 && rtss_limit_active(), "RTSS limits as before");
|
||||
CHECK(logged("rtss-profile.txt could not be written; a crash would leave the game's limit in RivaTuner Statistics "
|
||||
|
||||
Reference in New Issue
Block a user