mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
adhoc_session.py: --delay, --jitter and --loss for the relay's network simulation
Passes them on as --adhoc-delay, --adhoc-jitter and --adhoc-loss, and documents them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4f80e5c1db
commit
bc7cc87010
2 files changed
+37
-4
No files matched your search
+15
-4
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
# Runs several PPSSPP headless instances of a game against each other over ad hoc, and drives them over
|
||||
# the WebSocket debugger: press buttons, take screenshots, read frame rates. For testing a game's
|
||||
# multiplayer. See docs/adhoc-multiplayer-testing.md.
|
||||
# multiplayer, and for measuring what network delay it tolerates. See docs/adhoc-multiplayer-testing.md.
|
||||
#
|
||||
# python3 Tools/adhoc_session.py start ~/PSP/GAME.iso -n 2 [--state FILE]
|
||||
# python3 Tools/adhoc_session.py start ~/PSP/GAME.iso -n 2 [--delay 50] [--state FILE]
|
||||
# python3 Tools/adhoc_session.py press cross -i 2
|
||||
# python3 Tools/adhoc_session.py wait 3
|
||||
# python3 Tools/adhoc_session.py shot lobby
|
||||
@@ -209,6 +209,12 @@ def cmd_start(args):
|
||||
if n == 1:
|
||||
cmd.append("--adhoc-server")
|
||||
cmd.append("--nickname=" + (names[n - 1] if n <= len(names) else "PPSSPP %d" % n))
|
||||
if args.delay:
|
||||
cmd.append("--adhoc-delay=%d" % args.delay)
|
||||
if args.jitter:
|
||||
cmd.append("--adhoc-jitter=%d" % args.jitter)
|
||||
if args.loss:
|
||||
cmd.append("--adhoc-loss=%d" % args.loss)
|
||||
if args.log:
|
||||
cmd.append("--log")
|
||||
if args.state:
|
||||
@@ -232,10 +238,12 @@ def cmd_start(args):
|
||||
time.sleep(0.1)
|
||||
if inst["port"] is None:
|
||||
sys.exit("Instance %d didn't open a debugger port; see %s" % (inst["n"], inst["log"]))
|
||||
session = {"game": args.game, "instances": instances, "lagSync": not args.no_lag_sync, "p2p": args.p2p}
|
||||
session = {"game": args.game, "instances": instances, "delay": args.delay, "jitter": args.jitter,
|
||||
"loss": args.loss, "lagSync": not args.no_lag_sync, "p2p": args.p2p}
|
||||
with open(session_file(args), "w") as f:
|
||||
json.dump(session, f, indent=1)
|
||||
print("Started %d instances (%s), session in %s" % (args.n, "P2P" if args.p2p else "relay", args.dir))
|
||||
print("Started %d instances (%s%s), session in %s" % (args.n, "P2P" if args.p2p else "relay",
|
||||
", delay %d ms" % args.delay if args.delay else "", args.dir))
|
||||
|
||||
|
||||
def cmd_stop(args):
|
||||
@@ -499,6 +507,9 @@ def build_parser():
|
||||
p.add_argument("-n", type=int, default=2, help="Number of instances (default 2)")
|
||||
p.add_argument("--p2p", action="store_true", help="Talk directly instead of through the relay (needs a loopback address per instance)")
|
||||
p.add_argument("--names", help="Comma-separated nicknames for the instances (default: PPSSPP 1, PPSSPP 2, ...)")
|
||||
p.add_argument("--delay", type=int, default=0, help="Simulated delay in ms on received relay datagrams (each way)")
|
||||
p.add_argument("--jitter", type=int, default=0, help="Up to this many ms more, at random")
|
||||
p.add_argument("--loss", type=int, default=0, help="Percentage of received relay datagrams dropped")
|
||||
p.add_argument("--no-lag-sync", action="store_true", help="Pace once per frame, like the app's default")
|
||||
p.add_argument("--state", help="Savestate to load at boot in every instance")
|
||||
p.add_argument("--memstick", default=DEFAULT_MEMSTICK, help="Memory stick to take the firmware and savedata from")
|
||||
|
||||
@@ -107,6 +107,28 @@ sudo ifconfig lo0 alias 127.0.0.3 up
|
||||
|
||||
`adhoc_session.py start --p2p` checks for them and prints these commands if any are missing.
|
||||
|
||||
## Simulating a slow network
|
||||
|
||||
Three options delay or drop ad hoc data received through the relay, to see how a game copes with a
|
||||
distant player. They're also in the ini, under `[Network]`, for the app.
|
||||
|
||||
| Option | ini | What it does |
|
||||
|---|---|---|
|
||||
| `--adhoc-delay=MS` | `AdhocSimDelayMs` | Each datagram is handed to the game MS milliseconds after it arrived. |
|
||||
| `--adhoc-jitter=MS` | `AdhocSimJitterMs` | Up to MS more, at random. Datagrams stay in order. |
|
||||
| `--adhoc-loss=PERCENT` | `AdhocSimLossPercent` | Datagrams dropped. Through the relay nothing is ever lost otherwise, since it's TCP. |
|
||||
|
||||
`adhoc_session.py start` takes them as `--delay`, `--jitter` and `--loss`, and passes them to every
|
||||
instance. Things to know:
|
||||
|
||||
- **The delay is one way, on the receiving side.** With it on every instance, a round trip takes twice
|
||||
the delay more: `--adhoc-delay=50` turns a 3 ms PDP round trip into 103 ms
|
||||
(pspautotests `net/adhoc/pair/timing`).
|
||||
- **Only PDP data is delayed so far.** PTP connections and the ad hoc server's own messages aren't.
|
||||
- A datagram counts as arrived when the game next looks at its socket (a receive, a poll, a socket
|
||||
list query), not when it actually arrived. Games that poll every frame are measured to within a
|
||||
frame; with lag sync on, that's within a millisecond of emulated time.
|
||||
|
||||
## Measuring
|
||||
|
||||
- `stats` reads each instance's frame rate (`gpu.stats.get`). If vblanks/s is below 60, emulation itself
|
||||
|
||||
Reference in new issue
Block a user