RetroSharp.Tool 0.0.1493

dotnet tool install --global RetroSharp.Tool --version 0.0.1493
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local RetroSharp.Tool --version 0.0.1493
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=RetroSharp.Tool&version=0.0.1493
                    
nuke :add-package RetroSharp.Tool --version 0.0.1493
                    

RetroSharp.Tool

retrosharp compiles C#-like programs and a zero-cost 2D SDK into ROMs for the Game Boy, the NES, the Master System and the Game Gear. The Master System and Game Gear targets are still in development and support a subset of the SDK; unsupported calls fail with a clear diagnostic.

Requirement

The .NET 10 SDK must be installed: dotnet --list-sdks has to list a 10.0 version. Without it, dotnet tool install fails with Settings file 'DotnetToolSettings.xml' was not found in the package, because the tool targets .NET 10 only.

Install

dotnet tool install --global RetroSharp.Tool

Start

retrosharp --help

An AI agent should start with retrosharp guide. All the documentation travels with the tool and needs no repository or website: retrosharp guide lists the topics and retrosharp guide <topic> prints one.

Build a first game

retrosharp templates create minimal --name MyGame --output MyGame
retrosharp MyGame/game.retrosharp.json

The ROMs are written to the project's bin folder.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.0.1493 80 11/9/2026
0.0.1254 115 10/30/2026
0.0.1246 100 10/29/2026
0.0.1242 105 10/29/2026
0.0.1240 103 10/29/2026
0.0.1231 109 10/28/2026
0.0.902 124 10/13/2026
0.0.777 112 10/5/2026
0.0.769 113 10/5/2026
0.0.662 121 9/27/2026
0.0.661 119 9/24/2026
0.0.660 115 9/24/2026
0.0.659 117 9/24/2026
0.0.658 116 9/24/2026
0.0.657 112 9/24/2026
0.0.656 104 9/24/2026
0.0.655 122 9/24/2026
0.0.654 112 9/23/2026
0.0.653 120 9/23/2026
0.0.652 121 9/23/2026
Loading failed

# Changelog 0.0.1493

## Changes since v0.0.1254

- Roadmap #2614 closing check: one Portable2D path for Tiled layer calls, resource factories by their package, quoted methods by their declared name, unused binding queries retired (#3018) (#3019) (`5c19809d`)
- Portable2D: the camera always exists, over the active scene, so Camera.X/Y and camera moves need no Camera.Init (#1717) (#3017) (`5f6d4f24`)
- SDK frontend: the author's physical project reaches the compilation as its files' trees; AuthoredFunctionMap and the composer's text edits go (#2889) (#3016) (`e0734db4`)
- Plugin contract: source stages retire; plugins read the program only as the analyzers' view (#2630) (#3011) (`5d3a6474`)
- Contract 0.5: extension points are named only by their library's source, checked on the bind's references; the reserved-name token guard retires (#2971) (#3010) (`acf125cd`)
- Portable2D: Game.Run is SDK code with a single-call analyzer, and ManagedGame retires (#2617) (#3008) (`93399426`)
- Portable2D: Scene.TouchTiles is SDK code that answers a walk the game dispatches on, and the TileKinds source stage retires (#2627) (#3005) (`05eada37`)
- Tests: a let local passed to pool calls builds the explicitly typed ROM (#1473) (#3004) (`25219453`)
- Tests: actor tests judge Tiled spawns by the game's pool, not by the spawn generator's state names (#2718) (#3003) (`d99c1992`)
- Portable2D: Tiled spawns are pool methods that the game analyzer generates, with their state in static fields per pool type (#2628) (#3002) (`ab47a819`)
- Portable2D: the build warns where a camera follow policy becomes dynamic, naming the setter and the static form (#2249) (#3001) (`a78b6cc5`)
- Language: a free receiver function of a physical namespace is a member of its type under its author's name (#2990) (#2999) (`d54efa10`)
- Tests: a local hiding a constant in a camera policy argument keeps the dynamic follow policy (#2247) (#2998) (`a9a540eb`)
- Portable2D: the Camera API is declared in the SDK with its state in static fields, and the camera follow is a generator of literals (#2629) (#2997) (`a2f20373`)
- Language: a value helper with statements may compute a struct or class value (#2989) (#2996) (`2cf7be6e`)
- Language: a value helper with statements need not be inline, and its value may stand in a while or for condition (#1872) (#2988) (`bd320966`)
- Plugins: Portable2D Triggers is a generator whose state lives in SDK static fields (#2626) (#2985) (`4b3f33df`)
- Language: a compile-time string selects the code an inline function and a generated document compile (#2978) (#2983) (`111c77c3`)
- Diagnostics: a game with its own loop that calls Scene.Activate is refused at the call, pinned by a test (#2534) (#2977) (`5ba5d0e8`)
- Plugins: a generated document names a declaration of a game's physical namespaces by the program's name (#2972) (#2976) (`33f10364`)
- Contract 0.5: Portable2D's managed-game checks read the program view; the bound-program policies and sdk_source_anchor retire (#2716) (#2975) (`bda81c0e`)
- Plugins: a generated document specializes an extension point for a game type; unconstrained generics and global:: (#2966) (#2974) (`db960602`)
- Contract 0.5: the view reads the target's constants and says which flow folding keeps (#2959) (#2969) (`c891086a`)
- Plugins: the generator context reads resources, declares ROM tables and lets a generated document declare its own symbols (#2958) (#2965) (`e0968d64`)
- Plugins: SDK extension points and generated documents; Game.Run's services are extension points a policy implements late (#2624) (#2963) (`595d7b1c`)
- Language: a repeated function, receiver method or member in a physical namespace is named as written (#2414) (#2960) (`0ffe4156`)
- Bind: a bare name sees its namespace and those around it, then its usings and the roots, not a namespace inside or beside it (#2422) (#2954) (`a432c0eb`)
- Language: constraint, conformance and contract errors name declarations as their author wrote them (#2658) (#2952) (`18bd817e`)
- Tests: a physical library's const array is read by countof and by an indexed receiver call (#2651) (#2951) (`b27e8403`)
- Bind: a generic call's type arguments, written or inferred, are the bind's data; the plugin view reads them (#2939) (#2948) (`5a19cbba`)
- Portable2D: SpriteEffects becomes a program analyzer over the semantic view and reports at the effect argument (#2625) (#2946) (`39466fa0`)
- SDK plugins: a policy reads the program as written, as the bind resolves it, and reports at its elements (#2623) (#2943) (`c6bc29e9`)
- Portable2D: Camera.Follow exists only under Game.Run; retire its own-loop form (#2829) (#2941) (`ac92cf0e`)
- Language: a value helper's result is its return type's value on every target (#2886) (#2937) (`fe52ac93`)
- SDK frontend: the operation collectors select runtime routines from the program after constant-branch removal (#2880) (#2936) (`47b78709`)
- Language: an argument with effects to a call that a copied statement body passes its case view to runs once (#2920) (#2932) (`77df421e`)
- Language: an enum member computes as a variable of its enum, in the integer type that stores it (#2838) (#2931) (`0258e4d3`)
- Language: a typed constant computes at its type's width, as a variable of that type does (#2885) (#2928) (`be0e01b9`)
- Language: a library's call that no scope declares is an error at the call, as the author's is (#2881) (#2925) (`a5d659af`)
- Language: an argument with effects to a call the union lowering expands by name runs once (#2753) (#2922) (`8a35241f`)
- SDK frontend: the selector lowering quotes values through the source text writer, not a receiver rule of its own (#2835) (#2919) (`7203ac49`)
- Rules: mutation checks run with tools/test/mutate.py, and the reviewer may run it to confirm a mutant (#2916) (#2917) (`31e03fc2`)
- Tools: mutate.py runs a session's mutation checks from a list, and suite.py writes its outcome as data (#2760) (#2915) (`487c4ffa`)
- Rules: the worktree's command rule moves into AGENTS.md and states the isolation's criterion (#2901) (#2914) (`b8f8b22f`)
- Rules: a finding that belongs to another open issue goes to it with issue.py note (#2911) (#2913) (`8ad342d9`)
- Tools: issue.py note leaves a finding on the open issue it belongs to, and block --note-file leaves it on the blocker (#2842) (#2912) (`e71e7087`)
- Tools: suite.py lets a slow project close to its end finish after another fails (#2888) (#2910) (`521562ea`)
- Rules: the reviewer and the /issue author probe with probe.py, and the author runs --base before each handback (#2897) (#2908) (`8c749537`)
- Rules: the agents of a claimed issue work under the directory issue.py claim printed (#2902) (#2905) (`d6ea7cd7`)
- Tools: probe.py checks a directory of probe programs on each target with the worktree's compiler, and with --base the merge base's, in one call (#2758) (#2904) (`785735b6`)
- Tools: issue.py claim makes the issue's directory afresh with master's issue.py and prints it, and cleanup removes it (#2759) (#2903) (`02c4c3ec`)
- Tools: suite.py refuses a whole run of a slow test project outside the gate, so a script cannot get past the hook (#2788) (#2896) (`ae192f8a`)
- Tools: .claude/settings.json runs the agents' Bash under bash, so `echo ====` and an unmatched glob no longer drop a command (#2871) (#2895) (`76e0dff5`)
- SDK frontend: the author's text is read once before the stages, and the policies read the trees already read (#2714) (#2893) (`902ed715`)
- Language server: physical files bind with their namespaces, so two types of one name in two folders are two symbols (#2890) (#2892) (`b4832845`)
- Language: the merge and the library registry read each file once and write the internal names into its tree (#2876) (#2891) (`a4260a51`)
- Language: a call whose value is a constant folds to it, and a condition over it keeps one arm (#2879) (#2887) (`c77f79a3`)
- Language: the bind resolves physical namespaces, and the composer only writes the names it finds (#2713) (#2884) (`2dec5441`)
- Language: a static field takes storage and start-up code only when compiled code names it (#2878) (#2883) (`cf4ac1dc`)
- Frozen fixtures: the staircase, diagonal-scroll-v1 and runner-lift-v1 follow under Game.Run, with cadence bounds re-measured (#2828) (#2877) (`ac31c115`)
- Tools: issue.py start reads its command one way, and claim and roadmap-add read a parent roadmap one way (#2874) (#2875) (`7b46f44e`)
- Workflow: batch picks check every claimed worktree's files, and Claiming.md leaves the roadmap cap to claim (#2869) (#2873) (`4e2c704d`)
- Tools: issue.py claim refuses a roadmap's third claim (#2833) (#2872) (`9de0017c`)
- Workflow: Claiming.md names issue.py roadmap-state for reading and writing a roadmap's state comment (#2867) (#2870) (`8d58ebf9`)
- Tools: issue.py roadmap-state reads a roadmap's state comment with the newer comments, and writes it only under a size cap (#2855) (#2868) (`4e5b2136`)
- Workflow: continued review rounds end in a report file that issue.py wait returns on; long commands run through issue.py start and wait (#2866) (`f70098cf`)
- Docs: a Markdown line under docs/ stays under 200 characters, so a line-bounded read stays bounded (#2857) (#2865) (`693d32ac`)
- Tools: issue.py start runs a session's job detached, and issue.py wait returns when it ends or a file is written (#2864) (`a9aedc0a`)
- Language server: completion and signature help through the bind; SymbolResolver is retired (#2860) (`b63eb766`)
- Language: two declarations compiled under one namespaced name are an error at the later one (#2715) (#2858) (`8c3e5244`)
- Language frontend: a member a value's type does not declare is RS3106 at the member access, from the bind (#2691) (#2856) (`ce417294`)
- Language server: definition, references, hover and semantic tokens through the bind (#2854) (`9129b6cd`)
- Language frontend: an identifier is one name; readers stop splitting identifiers by dots (#2710) (#2848) (`8f44e101`)
- Language frontend: static interface lowering reads the expression type rule; StaticTypeScope and TryInferType are retired (#2817) (#2847) (`7e9ff099`)
- Workflow: cleanups found along a roadmap stay outside it (#2843) (#2844) (`d25d2033`)
- Language frontend: one evaluator gives the constant value of an expression to the fold, the type scopes, the bind and the validators (#2701) (#2841) (`201f4027`)
- Language: an instance method named Main is never the entry point (#2657) (#2840) (`4c4364a5`)
- Tests: a function named like an instance method is reached by a call with no receiver (#2648) (#2839) (`9d7e8d58`)
- Backends and SDK: an element's array storage is named from its base expression in one place; the selector lowering no longer splits the base text (#2708) (#2836) (`caa5a072`)
- Language frontend: InlineValueStatementLowerer and OperandTypes read the expression type rule; their own scope and inference are retired (#2700) (#2832) (`5e814dd3`)
- Tests: programs that follow the camera on the way to another subject run under Game.Run (#2789) (#2830) (`2377853d`)
- Language frontend: generic specialization reads the expression type rule; its TypeScope and TryInferType are retired (#2816) (#2827) (`ab61d459`)
- Language: the bind judges the arguments of each call it names, with the other binding errors and the author's names; RS1113 is retired (#2685) (#2826) (`37143e61`)
- Language frontend: the union lowering reads the expression type rule; its own type scope and TryInferType are retired (#2699) (#2824) (`9dc3b7e6`)
- Bind: a name in a type position names its type's symbol, and an expression's type carries it (#2811) (#2820) (`6a89aedb`)
- Language and SDK frontends: the resource handle-use check and ParameterSubstitution walk the tree with SyntaxWalker and SyntaxRewriter, not hand-written switches (#2808) (#2815) (`3b9b1405`)
- Language: the type of a receiver on the faithful tree, by the type rule over the bind's symbols (#2711) (#2813) (`4db89a10`)
- Language: the let types and the bool and enum checks run before the union lowering, so a call on a case designation is checked as a call (#2749) (#2810) (`0ca93b1b`)
- Parser: SyntaxWalker and SyntaxRewriter reach every child of every node; NameBinder, BoundNames and NodeLocator keep no list of their own (#2800) (#2809) (`53c205c6`)
- Workflow: batch stops and reports when a run's trajectory turns (#2805) (#2807) (`5aa4b41b`)
- Architecture: one ratchet over the mechanisms Mechanisms calls defects; existing code is not precedent (#2803) (#2806) (`d35ff4d5`)
- Language: the bind's symbols carry their declarations, name spans and identity, and the bind runs outside class lowering (#2709) (#2802) (`44c264cf`)
- Workflow: one reviewer per issue, continued across review rounds (#2798) (#2799) (`ae080bc2`)
- Language: one rule gives an expression its type; let inference and the bool and enum checks read it and report together (#2797) (`6940839e`)
- Language: a qualified call's receiver is bound and lowered by the value rule, as an element's base is (#2786) (#2795) (`0f54a69e`)
- Portable2D: the ActorSpawns reset at a scene activation exists only under Game.Run; an own loop that activates a scene cannot fill a pool from Tiled (#2704) (#2794) (`3cbef409`)
- Language: ArgumentCapture compares access paths as lists of names from the nodes, not as text (#2785) (#2792) (`8a2d0879`)
- Language: an element's and countof's base is an expression on the node, walked by every frontend reader instead of a dotted text path (#2702) (#2790) (`ecc7f84c`)
- Portable2D: tile kinds and Scene.Collect kinds reach the host from the bound program, not tokens (#2717) (#2787) (`6650b91a`)
- Workflow: a roadmap follow-up whose cause a planned sub-issue removes waits behind that sub-issue (#2781) (#2782) (`42280564`)
- Language: a qualified call's receiver is an expression on the node, read by every stage instead of the qualifier's text (#2761) (#2780) (`f2e40603`)
- SDK frontend: libraries and generated code enter the compilation as trees (#2712) (#2779) (`e23e7e5e`)
- Parser: an expression cut short inside a statement keeps its nodes, with what is missing marked (#2707) (#2776) (`348b1066`)
- Language: the applicability rule alone gives the verdict on a ref argument's type (#2769) (#2775) (`9866cf99`)
- Language: a helper call whose argument does not apply is reported at that argument by the one applicability rule (#2764) (#2772) (`4c40b2a4`)
- Language: a function no longer names its caller's variables; binding is lexical (#2705) (#2770) (`7edf12e4`)
- Language: a generic receiver method binds its arguments by the one applicability rule (#2725) (#2768) (`20f8ed1d`)
- Language: a qualified call's receiver is resolved from its segments, and quoted expressions omit the hidden receiver while writing (#2723) (#2763) (`5de7db50`)
- Language: a member named like an earlier member of its class or struct is RS1011 at the later one (#2654) (#2762) (`5ae74dc5`)
- Language: a call on a union case designation binds by the one applicability rule, as on a local of its case type (#2722) (#2757) (`f6e1ed57`)
- Parser: the semantic errors the parser threw come from the bind, and ParseRecovering always gives its tree (#2721) (#2755) (`fad9adc7`)
- Workflow: a roadmap's order is its native GitHub sub-issue order; roadmap-add places the issue there (#2752) (`f83a323b`)
- Language: every receiver call binds by the one applicability rule, and messages read whether the call was written on a receiver (#2719) (#2747) (`55f17380`)
- Tools and tests: launched builds run in parallel; staging tests through suite.py (#2746) (`19656c06`)
- Decide recursion through interface specializations in the language's recursion check (#2745) (`49c666bb`)
- Report recursion through parameter default values (#2744) (`d342d33f`)
- Workflow: commits, pull requests and issues are written in English (#2742) (`a16bc7e6`)
- Workflow: /issue diseña, implementa y corrige en una sola sesión; las reglas de /roadmap pasan a Claiming.md (#2740) (`8eb42649`)
- suite.py: cheap test projects run whole, and runs go cheapest first and stop at the first failure (#2738) (`f9d6622a`)
- diff_roms.py: reuse the merge base's ROMs from a shared cache (#2737) (`83b8ba58`)
- Workflow: use CodeGraph for C# symbol relations, rg for the rest (#2736) (`fb19b641`)
- Workflow: review findings are defect types with every site, and fixes sweep the change (#2735) (`25bb9708`)
- Workflow: prescribed commands need no command substitution; issue.py block records dependencies (#2734) (`83d734a0`)
- CLI: the passive SDK check reads the author's imports from each file's syntax, not with a regex over the composed text (#2726) (#2728) (`acb6fa4f`)
- SDK frontend: one composition entry reads each author file in its own SourceFile and reports every syntax error at its file and line, also with libraries; the CLI pre-parse is retired (#2621) (#2727) (`94452374`)
- Parser: text with syntax errors also gives its ProgramSyntax, each unreadable statement, declaration or member a SkippedSyntax with its span (#2683) (#2724) (`ba24bf5a`)
- Language: class constants, const arrays and target constants reach later passes as their declaration's name (Class::Name); the four text paths, QualifiedNames and RS1007 are retired (#2666) (#2720) (`ce160c82`)
- Language: the bind reports undeclared calls and unbound default values with RS1007, each at its node; UndeclaredCallValidator is retired (#2681) (#2697) (`9b8feeba`)
- RetroSharp sources use the .rcs extension; .rs is gone at every level, and the VS Code Rust-coexistence mechanism is deleted (#2694) (#2696) (`716f491d`)
- Workflow: batch runs a retrospective of the agents' environment every 5 sessions or after an anomalous one, without stopping the lanes (#2692) (#2693) (`5e9d8e8f`)
- Language: instance methods have their entry in the declaration table; ReceiverMethodCatalog.GeneratedSourceName and TryResolveLoweredName are retired (#2680) (#2686) (`e03ed894`)
- Language: a binder gives each authored name its symbol and class lowering reads it; StaticMembers.Bind and the two hand-written walkers are retired (#2665) (#2682) (`e95436ca`)
- Language: no backward compatibility; [removed], removed.rs, RS1405 and the other migration leftovers are deleted (#2668) (#2679) (`052c71eb`)
- Language: static methods lower to Class::Method, so A_B.C and A.B_C no longer collide (#2671) (#2673) (`6f549901`)
- Language: declarations carry their owner, authored name and namespace as data in ProgramSyntax.Declarations; DeclaredStaticMethodIndex and NormalizeGeneratedStaticCalls are retired (#2620) (#2672) (`443053d6`)
- Rules: no backward compatibility, not even with earlier RetroSharp versions (#2669) (#2670) (`79376b98`)
- Language: sizeof and offsetof measure with StructElementLayout.BytesOf; ConstantFolder keeps only the checks BytesOf cannot make (#2655) (#2664) (`6edde1c8`)
- Workflow: an issue's design is reviewed before any code (#2660) (#2662) (`0e119fd7`)
- Parser: the tree is faithful to what was written (classes, members and qualified calls); the renaming to Class_Method moves to the class lowering (#2619) (#2659) (`f68acdac`)
- Language: static fields, as in C#, in fixed storage the compiler reserves and the build report lists (#2618) (#2656) (`cde9c49d`)
- Portable2D: Scene.SetTile declares its tile as a [tile_name] parameter and the SDK binder numbers it; the SetTiles stage is retired (#2616) (#2653) (`3d04e507`)
- Language: indexing a const array of a [removed] class is an error at the use; the parser keeps the owner of a qualified index as data (#2646) (#2652) (`c15013b4`)
- Language: a use of a declaration marked [removed("…")] is an error at the use; the Portable2D RemovedApis stage is retired (#2650) (`f2a1bd2d`)
- Constant folding: ConstantOperandValidator reports overflow with owner and position; a speculative fold reads it as "not a constant" (#2633) (#2644) (`25da1f96`)
- Game Boy: world tilemap placement reads the plan, not the label prefix (#2639) (#2642) (`6f8ab1e2`)
- Game Boy: world tilemap placement reads the plan, not the label prefix (#2639) (#2642) (`8f1410c6`)
- NES: shared SDK subroutines are known by a record of the emitter, not by their label prefix (#2637) (#2641) (`8584bab8`)
- FrameBudget: the compiler records the owner of every run of code and FrameBudget no longer slices label names (#2579) (#2640) (`ffe13ba7`)
- Constant folding: "not a constant" is a typed result, with no generic InvalidOperationException catch (#2611) (#2635) (`d068afc5`)
- Language frontend: argument binding is asked with Try…, without generic InvalidOperationException catches (#2610) (#2632) (`07fedec7`)
- NES: no generic InvalidOperationException catch or Exception.Data decides the compilation (#2577) (#2613) (`81f77cda`)
- Game Boy: the raw compatibility fallback chosen by an exception's message is retired (#2576) (#2612) (`d66e91e2`)
- Diagnostics: the manifest's JSON message, the path shape as a sign of a real file and the copies of the broken plugin contract are retired (#2605) (#2609) (`43611a4e`)
- Language: let inference carries the class of its failure as data, not as text (#2602) (#2608) (`b5043c8c`)
- Diagnostics: CompilerDiagnosticLocator is retired; a diagnostic without a place prints without a position (#2487) (#2604) (`d7f33482`)
- Diagnostics: a malformed music envelope gives RS3300 in the envelope with a note at the declaration (#2596) (#2600) (`518d1bf5`)
- Diagnostics: the internal invariants of the targets, Z80Family and Parser are InternalCompilerError (#2549) (#2599) (`7e20c3f4`)
- Diagnostics: a Game Boy trace used as NES music is refused in its file with a note at the declaration (#2593) (#2598) (`8c69ef66`)
- Diagnostics: Master System and Game Gear resource errors are placed in the resource file with a note at the declaration (#2588) (#2595) (`af5c0f4a`)
- Diagnostics: NES resource errors are placed in the resource file with a note at the declaration (#2587) (#2592) (`4dc48adf`)
- Workflow: a roadmap batch without max goes on until the roadmap ends instead of stopping every 6 merges (#2589) (#2591) (`38f5f7e5`)
- Diagnostics: Game Boy resource errors are placed in the resource file with a note at the declaration (#2547) (#2590) (`f19fa344`)
- Diagnostics: resource importer errors are placed in the resource file with a note at the declaration that names it (#2546) (#2585) (`e094c9e8`)
- Diagnostics: plugin contracts and plugin invariants are internal errors naming the plugin (#2536) (#2583) (`4532d904`)
- Rules: recovering by text a datum the system had is a defect, and a design that departs from a reference compiler is a notice to the owner (#2581) (#2582) (`3fbc3fb9`)
- Diagnostics: a plugin hook's author errors are placed at the node the host processes (#2535) (#2575) (`9b3c80e1`)
- Tests: the isolated home of cold compiler builds shares the user's Antlr caches (#2569) (#2574) (`04dc8acb`)
- Diagnostics: the dead rules of CompilerDiagnosticLocator are removed (#2545) (#2573) (`501738db`)
- Diagnostics: an unknown resource declaration is placed at the attribute's id; PalettePlan's unreachable errors are InternalCompilerError (#2567) (#2572) (`a7d6491b`)
- Diagnostics: the SDK model's internal invariants are InternalCompilerError (#2529) (#2571) (`45221b02`)
- Diagnostics: a program-located error is placed in the compiled file on the failure path too (#2538) (#2570) (`a03d0549`)
- Diagnostics: target capability checks, the intrinsic catalog and the sprite draw plan errors carry the author's call location (#2528) (#2568) (`e925a1cc`)
- Diagnostics: the remaining language-frontend and parser errors carry their location (#2548) (#2563) (`938e499c`)
- Diagnostics: the tile-animation warning names the world as written and lies at its declaration (#2532) (#2561) (`8289e362`)
- Diagnostics: SdkCanonicalResourceGuard errors carry the location of the resource used (#2526) (#2560) (`4451d318`)
- Diagnostics: errors of the setup calls' ranges carry the author's call location (#2525) (#2557) (`497137e4`)
- Diagnostics: a CLI test pins a Button.Select read inside an author's function at its line (#2542) (#2555) (`2ea26fe9`)
- Diagnostics: project manifest errors carry their place in the manifest (#2484) (#2553) (`f511dc06`)
- Diagnostics: errors of the targets' code generators carry their location (#2482) (#2544) (`7e7df3ef`)
- Diagnostics: the absent-button and sprite-effect blink warnings are born at the read or draw that causes them (#2531) (#2543) (`4f8971f5`)
- Diagnostics: errors of the plugins' source stages carry their location (#2483) (#2541) (`160b1ab3`)
- Diagnostics: SDK operations carry their call's span and their validators report located errors (#2481) (#2537) (`4b80ea43`)
- Diagnostics: warnings are born with their location (#2485) (#2533) (`97335f52`)
- Diagnostics: errors of the SDK collectors and SdkCallReader carry their location (#2516) (#2527) (`d728bd3c`)
- Diagnostics: errors of the static interface lowerer carry their location (#2515) (#2523) (`d86d27de`)
- Diagnostics: errors of the SDK resource binder, in-place capture and undeclared calls carry their location (#2480) (#2522) (`26178cb8`)
- Diagnostics: a default argument keeps the span where it is written (#2518) (#2521) (`95777e46`)
- Diagnostics: errors of the generic specialization lowerer carry their location (#2512) (#2520) (`b2fcc398`)
- Diagnostics: errors of the union, constant, substitution and static-class lowerers carry their location (#2479) (#2514) (`1adfce8e`)
- Diagnostics: one loop places and writes the CLI's diagnostics (#2510) (#2513) (`d26df12d`)
- Diagnostics: one grammar read and one path form in the CLI after #2503 (#2506) (#2511) (`31191c35`)
- Diagnostics: errors of the language frontend's local semantics and aggregates carry their location (#2478) (#2509) (`f7ef3fa0`)
- Diagnostics: the storage report places each construct by its node's span (#2486) (#2508) (`9a746541`)
- Diagnostics: lexer and parser syntax errors reach the CLI and check --json as diagnostics, also in physical projects (#2503) (#2507) (`5e8656b8`)
- Diagnostics: errors with a location reach the CLI and the language server structured (#2477) (#2504) (`ce28702e`)
- Diagnostics: the source maps compose and the parser places spans in the author's files (#2476) (#2502) (`41357c67`)
- Diagnostics: hand-written lowerers and helper expansion keep the precise span (#2473) (#2501) (`b8d8550a`)
- Samples: an effects sample with Screen.Play and Sprite.Draw Blink, Flash and Glow on the four targets (#2498) (#2500) (`fa34953b`)
- Diagnostics: the remaining plugin stages, the composer and the library merge carry a position map (#2475) (#2499) (`22119611`)
- Effects: retire the unused NES screen-effect cells and the frontend's second collection of sprite-effect draws (#2496) (#2497) (`30a808a1`)
- Sprite Flash and Glow: the level choice moves to SDK source; targets only show a level (#2447) (#2495) (`275b4af1`)
- Diagnostics: the span is inherited when rewriting the tree (SyntaxRewriter and fill between stages) (#2472) (#2494) (`eb649f36`)
- Diagnostics: one source editor for plugin stages, with a position map (CameraFollow and ActorSpawns) (#2474) (#2493) (`54c726b1`)
- Diagnostics: the parser marks each syntax node with its source span (#2471) (#2492) (`3e1aa170`)
- Static setup: retire the unread tilemap step descriptor and the unbuilt TilemapSet/TilemapFill kinds (#2469) (#2490) (`16f92872`)
- Diagnostics: base types SourceSpan, SourceFile and Diagnostic in RetroSharp.Core (#2470) (#2489) (`d8cb2341`)
- NES: one method answers a placed sprite use's palettes (#2445) (#2488) (`8a0fe11c`)
- Game Boy: the subroutine call count skips the arms a constant condition removes (#2433) (#2468) (`4f2ed1f1`)
- NES: one decision for word-sized world columns in collision and collectibles (#2461) (#2467) (`c77444d5`)
- Game Boy: one slot-versus-pending group comparison for both protection loops of the visual lookup (#2463) (#2465) (`a1795b3e`)
- Game Boy: one emitter per axis for the visual lookup's axis-only pairs (plane iterator, edge lookup advance, visual cache groups) (#2430) (#2464) (`4d14651c`)
- Worlds: the world-set shape and the byte hit-top rule are decided once in the SDK (#2427) (#2462) (`ac01225d`)
- Names: the physical-namespace composer resolves once and yields the source, the authored-function map and factory names (#2429) (#2460) (`cd14200e`)
- Z80: one fixed-bank capacity check in the windowed banking model; Master System and Game Gear get their capacity error (#2454) (#2459) (`2857edd1`)
- Plugin ABI: retire SdkPluginTilemapSetupTargetPort, which nothing uses since #2426 (#2448) (#2458) (`45887fe7`)
- Workflow: with backlog: true, a roadmap batch lane without a free sub-issue carries a backlog issue (#2450) (#2457) (`e61fbdc5`)
- Workflow: batch gives each issue's hours, tokens per model and API cost (issue.py usage) (#2456) (`c2e7730a`)
- Game Boy has one world activation helper, so the helper choice that hung the build (#2286) is gone (#2425) (#2455) (`4566ffd6`)
- Workflow: from the third NOT READY review, /issue redesigns the mechanism or narrows the issue (#2451) (#2453) (`fd233ab1`)
- Tilemap writes have one classifier, keyed by the cell's place, in one walk; one setup door and one fill warning (#2426) (#2449) (`7f88518f`)
- NES: sprite Effect.Flash and Effect.Glow show in the sprite palette no draw leaves its pieces in (#2404) (#2446) (`305c331d`)
- Game Boy: sprite Effect.Flash and Effect.Glow show in the object palette no draw uses (#2403) (#2444) (`344d6ea6`)
- Screen.Play's effect state machine is SDK source; targets keep only level primitives (#2408) (#2443) (`bf1e0d73`)
- Sprite.Draw, DrawWorld and DrawTransformed are declared once, in the Portable2D plugin source, with their documentation (#2406) (#2442) (`a50f6160`)
- A value of one enum passed, assigned or returned where another enum is declared is a compile error that names both and says what to write (#2421) (#2440) (`39843e2a`)
- Implementer: test first, one decision in one place, and change the mechanism instead of adding a branch (#2435) (#2437) (`d4d97bd6`)
- Every PR states its net production lines, and the reviewer looks for the same decision across the repository (#2432) (#2436) (`04f12d44`)
- A helper called twice only from a function Main never calls builds on the Game Boy (#2418) (#2434) (`1cf3d244`)
- In a physical-namespace project, a method's bare call of a sibling method calls that method, before any function of the same name (#2416) (#2424) (`1239b60e`)
- A game type that hides a Portable2D type the SDK needs stops the build at its declaration and asks for another name (#2413) (#2423) (`44edff6f`)
- A Game Boy subroutine's locals are named in its SDK operations as the emitter names them, so a helper called twice reads its locals and stored operands (#1993) (#2419) (`20f76867`)
- Calling an undeclared function is an error at the call on every target, with the name to write instead (#2353) (#2417) (`8f6170d0`)
- A type name declared twice in one namespace stops the compile with an error at its declaration that asks for another name (#2325) (#2415) (`cffc8339`)
- A setup Tilemap.Fill after a run-time Tilemap.Set that may write its cells writes those cells at run time, in source order (#2350) (#2412) (`4331efa2`)
- Frame budget validation keeps one open budget, the upper bound of the paths, so conditional draws in a row cost linear time (#2405) (#2411) (`04750ad1`)
- Sprite effects: Sprite.Draw(..., effect:) blinks a sprite on GB, NES, SMS and GG, with Flash and Glow drawn as Blink and a build warning (#2400) (#2407) (`2cfd00ff`)
- Effect and screen effects: Screen.Play fades and flashes the screen on GB, NES, SMS and GG (#2395) (#2402) (`1b1912f4`)
- Retire the duplicate setup Set/Fill paths of roadmap #2348, the unused subroutines of Find and the --agent value rule (#2398) (#2399) (`8a3f953f`)
- retrosharp guide: no link to the private GitHub releases, and advice for Tiled actors that spawn moving away from the window (#2396) (#2397) (`e5d62290`)