Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 181 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# Contributing to libdof

Thank you for your interest in contributing to **libdof** — the open-source, cross-platform C++ port of the
DirectOutput Framework ([DirectOutput/DirectOutput](https://github.com/DirectOutput/DirectOutput),
[mjrgh/DirectOutput](https://github.com/mjrgh/DirectOutput)), used by
[Visual Pinball](https://github.com/vpinball/vpinball) and [VPinFE](https://github.com/superhac/vpinfe)
to drive feedback devices such as LEDs, solenoids, and motors on virtual pinball cabinets.
This document contains rules and guidelines relevant for contributing to any area of the project.

---

## Table of Contents

- [Code of Conduct](#code-of-conduct)
- [Respect Copyright](#respect-copyright)
- [Maintain 1:1 C# Correspondence](#maintain-11-c-correspondence)
- [Contribute One Change at a Time](#contribute-one-change-at-a-time)
- [Explain Your Contributions](#explain-your-contributions)
- [Contribute Only What You Understand](#contribute-only-what-you-understand)
- [AI-Assisted Contributions](#ai-assisted-contributions)
- [AI-Generated Fixes for Identified Issues](#ai-generated-fixes-for-identified-issues)
- [Build System](#build-system)

---

## Code of Conduct

When you contribute to libdof, we expect that you behave respectfully toward all contributors, maintainers, and community
members. Keep discussions technical and constructive. Personal attacks, harassment, or dismissive language will not
be tolerated.

---

## Respect Copyright

You must be mindful of the copyright and patent rights of anything you submit.

If you authored every part of your contribution and own the rights, this is not a problem — you can submit without
reading further. Note that this submission will then be directly considered to be compliant with libdof's [licensing model](LICENSE).

However, any code or assets taken from elsewhere — including code generated by AI — may be subject to copyright or
patent rights that you must respect. In such cases, check the license of the material. Some licenses are permissive
enough to be compatible with libdof's license. You must include the original license in your contribution if required.
Examples of compatible licenses include Apache 2.0, BSD, ISC, MPL 2.0, and MIT.

Other licenses may impose conditions incompatible with libdof's distribution and licensing model. **"Source-available" is not
"open-source"**: do not submit code or ideas taken from proprietary or source-available simulators or engines.
In any case, always make sure to match the conditions in libdof's [licensing model](LICENSE).

---

## Maintain 1:1 C# Correspondence

libdof aims to be a faithful 1:1 port of the original C# [DirectOutput](https://github.com/mjrgh/DirectOutput) codebase.
This is the project's defining constraint, and contributions are expected to preserve it:

- Match the C# namespace, directory structure, file names, method names, and method order.
- Enum values, constants, and timing values must match the C# source exactly.
- Do not add validation, guards, or behavior that is not present in the C# original.
- When fixing a bug, first check how the C# code behaves — if the bug exists there too, raise it for discussion
rather than silently diverging.

Deviations are sometimes necessary (platform differences, memory safety, C++ idioms), but they should be deliberate,
minimal, and called out in your PR description.

---

## Contribute One Change at a Time

Each pull request should contain a single, self-contained change. Avoid bundling multiple unrelated changes in the
same PR. Also, make sure to avoid any unnecessary formatting or line-ending changes (i.e. anything that does not fall
under the areas of source that you absolutely need to touch).

As a rule of thumb: if your pull request could be split into two without breaking anything, it probably should be
two separate pull requests.

The exception is **batching changes** — making the same kind of change across multiple files or locations (e.g.,
a systematic rename, or a build system fix). In this case, a single larger PR is preferable
to many small ones.

> **Think like a reviewer.** A PR that is simple, coherent, and focused on one concern is much easier to review,
> approve, and revert if needed. Keeping PRs small also makes bisecting regressions straightforward.

Limiting pull requests to one change at a time:

- Simplifies the Git history.
- Makes it possible to revert or cherry-pick specific changes.
- Reduces the risk of accidentally introducing bugs.

---

## Explain Your Contributions

When submitting a pull request, make full use of the PR description. It should clearly and succinctly explain
everything a reviewer needs to understand your changes.

For a small fix (e.g., a typo or a one-line correction), a single sentence is sufficient.

For larger or higher-impact changes, be more thorough. A complete description includes:

- **Summary of changes:** A short overview of what changed and why.
- **Motivation:** Why you opened the pull request. Ideally, link to an existing issue or discussion.
- **Related work:** Links to similar PRs, prior discussions, or external references that provide context.
For port-accuracy changes, link to the corresponding C# source.
- **Technical overview:** Briefly explain each significant change and why it is necessary.
- **Testing:** How you tested the change and what results you observed. Output controller changes should be
validated on real hardware whenever possible, and cross-platform changes should be validated on the relevant
platforms (Windows, Linux, macOS).
- **Discussion:** Risks, caveats, and how they could be mitigated. If existing cabinet configurations may be
negatively affected, disclose this explicitly — especially for compatibility breakages or behavioral regressions.
- **Additional work:** Anything you need help with, feedback on, or plan to follow up with.

> You do not need every section for every PR, and you do not need to copy this exact structure.
> Always ask yourself: *what does a reviewer need to know to feel confident approving this?*

---

## Contribute Only What You Understand

Only submit code that you understand and are prepared to explain to a maintainer.

If you do not fully understand a piece of code — because you adapted it from another source, implemented someone
else's idea, needed to use AI-assistance (see next section), or are working in an unfamiliar subsystem — take extra care to test
it rigorously and disclose this in your PR description.

This also applies to low-level subsystems such as output controller protocols (serial, HID, USB, FTDI), the effect
chain, or device auto-detection. If you are unsure about the impact of your change in these areas, say so.

---

## AI-Assisted Contributions

The use of AI to contribute to libdof is **discouraged**, and contributions made **entirely by AI are prohibited**.

> "AI" here refers to any LLM or generative AI tool (ChatGPT, Claude, Copilot, Gemini, etc.). Using translation
> software to communicate in English is fine. Single-line code completions do not need to be disclosed.

We recognize that AI tools can be useful, but we believe that human understanding, testing, and judgment produce
better and more reliable contributions — particularly in a codebase that must remain a faithful 1:1 port of the
original C# DirectOutput framework.

If you do use AI assistance:

- **Proofread and validate** everything it generates. Do not submit AI output as-is.
- **Test thoroughly** on real hardware with representative tables before submitting.
- **Disclose** what you used AI for in your PR description.

Maintainers invest significant time in review. Please only submit something you have genuinely thought through
and tested.

### AI-Generated Fixes for Identified Issues

There is one exception to the prohibition on contributions made entirely by AI: if you have identified a genuine
issue and used AI to generate a fix for it, you may still submit it under the following conditions:

- The pull request **must be opened as a draft PR**. It is not eligible for standard review or merge in this state.
- The PR description must **clearly state the issue** being addressed, ideally using the issue template, including
steps to reproduce and any relevant context.
- The PR description must **clearly state that this is an AI-generated fix**, offered as a starting point to help
design the final solution — not as a finished, reviewed contribution.

This exception exists to let issues surface along with a possible direction for a fix, without implying the fix
itself carries the same confidence as a human-validated contribution. Maintainers or other contributors may then
pick up the draft, refine it, or use it purely as a reference while implementing their own solution.

---

## Build System

libdof uses **CMake** as its sole build system, with per-platform configurations under [`platforms`](platforms)
(Windows, Linux, macOS, iOS, tvOS, Android).

When adding, removing, or renaming source files:

- Update `CMakeLists.txt` accordingly.
- Make sure the change builds on the platforms it affects — the CI workflow covers all supported platforms.

---

*These guidelines were derived from the [Godot Engine contributing guidelines](https://contributing.godotengine.org/en/latest/pull_requests/pull_request_guidelines.html),
which are published under the [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/) license.*
Loading