mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Had Claude clean up its own notes.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
1 parent
992b8bd9b6
commit
6bc20ab64b
4 files changed
+141
-82
No files matched your search
@@ -0,0 +1,36 @@
|
||||
# Command-line parsing
|
||||
|
||||
All command-line parsing for both the main app and the headless build belongs in `Core/CmdLine.cpp` /
|
||||
`Core/CmdLine.h` (`CommandLineOptions`), not in the platform entry points (`Windows/main.cpp`,
|
||||
`headless/Headless.cpp`, `UI/NativeApp.cpp`, etc.). Don't re-parse `argv` in those files - add a field
|
||||
to `CommandLineOptions` instead.
|
||||
|
||||
## Declaring an option
|
||||
|
||||
Most options are declared in the `g_autoParams` table in `CmdLine.cpp` as:
|
||||
|
||||
```cpp
|
||||
{offsetof(...), type, longName, shortName, docString, mode}
|
||||
```
|
||||
|
||||
`mode` gates the option to `CmdLineMode::Application`, `::Headless`, or `::Both` (the default if the
|
||||
field is omitted from the initializer).
|
||||
|
||||
The same long name can be reused for both modes with different types and meanings, because a given
|
||||
`Parse()` call only matches params whose mode is `Both` or equal to the current mode. `--log` is the
|
||||
example to know: a `String` "log to FILE" option in Application mode, a `Bool` "full log output" option
|
||||
in Headless mode. They don't collide.
|
||||
|
||||
Options that can be repeated (e.g. `--ignore TESTNAME`, collected into a `std::vector<std::string>`), or
|
||||
that don't fit the generic single-value table, need manual handling in the `else if` chain inside
|
||||
`CommandLineOptions::Parse()` - the same way `--graphics=` and the `boot` filenames are handled.
|
||||
|
||||
## Getting a parsed option into the emulator
|
||||
|
||||
`ApplyToConfig()` is where parsed options are pushed into `g_Config` / `g_logManager`. Prefer wiring a
|
||||
new option through there, so every platform gets it for free, rather than reading `CommandLineOptions`
|
||||
fields ad-hoc at each call site.
|
||||
|
||||
`NativeInit()` in `UI/NativeApp.cpp` still takes `argc`/`argv`, because several platform entry points
|
||||
pass them in, but it shouldn't read them directly: by the time `NativeInit()` runs,
|
||||
`CommandLineOptions` should already hold everything.
|
||||
@@ -121,6 +121,22 @@ A working invocation, and the traps around it:
|
||||
- **To line input injection up with a wall-clock repro, use `cpu.status`'s `us` field** (emulated microseconds), not
|
||||
`ticks`. The PSP's clock frequency is changeable and games do change it - CrossCraft Classic runs at 333MHz, so
|
||||
`ticks / 222000000` is off by a factor of 1.5. `clockHz` is reported alongside.
|
||||
- **`--graphics=software` cannot see "the screen stops updating" bugs.** When HLE writes pixels straight into a
|
||||
display buffer - video decoding, `sceJpeg`, `sceMpegAvcCsc` - the hardware backends only find out because the HLE
|
||||
calls `gpu->PerformWriteFormattedFromMemory()`. The software renderer reads that memory directly and so renders
|
||||
the frame whether or not anything was notified. A missing notification therefore looks perfect under
|
||||
`--graphics=software` and shows up as a frozen screen on every real backend, while the decode logs keep scrolling
|
||||
past as if all were well. Reproduce display bugs on `--graphics=d3d11` or `--graphics=vulkan` (`directx9` is not
|
||||
a valid value) and compare `--screenshot-save=` output, not the log.
|
||||
- **`wsdbg --launch` only works with the headless build.** The app build is a GUI-subsystem exe with no stdout, so
|
||||
the `Listening on port N` line never reaches the launcher and it gives up. Start it yourself with an explicit
|
||||
`--debugger=PORT` and point wsdbg at that port. Note also that `--debugger-run` is `CmdLineMode::Headless`; the
|
||||
app takes plain `--debugger=PORT`.
|
||||
- **`--launch` needs `--log` to find the port.** Without it, headless prints only emulated printfs, so the
|
||||
`Listening on port N` NOTICE never appears and `--launch` fails with "PPSSPP never reported a debugger port".
|
||||
`--log --loglevel=3` keeps the port line while cutting the debug flood - full `--log` at the default level costs
|
||||
a lot of emulation speed (a 25-second run of a game playing video wrote 450k lines and ran several times slower
|
||||
than real time, which on its own looks like the stall you're hunting).
|
||||
|
||||
## Debugging and breakpoint considerations
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# Patching files from a script
|
||||
|
||||
Most edits should go through an editor tool that does exact string replacement. This document is about
|
||||
the cases where you reach for a script instead - a repetitive change across many files, say - and the
|
||||
two ways that silently corrupts a diff on Windows.
|
||||
|
||||
The short versions of both live in `AGENTS.md` (General instructions, rules 5 and 6). This is the detail.
|
||||
|
||||
## Line endings
|
||||
|
||||
Which ending a file has depends on where it was checked out. Markdown, `.cpp` and most sources are
|
||||
stored in git with LF, and a Windows checkout converts them to CRLF on the way out; a Linux checkout
|
||||
leaves them alone. So the same file - `.vcxproj`, `.vcxproj.filters`, `android/jni/Android.mk`,
|
||||
`libretro/Makefile.common`, `AGENTS.md`, much of the source - is CRLF in one working copy and LF in
|
||||
another. Don't hardcode either, and don't "fix" a file's endings to match what a doc claims.
|
||||
|
||||
If you patch one with a script, read **and** write with `newline=''`, which keeps whatever was there.
|
||||
Reading with Python's default universal-newline translation and writing with `newline=''` silently
|
||||
converts the whole file, turning a two-line addition into a 5000-line diff.
|
||||
|
||||
Check `git diff --stat` before committing - a whole-file rewrite is obvious there and invisible in the
|
||||
editor.
|
||||
|
||||
## Backslashes in a bash heredoc
|
||||
|
||||
**Don't feed Python to `bash -c` via a heredoc when the code contains backslashes.** The Git Bash /
|
||||
MinGW layer strips one level of backslash escaping on the way in, *even with a quoted delimiter*
|
||||
(`<<'PY'`), which normally suppresses all substitution. So the script Python receives is not the one
|
||||
you wrote:
|
||||
|
||||
| You write in the heredoc | Python actually sees | Result |
|
||||
|---|---|---|
|
||||
| `"\r\n"` | `"\r\n"` | fine - survives, because you *want* Python to interpret it |
|
||||
| `"\\n"` (intending a literal `\n` in the output) | `"\n"` | **a real newline is written into the file** |
|
||||
| `'foo \\\r\n'` as a match anchor | `'foo \<CR><LF>'` | **anchor silently doesn't match**, reported as "anchor missing" |
|
||||
|
||||
The tell for the first case is a compiler error like `C2001: newline in string literal`; the second case
|
||||
produces no error at all, just a patch that quietly did nothing. Both are invisible in the heredoc you
|
||||
wrote.
|
||||
|
||||
The rule: **a heredoc is fine as long as every backslash in the script is one you want Python to
|
||||
interpret. The moment you need a literal backslash in the *output*, stop.** Then either:
|
||||
|
||||
- use an exact-string-replacement editor tool instead (no shell in the path - the best option for the
|
||||
common case of "insert a few lines of C++ that contain `\n`"), or
|
||||
- write the script to a file and run `python thescript.py`, or
|
||||
- build the backslash as `chr(92)` so no literal backslash appears in the heredoc at all.
|
||||
|
||||
Note this is about the *Python source*, not the data: reading and rewriting a CRLF file with
|
||||
`newline=''` and `\r\n` anchors works fine in a heredoc, and is the normal way to patch files here.
|
||||
Reference in new issue
Block a user