Step 39 · First contribution
Your first change
Choose a bounded behavior you can specify and test. Implementing a missing function is one route; adding a regression test for an existing function is another. The goal is a defensible change, not just a resolved import.
Before this page: Reproducible debugging labs · Debugging & diagnostics · Reading a run. View the learning route.
A small, understood HLE contract can make a good first contribution. An unresolved import is a research lead, not proof that returning success will improve compatibility. Use the developer curriculum to turn a hypothesis into evidence.
Step 1 — find what is missing
Run the game with logging to a file and search for stub messages:
kyty_emulator.exe --game "D:\Games\Example" --redzone --printf-direction File --printf-output-file _kyty.txt
The loader logs every import it could not resolve, with the NID and the owning module. A line naming a function the game then calls is your target.
Step 2 — work out what it should do
Combine these sources; none alone proves the complete contract:
- Call-site evidence. Inspect registers, verified argument memory and how the caller uses results. One call does not reveal every argument, optional field or error path.
- Symbol and type evidence. A NID database can suggest a name, not prove a signature. Verify parameter count/types, signedness, structure size/offsets and the guest ABI from lawful reference material and code evidence.
- Behavioral evidence. Specify success, failure, output writes and side effects before coding. Preserve a failing regression case. A guessed value that advances one title is a hypothesis, not a verified implementation.
Step 3 — write it
Add to the appropriate module file — or create one following the template in HLE libraries (a small standalone file such as libCes.cpp is the pattern):
The following is a fictional structural sketch, not a real API contract or copy-ready implementation. Establish size/flags validation, guest-pointer policy, ownership and output semantics for the actual function before using this pattern.
struct ExampleParam {
uint32_t size;
uint32_t flags;
void* buffer;
};
static int KYTY_SYSV_ABI ExampleGetStatus(const ExampleParam* param, int* out_status) {
PRINT_NAME();
LOGF("\t param = 0x%016" PRIx64 "\n"
"\t out_status = 0x%016" PRIx64 "\n",
(uint64_t)param, (uint64_t)out_status);
if (param == nullptr || out_status == nullptr) {
return EXAMPLE_ERROR_INVALID_PARAM;
}
LOGF("\t size = %" PRIu32 ", flags = 0x%08" PRIx32 "\n", param->size, param->flags);
*out_status = 0; // only if zero is established by this API's contract
return OK;
}
Then register it next to the owning module's entries. The example NID below is a placeholder, not a discovered export:
LIB_DEFINE(InitExample_1) {
LIB_FUNC("aBcDeFgHiJk", Example::ExampleGetStatus); // <- the NID from the log
}
Step 4 — verify it is actually reached
Rebuild and check that the import binds to the intended address. A breakpoint or trace can establish whether that path was called. If it was not reached, record it as untested. Neither a resolved slot nor a function-entry log proves correct return values, output bytes or side effects.
Step 5 — prove the guest-visible contract
Keep a test that fails before the change and passes after it. Check normal input, size/flag boundaries, null handling where the contract defines it, output layout and values, error codes and side effects. Use sentinels to detect unintended writes on error; do not dereference arbitrary invalid guest addresses just to add a negative test. Check ownership and concurrency when state survives the call.
Build affected targets and run the focused regression plus adjacent tests. If you run a title, record the exact binary, configuration and route with before/after observations. A unit test, a binding check and game progression are separate evidence. Lab C demonstrates why the return code alone is insufficient.
When it does not bind
| Symptom | Cause | Fix |
|---|---|---|
| NID still reported as stubbed | The NID string does not match exactly — one wrong character is enough — or the LIB_VERSION library/module name or version differs from what the game imports. | Compare against the log line, which prints the full nid#library#module. |
| Bound, but arguments are garbage | Possible ABI mismatch or wrong signature. A correct name does not guarantee correct parameter types/count. | Verify both KYTY_SYSV_ABI and the complete signature against call-site/type evidence. |
| Bound and called, then the game crashes inside your function | Your struct layout does not match the console's. Guest pointers point at guest-laid-out data. | Dump the raw bytes at the pointer and rebuild the struct from them. Add a static_assert on the size once you are confident. |
| Everything works but the game still misbehaves | The return value or output parameter is wrong for what the game expects. | Recheck the contract, output layout, error namespace, state changes and synchronization. Add a regression for the mismatch instead of trying arbitrary success values. |
The README asks that code contributions be focused, build on the platforms they touch, and include tests where practical. It also carries an explicit AI-use policy: assistance is allowed for research and development, but you must understand and test what you submit, disclose the scope of any AI involvement, and write the pull-request text yourself.
The five steps, in order. It is the same loop every time.
Use the triage tool to find candidates, then choose one with an understood, bounded contract. The top unresolved import can depend on a large subsystem or may never be called; it is not automatically a beginner task.
Work through the walkthrough above with a function from your own log rather than the example. The Examples page covers the same loop in a different order if you would rather see it laid out as steps.
Checkpoint
Use the developer route for end-to-end traces, reproducible labs, a coverage map and a contribution evidence record. The Playground supports selected learning tasks; it does not replace source review, regression tests or runtime evidence.